summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/17.txt1
-rw-r--r--api/current.txt67
-rw-r--r--cmds/installd/commands.c30
-rw-r--r--cmds/installd/installd.c150
-rw-r--r--cmds/installd/installd.h7
-rw-r--r--cmds/installd/utils.c50
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java41
-rw-r--r--cmds/svc/src/com/android/commands/svc/PowerCommand.java10
-rw-r--r--core/java/android/accounts/AccountManagerService.java4
-rwxr-xr-xcore/java/android/animation/ValueAnimator.java29
-rw-r--r--core/java/android/app/Activity.java33
-rw-r--r--core/java/android/app/ActivityManager.java12
-rw-r--r--core/java/android/app/ActivityOptions.java41
-rw-r--r--core/java/android/app/ActivityThread.java56
-rw-r--r--core/java/android/app/ApplicationPackageManager.java31
-rw-r--r--core/java/android/app/ContextImpl.java29
-rw-r--r--core/java/android/app/FragmentManager.java143
-rw-r--r--core/java/android/app/KeyguardManager.java5
-rw-r--r--core/java/android/app/PendingIntent.java10
-rw-r--r--core/java/android/app/SharedPreferencesImpl.java67
-rw-r--r--core/java/android/app/WallpaperManager.java7
-rw-r--r--core/java/android/appwidget/AppWidgetHost.java24
-rw-r--r--core/java/android/appwidget/AppWidgetHostView.java56
-rw-r--r--core/java/android/content/ContentProvider.java4
-rw-r--r--core/java/android/content/Context.java28
-rw-r--r--core/java/android/content/ContextWrapper.java24
-rw-r--r--core/java/android/content/Intent.java34
-rw-r--r--core/java/android/content/IntentSender.java10
-rw-r--r--core/java/android/content/SyncManager.java2
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl11
-rw-r--r--core/java/android/content/pm/PackageManager.java56
-rw-r--r--core/java/android/content/pm/PackageStats.java65
-rw-r--r--core/java/android/content/pm/UserInfo.java4
-rw-r--r--core/java/android/content/pm/VerificationParams.aidl19
-rw-r--r--core/java/android/content/pm/VerificationParams.java187
-rw-r--r--core/java/android/hardware/display/DisplayManager.java185
-rw-r--r--core/java/android/hardware/usb/IUsbManager.aidl8
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java3
-rw-r--r--core/java/android/net/MobileDataStateTracker.java13
-rw-r--r--core/java/android/net/NetworkStateTracker.java6
-rw-r--r--core/java/android/os/BatteryManager.java2
-rw-r--r--core/java/android/os/BatteryStats.java3
-rw-r--r--core/java/android/os/FactoryTest.java35
-rw-r--r--core/java/android/os/FileUtils.java51
-rw-r--r--core/java/android/os/IUserManager.aidl2
-rw-r--r--core/java/android/os/Process.java19
-rw-r--r--core/java/android/os/SELinux.java71
-rw-r--r--core/java/android/os/StatFs.java86
-rw-r--r--core/java/android/os/UEventObserver.java196
-rw-r--r--core/java/android/os/UserHandle.java126
-rw-r--r--core/java/android/os/UserManager.java38
-rw-r--r--core/java/android/provider/Settings.java1
-rw-r--r--core/java/android/service/dreams/DreamManagerService.java4
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java10
-rwxr-xr-xcore/java/android/speech/tts/TextToSpeech.java29
-rw-r--r--core/java/android/text/TextUtils.java7
-rw-r--r--core/java/android/text/style/LocaleSpan.java84
-rw-r--r--core/java/android/view/Choreographer.java3
-rw-r--r--core/java/android/view/Display.java48
-rw-r--r--core/java/android/view/DisplayInfo.java13
-rw-r--r--core/java/android/view/HardwareRenderer.java8
-rw-r--r--core/java/android/view/IWindowManager.aidl2
-rw-r--r--core/java/android/view/IWindowSession.aidl8
-rw-r--r--core/java/android/view/Surface.java19
-rw-r--r--core/java/android/view/SurfaceView.java14
-rw-r--r--core/java/android/view/View.java1104
-rw-r--r--core/java/android/view/ViewConfiguration.java5
-rw-r--r--core/java/android/view/ViewDebug.java15
-rw-r--r--core/java/android/view/ViewGroup.java134
-rw-r--r--core/java/android/view/ViewPropertyAnimator.java2
-rw-r--r--core/java/android/view/ViewRootImpl.java144
-rw-r--r--core/java/android/view/Window.java14
-rw-r--r--core/java/android/view/WindowManagerGlobal.java516
-rw-r--r--core/java/android/view/WindowManagerImpl.java557
-rw-r--r--core/java/android/view/WindowManagerPolicy.java10
-rw-r--r--core/java/android/webkit/WebSettings.java34
-rw-r--r--core/java/android/webkit/WebSettingsClassic.java47
-rw-r--r--core/java/android/webkit/WebView.java1
-rw-r--r--core/java/android/webkit/WebViewClassic.java23
-rw-r--r--core/java/android/webkit/WebViewFactoryProvider.java6
-rw-r--r--core/java/android/widget/CheckedTextView.java26
-rw-r--r--core/java/android/widget/RemoteViews.java91
-rw-r--r--core/java/android/widget/Switch.java2
-rw-r--r--core/java/android/widget/TabHost.java71
-rw-r--r--core/java/android/widget/TextView.java21
-rw-r--r--core/java/android/widget/Toast.java5
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java9
-rw-r--r--core/java/com/android/internal/os/ZygoteConnection.java17
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java8
-rw-r--r--core/java/com/android/internal/view/RotationPolicy.java7
-rw-r--r--core/jni/Android.mk1
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android/graphics/Paint.cpp50
-rw-r--r--core/jni/android/graphics/TextLayoutCache.cpp17
-rw-r--r--core/jni/android/graphics/TextLayoutCache.h4
-rw-r--r--core/jni/android_os_FileUtils.cpp99
-rw-r--r--core/jni/android_os_SELinux.cpp39
-rw-r--r--core/jni/android_os_StatFs.cpp163
-rw-r--r--core/jni/android_view_Surface.cpp10
-rw-r--r--core/res/AndroidManifest.xml12
-rw-r--r--core/res/res/values-af/strings.xml6
-rw-r--r--core/res/res/values-am/strings.xml3
-rw-r--r--core/res/res/values-ar/strings.xml4
-rw-r--r--core/res/res/values-be/strings.xml3
-rw-r--r--core/res/res/values-bg/strings.xml4
-rw-r--r--core/res/res/values-ca/strings.xml3
-rw-r--r--core/res/res/values-cs/strings.xml6
-rw-r--r--core/res/res/values-da/strings.xml3
-rw-r--r--core/res/res/values-de/strings.xml3
-rw-r--r--core/res/res/values-el/strings.xml3
-rw-r--r--core/res/res/values-en-rGB/strings.xml3
-rw-r--r--core/res/res/values-es-rUS/strings.xml4
-rw-r--r--core/res/res/values-es/strings.xml3
-rw-r--r--core/res/res/values-et/strings.xml4
-rw-r--r--core/res/res/values-fa/strings.xml4
-rw-r--r--core/res/res/values-fi/strings.xml3
-rw-r--r--core/res/res/values-fr/strings.xml4
-rw-r--r--core/res/res/values-hi/strings.xml6
-rw-r--r--core/res/res/values-hr/strings.xml4
-rw-r--r--core/res/res/values-hu/strings.xml4
-rw-r--r--core/res/res/values-in/strings.xml3
-rw-r--r--core/res/res/values-it/strings.xml3
-rw-r--r--core/res/res/values-iw/strings.xml3
-rw-r--r--core/res/res/values-ja/strings.xml4
-rw-r--r--core/res/res/values-ko/strings.xml4
-rw-r--r--core/res/res/values-lt/strings.xml4
-rw-r--r--core/res/res/values-lv/strings.xml4
-rw-r--r--core/res/res/values-ms/strings.xml4
-rw-r--r--core/res/res/values-nb/strings.xml3
-rw-r--r--core/res/res/values-nl/strings.xml3
-rw-r--r--core/res/res/values-pl/strings.xml4
-rw-r--r--core/res/res/values-pt-rPT/strings.xml6
-rw-r--r--core/res/res/values-pt/strings.xml4
-rw-r--r--core/res/res/values-rm/strings.xml6
-rw-r--r--core/res/res/values-ro/strings.xml4
-rw-r--r--core/res/res/values-ru/strings.xml4
-rw-r--r--core/res/res/values-sk/strings.xml4
-rw-r--r--core/res/res/values-sl/strings.xml3
-rw-r--r--core/res/res/values-sr/strings.xml4
-rw-r--r--core/res/res/values-sv/strings.xml3
-rw-r--r--core/res/res/values-sw/strings.xml3
-rw-r--r--core/res/res/values-th/strings.xml4
-rw-r--r--core/res/res/values-tl/strings.xml4
-rw-r--r--core/res/res/values-tr/strings.xml4
-rw-r--r--core/res/res/values-uk/strings.xml3
-rw-r--r--core/res/res/values-vi/strings.xml4
-rw-r--r--core/res/res/values-zh-rCN/strings.xml10
-rw-r--r--core/res/res/values-zh-rTW/strings.xml4
-rw-r--r--core/res/res/values-zu/strings.xml4
-rw-r--r--core/res/res/values/public.xml1
-rwxr-xr-xcore/res/res/values/strings.xml10
-rwxr-xr-xcore/tests/coretests/src/android/content/pm/AppCacheTest.java2
-rw-r--r--core/tests/coretests/src/android/content/pm/VerificationParamsTest.java171
-rw-r--r--core/tests/coretests/src/android/os/FileUtilsTest.java64
-rw-r--r--data/etc/Android.mk4
-rw-r--r--data/fonts/Android.mk11
-rw-r--r--data/fonts/fallback_fonts-ja.xml121
-rw-r--r--data/fonts/fallback_fonts.xml11
-rw-r--r--data/fonts/vendor_fonts.xml34
-rw-r--r--docs/html/intl/ja/index.jd159
-rw-r--r--drm/jni/Android.mk3
-rw-r--r--drm/jni/android_drm_DrmManagerClient.cpp105
-rw-r--r--keystore/java/android/security/AndroidKeyStore.java463
-rw-r--r--keystore/java/android/security/AndroidKeyStoreProvider.java34
-rw-r--r--keystore/java/android/security/KeyStore.java18
-rw-r--r--keystore/tests/src/android/security/AndroidKeyStoreTest.java1383
-rwxr-xr-xkeystore/tests/src/android/security/KeyStoreTest.java50
-rw-r--r--libs/hwui/FontRenderer.cpp222
-rw-r--r--libs/hwui/FontRenderer.h88
-rw-r--r--location/java/android/location/Criteria.java4
-rw-r--r--location/java/android/location/Geofence.java10
-rw-r--r--location/java/android/location/ILocationManager.aidl2
-rw-r--r--location/java/android/location/Location.java230
-rw-r--r--location/java/android/location/LocationManager.java804
-rw-r--r--location/java/android/location/LocationRequest.java314
-rw-r--r--location/java/com/android/internal/location/ProviderProperties.java2
-rw-r--r--location/lib/README.txt30
-rw-r--r--location/lib/java/com/android/location/provider/GeocodeProvider.java10
-rw-r--r--location/lib/java/com/android/location/provider/LocationProviderBase.java18
-rw-r--r--location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java8
-rw-r--r--location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java8
-rwxr-xr-xmedia/jni/mediaeditor/VideoEditorClasses.cpp9
-rwxr-xr-xmedia/jni/mediaeditor/VideoEditorJava.cpp3
-rwxr-xr-xmedia/jni/mediaeditor/VideoEditorMain.cpp5
-rw-r--r--media/libdrm/mobile1/src/objmng/drm_api.c4
-rw-r--r--media/mca/filterpacks/java/android/filterpacks/videosrc/MediaSource.java13
-rw-r--r--packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java2
-rw-r--r--packages/FusedLocation/src/com/android/location/fused/FusionEngine.java1
-rw-r--r--packages/SystemUI/AndroidManifest.xml10
-rw-r--r--packages/SystemUI/res/values-af/strings.xml6
-rw-r--r--packages/SystemUI/res/values-am/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml6
-rw-r--r--packages/SystemUI/res/values-be/strings.xml3
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml3
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml6
-rw-r--r--packages/SystemUI/res/values-da/strings.xml3
-rw-r--r--packages/SystemUI/res/values-de/strings.xml3
-rw-r--r--packages/SystemUI/res/values-el/strings.xml3
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml3
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml6
-rw-r--r--packages/SystemUI/res/values-es/strings.xml3
-rw-r--r--packages/SystemUI/res/values-et/strings.xml6
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml6
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml3
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml8
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml6
-rw-r--r--packages/SystemUI/res/values-in/strings.xml3
-rw-r--r--packages/SystemUI/res/values-it/strings.xml3
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml6
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml6
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml6
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml3
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml6
-rw-r--r--packages/SystemUI/res/values-rm/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml8
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml3
-rw-r--r--packages/SystemUI/res/values-th/strings.xml6
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml3
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml6
-rw-r--r--packages/SystemUI/res/values/strings.xml9
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/SearchPanelView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIService.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/UniverseBackground.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java137
-rw-r--r--policy/src/com/android/internal/policy/impl/GlobalActions.java17
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java7
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewManager.java6
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java6
-rw-r--r--policy/src/com/android/internal/policy/impl/LockScreen.java2
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java39
-rw-r--r--services/common_time/common_time_server.cpp17
-rw-r--r--services/java/com/android/server/AppWidgetService.java2
-rw-r--r--services/java/com/android/server/AppWidgetServiceImpl.java10
-rw-r--r--services/java/com/android/server/BatteryService.java14
-rw-r--r--services/java/com/android/server/ClipboardService.java2
-rw-r--r--services/java/com/android/server/ConnectivityService.java5
-rw-r--r--services/java/com/android/server/DockObserver.java233
-rw-r--r--services/java/com/android/server/LocationManagerService.java203
-rwxr-xr-xservices/java/com/android/server/NotificationManagerService.java4
-rw-r--r--services/java/com/android/server/SystemServer.java9
-rw-r--r--services/java/com/android/server/WallpaperManagerService.java15
-rw-r--r--services/java/com/android/server/WiredAccessoryObserver.java305
-rw-r--r--services/java/com/android/server/am/ActiveServices.java60
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java46
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java8
-rwxr-xr-xservices/java/com/android/server/am/ActivityStack.java4
-rw-r--r--services/java/com/android/server/am/ConnectionRecord.java28
-rw-r--r--services/java/com/android/server/am/IntentBindRecord.java18
-rw-r--r--services/java/com/android/server/am/ProviderMap.java14
-rw-r--r--services/java/com/android/server/am/ServiceRecord.java4
-rw-r--r--services/java/com/android/server/display/DisplayAdapter.java39
-rw-r--r--services/java/com/android/server/display/DisplayDevice.java14
-rw-r--r--services/java/com/android/server/display/DisplayDeviceInfo.java10
-rw-r--r--services/java/com/android/server/display/DisplayManagerService.java239
-rw-r--r--services/java/com/android/server/display/HeadlessDisplayAdapter.java38
-rw-r--r--services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java33
-rw-r--r--services/java/com/android/server/input/InputManagerService.java8
-rw-r--r--services/java/com/android/server/location/GeofenceManager.java14
-rwxr-xr-xservices/java/com/android/server/location/GpsLocationProvider.java4
-rw-r--r--services/java/com/android/server/location/LocationBlacklist.java135
-rw-r--r--services/java/com/android/server/location/LocationFudger.java310
-rw-r--r--services/java/com/android/server/pm/Installer.java4
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java129
-rw-r--r--services/java/com/android/server/pm/PreferredActivity.java18
-rw-r--r--services/java/com/android/server/pm/UserManagerService.java146
-rw-r--r--services/java/com/android/server/power/DisplayPowerController.java75
-rw-r--r--services/java/com/android/server/power/DisplayPowerState.java5
-rw-r--r--services/java/com/android/server/power/ElectronBeam.java10
-rw-r--r--services/java/com/android/server/usb/UsbDebuggingManager.java322
-rw-r--r--services/java/com/android/server/usb/UsbDeviceManager.java26
-rw-r--r--services/java/com/android/server/usb/UsbService.java10
-rw-r--r--services/java/com/android/server/wm/AppWindowAnimator.java2
-rw-r--r--services/java/com/android/server/wm/ScreenRotationAnimation.java16
-rw-r--r--services/java/com/android/server/wm/StrictModeFlash.java4
-rw-r--r--services/java/com/android/server/wm/Watermark.java6
-rw-r--r--services/java/com/android/server/wm/WindowAnimator.java4
-rwxr-xr-xservices/java/com/android/server/wm/WindowManagerService.java244
-rw-r--r--services/java/com/android/server/wm/WindowState.java25
-rw-r--r--services/java/com/android/server/wm/WindowStateAnimator.java35
-rw-r--r--services/jni/com_android_server_BatteryService.cpp16
-rw-r--r--services/jni/com_android_server_input_InputManagerService.cpp17
-rw-r--r--services/tests/servicestests/AndroidManifest.xml1
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java57
-rw-r--r--test-runner/src/android/test/mock/MockContext.java12
-rw-r--r--test-runner/src/android/test/mock/MockPackageManager.java14
-rw-r--r--tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java3
-rw-r--r--tests/ActivityTests/src/com/google/android/test/activity/SingleUserProvider.java4
-rw-r--r--tests/ActivityTests/src/com/google/android/test/activity/SingleUserReceiver.java3
-rw-r--r--tests/ActivityTests/src/com/google/android/test/activity/UserTarget.java3
-rw-r--r--tests/MemoryUsage/Android.mk16
-rw-r--r--tests/MemoryUsage/AndroidManifest.xml12
-rw-r--r--tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageInstrumentation.java38
-rw-r--r--tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java235
-rw-r--r--tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/BallsView.java2
-rw-r--r--tests/RenderScriptTests/ComputeBenchmark/Android.mk27
-rw-r--r--tests/RenderScriptTests/ComputeBenchmark/AndroidManifest.xml30
-rw-r--r--tests/RenderScriptTests/ComputeBenchmark/res/layout/main.xml31
-rw-r--r--tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/Benchmark.java39
-rw-r--r--tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/ComputeBench.java37
-rw-r--r--tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs408
-rw-r--r--tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Fisheye.java40
-rw-r--r--tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java40
-rw-r--r--tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye.rsh55
-rw-r--r--tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx.rsh58
-rw-r--r--tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs21
-rw-r--r--tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.rs22
-rw-r--r--tests/RenderScriptTests/ImageProcessing2/Android.mk4
-rw-r--r--tests/RenderScriptTests/ImageProcessing2/AndroidManifest.xml5
-rw-r--r--tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java7
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java12
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java2
-rw-r--r--wifi/java/android/net/wifi/ScanResult.java30
-rw-r--r--wifi/java/android/net/wifi/WifiNative.java16
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java200
344 files changed, 10738 insertions, 4681 deletions
diff --git a/api/17.txt b/api/17.txt
index c43802f..d002449 100644
--- a/api/17.txt
+++ b/api/17.txt
@@ -24500,7 +24500,6 @@ package android.view {
field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
field public static final int SYSTEM_UI_LAYOUT_FLAGS = 1536; // 0x600
field public static final int TEXT_ALIGNMENT_INHERIT = 0; // 0x0
- field public static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = 131072; // 0x20000
field public static final android.util.Property TRANSLATION_X;
field public static final android.util.Property TRANSLATION_Y;
field protected static final java.lang.String VIEW_LOG_TAG = "View";
diff --git a/api/current.txt b/api/current.txt
index 860ae09..e1d07e2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -68,6 +68,7 @@ package android {
field public static final java.lang.String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
field public static final java.lang.String MANAGE_ACCOUNTS = "android.permission.MANAGE_ACCOUNTS";
field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
+ field public static final java.lang.String MANAGE_USERS = "android.permission.MANAGE_USERS";
field public static final java.lang.String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
field public static final java.lang.String MODIFY_AUDIO_SETTINGS = "android.permission.MODIFY_AUDIO_SETTINGS";
field public static final java.lang.String MODIFY_PHONE_STATE = "android.permission.MODIFY_PHONE_STATE";
@@ -3871,7 +3872,7 @@ package android.app {
method public static android.app.PendingIntent getService(android.content.Context, int, android.content.Intent, int);
method public java.lang.String getTargetPackage();
method public int getTargetUid();
- method public int getTargetUserHandle();
+ method public android.os.UserHandle getTargetUserHandle();
method public static android.app.PendingIntent readPendingIntentOrNullFromParcel(android.os.Parcel);
method public void send() throws android.app.PendingIntent.CanceledException;
method public void send(int) throws android.app.PendingIntent.CanceledException;
@@ -5323,10 +5324,10 @@ package android.content {
method public abstract void revokeUriPermission(android.net.Uri, int);
method public abstract void sendBroadcast(android.content.Intent);
method public abstract void sendBroadcast(android.content.Intent, java.lang.String);
- method public abstract void sendBroadcastToUser(android.content.Intent, int);
+ method public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String);
method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
- method public abstract void sendOrderedBroadcastToUser(android.content.Intent, int, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ method public abstract void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
method public abstract void sendStickyBroadcast(android.content.Intent);
method public abstract void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
method public abstract void setTheme(int);
@@ -5460,10 +5461,10 @@ package android.content {
method public void revokeUriPermission(android.net.Uri, int);
method public void sendBroadcast(android.content.Intent);
method public void sendBroadcast(android.content.Intent, java.lang.String);
- method public void sendBroadcastToUser(android.content.Intent, int);
+ method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
method public void sendOrderedBroadcast(android.content.Intent, java.lang.String);
method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
- method public void sendOrderedBroadcastToUser(android.content.Intent, int, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ method public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
method public void sendStickyBroadcast(android.content.Intent);
method public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
method public void setTheme(int);
@@ -5837,7 +5838,7 @@ package android.content {
field public static final java.lang.String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT";
field public static final java.lang.String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
field public static final java.lang.String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
- field public static final java.lang.String EXTRA_ORIGINATING_URL = "android.intent.extra.ORIGINATING_URL";
+ field public static final java.lang.String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
field public static final java.lang.String EXTRA_REMOTE_INTENT_TOKEN = "android.intent.extra.remote_intent_token";
@@ -5989,7 +5990,7 @@ package android.content {
method public int describeContents();
method public java.lang.String getTargetPackage();
method public int getTargetUid();
- method public int getTargetUserHandle();
+ method public android.os.UserHandle getTargetUserHandle();
method public static android.content.IntentSender readIntentSenderOrNullFromParcel(android.os.Parcel);
method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler) throws android.content.IntentSender.SendIntentException;
method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler, java.lang.String) throws android.content.IntentSender.SendIntentException;
@@ -9980,6 +9981,15 @@ package android.hardware {
package android.hardware.display {
public final class DisplayManager {
+ method public android.view.Display getDisplay(int, android.content.Context);
+ method public void registerDisplayListener(android.hardware.display.DisplayManager.DisplayListener, android.os.Handler);
+ method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
+ }
+
+ public static abstract interface DisplayManager.DisplayListener {
+ method public abstract void onDisplayAdded(int);
+ method public abstract void onDisplayChanged(int);
+ method public abstract void onDisplayRemoved(int);
}
}
@@ -10556,7 +10566,7 @@ package android.location {
method public android.os.Bundle getExtras();
method public double getLatitude();
method public double getLongitude();
- method public java.lang.String getProvider();
+ method public deprecated java.lang.String getProvider();
method public float getSpeed();
method public long getTime();
method public boolean hasAccuracy();
@@ -10594,6 +10604,7 @@ package android.location {
}
public class LocationManager {
+ method public void addGeofence(android.location.LocationRequest, android.location.Geofence, android.app.PendingIntent);
method public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
method public boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
method public deprecated void addProximityAlert(double, double, float, long, android.app.PendingIntent);
@@ -10605,7 +10616,7 @@ package android.location {
method public deprecated java.lang.String getBestProvider(android.location.Criteria, boolean);
method public android.location.GpsStatus getGpsStatus(android.location.GpsStatus);
method public deprecated android.location.Location getLastKnownLocation(java.lang.String);
- method public android.location.Location getLastLocation(android.location.LocationRequest);
+ method public android.location.Location getLastLocation();
method public deprecated android.location.LocationProvider getProvider(java.lang.String);
method public deprecated java.util.List<java.lang.String> getProviders(boolean);
method public deprecated java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
@@ -10618,7 +10629,6 @@ package android.location {
method public deprecated void removeTestProvider(java.lang.String);
method public void removeUpdates(android.location.LocationListener);
method public void removeUpdates(android.app.PendingIntent);
- method public void requestGeofence(android.location.LocationRequest, android.location.Geofence, android.app.PendingIntent);
method public deprecated void requestLocationUpdates(java.lang.String, long, float, android.location.LocationListener);
method public deprecated void requestLocationUpdates(java.lang.String, long, float, android.location.LocationListener, android.os.Looper);
method public deprecated void requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper);
@@ -13216,6 +13226,7 @@ package android.net.wifi {
field public java.lang.String capabilities;
field public int frequency;
field public int level;
+ field public long timestamp;
}
public final class SupplicantState extends java.lang.Enum implements android.os.Parcelable {
@@ -15514,6 +15525,7 @@ package android.os {
field public static final int BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6; // 0x6
field public static final int BATTERY_PLUGGED_AC = 1; // 0x1
field public static final int BATTERY_PLUGGED_USB = 2; // 0x2
+ field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4
field public static final int BATTERY_STATUS_CHARGING = 2; // 0x2
field public static final int BATTERY_STATUS_DISCHARGING = 3; // 0x3
field public static final int BATTERY_STATUS_FULL = 5; // 0x5
@@ -16301,7 +16313,7 @@ package android.os {
method public static final int myPid();
method public static final int myTid();
method public static final int myUid();
- method public static final int myUserHandle();
+ method public static final android.os.UserHandle myUserHandle();
method public static final void sendSignal(int, int);
method public static final void setThreadPriority(int, int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
method public static final void setThreadPriority(int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
@@ -16456,6 +16468,15 @@ package android.os {
ctor public TransactionTooLargeException();
}
+ public final class UserHandle implements android.os.Parcelable {
+ ctor public UserHandle(android.os.Parcel);
+ method public int describeContents();
+ method public static android.os.UserHandle readFromParcel(android.os.Parcel);
+ method public void writeToParcel(android.os.Parcel, int);
+ method public static void writeToParcel(android.os.UserHandle, android.os.Parcel);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
public class UserManager {
method public java.lang.String getUserName();
method public boolean supportsMultipleUsers();
@@ -21205,10 +21226,10 @@ package android.test.mock {
method public void revokeUriPermission(android.net.Uri, int);
method public void sendBroadcast(android.content.Intent);
method public void sendBroadcast(android.content.Intent, java.lang.String);
- method public void sendBroadcastToUser(android.content.Intent, int);
+ method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
method public void sendOrderedBroadcast(android.content.Intent, java.lang.String);
method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
- method public void sendOrderedBroadcastToUser(android.content.Intent, int, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ method public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
method public void sendStickyBroadcast(android.content.Intent);
method public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
method public void setTheme(int);
@@ -22484,6 +22505,17 @@ package android.text.style {
method public abstract void chooseHeight(java.lang.CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt, android.text.TextPaint);
}
+ public class LocaleSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
+ ctor public LocaleSpan(java.util.Locale);
+ ctor public LocaleSpan(android.os.Parcel);
+ method public int describeContents();
+ method public java.util.Locale getLocale();
+ method public int getSpanTypeId();
+ method public void updateDrawState(android.text.TextPaint);
+ method public void updateMeasureState(android.text.TextPaint);
+ method public void writeToParcel(android.os.Parcel, int);
+ }
+
public class MaskFilterSpan extends android.text.style.CharacterStyle implements android.text.style.UpdateAppearance {
ctor public MaskFilterSpan(android.graphics.MaskFilter);
method public android.graphics.MaskFilter getMaskFilter();
@@ -24569,6 +24601,7 @@ package android.view {
method public final android.content.Context getContext();
method protected android.view.ContextMenu.ContextMenuInfo getContextMenuInfo();
method public static int getDefaultSize(int, int);
+ method public android.view.Display getDisplay();
method public final int[] getDrawableState();
method public android.graphics.Bitmap getDrawingCache();
method public android.graphics.Bitmap getDrawingCache(boolean);
@@ -25019,16 +25052,15 @@ package android.view {
field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
field public static final int SYSTEM_UI_LAYOUT_FLAGS = 1536; // 0x600
field public static final int TEXT_ALIGNMENT_CENTER = 4; // 0x4
- field protected static int TEXT_ALIGNMENT_DEFAULT;
+ field public static int TEXT_ALIGNMENT_DEFAULT;
field public static final int TEXT_ALIGNMENT_GRAVITY = 1; // 0x1
field public static final int TEXT_ALIGNMENT_INHERIT = 0; // 0x0
- field public static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = 131072; // 0x20000
field public static final int TEXT_ALIGNMENT_TEXT_END = 3; // 0x3
field public static final int TEXT_ALIGNMENT_TEXT_START = 2; // 0x2
field public static final int TEXT_ALIGNMENT_VIEW_END = 6; // 0x6
field public static final int TEXT_ALIGNMENT_VIEW_START = 5; // 0x5
field public static final int TEXT_DIRECTION_ANY_RTL = 2; // 0x2
- field protected static int TEXT_DIRECTION_DEFAULT;
+ field public static int TEXT_DIRECTION_DEFAULT;
field public static final int TEXT_DIRECTION_FIRST_STRONG = 1; // 0x1
field public static final int TEXT_DIRECTION_INHERIT = 0; // 0x0
field public static final int TEXT_DIRECTION_LOCALE = 5; // 0x5
@@ -26917,6 +26949,7 @@ package android.webkit {
method public synchronized boolean getUseWideViewPort();
method public deprecated synchronized int getUserAgent();
method public synchronized java.lang.String getUserAgentString();
+ method public static java.lang.String getDefaultUserAgent(android.content.Context);
method public void setAllowContentAccess(boolean);
method public void setAllowFileAccess(boolean);
method public abstract void setAllowFileAccessFromFileURLs(boolean);
@@ -29284,6 +29317,7 @@ package android.widget {
method public static int getTextColor(android.content.Context, android.content.res.TypedArray, int);
method public final android.content.res.ColorStateList getTextColors();
method public static android.content.res.ColorStateList getTextColors(android.content.Context, android.content.res.TypedArray);
+ method public java.util.Locale getTextLocale();
method public float getTextScaleX();
method public float getTextSize();
method public int getTotalPaddingBottom();
@@ -29386,6 +29420,7 @@ package android.widget {
method public void setTextIsSelectable(boolean);
method public final void setTextKeepState(java.lang.CharSequence);
method public final void setTextKeepState(java.lang.CharSequence, android.widget.TextView.BufferType);
+ method public void setTextLocale(java.util.Locale);
method public void setTextScaleX(float);
method public void setTextSize(float);
method public void setTextSize(int, float);
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index d94daf7..c16e6fb 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -213,18 +213,30 @@ int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
int delete_persona(uid_t persona)
{
- char pkgdir[PKG_PATH_MAX];
+ char data_path[PKG_PATH_MAX];
+ if (create_persona_path(data_path, persona)) {
+ return -1;
+ }
+ if (delete_dir_contents(data_path, 1, NULL)) {
+ return -1;
+ }
- if (create_persona_path(pkgdir, persona))
+ char media_path[PATH_MAX];
+ if (create_persona_media_path(media_path, (userid_t) persona) == -1) {
+ return -1;
+ }
+ if (delete_dir_contents(media_path, 1, NULL) == -1) {
return -1;
+ }
- return delete_dir_contents(pkgdir, 1, NULL);
+ return 0;
}
int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
{
char src_data_dir[PKG_PATH_MAX];
char pkg_path[PKG_PATH_MAX];
+ char media_path[PATH_MAX];
DIR *d;
struct dirent *de;
struct stat s;
@@ -233,6 +245,9 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
if (create_persona_path(src_data_dir, src_persona)) {
return -1;
}
+ if (create_persona_media_path(media_path, (userid_t) target_persona) == -1) {
+ return -1;
+ }
d = opendir(src_data_dir);
if (d != NULL) {
@@ -260,6 +275,11 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
}
closedir(d);
}
+
+ // ensure /data/media/<user_id> exists
+ if (ensure_dir(media_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+ return -1;
+ }
return 0;
}
@@ -412,7 +432,7 @@ int protect(char *pkgname, gid_t gid)
return 0;
}
-int get_size(const char *pkgname, const char *apkpath,
+int get_size(const char *pkgname, int persona, const char *apkpath,
const char *fwdlock_apkpath, const char *asecpath,
int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize,
int64_t* _asecsize)
@@ -459,7 +479,7 @@ int get_size(const char *pkgname, const char *apkpath,
}
}
- if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, 0)) {
+ if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, persona)) {
goto done;
}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 89c059e..7108d68 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -85,8 +85,9 @@ static int do_get_size(char **arg, char reply[REPLY_MAX])
int64_t asecsize = 0;
int res = 0;
- /* pkgdir, apkpath */
- res = get_size(arg[0], arg[1], arg[2], arg[3], &codesize, &datasize, &cachesize, &asecsize);
+ /* pkgdir, persona, apkpath */
+ res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4],
+ &codesize, &datasize, &cachesize, &asecsize);
/*
* Each int64_t can take up 22 characters printed out. Make sure it
@@ -150,7 +151,7 @@ struct cmdinfo cmds[] = {
{ "freecache", 1, do_free_cache },
{ "rmcache", 1, do_rm_cache },
{ "protect", 2, do_protect },
- { "getsize", 4, do_get_size },
+ { "getsize", 5, do_get_size },
{ "rmuserdata", 2, do_rm_user_data },
{ "movefiles", 0, do_movefiles },
{ "linklib", 2, do_linklib },
@@ -331,37 +332,138 @@ int initialize_globals() {
}
int initialize_directories() {
+ int res = -1;
+ int version = 0;
+ FILE* file;
+
+ // Read current filesystem layout version to handle upgrade paths
+ char version_path[PATH_MAX];
+ if (snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path) > PATH_MAX) {
+ return -1;
+ }
+ file = fopen(version_path, "r");
+ if (file != NULL) {
+ fscanf(file, "%d", &version);
+ fclose(file);
+ }
+
// /data/user
char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
// /data/data
char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX);
// /data/user/0
- char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX,
- "0");
- int ret = -1;
- if (user_data_dir != NULL && primary_data_dir != NULL && legacy_data_dir != NULL) {
- ret = 0;
- // Make the /data/user directory if necessary
- if (access(user_data_dir, R_OK) < 0) {
- if (mkdir(user_data_dir, 0711) < 0) {
- return -1;
- }
- if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) {
- return -1;
+ char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0");
+ if (!user_data_dir || !legacy_data_dir || !primary_data_dir) {
+ goto fail;
+ }
+
+ // Make the /data/user directory if necessary
+ if (access(user_data_dir, R_OK) < 0) {
+ if (mkdir(user_data_dir, 0711) < 0) {
+ goto fail;
+ }
+ if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) {
+ goto fail;
+ }
+ if (chmod(user_data_dir, 0711) < 0) {
+ goto fail;
+ }
+ }
+ // Make the /data/user/0 symlink to /data/data if necessary
+ if (access(primary_data_dir, R_OK) < 0) {
+ if (symlink(legacy_data_dir, primary_data_dir)) {
+ goto fail;
+ }
+ }
+
+ // /data/media/0
+ char owner_media_dir[PATH_MAX];
+ create_persona_media_path(owner_media_dir, 0);
+
+ if (version == 0) {
+ // Introducing multi-user, so migrate /data/media contents into /data/media/0
+ ALOGD("Migrating /data/media for multi-user");
+
+ // /data/media.tmp
+ char media_tmp_dir[PATH_MAX];
+ snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path);
+
+ // Only copy when upgrade not already in progress
+ if (access(media_tmp_dir, F_OK) == -1) {
+ if (rename(android_media_dir.path, media_tmp_dir) == -1) {
+ ALOGE("Failed to move legacy media path: %s", strerror(errno));
+ goto fail;
}
- if (chmod(user_data_dir, 0711) < 0) {
- return -1;
+ }
+
+ // Create /data/media again
+ if (ensure_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+ goto fail;
+ }
+
+ // Move any owner data into place
+ if (access(media_tmp_dir, F_OK) == 0) {
+ if (rename(media_tmp_dir, owner_media_dir) == -1) {
+ ALOGE("Failed to move owner media path: %s", strerror(errno));
+ goto fail;
}
}
- // Make the /data/user/0 symlink to /data/data if necessary
- if (access(primary_data_dir, R_OK) < 0) {
- ret = symlink(legacy_data_dir, primary_data_dir);
+
+ // Ensure media directories for any existing users
+ DIR *dir;
+ struct dirent *dirent;
+ char user_media_dir[PATH_MAX];
+
+ dir = opendir(user_data_dir);
+ if (dir != NULL) {
+ while ((dirent = readdir(dir))) {
+ if (dirent->d_type == DT_DIR) {
+ const char *name = dirent->d_name;
+
+ // skip "." and ".."
+ if (name[0] == '.') {
+ if (name[1] == 0) continue;
+ if ((name[1] == '.') && (name[2] == 0)) continue;
+ }
+
+ // /data/media/<user_id>
+ snprintf(user_media_dir, PATH_MAX, "%s%s", android_media_dir.path, name);
+ if (ensure_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+ ALOGE("Failed to ensure %s: %s", user_media_dir, strerror(errno));
+ goto fail;
+ }
+ }
+ }
+ closedir(dir);
}
- free(user_data_dir);
- free(legacy_data_dir);
- free(primary_data_dir);
+
+ version = 1;
}
- return ret;
+
+ // Ensure /data/media/0 is always ready
+ if (ensure_dir(owner_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+ goto fail;
+ }
+
+ // Persist our current version
+ file = fopen(version_path, "w");
+ if (file != NULL) {
+ fprintf(file, "%d", version);
+ fsync(fileno(file));
+ fclose(file);
+ } else {
+ ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
+ goto fail;
+ }
+
+ // Success!
+ res = 0;
+
+fail:
+ free(user_data_dir);
+ free(legacy_data_dir);
+ free(primary_data_dir);
+ return res;
}
int main(const int argc, const char *argv[]) {
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index f5853ff..3201427 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -35,6 +35,7 @@
#include <cutils/sockets.h>
#include <cutils/log.h>
#include <cutils/properties.h>
+#include <cutils/multiuser.h>
#include <private/android_filesystem_config.h>
@@ -138,6 +139,8 @@ int create_pkg_path(char path[PKG_PATH_MAX],
int create_persona_path(char path[PKG_PATH_MAX],
uid_t persona);
+int create_persona_media_path(char path[PKG_PATH_MAX], userid_t userid);
+
int create_move_path(char path[PKG_PATH_MAX],
const char* pkgname,
const char* leaf,
@@ -180,6 +183,8 @@ int append_and_increment(char** dst, const char* src, size_t* dst_size);
char *build_string2(char *s1, char *s2);
char *build_string3(char *s1, char *s2, char *s3);
+int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
+
/* commands.c */
int install(const char *pkgname, uid_t uid, gid_t gid);
@@ -194,7 +199,7 @@ int delete_cache(const char *pkgname);
int move_dex(const char *src, const char *dst);
int rm_dex(const char *path);
int protect(char *pkgname, gid_t gid);
-int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath,
+int get_size(const char *pkgname, int persona, const char *apkpath, const char *fwdlock_apkpath,
const char *asecpath, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
int64_t *asecsize);
int free_cache(int64_t free_size);
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
index 79db972..80247f1 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.c
@@ -137,6 +137,17 @@ int create_persona_path(char path[PKG_PATH_MAX],
return 0;
}
+/**
+ * Create the path name for media for a certain persona.
+ * Returns 0 on success, and -1 on failure.
+ */
+int create_persona_media_path(char path[PATH_MAX], userid_t userid) {
+ if (snprintf(path, PATH_MAX, "%s%d", android_media_dir.path, userid) > PATH_MAX) {
+ return -1;
+ }
+ return 0;
+}
+
int create_move_path(char path[PKG_PATH_MAX],
const char* pkgname,
const char* leaf,
@@ -979,3 +990,42 @@ char *build_string3(char *s1, char *s2, char *s3) {
return result;
}
+
+/* Ensure that directory exists with given mode and owners. */
+int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) {
+ // Check if path needs to be created
+ struct stat sb;
+ if (stat(path, &sb) == -1) {
+ if (errno == ENOENT) {
+ goto create;
+ } else {
+ ALOGE("Failed to stat(%s): %s", path, strerror(errno));
+ return -1;
+ }
+ }
+
+ // Exists, verify status
+ if (sb.st_mode == mode || sb.st_uid == uid || sb.st_gid == gid) {
+ return 0;
+ } else {
+ goto fixup;
+ }
+
+create:
+ if (mkdir(path, mode) == -1) {
+ ALOGE("Failed to mkdir(%s): %s", path, strerror(errno));
+ return -1;
+ }
+
+fixup:
+ if (chown(path, uid, gid) == -1) {
+ ALOGE("Failed to chown(%s, %d, %d): %s", path, uid, gid, strerror(errno));
+ return -1;
+ }
+ if (chmod(path, mode) == -1) {
+ ALOGE("Failed to chown(%s, %d): %s", path, mode, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index eb1f9a2..b34fd05 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -36,6 +36,7 @@ import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.net.Uri;
@@ -787,6 +788,8 @@ public final class Pm {
String macAlgo = null;
byte[] macKey = null;
byte[] tag = null;
+ String originatingUriString = null;
+ String referrer = null;
while ((opt=nextOption()) != null) {
if (opt.equals("-l")) {
@@ -850,6 +853,20 @@ public final class Pm {
showUsage();
return;
}
+ } else if (opt.equals("--originating-uri")) {
+ originatingUriString = nextOptionData();
+ if (originatingUriString == null) {
+ System.err.println("Error: must supply argument for --originating-uri");
+ showUsage();
+ return;
+ }
+ } else if (opt.equals("--referrer")) {
+ referrer = nextOptionData();
+ if (referrer == null) {
+ System.err.println("Error: must supply argument for --referrer");
+ showUsage();
+ return;
+ }
} else {
System.err.println("Error: Unknown option: " + opt);
showUsage();
@@ -897,6 +914,20 @@ public final class Pm {
final Uri apkURI;
final Uri verificationURI;
+ final Uri originatingURI;
+ final Uri referrerURI;
+
+ if (originatingUriString != null) {
+ originatingURI = Uri.parse(originatingUriString);
+ } else {
+ originatingURI = null;
+ }
+
+ if (referrer != null) {
+ referrerURI = Uri.parse(referrer);
+ } else {
+ referrerURI = null;
+ }
// Populate apkURI, must be present
final String apkFilePath = nextArg();
@@ -920,8 +951,11 @@ public final class Pm {
PackageInstallObserver obs = new PackageInstallObserver();
try {
- mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName,
- verificationURI, null, encryptionParams);
+ VerificationParams verificationParams = new VerificationParams(verificationURI,
+ originatingURI, referrerURI, null);
+
+ mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags,
+ installerPackageName, verificationParams, encryptionParams);
synchronized (obs) {
while (!obs.finished) {
@@ -1441,7 +1475,8 @@ public final class Pm {
System.err.println(" pm list libraries");
System.err.println(" pm path PACKAGE");
System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]");
- System.err.println(" [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>] PATH");
+ System.err.println(" [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>]");
+ System.err.println(" [--originating-uri <URI>] [--referrer <URI>] PATH");
System.err.println(" pm uninstall [-k] PACKAGE");
System.err.println(" pm clear PACKAGE");
System.err.println(" pm enable PACKAGE_OR_COMPONENT");
diff --git a/cmds/svc/src/com/android/commands/svc/PowerCommand.java b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
index deef2a3..ec3ec3e 100644
--- a/cmds/svc/src/com/android/commands/svc/PowerCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
@@ -37,7 +37,7 @@ public class PowerCommand extends Svc.Command {
public String longHelp() {
return shortHelp() + "\n"
+ "\n"
- + "usage: svc power stayon [true|false|usb|ac]\n"
+ + "usage: svc power stayon [true|false|usb|ac|wireless]\n"
+ " Set the 'keep awake while plugged in' setting.\n";
}
@@ -48,7 +48,8 @@ public class PowerCommand extends Svc.Command {
int val;
if ("true".equals(args[2])) {
val = BatteryManager.BATTERY_PLUGGED_AC |
- BatteryManager.BATTERY_PLUGGED_USB;
+ BatteryManager.BATTERY_PLUGGED_USB |
+ BatteryManager.BATTERY_PLUGGED_WIRELESS;
}
else if ("false".equals(args[2])) {
val = 0;
@@ -56,8 +57,9 @@ public class PowerCommand extends Svc.Command {
val = BatteryManager.BATTERY_PLUGGED_USB;
} else if ("ac".equals(args[2])) {
val = BatteryManager.BATTERY_PLUGGED_AC;
- }
- else {
+ } else if ("wireless".equals(args[2])) {
+ val = BatteryManager.BATTERY_PLUGGED_WIRELESS;
+ } else {
break fail;
}
IPowerManager pm
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index a4d28b0..7a9f285 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -369,7 +369,7 @@ public class AccountManagerService
}
private void onUserRemoved(Intent intent) {
- int userId = intent.getIntExtra(Intent.EXTRA_USERID, -1);
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
if (userId < 1) return;
UserAccounts accounts;
@@ -900,7 +900,7 @@ public class AccountManagerService
private void sendAccountsChangedBroadcast(int userId) {
Log.i(TAG, "the accounts changed, sending broadcast of "
+ ACCOUNTS_CHANGED_INTENT.getAction());
- mContext.sendBroadcastToUser(ACCOUNTS_CHANGED_INTENT, userId);
+ mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId));
}
public void clearPassword(Account account) {
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 107e980..f874d56 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -536,6 +536,9 @@ public class ValueAnimator extends Animator {
// The per-thread list of all active animations
private final ArrayList<ValueAnimator> mAnimations = new ArrayList<ValueAnimator>();
+ // Used in doAnimationFrame() to avoid concurrent modifications of mAnimations
+ private final ArrayList<ValueAnimator> mTmpAnimations = new ArrayList<ValueAnimator>();
+
// The per-thread set of animations to be started on the next animation frame
private final ArrayList<ValueAnimator> mPendingAnimations = new ArrayList<ValueAnimator>();
@@ -605,28 +608,18 @@ public class ValueAnimator extends Animator {
// Now process all active animations. The return value from animationFrame()
// tells the handler whether it should now be ended
int numAnims = mAnimations.size();
- int i = 0;
- while (i < numAnims) {
- ValueAnimator anim = mAnimations.get(i);
- if (anim.doAnimationFrame(frameTime)) {
+ for (int i = 0; i < numAnims; ++i) {
+ mTmpAnimations.add(mAnimations.get(i));
+ }
+ for (int i = 0; i < numAnims; ++i) {
+ ValueAnimator anim = mTmpAnimations.get(i);
+ if (mAnimations.contains(anim) && anim.doAnimationFrame(frameTime)) {
mEndingAnims.add(anim);
}
- if (mAnimations.size() == numAnims) {
- ++i;
- } else {
- // An animation might be canceled or ended by client code
- // during the animation frame. Check to see if this happened by
- // seeing whether the current index is the same as it was before
- // calling animationFrame(). Another approach would be to copy
- // animations to a temporary list and process that list instead,
- // but that entails garbage and processing overhead that would
- // be nice to avoid.
- --numAnims;
- mEndingAnims.remove(anim);
- }
}
+ mTmpAnimations.clear();
if (mEndingAnims.size() > 0) {
- for (i = 0; i < mEndingAnims.size(); ++i) {
+ for (int i = 0; i < mEndingAnims.size(); ++i) {
mEndingAnims.get(i).endAnimation(this);
}
mEndingAnims.clear();
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 809acac..395a79c 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -74,7 +74,7 @@ import android.view.ViewGroup.LayoutParams;
import android.view.ViewManager;
import android.view.Window;
import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.widget.AdapterView;
@@ -4733,6 +4733,29 @@ public class Activity extends ContextThemeWrapper
mLoaderManager.dump(prefix + " ", fd, writer, args);
}
mFragments.dump(prefix, fd, writer, args);
+ writer.print(prefix); writer.println("View Hierarchy:");
+ dumpViewHierarchy(prefix + " ", writer, getWindow().getDecorView());
+ }
+
+ private void dumpViewHierarchy(String prefix, PrintWriter writer, View view) {
+ writer.print(prefix);
+ if (view == null) {
+ writer.println("null");
+ return;
+ }
+ writer.println(view.toString());
+ if (!(view instanceof ViewGroup)) {
+ return;
+ }
+ ViewGroup grp = (ViewGroup)view;
+ final int N = grp.getChildCount();
+ if (N <= 0) {
+ return;
+ }
+ prefix = prefix + " ";
+ for (int i=0; i<N; i++) {
+ dumpViewHierarchy(prefix, writer, grp.getChildAt(i));
+ }
}
/**
@@ -4995,7 +5018,9 @@ public class Activity extends ContextThemeWrapper
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
- mWindow.setWindowManager(null, mToken, mComponent.flattenToString(),
+ mWindow.setWindowManager(
+ (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
+ mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
@@ -5042,7 +5067,7 @@ public class Activity extends ContextThemeWrapper
if (mStopped) {
mStopped = false;
if (mToken != null && mParent == null) {
- WindowManagerImpl.getDefault().setStoppedState(mToken, false);
+ WindowManagerGlobal.getInstance().setStoppedState(mToken, false);
}
synchronized (mManagedCursors) {
@@ -5142,7 +5167,7 @@ public class Activity extends ContextThemeWrapper
}
if (mToken != null && mParent == null) {
- WindowManagerImpl.getDefault().setStoppedState(mToken, true);
+ WindowManagerGlobal.getInstance().setStoppedState(mToken, true);
}
mFragments.dispatchStop();
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 2c6d5d9..e644db4 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -30,6 +30,7 @@ import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Point;
+import android.hardware.display.DisplayManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
@@ -366,7 +367,7 @@ public class ActivityManager {
* (which tends to consume a lot more RAM).
* @hide
*/
- static public boolean isHighEndGfx(Display display) {
+ static public boolean isHighEndGfx() {
MemInfoReader reader = new MemInfoReader();
reader.readMemInfo();
if (reader.getTotalSize() >= (512*1024*1024)) {
@@ -374,6 +375,8 @@ public class ActivityManager {
// we can afford the overhead of graphics acceleration.
return true;
}
+
+ Display display = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
Point p = new Point();
display.getRealSize(p);
int pixels = p.x * p.y;
@@ -1375,6 +1378,13 @@ public class ActivityManager {
public static final int FLAG_PERSISTENT = 1<<1;
/**
+ * Constant for {@link #flags}: this process is associated with a
+ * persistent system app.
+ * @hide
+ */
+ public static final int FLAG_HAS_ACTIVITIES = 1<<2;
+
+ /**
* Flags of information. May be any of
* {@link #FLAG_CANT_SAVE_STATE}.
* @hide
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 4edfdfb..87b1e24 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -97,9 +97,9 @@ public class ActivityOptions {
/** @hide */
public static final int ANIM_SCALE_UP = 2;
/** @hide */
- public static final int ANIM_THUMBNAIL = 3;
+ public static final int ANIM_THUMBNAIL_SCALE_UP = 3;
/** @hide */
- public static final int ANIM_THUMBNAIL_DELAYED = 4;
+ public static final int ANIM_THUMBNAIL_SCALE_DOWN = 4;
private String mPackageName;
private int mAnimationType = ANIM_NONE;
@@ -262,20 +262,19 @@ public class ActivityOptions {
*/
public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
- return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, listener, false);
+ return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, true);
}
/**
- * Create an ActivityOptions specifying an animation where a thumbnail
- * is scaled from a given position to the new activity window that is
- * being started. Before the animation, there is a short delay.
+ * Create an ActivityOptions specifying an animation where an activity window
+ * is scaled from a given position to a thumbnail at a specified location.
*
- * @param source The View that this thumbnail is animating from. This
+ * @param source The View that this thumbnail is animating to. This
* defines the coordinate space for <var>startX</var> and <var>startY</var>.
- * @param thumbnail The bitmap that will be shown as the initial thumbnail
+ * @param thumbnail The bitmap that will be shown as the final thumbnail
* of the animation.
- * @param startX The x starting location of the bitmap, relative to <var>source</var>.
- * @param startY The y starting location of the bitmap, relative to <var>source</var>.
+ * @param startX The x end location of the bitmap, relative to <var>source</var>.
+ * @param startY The y end location of the bitmap, relative to <var>source</var>.
* @param listener Optional OnAnimationStartedListener to find out when the
* requested animation has started running. If for some reason the animation
* is not executed, the callback will happen immediately.
@@ -283,17 +282,17 @@ public class ActivityOptions {
* supply these options as the options Bundle when starting an activity.
* @hide
*/
- public static ActivityOptions makeDelayedThumbnailScaleUpAnimation(View source,
+ public static ActivityOptions makeThumbnailScaleDownAnimation(View source,
Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
- return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, listener, true);
+ return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, false);
}
- private static ActivityOptions makeThumbnailScaleUpAnimation(View source,
+ private static ActivityOptions makeThumbnailAnimation(View source,
Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,
- boolean delayed) {
+ boolean scaleUp) {
ActivityOptions opts = new ActivityOptions();
opts.mPackageName = source.getContext().getPackageName();
- opts.mAnimationType = delayed ? ANIM_THUMBNAIL_DELAYED : ANIM_THUMBNAIL;
+ opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_SCALE_UP : ANIM_THUMBNAIL_SCALE_DOWN;
opts.mThumbnail = thumbnail;
int[] pts = new int[2];
source.getLocationOnScreen(pts);
@@ -320,8 +319,8 @@ public class ActivityOptions {
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0);
mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0);
- } else if (mAnimationType == ANIM_THUMBNAIL ||
- mAnimationType == ANIM_THUMBNAIL_DELAYED) {
+ } else if (mAnimationType == ANIM_THUMBNAIL_SCALE_UP ||
+ mAnimationType == ANIM_THUMBNAIL_SCALE_DOWN) {
mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
mStartX = opts.getInt(KEY_ANIM_START_X, 0);
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
@@ -434,8 +433,8 @@ public class ActivityOptions {
}
mAnimationStartedListener = null;
break;
- case ANIM_THUMBNAIL:
- case ANIM_THUMBNAIL_DELAYED:
+ case ANIM_THUMBNAIL_SCALE_UP:
+ case ANIM_THUMBNAIL_SCALE_DOWN:
mAnimationType = otherOptions.mAnimationType;
mThumbnail = otherOptions.mThumbnail;
mStartX = otherOptions.mStartX;
@@ -479,8 +478,8 @@ public class ActivityOptions {
b.putInt(KEY_ANIM_START_WIDTH, mStartWidth);
b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight);
break;
- case ANIM_THUMBNAIL:
- case ANIM_THUMBNAIL_DELAYED:
+ case ANIM_THUMBNAIL_SCALE_UP:
+ case ANIM_THUMBNAIL_SCALE_DOWN:
b.putInt(KEY_ANIM_TYPE, mAnimationType);
b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
b.putInt(KEY_ANIM_START_X, mStartX);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7eb86f4..28c5abd 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -42,6 +42,7 @@ import android.database.sqlite.SQLiteDebug;
import android.database.sqlite.SQLiteDebug.DbStats;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.hardware.display.DisplayManager;
import android.net.IConnectivityManager;
import android.net.Proxy;
import android.net.ProxyProperties;
@@ -79,8 +80,9 @@ import android.view.ViewManager;
import android.view.ViewRootImpl;
import android.view.Window;
import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
import android.renderscript.RenderScript;
+import android.security.AndroidKeyStoreProvider;
import com.android.internal.os.BinderInternal;
import com.android.internal.os.RuntimeInit;
@@ -95,6 +97,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.net.InetAddress;
+import java.security.Security;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -1055,7 +1058,7 @@ public final class ActivityThread {
@Override
public void dumpGfxInfo(FileDescriptor fd, String[] args) {
dumpGraphicsInfo(fd);
- WindowManagerImpl.getDefault().dumpGfxInfo(fd);
+ WindowManagerGlobal.getInstance().dumpGfxInfo(fd);
}
@Override
@@ -1553,13 +1556,23 @@ public final class ActivityThread {
if (dm != null && !forceUpdate) {
return dm;
}
+
+ DisplayManager displayManager = DisplayManager.getInstance();
+ if (displayManager == null) {
+ // may be null early in system startup
+ dm = new DisplayMetrics();
+ dm.setToDefaults();
+ return dm;
+ }
+
if (dm == null) {
dm = new DisplayMetrics();
mDisplayMetrics.put(ci, dm);
}
+
CompatibilityInfoHolder cih = new CompatibilityInfoHolder();
cih.set(ci);
- Display d = WindowManagerImpl.getDefault().makeCompatible(cih).getDefaultDisplay();
+ Display d = displayManager.getCompatibleDisplay(Display.DEFAULT_DISPLAY, cih);
d.getMetrics(dm);
//Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
// + metrics.heightPixels + " den=" + metrics.density
@@ -2631,7 +2644,7 @@ public final class ActivityThread {
r.mPendingRemoveWindowManager.removeViewImmediate(r.mPendingRemoveWindow);
IBinder wtoken = r.mPendingRemoveWindow.getWindowToken();
if (wtoken != null) {
- WindowManagerImpl.getDefault().closeAll(wtoken,
+ WindowManagerGlobal.getInstance().closeAll(wtoken,
r.activity.getClass().getName(), "Activity");
}
}
@@ -3166,7 +3179,7 @@ public final class ActivityThread {
apk.mCompatibilityInfo.set(data.info);
}
handleConfigurationChanged(mConfiguration, data.info);
- WindowManagerImpl.getDefault().reportNewConfiguration(mConfiguration);
+ WindowManagerGlobal.getInstance().reportNewConfiguration(mConfiguration);
}
private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
@@ -3355,7 +3368,7 @@ public final class ActivityThread {
}
}
if (wtoken != null && r.mPendingRemoveWindow == null) {
- WindowManagerImpl.getDefault().closeAll(wtoken,
+ WindowManagerGlobal.getInstance().closeAll(wtoken,
r.activity.getClass().getName(), "Activity");
}
r.activity.mDecor = null;
@@ -3367,7 +3380,7 @@ public final class ActivityThread {
// by the app will leak. Well we try to warning them a lot
// about leaking windows, because that is a bug, so if they are
// using this recreate facility then they get to live with leaks.
- WindowManagerImpl.getDefault().closeAll(token,
+ WindowManagerGlobal.getInstance().closeAll(token,
r.activity.getClass().getName(), "Activity");
}
@@ -3795,7 +3808,7 @@ public final class ActivityThread {
}
// Cleanup hardware accelerated stuff
- WindowManagerImpl.getDefault().trimLocalMemory();
+ WindowManagerGlobal.getInstance().trimLocalMemory();
freeTextLayoutCachesIfNeeded(configDiff);
@@ -3935,7 +3948,7 @@ public final class ActivityThread {
final void handleTrimMemory(int level) {
if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
- final WindowManagerImpl windowManager = WindowManagerImpl.getDefault();
+ final WindowManagerGlobal windowManager = WindowManagerGlobal.getInstance();
windowManager.startTrimMemory(level);
ArrayList<ComponentCallbacks2> callbacks;
@@ -3948,7 +3961,7 @@ public final class ActivityThread {
callbacks.get(i).onTrimMemory(level);
}
- windowManager.endTrimMemory();
+ windowManager.endTrimMemory();
}
private void setupGraphicsSupport(LoadedApk info, File cacheDir) {
@@ -4001,8 +4014,7 @@ public final class ActivityThread {
// Persistent processes on low-memory devices do not get to
// use hardware accelerated drawing, since this can add too much
// overhead to the process.
- final Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
- if (!ActivityManager.isHighEndGfx(display)) {
+ if (!ActivityManager.isHighEndGfx()) {
HardwareRenderer.disable(false);
}
}
@@ -4055,13 +4067,14 @@ public final class ActivityThread {
final ContextImpl appContext = new ContextImpl();
appContext.init(data.info, null, this);
- final File cacheDir = appContext.getCacheDir();
-
- // Provide a usable directory for temporary files
- System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
+ if (!Process.isIsolated()) {
+ final File cacheDir = appContext.getCacheDir();
- setupGraphicsSupport(data.info, cacheDir);
+ // Provide a usable directory for temporary files
+ System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
+ setupGraphicsSupport(data.info, cacheDir);
+ }
/**
* For system applications on userdebug/eng builds, log stack
* traces of disk and network access to dropbox for analysis.
@@ -4799,16 +4812,19 @@ public final class ActivityThread {
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
+ Security.addProvider(new AndroidKeyStoreProvider());
+
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
- if (sMainThreadHandler == null) {
- sMainThreadHandler = new Handler();
- }
ActivityThread thread = new ActivityThread();
thread.attach(false);
+ if (sMainThreadHandler == null) {
+ sMainThreadHandler = thread.getHandler();
+ }
+
AsyncTask.init();
if (false) {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 115c867..86ee8a0 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -43,6 +43,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.ManifestDigest;
import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
@@ -984,6 +985,18 @@ final class ApplicationPackageManager extends PackageManager {
}
@Override
+ public void installPackageWithVerificationAndEncryption(Uri packageURI,
+ IPackageInstallObserver observer, int flags, String installerPackageName,
+ VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+ try {
+ mPM.installPackageWithVerificationAndEncryption(packageURI, observer, flags,
+ installerPackageName, verificationParams, encryptionParams);
+ } catch (RemoteException e) {
+ // Should never happen!
+ }
+ }
+
+ @Override
public void verifyPendingInstall(int id, int response) {
try {
mPM.verifyPendingInstall(id, response);
@@ -1066,10 +1079,10 @@ final class ApplicationPackageManager extends PackageManager {
}
@Override
- public void getPackageSizeInfo(String packageName,
- IPackageStatsObserver observer) {
+ public void getPackageSizeInfo(String packageName, int userHandle,
+ IPackageStatsObserver observer) {
try {
- mPM.getPackageSizeInfo(packageName, observer);
+ mPM.getPackageSizeInfo(packageName, userHandle, observer);
} catch (RemoteException e) {
// Should never happen!
}
@@ -1106,7 +1119,17 @@ final class ApplicationPackageManager extends PackageManager {
public void addPreferredActivity(IntentFilter filter,
int match, ComponentName[] set, ComponentName activity) {
try {
- mPM.addPreferredActivity(filter, match, set, activity);
+ mPM.addPreferredActivity(filter, match, set, activity, UserHandle.myUserId());
+ } catch (RemoteException e) {
+ // Should never happen!
+ }
+ }
+
+ @Override
+ public void addPreferredActivity(IntentFilter filter, int match,
+ ComponentName[] set, ComponentName activity, int userId) {
+ try {
+ mPM.addPreferredActivity(filter, match, set, activity, userId);
} catch (RemoteException e) {
// Should never happen!
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index ed4f0a7..0543f05 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -95,7 +95,9 @@ import android.telephony.TelephonyManager;
import android.content.ClipboardManager;
import android.util.AndroidRuntimeException;
import android.util.Log;
+import android.view.CompatibilityInfoHolder;
import android.view.ContextThemeWrapper;
+import android.view.Display;
import android.view.WindowManagerImpl;
import android.view.accessibility.AccessibilityManager;
import android.view.inputmethod.InputMethodManager;
@@ -499,8 +501,8 @@ class ContextImpl extends Context {
registerService(WINDOW_SERVICE, new ServiceFetcher() {
public Object getService(ContextImpl ctx) {
- return WindowManagerImpl.getDefault().makeCompatible(
- ctx.mPackageInfo.mCompatibilityInfo);
+ return new WindowManagerImpl(ctx.getOuterContext(),
+ Display.DEFAULT_DISPLAY);
}});
registerService(USER_SERVICE, new ServiceFetcher() {
@@ -906,12 +908,13 @@ class ContextImpl extends Context {
/** @hide */
@Override
- public void startActivityAsUser(Intent intent, int userId) {
+ public void startActivityAsUser(Intent intent, UserHandle user) {
try {
ActivityManagerNative.getDefault().startActivityAsUser(
mMainThread.getApplicationThread(), intent,
intent.resolveTypeIfNeeded(getContentResolver()),
- null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, null, userId);
+ null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, null,
+ user.getIdentifier());
} catch (RemoteException re) {
}
}
@@ -931,12 +934,13 @@ class ContextImpl extends Context {
/** @hide */
@Override
- public void startActivityAsUser(Intent intent, Bundle options, int userId) {
+ public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
try {
ActivityManagerNative.getDefault().startActivityAsUser(
mMainThread.getApplicationThread(), intent,
intent.resolveTypeIfNeeded(getContentResolver()),
- null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, options, userId);
+ null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, options,
+ user.getIdentifier());
} catch (RemoteException re) {
}
}
@@ -1062,19 +1066,19 @@ class ContextImpl extends Context {
}
@Override
- public void sendBroadcastToUser(Intent intent, int userHandle) {
+ public void sendBroadcastAsUser(Intent intent, UserHandle user) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(mMainThread.getApplicationThread(),
intent, resolvedType, null, Activity.RESULT_OK, null, null, null, false, false,
- userHandle);
+ user.getIdentifier());
} catch (RemoteException e) {
}
}
@Override
- public void sendOrderedBroadcastToUser(Intent intent, int userHandle,
+ public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
BroadcastReceiver resultReceiver, Handler scheduler,
int initialCode, String initialData, Bundle initialExtras) {
IIntentReceiver rd = null;
@@ -1100,7 +1104,7 @@ class ContextImpl extends Context {
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, null,
- true, false, userHandle);
+ true, false, user.getIdentifier());
} catch (RemoteException e) {
}
}
@@ -1607,6 +1611,11 @@ class ContextImpl extends Context {
return mRestricted;
}
+ @Override
+ public CompatibilityInfoHolder getCompatibilityInfo() {
+ return mPackageInfo.mCompatibilityInfo;
+ }
+
private File getDataDirFile() {
if (mPackageInfo != null) {
return mPackageInfo.getDataDirFile();
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index c1e11bb..52a6557 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -428,92 +428,26 @@ final class FragmentManagerImpl extends FragmentManager {
}
};
- private void logViewHierarchy(String prefix, View view) {
- StringBuilder builder = new StringBuilder(128);
- builder.append(prefix);
- DebugUtils.buildShortClassTag(view, builder);
- int id = view.getId();
- if (id != -1) {
- builder.append(" #");
- builder.append(Integer.toHexString(id));
- if (id != 0 && id != -1) {
- try {
- String pkgname;
- switch (id&0xff000000) {
- case 0x7f000000:
- pkgname="app";
- break;
- case 0x01000000:
- pkgname="android";
- break;
- default:
- pkgname = view.getResources().getResourcePackageName(id);
- break;
- }
- String typename = view.getResources().getResourceTypeName(id);
- String entryname = view.getResources().getResourceEntryName(id);
- builder.append(" (");
- builder.append(pkgname);
- builder.append(":");
- builder.append(typename);
- builder.append("/");
- builder.append(entryname);
- builder.append(")");
- } catch (Resources.NotFoundException e) {
- }
- }
- }
- Object tag = view.getTag();
- if (tag != null) {
- builder.append(" ");
- builder.append(tag);
- }
- builder.append("}");
- Log.e(TAG, builder.toString());
-
- if (!(view instanceof ViewGroup)) {
- return;
- }
- ViewGroup grp = (ViewGroup)view;
- final int N = grp.getChildCount();
- if (N <= 0) {
- return;
- }
- prefix = prefix + " ";
- for (int i=0; i<N; i++) {
- logViewHierarchy(prefix, grp.getChildAt(i));
- }
- }
-
- private void throwNoViewFound(Fragment f) {
- String msg = "No view found for id 0x"
- + Integer.toHexString(f.mContainerId) + " ("
- + f.getResources().getResourceName(f.mContainerId)
- + ") for fragment " + f;
- Log.e(TAG, msg);
- Log.e(TAG, "Activity state:");
- if (f.getActivity() != null) {
+ private void throwException(RuntimeException ex) {
+ Log.e(TAG, ex.getMessage());
+ LogWriter logw = new LogWriter(Log.ERROR, TAG);
+ PrintWriter pw = new PrintWriter(logw);
+ if (mActivity != null) {
+ Log.e(TAG, "Activity state:");
try {
- LogWriter logw = new LogWriter(Log.ERROR, TAG);
- PrintWriter pw = new PrintWriter(logw);
- f.getActivity().dump(" ", null, pw, new String[] { });
+ mActivity.dump(" ", null, pw, new String[] { });
} catch (Exception e) {
Log.e(TAG, "Failed dumping state", e);
}
} else {
- Log.e(TAG, " NULL ACTIVITY!");
- }
- Log.e(TAG, "View hierarchy:");
- if (f.getActivity() != null) {
+ Log.e(TAG, "Fragment manager state:");
try {
- logViewHierarchy(" ", f.getActivity().getWindow().getDecorView());
+ dump(" ", null, pw, new String[] { });
} catch (Exception e) {
- Log.e(TAG, "Failed dumping view hierarchy", e);
+ Log.e(TAG, "Failed dumping state", e);
}
- } else {
- Log.e(TAG, " NULL ACTIVITY!");
}
- throw new IllegalArgumentException(msg);
+ throw ex;
}
@Override
@@ -608,8 +542,8 @@ final class FragmentManagerImpl extends FragmentManager {
@Override
public void putFragment(Bundle bundle, String key, Fragment fragment) {
if (fragment.mIndex < 0) {
- throw new IllegalStateException("Fragment " + fragment
- + " is not currently in the FragmentManager");
+ throwException(new IllegalStateException("Fragment " + fragment
+ + " is not currently in the FragmentManager"));
}
bundle.putInt(key, fragment.mIndex);
}
@@ -621,13 +555,13 @@ final class FragmentManagerImpl extends FragmentManager {
return null;
}
if (index >= mActive.size()) {
- throw new IllegalStateException("Fragement no longer exists for key "
- + key + ": index " + index);
+ throwException(new IllegalStateException("Fragement no longer exists for key "
+ + key + ": index " + index));
}
Fragment f = mActive.get(index);
if (f == null) {
- throw new IllegalStateException("Fragement no longer exists for key "
- + key + ": index " + index);
+ throwException(new IllegalStateException("Fragement no longer exists for key "
+ + key + ": index " + index));
}
return f;
}
@@ -635,8 +569,8 @@ final class FragmentManagerImpl extends FragmentManager {
@Override
public Fragment.SavedState saveFragmentInstanceState(Fragment fragment) {
if (fragment.mIndex < 0) {
- throw new IllegalStateException("Fragment " + fragment
- + " is not currently in the FragmentManager");
+ throwException(new IllegalStateException("Fragment " + fragment
+ + " is not currently in the FragmentManager"));
}
if (fragment.mState > Fragment.INITIALIZING) {
Bundle result = saveFragmentBasicState(fragment);
@@ -913,7 +847,11 @@ final class FragmentManagerImpl extends FragmentManager {
if (f.mContainerId != 0) {
container = (ViewGroup)mActivity.findViewById(f.mContainerId);
if (container == null && !f.mRestored) {
- throwNoViewFound(f);
+ throwException(new IllegalArgumentException(
+ "No view found for id 0x"
+ + Integer.toHexString(f.mContainerId) + " ("
+ + f.getResources().getResourceName(f.mContainerId)
+ + ") for fragment " + f));
}
}
f.mContainer = container;
@@ -1674,12 +1612,9 @@ final class FragmentManagerImpl extends FragmentManager {
Fragment f = mActive.get(i);
if (f != null) {
if (f.mIndex < 0) {
- String msg = "Failure saving state: active " + f
- + " has cleared index: " + f.mIndex;
- Slog.e(TAG, msg);
- dump(" ", null, new PrintWriter(new LogWriter(
- Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
- throw new IllegalStateException(msg);
+ throwException(new IllegalStateException(
+ "Failure saving state: active " + f
+ + " has cleared index: " + f.mIndex));
}
haveFragments = true;
@@ -1692,12 +1627,9 @@ final class FragmentManagerImpl extends FragmentManager {
if (f.mTarget != null) {
if (f.mTarget.mIndex < 0) {
- String msg = "Failure saving state: " + f
- + " has target not in fragment manager: " + f.mTarget;
- Slog.e(TAG, msg);
- dump(" ", null, new PrintWriter(new LogWriter(
- Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
- throw new IllegalStateException(msg);
+ throwException(new IllegalStateException(
+ "Failure saving state: " + f
+ + " has target not in fragment manager: " + f.mTarget));
}
if (fs.mSavedFragmentState == null) {
fs.mSavedFragmentState = new Bundle();
@@ -1736,12 +1668,9 @@ final class FragmentManagerImpl extends FragmentManager {
for (int i=0; i<N; i++) {
added[i] = mAdded.get(i).mIndex;
if (added[i] < 0) {
- String msg = "Failure saving state: active " + mAdded.get(i)
- + " has cleared index: " + added[i];
- Slog.e(TAG, msg);
- dump(" ", null, new PrintWriter(new LogWriter(
- Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
- throw new IllegalStateException(msg);
+ throwException(new IllegalStateException(
+ "Failure saving state: active " + mAdded.get(i)
+ + " has cleared index: " + added[i]));
}
if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
+ ": " + mAdded.get(i));
@@ -1846,8 +1775,8 @@ final class FragmentManagerImpl extends FragmentManager {
for (int i=0; i<fms.mAdded.length; i++) {
Fragment f = mActive.get(fms.mAdded[i]);
if (f == null) {
- throw new IllegalStateException(
- "No instantiated fragment for index #" + fms.mAdded[i]);
+ throwException(new IllegalStateException(
+ "No instantiated fragment for index #" + fms.mAdded[i]));
}
f.mAdded = true;
if (DEBUG) Log.v(TAG, "restoreAllState: making added #" + i + ": " + f);
@@ -1875,7 +1804,7 @@ final class FragmentManagerImpl extends FragmentManager {
}
public void attachActivity(Activity activity) {
- if (mActivity != null) throw new IllegalStateException();
+ if (mActivity != null) throw new IllegalStateException("Already attached");
mActivity = activity;
}
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index ef61af7..22a21cd 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -16,13 +16,12 @@
package android.app;
-import android.content.Context;
import android.os.Binder;
import android.os.RemoteException;
import android.os.IBinder;
-import android.os.ServiceManager;
import android.view.IWindowManager;
import android.view.IOnKeyguardExitResult;
+import android.view.WindowManagerGlobal;
/**
* Class that can be used to lock and unlock the keyboard. Get an instance of this
@@ -111,7 +110,7 @@ public class KeyguardManager {
KeyguardManager() {
- mWM = IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
+ mWM = WindowManagerGlobal.getWindowManagerService();
}
/**
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index f638f7e..a57c516 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -639,22 +639,22 @@ public final class PendingIntent implements Parcelable {
/**
* Return the user handle of the application that created this
* PendingIntent, that is the user under which you will actually be
- * sending the Intent. The returned integer is supplied by the system, so
+ * sending the Intent. The returned UserHandle is supplied by the system, so
* that an application can not spoof its user. See
* {@link android.os.Process#myUserHandle() Process.myUserHandle()} for
* more explanation of user handles.
*
- * @return The user handle of the PendingIntent, or -1 if there is
+ * @return The user handle of the PendingIntent, or null if there is
* none associated with it.
*/
- public int getTargetUserHandle() {
+ public UserHandle getTargetUserHandle() {
try {
int uid = ActivityManagerNative.getDefault()
.getUidForIntentSender(mTarget);
- return uid > 0 ? UserHandle.getUserId(uid) : -1;
+ return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
} catch (RemoteException e) {
// Should never happen.
- return -1;
+ return null;
}
}
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 615e8ce..201d7b2 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -17,7 +17,6 @@
package android.app;
import android.content.SharedPreferences;
-import android.os.FileUtils.FileStatus;
import android.os.FileUtils;
import android.os.Looper;
import android.util.Log;
@@ -45,6 +44,11 @@ import java.util.WeakHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
+import libcore.io.ErrnoException;
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
+import libcore.io.StructStat;
+
final class SharedPreferencesImpl implements SharedPreferences {
private static final String TAG = "SharedPreferencesImpl";
private static final boolean DEBUG = false;
@@ -105,26 +109,32 @@ final class SharedPreferencesImpl implements SharedPreferences {
}
Map map = null;
- FileStatus stat = new FileStatus();
- if (FileUtils.getFileStatus(mFile.getPath(), stat) && mFile.canRead()) {
- try {
- BufferedInputStream str = new BufferedInputStream(
- new FileInputStream(mFile), 16*1024);
- map = XmlUtils.readMapXml(str);
- str.close();
- } catch (XmlPullParserException e) {
- Log.w(TAG, "getSharedPreferences", e);
- } catch (FileNotFoundException e) {
- Log.w(TAG, "getSharedPreferences", e);
- } catch (IOException e) {
- Log.w(TAG, "getSharedPreferences", e);
+ StructStat stat = null;
+ try {
+ stat = Libcore.os.stat(mFile.getPath());
+ if (mFile.canRead()) {
+ BufferedInputStream str = null;
+ try {
+ str = new BufferedInputStream(
+ new FileInputStream(mFile), 16*1024);
+ map = XmlUtils.readMapXml(str);
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "getSharedPreferences", e);
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "getSharedPreferences", e);
+ } catch (IOException e) {
+ Log.w(TAG, "getSharedPreferences", e);
+ } finally {
+ IoUtils.closeQuietly(str);
+ }
}
+ } catch (ErrnoException e) {
}
mLoaded = true;
if (map != null) {
mMap = map;
- mStatTimestamp = stat.mtime;
- mStatSize = stat.size;
+ mStatTimestamp = stat.st_mtime;
+ mStatSize = stat.st_size;
} else {
mMap = new HashMap<String, Object>();
}
@@ -155,12 +165,21 @@ final class SharedPreferencesImpl implements SharedPreferences {
return false;
}
}
- FileStatus stat = new FileStatus();
- if (!FileUtils.getFileStatus(mFile.getPath(), stat)) {
+
+ final StructStat stat;
+ try {
+ /*
+ * Metadata operations don't usually count as a block guard
+ * violation, but we explicitly want this one.
+ */
+ BlockGuard.getThreadPolicy().onReadFromDisk();
+ stat = Libcore.os.stat(mFile.getPath());
+ } catch (ErrnoException e) {
return true;
}
+
synchronized (this) {
- return mStatTimestamp != stat.mtime || mStatSize != stat.size;
+ return mStatTimestamp != stat.st_mtime || mStatSize != stat.st_size;
}
}
@@ -577,12 +596,14 @@ final class SharedPreferencesImpl implements SharedPreferences {
FileUtils.sync(str);
str.close();
ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
- FileStatus stat = new FileStatus();
- if (FileUtils.getFileStatus(mFile.getPath(), stat)) {
+ try {
+ final StructStat stat = Libcore.os.stat(mFile.getPath());
synchronized (this) {
- mStatTimestamp = stat.mtime;
- mStatSize = stat.size;
+ mStatTimestamp = stat.st_mtime;
+ mStatSize = stat.st_size;
}
+ } catch (ErrnoException e) {
+ // Do nothing
}
// Writing was successful, delete the backup file if there is one.
mBackupFile.delete();
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 27843ac..1ad2e6d 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -43,6 +43,7 @@ import android.util.DisplayMetrics;
import android.util.Log;
import android.view.ViewRootImpl;
import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -689,7 +690,7 @@ public class WallpaperManager {
public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
try {
//Log.v(TAG, "Sending new wallpaper offsets from app...");
- ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
+ WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep);
//Log.v(TAG, "...app returning after sending offsets!");
} catch (RemoteException e) {
@@ -727,7 +728,7 @@ public class WallpaperManager {
int x, int y, int z, Bundle extras) {
try {
//Log.v(TAG, "Sending new wallpaper offsets from app...");
- ViewRootImpl.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand(
+ WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand(
windowToken, action, x, y, z, extras, false);
//Log.v(TAG, "...app returning after sending offsets!");
} catch (RemoteException e) {
@@ -747,7 +748,7 @@ public class WallpaperManager {
*/
public void clearWallpaperOffsets(IBinder windowToken) {
try {
- ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
+ WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
windowToken, -1, -1, -1, -1);
} catch (RemoteException e) {
// Ignore.
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 2c19c0c..c76bf91 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -29,6 +29,7 @@ import android.os.ServiceManager;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.widget.RemoteViews;
+import android.widget.RemoteViews.OnClickHandler;
import com.android.internal.appwidget.IAppWidgetHost;
import com.android.internal.appwidget.IAppWidgetService;
@@ -83,7 +84,7 @@ public class AppWidgetHost {
public UpdateHandler(Looper looper) {
super(looper);
}
-
+
public void handleMessage(Message msg) {
switch (msg.what) {
case HANDLE_UPDATE: {
@@ -105,16 +106,25 @@ public class AppWidgetHost {
}
}
}
-
+
Handler mHandler;
int mHostId;
Callbacks mCallbacks = new Callbacks();
final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<Integer, AppWidgetHostView>();
+ private OnClickHandler mOnClickHandler;
public AppWidgetHost(Context context, int hostId) {
+ this(context, hostId, null);
+ }
+
+ /**
+ * @hide
+ */
+ public AppWidgetHost(Context context, int hostId, OnClickHandler handler) {
mContext = context;
mHostId = hostId;
+ mOnClickHandler = handler;
mHandler = new UpdateHandler(context.getMainLooper());
mDisplayMetrics = context.getResources().getDisplayMetrics();
synchronized (sServiceLock) {
@@ -132,7 +142,7 @@ public class AppWidgetHost {
public void startListening() {
int[] updatedIds;
ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
-
+
try {
if (mPackageName == null) {
mPackageName = mContext.getPackageName();
@@ -180,7 +190,7 @@ public class AppWidgetHost {
}
/**
- * Stop listening to changes for this AppWidget.
+ * Stop listening to changes for this AppWidget.
*/
public void deleteAppWidgetId(int appWidgetId) {
synchronized (mViews) {
@@ -235,6 +245,7 @@ public class AppWidgetHost {
public final AppWidgetHostView createView(Context context, int appWidgetId,
AppWidgetProviderInfo appWidget) {
AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
+ view.setOnClickHandler(mOnClickHandler);
view.setAppWidget(appWidgetId, appWidget);
synchronized (mViews) {
mViews.put(appWidgetId, view);
@@ -246,6 +257,7 @@ public class AppWidgetHost {
throw new RuntimeException("system server dead?", e);
}
view.updateAppWidget(views);
+
return view;
}
@@ -255,7 +267,7 @@ public class AppWidgetHost {
*/
protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
AppWidgetProviderInfo appWidget) {
- return new AppWidgetHostView(context);
+ return new AppWidgetHostView(context, mOnClickHandler);
}
/**
@@ -265,7 +277,7 @@ public class AppWidgetHost {
AppWidgetHostView v;
// Convert complex to dp -- we are getting the AppWidgetProviderInfo from the
- // AppWidgetService, which doesn't have our context, hence we need to do the
+ // AppWidgetService, which doesn't have our context, hence we need to do the
// conversion here.
appWidget.minWidth =
TypedValue.complexToDimensionPixelSize(appWidget.minWidth, mDisplayMetrics);
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index ed95ae5..603ceb7 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -44,6 +44,7 @@ import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.RemoteViews;
+import android.widget.RemoteViews.OnClickHandler;
import android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback;
import android.widget.TextView;
@@ -83,7 +84,8 @@ public class AppWidgetHostView extends FrameLayout {
long mFadeStartTime = -1;
Bitmap mOld;
Paint mOldPaint = new Paint();
-
+ private OnClickHandler mOnClickHandler;
+
/**
* Create a host view. Uses default fade animations.
*/
@@ -92,9 +94,17 @@ public class AppWidgetHostView extends FrameLayout {
}
/**
+ * @hide
+ */
+ public AppWidgetHostView(Context context, OnClickHandler handler) {
+ this(context, android.R.anim.fade_in, android.R.anim.fade_out);
+ mOnClickHandler = handler;
+ }
+
+ /**
* Create a host view. Uses specified animations when pushing
* {@link #updateAppWidget(RemoteViews)}.
- *
+ *
* @param animationIn Resource ID of in animation to use
* @param animationOut Resource ID of out animation to use
*/
@@ -109,6 +119,17 @@ public class AppWidgetHostView extends FrameLayout {
}
/**
+ * Pass the given handler to RemoteViews when updating this widget. Unless this
+ * is done immediatly after construction, a call to {@link #updateAppWidget(RemoteViews)}
+ * should be made.
+ * @param handler
+ * @hide
+ */
+ public void setOnClickHandler(OnClickHandler handler) {
+ mOnClickHandler = handler;
+ }
+
+ /**
* Set the AppWidget that will be displayed by this view. This method also adds default padding
* to widgets, as described in {@link #getDefaultPaddingForWidget(Context, ComponentName, Rect)}
* and can be overridden in order to add custom padding.
@@ -177,7 +198,7 @@ public class AppWidgetHostView extends FrameLayout {
public int getAppWidgetId() {
return mAppWidgetId;
}
-
+
public AppWidgetProviderInfo getAppWidgetInfo() {
return mInfo;
}
@@ -281,12 +302,13 @@ public class AppWidgetHostView extends FrameLayout {
* AppWidget provider. Will animate into these new views as needed
*/
public void updateAppWidget(RemoteViews remoteViews) {
+
if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld);
boolean recycled = false;
View content = null;
Exception exception = null;
-
+
// Capture the old view into a bitmap so we can do the crossfade.
if (CROSSFADE) {
if (mFadeStartTime < 0) {
@@ -305,7 +327,7 @@ public class AppWidgetHostView extends FrameLayout {
}
}
}
-
+
if (remoteViews == null) {
if (mViewMode == VIEW_MODE_DEFAULT) {
// We've already done this -- nothing to do.
@@ -324,7 +346,7 @@ public class AppWidgetHostView extends FrameLayout {
// layout matches, try recycling it
if (content == null && layoutId == mLayoutId) {
try {
- remoteViews.reapply(mContext, mView);
+ remoteViews.reapply(mContext, mView, mOnClickHandler);
content = mView;
recycled = true;
if (LOGD) Log.d(TAG, "was able to recycled existing layout");
@@ -332,11 +354,11 @@ public class AppWidgetHostView extends FrameLayout {
exception = e;
}
}
-
+
// Try normal RemoteView inflation
if (content == null) {
try {
- content = remoteViews.apply(mContext, this);
+ content = remoteViews.apply(mContext, this, mOnClickHandler);
if (LOGD) Log.d(TAG, "had to inflate new layout");
} catch (RuntimeException e) {
exception = e;
@@ -346,7 +368,7 @@ public class AppWidgetHostView extends FrameLayout {
mLayoutId = layoutId;
mViewMode = VIEW_MODE_CONTENT;
}
-
+
if (content == null) {
if (mViewMode == VIEW_MODE_ERROR) {
// We've already done this -- nothing to do.
@@ -356,7 +378,7 @@ public class AppWidgetHostView extends FrameLayout {
content = getErrorView();
mViewMode = VIEW_MODE_ERROR;
}
-
+
if (!recycled) {
prepareView(content);
addView(content);
@@ -455,7 +477,7 @@ public class AppWidgetHostView extends FrameLayout {
return super.drawChild(canvas, child, drawingTime);
}
}
-
+
/**
* Prepare the given view to be shown. This might include adjusting
* {@link FrameLayout.LayoutParams} before inserting.
@@ -471,7 +493,7 @@ public class AppWidgetHostView extends FrameLayout {
requested.gravity = Gravity.CENTER;
view.setLayoutParams(requested);
}
-
+
/**
* Inflate and return the default layout requested by AppWidget provider.
*/
@@ -481,7 +503,7 @@ public class AppWidgetHostView extends FrameLayout {
}
View defaultView = null;
Exception exception = null;
-
+
try {
if (mInfo != null) {
Context theirContext = mContext.createPackageContext(
@@ -500,19 +522,19 @@ public class AppWidgetHostView extends FrameLayout {
} catch (RuntimeException e) {
exception = e;
}
-
+
if (exception != null) {
Log.w(TAG, "Error inflating AppWidget " + mInfo + ": " + exception.toString());
}
-
+
if (defaultView == null) {
if (LOGD) Log.d(TAG, "getDefaultView couldn't find any view, so inflating error");
defaultView = getErrorView();
}
-
+
return defaultView;
}
-
+
/**
* Inflate and return a view that represents an error state.
*/
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 8a69c3a..23d8f46 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -279,7 +279,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
final int uid = Binder.getCallingUid();
String missingPerm = null;
- if (uid == mMyUid) {
+ if (UserHandle.isSameApp(uid, mMyUid)) {
return;
}
@@ -340,7 +340,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
final int uid = Binder.getCallingUid();
String missingPerm = null;
- if (uid == mMyUid) {
+ if (UserHandle.isSameApp(uid, mMyUid)) {
return;
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a90142a..1460bf5 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -32,7 +32,9 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.os.UserHandle;
import android.util.AttributeSet;
+import android.view.CompatibilityInfoHolder;
import java.io.File;
import java.io.FileInputStream;
@@ -855,11 +857,11 @@ public abstract class Context {
* Same as {@link #startActivity(Intent)}, but for a specific user. It requires holding
* the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission.
* @param intent The description of the activity to start.
- * @param userId The user id of the user to start this activity for.
+ * @param user The UserHandle of the user to start this activity for.
* @throws ActivityNotFoundException
* @hide
*/
- public void startActivityAsUser(Intent intent, int userId) {
+ public void startActivityAsUser(Intent intent, UserHandle user) {
throw new RuntimeException("Not implemented. Must override in a subclass.");
}
@@ -898,11 +900,11 @@ public abstract class Context {
* May be null if there are no options. See {@link android.app.ActivityOptions}
* for how to build the Bundle supplied here; there are no supported definitions
* for building it manually.
- * @param userId The user id of the user to start this activity for.
+ * @param user The UserHandle of the user to start this activity for.
* @throws ActivityNotFoundException
* @hide
*/
- public void startActivityAsUser(Intent intent, Bundle options, int userId) {
+ public void startActivityAsUser(Intent intent, Bundle options, UserHandle userId) {
throw new RuntimeException("Not implemented. Must override in a subclass.");
}
@@ -1119,10 +1121,10 @@ public abstract class Context {
* requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
* permission.
* @param intent The intent to broadcast
- * @param userHandle User to send the intent to.
+ * @param user UserHandle to send the intent to.
* @see #sendBroadcast(Intent)
*/
- public abstract void sendBroadcastToUser(Intent intent, int userHandle);
+ public abstract void sendBroadcastAsUser(Intent intent, UserHandle user);
/**
* Same as
@@ -1136,7 +1138,7 @@ public abstract class Context {
*
* @param intent The Intent to broadcast; all receivers matching this
* Intent will receive the broadcast.
- * @param userHandle User to send the intent to.
+ * @param user UserHandle to send the intent to.
* @param resultReceiver Your own BroadcastReceiver to treat as the final
* receiver of the broadcast.
* @param scheduler A custom Handler with which to schedule the
@@ -1151,7 +1153,7 @@ public abstract class Context {
*
* @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
*/
- public abstract void sendOrderedBroadcastToUser(Intent intent, int userHandle,
+ public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
BroadcastReceiver resultReceiver, Handler scheduler,
int initialCode, String initialData, Bundle initialExtras);
@@ -2463,6 +2465,16 @@ public abstract class Context {
public abstract Context createConfigurationContext(Configuration overrideConfiguration);
/**
+ * Gets the compatibility info holder for this context. This information
+ * is provided on a per-application basis and is used to simulate lower density
+ * display metrics for legacy applications.
+ *
+ * @return The compatibility info holder, or null if not required by the application.
+ * @hide
+ */
+ public abstract CompatibilityInfoHolder getCompatibilityInfo();
+
+ /**
* Indicates whether this Context is restricted.
*
* @return True if this Context is restricted, false otherwise.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index fdf60ab..3a13725 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -30,6 +30,8 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.os.UserHandle;
+import android.view.CompatibilityInfoHolder;
import java.io.File;
import java.io.FileInputStream;
@@ -279,8 +281,8 @@ public class ContextWrapper extends Context {
/** @hide */
@Override
- public void startActivityAsUser(Intent intent, int userId) {
- mBase.startActivityAsUser(intent, userId);
+ public void startActivityAsUser(Intent intent, UserHandle user) {
+ mBase.startActivityAsUser(intent, user);
}
@Override
@@ -290,8 +292,8 @@ public class ContextWrapper extends Context {
/** @hide */
@Override
- public void startActivityAsUser(Intent intent, Bundle options, int userId) {
- mBase.startActivityAsUser(intent, options, userId);
+ public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
+ mBase.startActivityAsUser(intent, options, user);
}
@Override
@@ -347,15 +349,15 @@ public class ContextWrapper extends Context {
}
@Override
- public void sendBroadcastToUser(Intent intent, int userHandle) {
- mBase.sendBroadcastToUser(intent, userHandle);
+ public void sendBroadcastAsUser(Intent intent, UserHandle user) {
+ mBase.sendBroadcastAsUser(intent, user);
}
@Override
- public void sendOrderedBroadcastToUser(Intent intent, int userHandle,
+ public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
BroadcastReceiver resultReceiver, Handler scheduler,
int initialCode, String initialData, Bundle initialExtras) {
- mBase.sendOrderedBroadcastToUser(intent, userHandle, resultReceiver,
+ mBase.sendOrderedBroadcastAsUser(intent, user, resultReceiver,
scheduler, initialCode, initialData, initialExtras);
}
@@ -542,4 +544,10 @@ public class ContextWrapper extends Context {
public boolean isRestricted() {
return mBase.isRestricted();
}
+
+ /** @hide */
+ @Override
+ public CompatibilityInfoHolder getCompatibilityInfo() {
+ return mBase.getCompatibilityInfo();
+ }
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index d325186..06edf32 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -571,7 +571,7 @@ import java.util.Set;
* <li> {@link #EXTRA_INITIAL_INTENTS}
* <li> {@link #EXTRA_INTENT}
* <li> {@link #EXTRA_KEY_EVENT}
- * <li> {@link #EXTRA_ORIGINATING_URL}
+ * <li> {@link #EXTRA_ORIGINATING_URI}
* <li> {@link #EXTRA_PHONE_NUMBER}
* <li> {@link #EXTRA_REFERRER}
* <li> {@link #EXTRA_REMOTE_INTENT_TOKEN}
@@ -1288,17 +1288,17 @@ public class Intent implements Parcelable, Cloneable {
= "android.intent.extra.NOT_UNKNOWN_SOURCE";
/**
- * Used as a string extra field with {@link #ACTION_INSTALL_PACKAGE} and
- * {@link #ACTION_VIEW} to indicate the URL from which the local APK in the Intent
+ * Used as a URI extra field with {@link #ACTION_INSTALL_PACKAGE} and
+ * {@link #ACTION_VIEW} to indicate the URI from which the local APK in the Intent
* data field originated from.
*/
- public static final String EXTRA_ORIGINATING_URL
- = "android.intent.extra.ORIGINATING_URL";
+ public static final String EXTRA_ORIGINATING_URI
+ = "android.intent.extra.ORIGINATING_URI";
/**
- * Used as a string extra field with {@link #ACTION_INSTALL_PACKAGE} and
- * {@link #ACTION_VIEW} to indicate the HTTP referrer associated with the Intent
- * data field or {@link #EXTRA_ORIGINATING_URL}.
+ * Used as a URI extra field with {@link #ACTION_INSTALL_PACKAGE} and
+ * {@link #ACTION_VIEW} to indicate the HTTP referrer URI associated with the Intent
+ * data field or {@link #EXTRA_ORIGINATING_URI}.
*/
public static final String EXTRA_REFERRER
= "android.intent.extra.REFERRER";
@@ -2279,24 +2279,24 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.action.PRE_BOOT_COMPLETED";
/**
- * Broadcast sent to the system when a user is added. Carries an extra EXTRA_USERID that has the
- * userid of the new user.
+ * Broadcast sent to the system when a user is added. Carries an extra EXTRA_USER_HANDLE that has the
+ * userHandle of the new user.
* @hide
*/
public static final String ACTION_USER_ADDED =
"android.intent.action.USER_ADDED";
/**
- * Broadcast sent to the system when a user is removed. Carries an extra EXTRA_USERID that has
- * the userid of the user.
+ * Broadcast sent to the system when a user is removed. Carries an extra EXTRA_USER_HANDLE that has
+ * the userHandle of the user.
* @hide
*/
public static final String ACTION_USER_REMOVED =
"android.intent.action.USER_REMOVED";
/**
- * Broadcast sent to the system when the user switches. Carries an extra EXTRA_USERID that has
- * the userid of the user to become the current one.
+ * Broadcast sent to the system when the user switches. Carries an extra EXTRA_USER_HANDLE that has
+ * the userHandle of the user to become the current one.
* @hide
*/
public static final String ACTION_USER_SWITCHED =
@@ -2852,12 +2852,12 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.extra.LOCAL_ONLY";
/**
- * The userid carried with broadcast intents related to addition, removal and switching of users
+ * The userHandle carried with broadcast intents related to addition, removal and switching of users
* - {@link #ACTION_USER_ADDED}, {@link #ACTION_USER_REMOVED} and {@link #ACTION_USER_SWITCHED}.
* @hide
*/
- public static final String EXTRA_USERID =
- "android.intent.extra.user_id";
+ public static final String EXTRA_USER_HANDLE =
+ "android.intent.extra.user_handle";
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 1801488..079241a 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -245,22 +245,22 @@ public class IntentSender implements Parcelable {
/**
* Return the user handle of the application that created this
* PendingIntent, that is the user under which you will actually be
- * sending the Intent. The returned integer is supplied by the system, so
+ * sending the Intent. The returned UserHandle is supplied by the system, so
* that an application can not spoof its user. See
* {@link android.os.Process#myUserHandle() Process.myUserHandle()} for
* more explanation of user handles.
*
- * @return The user handle of the PendingIntent, or -1 if there is
+ * @return The user handle of the PendingIntent, or null if there is
* none associated with it.
*/
- public int getTargetUserHandle() {
+ public UserHandle getTargetUserHandle() {
try {
int uid = ActivityManagerNative.getDefault()
.getUidForIntentSender(mTarget);
- return uid > 0 ? UserHandle.getUserId(uid) : -1;
+ return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
} catch (RemoteException e) {
// Should never happen.
- return -1;
+ return null;
}
}
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 3d3ff51..ee075b4 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -895,7 +895,7 @@ public class SyncManager implements OnAccountsUpdateListener {
}
private void onUserRemoved(Intent intent) {
- int userId = intent.getIntExtra(Intent.EXTRA_USERID, -1);
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
if (userId == -1) return;
// Clean up the storage engine database
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 22807a4..3f4b994 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -39,6 +39,7 @@ import android.content.pm.PermissionInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
@@ -200,7 +201,7 @@ interface IPackageManager {
List<PackageInfo> getPreferredPackages(int flags);
void addPreferredActivity(in IntentFilter filter, int match,
- in ComponentName[] set, in ComponentName activity);
+ in ComponentName[] set, in ComponentName activity, int userId);
void replacePreferredActivity(in IntentFilter filter, int match,
in ComponentName[] set, in ComponentName activity);
@@ -304,10 +305,11 @@ interface IPackageManager {
* Get package statistics including the code, data and cache size for
* an already installed package
* @param packageName The package name of the application
+ * @param userHandle Which user the size should be retrieved for
* @param observer a callback to use to notify when the asynchronous
* retrieval of information is complete.
*/
- void getPackageSizeInfo(in String packageName, IPackageStatsObserver observer);
+ void getPackageSizeInfo(in String packageName, int userHandle, IPackageStatsObserver observer);
/**
* Get a list of shared libraries that are available on the
@@ -362,6 +364,11 @@ interface IPackageManager {
int flags, in String installerPackageName, in Uri verificationURI,
in ManifestDigest manifestDigest, in ContainerEncryptionParams encryptionParams);
+ void installPackageWithVerificationAndEncryption(in Uri packageURI,
+ in IPackageInstallObserver observer, int flags, in String installerPackageName,
+ in VerificationParams verificationParams,
+ in ContainerEncryptionParams encryptionParams);
+
void verifyPendingInstall(int id, int verificationCode);
VerifierDeviceIdentity getVerifierDeviceIdentity();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index f287ca5..0461dd1 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -28,6 +28,7 @@ import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Environment;
+import android.os.UserHandle;
import android.util.AndroidException;
import android.util.DisplayMetrics;
@@ -2227,6 +2228,37 @@ public abstract class PackageManager {
ContainerEncryptionParams encryptionParams);
/**
+ * Similar to
+ * {@link #installPackage(Uri, IPackageInstallObserver, int, String)} but
+ * with an extra verification information provided.
+ *
+ * @param packageURI The location of the package file to install. This can
+ * be a 'file:' or a 'content:' URI.
+ * @param observer An observer callback to get notified when the package
+ * installation is complete.
+ * {@link IPackageInstallObserver#packageInstalled(String, int)}
+ * will be called when that happens. observer may be null to
+ * indicate that no callback is desired.
+ * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
+ * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}
+ * .
+ * @param installerPackageName Optional package name of the application that
+ * is performing the installation. This identifies which market
+ * the package came from.
+ * @param verificationParams an object that holds signal information to
+ * assist verification. May be {@code null}.
+ * @param encryptionParams if the package to be installed is encrypted,
+ * these parameters describing the encryption and authentication
+ * used. May be {@code null}.
+ *
+ * @hide
+ */
+ public abstract void installPackageWithVerificationAndEncryption(Uri packageURI,
+ IPackageInstallObserver observer, int flags, String installerPackageName,
+ VerificationParams verificationParams,
+ ContainerEncryptionParams encryptionParams);
+
+ /**
* Allows a package listening to the
* {@link Intent#ACTION_PACKAGE_NEEDS_VERIFICATION package verification
* broadcast} to respond to the package manager. The response must include
@@ -2376,6 +2408,7 @@ public abstract class PackageManager {
* should have the {@link android.Manifest.permission#GET_PACKAGE_SIZE} permission.
*
* @param packageName The name of the package whose size information is to be retrieved
+ * @param userHandle The user whose size information should be retrieved.
* @param observer An observer callback to get notified when the operation
* is complete.
* {@link android.content.pm.IPackageStatsObserver#onGetStatsCompleted(PackageStats, boolean)}
@@ -2386,10 +2419,20 @@ public abstract class PackageManager {
*
* @hide
*/
- public abstract void getPackageSizeInfo(String packageName,
+ public abstract void getPackageSizeInfo(String packageName, int userHandle,
IPackageStatsObserver observer);
/**
+ * Like {@link #getPackageSizeInfo(String, int, IPackageStatsObserver)}, but
+ * returns the size for the calling user.
+ *
+ * @hide
+ */
+ public void getPackageSizeInfo(String packageName, IPackageStatsObserver observer) {
+ getPackageSizeInfo(packageName, UserHandle.myUserId(), observer);
+ }
+
+ /**
* @deprecated This function no longer does anything; it was an old
* approach to managing preferred activities, which has been superceeded
* (and conflicts with) the modern activity-based preferences.
@@ -2460,6 +2503,17 @@ public abstract class PackageManager {
ComponentName[] set, ComponentName activity);
/**
+ * Same as {@link #addPreferredActivity(IntentFilter, int,
+ ComponentName[], ComponentName)}, but with a specific userId to apply the preference
+ to.
+ * @hide
+ */
+ public void addPreferredActivity(IntentFilter filter, int match,
+ ComponentName[] set, ComponentName activity, int userId) {
+ throw new RuntimeException("Not implemented. Must override in a subclass.");
+ }
+
+ /**
* @deprecated This is a protected API that should not have been available
* to third party applications. It is the platform's responsibility for
* assigning preferred activities and this can not be directly modified.
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
index 1205da7..cb9039b 100644
--- a/core/java/android/content/pm/PackageStats.java
+++ b/core/java/android/content/pm/PackageStats.java
@@ -18,6 +18,7 @@ package android.content.pm;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
/**
* implementation of PackageStats associated with a
@@ -27,6 +28,9 @@ public class PackageStats implements Parcelable {
/** Name of the package to which this stats applies. */
public String packageName;
+ /** @hide */
+ public int userHandle;
+
/** Size of the code (e.g., APK) */
public long codeSize;
@@ -78,33 +82,58 @@ public class PackageStats implements Parcelable {
public String toString() {
final StringBuilder sb = new StringBuilder("PackageStats{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
- sb.append(" packageName=");
+ sb.append(" ");
sb.append(packageName);
- sb.append(",codeSize=");
- sb.append(codeSize);
- sb.append(",dataSize=");
- sb.append(dataSize);
- sb.append(",cacheSize=");
- sb.append(cacheSize);
- sb.append(",externalCodeSize=");
- sb.append(externalCodeSize);
- sb.append(",externalDataSize=");
- sb.append(externalDataSize);
- sb.append(",externalCacheSize=");
- sb.append(externalCacheSize);
- sb.append(",externalMediaSize=");
- sb.append(externalMediaSize);
- sb.append(",externalObbSize=");
- sb.append(externalObbSize);
+ if (codeSize != 0) {
+ sb.append(" code=");
+ sb.append(codeSize);
+ }
+ if (dataSize != 0) {
+ sb.append(" data=");
+ sb.append(dataSize);
+ }
+ if (cacheSize != 0) {
+ sb.append(" cache=");
+ sb.append(cacheSize);
+ }
+ if (externalCodeSize != 0) {
+ sb.append(" extCode=");
+ sb.append(externalCodeSize);
+ }
+ if (externalDataSize != 0) {
+ sb.append(" extData=");
+ sb.append(externalDataSize);
+ }
+ if (externalCacheSize != 0) {
+ sb.append(" extCache=");
+ sb.append(externalCacheSize);
+ }
+ if (externalMediaSize != 0) {
+ sb.append(" media=");
+ sb.append(externalMediaSize);
+ }
+ if (externalObbSize != 0) {
+ sb.append(" obb=");
+ sb.append(externalObbSize);
+ }
+ sb.append("}");
return sb.toString();
}
public PackageStats(String pkgName) {
packageName = pkgName;
+ userHandle = UserHandle.myUserId();
+ }
+
+ /** @hide */
+ public PackageStats(String pkgName, int userHandle) {
+ this.packageName = pkgName;
+ this.userHandle = userHandle;
}
public PackageStats(Parcel source) {
packageName = source.readString();
+ userHandle = source.readInt();
codeSize = source.readLong();
dataSize = source.readLong();
cacheSize = source.readLong();
@@ -117,6 +146,7 @@ public class PackageStats implements Parcelable {
public PackageStats(PackageStats pStats) {
packageName = pStats.packageName;
+ userHandle = pStats.userHandle;
codeSize = pStats.codeSize;
dataSize = pStats.dataSize;
cacheSize = pStats.cacheSize;
@@ -133,6 +163,7 @@ public class PackageStats implements Parcelable {
public void writeToParcel(Parcel dest, int parcelableFlags){
dest.writeString(packageName);
+ dest.writeInt(userHandle);
dest.writeLong(codeSize);
dest.writeLong(dataSize);
dest.writeLong(cacheSize);
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 638e273..060a235 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -53,6 +53,7 @@ public class UserInfo implements Parcelable {
public static final int FLAG_RESTRICTED = 0x00000008;
public int id;
+ public int serialNumber;
public String name;
public String iconPath;
public int flags;
@@ -88,6 +89,7 @@ public class UserInfo implements Parcelable {
iconPath = orig.iconPath;
id = orig.id;
flags = orig.flags;
+ serialNumber = orig.serialNumber;
}
@Override
@@ -104,6 +106,7 @@ public class UserInfo implements Parcelable {
dest.writeString(name);
dest.writeString(iconPath);
dest.writeInt(flags);
+ dest.writeInt(serialNumber);
}
public static final Parcelable.Creator<UserInfo> CREATOR
@@ -121,5 +124,6 @@ public class UserInfo implements Parcelable {
name = source.readString();
iconPath = source.readString();
flags = source.readInt();
+ serialNumber = source.readInt();
}
}
diff --git a/core/java/android/content/pm/VerificationParams.aidl b/core/java/android/content/pm/VerificationParams.aidl
new file mode 100644
index 0000000..5bb7f69
--- /dev/null
+++ b/core/java/android/content/pm/VerificationParams.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+parcelable VerificationParams;
diff --git a/core/java/android/content/pm/VerificationParams.java b/core/java/android/content/pm/VerificationParams.java
new file mode 100644
index 0000000..9bec87e
--- /dev/null
+++ b/core/java/android/content/pm/VerificationParams.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.content.pm.ManifestDigest;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents verification parameters used to verify packages to be installed.
+ *
+ * @hide
+ */
+public class VerificationParams implements Parcelable {
+ /** What we print out first when toString() is called. */
+ private static final String TO_STRING_PREFIX = "VerificationParams{";
+
+ /** The location of the supplementary verification file. */
+ private final Uri mVerificationURI;
+
+ /** URI referencing where the package was downloaded from. */
+ private final Uri mOriginatingURI;
+
+ /** HTTP referrer URI associated with the originatingURI. */
+ private final Uri mReferrer;
+
+ /**
+ * An object that holds the digest of the package which can be used to
+ * verify ownership.
+ */
+ private final ManifestDigest mManifestDigest;
+
+ /**
+ * Creates verification specifications for installing with application verification.
+ *
+ * @param verificationURI The location of the supplementary verification
+ * file. This can be a 'file:' or a 'content:' URI. May be {@code null}.
+ * @param originatingURI URI referencing where the package was downloaded
+ * from. May be {@code null}.
+ * @param referrer HTTP referrer URI associated with the originatingURI.
+ * May be {@code null}.
+ * @param manifestDigest an object that holds the digest of the package
+ * which can be used to verify ownership. May be {@code null}.
+ */
+ public VerificationParams(Uri verificationURI, Uri originatingURI, Uri referrer,
+ ManifestDigest manifestDigest) {
+ mVerificationURI = verificationURI;
+ mOriginatingURI = originatingURI;
+ mReferrer = referrer;
+ mManifestDigest = manifestDigest;
+ }
+
+ public Uri getVerificationURI() {
+ return mVerificationURI;
+ }
+
+ public Uri getOriginatingURI() {
+ return mOriginatingURI;
+ }
+
+ public Uri getReferrer() {
+ return mReferrer;
+ }
+
+ public ManifestDigest getManifestDigest() {
+ return mManifestDigest;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof VerificationParams)) {
+ return false;
+ }
+
+ final VerificationParams other = (VerificationParams) o;
+
+ if (mVerificationURI == null && other.mVerificationURI != null) {
+ return false;
+ }
+ if (!mVerificationURI.equals(other.mVerificationURI)) {
+ return false;
+ }
+
+ if (mOriginatingURI == null && other.mOriginatingURI != null) {
+ return false;
+ }
+ if (!mOriginatingURI.equals(other.mOriginatingURI)) {
+ return false;
+ }
+
+ if (mReferrer == null && other.mReferrer != null) {
+ return false;
+ }
+ if (!mReferrer.equals(other.mReferrer)) {
+ return false;
+ }
+
+ if (mManifestDigest == null && other.mManifestDigest != null) {
+ return false;
+ }
+ if (mManifestDigest != null && !mManifestDigest.equals(other.mManifestDigest)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+
+ hash += 5 * (mVerificationURI==null?1:mVerificationURI.hashCode());
+ hash += 7 * (mOriginatingURI==null?1:mOriginatingURI.hashCode());
+ hash += 11 * (mReferrer==null?1:mReferrer.hashCode());
+ hash += 13 * (mManifestDigest==null?1:mManifestDigest.hashCode());
+
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder(TO_STRING_PREFIX);
+
+ sb.append("mVerificationURI=");
+ sb.append(mVerificationURI.toString());
+ sb.append(",mOriginatingURI=");
+ sb.append(mOriginatingURI.toString());
+ sb.append(",mReferrer=");
+ sb.append(mReferrer.toString());
+ sb.append(",mManifestDigest=");
+ sb.append(mManifestDigest.toString());
+ sb.append('}');
+
+ return sb.toString();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mVerificationURI, 0);
+ dest.writeParcelable(mOriginatingURI, 0);
+ dest.writeParcelable(mReferrer, 0);
+ dest.writeParcelable(mManifestDigest, 0);
+ }
+
+
+ private VerificationParams(Parcel source) {
+ mVerificationURI = source.readParcelable(Uri.class.getClassLoader());
+ mOriginatingURI = source.readParcelable(Uri.class.getClassLoader());
+ mReferrer = source.readParcelable(Uri.class.getClassLoader());
+ mManifestDigest = source.readParcelable(ManifestDigest.class.getClassLoader());
+ }
+
+ public static final Parcelable.Creator<VerificationParams> CREATOR =
+ new Parcelable.Creator<VerificationParams>() {
+ public VerificationParams createFromParcel(Parcel source) {
+ return new VerificationParams(source);
+ }
+
+ public VerificationParams[] newArray(int size) {
+ return new VerificationParams[size];
+ }
+ };
+}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 640044b..a73115c 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -17,12 +17,20 @@
package android.hardware.display;
import android.content.Context;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
+import android.util.SparseArray;
+import android.view.CompatibilityInfoHolder;
+import android.view.Display;
import android.view.DisplayInfo;
+import java.util.ArrayList;
+
/**
* Manages the properties, media routing and power state of attached displays.
* <p>
@@ -34,25 +42,41 @@ import android.view.DisplayInfo;
*/
public final class DisplayManager {
private static final String TAG = "DisplayManager";
+ private static final boolean DEBUG = false;
+
+ private static final int MSG_DISPLAY_ADDED = 1;
+ private static final int MSG_DISPLAY_REMOVED = 2;
+ private static final int MSG_DISPLAY_CHANGED = 3;
private static DisplayManager sInstance;
private final IDisplayManager mDm;
+ // Guarded by mDisplayLock
+ private final Object mDisplayLock = new Object();
+ private final ArrayList<DisplayListenerDelegate> mDisplayListeners =
+ new ArrayList<DisplayListenerDelegate>();
+
+
private DisplayManager(IDisplayManager dm) {
mDm = dm;
}
/**
* Gets an instance of the display manager.
- * @return The display manager instance.
+ *
+ * @return The display manager instance, may be null early in system startup
+ * before the display manager has been fully initialized.
+ *
* @hide
*/
public static DisplayManager getInstance() {
synchronized (DisplayManager.class) {
if (sInstance == null) {
IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE);
- sInstance = new DisplayManager(IDisplayManager.Stub.asInterface(b));
+ if (b != null) {
+ sInstance = new DisplayManager(IDisplayManager.Stub.asInterface(b));
+ }
}
return sInstance;
}
@@ -74,4 +98,161 @@ public final class DisplayManager {
return false;
}
}
+
+ /**
+ * Gets information about a logical display.
+ *
+ * The display metrics may be adjusted to provide compatibility
+ * for legacy applications.
+ *
+ * @param displayId The logical display id.
+ * @param applicationContext The application context from which to obtain
+ * compatible metrics.
+ * @return The display object.
+ */
+ public Display getDisplay(int displayId, Context applicationContext) {
+ if (applicationContext == null) {
+ throw new IllegalArgumentException("applicationContext must not be null");
+ }
+
+ CompatibilityInfoHolder cih = null;
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ cih = applicationContext.getCompatibilityInfo();
+ }
+ return getCompatibleDisplay(displayId, cih);
+ }
+
+ /**
+ * Gets information about a logical display.
+ *
+ * The display metrics may be adjusted to provide compatibility
+ * for legacy applications.
+ *
+ * @param displayId The logical display id.
+ * @param cih The compatibility info, or null if none is required.
+ * @return The display object.
+ *
+ * @hide
+ */
+ public Display getCompatibleDisplay(int displayId, CompatibilityInfoHolder cih) {
+ return new Display(displayId, cih);
+ }
+
+ /**
+ * Gets information about a logical display without applying any compatibility metrics.
+ *
+ * @param displayId The logical display id.
+ * @return The display object.
+ *
+ * @hide
+ */
+ public Display getRealDisplay(int displayId) {
+ return getCompatibleDisplay(displayId, null);
+ }
+
+ /**
+ * Registers an display listener to receive notifications about when
+ * displays are added, removed or changed.
+ *
+ * @param listener The listener to register.
+ * @param handler The handler on which the listener should be invoked, or null
+ * if the listener should be invoked on the calling thread's looper.
+ *
+ * @see #unregisterDisplayListener
+ */
+ public void registerDisplayListener(DisplayListener listener, Handler handler) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+
+ synchronized (mDisplayLock) {
+ int index = findDisplayListenerLocked(listener);
+ if (index < 0) {
+ mDisplayListeners.add(new DisplayListenerDelegate(listener, handler));
+ }
+ }
+ }
+
+ /**
+ * Unregisters an input device listener.
+ *
+ * @param listener The listener to unregister.
+ *
+ * @see #registerDisplayListener
+ */
+ public void unregisterDisplayListener(DisplayListener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+
+ synchronized (mDisplayLock) {
+ int index = findDisplayListenerLocked(listener);
+ if (index >= 0) {
+ DisplayListenerDelegate d = mDisplayListeners.get(index);
+ d.removeCallbacksAndMessages(null);
+ mDisplayListeners.remove(index);
+ }
+ }
+ }
+
+ private int findDisplayListenerLocked(DisplayListener listener) {
+ final int numListeners = mDisplayListeners.size();
+ for (int i = 0; i < numListeners; i++) {
+ if (mDisplayListeners.get(i).mListener == listener) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Listens for changes in available display devices.
+ */
+ public interface DisplayListener {
+ /**
+ * Called whenever a logical display has been added to the system.
+ * Use {@link DisplayManager#getDisplay} to get more information about the display.
+ *
+ * @param displayId The id of the logical display that was added.
+ */
+ void onDisplayAdded(int displayId);
+
+ /**
+ * Called whenever a logical display has been removed from the system.
+ *
+ * @param displayId The id of the logical display that was removed.
+ */
+ void onDisplayRemoved(int displayId);
+
+ /**
+ * Called whenever the properties of a logical display have changed.
+ *
+ * @param displayId The id of the logical display that changed.
+ */
+ void onDisplayChanged(int displayId);
+ }
+
+ private static final class DisplayListenerDelegate extends Handler {
+ public final DisplayListener mListener;
+
+ public DisplayListenerDelegate(DisplayListener listener, Handler handler) {
+ super(handler != null ? handler.getLooper() : Looper.myLooper());
+ mListener = listener;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_DISPLAY_ADDED:
+ mListener.onDisplayAdded(msg.arg1);
+ break;
+ case MSG_DISPLAY_REMOVED:
+ mListener.onDisplayRemoved(msg.arg1);
+ break;
+ case MSG_DISPLAY_CHANGED:
+ mListener.onDisplayChanged(msg.arg1);
+ break;
+ }
+ }
+ }
}
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 9bab797..98bd4f5 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -87,4 +87,12 @@ interface IUsbManager
/* Sets the file path for USB mass storage backing file. */
void setMassStorageBackingFile(String path);
+
+ /* Allow USB debugging from the attached host. If alwaysAllow is true, add the
+ * the public key to list of host keys that the user has approved.
+ */
+ void allowUsbDebugging(boolean alwaysAllow, String publicKey);
+
+ /* Deny USB debugging from the attached host */
+ void denyUsbDebugging();
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index a9de289..d5b9edc 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -39,7 +39,6 @@ import android.text.method.MovementMethod;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
-import android.view.Display;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -630,7 +629,7 @@ public class InputMethodService extends AbstractInputMethodService {
if (mWindow != null) {
throw new IllegalStateException("Must be called before onCreate()");
}
- if (ActivityManager.isHighEndGfx(new Display(Display.DEFAULT_DISPLAY, null))) {
+ if (ActivityManager.isHighEndGfx()) {
mHardwareAccelerated = true;
return true;
}
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 00438a1..d59fa6a 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -184,8 +184,17 @@ public class MobileDataStateTracker implements NetworkStateTracker {
if (!TextUtils.equals(apnType, mApnType)) {
return;
}
- mNetworkInfo.setSubtype(TelephonyManager.getDefault().getNetworkType(),
- TelephonyManager.getDefault().getNetworkTypeName());
+
+ int oldSubtype = mNetworkInfo.getSubtype();
+ int newSubType = TelephonyManager.getDefault().getNetworkType();
+ String subTypeName = TelephonyManager.getDefault().getNetworkTypeName();
+ mNetworkInfo.setSubtype(newSubType, subTypeName);
+ if (newSubType != oldSubtype && mNetworkInfo.isConnected()) {
+ Message msg = mTarget.obtainMessage(EVENT_NETWORK_SUBTYPE_CHANGED,
+ oldSubtype, 0, mNetworkInfo);
+ msg.sendToTarget();
+ }
+
PhoneConstants.DataState state = Enum.valueOf(PhoneConstants.DataState.class,
intent.getStringExtra(PhoneConstants.STATE_KEY));
String reason = intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY);
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index 313c174..eae89f1 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -63,6 +63,12 @@ public interface NetworkStateTracker {
public static final int EVENT_RESTORE_DEFAULT_NETWORK = 6;
/**
+ * msg.what = EVENT_NETWORK_SUBTYPE_CHANGED
+ * msg.obj = NetworkInfo object
+ */
+ public static final int EVENT_NETWORK_SUBTYPE_CHANGED = 7;
+
+ /**
* -------------------------------------------------------------
* Control Interface
* -------------------------------------------------------------
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index c62715b..7b16f4d 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -115,4 +115,6 @@ public class BatteryManager {
public static final int BATTERY_PLUGGED_AC = 1;
/** Power source is a USB port. */
public static final int BATTERY_PLUGGED_USB = 2;
+ /** Power source is wireless. */
+ public static final int BATTERY_PLUGGED_WIRELESS = 4;
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index fcc0ae4..54f2fe3 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2071,6 +2071,9 @@ public abstract class BatteryStats implements Parcelable {
case BatteryManager.BATTERY_PLUGGED_USB:
pw.print("usb");
break;
+ case BatteryManager.BATTERY_PLUGGED_WIRELESS:
+ pw.print("wireless");
+ break;
default:
pw.print(oldPlug);
break;
diff --git a/core/java/android/os/FactoryTest.java b/core/java/android/os/FactoryTest.java
new file mode 100644
index 0000000..ec99697
--- /dev/null
+++ b/core/java/android/os/FactoryTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * Provides support for in-place factory test functions.
+ *
+ * This class provides a few properties that alter the normal operation of the system
+ * during factory testing.
+ *
+ * {@hide}
+ */
+public final class FactoryTest {
+ /**
+ * When true, long-press on power should immediately cause the device to
+ * shut down, without prompting the user.
+ */
+ public static boolean isLongPressOnPowerOffEnabled() {
+ return SystemProperties.getInt("factory.long_press_power_off", 0) != 0;
+ }
+}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 6c1445d..0941d71 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -28,9 +28,6 @@ import java.util.regex.Pattern;
import java.util.zip.CRC32;
import java.util.zip.CheckedInputStream;
-import libcore.io.Os;
-import libcore.io.StructStat;
-
/**
* Tools for managing files. Not for public consumption.
* @hide
@@ -50,60 +47,12 @@ public class FileUtils {
public static final int S_IROTH = 00004;
public static final int S_IWOTH = 00002;
public static final int S_IXOTH = 00001;
-
-
- /**
- * File status information. This class maps directly to the POSIX stat structure.
- * @deprecated use {@link StructStat} instead.
- * @hide
- */
- @Deprecated
- public static final class FileStatus {
- public int dev;
- public int ino;
- public int mode;
- public int nlink;
- public int uid;
- public int gid;
- public int rdev;
- public long size;
- public int blksize;
- public long blocks;
- public long atime;
- public long mtime;
- public long ctime;
- }
-
- /**
- * Get the status for the given path. This is equivalent to the POSIX stat(2) system call.
- * @param path The path of the file to be stat'd.
- * @param status Optional argument to fill in. It will only fill in the status if the file
- * exists.
- * @return true if the file exists and false if it does not exist. If you do not have
- * permission to stat the file, then this method will return false.
- * @deprecated use {@link Os#stat(String)} instead.
- */
- @Deprecated
- public static boolean getFileStatus(String path, FileStatus status) {
- StrictMode.noteDiskRead();
- return getFileStatusNative(path, status);
- }
-
- private static native boolean getFileStatusNative(String path, FileStatus status);
/** Regular expression for safe filenames: no spaces or metacharacters */
private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+");
public static native int setPermissions(String file, int mode, int uid, int gid);
- /**
- * @deprecated use {@link Os#stat(String)} instead.
- */
- @Deprecated
- public static native int getPermissions(String file, int[] outPermissions);
-
- public static native int setUMask(int mask);
-
/** returns the FAT file system volume ID for the volume mounted
* at the given mount point, or -1 for failure
* @param mountPoint point for FAT volume
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index cb1b962..c7a8493 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -33,4 +33,6 @@ interface IUserManager {
void setGuestEnabled(boolean enable);
boolean isGuestEnabled();
void wipeUser(int userHandle);
+ int getUserSerialNumber(int userHandle);
+ int getUserHandle(int userSerialNumber);
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 5118f1a..3513bdc 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -376,12 +376,13 @@ public class Process {
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
- int debugFlags, int targetSdkVersion,
+ int debugFlags, int mountExternal,
+ int targetSdkVersion,
String seInfo,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
- debugFlags, targetSdkVersion, seInfo, zygoteArgs);
+ debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
@@ -553,7 +554,8 @@ public class Process {
final String niceName,
final int uid, final int gid,
final int[] gids,
- int debugFlags, int targetSdkVersion,
+ int debugFlags, int mountExternal,
+ int targetSdkVersion,
String seInfo,
String[] extraArgs)
throws ZygoteStartFailedEx {
@@ -580,6 +582,11 @@ public class Process {
if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
argsForZygote.add("--enable-assert");
}
+ if (mountExternal == Zygote.MOUNT_EXTERNAL_SINGLEUSER) {
+ argsForZygote.add("--mount-external-singleuser");
+ } else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) {
+ argsForZygote.add("--mount-external-multiuser");
+ }
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
//TODO optionally enable debuger
@@ -648,13 +655,13 @@ public class Process {
public static final native int myUid();
/**
- * Returns the identifier of this process's user handle. This is the
+ * Returns this process's user handle. This is the
* user the process is running under. It is distinct from
* {@link #myUid()} in that a particular user will have multiple
* distinct apps running under it each with their own uid.
*/
- public static final int myUserHandle() {
- return UserHandle.getUserId(myUid());
+ public static final UserHandle myUserHandle() {
+ return new UserHandle(UserHandle.getUserId(myUid()));
}
/**
diff --git a/core/java/android/os/SELinux.java b/core/java/android/os/SELinux.java
index 90cfa37..c05a974 100644
--- a/core/java/android/os/SELinux.java
+++ b/core/java/android/os/SELinux.java
@@ -1,5 +1,25 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package android.os;
+import android.util.Slog;
+
+import java.io.IOException;
+import java.io.File;
import java.io.FileDescriptor;
/**
@@ -9,6 +29,8 @@ import java.io.FileDescriptor;
*/
public class SELinux {
+ private static final String TAG = "SELinux";
+
/**
* Determine whether SELinux is disabled or enabled.
* @return a boolean indicating whether SELinux is enabled.
@@ -102,4 +124,53 @@ public class SELinux {
* @return a boolean indicating whether permission was granted.
*/
public static final native boolean checkSELinuxAccess(String scon, String tcon, String tclass, String perm);
+
+ /**
+ * Restores a file to its default SELinux security context.
+ * If the system is not compiled with SELinux, then {@code true}
+ * is automatically returned.
+ * If SELinux is compiled in, but disabled, then {@code true} is
+ * returned.
+ *
+ * @param pathname The pathname of the file to be relabeled.
+ * @return a boolean indicating whether the relabeling succeeded.
+ * @exception NullPointerException if the pathname is a null object.
+ */
+ public static boolean restorecon(String pathname) throws NullPointerException {
+ if (pathname == null) { throw new NullPointerException(); }
+ return native_restorecon(pathname);
+ }
+
+ /**
+ * Restores a file to its default SELinux security context.
+ * If the system is not compiled with SELinux, then {@code true}
+ * is automatically returned.
+ * If SELinux is compiled in, but disabled, then {@code true} is
+ * returned.
+ *
+ * @param pathname The pathname of the file to be relabeled.
+ * @return a boolean indicating whether the relabeling succeeded.
+ */
+ private static native boolean native_restorecon(String pathname);
+
+ /**
+ * Restores a file to its default SELinux security context.
+ * If the system is not compiled with SELinux, then {@code true}
+ * is automatically returned.
+ * If SELinux is compiled in, but disabled, then {@code true} is
+ * returned.
+ *
+ * @param file The File object representing the path to be relabeled.
+ * @return a boolean indicating whether the relabeling succeeded.
+ * @exception NullPointerException if the file is a null object.
+ */
+ public static boolean restorecon(File file) throws NullPointerException {
+ try {
+ return native_restorecon(file.getCanonicalPath());
+ } catch (IOException e) {
+ Slog.e(TAG, "Error getting canonical path. Restorecon failed for " +
+ file.getPath(), e);
+ return false;
+ }
+ }
}
diff --git a/core/java/android/os/StatFs.java b/core/java/android/os/StatFs.java
index 912bfdf..ca7fdba 100644
--- a/core/java/android/os/StatFs.java
+++ b/core/java/android/os/StatFs.java
@@ -16,59 +16,77 @@
package android.os;
+import libcore.io.ErrnoException;
+import libcore.io.Libcore;
+import libcore.io.StructStatFs;
+
/**
- * Retrieve overall information about the space on a filesystem. This is a
- * Wrapper for Unix statfs().
+ * Retrieve overall information about the space on a filesystem. This is a
+ * wrapper for Unix statfs().
*/
public class StatFs {
+ private StructStatFs mStat;
+
/**
- * Construct a new StatFs for looking at the stats of the
- * filesystem at <var>path</var>. Upon construction, the stat of
- * the file system will be performed, and the values retrieved available
- * from the methods on this class.
- *
- * @param path A path in the desired file system to state.
+ * Construct a new StatFs for looking at the stats of the filesystem at
+ * {@code path}. Upon construction, the stat of the file system will be
+ * performed, and the values retrieved available from the methods on this
+ * class.
+ *
+ * @param path path in the desired file system to stat.
*/
- public StatFs(String path) { native_setup(path); }
-
+ public StatFs(String path) {
+ mStat = doStat(path);
+ }
+
+ private static StructStatFs doStat(String path) {
+ try {
+ return Libcore.os.statfs(path);
+ } catch (ErrnoException e) {
+ throw new IllegalArgumentException("Invalid path: " + path, e);
+ }
+ }
+
/**
- * Perform a restat of the file system referenced by this object. This
- * is the same as re-constructing the object with the same file system
- * path, and the new stat values are available upon return.
+ * Perform a restat of the file system referenced by this object. This is
+ * the same as re-constructing the object with the same file system path,
+ * and the new stat values are available upon return.
*/
- public void restat(String path) { native_restat(path); }
-
- @Override
- protected void finalize() { native_finalize(); }
+ public void restat(String path) {
+ mStat = doStat(path);
+ }
/**
- * The size, in bytes, of a block on the file system. This corresponds
- * to the Unix statfs.f_bsize field.
+ * The size, in bytes, of a block on the file system. This corresponds to
+ * the Unix {@code statfs.f_bsize} field.
*/
- public native int getBlockSize();
+ public int getBlockSize() {
+ return (int) mStat.f_bsize;
+ }
/**
- * The total number of blocks on the file system. This corresponds
- * to the Unix statfs.f_blocks field.
+ * The total number of blocks on the file system. This corresponds to the
+ * Unix {@code statfs.f_blocks} field.
*/
- public native int getBlockCount();
+ public int getBlockCount() {
+ return (int) mStat.f_blocks;
+ }
/**
* The total number of blocks that are free on the file system, including
- * reserved blocks (that are not available to normal applications). This
- * corresponds to the Unix statfs.f_bfree field. Most applications will
- * want to use {@link #getAvailableBlocks()} instead.
+ * reserved blocks (that are not available to normal applications). This
+ * corresponds to the Unix {@code statfs.f_bfree} field. Most applications
+ * will want to use {@link #getAvailableBlocks()} instead.
*/
- public native int getFreeBlocks();
+ public int getFreeBlocks() {
+ return (int) mStat.f_bfree;
+ }
/**
* The number of blocks that are free on the file system and available to
- * applications. This corresponds to the Unix statfs.f_bavail field.
+ * applications. This corresponds to the Unix {@code statfs.f_bavail} field.
*/
- public native int getAvailableBlocks();
-
- private int mNativeContext;
- private native void native_restat(String path);
- private native void native_setup(String path);
- private native void native_finalize();
+ public int getAvailableBlocks() {
+ return (int) mStat.f_bavail;
+ }
}
diff --git a/core/java/android/os/UEventObserver.java b/core/java/android/os/UEventObserver.java
index b924e84..d33382b 100644
--- a/core/java/android/os/UEventObserver.java
+++ b/core/java/android/os/UEventObserver.java
@@ -37,14 +37,79 @@ import java.util.HashMap;
* @hide
*/
public abstract class UEventObserver {
- private static final String TAG = UEventObserver.class.getSimpleName();
+ private static UEventThread sThread;
+
+ private static native void native_setup();
+ private static native int next_event(byte[] buffer);
+
+ public UEventObserver() {
+ }
+
+ protected void finalize() throws Throwable {
+ try {
+ stopObserving();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private static UEventThread getThread() {
+ synchronized (UEventObserver.class) {
+ if (sThread == null) {
+ sThread = new UEventThread();
+ sThread.start();
+ }
+ return sThread;
+ }
+ }
+
+ private static UEventThread peekThread() {
+ synchronized (UEventObserver.class) {
+ return sThread;
+ }
+ }
+
+ /**
+ * Begin observation of UEvent's.<p>
+ * This method will cause the UEvent thread to start if this is the first
+ * invocation of startObserving in this process.<p>
+ * Once called, the UEvent thread will call onUEvent() when an incoming
+ * UEvent matches the specified string.<p>
+ * This method can be called multiple times to register multiple matches.
+ * Only one call to stopObserving is required even with multiple registered
+ * matches.
+ * @param match A substring of the UEvent to match. Use "" to match all
+ * UEvent's
+ */
+ public final void startObserving(String match) {
+ final UEventThread t = getThread();
+ t.addObserver(match, this);
+ }
+
+ /**
+ * End observation of UEvent's.<p>
+ * This process's UEvent thread will never call onUEvent() on this
+ * UEventObserver after this call. Repeated calls have no effect.
+ */
+ public final void stopObserving() {
+ final UEventThread t = getThread();
+ if (t != null) {
+ t.removeObserver(this);
+ }
+ }
+
+ /**
+ * Subclasses of UEventObserver should override this method to handle
+ * UEvents.
+ */
+ public abstract void onUEvent(UEvent event);
/**
* Representation of a UEvent.
*/
- static public class UEvent {
+ public static final class UEvent {
// collection of key=value pairs parsed from the uevent message
- public HashMap<String,String> mMap = new HashMap<String,String>();
+ private final HashMap<String,String> mMap = new HashMap<String,String>();
public UEvent(String message) {
int offset = 0;
@@ -79,20 +144,20 @@ public abstract class UEventObserver {
}
}
- private static UEventThread sThread;
- private static boolean sThreadStarted = false;
-
- private static class UEventThread extends Thread {
+ private static final class UEventThread extends Thread {
/** Many to many mapping of string match to observer.
* Multimap would be better, but not available in android, so use
* an ArrayList where even elements are the String match and odd
* elements the corresponding UEventObserver observer */
- private ArrayList<Object> mObservers = new ArrayList<Object>();
-
- UEventThread() {
+ private final ArrayList<Object> mKeysAndObservers = new ArrayList<Object>();
+
+ private final ArrayList<UEventObserver> mTempObserversToSignal =
+ new ArrayList<UEventObserver>();
+
+ public UEventThread() {
super("UEventObserver");
}
-
+
public void run() {
native_setup();
@@ -101,91 +166,54 @@ public abstract class UEventObserver {
while (true) {
len = next_event(buffer);
if (len > 0) {
- String bufferStr = new String(buffer, 0, len); // easier to search a String
- synchronized (mObservers) {
- for (int i = 0; i < mObservers.size(); i += 2) {
- if (bufferStr.indexOf((String)mObservers.get(i)) != -1) {
- ((UEventObserver)mObservers.get(i+1))
- .onUEvent(new UEvent(bufferStr));
- }
- }
+ sendEvent(new String(buffer, 0, len));
+ }
+ }
+ }
+
+ private void sendEvent(String message) {
+ synchronized (mKeysAndObservers) {
+ final int N = mKeysAndObservers.size();
+ for (int i = 0; i < N; i += 2) {
+ final String key = (String)mKeysAndObservers.get(i);
+ if (message.indexOf(key) != -1) {
+ final UEventObserver observer =
+ (UEventObserver)mKeysAndObservers.get(i + 1);
+ mTempObserversToSignal.add(observer);
}
}
}
+
+ if (!mTempObserversToSignal.isEmpty()) {
+ final UEvent event = new UEvent(message);
+ final int N = mTempObserversToSignal.size();
+ for (int i = 0; i < N; i++) {
+ final UEventObserver observer = mTempObserversToSignal.get(i);
+ observer.onUEvent(event);
+ }
+ mTempObserversToSignal.clear();
+ }
}
+
public void addObserver(String match, UEventObserver observer) {
- synchronized(mObservers) {
- mObservers.add(match);
- mObservers.add(observer);
+ synchronized (mKeysAndObservers) {
+ mKeysAndObservers.add(match);
+ mKeysAndObservers.add(observer);
}
}
+
/** Removes every key/value pair where value=observer from mObservers */
public void removeObserver(UEventObserver observer) {
- synchronized(mObservers) {
- boolean found = true;
- while (found) {
- found = false;
- for (int i = 0; i < mObservers.size(); i += 2) {
- if (mObservers.get(i+1) == observer) {
- mObservers.remove(i+1);
- mObservers.remove(i);
- found = true;
- break;
- }
+ synchronized (mKeysAndObservers) {
+ for (int i = 0; i < mKeysAndObservers.size(); ) {
+ if (mKeysAndObservers.get(i + 1) == observer) {
+ mKeysAndObservers.remove(i + 1);
+ mKeysAndObservers.remove(i);
+ } else {
+ i += 2;
}
}
}
}
}
-
- private static native void native_setup();
- private static native int next_event(byte[] buffer);
-
- private static final synchronized void ensureThreadStarted() {
- if (sThreadStarted == false) {
- sThread = new UEventThread();
- sThread.start();
- sThreadStarted = true;
- }
- }
-
- /**
- * Begin observation of UEvent's.<p>
- * This method will cause the UEvent thread to start if this is the first
- * invocation of startObserving in this process.<p>
- * Once called, the UEvent thread will call onUEvent() when an incoming
- * UEvent matches the specified string.<p>
- * This method can be called multiple times to register multiple matches.
- * Only one call to stopObserving is required even with multiple registered
- * matches.
- * @param match A substring of the UEvent to match. Use "" to match all
- * UEvent's
- */
- public final synchronized void startObserving(String match) {
- ensureThreadStarted();
- sThread.addObserver(match, this);
- }
-
- /**
- * End observation of UEvent's.<p>
- * This process's UEvent thread will never call onUEvent() on this
- * UEventObserver after this call. Repeated calls have no effect.
- */
- public final synchronized void stopObserving() {
- sThread.removeObserver(this);
- }
-
- /**
- * Subclasses of UEventObserver should override this method to handle
- * UEvents.
- */
- public abstract void onUEvent(UEvent event);
-
- protected void finalize() throws Throwable {
- try {
- stopObserving();
- } finally {
- super.finalize();
- }
- }
}
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 577a8c6..0843d85 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -18,31 +18,33 @@ package android.os;
/**
* Representation of a user on the device.
- * @hide
*/
-public final class UserHandle {
+public final class UserHandle implements Parcelable {
/**
- * Range of IDs allocated for a user.
- *
- * @hide
+ * @hide Range of uids allocated for a user.
*/
public static final int PER_USER_RANGE = 100000;
- /** A user id to indicate all users on the device */
+ /** @hide A user id to indicate all users on the device */
public static final int USER_ALL = -1;
- /** A user id to indicate the currently active user */
+ /** @hide A user id to indicate the currently active user */
public static final int USER_CURRENT = -2;
- /** A user id constant to indicate the "owner" user of the device */
+ /** @hide An undefined user id */
+ public static final int USER_NULL = -10000;
+
+ /** @hide A user id constant to indicate the "owner" user of the device */
public static final int USER_OWNER = 0;
/**
- * Enable multi-user related side effects. Set this to false if there are problems with single
- * user usecases.
- * */
+ * @hide Enable multi-user related side effects. Set this to false if
+ * there are problems with single user use-cases.
+ */
public static final boolean MU_ENABLED = true;
+ final int mHandle;
+
/**
* Checks to see if the user id is the same for the two uids, i.e., they belong to the same
* user.
@@ -64,11 +66,13 @@ public final class UserHandle {
return getAppId(uid1) == getAppId(uid2);
}
+ /** @hide */
public static final boolean isIsolated(int uid) {
uid = getAppId(uid);
return uid >= Process.FIRST_ISOLATED_UID && uid <= Process.LAST_ISOLATED_UID;
}
+ /** @hide */
public static boolean isApp(int uid) {
if (uid > 0) {
uid = UserHandle.getAppId(uid);
@@ -90,6 +94,7 @@ public final class UserHandle {
}
}
+ /** @hide */
public static final int getCallingUserId() {
return getUserId(Binder.getCallingUid());
}
@@ -117,8 +122,107 @@ public final class UserHandle {
/**
* Returns the user id of the current process
* @return user id of the current process
+ * @hide
*/
public static final int myUserId() {
return getUserId(Process.myUid());
}
+
+ /** @hide */
+ public UserHandle(int h) {
+ mHandle = h;
+ }
+
+ /** @hide */
+ public int getIdentifier() {
+ return mHandle;
+ }
+
+ @Override
+ public String toString() {
+ return "UserHandle{" + mHandle + "}";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ try {
+ if (obj != null) {
+ UserHandle other = (UserHandle)obj;
+ return mHandle == other.mHandle;
+ }
+ } catch (ClassCastException e) {
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return mHandle;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mHandle);
+ }
+
+ /**
+ * Write a UserHandle to a Parcel, handling null pointers. Must be
+ * read with {@link #readFromParcel(Parcel)}.
+ *
+ * @param h The UserHandle to be written.
+ * @param out The Parcel in which the UserHandle will be placed.
+ *
+ * @see #readFromParcel(Parcel)
+ */
+ public static void writeToParcel(UserHandle h, Parcel out) {
+ if (h != null) {
+ h.writeToParcel(out, 0);
+ } else {
+ out.writeInt(USER_NULL);
+ }
+ }
+
+ /**
+ * Read a UserHandle from a Parcel that was previously written
+ * with {@link #writeToParcel(UserHandle, Parcel)}, returning either
+ * a null or new object as appropriate.
+ *
+ * @param in The Parcel from which to read the UserHandle
+ * @return Returns a new UserHandle matching the previously written
+ * object, or null if a null had been written.
+ *
+ * @see #writeToParcel(UserHandle, Parcel)
+ */
+ public static UserHandle readFromParcel(Parcel in) {
+ int h = in.readInt();
+ return h != USER_NULL ? new UserHandle(h) : null;
+ }
+
+ public static final Parcelable.Creator<UserHandle> CREATOR
+ = new Parcelable.Creator<UserHandle>() {
+ public UserHandle createFromParcel(Parcel in) {
+ return new UserHandle(in);
+ }
+
+ public UserHandle[] newArray(int size) {
+ return new UserHandle[size];
+ }
+ };
+
+ /**
+ * Instantiate a new UserHandle from the data in a Parcel that was
+ * previously written with {@link #writeToParcel(Parcel, int)}. Note that you
+ * must not use this with data written by
+ * {@link #writeToParcel(UserHandle, Parcel)} since it is not possible
+ * to handle a null UserHandle here.
+ *
+ * @param in The Parcel containing the previously written UserHandle,
+ * positioned at the location in the buffer where it was written.
+ */
+ public UserHandle(Parcel in) {
+ mHandle = in.readInt();
+ }
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 9c73392..0338ee7 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -51,7 +51,7 @@ public class UserManager {
* @hide
* */
public int getUserHandle() {
- return Process.myUserHandle();
+ return UserHandle.myUserId();
}
/**
@@ -209,4 +209,40 @@ public class UserManager {
public int getMaxSupportedUsers() {
return mContext.getResources().getInteger(R.integer.config_multiuserMaximumUsers);
}
+
+ /**
+ * Returns a serial number on this device for a given userHandle. User handles can be recycled
+ * when deleting and creating users, but serial numbers are not reused until the device is wiped.
+ * @param userHandle
+ * @return a serial number associated with that user, or -1 if the userHandle is not valid.
+ * @hide
+ */
+ public int getUserSerialNumber(int userHandle) {
+ try {
+ return mService.getUserSerialNumber(userHandle);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not get serial number for user " + userHandle);
+ }
+ return -1;
+ }
+
+ /**
+ * Returns a userHandle on this device for a given user serial number. User handles can be
+ * recycled when deleting and creating users, but serial numbers are not reused until the device
+ * is wiped.
+ * @param userSerialNumber
+ * @return the userHandle associated with that user serial number, or -1 if the serial number
+ * is not valid.
+ * @hide
+ */
+ public int getUserHandle(int userSerialNumber) {
+ try {
+ return mService.getUserHandle(userSerialNumber);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not get userHandle for user " + userSerialNumber);
+ }
+ return -1;
+ }
+
+
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6dbba46..28273f0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1147,6 +1147,7 @@ public final class Settings {
* <li>{@code 0} to never stay on while plugged in</li>
* <li>{@link BatteryManager#BATTERY_PLUGGED_AC} to stay on for AC charger</li>
* <li>{@link BatteryManager#BATTERY_PLUGGED_USB} to stay on for USB charger</li>
+ * <li>{@link BatteryManager#BATTERY_PLUGGED_WIRELESS} to stay on for wireless charger</li>
* </ul>
* These values can be OR-ed together.
*/
diff --git a/core/java/android/service/dreams/DreamManagerService.java b/core/java/android/service/dreams/DreamManagerService.java
index fc3f501..5d6b17e 100644
--- a/core/java/android/service/dreams/DreamManagerService.java
+++ b/core/java/android/service/dreams/DreamManagerService.java
@@ -18,6 +18,7 @@ import android.provider.Settings;
import android.util.Slog;
import android.view.IWindowManager;
import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
/**
*
@@ -44,8 +45,7 @@ public class DreamManagerService
public DreamManagerService(Context context) {
if (DEBUG) Slog.v(TAG, "DreamManagerService startup");
mContext = context;
- mIWindowManager = IWindowManager.Stub.asInterface(
- ServiceManager.getService(Context.WINDOW_SERVICE));
+ mIWindowManager = WindowManagerGlobal.getWindowManagerService();
}
private void checkPermission(String permission) {
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index b513915..efa8911 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -36,7 +36,6 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
-import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.util.LogPrinter;
@@ -51,9 +50,8 @@ import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewRootImpl;
import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -674,8 +672,8 @@ public abstract class WallpaperService extends Service {
}
}
- redrawNeeded |= creating
- || (relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0;
+ redrawNeeded |= creating || (relayoutResult
+ & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
if (forceReport || creating || surfaceCreating
|| formatChanged || sizeChanged) {
@@ -762,7 +760,7 @@ public abstract class WallpaperService extends Service {
mWindowToken = wrapper.mWindowToken;
mSurfaceHolder.setSizeFromLayout();
mInitializing = true;
- mSession = ViewRootImpl.getWindowSession(getMainLooper());
+ mSession = WindowManagerGlobal.getWindowSession(getMainLooper());
mWindow.setSession(mSession);
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 7a174af..5e367cb 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -1282,6 +1282,7 @@ public class TextToSpeech {
}
};
+ @Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "Connected to " + name);
synchronized(mStartLock) {
@@ -1305,6 +1306,7 @@ public class TextToSpeech {
return mCallback;
}
+ @Override
public void onServiceDisconnected(ComponentName name) {
synchronized(mStartLock) {
mService = null;
@@ -1317,24 +1319,33 @@ public class TextToSpeech {
public void disconnect() {
mContext.unbindService(this);
+
+ synchronized (mStartLock) {
+ mService = null;
+ // If this is the active connection, clear it
+ if (mServiceConnection == this) {
+ mServiceConnection = null;
+ }
+
+ }
}
public <R> R runAction(Action<R> action, R errorResult, String method, boolean reconnect) {
- try {
- synchronized (mStartLock) {
+ synchronized (mStartLock) {
+ try {
if (mService == null) {
Log.w(TAG, method + " failed: not connected to TTS engine");
return errorResult;
}
return action.run(mService);
+ } catch (RemoteException ex) {
+ Log.e(TAG, method + " failed", ex);
+ if (reconnect) {
+ disconnect();
+ initTts();
+ }
+ return errorResult;
}
- } catch (RemoteException ex) {
- Log.e(TAG, method + " failed", ex);
- if (reconnect) {
- disconnect();
- initTts();
- }
- return errorResult;
}
}
}
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 83a70f3..987062a 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -27,6 +27,7 @@ import android.text.style.CharacterStyle;
import android.text.style.EasyEditSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.LeadingMarginSpan;
+import android.text.style.LocaleSpan;
import android.text.style.MetricAffectingSpan;
import android.text.style.QuoteSpan;
import android.text.style.RelativeSizeSpan;
@@ -587,6 +588,8 @@ public class TextUtils {
public static final int SUGGESTION_RANGE_SPAN = 21;
/** @hide */
public static final int EASY_EDIT_SPAN = 22;
+ /** @hide */
+ public static final int LOCALE_SPAN = 23;
/**
* Flatten a CharSequence and whatever styles can be copied across processes
@@ -754,6 +757,10 @@ public class TextUtils {
readSpan(p, sp, new EasyEditSpan());
break;
+ case LOCALE_SPAN:
+ readSpan(p, sp, new LocaleSpan(p));
+ break;
+
default:
throw new RuntimeException("bogus span encoding " + kind);
}
diff --git a/core/java/android/text/style/LocaleSpan.java b/core/java/android/text/style/LocaleSpan.java
new file mode 100644
index 0000000..a12c42f
--- /dev/null
+++ b/core/java/android/text/style/LocaleSpan.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.style;
+
+import android.graphics.Paint;
+import android.os.Parcel;
+import android.text.ParcelableSpan;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import java.util.Locale;
+
+/**
+ * Changes the {@link Locale} of the text to which the span is attached.
+ */
+public class LocaleSpan extends MetricAffectingSpan implements ParcelableSpan {
+ private final Locale mLocale;
+
+ /**
+ * Creates a LocaleSpan.
+ * @param locale The {@link Locale} of the text to which the span is
+ * attached.
+ */
+ public LocaleSpan(Locale locale) {
+ mLocale = locale;
+ }
+
+ public LocaleSpan(Parcel src) {
+ mLocale = new Locale(src.readString(), src.readString(), src.readString());
+ }
+
+ @Override
+ public int getSpanTypeId() {
+ return TextUtils.LOCALE_SPAN;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mLocale.getLanguage());
+ dest.writeString(mLocale.getCountry());
+ dest.writeString(mLocale.getVariant());
+ }
+
+ /**
+ * Returns the {@link Locale}.
+ *
+ * @return The {@link Locale} for this span.
+ */
+ public Locale getLocale() {
+ return mLocale;
+ }
+
+ @Override
+ public void updateDrawState(TextPaint ds) {
+ apply(ds, mLocale);
+ }
+
+ @Override
+ public void updateMeasureState(TextPaint paint) {
+ apply(paint, mLocale);
+ }
+
+ private static void apply(Paint paint, Locale locale) {
+ paint.setTextLocale(locale);
+ }
+}
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 6288ce5..392d1f2 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -16,6 +16,7 @@
package android.view;
+import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -165,7 +166,7 @@ public final class Choreographer {
mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
mLastFrameTimeNanos = Long.MIN_VALUE;
- Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
+ Display d = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
mFrameIntervalNanos = (long)(1000000000 / d.getRefreshRate());
mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 5409b38..6f8ca13 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -67,20 +67,16 @@ public final class Display {
private int mCachedAppHeightCompat;
/**
- * The default Display id.
+ * The default Display id, which is the id of the built-in primary display
+ * assuming there is one.
*/
public static final int DEFAULT_DISPLAY = 0;
/**
- * Uninitialized display.
- * @hide
- */
- public static final int NO_DISPLAY = -1;
-
- /**
* Internal method to create a display.
* Applications should use {@link android.view.WindowManager#getDefaultDisplay()}
- * to get a display object for the default display.
+ * or {@link android.hardware.display.DisplayManager#getDisplay}
+ * to get a display object.
*
* @hide
*/
@@ -114,6 +110,31 @@ public final class Display {
}
/**
+ * Gets the display's layer stack.
+ *
+ * Each display has its own independent layer stack upon which surfaces
+ * are placed to be managed by surface flinger.
+ *
+ * @return The layer stack number.
+ * @hide
+ */
+ public int getLayerStack() {
+ // Note: This is the current convention but there is no requirement that
+ // the display id and layer stack id be the same.
+ return mDisplayId;
+ }
+
+ /**
+ * Gets the compatibility info used by this display instance.
+ *
+ * @return The compatibility info holder, or null if none is required.
+ * @hide
+ */
+ public CompatibilityInfoHolder getCompatibilityInfo() {
+ return mCompatibilityInfo;
+ }
+
+ /**
* Gets the size of the display, in pixels.
* <p>
* Note that this value should <em>not</em> be used for computing layouts,
@@ -361,5 +382,16 @@ public final class Display {
mLastCachedAppSizeUpdate = now;
}
}
+
+ // For debugging purposes
+ @Override
+ public String toString() {
+ synchronized (this) {
+ updateDisplayInfoLocked();
+ mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+ return "Display id " + mDisplayId + ": " + mDisplayInfo
+ + ", " + mTempMetrics;
+ }
+ }
}
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index c65ce63..e38f245 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -223,4 +223,17 @@ public final class DisplayInfo implements Parcelable {
}
}
}
+
+ // For debugging purposes
+ @Override
+ public String toString() {
+ return "app " + appWidth + " x " + appHeight
+ + ", real " + logicalWidth + " x " + logicalHeight
+ + ", largest app " + largestNominalAppWidth + " x " + largestNominalAppHeight
+ + ", smallest app " + smallestNominalAppWidth + " x " + smallestNominalAppHeight
+ + ", " + refreshRate + " fps"
+ + ", rotation " + rotation
+ + ", density " + logicalDensityDpi
+ + ", " + physicalXDpi + " x " + physicalYDpi + " dpi";
+ }
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 188fede..f906e24 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -1101,7 +1101,7 @@ public abstract class HardwareRenderer {
attachInfo.mIgnoreDirtyState = true;
attachInfo.mDrawingTime = SystemClock.uptimeMillis();
- view.mPrivateFlags |= View.DRAWN;
+ view.mPrivateFlags |= View.PFLAG_DRAWN;
final int surfaceState = checkCurrent();
if (surfaceState != SURFACE_STATE_ERROR) {
@@ -1135,9 +1135,9 @@ public abstract class HardwareRenderer {
callbacks.onHardwarePreDraw(canvas);
try {
- view.mRecreateDisplayList =
- (view.mPrivateFlags & View.INVALIDATED) == View.INVALIDATED;
- view.mPrivateFlags &= ~View.INVALIDATED;
+ view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
+ == View.PFLAG_INVALIDATED;
+ view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
long getDisplayListStartTime = 0;
if (mProfileEnabled) {
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5bccdd4..7f2de50 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -84,7 +84,7 @@ interface IWindowManager
void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
int startHeight);
void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
- IRemoteCallback startedCallback, boolean delayed);
+ IRemoteCallback startedCallback, boolean scaleUp);
void executeAppTransition();
void setAppStartingWindow(IBinder token, String pkg, int theme,
in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index e93e480..c5d9255 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -59,8 +59,8 @@ interface IWindowSession {
* @param requestedWidth The width the window wants to be.
* @param requestedHeight The height the window wants to be.
* @param viewVisibility Window root view's visibility.
- * @param flags Request flags: {@link WindowManagerImpl#RELAYOUT_INSETS_PENDING},
- * {@link WindowManagerImpl#RELAYOUT_DEFER_SURFACE_DESTROY}.
+ * @param flags Request flags: {@link WindowManagerGlobal#RELAYOUT_INSETS_PENDING},
+ * {@link WindowManagerGlobal#RELAYOUT_DEFER_SURFACE_DESTROY}.
* @param outFrame Rect in which is placed the new position/size on
* screen.
* @param outContentInsets Rect in which is placed the offsets from
@@ -79,8 +79,8 @@ interface IWindowSession {
* was last displayed.
* @param outSurface Object in which is placed the new display surface.
*
- * @return int Result flags: {@link WindowManagerImpl#RELAYOUT_SHOW_FOCUS},
- * {@link WindowManagerImpl#RELAYOUT_FIRST_TIME}.
+ * @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS},
+ * {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}.
*/
int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility,
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 5f5d1f2..517b514 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -246,22 +246,9 @@ public class Surface implements Parcelable {
native private static void nativeClassInit();
static { nativeClassInit(); }
- /** create a surface @hide */
- public Surface(SurfaceSession s,
- int pid, int displayId, int w, int h, int format, int flags)
- throws OutOfResourcesException {
- checkHeadless();
-
- if (DEBUG_RELEASE) {
- mCreationStack = new Exception();
- }
- mCanvas = new CompatibleCanvas();
- init(s,pid,null,displayId,w,h,format,flags);
- }
-
/** create a surface with a name @hide */
public Surface(SurfaceSession s,
- int pid, String name, int displayId, int w, int h, int format, int flags)
+ int pid, String name, int layerStack, int w, int h, int format, int flags)
throws OutOfResourcesException {
checkHeadless();
@@ -269,7 +256,7 @@ public class Surface implements Parcelable {
mCreationStack = new Exception();
}
mCanvas = new CompatibleCanvas();
- init(s,pid,name,displayId,w,h,format,flags);
+ init(s, pid, name, layerStack, w, h, format, flags);
mName = name;
}
@@ -470,7 +457,7 @@ public class Surface implements Parcelable {
/** @hide */
public native void setWindowCrop(Rect crop);
/** @hide */
- public native void setDisplayId(int displayId);
+ public native void setLayerStack(int layerStack);
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index f4d40cb..fdf1c22 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -296,7 +296,7 @@ public class SurfaceView extends View {
}
boolean opaque = true;
- if ((mPrivateFlags & SKIP_DRAW) == 0) {
+ if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
// this view draws, remove it from the transparent region
opaque = super.gatherTransparentRegion(region);
} else if (region != null) {
@@ -320,7 +320,7 @@ public class SurfaceView extends View {
public void draw(Canvas canvas) {
if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
// draw() is not called when SKIP_DRAW is set
- if ((mPrivateFlags & SKIP_DRAW) == 0) {
+ if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
// punch a whole in the view-hierarchy below us
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
}
@@ -332,7 +332,7 @@ public class SurfaceView extends View {
protected void dispatchDraw(Canvas canvas) {
if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
// if SKIP_DRAW is cleared, draw() has already punched a hole
- if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+ if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
// punch a whole in the view-hierarchy below us
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
}
@@ -480,10 +480,10 @@ public class SurfaceView extends View {
relayoutResult = mSession.relayout(
mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
visible ? VISIBLE : GONE,
- WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY,
+ WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
mWinFrame, mContentInsets,
mVisibleInsets, mConfiguration, mNewSurface);
- if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
+ if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
mReportDrawNeeded = true;
}
@@ -516,8 +516,8 @@ public class SurfaceView extends View {
SurfaceHolder.Callback callbacks[] = null;
- final boolean surfaceChanged =
- (relayoutResult&WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED) != 0;
+ final boolean surfaceChanged = (relayoutResult
+ & WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED) != 0;
if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
mSurfaceCreated = false;
if (mSurface.isValid()) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 59aeffc..b1f5e9e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -39,6 +39,7 @@ import android.graphics.Region;
import android.graphics.Shader;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -1568,17 +1569,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// for mPrivateFlags:
/** {@hide} */
- static final int WANTS_FOCUS = 0x00000001;
+ static final int PFLAG_WANTS_FOCUS = 0x00000001;
/** {@hide} */
- static final int FOCUSED = 0x00000002;
+ static final int PFLAG_FOCUSED = 0x00000002;
/** {@hide} */
- static final int SELECTED = 0x00000004;
+ static final int PFLAG_SELECTED = 0x00000004;
/** {@hide} */
- static final int IS_ROOT_NAMESPACE = 0x00000008;
+ static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008;
/** {@hide} */
- static final int HAS_BOUNDS = 0x00000010;
+ static final int PFLAG_HAS_BOUNDS = 0x00000010;
/** {@hide} */
- static final int DRAWN = 0x00000020;
+ static final int PFLAG_DRAWN = 0x00000020;
/**
* When this flag is set, this view is running an animation on behalf of its
* children and should therefore not cancel invalidate requests, even if they
@@ -1586,58 +1587,58 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* {@hide}
*/
- static final int DRAW_ANIMATION = 0x00000040;
+ static final int PFLAG_DRAW_ANIMATION = 0x00000040;
/** {@hide} */
- static final int SKIP_DRAW = 0x00000080;
+ static final int PFLAG_SKIP_DRAW = 0x00000080;
/** {@hide} */
- static final int ONLY_DRAWS_BACKGROUND = 0x00000100;
+ static final int PFLAG_ONLY_DRAWS_BACKGROUND = 0x00000100;
/** {@hide} */
- static final int REQUEST_TRANSPARENT_REGIONS = 0x00000200;
+ static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
/** {@hide} */
- static final int DRAWABLE_STATE_DIRTY = 0x00000400;
+ static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400;
/** {@hide} */
- static final int MEASURED_DIMENSION_SET = 0x00000800;
+ static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800;
/** {@hide} */
- static final int FORCE_LAYOUT = 0x00001000;
+ static final int PFLAG_FORCE_LAYOUT = 0x00001000;
/** {@hide} */
- static final int LAYOUT_REQUIRED = 0x00002000;
+ static final int PFLAG_LAYOUT_REQUIRED = 0x00002000;
- private static final int PRESSED = 0x00004000;
+ private static final int PFLAG_PRESSED = 0x00004000;
/** {@hide} */
- static final int DRAWING_CACHE_VALID = 0x00008000;
+ static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000;
/**
* Flag used to indicate that this view should be drawn once more (and only once
* more) after its animation has completed.
* {@hide}
*/
- static final int ANIMATION_STARTED = 0x00010000;
+ static final int PFLAG_ANIMATION_STARTED = 0x00010000;
- private static final int SAVE_STATE_CALLED = 0x00020000;
+ private static final int PFLAG_SAVE_STATE_CALLED = 0x00020000;
/**
* Indicates that the View returned true when onSetAlpha() was called and that
* the alpha must be restored.
* {@hide}
*/
- static final int ALPHA_SET = 0x00040000;
+ static final int PFLAG_ALPHA_SET = 0x00040000;
/**
* Set by {@link #setScrollContainer(boolean)}.
*/
- static final int SCROLL_CONTAINER = 0x00080000;
+ static final int PFLAG_SCROLL_CONTAINER = 0x00080000;
/**
* Set by {@link #setScrollContainer(boolean)}.
*/
- static final int SCROLL_CONTAINER_ADDED = 0x00100000;
+ static final int PFLAG_SCROLL_CONTAINER_ADDED = 0x00100000;
/**
* View flag indicating whether this view was invalidated (fully or partially.)
*
* @hide
*/
- static final int DIRTY = 0x00200000;
+ static final int PFLAG_DIRTY = 0x00200000;
/**
* View flag indicating whether this view was invalidated by an opaque
@@ -1645,35 +1646,35 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* @hide
*/
- static final int DIRTY_OPAQUE = 0x00400000;
+ static final int PFLAG_DIRTY_OPAQUE = 0x00400000;
/**
- * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}.
+ * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
*
* @hide
*/
- static final int DIRTY_MASK = 0x00600000;
+ static final int PFLAG_DIRTY_MASK = 0x00600000;
/**
* Indicates whether the background is opaque.
*
* @hide
*/
- static final int OPAQUE_BACKGROUND = 0x00800000;
+ static final int PFLAG_OPAQUE_BACKGROUND = 0x00800000;
/**
* Indicates whether the scrollbars are opaque.
*
* @hide
*/
- static final int OPAQUE_SCROLLBARS = 0x01000000;
+ static final int PFLAG_OPAQUE_SCROLLBARS = 0x01000000;
/**
* Indicates whether the view is opaque.
*
* @hide
*/
- static final int OPAQUE_MASK = 0x01800000;
+ static final int PFLAG_OPAQUE_MASK = 0x01800000;
/**
* Indicates a prepressed state;
@@ -1683,27 +1684,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* @hide
*/
- private static final int PREPRESSED = 0x02000000;
+ private static final int PFLAG_PREPRESSED = 0x02000000;
/**
* Indicates whether the view is temporarily detached.
*
* @hide
*/
- static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
+ static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000;
/**
* Indicates that we should awaken scroll bars once attached
*
* @hide
*/
- private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
+ private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
/**
* Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT.
* @hide
*/
- private static final int HOVERED = 0x10000000;
+ private static final int PFLAG_HOVERED = 0x10000000;
/**
* Indicates that pivotX or pivotY were explicitly set and we should not assume the center
@@ -1711,10 +1712,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* @hide
*/
- private static final int PIVOT_EXPLICITLY_SET = 0x20000000;
+ private static final int PFLAG_PIVOT_EXPLICITLY_SET = 0x20000000;
/** {@hide} */
- static final int ACTIVATED = 0x40000000;
+ static final int PFLAG_ACTIVATED = 0x40000000;
/**
* Indicates that this view was specifically invalidated, not just dirtied because some
@@ -1724,7 +1725,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* @hide
*/
- static final int INVALIDATED = 0x80000000;
+ static final int PFLAG_INVALIDATED = 0x80000000;
/* Masks for mPrivateFlags2 */
@@ -1733,7 +1734,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* Cleared when the drag operation concludes.
* @hide
*/
- static final int DRAG_CAN_ACCEPT = 0x00000001;
+ static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001;
/**
* Indicates that this view is currently directly under the drag location in a
@@ -1741,7 +1742,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* the drag exits the view, or when the drag operation concludes.
* @hide
*/
- static final int DRAG_HOVERED = 0x00000002;
+ static final int PFLAG2_DRAG_HOVERED = 0x00000002;
/**
* Horizontal layout direction of this view is from Left to Right.
@@ -1771,32 +1772,33 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
* @hide
*/
- static final int LAYOUT_DIRECTION_MASK_SHIFT = 2;
+ static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
/**
* Mask for use with private flags indicating bits used for horizontal layout direction.
* @hide
*/
- static final int LAYOUT_DIRECTION_MASK = 0x00000003 << LAYOUT_DIRECTION_MASK_SHIFT;
+ static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
/**
* Indicates whether the view horizontal layout direction has been resolved and drawn to the
* right-to-left direction.
* @hide
*/
- static final int LAYOUT_DIRECTION_RESOLVED_RTL = 4 << LAYOUT_DIRECTION_MASK_SHIFT;
+ static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
/**
* Indicates whether the view horizontal layout direction has been resolved.
* @hide
*/
- static final int LAYOUT_DIRECTION_RESOLVED = 8 << LAYOUT_DIRECTION_MASK_SHIFT;
+ static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
/**
* Mask for use with private flags indicating bits used for resolved horizontal layout direction.
* @hide
*/
- static final int LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C << LAYOUT_DIRECTION_MASK_SHIFT;
+ static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
+ << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
/*
* Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
@@ -1823,7 +1825,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* @hide
*/
- static final int HAS_TRANSIENT_STATE = 0x00000100;
+ static final int PFLAG2_HAS_TRANSIENT_STATE = 0x00000100;
/**
@@ -1863,58 +1865,61 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Default text direction is inherited
*/
- protected static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
+ public static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
/**
* Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
* @hide
*/
- static final int TEXT_DIRECTION_MASK_SHIFT = 6;
+ static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
/**
* Mask for use with private flags indicating bits used for text direction.
* @hide
*/
- static final int TEXT_DIRECTION_MASK = 0x00000007 << TEXT_DIRECTION_MASK_SHIFT;
+ static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
+ << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
/**
* Array of text direction flags for mapping attribute "textDirection" to correct
* flag value.
* @hide
*/
- private static final int[] TEXT_DIRECTION_FLAGS = {
- TEXT_DIRECTION_INHERIT << TEXT_DIRECTION_MASK_SHIFT,
- TEXT_DIRECTION_FIRST_STRONG << TEXT_DIRECTION_MASK_SHIFT,
- TEXT_DIRECTION_ANY_RTL << TEXT_DIRECTION_MASK_SHIFT,
- TEXT_DIRECTION_LTR << TEXT_DIRECTION_MASK_SHIFT,
- TEXT_DIRECTION_RTL << TEXT_DIRECTION_MASK_SHIFT,
- TEXT_DIRECTION_LOCALE << TEXT_DIRECTION_MASK_SHIFT
+ private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
+ TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+ TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+ TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+ TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+ TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+ TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
};
/**
* Indicates whether the view text direction has been resolved.
* @hide
*/
- static final int TEXT_DIRECTION_RESOLVED = 0x00000008 << TEXT_DIRECTION_MASK_SHIFT;
+ static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
+ << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
/**
* Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
* @hide
*/
- static final int TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
+ static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
/**
* Mask for use with private flags indicating bits used for resolved text direction.
* @hide
*/
- static final int TEXT_DIRECTION_RESOLVED_MASK = 0x00000007 << TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
+ static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
+ << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
/**
* Indicates whether the view text direction has been resolved to the "first strong" heuristic.
* @hide
*/
- static final int TEXT_DIRECTION_RESOLVED_DEFAULT =
- TEXT_DIRECTION_FIRST_STRONG << TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
+ static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
+ TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
/*
* Default text alignment. The text alignment of this View is inherited from its parent.
@@ -1970,58 +1975,59 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Default text alignment is inherited
*/
- protected static int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
+ public static int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
/**
* Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
* @hide
*/
- static final int TEXT_ALIGNMENT_MASK_SHIFT = 13;
+ static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
/**
* Mask for use with private flags indicating bits used for text alignment.
* @hide
*/
- static final int TEXT_ALIGNMENT_MASK = 0x00000007 << TEXT_ALIGNMENT_MASK_SHIFT;
+ static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
/**
* Array of text direction flags for mapping attribute "textAlignment" to correct
* flag value.
* @hide
*/
- private static final int[] TEXT_ALIGNMENT_FLAGS = {
- TEXT_ALIGNMENT_INHERIT << TEXT_ALIGNMENT_MASK_SHIFT,
- TEXT_ALIGNMENT_GRAVITY << TEXT_ALIGNMENT_MASK_SHIFT,
- TEXT_ALIGNMENT_TEXT_START << TEXT_ALIGNMENT_MASK_SHIFT,
- TEXT_ALIGNMENT_TEXT_END << TEXT_ALIGNMENT_MASK_SHIFT,
- TEXT_ALIGNMENT_CENTER << TEXT_ALIGNMENT_MASK_SHIFT,
- TEXT_ALIGNMENT_VIEW_START << TEXT_ALIGNMENT_MASK_SHIFT,
- TEXT_ALIGNMENT_VIEW_END << TEXT_ALIGNMENT_MASK_SHIFT
+ private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
+ TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+ TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+ TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+ TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+ TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+ TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+ TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
};
/**
* Indicates whether the view text alignment has been resolved.
* @hide
*/
- static final int TEXT_ALIGNMENT_RESOLVED = 0x00000008 << TEXT_ALIGNMENT_MASK_SHIFT;
+ static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
/**
* Bit shift to get the resolved text alignment.
* @hide
*/
- static final int TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
+ static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
/**
* Mask for use with private flags indicating bits used for text alignment.
* @hide
*/
- static final int TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007 << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+ static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
+ << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
/**
* Indicates whether if the view text alignment has been resolved to gravity
*/
- public static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT =
- TEXT_ALIGNMENT_GRAVITY << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+ private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
+ TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
// Accessiblity constants for mPrivateFlags2
@@ -2029,7 +2035,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* Shift for the bits in {@link #mPrivateFlags2} related to the
* "importantForAccessibility" attribute.
*/
- static final int IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
+ static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
/**
* Automatically determine whether a view is important for accessibility.
@@ -2055,26 +2061,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* Mask for obtainig the bits which specify how to determine
* whether a view is important for accessibility.
*/
- static final int IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
+ static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
| IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO)
- << IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+ << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
/**
* Flag indicating whether a view has accessibility focus.
*/
- static final int ACCESSIBILITY_FOCUSED = 0x00000040 << IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+ static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x00000040 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
/**
* Flag indicating whether a view state for accessibility has changed.
*/
- static final int ACCESSIBILITY_STATE_CHANGED = 0x00000080 << IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+ static final int PFLAG2_ACCESSIBILITY_STATE_CHANGED = 0x00000080
+ << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
/**
* Flag indicating whether a view failed the quickReject() check in draw(). This condition
* is used to check whether later changes to the view's transform should invalidate the
* view to force the quickReject test to run again.
*/
- static final int VIEW_QUICK_REJECTED = 0x10000000;
+ static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
/**
* Flag indicating that start/end padding has been resolved into left/right padding
@@ -2083,7 +2090,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* during measurement. In some special cases this is required such as when an adapter-based
* view measures prospective children without attaching them to a window.
*/
- static final int PADDING_RESOLVED = 0x20000000;
+ static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
// There are a couple of flags left in mPrivateFlags2
@@ -2096,19 +2103,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* an animation is cleared between successive frames, in order to tell the associated
* DisplayList to clear its animation matrix.
*/
- static final int VIEW_IS_ANIMATING_TRANSFORM = 0x1;
+ static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
/**
* Flag indicating that view has an alpha animation set on it. This is used to track whether an
* animation is cleared between successive frames, in order to tell the associated
* DisplayList to restore its alpha value.
*/
- static final int VIEW_IS_ANIMATING_ALPHA = 0x2;
+ static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
/* End of masks for mPrivateFlags3 */
- static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
+ static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
/**
* Always allow a user to over-scroll this view, provided it is a
@@ -2475,16 +2482,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* {@hide}
*/
@ViewDebug.ExportedProperty(flagMapping = {
- @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT,
+ @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
name = "FORCE_LAYOUT"),
- @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED,
+ @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
name = "LAYOUT_REQUIRED"),
- @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID,
+ @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
name = "DRAWING_CACHE_INVALID", outputIf = false),
- @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true),
- @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false),
- @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
- @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
+ @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
+ @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
+ @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
+ @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
})
int mPrivateFlags;
int mPrivateFlags2;
@@ -2790,6 +2797,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
int mUserPaddingEnd;
/**
+ * Whether a left padding has been defined during layout inflation.
+ *
+ * @hide
+ */
+ boolean mUserPaddingLeftDefined = false;
+
+ /**
+ * Whether a right padding has been defined during layout inflation.
+ *
+ * @hide
+ */
+ boolean mUserPaddingRightDefined = false;
+
+ /**
* Default undefined padding
*/
private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
@@ -3086,6 +3107,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
private boolean mSendingHoverAccessibilityEvents;
+ /**
+ * Delegate for injecting accessiblity functionality.
+ */
+ AccessibilityDelegate mAccessibilityDelegate;
+
+ /**
+ * Consistency verifier for debugging purposes.
+ * @hide
+ */
+ protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
+ InputEventConsistencyVerifier.isInstrumentationEnabled() ?
+ new InputEventConsistencyVerifier(this, 0) : null;
+
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
/**
@@ -3099,10 +3133,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mResources = context != null ? context.getResources() : null;
mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
// Set layout and text direction defaults
- mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << LAYOUT_DIRECTION_MASK_SHIFT) |
- (TEXT_DIRECTION_DEFAULT << TEXT_DIRECTION_MASK_SHIFT) |
- (TEXT_ALIGNMENT_DEFAULT << TEXT_ALIGNMENT_MASK_SHIFT) |
- (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
+ mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
+ (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
+ (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
+ (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
mUserPaddingStart = UNDEFINED_PADDING;
@@ -3110,19 +3144,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Delegate for injecting accessiblity functionality.
- */
- AccessibilityDelegate mAccessibilityDelegate;
-
- /**
- * Consistency verifier for debugging purposes.
- * @hide
- */
- protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
- InputEventConsistencyVerifier.isInstrumentationEnabled() ?
- new InputEventConsistencyVerifier(this, 0) : null;
-
- /**
* Constructor that is called when inflating a view from XML. This is called
* when a view is being constructed from an XML file, supplying attributes
* that were specified in the XML file. This version uses a default style of
@@ -3195,8 +3216,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
boolean transformSet = false;
int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
-
int overScrollMode = mOverScrollMode;
+ boolean initializeScrollbars = false;
+
+ final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
+
final int N = a.getIndexCount();
for (int i = 0; i < N; i++) {
int attr = a.getIndex(i);
@@ -3206,15 +3230,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
break;
case com.android.internal.R.styleable.View_padding:
padding = a.getDimensionPixelSize(attr, -1);
+ mUserPaddingLeftDefined = true;
+ mUserPaddingRightDefined = true;
break;
case com.android.internal.R.styleable.View_paddingLeft:
leftPadding = a.getDimensionPixelSize(attr, -1);
+ mUserPaddingLeftDefined = true;
break;
case com.android.internal.R.styleable.View_paddingTop:
topPadding = a.getDimensionPixelSize(attr, -1);
break;
case com.android.internal.R.styleable.View_paddingRight:
rightPadding = a.getDimensionPixelSize(attr, -1);
+ mUserPaddingRightDefined = true;
break;
case com.android.internal.R.styleable.View_paddingBottom:
bottomPadding = a.getDimensionPixelSize(attr, -1);
@@ -3325,12 +3353,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
break;
case com.android.internal.R.styleable.View_layoutDirection:
// Clear any layout direction flags (included resolved bits) already set
- mPrivateFlags2 &= ~(LAYOUT_DIRECTION_MASK | LAYOUT_DIRECTION_RESOLVED_MASK);
+ mPrivateFlags2 &= ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
// Set the layout direction flags depending on the value of the attribute
final int layoutDirection = a.getInt(attr, -1);
final int value = (layoutDirection != -1) ?
LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
- mPrivateFlags2 |= (value << LAYOUT_DIRECTION_MASK_SHIFT);
+ mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
break;
case com.android.internal.R.styleable.View_drawingCacheQuality:
final int cacheQuality = a.getInt(attr, 0);
@@ -3359,12 +3387,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (scrollbars != SCROLLBARS_NONE) {
viewFlagValues |= scrollbars;
viewFlagMasks |= SCROLLBARS_MASK;
- initializeScrollbars(a);
+ initializeScrollbars = true;
}
break;
//noinspection deprecation
case R.styleable.View_fadingEdge:
- if (context.getApplicationInfo().targetSdkVersion >= ICE_CREAM_SANDWICH) {
+ if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
// Ignore the attribute starting with ICS
break;
}
@@ -3475,19 +3503,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
break;
case R.styleable.View_textDirection:
// Clear any text direction flag already set
- mPrivateFlags2 &= ~TEXT_DIRECTION_MASK;
+ mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
// Set the text direction flags depending on the value of the attribute
final int textDirection = a.getInt(attr, -1);
if (textDirection != -1) {
- mPrivateFlags2 |= TEXT_DIRECTION_FLAGS[textDirection];
+ mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
}
break;
case R.styleable.View_textAlignment:
// Clear any text alignment flag already set
- mPrivateFlags2 &= ~TEXT_ALIGNMENT_MASK;
+ mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
// Set the text alignment flag depending on the value of the attribute
final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
- mPrivateFlags2 |= TEXT_ALIGNMENT_FLAGS[textAlignment];
+ mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
break;
case R.styleable.View_importantForAccessibility:
setImportantForAccessibility(a.getInt(attr,
@@ -3496,12 +3524,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
- a.recycle();
-
setOverScrollMode(overScrollMode);
- // Cache user padding as we cannot fully resolve padding here (we dont have yet the resolved
- // layout direction). Those cached values will be used later during padding resolution.
+ // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
+ // the resolved layout direction). Those cached values will be used later during padding
+ // resolution.
mUserPaddingStart = startPadding;
mUserPaddingEnd = endPadding;
@@ -3529,6 +3556,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
setFlags(viewFlagValues, viewFlagMasks);
}
+ if (initializeScrollbars) {
+ initializeScrollbars(a);
+ }
+
+ a.recycle();
+
// Needs to be called after mViewFlags is set
if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
recomputePadding();
@@ -3562,6 +3595,81 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mResources = null;
}
+ public String toString() {
+ StringBuilder out = new StringBuilder(128);
+ out.append(getClass().getName());
+ out.append('{');
+ out.append(Integer.toHexString(System.identityHashCode(this)));
+ out.append(' ');
+ switch (mViewFlags&VISIBILITY_MASK) {
+ case VISIBLE: out.append('V'); break;
+ case INVISIBLE: out.append('I'); break;
+ case GONE: out.append('G'); break;
+ default: out.append('.'); break;
+ }
+ out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
+ out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
+ out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
+ out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
+ out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
+ out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
+ out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
+ out.append(' ');
+ out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
+ out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
+ out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
+ if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
+ out.append('p');
+ } else {
+ out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
+ }
+ out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
+ out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
+ out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
+ out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
+ out.append(' ');
+ out.append(mLeft);
+ out.append(',');
+ out.append(mTop);
+ out.append('-');
+ out.append(mRight);
+ out.append(',');
+ out.append(mBottom);
+ final int id = getId();
+ if (id != NO_ID) {
+ out.append(" #");
+ out.append(Integer.toHexString(id));
+ final Resources r = mResources;
+ if (id != 0 && r != null) {
+ try {
+ String pkgname;
+ switch (id&0xff000000) {
+ case 0x7f000000:
+ pkgname="app";
+ break;
+ case 0x01000000:
+ pkgname="android";
+ break;
+ default:
+ pkgname = r.getResourcePackageName(id);
+ break;
+ }
+ String typename = r.getResourceTypeName(id);
+ String entryname = r.getResourceEntryName(id);
+ out.append(" ");
+ out.append(pkgname);
+ out.append(":");
+ out.append(typename);
+ out.append("/");
+ out.append(entryname);
+ } catch (Resources.NotFoundException e) {
+ }
+ }
+ }
+ out.append("}");
+ return out.toString();
+ }
+
/**
* <p>
* Initializes the fading edges from a given set of styled attributes. This
@@ -4119,8 +4227,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
System.out.println(this + " requestFocus()");
}
- if ((mPrivateFlags & FOCUSED) == 0) {
- mPrivateFlags |= FOCUSED;
+ if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
+ mPrivateFlags |= PFLAG_FOCUSED;
if (mParent != null) {
mParent.requestChildFocus(this, this);
@@ -4204,8 +4312,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
System.out.println(this + " clearFocus()");
}
- if ((mPrivateFlags & FOCUSED) != 0) {
- mPrivateFlags &= ~FOCUSED;
+ if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
+ mPrivateFlags &= ~PFLAG_FOCUSED;
if (mParent != null) {
mParent.clearChildFocus(this);
@@ -4239,8 +4347,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
System.out.println(this + " unFocus()");
}
- if ((mPrivateFlags & FOCUSED) != 0) {
- mPrivateFlags &= ~FOCUSED;
+ if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
+ mPrivateFlags &= ~PFLAG_FOCUSED;
onFocusChanged(false, 0, null);
refreshDrawableState();
@@ -4259,7 +4367,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@ViewDebug.ExportedProperty(category = "focus")
public boolean hasFocus() {
- return (mPrivateFlags & FOCUSED) != 0;
+ return (mPrivateFlags & PFLAG_FOCUSED) != 0;
}
/**
@@ -4959,7 +5067,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@ViewDebug.ExportedProperty(category = "focus")
public boolean isFocused() {
- return (mPrivateFlags & FOCUSED) != 0;
+ return (mPrivateFlags & PFLAG_FOCUSED) != 0;
}
/**
@@ -4970,7 +5078,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* be found.
*/
public View findFocus() {
- return (mPrivateFlags & FOCUSED) != 0 ? this : null;
+ return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
}
/**
@@ -4983,7 +5091,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @attr ref android.R.styleable#View_isScrollContainer
*/
public boolean isScrollContainer() {
- return (mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0;
+ return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
}
/**
@@ -4997,16 +5105,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void setScrollContainer(boolean isScrollContainer) {
if (isScrollContainer) {
- if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) {
+ if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
mAttachInfo.mScrollContainers.add(this);
- mPrivateFlags |= SCROLL_CONTAINER_ADDED;
+ mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
}
- mPrivateFlags |= SCROLL_CONTAINER;
+ mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
} else {
- if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
+ if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
mAttachInfo.mScrollContainers.remove(this);
}
- mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED);
+ mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
}
}
@@ -5513,7 +5621,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
@ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE")
})
public int getLayoutDirection() {
- return (mPrivateFlags2 & LAYOUT_DIRECTION_MASK) >> LAYOUT_DIRECTION_MASK_SHIFT;
+ return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
}
/**
@@ -5531,12 +5639,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public void setLayoutDirection(int layoutDirection) {
if (getLayoutDirection() != layoutDirection) {
// Reset the current layout direction and the resolved one
- mPrivateFlags2 &= ~LAYOUT_DIRECTION_MASK;
+ mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
resetResolvedLayoutDirection();
- // Set the new layout direction (filtered) and ask for a layout pass
+ // Reset padding resolution
+ mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
+ // Set the new layout direction (filtered)
mPrivateFlags2 |=
- ((layoutDirection << LAYOUT_DIRECTION_MASK_SHIFT) & LAYOUT_DIRECTION_MASK);
- resolvePadding();
+ ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
+ resolveRtlProperties();
+ // ... and ask for a layout pass
requestLayout();
}
}
@@ -5552,11 +5663,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
@ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
})
public int getResolvedLayoutDirection() {
+ final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
+ if (targetSdkVersion < JELLY_BEAN_MR1) {
+ mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
+ return LAYOUT_DIRECTION_LTR;
+ }
// The layout direction will be resolved only if needed
- if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) != LAYOUT_DIRECTION_RESOLVED) {
+ if ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) != PFLAG2_LAYOUT_DIRECTION_RESOLVED) {
resolveLayoutDirection();
}
- return ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED_RTL) == LAYOUT_DIRECTION_RESOLVED_RTL) ?
+ return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) == PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ?
LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
}
@@ -5585,7 +5701,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@ViewDebug.ExportedProperty(category = "layout")
public boolean hasTransientState() {
- return (mPrivateFlags2 & HAS_TRANSIENT_STATE) == HAS_TRANSIENT_STATE;
+ return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
}
/**
@@ -5612,8 +5728,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if ((hasTransientState && mTransientStateCount == 1) ||
(!hasTransientState && mTransientStateCount == 0)) {
// update flag if we've just incremented up from 0 or decremented down to 0
- mPrivateFlags2 = (mPrivateFlags2 & ~HAS_TRANSIENT_STATE) |
- (hasTransientState ? HAS_TRANSIENT_STATE : 0);
+ mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
+ (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
if (mParent != null) {
try {
mParent.childHasTransientStateChanged(this, hasTransientState);
@@ -5736,12 +5852,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* the View's internal state from a previously set "pressed" state.
*/
public void setPressed(boolean pressed) {
- final boolean needsRefresh = pressed != ((mPrivateFlags & PRESSED) == PRESSED);
+ final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
if (pressed) {
- mPrivateFlags |= PRESSED;
+ mPrivateFlags |= PFLAG_PRESSED;
} else {
- mPrivateFlags &= ~PRESSED;
+ mPrivateFlags &= ~PFLAG_PRESSED;
}
if (needsRefresh) {
@@ -5772,7 +5888,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return true if the view is currently pressed, false otherwise
*/
public boolean isPressed() {
- return (mPrivateFlags & PRESSED) == PRESSED;
+ return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
}
/**
@@ -6099,7 +6215,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return True if this View is accessibility focused.
*/
boolean isAccessibilityFocused() {
- return (mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0;
+ return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
}
/**
@@ -6124,8 +6240,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
return false;
}
- if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) == 0) {
- mPrivateFlags2 |= ACCESSIBILITY_FOCUSED;
+ if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
+ mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
ViewRootImpl viewRootImpl = getViewRootImpl();
if (viewRootImpl != null) {
viewRootImpl.setAccessibilityFocus(this, null);
@@ -6147,8 +6263,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
public void clearAccessibilityFocus() {
- if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
- mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
+ if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
+ mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
invalidate();
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
notifyAccessibilityStateChanged();
@@ -6196,8 +6312,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* another view.
*/
void clearAccessibilityFocusNoCallbacks() {
- if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
- mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
+ if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
+ mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
invalidate();
}
}
@@ -6354,8 +6470,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
@ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no")
})
public int getImportantForAccessibility() {
- return (mPrivateFlags2 & IMPORTANT_FOR_ACCESSIBILITY_MASK)
- >> IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+ return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
+ >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
}
/**
@@ -6373,9 +6489,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void setImportantForAccessibility(int mode) {
if (mode != getImportantForAccessibility()) {
- mPrivateFlags2 &= ~IMPORTANT_FOR_ACCESSIBILITY_MASK;
- mPrivateFlags2 |= (mode << IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
- & IMPORTANT_FOR_ACCESSIBILITY_MASK;
+ mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
+ mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
+ & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
notifyAccessibilityStateChanged();
}
}
@@ -6388,8 +6504,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
public boolean isImportantForAccessibility() {
- final int mode = (mPrivateFlags2 & IMPORTANT_FOR_ACCESSIBILITY_MASK)
- >> IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+ final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
+ >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
switch (mode) {
case IMPORTANT_FOR_ACCESSIBILITY_YES:
return true;
@@ -6498,8 +6614,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
return;
}
- if ((mPrivateFlags2 & ACCESSIBILITY_STATE_CHANGED) == 0) {
- mPrivateFlags2 |= ACCESSIBILITY_STATE_CHANGED;
+ if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_STATE_CHANGED) == 0) {
+ mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_STATE_CHANGED;
if (mParent != null) {
mParent.childAccessibilityStateChanged(this);
}
@@ -6513,7 +6629,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
public void resetAccessibilityStateChanged() {
- mPrivateFlags2 &= ~ACCESSIBILITY_STATE_CHANGED;
+ mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_STATE_CHANGED;
}
/**
@@ -6765,7 +6881,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void onStartTemporaryDetach() {
removeUnsetPressCallback();
- mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
+ mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
}
/**
@@ -7084,13 +7200,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (isPressed()) {
setPressed(false);
}
- if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
+ if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
imm.focusOut(this);
}
removeLongPressCallback();
removeTapCallback();
onFocusLost();
- } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
+ } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
imm.focusIn(this);
}
refreshDrawableState();
@@ -7130,7 +7246,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mAttachInfo != null) {
initialAwakenScrollBars();
} else {
- mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH;
+ mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
}
}
}
@@ -7231,7 +7347,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
outRect.bottom -= insets.bottom;
return;
}
- Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
+ Display d = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
d.getRectSize(outRect);
}
@@ -7730,7 +7846,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@ViewDebug.ExportedProperty
public boolean isHovered() {
- return (mPrivateFlags & HOVERED) != 0;
+ return (mPrivateFlags & PFLAG_HOVERED) != 0;
}
/**
@@ -7750,14 +7866,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void setHovered(boolean hovered) {
if (hovered) {
- if ((mPrivateFlags & HOVERED) == 0) {
- mPrivateFlags |= HOVERED;
+ if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
+ mPrivateFlags |= PFLAG_HOVERED;
refreshDrawableState();
onHoverChanged(true);
}
} else {
- if ((mPrivateFlags & HOVERED) != 0) {
- mPrivateFlags &= ~HOVERED;
+ if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
+ mPrivateFlags &= ~PFLAG_HOVERED;
refreshDrawableState();
onHoverChanged(false);
}
@@ -7789,7 +7905,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
final int viewFlags = mViewFlags;
if ((viewFlags & ENABLED_MASK) == DISABLED) {
- if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PRESSED) != 0) {
+ if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
setPressed(false);
}
// A disabled view that is clickable still consumes the touch
@@ -7808,8 +7924,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
- boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;
- if ((mPrivateFlags & PRESSED) != 0 || prepressed) {
+ boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
+ if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
// take focus if we don't have it already and we should in
// touch mode.
boolean focusTaken = false;
@@ -7871,7 +7987,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// For views inside a scrolling container, delay the pressed feedback for
// a short period in case this is a scroll.
if (isInScrollingContainer) {
- mPrivateFlags |= PREPRESSED;
+ mPrivateFlags |= PFLAG_PREPRESSED;
if (mPendingCheckForTap == null) {
mPendingCheckForTap = new CheckForTap();
}
@@ -7896,7 +8012,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (!pointInView(x, y, mTouchSlop)) {
// Outside button
removeTapCallback();
- if ((mPrivateFlags & PRESSED) != 0) {
+ if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
// Remove any future long press/tap checks
removeLongPressCallback();
@@ -7947,7 +8063,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* Remove the prepress detection timer.
*/
private void removeUnsetPressCallback() {
- if ((mPrivateFlags & PRESSED) != 0 && mUnsetPressedState != null) {
+ if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
setPressed(false);
removeCallbacks(mUnsetPressedState);
}
@@ -7958,7 +8074,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
private void removeTapCallback() {
if (mPendingCheckForTap != null) {
- mPrivateFlags &= ~PREPRESSED;
+ mPrivateFlags &= ~PFLAG_PREPRESSED;
removeCallbacks(mPendingCheckForTap);
}
}
@@ -8023,13 +8139,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/* Check if the FOCUSABLE bit has changed */
if (((changed & FOCUSABLE_MASK) != 0) &&
- ((privateFlags & HAS_BOUNDS) !=0)) {
+ ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
if (((old & FOCUSABLE_MASK) == FOCUSABLE)
- && ((privateFlags & FOCUSED) != 0)) {
+ && ((privateFlags & PFLAG_FOCUSED) != 0)) {
/* Give up focus if we are no longer focusable */
clearFocus();
} else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
- && ((privateFlags & FOCUSED) == 0)) {
+ && ((privateFlags & PFLAG_FOCUSED) == 0)) {
/*
* Tell the view system that we are now available to take focus
* if no one else already has it.
@@ -8048,7 +8164,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* it was not visible. Marking it drawn ensures that the invalidation will
* go through.
*/
- mPrivateFlags |= DRAWN;
+ mPrivateFlags |= PFLAG_DRAWN;
invalidate(true);
needGlobalAttributesUpdate(true);
@@ -8078,7 +8194,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
// Mark the view drawn to ensure that it gets invalidated properly the next
// time it is visible and gets invalidated
- mPrivateFlags |= DRAWN;
+ mPrivateFlags |= PFLAG_DRAWN;
}
if (mAttachInfo != null) {
mAttachInfo.mViewVisibilityChanged = true;
@@ -8092,7 +8208,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* If this view is becoming invisible, set the DRAWN flag so that
* the next invalidate() will not be skipped.
*/
- mPrivateFlags |= DRAWN;
+ mPrivateFlags |= PFLAG_DRAWN;
if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
// root view becoming invisible shouldn't clear focus and accessibility focus
@@ -8123,25 +8239,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if ((changed & DRAWING_CACHE_ENABLED) != 0) {
destroyDrawingCache();
- mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
invalidateParentCaches();
}
if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
destroyDrawingCache();
- mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
}
if ((changed & DRAW_MASK) != 0) {
if ((mViewFlags & WILL_NOT_DRAW) != 0) {
if (mBackground != null) {
- mPrivateFlags &= ~SKIP_DRAW;
- mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
+ mPrivateFlags &= ~PFLAG_SKIP_DRAW;
+ mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
} else {
- mPrivateFlags |= SKIP_DRAW;
+ mPrivateFlags |= PFLAG_SKIP_DRAW;
}
} else {
- mPrivateFlags &= ~SKIP_DRAW;
+ mPrivateFlags &= ~PFLAG_SKIP_DRAW;
}
requestLayout();
invalidate(true);
@@ -8449,7 +8565,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// asked for the matrix; recalculate it with the current values
// Figure out if we need to update the pivot point
- if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+ if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
info.mPrevWidth = mRight - mLeft;
info.mPrevHeight = mBottom - mTop;
@@ -8593,7 +8709,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mDisplayList != null) {
mDisplayList.setCameraDistance(-Math.abs(distance) / dpi);
}
- if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
invalidateParentIfNeeded();
}
@@ -8639,7 +8755,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mDisplayList != null) {
mDisplayList.setRotation(rotation);
}
- if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
invalidateParentIfNeeded();
}
@@ -8690,7 +8806,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mDisplayList != null) {
mDisplayList.setRotationY(rotationY);
}
- if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
invalidateParentIfNeeded();
}
@@ -8741,7 +8857,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mDisplayList != null) {
mDisplayList.setRotationX(rotationX);
}
- if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
invalidateParentIfNeeded();
}
@@ -8784,7 +8900,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mDisplayList != null) {
mDisplayList.setScaleX(scaleX);
}
- if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
invalidateParentIfNeeded();
}
@@ -8827,7 +8943,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mDisplayList != null) {
mDisplayList.setScaleY(scaleY);
}
- if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
invalidateParentIfNeeded();
}
@@ -8868,7 +8984,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void setPivotX(float pivotX) {
ensureTransformationInfo();
- mPrivateFlags |= PIVOT_EXPLICITLY_SET;
+ mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
final TransformationInfo info = mTransformationInfo;
if (info.mPivotX != pivotX) {
invalidateViewProperty(true, false);
@@ -8878,7 +8994,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mDisplayList != null) {
mDisplayList.setPivotX(pivotX);
}
- if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
invalidateParentIfNeeded();
}
@@ -8918,7 +9034,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void setPivotY(float pivotY) {
ensureTransformationInfo();
- mPrivateFlags |= PIVOT_EXPLICITLY_SET;
+ mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
final TransformationInfo info = mTransformationInfo;
if (info.mPivotY != pivotY) {
invalidateViewProperty(true, false);
@@ -8928,7 +9044,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mDisplayList != null) {
mDisplayList.setPivotY(pivotY);
}
- if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
invalidateParentIfNeeded();
}
@@ -8988,12 +9104,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mTransformationInfo.mAlpha != alpha) {
mTransformationInfo.mAlpha = alpha;
if (onSetAlpha((int) (alpha * 255))) {
- mPrivateFlags |= ALPHA_SET;
+ mPrivateFlags |= PFLAG_ALPHA_SET;
// subclass is handling alpha - don't optimize rendering cache invalidation
invalidateParentCaches();
invalidate(true);
} else {
- mPrivateFlags &= ~ALPHA_SET;
+ mPrivateFlags &= ~PFLAG_ALPHA_SET;
invalidateViewProperty(true, false);
if (mDisplayList != null) {
mDisplayList.setAlpha(alpha);
@@ -9018,10 +9134,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mTransformationInfo.mAlpha = alpha;
boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
if (subclassHandlesAlpha) {
- mPrivateFlags |= ALPHA_SET;
+ mPrivateFlags |= PFLAG_ALPHA_SET;
return true;
} else {
- mPrivateFlags &= ~ALPHA_SET;
+ mPrivateFlags &= ~PFLAG_ALPHA_SET;
if (mDisplayList != null) {
mDisplayList.setAlpha(alpha);
}
@@ -9081,16 +9197,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
onSizeChanged(width, mBottom - mTop, width, oldHeight);
if (!matrixIsIdentity) {
- if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+ if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
// A change in dimension means an auto-centered pivot point changes, too
mTransformationInfo.mMatrixDirty = true;
}
- mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
invalidate(true);
}
mBackgroundSizeChanged = true;
invalidateParentIfNeeded();
- if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
invalidateParentIfNeeded();
}
@@ -9113,7 +9229,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The dirty state of this view.
*/
public boolean isDirty() {
- return (mPrivateFlags & DIRTY_MASK) != 0;
+ return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
}
/**
@@ -9154,16 +9270,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
onSizeChanged(width, mBottom - mTop, width, oldHeight);
if (!matrixIsIdentity) {
- if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+ if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
// A change in dimension means an auto-centered pivot point changes, too
mTransformationInfo.mMatrixDirty = true;
}
- mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
invalidate(true);
}
mBackgroundSizeChanged = true;
invalidateParentIfNeeded();
- if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
invalidateParentIfNeeded();
}
@@ -9221,16 +9337,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
onSizeChanged(mRight - mLeft, height, oldWidth, height);
if (!matrixIsIdentity) {
- if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+ if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
// A change in dimension means an auto-centered pivot point changes, too
mTransformationInfo.mMatrixDirty = true;
}
- mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
invalidate(true);
}
mBackgroundSizeChanged = true;
invalidateParentIfNeeded();
- if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
invalidateParentIfNeeded();
}
@@ -9285,16 +9401,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
onSizeChanged(mRight - mLeft, height, oldWidth, height);
if (!matrixIsIdentity) {
- if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+ if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
// A change in dimension means an auto-centered pivot point changes, too
mTransformationInfo.mMatrixDirty = true;
}
- mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
invalidate(true);
}
mBackgroundSizeChanged = true;
invalidateParentIfNeeded();
- if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
invalidateParentIfNeeded();
}
@@ -9382,7 +9498,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mDisplayList != null) {
mDisplayList.setTranslationX(translationX);
}
- if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
invalidateParentIfNeeded();
}
@@ -9423,7 +9539,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mDisplayList != null) {
mDisplayList.setTranslationY(translationY);
}
- if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
invalidateParentIfNeeded();
}
@@ -9657,6 +9773,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
throw new NullPointerException("Layout parameters cannot be null");
}
mLayoutParams = params;
+ resolveLayoutParams();
if (mParent instanceof ViewGroup) {
((ViewGroup) mParent).onSetLayoutParams(this, params);
}
@@ -9664,6 +9781,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Resolve the layout parameters depending on the resolved layout direction
+ */
+ private void resolveLayoutParams() {
+ if (mLayoutParams != null) {
+ mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
+ }
+ }
+
+ /**
* Set the scrolled position of your view. This will cause a call to
* {@link #onScrollChanged(int, int, int, int)} and the view will be
* invalidated.
@@ -9884,12 +10010,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (skipInvalidate()) {
return;
}
- if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
- (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
- (mPrivateFlags & INVALIDATED) != INVALIDATED) {
- mPrivateFlags &= ~DRAWING_CACHE_VALID;
- mPrivateFlags |= INVALIDATED;
- mPrivateFlags |= DIRTY;
+ if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
+ (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
+ (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
+ mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
+ mPrivateFlags |= PFLAG_INVALIDATED;
+ mPrivateFlags |= PFLAG_DIRTY;
final ViewParent p = mParent;
final AttachInfo ai = mAttachInfo;
//noinspection PointlessBooleanExpression,ConstantConditions
@@ -9927,12 +10053,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (skipInvalidate()) {
return;
}
- if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
- (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
- (mPrivateFlags & INVALIDATED) != INVALIDATED) {
- mPrivateFlags &= ~DRAWING_CACHE_VALID;
- mPrivateFlags |= INVALIDATED;
- mPrivateFlags |= DIRTY;
+ if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
+ (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
+ (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
+ mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
+ mPrivateFlags |= PFLAG_INVALIDATED;
+ mPrivateFlags |= PFLAG_DIRTY;
final ViewParent p = mParent;
final AttachInfo ai = mAttachInfo;
//noinspection PointlessBooleanExpression,ConstantConditions
@@ -9979,15 +10105,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (skipInvalidate()) {
return;
}
- if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
- (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) ||
- (mPrivateFlags & INVALIDATED) != INVALIDATED || isOpaque() != mLastIsOpaque) {
+ if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
+ (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) ||
+ (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) {
mLastIsOpaque = isOpaque();
- mPrivateFlags &= ~DRAWN;
- mPrivateFlags |= DIRTY;
+ mPrivateFlags &= ~PFLAG_DRAWN;
+ mPrivateFlags |= PFLAG_DIRTY;
if (invalidateCache) {
- mPrivateFlags |= INVALIDATED;
- mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ mPrivateFlags |= PFLAG_INVALIDATED;
+ mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
}
final AttachInfo ai = mAttachInfo;
final ViewParent p = mParent;
@@ -10028,12 +10154,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* list properties are not being used in this view
*/
void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
- if (mDisplayList == null || (mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) {
+ if (mDisplayList == null || (mPrivateFlags & PFLAG_DRAW_ANIMATION) == PFLAG_DRAW_ANIMATION) {
if (invalidateParent) {
invalidateParentCaches();
}
if (forceRedraw) {
- mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
}
invalidate(false);
} else {
@@ -10077,7 +10203,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
protected void invalidateParentCaches() {
if (mParent instanceof View) {
- ((View) mParent).mPrivateFlags |= INVALIDATED;
+ ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
}
}
@@ -10109,7 +10235,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@ViewDebug.ExportedProperty(category = "drawing")
public boolean isOpaque() {
- return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK &&
+ return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1.0f) >= 1.0f);
}
@@ -10123,17 +10249,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// - Doesn't have scrollbars or scrollbars are inside overlay
if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
- mPrivateFlags |= OPAQUE_BACKGROUND;
+ mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
} else {
- mPrivateFlags &= ~OPAQUE_BACKGROUND;
+ mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
}
final int flags = mViewFlags;
if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
(flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
- mPrivateFlags |= OPAQUE_SCROLLBARS;
+ mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
} else {
- mPrivateFlags &= ~OPAQUE_SCROLLBARS;
+ mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
}
}
@@ -10141,7 +10267,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
protected boolean hasOpaqueScrollbars() {
- return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
+ return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
}
/**
@@ -11186,23 +11312,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #onDetachedFromWindow()
*/
protected void onAttachedToWindow() {
- if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
+ if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
mParent.requestTransparentRegion(this);
}
- if ((mPrivateFlags & AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
+ if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
initialAwakenScrollBars();
- mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
+ mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
}
jumpDrawablesToCurrentState();
- // Order is important here: LayoutDirection MUST be resolved before Padding
- // and TextDirection
- resolveLayoutDirection();
- resolvePadding();
- resolveTextDirection();
- resolveTextAlignment();
+ resolveRtlProperties();
clearAccessibilityFocus();
if (isFocused()) {
@@ -11215,6 +11336,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
+ void resolveRtlProperties() {
+ // Order is important here: LayoutDirection MUST be resolved first...
+ resolveLayoutDirection();
+ // ... then we can resolve the others properties depending on the resolved LayoutDirection.
+ resolvePadding();
+ resolveLayoutParams();
+ resolveTextDirection();
+ resolveTextAlignment();
+ }
+
/**
* @see #onScreenStateChanged(int)
*/
@@ -11248,7 +11379,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void resolveLayoutDirection() {
// Clear any previous layout direction resolution
- mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_MASK;
+ mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
if (hasRtlSupport()) {
// Set resolved depending on layout direction
@@ -11265,15 +11396,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (!viewGroup.canResolveLayoutDirection()) return;
if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
- mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
+ mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
}
break;
case LAYOUT_DIRECTION_RTL:
- mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
+ mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
break;
case LAYOUT_DIRECTION_LOCALE:
if(isLayoutDirectionRtl(Locale.getDefault())) {
- mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
+ mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
}
break;
default:
@@ -11282,7 +11413,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
// Set to resolved
- mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
+ mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
onResolvedLayoutDirectionChanged();
}
@@ -11295,56 +11426,66 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Return if padding has been resolved
+ */
+ boolean isPaddingResolved() {
+ return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) != 0;
+ }
+
+ /**
* Resolve padding depending on layout direction.
*/
public void resolvePadding() {
- // If the user specified the absolute padding (either with android:padding or
- // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
- // use the default padding or the padding from the background drawable
- // (stored at this point in mPadding*)
- int resolvedLayoutDirection = getResolvedLayoutDirection();
- switch (resolvedLayoutDirection) {
- case LAYOUT_DIRECTION_RTL:
- // Start user padding override Right user padding. Otherwise, if Right user
- // padding is not defined, use the default Right padding. If Right user padding
- // is defined, just use it.
- if (mUserPaddingStart != UNDEFINED_PADDING) {
- mUserPaddingRight = mUserPaddingStart;
- }
- if (mUserPaddingRight == UNDEFINED_PADDING) {
- mUserPaddingRight = mPaddingRight;
- }
- if (mUserPaddingEnd != UNDEFINED_PADDING) {
- mUserPaddingLeft = mUserPaddingEnd;
- }
- if (mUserPaddingLeft == UNDEFINED_PADDING) {
- mUserPaddingLeft = mPaddingLeft;
- }
- break;
- case LAYOUT_DIRECTION_LTR:
- default:
- // Start user padding override Left user padding. Otherwise, if Left user
- // padding is not defined, use the default left padding. If Left user padding
- // is defined, just use it.
- if (mUserPaddingStart != UNDEFINED_PADDING) {
- mUserPaddingLeft = mUserPaddingStart;
- }
- if (mUserPaddingLeft == UNDEFINED_PADDING) {
- mUserPaddingLeft = mPaddingLeft;
- }
- if (mUserPaddingEnd != UNDEFINED_PADDING) {
- mUserPaddingRight = mUserPaddingEnd;
- }
- if (mUserPaddingRight == UNDEFINED_PADDING) {
- mUserPaddingRight = mPaddingRight;
- }
- }
+ final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
+ if (targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport()) {
+ // Pre Jelly Bean MR1 case (compatibility mode) OR no RTL support case:
+ // left / right padding are used if defined. If they are not defined and start / end
+ // padding are defined (e.g. in Frameworks resources), then we use start / end and
+ // resolve them as left / right (layout direction is not taken into account).
+ if (!mUserPaddingLeftDefined && mUserPaddingStart != UNDEFINED_PADDING) {
+ mUserPaddingLeft = mUserPaddingStart;
+ }
+ if (!mUserPaddingRightDefined && mUserPaddingEnd != UNDEFINED_PADDING) {
+ mUserPaddingRight = mUserPaddingEnd;
+ }
- mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
+ mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
- internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
- onPaddingChanged(resolvedLayoutDirection);
- mPrivateFlags2 |= PADDING_RESOLVED;
+ internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
+ mUserPaddingBottom);
+ } else {
+ // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
+ // If start / end padding are defined, they will be resolved (hence overriding) to
+ // left / right or right / left depending on the resolved layout direction.
+ // If start / end padding are not defined, use the left / right ones.
+ int resolvedLayoutDirection = getResolvedLayoutDirection();
+ switch (resolvedLayoutDirection) {
+ case LAYOUT_DIRECTION_RTL:
+ if (mUserPaddingStart != UNDEFINED_PADDING) {
+ mUserPaddingRight = mUserPaddingStart;
+ }
+ if (mUserPaddingEnd != UNDEFINED_PADDING) {
+ mUserPaddingLeft = mUserPaddingEnd;
+ }
+ break;
+ case LAYOUT_DIRECTION_LTR:
+ default:
+ if (mUserPaddingStart != UNDEFINED_PADDING) {
+ mUserPaddingLeft = mUserPaddingStart;
+ }
+ if (mUserPaddingEnd != UNDEFINED_PADDING) {
+ mUserPaddingRight = mUserPaddingEnd;
+ }
+ }
+
+ mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
+
+ internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
+ mUserPaddingBottom);
+ onPaddingChanged(resolvedLayoutDirection);
+ }
+
+ mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
}
/**
@@ -11380,7 +11521,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void resetResolvedLayoutDirection() {
// Reset the current resolved bits
- mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_MASK;
+ mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
onResolvedLayoutDirectionReset();
// Reset also the text direction
resetResolvedTextDirection();
@@ -11414,7 +11555,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #onAttachedToWindow()
*/
protected void onDetachedFromWindow() {
- mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
+ mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
removeUnsetPressCallback();
removeLongPressCallback();
@@ -11440,7 +11581,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
resetResolvedLayoutDirection();
resetResolvedTextAlignment();
resetAccessibilityStateChanged();
- mPrivateFlags2 &= ~PADDING_RESOLVED;
+ mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
}
/**
@@ -11482,6 +11623,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Gets the logical display to which the view's window has been attached.
+ *
+ * @return The logical display, or null if the view is not currently attached to a window.
+ */
+ public Display getDisplay() {
+ return mAttachInfo != null ? mAttachInfo.mDisplay : null;
+ }
+
+ /**
* Retrieve private session object this view hierarchy is using to
* communicate with the window manager.
* @return the session object to communicate with the window manager
@@ -11499,14 +11649,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mAttachInfo = info;
mWindowAttachCount++;
// We will need to evaluate the drawable state at least once.
- mPrivateFlags |= DRAWABLE_STATE_DIRTY;
+ mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
if (mFloatingTreeObserver != null) {
info.mTreeObserver.merge(mFloatingTreeObserver);
mFloatingTreeObserver = null;
}
- if ((mPrivateFlags&SCROLL_CONTAINER) != 0) {
+ if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
mAttachInfo.mScrollContainers.add(this);
- mPrivateFlags |= SCROLL_CONTAINER_ADDED;
+ mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
}
performCollectViewAttributes(mAttachInfo, visibility);
onAttachedToWindow();
@@ -11528,7 +11678,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (vis != GONE) {
onWindowVisibilityChanged(vis);
}
- if ((mPrivateFlags&DRAWABLE_STATE_DIRTY) != 0) {
+ if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
// If nobody has evaluated the drawable state yet, then do it now.
refreshDrawableState();
}
@@ -11558,9 +11708,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
- if ((mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0) {
+ if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
mAttachInfo.mScrollContainers.remove(this);
- mPrivateFlags &= ~SCROLL_CONTAINER_ADDED;
+ mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
}
mAttachInfo = null;
@@ -11592,9 +11742,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
- mPrivateFlags &= ~SAVE_STATE_CALLED;
+ mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
Parcelable state = onSaveInstanceState();
- if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
+ if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
throw new IllegalStateException(
"Derived class did not call super.onSaveInstanceState()");
}
@@ -11628,7 +11778,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #setSaveEnabled(boolean)
*/
protected Parcelable onSaveInstanceState() {
- mPrivateFlags |= SAVE_STATE_CALLED;
+ mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
return BaseSavedState.EMPTY_STATE;
}
@@ -11663,9 +11813,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (state != null) {
// Log.i("View", "Restoreing #" + Integer.toHexString(mID)
// + ": " + state);
- mPrivateFlags &= ~SAVE_STATE_CALLED;
+ mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
onRestoreInstanceState(state);
- if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
+ if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
throw new IllegalStateException(
"Derived class did not call super.onRestoreInstanceState()");
}
@@ -11686,7 +11836,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #dispatchRestoreInstanceState(android.util.SparseArray)
*/
protected void onRestoreInstanceState(Parcelable state) {
- mPrivateFlags |= SAVE_STATE_CALLED;
+ mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
if (state != BaseSavedState.EMPTY_STATE && state != null) {
throw new IllegalArgumentException("Wrong state class, expecting View State but "
+ "received " + state.getClass().toString() + " instead. This usually happens "
@@ -11901,7 +12051,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return null;
}
- if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
+ if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
if (mHardwareLayer == null) {
mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
width, height, isOpaque());
@@ -12031,10 +12181,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@SuppressWarnings({"UnusedDeclaration"})
public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
- Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.DIRTY_MASK) +
- ") DRAWN(" + (mPrivateFlags & DRAWN) + ")" + " CACHE_VALID(" +
- (mPrivateFlags & View.DRAWING_CACHE_VALID) +
- ") INVALIDATED(" + (mPrivateFlags & INVALIDATED) + ")");
+ Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
+ ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
+ (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
+ ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
if (clear) {
mPrivateFlags &= clearMask;
}
@@ -12098,15 +12248,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return null;
}
- if (((mPrivateFlags & DRAWING_CACHE_VALID) == 0 ||
+ if (((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 ||
displayList == null || !displayList.isValid() ||
(!isLayer && mRecreateDisplayList))) {
// Don't need to recreate the display list, just need to tell our
// children to restore/recreate theirs
if (displayList != null && displayList.isValid() &&
!isLayer && !mRecreateDisplayList) {
- mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
- mPrivateFlags &= ~DIRTY_MASK;
+ mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
+ mPrivateFlags &= ~PFLAG_DIRTY_MASK;
dispatchGetDisplayList();
return displayList;
@@ -12161,12 +12311,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
canvas.translate(-mScrollX, -mScrollY);
if (!isLayer) {
- mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
- mPrivateFlags &= ~DIRTY_MASK;
+ mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
+ mPrivateFlags &= ~PFLAG_DIRTY_MASK;
}
// Fast path for layouts with no backgrounds
- if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+ if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
dispatchDraw(canvas);
} else {
draw(canvas);
@@ -12184,8 +12334,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
} else if (!isLayer) {
- mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
- mPrivateFlags &= ~DIRTY_MASK;
+ mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
+ mPrivateFlags &= ~PFLAG_DIRTY_MASK;
}
return displayList;
@@ -12307,7 +12457,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public void setDrawingCacheBackgroundColor(int color) {
if (color != mDrawingCacheBackgroundColor) {
mDrawingCacheBackgroundColor = color;
- mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
}
}
@@ -12353,7 +12503,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #destroyDrawingCache()
*/
public void buildDrawingCache(boolean autoScale) {
- if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
+ if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
mDrawingCache == null : mUnscaledDrawingCache == null)) {
mCachingFailed = false;
@@ -12469,15 +12619,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
canvas.translate(-mScrollX, -mScrollY);
- mPrivateFlags |= DRAWN;
+ mPrivateFlags |= PFLAG_DRAWN;
if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
mLayerType != LAYER_TYPE_NONE) {
- mPrivateFlags |= DRAWING_CACHE_VALID;
+ mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
}
// Fast path for layouts with no backgrounds
- if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
- mPrivateFlags &= ~DIRTY_MASK;
+ if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
+ mPrivateFlags &= ~PFLAG_DIRTY_MASK;
dispatchDraw(canvas);
} else {
draw(canvas);
@@ -12545,10 +12695,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Temporarily remove the dirty mask
int flags = mPrivateFlags;
- mPrivateFlags &= ~DIRTY_MASK;
+ mPrivateFlags &= ~PFLAG_DIRTY_MASK;
// Fast path for layouts with no backgrounds
- if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+ if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
dispatchDraw(canvas);
} else {
draw(canvas);
@@ -12738,7 +12888,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
} else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
// The child need to draw an animation, potentially offscreen, so
// make sure we do not cancel invalidate requests
- parent.mPrivateFlags |= DRAW_ANIMATION;
+ parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
parent.invalidate(mLeft, mTop, mRight, mBottom);
}
} else {
@@ -12751,7 +12901,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// The child need to draw an animation, potentially offscreen, so
// make sure we do not cancel invalidate requests
- parent.mPrivateFlags |= DRAW_ANIMATION;
+ parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
final int left = mLeft + (int) region.left;
final int top = mTop + (int) region.top;
@@ -12813,7 +12963,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mTransformationInfo.matrix3D = new Matrix();
}
displayList.setCameraDistance(mTransformationInfo.mCamera.getLocationZ());
- if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == PIVOT_EXPLICITLY_SET) {
+ if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == PFLAG_PIVOT_EXPLICITLY_SET) {
displayList.setPivotX(getPivotX());
displayList.setPivotY(getPivotY());
}
@@ -12861,15 +13011,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
more = drawAnimation(parent, drawingTime, a, scalingRequired);
concatMatrix = a.willChangeTransformationMatrix();
if (concatMatrix) {
- mPrivateFlags3 |= VIEW_IS_ANIMATING_TRANSFORM;
+ mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
}
transformToApply = parent.mChildTransformation;
} else {
- if ((mPrivateFlags3 & VIEW_IS_ANIMATING_TRANSFORM) == VIEW_IS_ANIMATING_TRANSFORM &&
+ if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) == PFLAG3_VIEW_IS_ANIMATING_TRANSFORM &&
mDisplayList != null) {
// No longer animating: clear out old animation matrix
mDisplayList.setAnimationMatrix(null);
- mPrivateFlags3 &= ~VIEW_IS_ANIMATING_TRANSFORM;
+ mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
}
if (!useDisplayListProperties &&
(flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
@@ -12888,21 +13038,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Sets the flag as early as possible to allow draw() implementations
// to call invalidate() successfully when doing animations
- mPrivateFlags |= DRAWN;
+ mPrivateFlags |= PFLAG_DRAWN;
if (!concatMatrix && (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) == 0 &&
canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
- (mPrivateFlags & DRAW_ANIMATION) == 0) {
- mPrivateFlags2 |= VIEW_QUICK_REJECTED;
+ (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
+ mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
return more;
}
- mPrivateFlags2 &= ~VIEW_QUICK_REJECTED;
+ mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
if (hardwareAccelerated) {
// Clear INVALIDATED flag to allow invalidation to occur during rendering, but
// retain the flag's value temporarily in the mRecreateDisplayList flag
- mRecreateDisplayList = (mPrivateFlags & INVALIDATED) == INVALIDATED;
- mPrivateFlags &= ~INVALIDATED;
+ mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
+ mPrivateFlags &= ~PFLAG_INVALIDATED;
}
DisplayList displayList = null;
@@ -12986,7 +13136,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
float alpha = useDisplayListProperties ? 1 : getAlpha();
if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
- (mPrivateFlags3 & VIEW_IS_ANIMATING_ALPHA) == VIEW_IS_ANIMATING_ALPHA) {
+ (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
if (transformToApply != null || !childHasIdentityMatrix) {
int transX = 0;
int transY = 0;
@@ -13026,11 +13176,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Deal with alpha if it is or used to be <1
if (alpha < 1 ||
- (mPrivateFlags3 & VIEW_IS_ANIMATING_ALPHA) == VIEW_IS_ANIMATING_ALPHA) {
+ (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
if (alpha < 1) {
- mPrivateFlags3 |= VIEW_IS_ANIMATING_ALPHA;
+ mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
} else {
- mPrivateFlags3 &= ~VIEW_IS_ANIMATING_ALPHA;
+ mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
}
parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
if (hasNoCache) {
@@ -13051,13 +13201,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
} else {
// Alpha is handled by the child directly, clobber the layer's alpha
- mPrivateFlags |= ALPHA_SET;
+ mPrivateFlags |= PFLAG_ALPHA_SET;
}
}
}
- } else if ((mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
+ } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
onSetAlpha(255);
- mPrivateFlags &= ~ALPHA_SET;
+ mPrivateFlags &= ~PFLAG_ALPHA_SET;
}
if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN &&
@@ -13104,19 +13254,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (!layerRendered) {
if (!hasDisplayList) {
// Fast path for layouts with no backgrounds
- if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
- mPrivateFlags &= ~DIRTY_MASK;
+ if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
+ mPrivateFlags &= ~PFLAG_DIRTY_MASK;
dispatchDraw(canvas);
} else {
draw(canvas);
}
} else {
- mPrivateFlags &= ~DIRTY_MASK;
+ mPrivateFlags &= ~PFLAG_DIRTY_MASK;
((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags);
}
}
} else if (cache != null) {
- mPrivateFlags &= ~DIRTY_MASK;
+ mPrivateFlags &= ~PFLAG_DIRTY_MASK;
Paint cachePaint;
if (layerType == LAYER_TYPE_NONE) {
@@ -13156,7 +13306,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// display lists to render, force an invalidate to allow the animation to
// continue drawing another frame
parent.invalidate(true);
- if (a.hasAlpha() && (mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
+ if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
// alpha animations should cause the child to recreate its display list
invalidate(true);
}
@@ -13178,9 +13328,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void draw(Canvas canvas) {
final int privateFlags = mPrivateFlags;
- final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&
+ final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
(mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
- mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;
+ mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
/*
* Draw traversal performs several drawing steps which must be executed
@@ -13435,12 +13585,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
String output = "";
int numFlags = 0;
- if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) {
+ if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
output += "WANTS_FOCUS";
numFlags++;
}
- if ((privateFlags & FOCUSED) == FOCUSED) {
+ if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
if (numFlags > 0) {
output += " ";
}
@@ -13448,7 +13598,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
numFlags++;
}
- if ((privateFlags & SELECTED) == SELECTED) {
+ if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
if (numFlags > 0) {
output += " ";
}
@@ -13456,7 +13606,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
numFlags++;
}
- if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) {
+ if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
if (numFlags > 0) {
output += " ";
}
@@ -13464,7 +13614,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
numFlags++;
}
- if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+ if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
if (numFlags > 0) {
output += " ";
}
@@ -13472,7 +13622,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
numFlags++;
}
- if ((privateFlags & DRAWN) == DRAWN) {
+ if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
if (numFlags > 0) {
output += " ";
}
@@ -13489,7 +13639,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return true if the layout will be forced during next layout pass
*/
public boolean isLayoutRequested() {
- return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT;
+ return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
}
/**
@@ -13519,9 +13669,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
int oldB = mBottom;
int oldR = mRight;
boolean changed = setFrame(l, t, r, b);
- if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
+ if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
onLayout(changed, l, t, r, b);
- mPrivateFlags &= ~LAYOUT_REQUIRED;
+ mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnLayoutChangeListeners != null) {
@@ -13533,7 +13683,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
}
- mPrivateFlags &= ~FORCE_LAYOUT;
+ mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
}
/**
@@ -13577,7 +13727,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
changed = true;
// Remember our drawn bit
- int drawn = mPrivateFlags & DRAWN;
+ int drawn = mPrivateFlags & PFLAG_DRAWN;
int oldWidth = mRight - mLeft;
int oldHeight = mBottom - mTop;
@@ -13596,11 +13746,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
}
- mPrivateFlags |= HAS_BOUNDS;
+ mPrivateFlags |= PFLAG_HAS_BOUNDS;
if (sizeChanged) {
- if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+ if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
// A change in dimension means an auto-centered pivot point changes, too
if (mTransformationInfo != null) {
mTransformationInfo.mMatrixDirty = true;
@@ -13615,7 +13765,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// This is because someone may have invalidated this view
// before this call to setFrame came in, thereby clearing
// the DRAWN bit.
- mPrivateFlags |= DRAWN;
+ mPrivateFlags |= PFLAG_DRAWN;
invalidate(sizeChanged);
// parent display list may need to be recreated based on a change in the bounds
// of any child
@@ -13793,7 +13943,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #getDrawableState
*/
public void refreshDrawableState() {
- mPrivateFlags |= DRAWABLE_STATE_DIRTY;
+ mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
drawableStateChanged();
ViewParent parent = mParent;
@@ -13813,11 +13963,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #onCreateDrawableState(int)
*/
public final int[] getDrawableState() {
- if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
+ if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
return mDrawableState;
} else {
mDrawableState = onCreateDrawableState(0);
- mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
+ mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
return mDrawableState;
}
}
@@ -13848,12 +13998,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
int privateFlags = mPrivateFlags;
int viewStateIndex = 0;
- if ((privateFlags & PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
+ if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
- if ((privateFlags & SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
+ if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
- if ((privateFlags & ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
+ if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
HardwareRenderer.isAvailable()) {
// This is set if HW acceleration is requested, even if the current
@@ -13861,11 +14011,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// windows to better match their app.
viewStateIndex |= VIEW_STATE_ACCELERATED;
}
- if ((privateFlags & HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
+ if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
final int privateFlags2 = mPrivateFlags2;
- if ((privateFlags2 & DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
- if ((privateFlags2 & DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
+ if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
+ if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
drawableState = VIEW_STATE_SETS[viewStateIndex];
@@ -13873,10 +14023,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (false) {
Log.i("View", "drawableStateIndex=" + viewStateIndex);
Log.i("View", toString()
- + " pressed=" + ((privateFlags & PRESSED) != 0)
+ + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
+ " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
+ " fo=" + hasFocus()
- + " sl=" + ((privateFlags & SELECTED) != 0)
+ + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
+ " wf=" + hasWindowFocus()
+ ": " + Arrays.toString(drawableState));
}
@@ -14016,6 +14166,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
background.setLayoutDirection(getResolvedLayoutDirection());
if (background.getPadding(padding)) {
+ // Reset padding resolution
+ mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
switch (background.getLayoutDirection()) {
case LAYOUT_DIRECTION_RTL:
internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
@@ -14040,23 +14192,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
background.setVisible(getVisibility() == VISIBLE, false);
mBackground = background;
- if ((mPrivateFlags & SKIP_DRAW) != 0) {
- mPrivateFlags &= ~SKIP_DRAW;
- mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
+ if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
+ mPrivateFlags &= ~PFLAG_SKIP_DRAW;
+ mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
requestLayout = true;
}
} else {
/* Remove the background */
mBackground = null;
- if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
+ if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
/*
* This view ONLY drew the background before and we're removing
* the background, so now it won't draw anything
* (hence we SKIP_DRAW)
*/
- mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
- mPrivateFlags |= SKIP_DRAW;
+ mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
+ mPrivateFlags |= PFLAG_SKIP_DRAW;
}
/*
@@ -14112,13 +14264,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @param bottom the bottom padding in pixels
*/
public void setPadding(int left, int top, int right, int bottom) {
+ // Reset padding resolution
+ mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
+
mUserPaddingStart = UNDEFINED_PADDING;
mUserPaddingEnd = UNDEFINED_PADDING;
internalSetPadding(left, top, right, bottom);
}
- void internalSetPadding(int left, int top, int right, int bottom) {
+ /**
+ * @hide
+ */
+ protected void internalSetPadding(int left, int top, int right, int bottom) {
mUserPaddingLeft = left;
mUserPaddingRight = right;
mUserPaddingBottom = bottom;
@@ -14193,6 +14351,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @param bottom the bottom padding in pixels
*/
public void setPaddingRelative(int start, int top, int end, int bottom) {
+ // Reset padding resolution
+ mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
+
mUserPaddingStart = start;
mUserPaddingEnd = end;
@@ -14234,6 +14395,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the left padding in pixels
*/
public int getPaddingLeft() {
+ if (!isPaddingResolved()) {
+ resolvePadding();
+ }
return mPaddingLeft;
}
@@ -14245,6 +14409,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the start padding in pixels
*/
public int getPaddingStart() {
+ if (!isPaddingResolved()) {
+ resolvePadding();
+ }
return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
mPaddingRight : mPaddingLeft;
}
@@ -14257,6 +14424,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the right padding in pixels
*/
public int getPaddingRight() {
+ if (!isPaddingResolved()) {
+ resolvePadding();
+ }
return mPaddingRight;
}
@@ -14268,6 +14438,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the end padding in pixels
*/
public int getPaddingEnd() {
+ if (!isPaddingResolved()) {
+ resolvePadding();
+ }
return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
mPaddingLeft : mPaddingRight;
}
@@ -14310,8 +14483,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @param selected true if the view must be selected, false otherwise
*/
public void setSelected(boolean selected) {
- if (((mPrivateFlags & SELECTED) != 0) != selected) {
- mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
+ if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
+ mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
if (!selected) resetPressedState();
invalidate(true);
refreshDrawableState();
@@ -14339,7 +14512,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@ViewDebug.ExportedProperty
public boolean isSelected() {
- return (mPrivateFlags & SELECTED) != 0;
+ return (mPrivateFlags & PFLAG_SELECTED) != 0;
}
/**
@@ -14356,8 +14529,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @param activated true if the view must be activated, false otherwise
*/
public void setActivated(boolean activated) {
- if (((mPrivateFlags & ACTIVATED) != 0) != activated) {
- mPrivateFlags = (mPrivateFlags & ~ACTIVATED) | (activated ? ACTIVATED : 0);
+ if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
+ mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
invalidate(true);
refreshDrawableState();
dispatchSetActivated(activated);
@@ -14381,7 +14554,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@ViewDebug.ExportedProperty
public boolean isActivated() {
- return (mPrivateFlags & ACTIVATED) != 0;
+ return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
}
/**
@@ -14669,9 +14842,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void setIsRootNamespace(boolean isRoot) {
if (isRoot) {
- mPrivateFlags |= IS_ROOT_NAMESPACE;
+ mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
} else {
- mPrivateFlags &= ~IS_ROOT_NAMESPACE;
+ mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
}
}
@@ -14681,7 +14854,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return true if the view belongs to the root namespace, false otherwise
*/
public boolean isRootNamespace() {
- return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;
+ return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
}
/**
@@ -14830,7 +15003,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
Log.d(VIEW_LOG_TAG, output);
- if ((mPrivateFlags & FOCUSED) != 0) {
+ if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
output = debugIndent(depth) + " FOCUSED";
Log.d(VIEW_LOG_TAG, output);
}
@@ -14910,12 +15083,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* tree.
*/
public void requestLayout() {
- mPrivateFlags |= FORCE_LAYOUT;
- mPrivateFlags |= INVALIDATED;
-
- if (mLayoutParams != null) {
- mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
- }
+ mPrivateFlags |= PFLAG_FORCE_LAYOUT;
+ mPrivateFlags |= PFLAG_INVALIDATED;
if (mParent != null && !mParent.isLayoutRequested()) {
mParent.requestLayout();
@@ -14928,8 +15097,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* on the parent.
*/
public void forceLayout() {
- mPrivateFlags |= FORCE_LAYOUT;
- mPrivateFlags |= INVALIDATED;
+ mPrivateFlags |= PFLAG_FORCE_LAYOUT;
+ mPrivateFlags |= PFLAG_INVALIDATED;
}
/**
@@ -14953,14 +15122,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #onMeasure(int, int)
*/
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
- if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
+ if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
widthMeasureSpec != mOldWidthMeasureSpec ||
heightMeasureSpec != mOldHeightMeasureSpec) {
// first clears the measured dimension flag
- mPrivateFlags &= ~MEASURED_DIMENSION_SET;
+ mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
- if ((mPrivateFlags2 & PADDING_RESOLVED) == 0) {
+ if (!isPaddingResolved()) {
resolvePadding();
}
@@ -14969,13 +15138,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// flag not set, setMeasuredDimension() was not invoked, we raise
// an exception to warn the developer
- if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
+ if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
throw new IllegalStateException("onMeasure() did not set the"
+ " measured dimension by calling"
+ " setMeasuredDimension()");
}
- mPrivateFlags |= LAYOUT_REQUIRED;
+ mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
}
mOldWidthMeasureSpec = widthMeasureSpec;
@@ -15049,7 +15218,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mMeasuredWidth = measuredWidth;
mMeasuredHeight = measuredHeight;
- mPrivateFlags |= MEASURED_DIMENSION_SET;
+ mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
}
/**
@@ -15293,7 +15462,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #getAnimation()
*/
protected void onAnimationStart() {
- mPrivateFlags |= ANIMATION_STARTED;
+ mPrivateFlags |= PFLAG_ANIMATION_STARTED;
}
/**
@@ -15305,7 +15474,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #getAnimation()
*/
protected void onAnimationEnd() {
- mPrivateFlags &= ~ANIMATION_STARTED;
+ mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
}
/**
@@ -15342,14 +15511,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
final AttachInfo attachInfo = mAttachInfo;
if (region != null && attachInfo != null) {
final int pflags = mPrivateFlags;
- if ((pflags & SKIP_DRAW) == 0) {
+ if ((pflags & PFLAG_SKIP_DRAW) == 0) {
// The SKIP_DRAW flag IS NOT set, so this view draws. We need to
// remove it from the transparent region.
final int[] location = attachInfo.mTransparentLocation;
getLocationInWindow(location);
region.op(location[0], location[1], location[0] + mRight - mLeft,
location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
- } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
+ } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
// The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
// exists, so we remove the background drawable's non-transparent
// parts from this transparent region.
@@ -15826,7 +15995,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
boolean canAcceptDrag() {
- return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0;
+ return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
}
/**
@@ -16091,7 +16260,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
@ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
})
public int getTextDirection() {
- return (mPrivateFlags2 & TEXT_DIRECTION_MASK) >> TEXT_DIRECTION_MASK_SHIFT;
+ return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
}
/**
@@ -16109,10 +16278,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public void setTextDirection(int textDirection) {
if (getTextDirection() != textDirection) {
// Reset the current text direction and the resolved one
- mPrivateFlags2 &= ~TEXT_DIRECTION_MASK;
+ mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
resetResolvedTextDirection();
// Set the new text direction
- mPrivateFlags2 |= ((textDirection << TEXT_DIRECTION_MASK_SHIFT) & TEXT_DIRECTION_MASK);
+ mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
// Refresh
requestLayout();
invalidate(true);
@@ -16137,10 +16306,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public int getResolvedTextDirection() {
// The text direction will be resolved only if needed
- if ((mPrivateFlags2 & TEXT_DIRECTION_RESOLVED) != TEXT_DIRECTION_RESOLVED) {
+ if ((mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) != PFLAG2_TEXT_DIRECTION_RESOLVED) {
resolveTextDirection();
}
- return (mPrivateFlags2 & TEXT_DIRECTION_RESOLVED_MASK) >> TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
+ return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
}
/**
@@ -16149,7 +16318,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void resolveTextDirection() {
// Reset any previous text direction resolution
- mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
+ mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
if (hasRtlSupport()) {
// Set resolved text direction flag depending on text direction flag
@@ -16168,15 +16337,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
case TEXT_DIRECTION_RTL:
case TEXT_DIRECTION_LOCALE:
mPrivateFlags2 |=
- (parentResolvedDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+ (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
break;
default:
// Default resolved direction is "first strong" heuristic
- mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+ mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
}
} else {
// We cannot do the resolution if there is no parent, so use the default one
- mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+ mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
}
break;
case TEXT_DIRECTION_FIRST_STRONG:
@@ -16185,19 +16354,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
case TEXT_DIRECTION_RTL:
case TEXT_DIRECTION_LOCALE:
// Resolved direction is the same as text direction
- mPrivateFlags2 |= (textDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+ mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
break;
default:
// Default resolved direction is "first strong" heuristic
- mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+ mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
}
} else {
// Default resolved direction is "first strong" heuristic
- mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+ mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
}
// Set to resolved
- mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED;
+ mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
onResolvedTextDirectionChanged();
}
@@ -16230,7 +16399,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* reset is done.
*/
public void resetResolvedTextDirection() {
- mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
+ mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
onResolvedTextDirectionReset();
}
@@ -16266,7 +16435,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
@ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
})
public int getTextAlignment() {
- return (mPrivateFlags2 & TEXT_ALIGNMENT_MASK) >> TEXT_ALIGNMENT_MASK_SHIFT;
+ return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
}
/**
@@ -16287,10 +16456,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public void setTextAlignment(int textAlignment) {
if (textAlignment != getTextAlignment()) {
// Reset the current and resolved text alignment
- mPrivateFlags2 &= ~TEXT_ALIGNMENT_MASK;
+ mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
resetResolvedTextAlignment();
// Set the new text alignment
- mPrivateFlags2 |= ((textAlignment << TEXT_ALIGNMENT_MASK_SHIFT) & TEXT_ALIGNMENT_MASK);
+ mPrivateFlags2 |= ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
// Refresh
requestLayout();
invalidate(true);
@@ -16324,10 +16493,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
})
public int getResolvedTextAlignment() {
// If text alignment is not resolved, then resolve it
- if ((mPrivateFlags2 & TEXT_ALIGNMENT_RESOLVED) != TEXT_ALIGNMENT_RESOLVED) {
+ if ((mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) != PFLAG2_TEXT_ALIGNMENT_RESOLVED) {
resolveTextAlignment();
}
- return (mPrivateFlags2 & TEXT_ALIGNMENT_RESOLVED_MASK) >> TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+ return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >> PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
}
/**
@@ -16336,7 +16505,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void resolveTextAlignment() {
// Reset any previous text alignment resolution
- mPrivateFlags2 &= ~(TEXT_ALIGNMENT_RESOLVED | TEXT_ALIGNMENT_RESOLVED_MASK);
+ mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
if (hasRtlSupport()) {
// Set resolved text alignment flag depending on text alignment flag
@@ -16358,16 +16527,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Resolved text alignment is the same as the parent resolved
// text alignment
mPrivateFlags2 |=
- (parentResolvedTextAlignment << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
+ (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
break;
default:
// Use default resolved text alignment
- mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+ mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
}
}
else {
// We cannot do the resolution if there is no parent so use the default
- mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+ mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
}
break;
case TEXT_ALIGNMENT_GRAVITY:
@@ -16377,19 +16546,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
case TEXT_ALIGNMENT_VIEW_START:
case TEXT_ALIGNMENT_VIEW_END:
// Resolved text alignment is the same as text alignment
- mPrivateFlags2 |= (textAlignment << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
+ mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
break;
default:
// Use default resolved text alignment
- mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+ mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
}
} else {
// Use default resolved text alignment
- mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+ mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
}
// Set the resolved
- mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED;
+ mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
onResolvedTextAlignmentChanged();
}
@@ -16423,7 +16592,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void resetResolvedTextAlignment() {
// Reset any previous text alignment resolution
- mPrivateFlags2 &= ~(TEXT_ALIGNMENT_RESOLVED | TEXT_ALIGNMENT_RESOLVED_MASK);
+ mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
onResolvedTextAlignmentReset();
}
@@ -16753,7 +16922,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private final class CheckForTap implements Runnable {
public void run() {
- mPrivateFlags &= ~PREPRESSED;
+ mPrivateFlags &= ~PFLAG_PREPRESSED;
setPressed(true);
checkForLongClick(ViewConfiguration.getTapTimeout());
}
@@ -17101,6 +17270,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
final IBinder mWindowToken;
+ final Display mDisplay;
+
final Callbacks mRootCallbacks;
HardwareCanvas mHardwareCanvas;
@@ -17360,11 +17531,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* @param handler the events handler the view must use
*/
- AttachInfo(IWindowSession session, IWindow window,
+ AttachInfo(IWindowSession session, IWindow window, Display display,
ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
mSession = session;
mWindow = window;
mWindowToken = window.asBinder();
+ mDisplay = display;
mViewRootImpl = viewRootImpl;
mHandler = handler;
mRootCallbacks = effectPlayer;
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 3082976..499075e 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -279,7 +279,8 @@ public class ViewConfiguration {
mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f);
// Size of the screen in bytes, in ARGB_8888 format
- final Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
+ final WindowManager win = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+ final Display display = win.getDefaultDisplay();
final Point size = new Point();
display.getRealSize(size);
mMaximumDrawingCacheSize = 4 * size.x * size.y;
@@ -288,7 +289,7 @@ public class ViewConfiguration {
mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f);
if (!sHasPermanentMenuKeySet) {
- IWindowManager wm = WindowManagerImpl.getWindowManagerService();
+ IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
try {
sHasPermanentMenuKey = !wm.hasSystemNavBar() && !wm.hasNavigationBar();
sHasPermanentMenuKeySet = true;
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index dae9265..1286eb9 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -497,8 +497,8 @@ public class ViewDebug {
throws IOException {
long durationMeasure =
- (root || (view.mPrivateFlags & View.MEASURED_DIMENSION_SET) != 0) ? profileViewOperation(
- view, new ViewOperation<Void>() {
+ (root || (view.mPrivateFlags & View.PFLAG_MEASURED_DIMENSION_SET) != 0)
+ ? profileViewOperation(view, new ViewOperation<Void>() {
public Void[] pre() {
forceLayout(view);
return null;
@@ -524,8 +524,8 @@ public class ViewDebug {
})
: 0;
long durationLayout =
- (root || (view.mPrivateFlags & View.LAYOUT_REQUIRED) != 0) ? profileViewOperation(
- view, new ViewOperation<Void>() {
+ (root || (view.mPrivateFlags & View.PFLAG_LAYOUT_REQUIRED) != 0)
+ ? profileViewOperation(view, new ViewOperation<Void>() {
public Void[] pre() {
return null;
}
@@ -538,9 +538,8 @@ public class ViewDebug {
}
}) : 0;
long durationDraw =
- (root || !view.willNotDraw() || (view.mPrivateFlags & View.DRAWN) != 0) ? profileViewOperation(
- view,
- new ViewOperation<Object>() {
+ (root || !view.willNotDraw() || (view.mPrivateFlags & View.PFLAG_DRAWN) != 0)
+ ? profileViewOperation(view, new ViewOperation<Object>() {
public Object[] pre() {
final DisplayMetrics metrics =
(view != null && view.getResources() != null) ?
@@ -651,7 +650,7 @@ public class ViewDebug {
final boolean localVisible = view.getVisibility() == View.VISIBLE && visible;
- if ((view.mPrivateFlags & View.SKIP_DRAW) != View.SKIP_DRAW) {
+ if ((view.mPrivateFlags & View.PFLAG_SKIP_DRAW) != View.PFLAG_SKIP_DRAW) {
final int id = view.getId();
String name = view.getClass().getSimpleName();
if (id != View.NO_ID) {
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 1548743..3ab0e94 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -804,7 +804,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*/
@Override
public boolean hasFocus() {
- return (mPrivateFlags & FOCUSED) != 0 || mFocused != null;
+ return (mPrivateFlags & PFLAG_FOCUSED) != 0 || mFocused != null;
}
/*
@@ -898,7 +898,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
for (int i = 0; i < childrenCount; i++) {
View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
- && (child.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+ && (child.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
child.findViewsWithText(outViews, text, flags);
}
}
@@ -1177,7 +1177,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final View view = mCurrentDragView;
event.mAction = DragEvent.ACTION_DRAG_EXITED;
view.dispatchDragEvent(event);
- view.mPrivateFlags2 &= ~View.DRAG_HOVERED;
+ view.mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
view.refreshDrawableState();
}
mCurrentDragView = target;
@@ -1186,7 +1186,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (target != null) {
event.mAction = DragEvent.ACTION_DRAG_ENTERED;
target.dispatchDragEvent(event);
- target.mPrivateFlags2 |= View.DRAG_HOVERED;
+ target.mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
target.refreshDrawableState();
}
event.mAction = action; // restore the event's original state
@@ -1220,7 +1220,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (mCurrentDragView != null) {
final View view = mCurrentDragView;
view.dispatchDragEvent(event);
- view.mPrivateFlags2 &= ~View.DRAG_HOVERED;
+ view.mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
view.refreshDrawableState();
mCurrentDragView = null;
@@ -1281,7 +1281,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
mDragNotifiedChildren.add(child);
canAccept = child.dispatchDragEvent(mCurrentDrag);
if (canAccept && !child.canAcceptDrag()) {
- child.mPrivateFlags2 |= View.DRAG_CAN_ACCEPT;
+ child.mPrivateFlags2 |= View.PFLAG2_DRAG_CAN_ACCEPT;
child.refreshDrawableState();
}
}
@@ -1330,9 +1330,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*/
@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
- if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+ if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+ == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
return super.dispatchKeyEventPreIme(event);
- } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+ } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+ == PFLAG_HAS_BOUNDS) {
return mFocused.dispatchKeyEventPreIme(event);
}
return false;
@@ -1347,11 +1349,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
mInputEventConsistencyVerifier.onKeyEvent(event, 1);
}
- if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+ if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+ == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
if (super.dispatchKeyEvent(event)) {
return true;
}
- } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+ } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+ == PFLAG_HAS_BOUNDS) {
if (mFocused.dispatchKeyEvent(event)) {
return true;
}
@@ -1368,9 +1372,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*/
@Override
public boolean dispatchKeyShortcutEvent(KeyEvent event) {
- if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+ if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+ == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
return super.dispatchKeyShortcutEvent(event);
- } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+ } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+ == PFLAG_HAS_BOUNDS) {
return mFocused.dispatchKeyShortcutEvent(event);
}
return false;
@@ -1385,11 +1391,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
mInputEventConsistencyVerifier.onTrackballEvent(event, 1);
}
- if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+ if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+ == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
if (super.dispatchTrackballEvent(event)) {
return true;
}
- } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+ } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+ == PFLAG_HAS_BOUNDS) {
if (mFocused.dispatchTrackballEvent(event)) {
return true;
}
@@ -1715,8 +1723,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final float x = event.getX();
final float y = event.getY();
+ final boolean customOrder = isChildrenDrawingOrderEnabled();
for (int i = childrenCount - 1; i >= 0; i--) {
- final View child = children[i];
+ final int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
+ final View child = children[childIndex];
if (!canViewReceivePointerEvents(child)
|| !isTransformedTouchPointInView(x, y, child, null)) {
continue;
@@ -1738,9 +1748,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
@Override
protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
// Send the event to the focused child or to this view group if it has focus.
- if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+ if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+ == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
return super.dispatchGenericFocusedEvent(event);
- } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+ } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+ == PFLAG_HAS_BOUNDS) {
return mFocused.dispatchGenericMotionEvent(event);
}
return false;
@@ -1841,8 +1853,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final float x = ev.getX(actionIndex);
final float y = ev.getY(actionIndex);
+ final boolean customOrder = isChildrenDrawingOrderEnabled();
for (int i = childrenCount - 1; i >= 0; i--) {
- final View child = children[i];
+ final int childIndex = customOrder ?
+ getChildDrawingOrder(childrenCount, i) : i;
+ final View child = children[childIndex];
if (!canViewReceivePointerEvents(child)
|| !isTransformedTouchPointInView(x, y, child, null)) {
continue;
@@ -1860,7 +1875,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
// Child wants to receive touch within its bounds.
mLastTouchDownTime = ev.getDownTime();
- mLastTouchDownIndex = i;
+ mLastTouchDownIndex = childIndex;
mLastTouchDownX = ev.getX();
mLastTouchDownY = ev.getY();
newTouchTarget = addTouchTarget(child, idBitsToAssign);
@@ -1951,8 +1966,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* Returns true if the flag was previously set.
*/
private static boolean resetCancelNextUpFlag(View view) {
- if ((view.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
- view.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
+ if ((view.mPrivateFlags & PFLAG_CANCEL_NEXT_UP_EVENT) != 0) {
+ view.mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
return true;
}
return false;
@@ -2517,8 +2532,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
super.dispatchDetachedFromWindow();
}
+ /**
+ * @hide
+ */
@Override
- void internalSetPadding(int left, int top, int right, int bottom) {
+ protected void internalSetPadding(int left, int top, int right, int bottom) {
super.internalSetPadding(left, top, right, bottom);
if ((mPaddingLeft | mPaddingTop | mPaddingRight | mPaddingBottom) != 0) {
@@ -2766,7 +2784,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
// We will draw our child's animation, let's reset the flag
- mPrivateFlags &= ~DRAW_ANIMATION;
+ mPrivateFlags &= ~PFLAG_DRAW_ANIMATION;
mGroupFlags &= ~FLAG_INVALIDATE_REQUIRED;
boolean more = false;
@@ -2886,8 +2904,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final View child = children[i];
if (((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) &&
child.hasStaticLayer()) {
- child.mRecreateDisplayList = (child.mPrivateFlags & INVALIDATED) == INVALIDATED;
- child.mPrivateFlags &= ~INVALIDATED;
+ child.mRecreateDisplayList = (child.mPrivateFlags & PFLAG_INVALIDATED)
+ == PFLAG_INVALIDATED;
+ child.mPrivateFlags &= ~PFLAG_INVALIDATED;
child.getDisplayList();
child.mRecreateDisplayList = false;
}
@@ -3030,7 +3049,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
for (int i = 0; i < len; i++) {
View v = where[i];
- if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+ if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
v = v.findViewById(id);
if (v != null) {
@@ -3057,7 +3076,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
for (int i = 0; i < len; i++) {
View v = where[i];
- if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+ if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
v = v.findViewWithTag(tag);
if (v != null) {
@@ -3084,7 +3103,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
for (int i = 0; i < len; i++) {
View v = where[i];
- if (v != childToSkip && (v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+ if (v != childToSkip && (v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
v = v.findViewByPredicate(predicate);
if (v != null) {
@@ -3294,7 +3313,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
boolean preventRequestLayout) {
child.mParent = null;
addViewInner(child, index, params, preventRequestLayout);
- child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK) | DRAWN;
+ child.mPrivateFlags = (child.mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
return true;
}
@@ -3304,7 +3323,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @param child the child on which to perform the cleanup
*/
protected void cleanupLayoutState(View child) {
- child.mPrivateFlags &= ~View.FORCE_LAYOUT;
+ child.mPrivateFlags &= ~View.PFLAG_FORCE_LAYOUT;
}
private void addViewInner(View child, int index, LayoutParams params,
@@ -3372,6 +3391,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (child.hasTransientState()) {
childHasTransientStateChanged(child, true);
}
+
+ if (child.getLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
+ child.resetResolvedLayoutDirection();
+ child.resolveRtlProperties();
+ }
}
private void addInArray(View child, int index) {
@@ -3597,6 +3621,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
childHasTransientStateChanged(view, false);
}
+ view.resetResolvedLayoutDirection();
+
onViewRemoved(view);
needGlobalAttributesUpdate(false);
@@ -3844,9 +3870,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
addInArray(child, index);
child.mParent = this;
- child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK & ~DRAWING_CACHE_VALID) |
- DRAWN | INVALIDATED;
- this.mPrivateFlags |= INVALIDATED;
+ child.mPrivateFlags = (child.mPrivateFlags & ~PFLAG_DIRTY_MASK
+ & ~PFLAG_DRAWING_CACHE_VALID)
+ | PFLAG_DRAWN | PFLAG_INVALIDATED;
+ this.mPrivateFlags |= PFLAG_INVALIDATED;
if (child.hasFocus()) {
requestChildFocus(child, child.findFocus());
@@ -3947,7 +3974,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
// If the child is drawing an animation, we want to copy this flag onto
// ourselves and the parent to make sure the invalidate request goes
// through
- final boolean drawAnimation = (child.mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION;
+ final boolean drawAnimation = (child.mPrivateFlags & PFLAG_DRAW_ANIMATION)
+ == PFLAG_DRAW_ANIMATION;
// Check whether the child that requests the invalidate is fully opaque
// Views being animated or transformed are not considered opaque because we may
@@ -3957,11 +3985,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
child.getAnimation() == null && childMatrix.isIdentity();
// Mark the child as dirty, using the appropriate flag
// Make sure we do not set both flags at the same time
- int opaqueFlag = isOpaque ? DIRTY_OPAQUE : DIRTY;
+ int opaqueFlag = isOpaque ? PFLAG_DIRTY_OPAQUE : PFLAG_DIRTY;
if (child.mLayerType != LAYER_TYPE_NONE) {
- mPrivateFlags |= INVALIDATED;
- mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ mPrivateFlags |= PFLAG_INVALIDATED;
+ mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
child.mLocalDirtyRect.union(dirty);
}
@@ -4003,7 +4031,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (drawAnimation) {
if (view != null) {
- view.mPrivateFlags |= DRAW_ANIMATION;
+ view.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
} else if (parent instanceof ViewRootImpl) {
((ViewRootImpl) parent).mIsAnimating = true;
}
@@ -4014,10 +4042,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (view != null) {
if ((view.mViewFlags & FADING_EDGE_MASK) != 0 &&
view.getSolidColor() == 0) {
- opaqueFlag = DIRTY;
+ opaqueFlag = PFLAG_DIRTY;
}
- if ((view.mPrivateFlags & DIRTY_MASK) != DIRTY) {
- view.mPrivateFlags = (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag;
+ if ((view.mPrivateFlags & PFLAG_DIRTY_MASK) != PFLAG_DIRTY) {
+ view.mPrivateFlags = (view.mPrivateFlags & ~PFLAG_DIRTY_MASK) | opaqueFlag;
}
}
@@ -4048,8 +4076,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* does not intersect with this ViewGroup's bounds.
*/
public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {
- if ((mPrivateFlags & DRAWN) == DRAWN ||
- (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
+ if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN ||
+ (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) {
if ((mGroupFlags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) !=
FLAG_OPTIMIZE_INVALIDATE) {
dirty.offset(location[CHILD_LEFT_INDEX] - mScrollX,
@@ -4063,20 +4091,20 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
dirty.setEmpty();
}
}
- mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
location[CHILD_LEFT_INDEX] = left;
location[CHILD_TOP_INDEX] = top;
if (mLayerType != LAYER_TYPE_NONE) {
- mPrivateFlags |= INVALIDATED;
+ mPrivateFlags |= PFLAG_INVALIDATED;
mLocalDirtyRect.union(dirty);
}
return mParent;
} else {
- mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID;
+ mPrivateFlags &= ~PFLAG_DRAWN & ~PFLAG_DRAWING_CACHE_VALID;
location[CHILD_LEFT_INDEX] = mLeft;
location[CHILD_TOP_INDEX] = mTop;
@@ -4088,7 +4116,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
if (mLayerType != LAYER_TYPE_NONE) {
- mPrivateFlags |= INVALIDATED;
+ mPrivateFlags |= PFLAG_INVALIDATED;
mLocalDirtyRect.union(dirty);
}
@@ -4150,8 +4178,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* coordinate system, pruning the invalidation if the parent has already been invalidated.
*/
private ViewParent invalidateChildInParentFast(int left, int top, final Rect dirty) {
- if ((mPrivateFlags & DRAWN) == DRAWN ||
- (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
+ if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN ||
+ (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) {
dirty.offset(left - mScrollX, top - mScrollY);
if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0 ||
@@ -4914,11 +4942,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
view.clearAnimation();
}
- if ((view.mPrivateFlags & ANIMATION_STARTED) == ANIMATION_STARTED) {
+ if ((view.mPrivateFlags & PFLAG_ANIMATION_STARTED) == PFLAG_ANIMATION_STARTED) {
view.onAnimationEnd();
// Should be performed by onAnimationEnd() but this avoid an infinite loop,
// so we'd rather be safe than sorry
- view.mPrivateFlags &= ~ANIMATION_STARTED;
+ view.mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
// Draw one more frame after the animation is done
mGroupFlags |= FLAG_INVALIDATE_REQUIRED;
}
@@ -5017,7 +5045,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
@Override
public boolean gatherTransparentRegion(Region region) {
// If no transparent regions requested, we are always opaque.
- final boolean meOpaque = (mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) == 0;
+ final boolean meOpaque = (mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0;
if (meOpaque && region == null) {
// The caller doesn't care about the region, so stop now.
return true;
@@ -5042,7 +5070,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*/
public void requestTransparentRegion(View child) {
if (child != null) {
- child.mPrivateFlags |= View.REQUEST_TRANSPARENT_REGIONS;
+ child.mPrivateFlags |= View.PFLAG_REQUEST_TRANSPARENT_REGIONS;
if (mParent != null) {
mParent.requestTransparentRegion(this);
}
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index ce6f4c5..d8db14c 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -1036,7 +1036,7 @@ public class ViewPropertyAnimator {
if ((propertyMask & TRANSFORM_MASK) != 0) {
mView.mTransformationInfo.mMatrixDirty = true;
if (!useDisplayListProperties) {
- mView.mPrivateFlags |= View.DRAWN; // force another invalidation
+ mView.mPrivateFlags |= View.PFLAG_DRAWN; // force another invalidation
}
}
// invalidate(false) in all cases except if alphaHandled gets set to true
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index afcbaaf..725d9b5 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -18,7 +18,6 @@ package android.view;
import android.Manifest;
import android.animation.LayoutTransition;
-import android.animation.ValueAnimator;
import android.app.ActivityManagerNative;
import android.content.ClipDescription;
import android.content.ComponentCallbacks;
@@ -88,7 +87,7 @@ import java.util.HashSet;
/**
* The top of a view hierarchy, implementing the needed protocol between View
* and the WindowManager. This is for the most part an internal implementation
- * detail of {@link WindowManagerImpl}.
+ * detail of {@link WindowManagerGlobal}.
*
* {@hide}
*/
@@ -126,11 +125,6 @@ public final class ViewRootImpl implements ViewParent,
*/
static final int MAX_TRACKBALL_DELAY = 250;
- static IWindowSession sWindowSession;
-
- static final Object mStaticInit = new Object();
- static boolean mInitialized = false;
-
static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<RunQueue>();
static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList<Runnable>();
@@ -143,6 +137,9 @@ public final class ViewRootImpl implements ViewParent,
private static boolean sRenderThreadQueried = false;
private static final Object[] sRenderThreadQueryLock = new Object[0];
+ final IWindowSession mWindowSession;
+ final Display mDisplay;
+
long mLastTrackballTime = 0;
final TrackballAxis mTrackballAxisX = new TrackballAxis();
final TrackballAxis mTrackballAxisY = new TrackballAxis();
@@ -250,7 +247,7 @@ public final class ViewRootImpl implements ViewParent,
boolean mAdded;
boolean mAddedTouchMode;
- CompatibilityInfoHolder mCompatibilityInfo;
+ final CompatibilityInfoHolder mCompatibilityInfo;
// These are accessed by multiple threads.
final Rect mWinFrame; // frame given by window manager.
@@ -322,24 +319,6 @@ public final class ViewRootImpl implements ViewParent,
InputEventConsistencyVerifier.isInstrumentationEnabled() ?
new InputEventConsistencyVerifier(this, 0) : null;
- public static IWindowSession getWindowSession(Looper mainLooper) {
- synchronized (mStaticInit) {
- if (!mInitialized) {
- try {
- InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
- IWindowManager windowManager = WindowManagerImpl.getWindowManagerService();
- sWindowSession = windowManager.openSession(
- imm.getClient(), imm.getInputContext());
- float animatorScale = windowManager.getAnimationScale(2);
- ValueAnimator.setDurationScale(animatorScale);
- mInitialized = true;
- } catch (RemoteException e) {
- }
- }
- return sWindowSession;
- }
- }
-
static final class SystemUiVisibilityInfo {
int seq;
int globalVisibility;
@@ -347,7 +326,7 @@ public final class ViewRootImpl implements ViewParent,
int localChanges;
}
- public ViewRootImpl(Context context) {
+ public ViewRootImpl(Context context, Display display) {
super();
if (MEASURE_LATENCY) {
@@ -359,7 +338,11 @@ public final class ViewRootImpl implements ViewParent,
// Initialize the statics when this class is first instantiated. This is
// done here instead of in the static block because Zygote does not
// allow the spawning of threads.
- getWindowSession(context.getMainLooper());
+ mWindowSession = WindowManagerGlobal.getWindowSession(context.getMainLooper());
+ mDisplay = display;
+
+ CompatibilityInfoHolder cih = display.getCompatibilityInfo();
+ mCompatibilityInfo = cih != null ? cih : new CompatibilityInfoHolder();
mThread = Thread.currentThread();
mLocation = new WindowLeaked(null);
@@ -383,7 +366,7 @@ public final class ViewRootImpl implements ViewParent,
new AccessibilityInteractionConnectionManager();
mAccessibilityManager.addAccessibilityStateChangeListener(
mAccessibilityInteractionConnectionManager);
- mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, mHandler, this);
+ mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
mViewConfiguration = ViewConfiguration.get(context);
mDensity = context.getResources().getDisplayMetrics().densityDpi;
mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
@@ -460,9 +443,10 @@ public final class ViewRootImpl implements ViewParent,
* @hide
*/
static boolean isInTouchMode() {
- if (mInitialized) {
+ IWindowSession windowSession = WindowManagerGlobal.peekWindowSession();
+ if (windowSession != null) {
try {
- return sWindowSession.getInTouchMode();
+ return windowSession.getInTouchMode();
} catch (RemoteException e) {
}
}
@@ -541,8 +525,8 @@ public final class ViewRootImpl implements ViewParent,
mOrigWindowType = mWindowAttributes.type;
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
- res = sWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
- getHostVisibility(), Display.DEFAULT_DISPLAY,
+ res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
+ getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mInputChannel);
} catch (RemoteException e) {
mAdded = false;
@@ -565,7 +549,7 @@ public final class ViewRootImpl implements ViewParent,
mPendingContentInsets.set(mAttachInfo.mContentInsets);
mPendingVisibleInsets.set(0, 0, 0, 0);
if (DEBUG_LAYOUT) Log.v(TAG, "Added window " + mWindow);
- if (res < WindowManagerImpl.ADD_OKAY) {
+ if (res < WindowManagerGlobal.ADD_OKAY) {
mView = null;
mAttachInfo.mRootView = null;
mAdded = false;
@@ -573,33 +557,33 @@ public final class ViewRootImpl implements ViewParent,
unscheduleTraversals();
setAccessibilityFocus(null, null);
switch (res) {
- case WindowManagerImpl.ADD_BAD_APP_TOKEN:
- case WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN:
- throw new WindowManagerImpl.BadTokenException(
+ case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
+ case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
+ throw new WindowManager.BadTokenException(
"Unable to add window -- token " + attrs.token
+ " is not valid; is your activity running?");
- case WindowManagerImpl.ADD_NOT_APP_TOKEN:
- throw new WindowManagerImpl.BadTokenException(
+ case WindowManagerGlobal.ADD_NOT_APP_TOKEN:
+ throw new WindowManager.BadTokenException(
"Unable to add window -- token " + attrs.token
+ " is not for an application");
- case WindowManagerImpl.ADD_APP_EXITING:
- throw new WindowManagerImpl.BadTokenException(
+ case WindowManagerGlobal.ADD_APP_EXITING:
+ throw new WindowManager.BadTokenException(
"Unable to add window -- app for token " + attrs.token
+ " is exiting");
- case WindowManagerImpl.ADD_DUPLICATE_ADD:
- throw new WindowManagerImpl.BadTokenException(
+ case WindowManagerGlobal.ADD_DUPLICATE_ADD:
+ throw new WindowManager.BadTokenException(
"Unable to add window -- window " + mWindow
+ " has already been added");
- case WindowManagerImpl.ADD_STARTING_NOT_NEEDED:
+ case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED:
// Silently ignore -- we would have just removed it
// right away, anyway.
return;
- case WindowManagerImpl.ADD_MULTIPLE_SINGLETON:
- throw new WindowManagerImpl.BadTokenException(
+ case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON:
+ throw new WindowManager.BadTokenException(
"Unable to add window " + mWindow +
" -- another window of this type already exists");
- case WindowManagerImpl.ADD_PERMISSION_DENIED:
- throw new WindowManagerImpl.BadTokenException(
+ case WindowManagerGlobal.ADD_PERMISSION_DENIED:
+ throw new WindowManager.BadTokenException(
"Unable to add window " + mWindow +
" -- permission denied for this window type");
}
@@ -622,8 +606,8 @@ public final class ViewRootImpl implements ViewParent,
}
view.assignParent(this);
- mAddedTouchMode = (res&WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE) != 0;
- mAppVisible = (res&WindowManagerImpl.ADD_FLAG_APP_VISIBLE) != 0;
+ mAddedTouchMode = (res & WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE) != 0;
+ mAppVisible = (res & WindowManagerGlobal.ADD_FLAG_APP_VISIBLE) != 0;
if (mAccessibilityManager.isEnabled()) {
mAccessibilityInteractionConnectionManager.ensureConnection();
@@ -1164,9 +1148,8 @@ public final class ViewRootImpl implements ViewParent,
if (lp.type == WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL) {
// NOTE -- system code, won't try to do compat mode.
- Display disp = WindowManagerImpl.getDefault().getDefaultDisplay();
Point size = new Point();
- disp.getRealSize(size);
+ mDisplay.getRealSize(size);
desiredWindowWidth = size.x;
desiredWindowHeight = size.y;
} else {
@@ -1251,9 +1234,8 @@ public final class ViewRootImpl implements ViewParent,
if (lp.type == WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL) {
// NOTE -- system code, won't try to do compat mode.
- Display disp = WindowManagerImpl.getDefault().getDefaultDisplay();
Point size = new Point();
- disp.getRealSize(size);
+ mDisplay.getRealSize(size);
desiredWindowWidth = size.x;
desiredWindowHeight = size.y;
} else {
@@ -1303,7 +1285,7 @@ public final class ViewRootImpl implements ViewParent,
}
}
- if (params != null && (host.mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) != 0) {
+ if (params != null && (host.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
if (!PixelFormat.formatHasAlpha(params.format)) {
params.format = PixelFormat.TRANSLUCENT;
}
@@ -1502,7 +1484,7 @@ public final class ViewRootImpl implements ViewParent,
} catch (Surface.OutOfResourcesException e) {
Log.e(TAG, "OutOfResourcesException initializing HW surface", e);
try {
- if (!sWindowSession.outOfMemory(mWindow)) {
+ if (!mWindowSession.outOfMemory(mWindow)) {
Slog.w(TAG, "No processes killed for memory; killing self");
Process.killProcess(Process.myPid());
}
@@ -1535,7 +1517,7 @@ public final class ViewRootImpl implements ViewParent,
} catch (Surface.OutOfResourcesException e) {
Log.e(TAG, "OutOfResourcesException updating HW surface", e);
try {
- if (!sWindowSession.outOfMemory(mWindow)) {
+ if (!mWindowSession.outOfMemory(mWindow)) {
Slog.w(TAG, "No processes killed for memory; killing self");
Process.killProcess(Process.myPid());
}
@@ -1629,7 +1611,7 @@ public final class ViewRootImpl implements ViewParent,
if (!mStopped) {
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
- (relayoutResult&WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
+ (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
|| mHeight != host.getMeasuredHeight() || contentInsetsChanged) {
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
@@ -1709,7 +1691,7 @@ public final class ViewRootImpl implements ViewParent,
// By this point all views have been sized and positionned
// We can compute the transparent area
- if ((host.mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) != 0) {
+ if ((host.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
// start out transparent
// TODO: AVOID THAT CALL BY CACHING THE RESULT?
host.getLocationInWindow(mTmpLocation);
@@ -1726,7 +1708,7 @@ public final class ViewRootImpl implements ViewParent,
mPreviousTransparentRegion.set(mTransparentRegion);
// reconfigure window manager
try {
- sWindowSession.setTransparentRegion(mWindow, mTransparentRegion);
+ mWindowSession.setTransparentRegion(mWindow, mTransparentRegion);
} catch (RemoteException e) {
}
}
@@ -1775,7 +1757,7 @@ public final class ViewRootImpl implements ViewParent,
}
try {
- sWindowSession.setInsets(mWindow, insets.mTouchableInsets,
+ mWindowSession.setInsets(mWindow, insets.mTouchableInsets,
contentInsets, visibleInsets, touchableRegion);
} catch (RemoteException e) {
}
@@ -1800,7 +1782,7 @@ public final class ViewRootImpl implements ViewParent,
+ mRealFocusedView);
}
}
- if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_ANIMATING) != 0) {
+ if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_ANIMATING) != 0) {
// The first time we relayout the window, if the system is
// doing window animations, we want to hold of on any future
// draws until the animation is done.
@@ -1831,7 +1813,7 @@ public final class ViewRootImpl implements ViewParent,
}
// Remember if we must report the next draw.
- if ((relayoutResult & WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
+ if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
mReportNextDraw = true;
}
@@ -1893,7 +1875,7 @@ public final class ViewRootImpl implements ViewParent,
// the test below should not fail unless someone is messing with us
checkThread();
if (mView == child) {
- mView.mPrivateFlags |= View.REQUEST_TRANSPARENT_REGIONS;
+ mView.mPrivateFlags |= View.PFLAG_REQUEST_TRANSPARENT_REGIONS;
// Need to make sure we re-evaluate the window attributes next
// time around, to ensure the window has the correct format.
mWindowAttributesChanged = true;
@@ -2061,7 +2043,7 @@ public final class ViewRootImpl implements ViewParent,
}
}
try {
- sWindowSession.finishDrawing(mWindow);
+ mWindowSession.finishDrawing(mWindow);
} catch (RemoteException e) {
}
}
@@ -2217,7 +2199,7 @@ public final class ViewRootImpl implements ViewParent,
} catch (Surface.OutOfResourcesException e) {
Log.e(TAG, "OutOfResourcesException locking surface", e);
try {
- if (!sWindowSession.outOfMemory(mWindow)) {
+ if (!mWindowSession.outOfMemory(mWindow)) {
Slog.w(TAG, "No processes killed for memory; killing self");
Process.killProcess(Process.myPid());
}
@@ -2256,7 +2238,7 @@ public final class ViewRootImpl implements ViewParent,
dirty.setEmpty();
mIsAnimating = false;
attachInfo.mDrawingTime = SystemClock.uptimeMillis();
- mView.mPrivateFlags |= View.DRAWN;
+ mView.mPrivateFlags |= View.PFLAG_DRAWN;
if (DEBUG_DRAW) {
Context cxt = mView.getContext();
@@ -2646,7 +2628,7 @@ public final class ViewRootImpl implements ViewParent,
mInputEventReceiver = null;
}
try {
- sWindowSession.remove(mWindow);
+ mWindowSession.remove(mWindow);
} catch (RemoteException e) {
}
@@ -2891,7 +2873,7 @@ public final class ViewRootImpl implements ViewParent,
} catch (Surface.OutOfResourcesException e) {
Log.e(TAG, "OutOfResourcesException locking surface", e);
try {
- if (!sWindowSession.outOfMemory(mWindow)) {
+ if (!mWindowSession.outOfMemory(mWindow)) {
Slog.w(TAG, "No processes killed for memory; killing self");
Process.killProcess(Process.myPid());
}
@@ -3036,7 +3018,7 @@ public final class ViewRootImpl implements ViewParent,
// tell the window manager
try {
- sWindowSession.setInTouchMode(inTouchMode);
+ mWindowSession.setInTouchMode(inTouchMode);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
@@ -3750,10 +3732,10 @@ public final class ViewRootImpl implements ViewParent,
if (prevDragView != mCurrentDragView) {
try {
if (prevDragView != null) {
- sWindowSession.dragRecipientExited(mWindow);
+ mWindowSession.dragRecipientExited(mWindow);
}
if (mCurrentDragView != null) {
- sWindowSession.dragRecipientEntered(mWindow);
+ mWindowSession.dragRecipientEntered(mWindow);
}
} catch (RemoteException e) {
Slog.e(TAG, "Unable to note drag target change");
@@ -3765,7 +3747,7 @@ public final class ViewRootImpl implements ViewParent,
mDragDescription = null;
try {
Log.i(TAG, "Reporting drop result: " + result);
- sWindowSession.reportDropResult(mWindow, result);
+ mWindowSession.reportDropResult(mWindow, result);
} catch (RemoteException e) {
Log.e(TAG, "Unable to report drop result");
}
@@ -3867,11 +3849,11 @@ public final class ViewRootImpl implements ViewParent,
params.type = mOrigWindowType;
}
}
- int relayoutResult = sWindowSession.relayout(
+ int relayoutResult = mWindowSession.relayout(
mWindow, mSeq, params,
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f),
- viewVisibility, insetsPending ? WindowManagerImpl.RELAYOUT_INSETS_PENDING : 0,
+ viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
mWinFrame, mPendingContentInsets, mPendingVisibleInsets,
mPendingConfiguration, mSurface);
//Log.d(TAG, "<<<<<< BACK FROM relayout");
@@ -3928,7 +3910,7 @@ public final class ViewRootImpl implements ViewParent,
*/
public boolean performHapticFeedback(int effectId, boolean always) {
try {
- return sWindowSession.performHapticFeedback(mWindow, effectId, always);
+ return mWindowSession.performHapticFeedback(mWindow, effectId, always);
} catch (RemoteException e) {
return false;
}
@@ -4007,8 +3989,8 @@ public final class ViewRootImpl implements ViewParent,
// animation info.
try {
if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
- & WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
- sWindowSession.finishDrawing(mWindow);
+ & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
+ mWindowSession.finishDrawing(mWindow);
}
} catch (RemoteException e) {
}
@@ -4726,9 +4708,11 @@ public final class ViewRootImpl implements ViewParent,
static class W extends IWindow.Stub {
private final WeakReference<ViewRootImpl> mViewAncestor;
+ private final IWindowSession mWindowSession;
W(ViewRootImpl viewAncestor) {
mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
+ mWindowSession = viewAncestor.mWindowSession;
}
public void resized(Rect frame, Rect contentInsets,
@@ -4827,7 +4811,7 @@ public final class ViewRootImpl implements ViewParent,
boolean sync) {
if (sync) {
try {
- sWindowSession.wallpaperOffsetsComplete(asBinder());
+ mWindowSession.wallpaperOffsetsComplete(asBinder());
} catch (RemoteException e) {
}
}
@@ -4837,7 +4821,7 @@ public final class ViewRootImpl implements ViewParent,
int z, Bundle extras, boolean sync) {
if (sync) {
try {
- sWindowSession.wallpaperCommandComplete(asBinder(), null);
+ mWindowSession.wallpaperCommandComplete(asBinder(), null);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index f57f056..a242895 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -16,7 +16,6 @@
package android.view;
-import android.app.Application;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
@@ -455,7 +454,7 @@ public abstract class Window {
* display panels. This is <em>not</em> used for displaying the
* Window itself -- that must be done by the client.
*
- * @param wm The ViewManager for adding new windows.
+ * @param wm The window manager for adding new windows.
*/
public void setWindowManager(WindowManager wm, IBinder appToken, String appName) {
setWindowManager(wm, appToken, appName, false);
@@ -466,7 +465,7 @@ public abstract class Window {
* display panels. This is <em>not</em> used for displaying the
* Window itself -- that must be done by the client.
*
- * @param wm The ViewManager for adding new windows.
+ * @param wm The window manager for adding new windows.
*/
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
@@ -475,14 +474,9 @@ public abstract class Window {
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
if (wm == null) {
- wm = WindowManagerImpl.getDefault();
+ wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
- mWindowManager = ((WindowManagerImpl)wm).makeLocal(this);
- }
-
- CompatibilityInfoHolder getCompatibilityInfo() {
- Application app = (Application)mContext.getApplicationContext();
- return app != null ? app.mLoadedApk.mCompatibilityInfo : null;
+ mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
void adjustLayoutParamsForSubWindow(WindowManager.LayoutParams wp) {
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
new file mode 100644
index 0000000..7855763c
--- /dev/null
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.animation.ValueAnimator;
+import android.app.ActivityManager;
+import android.content.ComponentCallbacks2;
+import android.content.res.Configuration;
+import android.opengl.ManagedEGLContext;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.util.AndroidRuntimeException;
+import android.util.Log;
+import android.view.inputmethod.InputMethodManager;
+
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+
+/**
+ * Provides low-level communication with the system window manager for
+ * operations that are not associated with any particular context.
+ *
+ * This class is only used internally to implement global functions where
+ * the caller already knows the display and relevant compatibility information
+ * for the operation. For most purposes, you should use {@link WindowManager} instead
+ * since it is bound to a context.
+ *
+ * @see WindowManagerImpl
+ * @hide
+ */
+public final class WindowManagerGlobal {
+ private static final String TAG = "WindowManager";
+
+ /**
+ * The user is navigating with keys (not the touch screen), so
+ * navigational focus should be shown.
+ */
+ public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1;
+
+ /**
+ * This is the first time the window is being drawn,
+ * so the client must call drawingFinished() when done
+ */
+ public static final int RELAYOUT_RES_FIRST_TIME = 0x2;
+
+ /**
+ * The window manager has changed the surface from the last call.
+ */
+ public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4;
+
+ /**
+ * The window manager is currently animating. It will call
+ * IWindow.doneAnimating() when done.
+ */
+ public static final int RELAYOUT_RES_ANIMATING = 0x8;
+
+ /**
+ * Flag for relayout: the client will be later giving
+ * internal insets; as a result, the window will not impact other window
+ * layouts until the insets are given.
+ */
+ public static final int RELAYOUT_INSETS_PENDING = 0x1;
+
+ /**
+ * Flag for relayout: the client may be currently using the current surface,
+ * so if it is to be destroyed as a part of the relayout the destroy must
+ * be deferred until later. The client will call performDeferredDestroy()
+ * when it is okay.
+ */
+ public static final int RELAYOUT_DEFER_SURFACE_DESTROY = 0x2;
+
+ public static final int ADD_FLAG_APP_VISIBLE = 0x2;
+ public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_RES_IN_TOUCH_MODE;
+
+ public static final int ADD_OKAY = 0;
+ public static final int ADD_BAD_APP_TOKEN = -1;
+ public static final int ADD_BAD_SUBWINDOW_TOKEN = -2;
+ public static final int ADD_NOT_APP_TOKEN = -3;
+ public static final int ADD_APP_EXITING = -4;
+ public static final int ADD_DUPLICATE_ADD = -5;
+ public static final int ADD_STARTING_NOT_NEEDED = -6;
+ public static final int ADD_MULTIPLE_SINGLETON = -7;
+ public static final int ADD_PERMISSION_DENIED = -8;
+
+ private static WindowManagerGlobal sDefaultWindowManager;
+ private static IWindowManager sWindowManagerService;
+ private static IWindowSession sWindowSession;
+
+ private final Object mLock = new Object();
+
+ private View[] mViews;
+ private ViewRootImpl[] mRoots;
+ private WindowManager.LayoutParams[] mParams;
+ private boolean mNeedsEglTerminate;
+
+ private Runnable mSystemPropertyUpdater;
+
+ private WindowManagerGlobal() {
+ }
+
+ public static WindowManagerGlobal getInstance() {
+ synchronized (WindowManagerGlobal.class) {
+ if (sDefaultWindowManager == null) {
+ sDefaultWindowManager = new WindowManagerGlobal();
+ }
+ return sDefaultWindowManager;
+ }
+ }
+
+ public static IWindowManager getWindowManagerService() {
+ synchronized (WindowManagerGlobal.class) {
+ if (sWindowManagerService == null) {
+ sWindowManagerService = IWindowManager.Stub.asInterface(
+ ServiceManager.getService("window"));
+ }
+ return sWindowManagerService;
+ }
+ }
+
+ public static IWindowSession getWindowSession(Looper mainLooper) {
+ synchronized (WindowManagerGlobal.class) {
+ if (sWindowSession == null) {
+ try {
+ InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
+ IWindowManager windowManager = getWindowManagerService();
+ sWindowSession = windowManager.openSession(
+ imm.getClient(), imm.getInputContext());
+ float animatorScale = windowManager.getAnimationScale(2);
+ ValueAnimator.setDurationScale(animatorScale);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to open window session", e);
+ }
+ }
+ return sWindowSession;
+ }
+ }
+
+ public static IWindowSession peekWindowSession() {
+ synchronized (WindowManagerGlobal.class) {
+ return sWindowSession;
+ }
+ }
+
+ public void addView(View view, ViewGroup.LayoutParams params,
+ Display display, Window parentWindow) {
+ if (view == null) {
+ throw new IllegalArgumentException("view must not be null");
+ }
+ if (display == null) {
+ throw new IllegalArgumentException("display must not be null");
+ }
+ if (!(params instanceof WindowManager.LayoutParams)) {
+ throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
+ }
+
+ final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
+ if (parentWindow != null) {
+ parentWindow.adjustLayoutParamsForSubWindow(wparams);
+ }
+
+ ViewRootImpl root;
+ View panelParentView = null;
+
+ synchronized (mLock) {
+ // Start watching for system property changes.
+ if (mSystemPropertyUpdater == null) {
+ mSystemPropertyUpdater = new Runnable() {
+ @Override public void run() {
+ synchronized (mLock) {
+ for (ViewRootImpl root : mRoots) {
+ root.loadSystemProperties();
+ }
+ }
+ }
+ };
+ SystemProperties.addChangeCallback(mSystemPropertyUpdater);
+ }
+
+ int index = findViewLocked(view, false);
+ if (index >= 0) {
+ throw new IllegalStateException("View " + view
+ + " has already been added to the window manager.");
+ }
+
+ // If this is a panel window, then find the window it is being
+ // attached to for future reference.
+ if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
+ wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+ final int count = mViews != null ? mViews.length : 0;
+ for (int i=0; i<count; i++) {
+ if (mRoots[i].mWindow.asBinder() == wparams.token) {
+ panelParentView = mViews[i];
+ }
+ }
+ }
+
+ root = new ViewRootImpl(view.getContext(), display);
+
+ view.setLayoutParams(wparams);
+
+ if (mViews == null) {
+ index = 1;
+ mViews = new View[1];
+ mRoots = new ViewRootImpl[1];
+ mParams = new WindowManager.LayoutParams[1];
+ } else {
+ index = mViews.length + 1;
+ Object[] old = mViews;
+ mViews = new View[index];
+ System.arraycopy(old, 0, mViews, 0, index-1);
+ old = mRoots;
+ mRoots = new ViewRootImpl[index];
+ System.arraycopy(old, 0, mRoots, 0, index-1);
+ old = mParams;
+ mParams = new WindowManager.LayoutParams[index];
+ System.arraycopy(old, 0, mParams, 0, index-1);
+ }
+ index--;
+
+ mViews[index] = view;
+ mRoots[index] = root;
+ mParams[index] = wparams;
+ }
+
+ // do this last because it fires off messages to start doing things
+ root.setView(view, wparams, panelParentView);
+ }
+
+ public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
+ if (view == null) {
+ throw new IllegalArgumentException("view must not be null");
+ }
+ if (!(params instanceof WindowManager.LayoutParams)) {
+ throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
+ }
+
+ final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
+
+ view.setLayoutParams(wparams);
+
+ synchronized (mLock) {
+ int index = findViewLocked(view, true);
+ ViewRootImpl root = mRoots[index];
+ mParams[index] = wparams;
+ root.setLayoutParams(wparams, false);
+ }
+ }
+
+ public void removeView(View view, boolean immediate) {
+ if (view == null) {
+ throw new IllegalArgumentException("view must not be null");
+ }
+
+ synchronized (mLock) {
+ int index = findViewLocked(view, true);
+ View curView = removeViewLocked(index, immediate);
+ if (curView == view) {
+ return;
+ }
+
+ throw new IllegalStateException("Calling with view " + view
+ + " but the ViewAncestor is attached to " + curView);
+ }
+ }
+
+ public void closeAll(IBinder token, String who, String what) {
+ synchronized (mLock) {
+ if (mViews == null)
+ return;
+
+ int count = mViews.length;
+ //Log.i("foo", "Closing all windows of " + token);
+ for (int i=0; i<count; i++) {
+ //Log.i("foo", "@ " + i + " token " + mParams[i].token
+ // + " view " + mRoots[i].getView());
+ if (token == null || mParams[i].token == token) {
+ ViewRootImpl root = mRoots[i];
+
+ //Log.i("foo", "Force closing " + root);
+ if (who != null) {
+ WindowLeaked leak = new WindowLeaked(
+ what + " " + who + " has leaked window "
+ + root.getView() + " that was originally added here");
+ leak.setStackTrace(root.getLocation().getStackTrace());
+ Log.e(TAG, leak.getMessage(), leak);
+ }
+
+ removeViewLocked(i, false);
+ i--;
+ count--;
+ }
+ }
+ }
+ }
+
+ private View removeViewLocked(int index, boolean immediate) {
+ ViewRootImpl root = mRoots[index];
+ View view = root.getView();
+
+ if (view != null) {
+ InputMethodManager imm = InputMethodManager.getInstance(view.getContext());
+ if (imm != null) {
+ imm.windowDismissed(mViews[index].getWindowToken());
+ }
+ }
+ root.die(immediate);
+
+ final int count = mViews.length;
+
+ // remove it from the list
+ View[] tmpViews = new View[count-1];
+ removeItem(tmpViews, mViews, index);
+ mViews = tmpViews;
+
+ ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1];
+ removeItem(tmpRoots, mRoots, index);
+ mRoots = tmpRoots;
+
+ WindowManager.LayoutParams[] tmpParams
+ = new WindowManager.LayoutParams[count-1];
+ removeItem(tmpParams, mParams, index);
+ mParams = tmpParams;
+
+ if (view != null) {
+ view.assignParent(null);
+ // func doesn't allow null... does it matter if we clear them?
+ //view.setLayoutParams(null);
+ }
+ return view;
+ }
+
+ private static void removeItem(Object[] dst, Object[] src, int index) {
+ if (dst.length > 0) {
+ if (index > 0) {
+ System.arraycopy(src, 0, dst, 0, index);
+ }
+ if (index < dst.length) {
+ System.arraycopy(src, index+1, dst, index, src.length-index-1);
+ }
+ }
+ }
+
+ private int findViewLocked(View view, boolean required) {
+ synchronized (mLock) {
+ if (mViews != null) {
+ final int count = mViews.length;
+ for (int i = 0; i < count; i++) {
+ if (mViews[i] == view) {
+ return i;
+ }
+ }
+ }
+ if (required) {
+ throw new IllegalArgumentException("View not attached to window manager");
+ }
+ return -1;
+ }
+ }
+
+ public void startTrimMemory(int level) {
+ if (HardwareRenderer.isAvailable()) {
+ // On low-end gfx devices we trim when memory is moderate;
+ // on high-end devices we do this when low.
+ if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
+ || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE
+ && !ActivityManager.isHighEndGfx())) {
+ // Destroy all hardware surfaces and resources associated to
+ // known windows
+ synchronized (mLock) {
+ if (mViews == null) return;
+ int count = mViews.length;
+ for (int i = 0; i < count; i++) {
+ mRoots[i].terminateHardwareResources();
+ }
+ }
+ // Force a full memory flush
+ mNeedsEglTerminate = true;
+ HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
+ return;
+ }
+
+ HardwareRenderer.startTrimMemory(level);
+ }
+ }
+
+ public void endTrimMemory() {
+ HardwareRenderer.endTrimMemory();
+
+ if (mNeedsEglTerminate) {
+ ManagedEGLContext.doTerminate();
+ mNeedsEglTerminate = false;
+ }
+ }
+
+ public void trimLocalMemory() {
+ synchronized (mLock) {
+ if (mViews == null) return;
+ int count = mViews.length;
+ for (int i = 0; i < count; i++) {
+ mRoots[i].destroyHardwareLayers();
+ }
+ }
+ }
+
+ public void dumpGfxInfo(FileDescriptor fd) {
+ FileOutputStream fout = new FileOutputStream(fd);
+ PrintWriter pw = new PrintWriter(fout);
+ try {
+ synchronized (mLock) {
+ if (mViews != null) {
+ final int count = mViews.length;
+
+ pw.println("Profile data in ms:");
+
+ for (int i = 0; i < count; i++) {
+ ViewRootImpl root = mRoots[i];
+ String name = getWindowName(root);
+ pw.printf("\n\t%s", name);
+
+ HardwareRenderer renderer =
+ root.getView().mAttachInfo.mHardwareRenderer;
+ if (renderer != null) {
+ renderer.dumpGfxInfo(pw);
+ }
+ }
+
+ pw.println("\nView hierarchy:\n");
+
+ int viewsCount = 0;
+ int displayListsSize = 0;
+ int[] info = new int[2];
+
+ for (int i = 0; i < count; i++) {
+ ViewRootImpl root = mRoots[i];
+ root.dumpGfxInfo(info);
+
+ String name = getWindowName(root);
+ pw.printf(" %s\n %d views, %.2f kB of display lists",
+ name, info[0], info[1] / 1024.0f);
+ HardwareRenderer renderer =
+ root.getView().mAttachInfo.mHardwareRenderer;
+ if (renderer != null) {
+ pw.printf(", %d frames rendered", renderer.getFrameCount());
+ }
+ pw.printf("\n\n");
+
+ viewsCount += info[0];
+ displayListsSize += info[1];
+ }
+
+ pw.printf("\nTotal ViewRootImpl: %d\n", count);
+ pw.printf("Total Views: %d\n", viewsCount);
+ pw.printf("Total DisplayList: %.2f kB\n\n", displayListsSize / 1024.0f);
+ }
+ }
+ } finally {
+ pw.flush();
+ }
+ }
+
+ private static String getWindowName(ViewRootImpl root) {
+ return root.mWindowAttributes.getTitle() + "/" +
+ root.getClass().getName() + '@' + Integer.toHexString(root.hashCode());
+ }
+
+ public void setStoppedState(IBinder token, boolean stopped) {
+ synchronized (mLock) {
+ if (mViews != null) {
+ int count = mViews.length;
+ for (int i=0; i < count; i++) {
+ if (token == null || mParams[i].token == token) {
+ ViewRootImpl root = mRoots[i];
+ root.setStopped(stopped);
+ }
+ }
+ }
+ }
+ }
+
+ public void reportNewConfiguration(Configuration config) {
+ synchronized (mLock) {
+ if (mViews != null) {
+ int count = mViews.length;
+ config = new Configuration(config);
+ for (int i=0; i < count; i++) {
+ ViewRootImpl root = mRoots[i];
+ root.requestUpdateConfiguration(config);
+ }
+ }
+ }
+ }
+}
+
+final class WindowLeaked extends AndroidRuntimeException {
+ public WindowLeaked(String msg) {
+ super(msg);
+ }
+}
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index bd95cdb..bf061df 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -16,34 +16,20 @@
package android.view;
-import android.app.ActivityManager;
-import android.content.ComponentCallbacks2;
-import android.content.res.Configuration;
-import android.opengl.ManagedEGLContext;
-import android.os.IBinder;
-import android.os.ServiceManager;
-import android.os.SystemProperties;
-import android.util.AndroidRuntimeException;
-import android.util.Log;
-import android.view.inputmethod.InputMethodManager;
-
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.PrintWriter;
-
-final class WindowLeaked extends AndroidRuntimeException {
- public WindowLeaked(String msg) {
- super(msg);
- }
-}
+import android.content.Context;
+import android.hardware.display.DisplayManager;
/**
- * Low-level communication with the global system window manager. It implements
- * the ViewManager interface, allowing you to add any View subclass as a
- * top-level window on the screen. Additional window manager specific layout
- * parameters are defined for control over how windows are displayed.
- * It also implements the WindowManager interface, allowing you to control the
- * displays attached to the device.
+ * Provides low-level communication with the system window manager for
+ * operations that are bound to a particular context, display or parent window.
+ * Instances of this object are sensitive to the compatibility info associated
+ * with the running application.
+ *
+ * This object implements the {@link ViewManager} interface,
+ * allowing you to add any View subclass as a top-level window on the screen.
+ * Additional window manager specific layout parameters are defined for
+ * control over how windows are displayed. It also implements the {@link WindowManager}
+ * interface, allowing you to control the displays attached to the device.
*
* <p>Applications will not normally use WindowManager directly, instead relying
* on the higher-level facilities in {@link android.app.Activity} and
@@ -51,531 +37,58 @@ final class WindowLeaked extends AndroidRuntimeException {
*
* <p>Even for low-level window manager access, it is almost never correct to use
* this class. For example, {@link android.app.Activity#getWindowManager}
- * provides a ViewManager for adding windows that are associated with that
+ * provides a window manager for adding windows that are associated with that
* activity -- the window manager will not normally allow you to add arbitrary
* windows that are not associated with an activity.
- *
+ *
+ * @see WindowManager
+ * @see WindowManagerGlobal
* @hide
*/
-public class WindowManagerImpl implements WindowManager {
- private static final String TAG = "WindowManager";
-
- /**
- * The user is navigating with keys (not the touch screen), so
- * navigational focus should be shown.
- */
- public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1;
-
- /**
- * This is the first time the window is being drawn,
- * so the client must call drawingFinished() when done
- */
- public static final int RELAYOUT_RES_FIRST_TIME = 0x2;
-
- /**
- * The window manager has changed the surface from the last call.
- */
- public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4;
-
- /**
- * The window manager is currently animating. It will call
- * IWindow.doneAnimating() when done.
- */
- public static final int RELAYOUT_RES_ANIMATING = 0x8;
-
- /**
- * Flag for relayout: the client will be later giving
- * internal insets; as a result, the window will not impact other window
- * layouts until the insets are given.
- */
- public static final int RELAYOUT_INSETS_PENDING = 0x1;
-
- /**
- * Flag for relayout: the client may be currently using the current surface,
- * so if it is to be destroyed as a part of the relayout the destroy must
- * be deferred until later. The client will call performDeferredDestroy()
- * when it is okay.
- */
- public static final int RELAYOUT_DEFER_SURFACE_DESTROY = 0x2;
-
- public static final int ADD_FLAG_APP_VISIBLE = 0x2;
- public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_RES_IN_TOUCH_MODE;
-
- public static final int ADD_OKAY = 0;
- public static final int ADD_BAD_APP_TOKEN = -1;
- public static final int ADD_BAD_SUBWINDOW_TOKEN = -2;
- public static final int ADD_NOT_APP_TOKEN = -3;
- public static final int ADD_APP_EXITING = -4;
- public static final int ADD_DUPLICATE_ADD = -5;
- public static final int ADD_STARTING_NOT_NEEDED = -6;
- public static final int ADD_MULTIPLE_SINGLETON = -7;
- public static final int ADD_PERMISSION_DENIED = -8;
-
- private static WindowManagerImpl sDefaultWindowManager;
- private static IWindowManager sWindowManagerService;
-
- private final WindowManagerState mState;
+public final class WindowManagerImpl implements WindowManager {
+ private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
+ private final Context mContext;
+ private final Display mDisplay;
private final Window mParentWindow;
- private final CompatibilityInfoHolder mCompatibilityInfo;
- private final Display mDefaultDisplay;
- private WindowManagerImpl(WindowManagerState state, Window parentWindow,
- CompatibilityInfoHolder compatibilityInfo) {
- mState = state;
- mParentWindow = parentWindow;
- mCompatibilityInfo = compatibilityInfo;
- mDefaultDisplay = mState.getDefaultDisplay(mCompatibilityInfo);
+ public WindowManagerImpl(Context context, int displayId) {
+ mContext = context;
+ mDisplay = DisplayManager.getInstance().getDisplay(displayId, mContext);
+ mParentWindow = null;
}
- public static WindowManagerImpl getDefault() {
- synchronized (WindowManagerImpl.class) {
- if (sDefaultWindowManager == null) {
- sDefaultWindowManager = new WindowManagerImpl(
- new WindowManagerState(), null, null);
- }
- return sDefaultWindowManager;
- }
- }
-
- public static IWindowManager getWindowManagerService() {
- synchronized (WindowManagerImpl.class) {
- if (sWindowManagerService == null) {
- sWindowManagerService = IWindowManager.Stub.asInterface(
- ServiceManager.getService("window"));
- }
- return sWindowManagerService;
- }
- }
-
- public WindowManagerImpl makeLocal(Window parentWindow) {
- return new WindowManagerImpl(mState, parentWindow, parentWindow.getCompatibilityInfo());
+ private WindowManagerImpl(Context context, Display display, Window parentWindow) {
+ mContext = context;
+ mDisplay = display;
+ mParentWindow = parentWindow;
}
- public WindowManagerImpl makeCompatible(CompatibilityInfoHolder compatInfo) {
- if (compatInfo == mCompatibilityInfo) {
- return this;
- }
- if (compatInfo == null && mParentWindow == null) {
- return getDefault();
- }
- return new WindowManagerImpl(mState, mParentWindow, compatInfo);
+ public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
+ return new WindowManagerImpl(mContext, mDisplay, parentWindow);
}
@Override
public void addView(View view, ViewGroup.LayoutParams params) {
- mState.addView(view, params, mParentWindow, mCompatibilityInfo);
+ mGlobal.addView(view, params, mDisplay, mParentWindow);
}
@Override
public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
- mState.updateViewLayout(view, params);
+ mGlobal.updateViewLayout(view, params);
}
@Override
public void removeView(View view) {
- mState.removeView(view, false);
+ mGlobal.removeView(view, false);
}
@Override
public void removeViewImmediate(View view) {
- mState.removeView(view, true);
+ mGlobal.removeView(view, true);
}
@Override
public Display getDefaultDisplay() {
- return mDefaultDisplay;
- }
-
- public void closeAll(IBinder token, String who, String what) {
- mState.closeAll(token, who, what);
- }
-
- public void startTrimMemory(int level) {
- mState.startTrimMemory(level);
- }
-
- public void endTrimMemory() {
- mState.endTrimMemory();
- }
-
- public void trimLocalMemory() {
- mState.trimLocalMemory();
- }
-
- public void dumpGfxInfo(FileDescriptor fd) {
- mState.dumpGfxInfo(fd);
- }
-
- public void setStoppedState(IBinder token, boolean stopped) {
- mState.setStoppedState(token, stopped);
- }
-
- public void reportNewConfiguration(Configuration config) {
- mState.reportNewConfiguration(config);
- }
-
- static final class WindowManagerState {
- private final Display mDefaultDisplay;
-
- private View[] mViews;
- private ViewRootImpl[] mRoots;
- private WindowManager.LayoutParams[] mParams;
- private boolean mNeedsEglTerminate;
-
- private Runnable mSystemPropertyUpdater;
-
- public WindowManagerState() {
- mDefaultDisplay = new Display(Display.DEFAULT_DISPLAY, null);
- }
-
- public Display getDefaultDisplay(CompatibilityInfoHolder compatInfo) {
- if (compatInfo == null) {
- return mDefaultDisplay;
- }
- return new Display(Display.DEFAULT_DISPLAY, compatInfo);
- }
-
- public void addView(View view, ViewGroup.LayoutParams params, Window parentWindow,
- CompatibilityInfoHolder cih) {
- if (!(params instanceof WindowManager.LayoutParams)) {
- throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
- }
-
- final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
- if (parentWindow != null) {
- parentWindow.adjustLayoutParamsForSubWindow(wparams);
- }
-
- ViewRootImpl root;
- View panelParentView = null;
-
- synchronized (this) {
- // Start watching for system property changes.
- if (mSystemPropertyUpdater == null) {
- mSystemPropertyUpdater = new Runnable() {
- @Override public void run() {
- synchronized (this) {
- synchronized (this) {
- for (ViewRootImpl root : mRoots) {
- root.loadSystemProperties();
- }
- }
- }
- }
- };
- SystemProperties.addChangeCallback(mSystemPropertyUpdater);
- }
-
- int index = findViewLocked(view, false);
- if (index >= 0) {
- throw new IllegalStateException("View " + view
- + " has already been added to the window manager.");
- }
-
- // If this is a panel window, then find the window it is being
- // attached to for future reference.
- if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
- wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
- final int count = mViews != null ? mViews.length : 0;
- for (int i=0; i<count; i++) {
- if (mRoots[i].mWindow.asBinder() == wparams.token) {
- panelParentView = mViews[i];
- }
- }
- }
-
- root = new ViewRootImpl(view.getContext());
- if (cih == null) {
- root.mCompatibilityInfo = new CompatibilityInfoHolder();
- } else {
- root.mCompatibilityInfo = cih;
- }
-
- view.setLayoutParams(wparams);
-
- if (mViews == null) {
- index = 1;
- mViews = new View[1];
- mRoots = new ViewRootImpl[1];
- mParams = new WindowManager.LayoutParams[1];
- } else {
- index = mViews.length + 1;
- Object[] old = mViews;
- mViews = new View[index];
- System.arraycopy(old, 0, mViews, 0, index-1);
- old = mRoots;
- mRoots = new ViewRootImpl[index];
- System.arraycopy(old, 0, mRoots, 0, index-1);
- old = mParams;
- mParams = new WindowManager.LayoutParams[index];
- System.arraycopy(old, 0, mParams, 0, index-1);
- }
- index--;
-
- mViews[index] = view;
- mRoots[index] = root;
- mParams[index] = wparams;
- }
-
- // do this last because it fires off messages to start doing things
- root.setView(view, wparams, panelParentView);
- }
-
- public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
- if (!(params instanceof WindowManager.LayoutParams)) {
- throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
- }
-
- final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
-
- view.setLayoutParams(wparams);
-
- synchronized (this) {
- int index = findViewLocked(view, true);
- ViewRootImpl root = mRoots[index];
- mParams[index] = wparams;
- root.setLayoutParams(wparams, false);
- }
- }
-
- public void removeView(View view, boolean immediate) {
- synchronized (this) {
- int index = findViewLocked(view, true);
- View curView = removeViewLocked(index, immediate);
- if (curView == view) {
- return;
- }
-
- throw new IllegalStateException("Calling with view " + view
- + " but the ViewAncestor is attached to " + curView);
- }
- }
-
- public void closeAll(IBinder token, String who, String what) {
- synchronized (this) {
- if (mViews == null)
- return;
-
- int count = mViews.length;
- //Log.i("foo", "Closing all windows of " + token);
- for (int i=0; i<count; i++) {
- //Log.i("foo", "@ " + i + " token " + mParams[i].token
- // + " view " + mRoots[i].getView());
- if (token == null || mParams[i].token == token) {
- ViewRootImpl root = mRoots[i];
-
- //Log.i("foo", "Force closing " + root);
- if (who != null) {
- WindowLeaked leak = new WindowLeaked(
- what + " " + who + " has leaked window "
- + root.getView() + " that was originally added here");
- leak.setStackTrace(root.getLocation().getStackTrace());
- Log.e(TAG, leak.getMessage(), leak);
- }
-
- removeViewLocked(i, false);
- i--;
- count--;
- }
- }
- }
- }
-
- private View removeViewLocked(int index, boolean immediate) {
- ViewRootImpl root = mRoots[index];
- View view = root.getView();
-
- if (view != null) {
- InputMethodManager imm = InputMethodManager.getInstance(view.getContext());
- if (imm != null) {
- imm.windowDismissed(mViews[index].getWindowToken());
- }
- }
- root.die(immediate);
-
- final int count = mViews.length;
-
- // remove it from the list
- View[] tmpViews = new View[count-1];
- removeItem(tmpViews, mViews, index);
- mViews = tmpViews;
-
- ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1];
- removeItem(tmpRoots, mRoots, index);
- mRoots = tmpRoots;
-
- WindowManager.LayoutParams[] tmpParams
- = new WindowManager.LayoutParams[count-1];
- removeItem(tmpParams, mParams, index);
- mParams = tmpParams;
-
- if (view != null) {
- view.assignParent(null);
- // func doesn't allow null... does it matter if we clear them?
- //view.setLayoutParams(null);
- }
- return view;
- }
-
- private static void removeItem(Object[] dst, Object[] src, int index) {
- if (dst.length > 0) {
- if (index > 0) {
- System.arraycopy(src, 0, dst, 0, index);
- }
- if (index < dst.length) {
- System.arraycopy(src, index+1, dst, index, src.length-index-1);
- }
- }
- }
-
- private int findViewLocked(View view, boolean required) {
- synchronized (this) {
- if (mViews != null) {
- final int count = mViews.length;
- for (int i = 0; i < count; i++) {
- if (mViews[i] == view) {
- return i;
- }
- }
- }
- if (required) {
- throw new IllegalArgumentException("View not attached to window manager");
- }
- return -1;
- }
- }
-
- public void startTrimMemory(int level) {
- if (HardwareRenderer.isAvailable()) {
- // On low-end gfx devices we trim when memory is moderate;
- // on high-end devices we do this when low.
- if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
- || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE
- && !ActivityManager.isHighEndGfx(mDefaultDisplay))) {
- // Destroy all hardware surfaces and resources associated to
- // known windows
- synchronized (this) {
- if (mViews == null) return;
- int count = mViews.length;
- for (int i = 0; i < count; i++) {
- mRoots[i].terminateHardwareResources();
- }
- }
- // Force a full memory flush
- mNeedsEglTerminate = true;
- HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
- return;
- }
-
- HardwareRenderer.startTrimMemory(level);
- }
- }
-
- public void endTrimMemory() {
- HardwareRenderer.endTrimMemory();
-
- if (mNeedsEglTerminate) {
- ManagedEGLContext.doTerminate();
- mNeedsEglTerminate = false;
- }
- }
-
- public void trimLocalMemory() {
- synchronized (this) {
- if (mViews == null) return;
- int count = mViews.length;
- for (int i = 0; i < count; i++) {
- mRoots[i].destroyHardwareLayers();
- }
- }
- }
-
- public void dumpGfxInfo(FileDescriptor fd) {
- FileOutputStream fout = new FileOutputStream(fd);
- PrintWriter pw = new PrintWriter(fout);
- try {
- synchronized (this) {
- if (mViews != null) {
- final int count = mViews.length;
-
- pw.println("Profile data in ms:");
-
- for (int i = 0; i < count; i++) {
- ViewRootImpl root = mRoots[i];
- String name = getWindowName(root);
- pw.printf("\n\t%s", name);
-
- HardwareRenderer renderer =
- root.getView().mAttachInfo.mHardwareRenderer;
- if (renderer != null) {
- renderer.dumpGfxInfo(pw);
- }
- }
-
- pw.println("\nView hierarchy:\n");
-
- int viewsCount = 0;
- int displayListsSize = 0;
- int[] info = new int[2];
-
- for (int i = 0; i < count; i++) {
- ViewRootImpl root = mRoots[i];
- root.dumpGfxInfo(info);
-
- String name = getWindowName(root);
- pw.printf(" %s\n %d views, %.2f kB of display lists",
- name, info[0], info[1] / 1024.0f);
- HardwareRenderer renderer =
- root.getView().mAttachInfo.mHardwareRenderer;
- if (renderer != null) {
- pw.printf(", %d frames rendered", renderer.getFrameCount());
- }
- pw.printf("\n\n");
-
- viewsCount += info[0];
- displayListsSize += info[1];
- }
-
- pw.printf("\nTotal ViewRootImpl: %d\n", count);
- pw.printf("Total Views: %d\n", viewsCount);
- pw.printf("Total DisplayList: %.2f kB\n\n", displayListsSize / 1024.0f);
- }
- }
- } finally {
- pw.flush();
- }
- }
-
- private static String getWindowName(ViewRootImpl root) {
- return root.mWindowAttributes.getTitle() + "/" +
- root.getClass().getName() + '@' + Integer.toHexString(root.hashCode());
- }
-
- public void setStoppedState(IBinder token, boolean stopped) {
- synchronized (this) {
- if (mViews != null) {
- int count = mViews.length;
- for (int i=0; i < count; i++) {
- if (token == null || mParams[i].token == token) {
- ViewRootImpl root = mRoots[i];
- root.setStopped(stopped);
- }
- }
- }
- }
- }
-
- public void reportNewConfiguration(Configuration config) {
- synchronized (this) {
- if (mViews != null) {
- int count = mViews.length;
- config = new Configuration(config);
- for (int i=0; i < count; i++) {
- ViewRootImpl root = mRoots[i];
- root.requestUpdateConfiguration(config);
- }
- }
- }
- }
+ return mDisplay;
}
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 7aa3bb4..7173d1d 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -390,8 +390,8 @@ public interface WindowManagerPolicy {
*/
public void switchKeyboardLayout(int deviceId, int direction);
- public void shutdown();
- public void rebootSafeMode();
+ public void shutdown(boolean confirm);
+ public void rebootSafeMode(boolean confirm);
}
/**
@@ -487,9 +487,9 @@ public interface WindowManagerPolicy {
*
* @param attrs The window's LayoutParams.
*
- * @return {@link WindowManagerImpl#ADD_OKAY} if the add can proceed;
+ * @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed;
* else an error code, usually
- * {@link WindowManagerImpl#ADD_PERMISSION_DENIED}, to abort the add.
+ * {@link WindowManagerGlobal#ADD_PERMISSION_DENIED}, to abort the add.
*/
public int checkAddPermission(WindowManager.LayoutParams attrs);
@@ -662,7 +662,7 @@ public interface WindowManagerPolicy {
* @param win The window being added.
* @param attrs The window's LayoutParams.
*
- * @return {@link WindowManagerImpl#ADD_OKAY} if the add can proceed, else an
+ * @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed, else an
* error code to abort the add.
*/
public int prepareAddWindowLw(WindowState win,
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 193e98d..e8ff01f 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -16,8 +16,7 @@
package android.webkit;
-import android.os.Message;
-import android.os.Build;
+import android.content.Context;
/**
* Manages settings state for a WebView. When a WebView is first created, it
@@ -422,7 +421,7 @@ public abstract class WebSettings {
* Gets the text zoom of the page in percent.
*
* @return the text zoom of the page in percent
- * @see #setTextSizeZoom
+ * @see #setTextZoom
*/
public synchronized int getTextZoom() {
throw new MustOverrideException();
@@ -435,7 +434,7 @@ public abstract class WebSettings {
* @deprecated Use {@link #setTextZoom} instead.
*/
public synchronized void setTextSize(TextSize t) {
- throw new MustOverrideException();
+ setTextZoom(t.value);
}
/**
@@ -448,7 +447,20 @@ public abstract class WebSettings {
* @deprecated Use {@link #getTextZoom} instead.
*/
public synchronized TextSize getTextSize() {
- throw new MustOverrideException();
+ TextSize closestSize = null;
+ int smallestDelta = Integer.MAX_VALUE;
+ int textSize = getTextZoom();
+ for (TextSize size : TextSize.values()) {
+ int delta = Math.abs(textSize - size.value);
+ if (delta == 0) {
+ return size;
+ }
+ if (delta < smallestDelta) {
+ smallestDelta = delta;
+ closestSize = size;
+ }
+ }
+ return closestSize != null ? closestSize : TextSize.NORMAL;
}
/**
@@ -1226,6 +1238,18 @@ public abstract class WebSettings {
}
/**
+ * Returns the default User-Agent used by a WebView.
+ * An instance of WebView could use a different User-Agent if a call
+ * is made to {@link WebSettings#setUserAgent(int)} or
+ * {@link WebSettings#setUserAgentString(String)}.
+ *
+ * @param context a Context object used to access application assets
+ */
+ public static String getDefaultUserAgent(Context context) {
+ return WebViewFactory.getProvider().getStatics().getDefaultUserAgent(context);
+ }
+
+ /**
* Tells the WebView whether it needs to set a node to have focus when
* {@link WebView#requestFocus(int, android.graphics.Rect)} is called. The
* default value is true.
diff --git a/core/java/android/webkit/WebSettingsClassic.java b/core/java/android/webkit/WebSettingsClassic.java
index 66651f7..d1f8b4b 100644
--- a/core/java/android/webkit/WebSettingsClassic.java
+++ b/core/java/android/webkit/WebSettingsClassic.java
@@ -374,6 +374,21 @@ public class WebSettingsClassic extends WebSettings {
synchronized(sLockForLocaleSettings) {
locale = sLocale;
}
+ return getDefaultUserAgentForLocale(mContext, locale);
+ }
+
+ /**
+ * Returns the default User-Agent used by a WebView.
+ * An instance of WebView could use a different User-Agent if a call
+ * is made to {@link WebSettings#setUserAgent(int)} or
+ * {@link WebSettings#setUserAgentString(String)}.
+ *
+ * @param context a Context object used to access application assets
+ * @param locale The Locale to use in the User-Agent string.
+ * @see WebViewFactoryProvider#getDefaultUserAgent(Context)
+ * @see WebView#getDefaultUserAgent(Context)
+ */
+ public static String getDefaultUserAgentForLocale(Context context, Locale locale) {
StringBuffer buffer = new StringBuffer();
// Add version
final String version = Build.VERSION.RELEASE;
@@ -417,9 +432,9 @@ public class WebSettingsClassic extends WebSettings {
buffer.append(" Build/");
buffer.append(id);
}
- String mobile = mContext.getResources().getText(
+ String mobile = context.getResources().getText(
com.android.internal.R.string.web_user_agent_target_content).toString();
- final String base = mContext.getResources().getText(
+ final String base = context.getResources().getText(
com.android.internal.R.string.web_user_agent).toString();
return String.format(base, buffer, mobile);
}
@@ -650,34 +665,6 @@ public class WebSettingsClassic extends WebSettings {
}
/**
- * @see android.webkit.WebSettings#setTextSize(android.webkit.WebSettingsClassic.TextSize)
- */
- @Override
- public synchronized void setTextSize(TextSize t) {
- setTextZoom(t.value);
- }
-
- /**
- * @see android.webkit.WebSettings#getTextSize()
- */
- @Override
- public synchronized TextSize getTextSize() {
- TextSize closestSize = null;
- int smallestDelta = Integer.MAX_VALUE;
- for (TextSize size : TextSize.values()) {
- int delta = Math.abs(mTextSize - size.value);
- if (delta == 0) {
- return size;
- }
- if (delta < smallestDelta) {
- smallestDelta = delta;
- closestSize = size;
- }
- }
- return closestSize != null ? closestSize : TextSize.NORMAL;
- }
-
- /**
* Set the double-tap zoom of the page in percent. Default is 100.
* @param doubleTapZoom A percent value for increasing or decreasing the double-tap zoom.
*/
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index a5420bb..436762d 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1403,7 +1403,6 @@ public class WebView extends AbsoluteLayout
* @return the address, or if no address is found, null
*/
public static String findAddress(String addr) {
- checkThread();
return getFactory().getStatics().findAddress(addr);
}
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 8d79492..9df4852 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -132,6 +132,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
@@ -1308,6 +1309,12 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
public WebViewDatabase getWebViewDatabase(Context context) {
return WebViewDatabaseClassic.getInstance(context);
}
+
+ @Override
+ public String getDefaultUserAgent(Context context) {
+ return WebSettingsClassic.getDefaultUserAgentForLocale(context,
+ Locale.getDefault());
+ }
}
private void onHandleUiEvent(MotionEvent event, int eventType, int flags) {
@@ -6441,9 +6448,13 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
mWebViewPrivate.getVerticalScrollFactor());
final int hdelta = (int) (hscroll *
mWebViewPrivate.getHorizontalScrollFactor());
- if (pinScrollBy(hdelta, vdelta, false, 0)) {
- return true;
- }
+
+ abortAnimation();
+ int oldTouchMode = mTouchMode;
+ startScrollingLayer(event.getX(), event.getY());
+ doDrag(hdelta, vdelta);
+ mTouchMode = oldTouchMode;
+ return true;
}
}
}
@@ -7279,11 +7290,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
// nativeCreate sets mNativeClass to a non-zero value
String drawableDir = BrowserFrame.getRawResFilename(
BrowserFrame.DRAWABLEDIR, mContext);
- WindowManager windowManager =
- (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
- Display display = windowManager.getDefaultDisplay();
- nativeCreate(msg.arg1, drawableDir,
- ActivityManager.isHighEndGfx(display));
+ nativeCreate(msg.arg1, drawableDir, ActivityManager.isHighEndGfx());
if (mDelaySetPicture != null) {
setNewPicture(mDelaySetPicture, true);
mDelaySetPicture = null;
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index 1d302f1..934ef83 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -42,6 +42,12 @@ public interface WebViewFactoryProvider {
* {@link android.webkit.WebView#disablePlatformNotifications()}
*/
void setPlatformNotificationsEnabled(boolean enable);
+
+ /**
+ * Implements the API method:
+ * {@link android.webkit.WebSettings#getDefaultUserAgent(Context) }
+ */
+ String getDefaultUserAgent(Context context);
}
Statics getStatics();
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 46079f9..f91201a 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -151,7 +151,7 @@ public class CheckedTextView extends TextView implements Checkable {
mCheckMarkWidth = 0;
}
mCheckMarkDrawable = d;
- // Do padding resolution. This will call setPadding() and do a requestLayout() if needed.
+ // Do padding resolution. This will call internalSetPadding() and do a requestLayout() if needed.
resolvePadding();
}
@@ -169,6 +169,19 @@ public class CheckedTextView extends TextView implements Checkable {
return mCheckMarkDrawable;
}
+ /**
+ * @hide
+ */
+ @Override
+ protected void internalSetPadding(int left, int top, int right, int bottom) {
+ super.internalSetPadding(left, top, right, bottom);
+ if (isLayoutRtl()) {
+ mBasePadding = mUserPaddingLeft;
+ } else {
+ mBasePadding = mUserPaddingRight;
+ }
+ }
+
@Override
public void onPaddingChanged(int layoutDirection) {
int newPadding = (mCheckMarkDrawable != null) ?
@@ -221,8 +234,15 @@ public class CheckedTextView extends TextView implements Checkable {
final int width = getWidth();
final int top = y;
final int bottom = top + height;
- final int left = isLayoutRtl ? getPaddingEnd() : width - getPaddingEnd();
- final int right = left + mCheckMarkWidth;
+ final int left;
+ final int right;
+ if (isLayoutRtl) {
+ right = getPaddingEnd();
+ left = right - mCheckMarkWidth;
+ } else {
+ left = width - getPaddingEnd();
+ right = left + mCheckMarkWidth;
+ }
checkMarkDrawable.setBounds( left, top, right, bottom);
checkMarkDrawable.draw(canvas);
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index dd05a03..dcf90e9 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -61,9 +61,9 @@ import java.util.ArrayList;
* the content of the inflated hierarchy.
*/
public class RemoteViews implements Parcelable, Filter {
-
+
private static final String LOG_TAG = "RemoteViews";
-
+
/**
* The intent extra that contains the appWidgetId.
* @hide
@@ -71,11 +71,11 @@ public class RemoteViews implements Parcelable, Filter {
static final String EXTRA_REMOTEADAPTER_APPWIDGET_ID = "remoteAdapterAppWidgetId";
/**
- * The package name of the package containing the layout
+ * The package name of the package containing the layout
* resource. (Added to the parcel)
*/
private final String mPackage;
-
+
/**
* The resource ID of the layout file. (Added to the parcel)
*/
@@ -86,7 +86,7 @@ public class RemoteViews implements Parcelable, Filter {
* inflated
*/
private ArrayList<Action> mActions;
-
+
/**
* A class to keep track of memory usage by this RemoteViews
*/
@@ -522,13 +522,13 @@ public class RemoteViews implements Parcelable, Filter {
.getCompatibilityInfo().applicationScale;
final int[] pos = new int[2];
v.getLocationOnScreen(pos);
-
+
final Rect rect = new Rect();
rect.left = (int) (pos[0] * appScale + 0.5f);
rect.top = (int) (pos[1] * appScale + 0.5f);
rect.right = (int) ((pos[0] + v.getWidth()) * appScale + 0.5f);
rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f);
-
+
final Intent intent = new Intent();
intent.setSourceBounds(rect);
handler.onClickHandler(v, pendingIntent, intent);
@@ -567,7 +567,7 @@ public class RemoteViews implements Parcelable, Filter {
this.filterMode = mode;
this.level = level;
}
-
+
public SetDrawableParameters(Parcel parcel) {
viewId = parcel.readInt();
targetBackground = parcel.readInt() != 0;
@@ -581,7 +581,7 @@ public class RemoteViews implements Parcelable, Filter {
}
level = parcel.readInt();
}
-
+
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(TAG);
dest.writeInt(viewId);
@@ -596,12 +596,12 @@ public class RemoteViews implements Parcelable, Filter {
}
dest.writeInt(level);
}
-
+
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
final View target = root.findViewById(viewId);
if (target == null) return;
-
+
// Pick the correct drawable to modify for this view
Drawable targetDrawable = null;
if (targetBackground) {
@@ -610,7 +610,7 @@ public class RemoteViews implements Parcelable, Filter {
ImageView imageView = (ImageView) target;
targetDrawable = imageView.getDrawable();
}
-
+
if (targetDrawable != null) {
// Perform modifications only if values are set correctly
if (alpha != -1) {
@@ -634,7 +634,7 @@ public class RemoteViews implements Parcelable, Filter {
public final static int TAG = 3;
}
-
+
private class ReflectionActionWithoutParams extends Action {
int viewId;
String methodName;
@@ -938,7 +938,7 @@ public class RemoteViews implements Parcelable, Filter {
out.writeString((String)this.value);
break;
case CHAR_SEQUENCE:
- TextUtils.writeToParcel((CharSequence)this.value, out, flags);
+ TextUtils.writeToParcel((CharSequence)this.value, out, flags);
break;
case URI:
out.writeInt(this.value != null ? 1 : 0);
@@ -1314,7 +1314,7 @@ public class RemoteViews implements Parcelable, Filter {
/**
* Create a new RemoteViews object that will display the views contained
* in the specified layout file.
- *
+ *
* @param packageName Name of the package that contains the layout resource
* @param layoutId The id of the layout resource
*/
@@ -1364,7 +1364,7 @@ public class RemoteViews implements Parcelable, Filter {
/**
* Reads a RemoteViews object from a parcel.
- *
+ *
* @param parcel
*/
public RemoteViews(Parcel parcel) {
@@ -1547,7 +1547,7 @@ public class RemoteViews implements Parcelable, Filter {
/**
* Add an action to be executed on the remote side when apply is called.
- *
+ *
* @param a The action to add
*/
private void addAction(Action a) {
@@ -1619,7 +1619,7 @@ public class RemoteViews implements Parcelable, Filter {
/**
* Equivalent to calling View.setVisibility
- *
+ *
* @param viewId The id of the view whose visibility should change
* @param visibility The new visibility for the view
*/
@@ -1629,7 +1629,7 @@ public class RemoteViews implements Parcelable, Filter {
/**
* Equivalent to calling TextView.setText
- *
+ *
* @param viewId The id of the view whose text should change
* @param text The new text for the view
*/
@@ -1639,7 +1639,7 @@ public class RemoteViews implements Parcelable, Filter {
/**
* Equivalent to calling {@link TextView#setTextSize(int, float)}
- *
+ *
* @param viewId The id of the view whose text size should change
* @param units The units of size (e.g. COMPLEX_UNIT_SP)
* @param size The size of the text
@@ -1649,33 +1649,29 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
- * Equivalent to calling
+ * Equivalent to calling
* {@link TextView#setCompoundDrawablesWithIntrinsicBounds(int, int, int, int)}.
*
* @param viewId The id of the view whose text should change
* @param left The id of a drawable to place to the left of the text, or 0
* @param top The id of a drawable to place above the text, or 0
* @param right The id of a drawable to place to the right of the text, or 0
- * @param bottom The id of a drawable to place below the text, or 0
+ * @param bottom The id of a drawable to place below the text, or 0
*/
public void setTextViewCompoundDrawables(int viewId, int left, int top, int right, int bottom) {
addAction(new TextViewDrawableAction(viewId, false, left, top, right, bottom));
}
/**
- * Equivalent to calling {@link
+ * Equivalent to calling {@link
* TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int)}.
*
* @param viewId The id of the view whose text should change
- * @param start The id of a drawable to place before the text (relative to the
+ * @param start The id of a drawable to place before the text (relative to the
* layout direction), or 0
* @param top The id of a drawable to place above the text, or 0
* @param end The id of a drawable to place after the text, or 0
-<<<<<<< HEAD
- * @param bottom The id of a drawable to place below the text, or 0
-=======
* @param bottom The id of a drawable to place below the text, or 0
->>>>>>> 0a43f67e
*/
public void setTextViewCompoundDrawablesRelative(int viewId, int start, int top, int end, int bottom) {
addAction(new TextViewDrawableAction(viewId, true, start, top, end, bottom));
@@ -1683,17 +1679,17 @@ public class RemoteViews implements Parcelable, Filter {
/**
* Equivalent to calling ImageView.setImageResource
- *
+ *
* @param viewId The id of the view whose drawable should change
* @param srcId The new resource id for the drawable
*/
- public void setImageViewResource(int viewId, int srcId) {
+ public void setImageViewResource(int viewId, int srcId) {
setInt(viewId, "setImageResource", srcId);
}
/**
* Equivalent to calling ImageView.setImageURI
- *
+ *
* @param viewId The id of the view whose drawable should change
* @param uri The Uri for the image
*/
@@ -1703,7 +1699,7 @@ public class RemoteViews implements Parcelable, Filter {
/**
* Equivalent to calling ImageView.setImageBitmap
- *
+ *
* @param viewId The id of the view whose bitmap should change
* @param bitmap The new Bitmap for the drawable
*/
@@ -1726,7 +1722,7 @@ public class RemoteViews implements Parcelable, Filter {
* {@link Chronometer#setFormat Chronometer.setFormat},
* and {@link Chronometer#start Chronometer.start()} or
* {@link Chronometer#stop Chronometer.stop()}.
- *
+ *
* @param viewId The id of the {@link Chronometer} to change
* @param base The time at which the timer would have read 0:00. This
* time should be based off of
@@ -1740,21 +1736,21 @@ public class RemoteViews implements Parcelable, Filter {
setString(viewId, "setFormat", format);
setBoolean(viewId, "setStarted", started);
}
-
+
/**
* Equivalent to calling {@link ProgressBar#setMax ProgressBar.setMax},
* {@link ProgressBar#setProgress ProgressBar.setProgress}, and
* {@link ProgressBar#setIndeterminate ProgressBar.setIndeterminate}
*
* If indeterminate is true, then the values for max and progress are ignored.
- *
+ *
* @param viewId The id of the {@link ProgressBar} to change
* @param max The 100% value for the progress bar
* @param progress The current value of the progress bar.
- * @param indeterminate True if the progress bar is indeterminate,
+ * @param indeterminate True if the progress bar is indeterminate,
* false if not.
*/
- public void setProgressBar(int viewId, int max, int progress,
+ public void setProgressBar(int viewId, int max, int progress,
boolean indeterminate) {
setBoolean(viewId, "setIndeterminate", indeterminate);
if (!indeterminate) {
@@ -1762,12 +1758,12 @@ public class RemoteViews implements Parcelable, Filter {
setInt(viewId, "setProgress", progress);
}
}
-
+
/**
* Equivalent to calling
* {@link android.view.View#setOnClickListener(android.view.View.OnClickListener)}
* to launch the provided {@link PendingIntent}.
- *
+ *
* When setting the on-click action of items within collections (eg. {@link ListView},
* {@link StackView} etc.), this method will not work. Instead, use {@link
* RemoteViews#setPendingIntentTemplate(int, PendingIntent) in conjunction with
@@ -1827,7 +1823,7 @@ public class RemoteViews implements Parcelable, Filter {
* view.
* <p>
* You can omit specific calls by marking their values with null or -1.
- *
+ *
* @param viewId The id of the view that contains the target
* {@link Drawable}
* @param targetBackground If true, apply these parameters to the
@@ -1853,7 +1849,7 @@ public class RemoteViews implements Parcelable, Filter {
/**
* Equivalent to calling {@link android.widget.TextView#setTextColor(int)}.
- *
+ *
* @param viewId The id of the view whose text color should change
* @param color Sets the text color for all the states (normal, selected,
* focused) to be this color.
@@ -2105,16 +2101,16 @@ public class RemoteViews implements Parcelable, Filter {
/**
* Inflates the view hierarchy represented by this object and applies
* all of the actions.
- *
+ *
* <p><strong>Caller beware: this may throw</strong>
- *
+ *
* @param context Default context to use
* @param parent Parent that the resulting view hierarchy will be attached to. This method
* does <strong>not</strong> attach the hierarchy. The caller should do so when appropriate.
* @return The inflated view hierarchy
*/
public View apply(Context context, ViewGroup parent) {
- return apply(context, parent, DEFAULT_ON_CLICK_HANDLER);
+ return apply(context, parent, null);
}
/** @hide */
@@ -2142,12 +2138,12 @@ public class RemoteViews implements Parcelable, Filter {
* Applies all of the actions to the provided view.
*
* <p><strong>Caller beware: this may throw</strong>
- *
+ *
* @param v The view to apply the actions to. This should be the result of
* the {@link #apply(Context,ViewGroup)} call.
*/
public void reapply(Context context, View v) {
- reapply(context, v, DEFAULT_ON_CLICK_HANDLER);
+ reapply(context, v, null);
}
/** @hide */
@@ -2170,6 +2166,7 @@ public class RemoteViews implements Parcelable, Filter {
private void performApply(View v, ViewGroup parent, OnClickHandler handler) {
if (mActions != null) {
+ handler = handler == null ? DEFAULT_ON_CLICK_HANDLER : handler;
final int count = mActions.size();
for (int i = 0; i < count; i++) {
Action a = mActions.get(i);
@@ -2198,7 +2195,7 @@ public class RemoteViews implements Parcelable, Filter {
/* (non-Javadoc)
* Used to restrict the views which can be inflated
- *
+ *
* @see android.view.LayoutInflater.Filter#onLoadClass(java.lang.Class)
*/
public boolean onLoadClass(Class clazz) {
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 5d6491d..1f713d4 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -664,7 +664,7 @@ public class Switch extends CompoundButton {
@Override
public void setChecked(boolean checked) {
super.setChecked(checked);
- setThumbPosition(checked);
+ setThumbPosition(isChecked());
invalidate();
}
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 8bb9348..238dc55 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -48,6 +48,10 @@ import java.util.List;
*/
public class TabHost extends FrameLayout implements ViewTreeObserver.OnTouchModeChangeListener {
+ private static final int TABWIDGET_LOCATION_LEFT = 0;
+ private static final int TABWIDGET_LOCATION_TOP = 1;
+ private static final int TABWIDGET_LOCATION_RIGHT = 2;
+ private static final int TABWIDGET_LOCATION_BOTTOM = 3;
private TabWidget mTabWidget;
private FrameLayout mTabContent;
private List<TabSpec> mTabSpecs = new ArrayList<TabSpec>(2);
@@ -293,22 +297,73 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
return mTabContent;
}
+ /**
+ * Get the location of the TabWidget.
+ *
+ * @return The TabWidget location.
+ */
+ private int getTabWidgetLocation() {
+ int location = TABWIDGET_LOCATION_TOP;
+
+ switch (mTabWidget.getOrientation()) {
+ case LinearLayout.VERTICAL:
+ location = (mTabContent.getLeft() < mTabWidget.getLeft()) ? TABWIDGET_LOCATION_RIGHT
+ : TABWIDGET_LOCATION_LEFT;
+ break;
+ case LinearLayout.HORIZONTAL:
+ default:
+ location = (mTabContent.getTop() < mTabWidget.getTop()) ? TABWIDGET_LOCATION_BOTTOM
+ : TABWIDGET_LOCATION_TOP;
+ break;
+ }
+ return location;
+ }
+
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
final boolean handled = super.dispatchKeyEvent(event);
- // unhandled key ups change focus to tab indicator for embedded activities
- // when there is nothing that will take focus from default focus searching
+ // unhandled key events change focus to tab indicator for embedded
+ // activities when there is nothing that will take focus from default
+ // focus searching
if (!handled
&& (event.getAction() == KeyEvent.ACTION_DOWN)
- && (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP)
&& (mCurrentView != null)
&& (mCurrentView.isRootNamespace())
- && (mCurrentView.hasFocus())
- && (mCurrentView.findFocus().focusSearch(View.FOCUS_UP) == null)) {
- mTabWidget.getChildTabViewAt(mCurrentTab).requestFocus();
- playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
- return true;
+ && (mCurrentView.hasFocus())) {
+ int keyCodeShouldChangeFocus = KeyEvent.KEYCODE_DPAD_UP;
+ int directionShouldChangeFocus = View.FOCUS_UP;
+ int soundEffect = SoundEffectConstants.NAVIGATION_UP;
+
+ switch (getTabWidgetLocation()) {
+ case TABWIDGET_LOCATION_LEFT:
+ keyCodeShouldChangeFocus = KeyEvent.KEYCODE_DPAD_LEFT;
+ directionShouldChangeFocus = View.FOCUS_LEFT;
+ soundEffect = SoundEffectConstants.NAVIGATION_LEFT;
+ break;
+ case TABWIDGET_LOCATION_RIGHT:
+ keyCodeShouldChangeFocus = KeyEvent.KEYCODE_DPAD_RIGHT;
+ directionShouldChangeFocus = View.FOCUS_RIGHT;
+ soundEffect = SoundEffectConstants.NAVIGATION_RIGHT;
+ break;
+ case TABWIDGET_LOCATION_BOTTOM:
+ keyCodeShouldChangeFocus = KeyEvent.KEYCODE_DPAD_DOWN;
+ directionShouldChangeFocus = View.FOCUS_DOWN;
+ soundEffect = SoundEffectConstants.NAVIGATION_DOWN;
+ break;
+ case TABWIDGET_LOCATION_TOP:
+ default:
+ keyCodeShouldChangeFocus = KeyEvent.KEYCODE_DPAD_UP;
+ directionShouldChangeFocus = View.FOCUS_UP;
+ soundEffect = SoundEffectConstants.NAVIGATION_UP;
+ break;
+ }
+ if (event.getKeyCode() == keyCodeShouldChangeFocus
+ && mCurrentView.findFocus().focusSearch(directionShouldChangeFocus) == null) {
+ mTabWidget.getChildTabViewAt(mCurrentTab).requestFocus();
+ playSoundEffect(soundEffect);
+ return true;
+ }
}
return handled;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5be9899..f502de4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2203,6 +2203,27 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
+ * Get the default {@link Locale} of the text in this TextView.
+ * @return the default {@link Locale} of the text in this TextView.
+ */
+ public Locale getTextLocale() {
+ return mTextPaint.getTextLocale();
+ }
+
+ /**
+ * Set the default {@link Locale} of the text in this TextView to the given value. This value
+ * is used to choose appropriate typefaces for ambiguous characters. Typically used for CJK
+ * locales to disambiguate Hanzi/Kanji/Hanja characters.
+ *
+ * @param locale the {@link Locale} for drawing text, must not be null.
+ *
+ * @see Paint#setTextLocale
+ */
+ public void setTextLocale(Locale locale) {
+ mTextPaint.setTextLocale(locale);
+ }
+
+ /**
* @return the size (in pixels) of the default text size in this TextView.
*/
@ViewDebug.ExportedProperty(category = "text")
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 7dcbc3e..053ade7 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -30,7 +30,6 @@ import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
-import android.view.WindowManagerImpl;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -331,7 +330,7 @@ public class Toast {
View mView;
View mNextView;
- WindowManagerImpl mWM;
+ WindowManager mWM;
TN() {
// XXX This should be changed to use a Dialog, with a Theme.Toast
@@ -371,7 +370,7 @@ public class Toast {
// remove the old view if necessary
handleHide();
mView = mNextView;
- mWM = WindowManagerImpl.getDefault();
+ mWM = (WindowManager)mView.getContext().getSystemService(Context.WINDOW_SERVICE);
// We can resolve the Gravity here by using the Locale for getting
// the layout direction
final Configuration config = mView.getContext().getResources().getConfiguration();
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index e63c57f..bffbe11 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -150,7 +150,8 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
resizeGrid();
} else if (count == 1) {
- startActivity(mAdapter.intentForPosition(0));
+ startActivityAsUser(mAdapter.intentForPosition(0),
+ new UserHandle(UserHandle.getUserId(mLaunchedFromUid)));
mPackageMonitor.unregister();
mRegistered = false;
finish();
@@ -363,12 +364,12 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
if (r.match > bestMatch) bestMatch = r.match;
}
getPackageManager().addPreferredActivity(filter, bestMatch, set,
- intent.getComponent());
+ intent.getComponent(), UserHandle.getUserId(mLaunchedFromUid));
}
}
if (intent != null) {
- startActivity(intent);
+ startActivityAsUser(intent, new UserHandle(UserHandle.getUserId(mLaunchedFromUid)));
}
}
@@ -376,7 +377,7 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
Intent in = new Intent().setAction("android.settings.APPLICATION_DETAILS_SETTINGS")
.setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
- startActivity(in);
+ startActivityAsUser(in, new UserHandle(UserHandle.getUserId(mLaunchedFromUid)));
}
private final class DisplayResolveInfo {
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index b016e99..1e268c4 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -18,16 +18,14 @@ package com.android.internal.os;
import android.net.Credentials;
import android.net.LocalSocket;
-import android.os.Build;
import android.os.Process;
+import android.os.SELinux;
import android.os.SystemProperties;
import android.util.Log;
import dalvik.system.PathClassLoader;
import dalvik.system.Zygote;
-import android.os.SELinux;
-
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -234,9 +232,9 @@ class ZygoteConnection {
ZygoteInit.setCloseOnExec(serverPipeFd, true);
}
- pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
- parsedArgs.gids, parsedArgs.debugFlags, rlimits,
- parsedArgs.seInfo, parsedArgs.niceName);
+ pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
+ parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
+ parsedArgs.niceName);
} catch (IOException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (ErrnoException ex) {
@@ -341,6 +339,9 @@ class ZygoteConnection {
*/
int debugFlags;
+ /** From --mount-external */
+ int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
+
/** from --target-sdk-version. */
int targetSdkVersion;
boolean targetSdkVersionSpecified;
@@ -526,6 +527,10 @@ class ZygoteConnection {
"Duplicate arg specified");
}
niceName = arg.substring(arg.indexOf('=') + 1);
+ } else if (arg.equals("--mount-external-singleuser")) {
+ mountExternal = Zygote.MOUNT_EXTERNAL_SINGLEUSER;
+ } else if (arg.equals("--mount-external-multiuser")) {
+ mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
} else {
break;
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 6ad67c3..9e43749 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -16,16 +16,17 @@
package com.android.internal.os;
+import static libcore.io.OsConstants.S_IRWXG;
+import static libcore.io.OsConstants.S_IRWXO;
+
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.net.LocalServerSocket;
import android.os.Debug;
-import android.os.FileUtils;
import android.os.Process;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.util.EventLog;
import android.util.Log;
@@ -33,6 +34,7 @@ import dalvik.system.VMRuntime;
import dalvik.system.Zygote;
import libcore.io.IoUtils;
+import libcore.io.Libcore;
import java.io.BufferedReader;
import java.io.FileDescriptor;
@@ -452,7 +454,7 @@ public class ZygoteInit {
closeServerSocket();
// set umask to 0077 so new files and directories will default to owner-only permissions.
- FileUtils.setUMask(FileUtils.S_IRWXG | FileUtils.S_IRWXO);
+ Libcore.os.umask(S_IRWXG | S_IRWXO);
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
diff --git a/core/java/com/android/internal/view/RotationPolicy.java b/core/java/com/android/internal/view/RotationPolicy.java
index af512a3..98beadb 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -27,6 +27,7 @@ import android.provider.Settings;
import android.util.Log;
import android.view.IWindowManager;
import android.view.Surface;
+import android.view.WindowManagerGlobal;
/**
* Provides helper functions for configuring the display rotation policy.
@@ -79,8 +80,7 @@ public final class RotationPolicy {
@Override
public void run() {
try {
- IWindowManager wm = IWindowManager.Stub.asInterface(
- ServiceManager.getService(Context.WINDOW_SERVICE));
+ IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
if (enabled) {
wm.freezeRotation(-1);
} else {
@@ -107,8 +107,7 @@ public final class RotationPolicy {
@Override
public void run() {
try {
- IWindowManager wm = IWindowManager.Stub.asInterface(
- ServiceManager.getService(Context.WINDOW_SERVICE));
+ IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
if (enabled) {
wm.freezeRotation(Surface.ROTATION_0);
} else {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index b1423ca..f950d3d 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -67,7 +67,6 @@ LOCAL_SRC_FILES:= \
android_os_ParcelFileDescriptor.cpp \
android_os_Parcel.cpp \
android_os_SELinux.cpp \
- android_os_StatFs.cpp \
android_os_SystemClock.cpp \
android_os_SystemProperties.cpp \
android_os_Trace.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index c936b0b..0c88297 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -134,7 +134,6 @@ extern int register_android_os_MessageQueue(JNIEnv* env);
extern int register_android_os_Parcel(JNIEnv* env);
extern int register_android_os_ParcelFileDescriptor(JNIEnv *env);
extern int register_android_os_SELinux(JNIEnv* env);
-extern int register_android_os_StatFs(JNIEnv *env);
extern int register_android_os_SystemProperties(JNIEnv *env);
extern int register_android_os_SystemClock(JNIEnv* env);
extern int register_android_os_Trace(JNIEnv* env);
@@ -1142,7 +1141,6 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_os_MessageQueue),
REG_JNI(register_android_os_ParcelFileDescriptor),
REG_JNI(register_android_os_SELinux),
- REG_JNI(register_android_os_StatFs),
REG_JNI(register_android_os_Trace),
REG_JNI(register_android_os_UEventObserver),
REG_JNI(register_android_net_LocalSocketImpl),
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index a65262c..edc9732 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -22,6 +22,7 @@
#include "jni.h"
#include "GraphicsJNI.h"
#include <android_runtime/AndroidRuntime.h>
+#include <ScopedUtfChars.h>
#include "SkBlurDrawLooper.h"
#include "SkColorFilter.h"
@@ -30,6 +31,7 @@
#include "SkShader.h"
#include "SkTypeface.h"
#include "SkXfermode.h"
+#include "unicode/uloc.h"
#include "unicode/ushape.h"
#include "TextLayout.h"
@@ -254,11 +256,51 @@ public:
obj->setTextAlign(align);
}
+ // generate bcp47 identifier for the supplied locale
+ static void toLanguageTag(char* output, size_t outSize,
+ const char* locale) {
+ if (output == NULL || outSize <= 0) {
+ return;
+ }
+ if (locale == NULL) {
+ output[0] = '\0';
+ return;
+ }
+ char canonicalChars[ULOC_FULLNAME_CAPACITY];
+ UErrorCode uErr = U_ZERO_ERROR;
+ uloc_canonicalize(locale, canonicalChars, ULOC_FULLNAME_CAPACITY,
+ &uErr);
+ if (U_SUCCESS(uErr)) {
+ char likelyChars[ULOC_FULLNAME_CAPACITY];
+ uErr = U_ZERO_ERROR;
+ uloc_addLikelySubtags(canonicalChars, likelyChars,
+ ULOC_FULLNAME_CAPACITY, &uErr);
+ if (U_SUCCESS(uErr)) {
+ uErr = U_ZERO_ERROR;
+ uloc_toLanguageTag(likelyChars, output, outSize, FALSE, &uErr);
+ if (U_SUCCESS(uErr)) {
+ return;
+ } else {
+ ALOGD("uloc_toLanguageTag(\"%s\") failed: %s", likelyChars,
+ u_errorName(uErr));
+ }
+ } else {
+ ALOGD("uloc_addLikelySubtags(\"%s\") failed: %s",
+ canonicalChars, u_errorName(uErr));
+ }
+ } else {
+ ALOGD("uloc_canonicalize(\"%s\") failed: %s", locale,
+ u_errorName(uErr));
+ }
+ // unable to build a proper language identifier
+ output[0] = '\0';
+ }
+
static void setTextLocale(JNIEnv* env, jobject clazz, SkPaint* obj, jstring locale) {
- const char* localeArray = env->GetStringUTFChars(locale, NULL);
- SkString skLocale(localeArray);
- obj->setTextLocale(skLocale);
- env->ReleaseStringUTFChars(locale, localeArray);
+ ScopedUtfChars localeChars(env, locale);
+ char langTag[ULOC_FULLNAME_CAPACITY];
+ toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, localeChars.c_str());
+ obj->setLanguage(SkLanguage(langTag));
}
static jfloat getTextSize(JNIEnv* env, jobject paint) {
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 9b9b991..7abfcf1 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -19,6 +19,7 @@
#include "TextLayoutCache.h"
#include "TextLayout.h"
#include "SkFontHost.h"
+#include "SkTypeface_android.h"
#include <unicode/unistr.h>
#include <unicode/normlzr.h>
#include <unicode/uchar.h>
@@ -224,7 +225,7 @@ void TextLayoutCache::dumpCacheStats() {
*/
TextLayoutCacheKey::TextLayoutCacheKey(): text(NULL), start(0), count(0), contextCount(0),
dirFlags(0), typeface(NULL), textSize(0), textSkewX(0), textScaleX(0), flags(0),
- hinting(SkPaint::kNo_Hinting) {
+ hinting(SkPaint::kNo_Hinting), variant(SkPaint::kDefault_Variant), language() {
}
TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint, const UChar* text,
@@ -237,6 +238,8 @@ TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint, const UChar* text,
textScaleX = paint->getTextScaleX();
flags = paint->getFlags();
hinting = paint->getHinting();
+ variant = paint->getFontVariant();
+ language = paint->getLanguage();
}
TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) :
@@ -251,7 +254,9 @@ TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) :
textSkewX(other.textSkewX),
textScaleX(other.textScaleX),
flags(other.flags),
- hinting(other.hinting) {
+ hinting(other.hinting),
+ variant(other.variant),
+ language(other.language) {
if (other.text) {
textCopy.setTo(other.text, other.contextCount);
}
@@ -288,6 +293,12 @@ int TextLayoutCacheKey::compare(const TextLayoutCacheKey& lhs, const TextLayoutC
deltaInt = lhs.dirFlags - rhs.dirFlags;
if (deltaInt) return (deltaInt);
+ deltaInt = lhs.variant - rhs.variant;
+ if (deltaInt) return (deltaInt);
+
+ if (lhs.language < rhs.language) return -1;
+ if (lhs.language > rhs.language) return +1;
+
return memcmp(lhs.getText(), rhs.getText(), lhs.contextCount * sizeof(UChar));
}
@@ -615,6 +626,8 @@ void TextLayoutShaper::computeRunValues(const SkPaint* paint, const UChar* chars
mShapingPaint.setTextScaleX(paint->getTextScaleX());
mShapingPaint.setFlags(paint->getFlags());
mShapingPaint.setHinting(paint->getHinting());
+ mShapingPaint.setFontVariant(paint->getFontVariant());
+ mShapingPaint.setLanguage(paint->getLanguage());
// Split the BiDi run into Script runs. Harfbuzz will populate the pos, length and script
// into the shaperItem
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index f007f9a..64b33a0 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -32,7 +32,7 @@
#include <SkTemplates.h>
#include <SkUtils.h>
#include <SkAutoKern.h>
-#include "SkTypeface_android.h"
+#include <SkLanguage.h>
#include <unicode/ubidi.h>
#include <unicode/ushape.h>
@@ -102,6 +102,8 @@ private:
SkScalar textScaleX;
uint32_t flags;
SkPaint::Hinting hinting;
+ SkPaint::FontVariant variant;
+ SkLanguage language;
inline const UChar* getText() const { return text ? text : textCopy.string(); }
diff --git a/core/jni/android_os_FileUtils.cpp b/core/jni/android_os_FileUtils.cpp
index 8d65cbc..a07f5b7 100644
--- a/core/jni/android_os_FileUtils.cpp
+++ b/core/jni/android_os_FileUtils.cpp
@@ -33,19 +33,6 @@
namespace android {
-static jfieldID gFileStatusDevFieldID;
-static jfieldID gFileStatusInoFieldID;
-static jfieldID gFileStatusModeFieldID;
-static jfieldID gFileStatusNlinkFieldID;
-static jfieldID gFileStatusUidFieldID;
-static jfieldID gFileStatusGidFieldID;
-static jfieldID gFileStatusSizeFieldID;
-static jfieldID gFileStatusBlksizeFieldID;
-static jfieldID gFileStatusBlocksFieldID;
-static jfieldID gFileStatusAtimeFieldID;
-static jfieldID gFileStatusMtimeFieldID;
-static jfieldID gFileStatusCtimeFieldID;
-
jint android_os_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
jstring file, jint mode,
jint uid, jint gid)
@@ -68,44 +55,6 @@ jint android_os_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
return chmod(file8.string(), mode) == 0 ? 0 : errno;
}
-jint android_os_FileUtils_getPermissions(JNIEnv* env, jobject clazz,
- jstring file, jintArray outArray)
-{
- const jchar* str = env->GetStringCritical(file, 0);
- String8 file8;
- if (str) {
- file8 = String8(str, env->GetStringLength(file));
- env->ReleaseStringCritical(file, str);
- }
- if (file8.size() <= 0) {
- return ENOENT;
- }
- struct stat st;
- if (stat(file8.string(), &st) != 0) {
- return errno;
- }
- jint* array = (jint*)env->GetPrimitiveArrayCritical(outArray, 0);
- if (array) {
- int len = env->GetArrayLength(outArray);
- if (len >= 1) {
- array[0] = st.st_mode;
- }
- if (len >= 2) {
- array[1] = st.st_uid;
- }
- if (len >= 3) {
- array[2] = st.st_gid;
- }
- }
- env->ReleasePrimitiveArrayCritical(outArray, array, 0);
- return 0;
-}
-
-jint android_os_FileUtils_setUMask(JNIEnv* env, jobject clazz, jint mask)
-{
- return umask(mask);
-}
-
jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring path)
{
if (path == NULL) {
@@ -127,63 +76,15 @@ jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring pat
return result;
}
-jboolean android_os_FileUtils_getFileStatus(JNIEnv* env, jobject clazz, jstring path, jobject fileStatus) {
- const char* pathStr = env->GetStringUTFChars(path, NULL);
- jboolean ret = false;
-
- struct stat s;
- int res = stat(pathStr, &s);
- if (res == 0) {
- ret = true;
- if (fileStatus != NULL) {
- env->SetIntField(fileStatus, gFileStatusDevFieldID, s.st_dev);
- env->SetIntField(fileStatus, gFileStatusInoFieldID, s.st_ino);
- env->SetIntField(fileStatus, gFileStatusModeFieldID, s.st_mode);
- env->SetIntField(fileStatus, gFileStatusNlinkFieldID, s.st_nlink);
- env->SetIntField(fileStatus, gFileStatusUidFieldID, s.st_uid);
- env->SetIntField(fileStatus, gFileStatusGidFieldID, s.st_gid);
- env->SetLongField(fileStatus, gFileStatusSizeFieldID, s.st_size);
- env->SetIntField(fileStatus, gFileStatusBlksizeFieldID, s.st_blksize);
- env->SetLongField(fileStatus, gFileStatusBlocksFieldID, s.st_blocks);
- env->SetLongField(fileStatus, gFileStatusAtimeFieldID, s.st_atime);
- env->SetLongField(fileStatus, gFileStatusMtimeFieldID, s.st_mtime);
- env->SetLongField(fileStatus, gFileStatusCtimeFieldID, s.st_ctime);
- }
- }
-
- env->ReleaseStringUTFChars(path, pathStr);
-
- return ret;
-}
-
static const JNINativeMethod methods[] = {
{"setPermissions", "(Ljava/lang/String;III)I", (void*)android_os_FileUtils_setPermissions},
- {"getPermissions", "(Ljava/lang/String;[I)I", (void*)android_os_FileUtils_getPermissions},
- {"setUMask", "(I)I", (void*)android_os_FileUtils_setUMask},
{"getFatVolumeId", "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getFatVolumeId},
- {"getFileStatusNative", "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z", (void*)android_os_FileUtils_getFileStatus},
};
static const char* const kFileUtilsPathName = "android/os/FileUtils";
int register_android_os_FileUtils(JNIEnv* env)
{
- jclass fileStatusClass = env->FindClass("android/os/FileUtils$FileStatus");
- LOG_FATAL_IF(fileStatusClass == NULL, "Unable to find class android.os.FileUtils$FileStatus");
-
- gFileStatusDevFieldID = env->GetFieldID(fileStatusClass, "dev", "I");
- gFileStatusInoFieldID = env->GetFieldID(fileStatusClass, "ino", "I");
- gFileStatusModeFieldID = env->GetFieldID(fileStatusClass, "mode", "I");
- gFileStatusNlinkFieldID = env->GetFieldID(fileStatusClass, "nlink", "I");
- gFileStatusUidFieldID = env->GetFieldID(fileStatusClass, "uid", "I");
- gFileStatusGidFieldID = env->GetFieldID(fileStatusClass, "gid", "I");
- gFileStatusSizeFieldID = env->GetFieldID(fileStatusClass, "size", "J");
- gFileStatusBlksizeFieldID = env->GetFieldID(fileStatusClass, "blksize", "I");
- gFileStatusBlocksFieldID = env->GetFieldID(fileStatusClass, "blocks", "J");
- gFileStatusAtimeFieldID = env->GetFieldID(fileStatusClass, "atime", "J");
- gFileStatusMtimeFieldID = env->GetFieldID(fileStatusClass, "mtime", "J");
- gFileStatusCtimeFieldID = env->GetFieldID(fileStatusClass, "ctime", "J");
-
return AndroidRuntime::registerNativeMethods(
env, kFileUtilsPathName,
methods, NELEM(methods));
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index 40443ff..e813c38 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#define LOG_TAG "SELinuxJNI"
#include <utils/Log.h>
@@ -6,6 +22,7 @@
#include "android_runtime/AndroidRuntime.h"
#ifdef HAVE_SELINUX
#include "selinux/selinux.h"
+#include "selinux/android.h"
#endif
#include <errno.h>
@@ -458,6 +475,27 @@ namespace android {
}
/*
+ * Function: native_restorecon
+ * Purpose: restore default SELinux security context
+ * Parameters: pathname: the pathname for the file to be relabeled
+ * Returns: boolean: (true) file label successfully restored, (false) otherwise
+ * Exceptions: none
+ */
+ static jboolean native_restorecon(JNIEnv *env, jobject clazz, jstring pathname) {
+#ifdef HAVE_SELINUX
+ if (isSELinuxDisabled)
+ return true;
+
+ const char *file = const_cast<char *>(env->GetStringUTFChars(pathname, NULL));
+ int ret = selinux_android_restorecon(file);
+ env->ReleaseStringUTFChars(pathname, file);
+ return (ret == 0);
+#else
+ return true;
+#endif
+ }
+
+ /*
* JNI registration.
*/
static JNINativeMethod method_table[] = {
@@ -472,6 +510,7 @@ namespace android {
{ "getPidContext" , "(I)Ljava/lang/String;" , (void*)getPidCon },
{ "isSELinuxEnforced" , "()Z" , (void*)isSELinuxEnforced},
{ "isSELinuxEnabled" , "()Z" , (void*)isSELinuxEnabled },
+ { "native_restorecon" , "(Ljava/lang/String;)Z" , (void*)native_restorecon},
{ "setBooleanValue" , "(Ljava/lang/String;Z)Z" , (void*)setBooleanValue },
{ "setFileContext" , "(Ljava/lang/String;Ljava/lang/String;)Z" , (void*)setFileCon },
{ "setFSCreateContext" , "(Ljava/lang/String;)Z" , (void*)setFSCreateCon },
diff --git a/core/jni/android_os_StatFs.cpp b/core/jni/android_os_StatFs.cpp
deleted file mode 100644
index 79d8fef..0000000
--- a/core/jni/android_os_StatFs.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright 2007, 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.
- */
-
-#if INCLUDE_SYS_MOUNT_FOR_STATFS
-#include <sys/mount.h>
-#else
-#include <sys/statfs.h>
-#endif
-
-#include <errno.h>
-
-#include "jni.h"
-#include "JNIHelp.h"
-#include "android_runtime/AndroidRuntime.h"
-
-
-namespace android
-{
-
-// ----------------------------------------------------------------------------
-
-struct fields_t {
- jfieldID context;
-};
-static fields_t fields;
-
-// ----------------------------------------------------------------------------
-
-static jint
-android_os_StatFs_getBlockSize(JNIEnv *env, jobject thiz)
-{
- struct statfs *stat = (struct statfs *)env->GetIntField(thiz, fields.context);
- return stat->f_bsize;
-}
-
-static jint
-android_os_StatFs_getBlockCount(JNIEnv *env, jobject thiz)
-{
- struct statfs *stat = (struct statfs *)env->GetIntField(thiz, fields.context);
- return stat->f_blocks;
-}
-
-static jint
-android_os_StatFs_getFreeBlocks(JNIEnv *env, jobject thiz)
-{
- struct statfs *stat = (struct statfs *)env->GetIntField(thiz, fields.context);
- return stat->f_bfree;
-}
-
-static jint
-android_os_StatFs_getAvailableBlocks(JNIEnv *env, jobject thiz)
-{
- struct statfs *stat = (struct statfs *)env->GetIntField(thiz, fields.context);
- return stat->f_bavail;
-}
-
-static void
-android_os_StatFs_native_restat(JNIEnv *env, jobject thiz, jstring path)
-{
- if (path == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
- return;
- }
-
- // get the object handle
- struct statfs *stat = (struct statfs *)env->GetIntField(thiz, fields.context);
- if (stat == NULL) {
- jniThrowException(env, "java/lang/NoSuchFieldException", NULL);
- return;
- }
-
- const char* pathstr = env->GetStringUTFChars(path, NULL);
- if (pathstr == NULL) {
- jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
- return;
- }
-
- // note that stat will contain the new file data corresponding to
- // pathstr
- if (statfs(pathstr, stat) != 0) {
- ALOGE("statfs %s failed, errno: %d", pathstr, errno);
- delete stat;
- env->SetIntField(thiz, fields.context, 0);
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
- }
- // Release pathstr
- env->ReleaseStringUTFChars(path, pathstr);
-}
-
-static void
-android_os_StatFs_native_setup(JNIEnv *env, jobject thiz, jstring path)
-{
- if (path == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
- return;
- }
-
- struct statfs* stat = new struct statfs;
- if (stat == NULL) {
- jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
- return;
- }
- env->SetIntField(thiz, fields.context, (int)stat);
- android_os_StatFs_native_restat(env, thiz, path);
-}
-
-static void
-android_os_StatFs_native_finalize(JNIEnv *env, jobject thiz)
-{
- struct statfs *stat = (struct statfs *)env->GetIntField(thiz, fields.context);
- if (stat != NULL) {
- delete stat;
- env->SetIntField(thiz, fields.context, 0);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-static JNINativeMethod gMethods[] = {
- {"getBlockSize", "()I", (void *)android_os_StatFs_getBlockSize},
- {"getBlockCount", "()I", (void *)android_os_StatFs_getBlockCount},
- {"getFreeBlocks", "()I", (void *)android_os_StatFs_getFreeBlocks},
- {"getAvailableBlocks", "()I", (void *)android_os_StatFs_getAvailableBlocks},
- {"native_setup", "(Ljava/lang/String;)V", (void *)android_os_StatFs_native_setup},
- {"native_finalize", "()V", (void *)android_os_StatFs_native_finalize},
- {"native_restat", "(Ljava/lang/String;)V", (void *)android_os_StatFs_native_restat},
-};
-
-
-int register_android_os_StatFs(JNIEnv *env)
-{
- jclass clazz;
-
- clazz = env->FindClass("android/os/StatFs");
- if (clazz == NULL) {
- ALOGE("Can't find android/os/StatFs");
- return -1;
- }
-
- fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
- if (fields.context == NULL) {
- ALOGE("Can't find StatFs.mNativeContext");
- return -1;
- }
-
- return AndroidRuntime::registerNativeMethods(env,
- "android/os/StatFs", gMethods, NELEM(gMethods));
-}
-
-} // namespace android
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 3ad6406..bada329 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -221,7 +221,7 @@ void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface)
static void Surface_init(
JNIEnv* env, jobject clazz,
jobject session,
- jint, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)
+ jint, jstring jname, jint layerStack, jint w, jint h, jint format, jint flags)
{
if (session == NULL) {
doThrowNPE(env);
@@ -233,12 +233,12 @@ static void Surface_init(
sp<SurfaceControl> surface;
if (jname == NULL) {
- surface = client->createSurface(dpy, w, h, format, flags);
+ surface = client->createSurface(layerStack, w, h, format, flags);
} else {
const jchar* str = env->GetStringCritical(jname, 0);
const String8 name(str, env->GetStringLength(jname));
env->ReleaseStringCritical(jname, str);
- surface = client->createSurface(name, dpy, w, h, format, flags);
+ surface = client->createSurface(name, layerStack, w, h, format, flags);
}
if (surface == 0) {
@@ -717,7 +717,7 @@ static void Surface_setWindowCrop(JNIEnv* env, jobject thiz, jobject crop)
}
}
-static void Surface_setDisplayId(JNIEnv* env, jobject thiz, jint displayId)
+static void Surface_setLayerStack(JNIEnv* env, jobject thiz, jint layerStack)
{
const sp<SurfaceControl>& surface(getSurfaceControl(env, thiz));
if (surface == 0) return;
@@ -863,7 +863,7 @@ static JNINativeMethod gSurfaceMethods[] = {
{"writeToParcel", "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel },
{"isConsumerRunningBehind", "()Z", (void*)Surface_isConsumerRunningBehind },
{"setWindowCrop", "(Landroid/graphics/Rect;)V", (void*)Surface_setWindowCrop },
- {"setDisplayId", "(I)V", (void*)Surface_setDisplayId },
+ {"setLayerStack", "(I)V", (void*)Surface_setLayerStack },
};
void nativeClassInit(JNIEnv* env, jclass clazz)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 195b1ef..89be5cb 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -283,7 +283,7 @@
<!-- @hide -->
<permission android:name="android.permission.BIND_DIRECTORY_SEARCH"
android:permissionGroup="android.permission-group.PERSONAL_INFO"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature|system" />
<!-- Allows an application to read the user's call log. -->
<permission android:name="android.permission.READ_CALL_LOG"
@@ -766,7 +766,6 @@
android:protectionLevel="dangerous"
android:label="@string/permlab_getTasks"
android:description="@string/permdesc_getTasks" />
-
<!-- Allows an application to call APIs that allow it to do interactions
across the users on the device, using singleton services and
user-targeted broadcasts. This permission is not available to
@@ -786,6 +785,15 @@
android:label="@string/permlab_interactAcrossUsersFull"
android:description="@string/permdesc_interactAcrossUsersFull" />
+ <!-- Allows an application to call APIs that allow it to query and manage
+ users on the device. This permission is not available to
+ third party applications. -->
+ <permission android:name="android.permission.MANAGE_USERS"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:protectionLevel="signature"
+ android:label="@string/permlab_manageUsers"
+ android:description="@string/permdesc_manageUsers" />
+
<!-- Allows an application to get full detailed information about
recently running tasks, with full fidelity to the real state.
@hide -->
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index db862c8..ad03dd2 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -224,6 +224,10 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Laat die program toe om aksies vir verskillende gebruikers op die toestel uit te voer. Kwaadwillige programme kan dit gebruik om die beskerming tussen gebruikers te skend."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"volle lisensie vir interaksie tussen gebruikers"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Laat alle moontlike interaksies tussen gebruikers toe."</string>
+ <!-- no translation found for permlab_manageUsers (1676150911672282428) -->
+ <skip />
+ <!-- no translation found for permdesc_manageUsers (8409306667645355638) -->
+ <skip />
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"haal besonderhede van lopende programme op"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Laat die program toe om inligting op te haal oor huidige en onlangse lopende take. Kwaadwillige programme kan dalk private inligting oor ander programme ontdek."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"herrangskik lopende programme"</string>
@@ -1309,4 +1313,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-oudio"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Klaar"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Media-uitvoer"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index ef8f604..fc6d4b8 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"መተግበሪያው በመሣሪያው ላይ በተለያዩ ተጠቃሚዎች ላይ እርምጃዎችን እንዲፈጽም ይፈቅድለታል። ተንኮል-አዘል መተግበሪያዎች ይህንን ተጠቅመው በተጠቃሚዎች መካከል ያለውን ጥበቃ ሊጥሱ ይችላሉ።"</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"በተለያዩ ተጠቃሚዎች መካከል መስተጋብር ለመፍጠር ሙሉ ፍቃድ"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"በተለያዩ ተጠቃሚዎች ላይ ሊኖሩ የሚችሉ መስተጋብሮችን ሁሉ ይፈቅዳል።"</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"ተጠቃሚዎችን ያስተዳድሩ"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"መተግበሪያዎች በመሣሪያዎች ላይ ያሉ ተጠቃሚዎችን እንዲያቀናብር ያስችለዋል፣ መጠየቅን፣ መፍጠርንና መሰረዝን ጨምሮ።"</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"እየሄዱ ስላሉ የመተግበሪያዎች ዝርዝሮች አምጣ"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"መተግበሪያው በአሁኑ ጊዜ እየተካሄዱ ስላሉና በቅርብ ጊዜ ስለተካሄዱ ተግባሮች መረጃ ዝርዝር እንዲያወጣ ይፈቅድለታል። ተንኮል-አዘል መተግበሪያዎች ስለ ሌሎች መተግበሪያዎች የግል መረጃ ሊያገኙ ይችላሉ።"</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"አሂድ ትግበራዎችን ድጋሚ ደርድር"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"የብሉቱዝ ድምጽ"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"ተከናውኗል"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"የሚዲያ ውጽዓት"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"ውስጥ የተሰራ ማያ ገጽ"</string>
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 17f4dd1..14d95a5 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"للسماح للتطبيق بتنفيذ إجراءات بين مستخدمين مختلفين على الجهاز. قد تستخدم التطبيقات الضارة ذلك لانتهاك الحماية بين المستخدمين."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"الترخيص بالكامل للتعامل بين المستخدمين"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"للسماح بجميع التعاملات المحتملة بين المستخدمين."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"إدارة المستخدمين"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"لتمكين التطبيقات من إدارة المستخدمين على الجهاز، بما في ذلك طلب البحث والإنشاء والحذف."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"استرداد تفاصيل التطبيقات قيد التشغيل"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"يسمح للتطبيق باسترداد معلومات تفصيلية حول المهام قيد التشغيل حاليًا ومؤخرًا. قد تكتشف التطبيقات الضارة معلومات خاصة حول التطبيقات الأخرى."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"إعادة ترتيب التطبيقات قيد التشغيل"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"صوت بلوتوث"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"تم"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"المنفذ الإعلامي"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index b9b6cf3..d801628 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Дазваляе прыкладанню выконваць дзеяннi сярод розных карыстальнiкаў прылады. Шкоднасныя прыкладаннi могуць выкарыстоўваць гэта, каб парушыць абарону памiж карыстальнiкамi."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"поўная ліцэнзія для ўзаемадзеяння паміж карыстальнiкамi"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Дазваляе ўсе магчымыя ўзаемадзеяннi паміж карыстальнікамі."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"кіраванне дадзенымi карыстальнікаў"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Дазваляе прыкладанням кіраваць звесткамi карыстальнікаў на прыладзе, у тым ліку запытамi, працэсамi стварэння і выдалення."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"атрымаць падрабязныя дадзеныя пра запушчаныя прыкладаннi"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Дазваляе прыкладанню атрымліваць падрабязную інфармацыю пра бягучыя і нядаўна запушчаныя задачы. Шкоднасныя прыкладанні могуць атрымліваць асабістую інфармацыю пра іншыя прыкладаннi."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"змяніць парадак запушчаных прыкладанняў"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-аўдыё"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Гатова"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Мультымедыйны выхад"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Убудаваны экран"</string>
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 6370ed4..81ba8a7 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Разрешава на приложението да изпълнява действия за различни потребители на устройството. Злонамерените приложения може да използват това, за да нарушат защитата между потребителите."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"пълен лиценз за взаимодействие с потребителите"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Разрешава всички възможни взаимодействия с потребителите."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"управление на потребителите"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Разрешава на приложенията да управляват потребителите на устройството, включително изброяването, създаването и изтриването им."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"извличане на подробности за изпълняваните прилож."</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Разрешава на приложението да извлича подробна информация за задачите, изпълнявани понастоящем и неотдавна. Злонамерените приложения могат да открият поверителна информация за други приложения."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"пренареждане на изпълняваните приложения"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Звук през Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Изходяща мултимедия"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 9c6cca1..0781217 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permet que l\'aplicació dugui a terme accions en diferents usuaris del dispositiu. Les aplicacions malicioses poden fer servir aquest permís per infringir la protecció entre usuaris."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"llicència completa per interaccionar entre usuaris"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permet totes les interaccions possibles entre usuaris."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"gestió d\'usuaris"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permet que les aplicacions gestionin usuaris al dispositiu, incloses les consultes, la creació i la supressió."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recupera els detalls d\'aplicacions en execució"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permet que l\'aplicació recuperi informació detallada sobre les tasques que s\'estan executant actualment i que s\'han executat recentment. Les aplicacions malicioses poden descobrir informació privada sobre altres aplicacions."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"canvia l\'ordre de les aplicacions en execució"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Àudio per Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fet"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Sortida de contingut multimèdia"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Pantalla integrada"</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 898fe14..4e7da84 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Umožňuje aplikaci provádět akce napříč různými uživateli zařízení. Škodlivé aplikace toto oprávnění mohou zneužít k obejití ochrany mezi uživateli."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"úplné oprávnění k interakcím napříč uživateli"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Povoluje všechny možné interakce napříč uživateli."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"správa uživatelů"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Umožňuje aplikacím spravovat uživatele v zařízení, včetně vytváření a mazání dotazů."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"získání podrobností o spuštěných aplikacích"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Umožňuje aplikaci získat podrobné informace o aktuálně a naposledy spuštěných úlohách. Škodlivé aplikace mohou odhalit soukromé informace o ostatních aplikacích."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"změna uspořádání spuštěných aplikací"</string>
@@ -842,7 +844,7 @@
<item quantity="other" msgid="3903706804349556379">"před <xliff:g id="COUNT">%d</xliff:g> s"</item>
</plurals>
<plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"před 1 minutou"</item>
+ <item quantity="one" msgid="3306787433088810191">"před 1 min"</item>
<item quantity="other" msgid="2176942008915455116">"před <xliff:g id="COUNT">%d</xliff:g> min"</item>
</plurals>
<plurals name="num_hours_ago">
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth Audio"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Hotovo"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Výstup médií"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 9ccf3f0..ea40879 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Tillader, at appen udfører handlinger på tværs af forskellige brugere på enheden. Ondsindede apps kan bruge dette til at krænke beskyttelsen mellem brugere."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"fuld licens til at kommunikere på tværs af brugere"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Tillader alle mulige former for kommunikation på tværs af brugere."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"administrer brugere"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Tillader, at apps administrerer brugere på enheden, herunder forespørgsler, oprettelser og sletninger."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"hente oplysninger om apps, der kører"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Tillader, at appen kan hente oplysninger om aktuelle og seneste opgaver. Ondsindede apps kan muligvis finde personlige oplysninger om andre apps."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"omorganisere kørende apps"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-lyd"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Udfør"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Medieudgang"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Indbygget skærm"</string>
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index f72d625..a0280c8 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Ermöglicht der App, auf dem Gerät nutzerübergreifend Aktionen durchzuführen. Schädliche Apps können so den zwischen den Nutzern bestehenden Schutz aufheben."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"Vollständige Lizenz zum nutzerübergreifenden Interagieren"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Ermöglicht alle möglichen nutzerübergreifenden Interaktionen"</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"Nutzer verwalten"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Ermöglicht Apps die Verwaltung der Nutzer auf dem Gerät, unter anderem das Abfragen, Erstellen und Löschen von Nutzern"</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"Details zu ausgeführten Apps abrufen"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Ermöglicht der App, detaillierte Informationen zu aktuellen und kürzlich ausgeführten Aufgaben abzurufen. Schädliche Apps können so geheime Informationen zu anderen Apps erhalten."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"Aktive Apps neu ordnen"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-Audio"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fertig"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Medienausgabe"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Integrierter Bildschirm"</string>
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 95717a2..82f0c62 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Δίνει στην εφαρμογή τη δυνατότητα να πραγματοποιεί ενέργειες σε όλους τους διαφορετικούς χρήστες στη συσκευή. Οι κακόβουλες εφαρμογές ενδέχεται να χρησιμοποιήσουν αυτή τη δυνατότητα για να παραβιάσουν την προστασία μεταξύ των χρηστών."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"πλήρης άδεια αλληλεπίδρασης στους χρήστες"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Επιτρέπει όλες τις πιθανές αλληλεπιδράσεις στους χρήστες."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"διαχείριση χρηστών"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Επιτρέπει στις εφαρμογές να διαχειρίζονται τους χρήστες της συσκευής, συμπεριλαμβανομένων των ερωτημάτων της δημιουργίας και της διαγραφής."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"ανάκτηση λεπτομερειών σχετικά με τις εκτελούμενες εφαρμογές"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Επιτρέπει στην εφαρμογή την ανάκτηση λεπτομερών πληροφοριών σχετικά με τις τρέχουσες εκτελούμενες εργασίες και τις εργασίες που έχουν εκτελεστεί πρόσφατα. Τυχόν κακόβουλες εφαρμογές ενδέχεται να ανακαλύψουν ιδιωτικές πληροφορίες σχετικά με άλλες εφαρμογές."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"αναδιάταξη εκτελούμενων εφαρμογών"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Ήχος Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Τέλος"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Έξοδος μέσων"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Ενσωματωμένη οθόνη"</string>
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index eaa3578..4f7b087 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Allows the app to perform actions across different users on the device. Malicious apps may use this to violate the protection between users."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"full license to interact across users"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Allows all possible interactions across users."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"manage users"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Allows apps to manage users on the device, including query, creation and deletion."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"retrieve details of running apps"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Allows the app to retrieve detailed information about currently and recently running tasks. Malicious apps may discover private information about other apps."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"re-order running apps"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Done"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Media output"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Built-in Screen"</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index b589afb..9108337 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite que la aplicación lleve a cabo acciones entre los diferentes usuarios del dispositivo. Las aplicaciones maliciosas pueden utilizar este permiso para infringir la protección entre usuarios."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"Licencia completa para interactuar con los usuarios"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite todas las interacciones posibles con los usuarios."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"Administrar usuarios"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite a las aplicaciones administrar a los usuarios del dispositivo, incluidas la creación y la eliminación de consultas."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recuperar información sobre las aplicaciones en ejecución"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite que la aplicación recupere información detallada sobre tareas en ejecución y recientemente ejecutadas. Las aplicaciones malintencionadas pueden hallar información privada sobre otras aplicaciones."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"reorganizar aplicaciones en ejecución"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Listo"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Salida multimedia"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index ec7bbb2..c998ff6 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite que la aplicación lleve a cabo acciones entre los diferentes usuarios del dispositivo. Las aplicaciones maliciosas pueden utilizar este permiso para infringir la protección entre usuarios."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"licencia completa para interactuar con los usuarios"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite que la aplicación interactúe con los usuarios."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"administrar usuarios"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite a las aplicaciones administrar los usuarios del dispositivo, así como buscarlos, crearlos y eliminarlos."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recuperar información de aplicaciones en ejecución"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite que la aplicación recupere información sobre tareas que se están ejecutando en este momento o que se han ejecutado recientemente. Las aplicaciones malintencionadas pueden usar este servicio para acceder a información privada sobre otras aplicaciones."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"reorganizar aplicaciones en ejecución"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fin"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Salida multimedia"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Pantalla integrada"</string>
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 957e941..872f485 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Lubab rakendusel teha toiminguid seadme erinevatel kasutajakontodel. Pahatahtlikud rakendused võivad kasutada seda kasutajatevahelise kaitse rikkumiseks."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"täielik litsents teha toiminguid erinevatel kasutajakontodel"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Lubab kõiki võimalikke toiminguid erinevatel kasutajakontodel."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"kasutajate haldamine"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Võimaldab rakendustel hallata seadme kasutajaid, sealhulgas päringuid, loomist ja kustutamist."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"töötavate rakenduste üksikasjade toomine"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Võimaldab rakendusel tuua üksikasjalikku teavet praegu töötavate ja hiljuti käitatud ülesannete kohta. Pahatahtlikud rakendused võivad tuvastada privaatset teavet muude rakenduste kohta."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"käitatud rakenduste ümberjärjestamine"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-heli"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Valmis"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Meediaväljund"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 6f99078..ecdebe8 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"به برنامه اجازه می‌دهد اقداماتی در بین کاربران مختلف در دستگاه انجام دهد. ممکن است برنامه‌های مخرب از این قابلیت برای نقض حفاظت موجود در بین کاربران استفاده کنند."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"مجوز کامل برای ارتباط بین کاربران"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"اجازه می‌دهد همه ارتباطات ممکن بین کاربران انجام شود."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"مدیریت کاربران"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"به برنامه‌ها اجازه می‌دهد مدیریت کاربران، از قبیل پرسش، ایجاد و حذف کاربران، را در دستگاه انجام دهند."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"بازیابی جزئیات برنامه‌های در حال اجرا"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"به برنامه اجازه می‎دهد تا اطلاعات مفصلی مربوط به کارهایی که در حال حاضر و اخیراً اجرا می‎شوند را بازیابی کند. برنامه‎های مخرب می‎توانند اطلاعات شخصی مربوط به برنامه‎های دیگر را پیدا کنند."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"تنظیم مجدد ترتیب برنامه‎های در حال اجرا"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"بلوتوث‌های صوتی"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"انجام شد"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"خروجی رسانه"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index e06dfcc..f6ab9f8 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Antaa sovelluksen suorittaa käyttäjien välisiä toimintoja laitteessa. Haitalliset sovellukset voivat vahingoittaa käyttäjien välistä suojausta."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"lupa suorittaa käyttäjien välisiä toimintoja"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Sallii kaikki käyttäjien väliset toiminnot."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"hallinnoi käyttäjiä"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Antaa sovelluksien hallinnoida laitteen käyttäjiä esim. hakemalla, luomalla tai poistamalla käyttäjiä."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"hae tiedot suoritettavista sovelluksista"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Antaa sovellukselle oikeuden noutaa käynnissä oleviin ja käynnissä olleisiin tehtäviin liittyviä tietoja. Haitalliset sovellukset saattavat saada näin muihin sovelluksiin liittyviä yksityisiä tietoja."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"käynnissä olevien sovellusten järjesteleminen"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ääni"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Valmis"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Median äänentoisto"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Sisäänrakennettu näyttö"</string>
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index e98000a..c35fe8d 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permet à l\'application d\'effectuer des actions entre les différents utilisateurs de l\'appareil. Les applications malveillantes peuvent utiliser cette autorisation pour passer outre la protection entre les utilisateurs."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"autorisation totale d\'interagir entre les utilisateurs"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permet toutes les interactions possibles entre les utilisateurs."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"Gérer les utilisateurs"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permet aux applications de gérer les utilisateurs de l\'appareil, y compris la recherche, la création et la suppression d\'utilisateurs."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"récupérer les détails des applications en cours d\'exécution"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permet à l\'application de récupérer des informations détaillées sur les tâches en cours d\'exécution ou récemment exécutées. Des applications malveillantes peuvent utiliser cette fonctionnalité pour obtenir des informations confidentielles relatives à d\'autres applications."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"réorganiser les applications en cours d\'exécution"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"OK"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Sortie multimédia"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index cf8fa01..6ea8f7b 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"एप्लिकेशन को उपकरण पर भिन्न उपयोगकर्ताओं के बीच कार्य निष्पादित करने देता है. दुर्भावनापूर्ण एप्लिकेशन उपयोगकर्ताओं के बीच सुरक्षा का उल्लंघन करने के लिए इसका उपयोग कर सकते हैं."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"उपयोगकर्ताओं के बीच सहभागिता करने के लिए पूर्ण लाइसेंस"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"उपयोगकर्ताओं के बीच सभी संभव सहभागिता करने देता है."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"उपयोगकर्ता प्रबंधित करें"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"एप्लिकेशन को उपकरण पर क्वेरी, निर्माण और हटाने सहित उपयोगकर्ताओं को प्रबंधित करने की सुविधा देता है."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"चल रहे एप्‍लिकेशन के विवरण प्राप्त करें"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"एप्लिकेशन को वर्तमान में और हाल ही में चल रहे कार्यों की जानकारी प्राप्त करने देता है. दुर्भावनापूर्ण एप्लिकेशन अन्य एप्लिकेशन के बारे में निजी जानकारी खोज सकते हैं."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"चल रहे एप्‍लिकेशन पुन: क्रमित करें"</string>
@@ -722,7 +724,7 @@
<string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"आपका सिम कार्ड स्‍थायी रूप से अक्षम कर दिया गया है."\n" दूसरे SIM कार्ड के लिए अपने वायरलेस सेवा प्रदाता से संपर्क करें."</string>
<string name="lockscreen_transport_prev_description" msgid="201594905152746886">"पिछला ट्रैक बटन"</string>
<string name="lockscreen_transport_next_description" msgid="6089297650481292363">"अगला ट्रैक बटन"</string>
- <string name="lockscreen_transport_pause_description" msgid="7659088786780128001">"रोकें बटन"</string>
+ <string name="lockscreen_transport_pause_description" msgid="7659088786780128001">"पॉज़ करें बटन"</string>
<string name="lockscreen_transport_play_description" msgid="5888422938351019426">"चलाएं बटन"</string>
<string name="lockscreen_transport_stop_description" msgid="4562318378766987601">"रोकें बटन"</string>
<string name="emergency_calls_only" msgid="6733978304386365407">"केवल आपातकालीन कॉल"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth ऑडियो"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"पूर्ण"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"मीडिया आउटपुट"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 2029530..26bc6ec 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Omogućuje aplikaciji izvršavanje radnji među korisnicima na uređaju. Zlonamjerne aplikacije mogu to iskoristiti za narušavanje zaštite među korisnicima."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"dozvola za potpunu interakciju među korisnicima"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Omogućuje sve moguće interakcije među korisnicima."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"upravljanje korisnicima"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Omogućuje aplikacijama upravljanje korisnicima na uređaju, uključujući upit, izradu i brisanje."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"dohvaćanje pojedinosti o pokrenutim aplikacijama"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Aplikaciji omogućuje dohvaćanje detaljnih informacija o trenutačno i nedavno pokrenutim zadacima. Zlonamjerne aplikacije mogu otkriti privatne informacije o drugim aplikacijama."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"promjena redoslijeda pokrenutih aplikacija"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth zvuk"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gotovo"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Medijski izlaz"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 421c5be..42e7888 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Lehetővé teszi az alkalmazás számára, hogy több felhasználó között végezzen különféle műveleteket az eszközön. A rosszindulatú alkalmazások arra használhatják ezt, hogy megsértsék a felhasználók biztonságát."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"teljes licenc a felhasználók közötti interakcióhoz"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Lehetővé teszi az összes lehetséges interakciót a felhasználók között."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"Felhasználók kezelése"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Lehetővé teszi az alkalmazások számára a készüléken beállított felhasználók kezelését, beleértve a lekérdezéseket, a létrehozásokat és törléseket."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"futó alkalmazások részleteinek lekérése"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Lehetővé teszi az alkalmazás számára a jelenleg és a nemrég futó feladatok részletes adatainak lekérését. A rosszindulatú alkalmazások más alkalmazásokkal kapcsolatos privát adatokhoz férhetnek hozzá."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"futó alkalmazások átrendezése"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth hang"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Kész"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Médiakimenet"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index ef759e0..34e6a96 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Mengizinkan aplikasi melakukan tindakan antar-pengguna yang berbeda pada perangkat. Aplikasi berbahaya dapat menggunakan ini untuk mengganggu perlindungan antar-pengguna."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"lisensi penuh untuk berinteraksi antar-pengguna"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Mengizinkan semua interaksi yang mungkin antar-pengguna."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"kelola pengguna"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Memungkinkan aplikasi mengelola pengguna pada perangkat, termasuk kueri, pembuatan, dan penghapusan."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"mengambil detail aplikasi yang sedang berjalan"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Izinkan aplikasi mengambil informasi mendetail tentang tugas yang saat ini dan baru-baru ini dijalankan. Aplikasi berbahaya dapat menemukan informasi pribadi tentang aplikasi lain."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"menyusun ulang apl yang berjalan"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Selesai"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Keluaran media"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Layar Ada Di Dalamnya"</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 5f64c20..a693dc8 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Consente all\'applicazione di compiere azioni per diversi utenti sul dispositivo. Le applicazioni dannose potrebbero farne uso per violare la protezione tra utenti."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"licenza completa per l\'interazione tra utenti"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Consente tutte le interazioni possibili tra gli utenti."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"Gestione utenti"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Consente alle applicazioni di gestire gli utenti sul dispositivo, nonché query, creazione ed eliminazione."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recupero dettagli applicazioni in esecuzione"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Consente all\'applicazione di recuperare informazioni dettagliate sulle attività attualmente e recentemente in esecuzione. Le applicazioni dannose potrebbero scoprire informazioni riservate su altre applicazioni."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"riordinamento applicazioni in esecuzione"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fine"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Uscita media"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Schermo incorporato"</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 5432f26..a318907 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"מאפשר ליישום לבצע פעולות בין משתמשים שונים במכשיר. יישומים זדוניים עשויים להשתמש ביכולת זו כדי לפרוץ את ההגנה בין משתמשים."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"רישיון מלא לבצע אינטראקציה בין משתמשים"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"מאפשר את כל האינטראקציות האפשריות בין משתמשים."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"נהל משתמשים"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"מאפשר ליישומים לנהל משתמשים במכשיר, כולל שאילתה, יצירה ומחיקה."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"אחזור פרטי יישומים פועלים"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"מאפשר ליישום לאחזר מידע מפורט על המשימות הנוכחיות הפועלות ועל משימות שפעלו לאחרונה. יישומים זדוניים עלולים לגלות מידע אישי על יישומים אחרים."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"סידור מחדש של יישומים פעילים"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"אודיו Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"סיום"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"פלט מדיה"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"מסך מובנה"</string>
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index f8ab2bf..dc0c139 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"端末上の各ユーザーに対して操作を実行することをアプリに許可します。この許可を悪意のあるアプリに利用されると、ユーザー間の保護が侵害される恐れがあります。"</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"ユーザー間で交流するための完全ライセンス"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"ユーザー間の交流をすべて許可します。"</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"ユーザーの管理"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"ユーザーの問い合わせ、作成、削除を含め、端末上のユーザーを管理することをアプリに許可します。"</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"実行中のアプリの詳細の取得"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"現在実行中のタスクまたは最近実行したタスクに関する情報の取得をアプリに許可します。この許可を悪意のあるアプリに利用されると、他のアプリに関する非公開情報が読み取られる恐れがあります。"</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"実行中のアプリの順序変更"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth音声"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"完了"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"メディア出力"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index ec301a4..f6ae2af 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"앱이 기기에서 다양한 사용자에 대한 작업을 수행할 수 있도록 허용합니다. 이 경우 악성 앱이 사용자 간의 보호를 위반할 수 있습니다."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"여러 사용자와의 상호작용을 위한 정식 라이센스"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"여러 사용자와의 가능한 모든 상호작용을 허용합니다."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"사용자 관리"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"앱이 기기에서 검색, 생성 및 삭제를 포함한 사용자 관리를 할 수 있도록 허용합니다."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"실행 중인 앱 세부정보 검색"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"앱이 현재 실행 중이거나 최근에 실행된 작업에 대한 상세한 정보를 검색할 수 있도록 허용합니다. 이 경우 악성 앱이 다른 앱에 대한 개인 정보를 검색할 수 있습니다."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"실행 중인 앱 순서 재지정"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"블루투스 오디오"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"완료"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"미디어 출력"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 7f44e81..7692620 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Leidžiama programai atlikti veiksmus skirtingų įrenginio naudotojų profiliuose. Kenkėjiškos programos gali pasinaudoti šiuo leidimu, kad pažeistų naudotojų saugumą."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"visa licencija, leidžianti sąveikauti su naudotojais"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Leidžiama bet kokia sąveika tarp naudotojų."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"tvarkyti naudotojus"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Leidžia tvarkyti įrenginio naudotojų duomenis, įskaitant užklausų teikimą, duomenų kūrimą ir ištrynimą."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"nuskaityti veikiančių programų išsamią informaciją"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Leidžiama programai nuskaityti išsamią informaciją apie šiuo ir pastaruoju metu vykdomas užduotis. Kenkėjiškos programos gali surasti privačios informacijos apie kitas programas."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"pertvarkyti vykdomas programas"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"„Bluetooth“ garsas"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Atlikta"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Medijos išvestis"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 1d46ccb..d63c45b 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Ļauj lietotnei veikt darbības vairāku ierīces lietotāju kontos. Ļaunprātīgas lietotnes var izmantot šo atļauju, lai apdraudētu lietotāju kontu drošību."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"pilna licence ar atļauju darboties visos lietotāju kontos"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Ļauj veikt jebkādas darbības visos lietotāju kontos."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"Lietotāju pārvaldība"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Ļauj lietotnēm pārvaldīt ierīces lietotājus, tostarp izveidot un dzēst lietotājus vai veidot vaicājumus."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"Informācijas izguve par izmantotajām lietotnēm"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Ļauj lietotnei izgūt informāciju par šobrīd un nesen veiktajiem uzdevumiem. Ļaunprātīgas lietotnes var atklāt privātu informāciju par citām lietotnēm."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"pārkārtot izmantotās lietotnes"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gatavs"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Multivides izeja"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 5bbebc5..a22ff51 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Membenarkan apl melakukan tindakan merentasi pengguna berbeza pada peranti. Apl hasad boleh menggunakan ini untuk melanggar perlindungan antara pengguna."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"lesen penuh untuk berinteraksi sesama pengguna"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Membenarkan semua interaksi yang mungkin sesama pengguna."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"urus pengguna"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Membenarkan apl mengurus pengguna pada peranti ini, termasuk pertanyaan, pembuatan dan pemadaman."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"dapatkan butiran apl yang berjalan"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Membenarkan apl untuk mendapatkan maklumat terperinci tentang tugasan yang sedang dan baru berjalan. Apl hasad boleh mendapat maklumat peribadi tentang apl lain."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"susun semula tertib apl yang dijalankan"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Selesai"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Output media"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 68f8918..3a4212b 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Tillater at appen utfører handlinger på tvers av ulike brukere på enheten. Skadelige apper kan utnytte dette til å bryte beskyttelsen mellom brukere."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"full lisens til å samhandle på tvers av brukere"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Tillater alle mulige samhandlinger på tvers av brukere."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"Administrere brukere"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Lar apper administrere brukere på enheten, herunder forespørsler, oppretting og sletting."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"hente informasjon om apper som kjører"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Tillater at appen henter ut informasjon om oppgaver som kjører eller nylig har kjørt. Skadelige apper kan bruke dette til å oppdage privat informasjon om andre apper."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"Endre rekkefølge på apper som kjører"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-lyd"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fullført"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Medieutgang"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Innebygd skjerm"</string>
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 985da7e..89e52a9 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Hiermee kan de app acties uitvoeren voor verschillende gebruikers van het apparaat. Schadelijke apps kunnen dit gebruiken om de beveiliging tussen gebruikers te schenden."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"volledige toestemming voor interactie tussen gebruikers"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Hiermee is alle mogelijke interactie tussen gebruikers toegestaan."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"gebruikers beheren"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Toestaan dat apps gebruikers op het apparaat beheren, inclusief het opvragen van gegevens en het maken en verwijderen van gebruikers."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"details van actieve apps ophalen"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Hiermee kan de app gedetailleerde informatie over huidige en recent uitgevoerde taken ophalen. Schadelijke apps kunnen op deze manier mogelijk privé-informatie over andere apps achterhalen."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"actieve apps opnieuw rangschikken"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-audio"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gereed"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Media-uitvoer"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Ingebouwd scherm"</string>
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 19f317d..e16d308 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Umożliwia aplikacji wykonywanie działań dotyczących różnych użytkowników urządzenia. Złośliwe aplikacje mogą to wykorzystać do złamania zabezpieczeń na kontach użytkowników."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"pełna licencja na interakcje między użytkownikami"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Zezwala na wszystkie możliwe interakcje między użytkownikami."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"zarządzanie użytkownikami"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Pozwala aplikacjom na zarządzanie użytkownikami na urządzeniu, w tym na ich sprawdzanie, tworzenie i usuwanie."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"Pobieraj informacje o uruchomionych aplikacjach"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Zezwala aplikacji na pobieranie informacji o obecnie i ostatnio uruchomionych zadaniach. Złośliwe aplikacje mogą uzyskać dostęp do prywatnych informacji na temat innych aplikacji."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"zmienianie kolejności uruchomionych aplikacji"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Dźwięk Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gotowe"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Wyjście multimediów"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 788d1a2..996be49 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite que a aplicação execute ações com diferentes utilizadores no dispositivo. Aplicações maliciosas poderão utilizar esta opção para violar a proteção entre utilizadores."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"licença completa para interagir entre utilizadores"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite todas as interações possíveis entre utilizadores."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"gerir utilizadores"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite às aplicações a gestão de utilizadores no dispositivo, incluindo a criação e eliminação de consultas."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"obter detalhes das aplicações em execução"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite à aplicação obter informações detalhadas sobre tarefas atualmente em execução e recentemente executadas. As aplicações maliciosas poderão descobrir informações privadas de outras aplicações."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"reordenar as aplicações em execução"</string>
@@ -1132,7 +1134,7 @@
<string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"O armazenamento USB foi removido. Insira um novo suporte de dados."</string>
<string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Cartão SD removido. Insira um novo cartão."</string>
<string name="activity_list_empty" msgid="1675388330786841066">"Não foi encontrada nenhuma atividade correspondente."</string>
- <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"actualizar estatísticas de utilização de componentes"</string>
+ <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"atualizar estatísticas de utilização de componentes"</string>
<string name="permdesc_pkgUsageStats" msgid="1106612424254277630">"Permite que a aplicação modifique as estatísticas de utilização de componentes recolhidas. Não se destina a utilização por aplicações normais."</string>
<string name="permlab_copyProtectedData" msgid="4341036311211406692">"copiar conteúdo"</string>
<string name="permdesc_copyProtectedData" msgid="4390697124288317831">"Permite à aplicação invocar o serviço de contentor predefinido para copiar conteúdo. Não se destina a ser utilizado por aplicações normais."</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Áudio Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Concluído"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Saída de som multimédia"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 9bdfcd8..7d7672f 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite que o aplicativo execute ações entre os diversos usuários do aparelho. Aplicativos mal-intencionados podem usar isto para violar a proteção entre os usuários."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"permissão total para interagir entre os usuários"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite todas as interações possíveis entre os usuários."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"gerenciar usuários"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite que os aplicativos gerenciem os usuários do dispositivo, incluindo a consulta, a criação e a exclusão de usuários."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recuperar detalhes dos aplicativos em execução"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite que o aplicativo recupere informações detalhadas sobre tarefas executadas atual e recentemente. Aplicativos maliciosos podem descobrir informações privadas sobre outros aplicativos."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"reordenar os aplicativos em execução"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Áudio Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Concluído"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Saída de mídia"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 097d6de..a093bfb 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -303,6 +303,10 @@
<skip />
<!-- no translation found for permdesc_interactAcrossUsersFull (376841368395502366) -->
<skip />
+ <!-- no translation found for permlab_manageUsers (1676150911672282428) -->
+ <skip />
+ <!-- no translation found for permdesc_manageUsers (8409306667645355638) -->
+ <skip />
<!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
<skip />
<!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
@@ -2066,4 +2070,6 @@
<skip />
<!-- no translation found for media_route_button_content_description (5758553567065145276) -->
<skip />
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 7284dd7..6300a1f 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite aplicaţiei să efectueze acţiuni pentru diferiţi utilizatori pe dispozitiv. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a încălca protecţia între utilizatori."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"licenţă completă pentru interacţiune între utilizatori"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite toate interacţiunile posibile între utilizatori."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"gestionează utilizatorii"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite aplicaţiilor să gestioneze utilizatorii de pe dispozitiv, inclusiv interogarea, crearea şi ştergerea acestora."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"preia detalii despre aplicaţiile care rulează"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite aplicaţiei să preia informaţii detaliate despre activităţile rulate curent şi recent. Aplicaţiile rău intenţionate pot să descopere informaţii private despre alte aplicaţii."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"reordonare aplicaţii care rulează"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Terminat"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Rezultate media"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index c32f93a..004b2b6 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Приложение сможет выполнять действия во всех аккаунтах на этом устройстве. При этом защита от вредоносных приложений может быть недостаточной."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"разрешить полное взаимодействие со всеми аккаунтами"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Приложение сможет выполнять любые действия во всех аккаунтах на этом устройстве."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"Управлять аккаунтами"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Приложения смогут управлять аккаунтами на этом устройстве (выполнять поиск, создавать и удалять их)"</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"получение сведений о работающих приложениях"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Приложение сможет получать подробные сведения о недавно запущенных и выполняемых задачах. При этом конфиденциальная информация о других приложениях не будет защищена от вредоносных программ."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"Упорядочивание запущенных приложений"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Воспроизведение звука через Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Перенаправлять поток мультимедиа"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 3464faa..15c359c 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Umožňuje aplikácii vykonávať akcie naprieč rôznymi používateľmi zariadenia. Škodlivé aplikácie môžu toto povolenie zneužiť na obídenie ochrany medzi používateľmi."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"plná licencia na interakcie naprieč používateľmi"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Umožňuje všetky možné interakcie naprieč používateľmi."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"správa používateľov"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Umožňuje aplikáciám spravovať používateľov v zariadení, vrátane vyhľadávania dopytov, vytvorenia a odstránenia."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"načítať podrobnosti o spustených aplikáciách"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Umožňuje aplikácii načítať podrobné informácie o aktuálnych a nedávno spustených úlohách. Škodlivé aplikácie môžu odhaliť súkromné informácie o iných aplikáciách."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"zmeniť poradie spustených aplikácií"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Hotovo"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Výstup médií"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 35246b1..1ede6b7 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Aplikaciji omogoča izvajanje dejanj za različne uporabnike v napravi. Zlonamerne aplikacije lahko to uporabijo za kršitev zaščite med uporabniki."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"polna licenca za interakcijo z uporabniki"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Dovoli vso mogočo interakcijo z uporabniki"</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"upravljanje uporabnikov"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Aplikacijam omogoča upravljanje uporabnikov v napravi, vključno z iskanjem, ustvarjanjem in brisanjem."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"prejemanje podrobnosti o aplikacijah, ki se izvajajo"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Aplikaciji omogoča, da dobi podatke o trenutnih in nedavno izvajajočih se opravilih. Zlonamerne aplikacije lahko odkrijejo zasebne podatke o drugih aplikacijah."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"preurejanje programov, ki se izvajajo"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Zvok prek Bluetootha"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Končano"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Izhod predstavnosti"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Vgrajen zaslon"</string>
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index d5c0561..e4cf347 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Дозвољава апликацији да обавља радње између различитих корисника на уређају. Злонамерне апликације могу да користе ово да би угрозиле заштиту између корисника."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"пуна лиценца за интеракцију између корисника"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Дозвољава све могуће интеракције између корисника."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"управљање корисницима"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Дозвољава апликацијама да управљају корисницима на уређају, укључујући постављање упита, прављење и брисање."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"преузимање детаља о покренутим апликацијама"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Дозвољава апликацији да преузима детаљне информације о актуелним и недавно покренутим задацима. Злонамерне апликације могу да открију приватне информације о другим апликацијама."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"промена редоследа покренутих апликација"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth аудио"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Излаз медија"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 89c0796..493a0bb 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Tillåter att appen utför åtgärder mellan användare på enheten. Skadliga appar kan använda detta som ett sätt att kringgå skyddet mellan användare."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"fullständig behörighet att interagera mellan användare"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Tillåter all slags interaktion mellan användare."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"hantera användare"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Tillåter att appen hanterar användare på enheten, inklusive att söka efter, skapa och radera användarinformation."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"hämta information om aktiva appar"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Tillåter att appen hämtar detaljerad information om uppgifter som körs och har körts. Skadliga appar kan upptäcka personliga uppgifter om andra appar."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"byt ordning på appar som körs"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ljud"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Klar"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Medieuppspelning"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Inbyggd skärm"</string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 3fd7af0..759000d 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Inaruhusu programu kutenda vitendo kwa watumiaji tofauti kwenye kifaa. Programu hasidi huenda zikatumia hii ili kukiuka ulinzi kati ya watumiaji."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"leseni kamili ili kutagusana na watumiaji"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Inaruhusu miingialiano yote inayowezekana kwa watumiaji."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"dhibiti watumiaji"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Inaruhusu programu kudhibiti watumiaji kwenye kifaa, pamoja na hoji, uundaji na ufutaji."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"epua maelezo ya programu zinazoendeshwa"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Huruhusu programu kuepua maelezo tondoti kuhusu kazi za sasa na zinazoendelea hivi karibuni. Programu hasidi huenda zikagundua maelezo ya kibinafsi kuhusu programu zingine."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"Agiza tena programu za kuendeshwa"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Sauti ya Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Kwisha"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Towe la midia"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Skrini Iliyojengewa ndani"</string>
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 61e25b2..c25e6db 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"อนุญาตให้แอปพลิเคชันทำงานได้กับผู้ใช้หลายรายบนอุปกรณ์นี้ แอปพลิเคชันที่เป็นอันตรายอาจใช้การทำงานนี้ในการบุกรุกการป้องกันระหว่างผู้ใช้"</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"ใบอนุญาตฉบับเต็มสำหรับการโต้ตอบระหว่างผู้ใช้"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"อนุญาตให้ทำการโต้ตอบทุกชนิดที่เป็นไปได้กับผู้ใช้ต่างๆ"</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"จัดการผู้ใช้"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"อนุญาตให้แอปพลิเคชันจัดการผู้ใช้บนอุปกรณ์ รวมทั้งการถามคำถาม การสร้าง และการลบ"</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"ดึงรายละเอียดของแอปที่ทำงานอยู่"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"อนุญาตให้แอปพลิเคชันดึงข้อมูลเกี่ยวกับงานที่กำลังเรียกใช้อยู่ในปัจจุบันและงานล่าสุด แอปพลิเคชันที่เป็นอันตรายอาจค้นพบข้อมูลเฉพาะตัวเกี่ยวกับแอปพลิเคชันอื่นๆ"</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"จัดลำดับแอปพลิเคชันที่ทำงานอยู่ใหม่"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"เสียงบลูทูธ"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"เสร็จสิ้น"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"เอาต์พุตสื่อ"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index adf7ef2..ab4ff29 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Binibigyang-daan ang app upang magsagawa ng mga pagkilos sa kabuuan ng iba\'t ibang mga user sa device. Maaari itong gamitin ng nakakahamak na apps upang lumabag sa proteksyon sa pagitan ng mga user."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"ganap na lisensya upang makipag-ugnayan sa kabuuan ng mga user"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Pinapayagan ang lahat ng posibleng pakikipag-ugnayan sa kabuuan ng mga user."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"pamahalaan ang mga user"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Binibigyang-daan ang apps na mamahala ng mga user sa device, kabilang ang query, paglikha at pagtanggal."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"bawiin ang mga detalye ng gumaganang apps"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Binibigyang-daan ang app na bawiin ang detalyadong impormasyon tungkol sa mga kasalukuyan at kamakailang gumaganang gawain. Maaaring makatuklas ang nakakahamak na apps ng pribadong impormasyon tungkol sa iba pang apps."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"muling isaayos ang tumatakbong apps"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio sa Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Tapos na"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Output ng media"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e15402a..95637dc 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Uygulamaya cihazdaki farklı kullanıcılar arasında işlem gerçekleştirme izni verir. Kötü amaçlı uygulamalar bu izinle kullanıcılar arasındaki korumayı ihlal edebilir."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"kullanıcılar arasında etkileşim kurmak için tam izin"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Kullanıcılar arasında tüm etkileşime izin verir."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"kullanıcıları yönet"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Uygulamalara, sorgulama, oluşturma ve silme işlemleri de dahil olmak üzere cihazdaki kullanıcıları yönetme izni verir."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"çalışan uygulamaların ayrıntılarını al"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Uygulamaya, şu anda çalışmakta olan ve son çalışan işlemler hakkında ayrıntılı bilgi alma izni verir. Kötü amaçlı uygulamalar diğer uygulamalar hakkında gizli bilgileri ele geçirebilir."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"çalışan uygulamaları yeniden sırala"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth ses"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Tamamlandı"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Medya çıkışı"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index d37cbd8..a8633e8 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Дозволяє програмі виконувати дії щодо різних користувачів на пристрої. Шкідливі програми можуть використовувати це для порушення захисту окремих користувачів."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"повна ліцензія на взаємодію між користувачами"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Дозволяє всі можливі взаємодії щодо користувачів."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"керувати користувачами"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Дозволяє програмам керувати користувачами на пристрої, зокрема надсилати запити про користувачів, створювати й видаляти їх."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"отримувати дані про запущені програми"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Дозволяє програмі отримувати інформацію про поточні й останні запущені завдання. Шкідливі програми можуть виявляти особисту інформацію про інші програми."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"змінювати порядок запущених програм"</string>
@@ -1309,4 +1311,5 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Аудіо Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Вивід медіа-даних"</string>
+ <string name="display_manager_built_in_display" msgid="9042666544146043569">"Вбудований екран"</string>
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 8ce6f4e..384a1ee 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Cho phép ứng dụng thực hiện hành động giữa những người dùng khác trên thiết bị. Ứng dụng độc hại có thể sử dụng quyền này để vi phạm khả năng bảo vệ giữa người dùng."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"cấp phép đầy đủ để tương tác giữa người dùng"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Cho phép tất cả các tương tác giữa người dùng."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"quản lý người dùng"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Cho phép ứng dụng quản lý người dùng trên thiết bị, bao gồm truy vấn, tạo và xóa."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"truy xuất chi tiết về các ứng dụng đang chạy"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Cho phép ứng dụng truy xuất thông tin chi tiết về các tác vụ đã và đang chạy gần đây. Ứng dụng độc hại có thể phát hiện thông tin riêng tư về các ứng dụng khác."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"sắp xếp lại những ứng dụng đang chạy"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Âm thanh Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Xong"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Đầu ra phương tiện"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 4a9cd5a..289dcf8 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -155,7 +155,7 @@
<string name="global_action_lock" msgid="2844945191792119712">"屏幕锁定"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"关机"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"错误报告"</string>
- <string name="bugreport_title" msgid="2667494803742548533">"获取错误报告"</string>
+ <string name="bugreport_title" msgid="2667494803742548533">"提交错误报告"</string>
<string name="bugreport_message" msgid="398447048750350456">"这会收集有关当前设备状态的信息,并以电子邮件的形式进行发送。从开始生成错误报告到准备好发送需要一点时间,请耐心等待。"</string>
<string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"静音模式"</string>
<string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"声音已关闭"</string>
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"允许该应用在设备上跨多个用户执行操作。恶意应用可能会借此破坏用户之间的保护措施。"</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"完全允许在用户之间进行互动"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"允许在用户之间进行所有可能的互动。"</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"管理用户"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"允许应用管理设备上的用户(包括查询、创建和删除用户)。"</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"检索正在运行的应用的详细信息"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"允许该应用检索当前正在运行和近期运行的任务的详细信息。恶意应用可能会发现有关其他应用的私密信息。"</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"对正在运行的应用重新排序"</string>
@@ -1068,13 +1070,13 @@
<string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"新增:"</font></string>
<string name="perms_description_app" msgid="5139836143293299417">"由“<xliff:g id="APP_NAME">%1$s</xliff:g>”提供。"</string>
<string name="usb_storage_activity_title" msgid="4465055157209648641">"USB 大容量存储设备"</string>
- <string name="usb_storage_title" msgid="5901459041398751495">"USB 已连接"</string>
+ <string name="usb_storage_title" msgid="5901459041398751495">"已连接 USB"</string>
<string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"您已通过 USB 连接至计算机。如果您要在计算机与 Android 设备的 USB 存储设备之间复制文件,请触摸下面的按钮。"</string>
<string name="usb_storage_message" product="default" msgid="805351000446037811">"您已通过 USB 连接至计算机。如果您要在计算机和 Android 设备的 SD 卡之间复制文件,请触摸下面的按钮。"</string>
<string name="usb_storage_button_mount" msgid="1052259930369508235">"打开 USB 存储设备"</string>
<string name="usb_storage_error_message" product="nosdcard" msgid="3017045217365540658">"使用 USB 存储设备作为 USB 大容量存储设备时出现问题。"</string>
<string name="usb_storage_error_message" product="default" msgid="2876018512716970313">"使用 SD 卡作为 USB 大容量存储设备时出现问题。"</string>
- <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB 已连接"</string>
+ <string name="usb_storage_notification_title" msgid="8175892554757216525">"已连接 USB"</string>
<string name="usb_storage_notification_message" msgid="939822783828183763">"触摸可将文件复制到计算机或从计算机复制到存储设备。"</string>
<string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"关闭 USB 存储设备"</string>
<string name="usb_storage_stop_notification_message" msgid="1656852098555623822">"触摸可关闭 USB 存储设备。"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"蓝牙音频"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"完成"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"媒体输出线路"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 20a15d1..96ba8c1 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"允許應用程式對裝置上的所有使用者執行各種動作。請注意,惡意應用程式可能利用此功能侵害使用者之間的保護機制。"</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"完整授權對所有使用者執行各種動作"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"允許對所有使用者執行各種可能的動作。"</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"管理使用者"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"允許應用程式管理裝置上的使用者,包括查詢、建立及刪除使用者。"</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"擷取執行中應用程式的詳細資訊"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"允許應用程式擷取目前及最近所執行任務的詳細資訊。請注意,惡意應用程式可能會找出其他應用程式的不公開資訊。"</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"重新排序正在執行的應用程式"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"藍牙音訊"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"完成"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"媒體輸出"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 8978e52..2a17f8f 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -224,6 +224,8 @@
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Ivumela uhlelo lokusebenza ukwenza izenzo kubasebenzisi bonke kudivayisi. Izinhlelo zokusebenza ezingalungile zingasebenzisa lokhu ukwephula ukuvikela phakathi kwabasebenzisi."</string>
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"ilayisensi egcwele yokuhlanganyela kubasebenzisi"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Ivumela konke ukuhlanganyela phakathi kwabasebenzisi."</string>
+ <string name="permlab_manageUsers" msgid="1676150911672282428">"phatha abasebenzisi"</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Ivumela izinhlelo zokusebenza ukuphatha abasebenzisi kudivayisi, kufaka phakathi umbuzo, ukudala nokususa."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"thola kabusha imininingwane yezinhlelo zokusebenza ezisebenzayo"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Ivumela uhlelo lokusebenza ukuthola kabusha ulwazi mayelana nezinto ezenzeka manje nezisanda kwenzeka. Izinhlelo zokusebenza ezingalungile zingathola imininingwane eyimfihlo mayelana nezinye izinhlelo zokusebenza."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"misa kabusha izinsiza ezisebenzayo"</string>
@@ -1309,4 +1311,6 @@
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Umsindo we-Bluetooth"</string>
<string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Qedile"</string>
<string name="media_route_button_content_description" msgid="5758553567065145276">"Okukhiphayo kwemidiya"</string>
+ <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+ <skip />
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 38a431f..0d190ee 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -479,6 +479,7 @@
<java-symbol type="string" name="decline" />
<java-symbol type="string" name="default_text_encoding" />
<java-symbol type="string" name="description_target_unlock_tablet" />
+ <java-symbol type="string" name="display_manager_built_in_display" />
<java-symbol type="string" name="double_tap_toast" />
<java-symbol type="string" name="elapsed_time_short_format_h_mm_ss" />
<java-symbol type="string" name="elapsed_time_short_format_mm_ss" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 352c409..b7ad1e9 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -567,6 +567,11 @@
<string name="permdesc_interactAcrossUsersFull">Allows all possible interactions across
users.</string>
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to create/remove/query users. [CHAR LIMIT=none] -->
+ <string name="permlab_manageUsers">manage users</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to create/remove/query users. [CHAR LIMIT=NONE] -->
+ <string name="permdesc_manageUsers">Allows apps to manage users on the device, including query, creation and deletion.</string>
+
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=50] -->
<string name="permlab_getDetailedTasks">retrieve details of running apps</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
@@ -3634,4 +3639,9 @@
<!-- Content description of a MediaRouteButton for accessibility support -->
<string name="media_route_button_content_description">Media output</string>
+ <!-- Display manager service -->
+
+ <!-- Name of the built-in display. [CHAR LIMIT=50] -->
+ <string name="display_manager_built_in_display">Built-in Screen</string>
+
</resources>
diff --git a/core/tests/coretests/src/android/content/pm/AppCacheTest.java b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
index 8d53db9..aae55e8 100755
--- a/core/tests/coretests/src/android/content/pm/AppCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
@@ -570,7 +570,7 @@ public class AppCacheTest extends AndroidTestCase {
PackageStatsObserver observer = new PackageStatsObserver();
//wait on observer
synchronized(observer) {
- getPm().getPackageSizeInfo(packageName, observer);
+ getPm().getPackageSizeInfo(packageName, UserHandle.myUserId(), observer);
long waitTime = 0;
while((!observer.isDone()) || (waitTime > MAX_WAIT_TIME) ) {
observer.wait(WAIT_TIME_INCR);
diff --git a/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
new file mode 100644
index 0000000..b814e2d
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.content.pm.ManifestDigest;
+import android.content.pm.VerificationParams;
+import android.net.Uri;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+/**
+ * Tests the android.content.pm.VerificationParams class
+ *
+ * To test run:
+ * ./development/testrunner/runtest.py frameworks-core -c android.content.pm.VerificationParamsTest
+ */
+public class VerificationParamsTest extends AndroidTestCase {
+
+ private final static String VERIFICATION_URI_STRING = "http://verification.uri/path";
+ private final static String ORIGINATING_URI_STRING = "http://originating.uri/path";
+ private final static String REFERRER_STRING = "http://referrer.uri/path";
+ private final static byte[] DIGEST_BYTES = "fake digest".getBytes();
+
+ private final static Uri VERIFICATION_URI = Uri.parse(VERIFICATION_URI_STRING);
+ private final static Uri ORIGINATING_URI = Uri.parse(ORIGINATING_URI_STRING);
+ private final static Uri REFERRER = Uri.parse(REFERRER_STRING);
+
+ private final static ManifestDigest MANIFEST_DIGEST = new ManifestDigest(DIGEST_BYTES);
+
+ public void testParcel() throws Exception {
+ VerificationParams expected = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+ REFERRER, MANIFEST_DIGEST);
+
+ Parcel parcel = Parcel.obtain();
+ expected.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ VerificationParams actual = VerificationParams.CREATOR.createFromParcel(parcel);
+
+ assertEquals(VERIFICATION_URI, actual.getVerificationURI());
+
+ assertEquals(ORIGINATING_URI, actual.getOriginatingURI());
+
+ assertEquals(REFERRER, actual.getReferrer());
+
+ assertEquals(MANIFEST_DIGEST, actual.getManifestDigest());
+ }
+
+ public void testEquals_Success() throws Exception {
+ VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+ REFERRER, MANIFEST_DIGEST);
+
+ VerificationParams params2 = new VerificationParams(
+ Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+ Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+ assertEquals(params1, params2);
+ }
+
+ public void testEquals_VerificationUri_Failure() throws Exception {
+ VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+ REFERRER, MANIFEST_DIGEST);
+
+ VerificationParams params2 = new VerificationParams(
+ Uri.parse("http://a.different.uri/"), Uri.parse(ORIGINATING_URI_STRING),
+ Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+ assertFalse(params1.equals(params2));
+ }
+
+ public void testEquals_OriginatingUri_Failure() throws Exception {
+ VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+ REFERRER, MANIFEST_DIGEST);
+
+ VerificationParams params2 = new VerificationParams(
+ Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
+ Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+ assertFalse(params1.equals(params2));
+ }
+
+ public void testEquals_Referrer_Failure() throws Exception {
+ VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+ REFERRER, MANIFEST_DIGEST);
+
+ VerificationParams params2 = new VerificationParams(
+ Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+ Uri.parse("http://a.different.uri/"), new ManifestDigest(DIGEST_BYTES));
+
+ assertFalse(params1.equals(params2));
+ }
+
+ public void testEquals_ManifestDigest_Failure() throws Exception {
+ VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+ REFERRER, MANIFEST_DIGEST);
+
+ VerificationParams params2 = new VerificationParams(
+ Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+ Uri.parse(REFERRER_STRING), new ManifestDigest("a different digest".getBytes()));
+
+ assertFalse(params1.equals(params2));
+ }
+
+ public void testHashCode_Success() throws Exception {
+ VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+ REFERRER, MANIFEST_DIGEST);
+
+ VerificationParams params2 = new VerificationParams(
+ Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+ Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+ assertEquals(params1.hashCode(), params2.hashCode());
+ }
+
+ public void testHashCode_VerificationUri_Failure() throws Exception {
+ VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+ REFERRER, MANIFEST_DIGEST);
+
+ VerificationParams params2 = new VerificationParams(null, Uri.parse(ORIGINATING_URI_STRING),
+ Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+ assertFalse(params1.hashCode() == params2.hashCode());
+ }
+
+ public void testHashCode_OriginatingUri_Failure() throws Exception {
+ VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+ REFERRER, MANIFEST_DIGEST);
+
+ VerificationParams params2 = new VerificationParams(
+ Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
+ Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+ assertFalse(params1.hashCode() == params2.hashCode());
+ }
+
+ public void testHashCode_Referrer_Failure() throws Exception {
+ VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+ REFERRER, MANIFEST_DIGEST);
+
+ VerificationParams params2 = new VerificationParams(
+ Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING), null,
+ new ManifestDigest(DIGEST_BYTES));
+
+ assertFalse(params1.hashCode() == params2.hashCode());
+ }
+
+ public void testHashCode_ManifestDigest_Failure() throws Exception {
+ VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+ REFERRER, MANIFEST_DIGEST);
+
+ VerificationParams params2 = new VerificationParams(
+ Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+ Uri.parse(REFERRER_STRING), new ManifestDigest("a different digest".getBytes()));
+
+ assertFalse(params1.hashCode() == params2.hashCode());
+ }
+}
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index f12cbe1..4d0b892 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -17,21 +17,13 @@
package android.os;
import android.content.Context;
-import android.os.FileUtils;
-import android.os.FileUtils.FileStatus;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
import java.io.ByteArrayInputStream;
import java.io.File;
-import java.io.FileWriter;
-import java.io.FileNotFoundException;
import java.io.FileOutputStream;
-import java.io.IOException;
-
-import junit.framework.Assert;
+import java.io.FileWriter;
public class FileUtilsTest extends AndroidTestCase {
private static final String TEST_DATA =
@@ -60,60 +52,6 @@ public class FileUtilsTest extends AndroidTestCase {
if (mCopyFile.exists()) mCopyFile.delete();
}
- @LargeTest
- public void testGetFileStatus() {
- final byte[] MAGIC = { 0xB, 0xE, 0x0, 0x5 };
-
- try {
- // truncate test file and write MAGIC (4 bytes) to it.
- FileOutputStream os = new FileOutputStream(mTestFile, false);
- os.write(MAGIC, 0, 4);
- os.flush();
- os.close();
- } catch (FileNotFoundException e) {
- Assert.fail("File was removed durning test" + e);
- } catch (IOException e) {
- Assert.fail("Unexpected IOException: " + e);
- }
-
- Assert.assertTrue(mTestFile.exists());
- Assert.assertTrue(FileUtils.getFileStatus(mTestFile.getPath(), null));
-
- FileStatus status1 = new FileStatus();
- FileUtils.getFileStatus(mTestFile.getPath(), status1);
-
- Assert.assertEquals(4, status1.size);
-
- // Sleep for at least one second so that the modification time will be different.
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- }
-
- try {
- // append so we don't change the creation time.
- FileOutputStream os = new FileOutputStream(mTestFile, true);
- os.write(MAGIC, 0, 4);
- os.flush();
- os.close();
- } catch (FileNotFoundException e) {
- Assert.fail("File was removed durning test" + e);
- } catch (IOException e) {
- Assert.fail("Unexpected IOException: " + e);
- }
-
- FileStatus status2 = new FileStatus();
- FileUtils.getFileStatus(mTestFile.getPath(), status2);
-
- Assert.assertEquals(8, status2.size);
- Assert.assertTrue(status2.mtime > status1.mtime);
-
- mTestFile.delete();
-
- Assert.assertFalse(mTestFile.exists());
- Assert.assertFalse(FileUtils.getFileStatus(mTestFile.getPath(), null));
- }
-
// TODO: test setPermissions(), getPermissions()
@MediumTest
diff --git a/data/etc/Android.mk b/data/etc/Android.mk
index 71a9a15..134ac0c 100644
--- a/data/etc/Android.mk
+++ b/data/etc/Android.mk
@@ -21,8 +21,6 @@ include $(CLEAR_VARS)
LOCAL_MODULE := platform.xml
-LOCAL_MODULE_TAGS := user
-
LOCAL_MODULE_CLASS := ETC
# This will install the file in /system/etc/permissions
@@ -38,8 +36,6 @@ include $(BUILD_PREBUILT)
#LOCAL_MODULE := required_hardware.xml
-#LOCAL_MODULE_TAGS := user
-
#LOCAL_MODULE_CLASS := ETC
# This will install the file in /system/etc/permissions
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 3d6c9d3..7bc172c 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -76,14 +76,6 @@ LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts
include $(BUILD_PREBUILT)
-include $(CLEAR_VARS)
-LOCAL_MODULE := fallback_fonts-ja.xml
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
-include $(BUILD_PREBUILT)
-
droidsans_fallback_src := DroidSansFallbackFull.ttf
extra_font_files := \
DroidSans.ttf \
@@ -91,8 +83,7 @@ extra_font_files := \
DroidSansEthiopic-Regular.ttf \
DroidSansTamil-Regular.ttf \
DroidSansTamil-Bold.ttf \
- MTLmr3m.ttf \
- fallback_fonts-ja.xml
+ MTLmr3m.ttf
endif # SMALLER_FONT_FOOTPRINT
################################
diff --git a/data/fonts/fallback_fonts-ja.xml b/data/fonts/fallback_fonts-ja.xml
deleted file mode 100644
index 82e3a38..0000000
--- a/data/fonts/fallback_fonts-ja.xml
+++ /dev/null
@@ -1,121 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Fallback Fonts
-
- This file specifies the fonts, and the priority order, that will be searched for any
- glyphs not handled by the default fonts specified in /system/etc/system_fonts.xml.
- Each entry consists of a family tag and a list of files (file names) which support that
- family. The fonts for each family are listed in the order of the styles that they
- handle (the order is: regular, bold, italic, and bold-italic). The order in which the
- families are listed in this file represents the order in which these fallback fonts
- will be searched for glyphs that are not supported by the default system fonts (which are
- found in /system/etc/system_fonts.xml).
-
- Note that there is not nameset for fallback fonts, unlike the fonts specified in
- system_fonts.xml. The ability to support specific names in fallback fonts may be supported
- in the future. For now, the lack of files entries here is an indicator to the system that
- these are fallback fonts, instead of default named system fonts.
-
- There is another optional file in /vendor/etc/fallback_fonts.xml. That file can be used to
- provide references to other font families that should be used in addition to the default
- fallback fonts. That file can also specify the order in which the fallback fonts should be
- searched, to ensure that a vendor-provided font will be used before another fallback font
- which happens to handle the same glyph.
-
- Han languages (Chinese, Japanese, and Korean) share a common range of unicode characters;
- their ordering in the fallback or vendor files gives priority to the first in the list.
- Locale-specific ordering can be configured by adding language and region codes to the end
- of the filename (e.g. /system/etc/fallback_fonts-ja.xml). When no region code is used,
- as with this example, all regions are matched. Use separate files for each supported locale.
- The standard fallback file (fallback_fonts.xml) is used when a locale does not have its own
- file. All fallback files must contain the same complete set of fonts; only their ordering
- can differ.
--->
-<familyset>
- <family>
- <fileset>
- <file variant="elegant">DroidNaskh-Regular.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
- <file variant="compact">DroidNaskh-Regular-SystemUI.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
- <file>DroidSansEthiopic-Regular.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
- <file>DroidSansHebrew-Regular.ttf</file>
- <file>DroidSansHebrew-Bold.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
- <file>DroidSansThai.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
- <file>DroidSansArmenian.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
- <file>DroidSansGeorgian.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
- <file>DroidSansDevanagari-Regular.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
- <file>DroidSansTamil-Regular.ttf</file>
- <file>DroidSansTamil-Bold.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
- <file>AnjaliNewLipi-light.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
- <file>Lohit-Bengali.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
- <file>Lohit-Kannada.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
- <file>AndroidEmoji.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
- <file>MTLmr3m.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
- <file>DroidSansFallback.ttf</file>
- </fileset>
- </family>
- <!--
- Fonts below this point have problematic glyphs and should not be moved
- higher in the fallback list until those glyphs have been fixed.
- -->
- <family>
- <fileset>
- <file>Lohit-Telugu.ttf</file> <!-- masks U+FFBC-10007 -->
- </fileset>
- </family>
-</familyset>
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index 758adb5..2c9a0c8 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -24,12 +24,9 @@
Han languages (Chinese, Japanese, and Korean) share a common range of unicode characters;
their ordering in the fallback or vendor files gives priority to the first in the list.
- Locale-specific ordering can be configured by adding language and region codes to the end
- of the filename (e.g. /system/etc/fallback_fonts-ja.xml). When no region code is used,
- as with this example, all regions are matched. Use separate files for each supported locale.
- The standard fallback file (fallback_fonts.xml) is used when a locale does not have its own
- file. All fallback files must contain the same complete set of fonts; only their ordering
- can differ.
+ Language-specific ordering can be configured by adding a BCP 47-style "lang" attribute to
+ a "file" element; fonts matching the language of text being drawn will be prioritised over
+ all others.
-->
<familyset>
<family>
@@ -106,7 +103,7 @@
</family>
<family>
<fileset>
- <file>MTLmr3m.ttf</file>
+ <file lang="ja">MTLmr3m.ttf</file>
</fileset>
</family>
<!--
diff --git a/data/fonts/vendor_fonts.xml b/data/fonts/vendor_fonts.xml
index 5850f94..8690ee1 100644
--- a/data/fonts/vendor_fonts.xml
+++ b/data/fonts/vendor_fonts.xml
@@ -7,8 +7,7 @@
that in your makefile, this directory should be referenced as $(TARGET_COPY_OUT_VENDOR)/etc/:
PRODUCT_COPY_FILES += \
- frameworks/base/data/fonts/vendor_fonts.xml:$(TARGET_COPY_OUT_VENDOR)/etc/fallback_fonts.xml \
- frameworks/base/data/fonts/vendor_fonts-ja.xml:$(TARGET_COPY_OUT_VENDOR)/etc/fallback_fonts-ja.xml
+ frameworks/base/data/fonts/vendor_fonts.xml:$(TARGET_COPY_OUT_VENDOR)/etc/fallback_fonts.xml
For example, vendors might want to build configurations for locales that are
better served by fonts which either handle glyphs not supported in the default fonts or which
@@ -32,32 +31,9 @@
Han languages (Chinese, Japanese, and Korean) share a common range of unicode characters;
their ordering in the fallback or vendor files gives priority to the first in the list.
- Locale-specific ordering can be configured by adding language and region codes to the end
- of the filename (e.g. /vendor/etc/fallback_fonts-ja.xml). When no region code is used,
- as with this example, all regions are matched. Use separate files for each supported locale.
- The standard fallback file (fallback_fonts.xml) is used when a locale does not have its own
- file. All fallback files must contain the same complete set of fonts; only their ordering
- can differ. For example, on a device supporting Japanese, but with English as the default,
- /vendor/etc/fallback_fonts.xml might contain:
-
- <familyset>
- <family>
- <fileset>
- <file>DroidSansJapanese.ttf</file>
- </fileset>
- </family>
- </familyset>
-
- placing the Japanese font at the end of the fallback sequence for English, with a corresponding
- /system/vendor/etc/fallback_fonts-ja.xml, placing it at the front of the list.
-
- <familyset>
- <family order="0">
- <fileset>
- <file>DroidSansJapanese.ttf</file>
- </fileset>
- </family>
- </familyset>
+ Language-specific ordering can be configured by adding a BCP 47-style "lang" attribute to
+ a "file" element; fonts matching the language of text being drawn will be prioritised over
+ all others.
The sample configuration below is an example of how one might provide two families of fonts
that get inserted at the first and second (0 and 1) position in the overall fallback fonts.
@@ -82,4 +58,4 @@
</fileset>
</family>
</familyset>
---> \ No newline at end of file
+--->
diff --git a/docs/html/intl/ja/index.jd b/docs/html/intl/ja/index.jd
deleted file mode 100644
index ac36f90..0000000
--- a/docs/html/intl/ja/index.jd
+++ /dev/null
@@ -1,159 +0,0 @@
-home=true
-@jd:body
-
-
- <div id="mainBodyFixed">
- <div id="mainBodyLeft">
- <div id="homeMiddle">
- <div id="topAnnouncement">
- <div id="homeTitle">
- <h2>デベロッパーへのお知らせ</h2>
- </div><!-- end homeTitle -->
- <div id="announcement-block">
- <!-- total max width is 520px -->
- <img src="/assets/images/home/android_adc.png" alt="Android Developer Challenge 2" width="232px" />
- <div id="announcement" style="width:275px">
- <p>第2Android Developer Challengeが、遂に登場しました!このアプリケーション開発コンテストでは、Androidのユーザなら誰でも簡単に参加でき、一等の賞金は$250,000 です。登録の締切日は8月31日になります。</p>
- <p><a href="http://code.google.com/android/adc/">Android Developer Challengeについて詳しくはこちら &raquo;</a></p>
- </div> <!-- end annoucement -->
- </div> <!-- end annoucement-block -->
- </div><!-- end topAnnouncement -->
- <div id="carouselMain" style="height:210px"> <!-- this height can be adjusted based on the content height -->
- </div>
- <div class="clearer"></div>
- <div id="carouselWheel">
- <div class="app-list-container" align="center">
- <a href="javascript:{}" id="arrow-left" onclick="" class="arrow-left-off"></a>
- <div id="list-clip">
- <div style="left: 0px;" id="app-list">
- <!-- populated by buildCarousel() -->
- </div>
- </div><!-- end list-clip -->
- <a href="javascript:{ page_right(); }" id="arrow-right" onclick="" class="arrow-right-on"></a>
- <div class="clearer"></div>
- </div><!-- end app-list container -->
- </div><!-- end carouselWheel -->
- </div><!-- end homeMiddle -->
-
- <div style="clear:both">&nbsp;</div>
- </div><!-- end mainBodyLeft -->
-
- <div id="mainBodyRight">
- <table id="rightColumn">
- <tr>
- <td class="imageCell"><a href="{@docRoot}sdk/index.html"><img src="{@docRoot}assets/images/icon_download.jpg" style="padding:0" /></a></td>
- <td>
- <h2 class="green">ダウンロード</h2>
- <p>Android SDK には、優れたアプリケーションの作成に必要となるツール、サンプル コード、ドキュメントが含まれています。 </p>
- <p><a href="{@docRoot}sdk/index.html">詳細 &raquo;</a></p>
- </td>
- </tr>
- <tr>
- <td colspan="2"><div class="seperator">&nbsp;</div></td>
- </tr>
- <tr>
- <td class="imageCell"><a href="http://play.google.com/apps/publish"><img src="{@docRoot}assets/images/icon_play.png" style="padding:0" /></a></td>
- <td>
- <h2 class="green">公開</h2>
- <p>Android マーケットは、アプリケーションを携帯端末に配信するためのオープン サービスです。</p>
- <p><a href="http://play.google.com/apps/publish">詳細 &raquo;</a></p>
- </td>
- </tr>
- <tr>
- <td colspan="2"><div class="seperator">&nbsp;</div></td>
- </tr>
- <tr>
- <td class="imageCell"><a href="http://source.android.com"><img src="{@docRoot}assets/images/icon_contribute.jpg" style="padding:0" /></a></td>
- <td>
- <h2 class="green">貢献</h2>
- <p>Android オープンソース プロジェクトでは、プラットフォーム全体のソースコードを公開しています。</p>
- <p><a href="http://source.android.com">詳細 &raquo;</a></p>
- </td>
- </tr>
- <tr>
- <td colspan="2"><div class="seperator">&nbsp;</div></td>
- </tr>
- <tr>
- <td class="imageCell"><a href="http://www.youtube.com/user/androiddevelopers"><img src="{@docRoot}assets/images/video-droid.png" style="padding:0" /></a></td>
- <td>
- <h2 class="green">再生</h2>
- <object width="150" height="140"><param name="movie" value="http://www.youtube.com/v/GARMe7Km_gk&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/GARMe7Km_gk&hl=en&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="150" height="140"></embed></object>
- <p style="margin-top:1em"><a href="{@docRoot}videos/index.html">その他の Android 動画 &raquo;</a></p>
- </td>
- </tr>
-
- </table>
- </div>
- </div>
-
-<!--[if lte IE 6]>
- <style>
- #arrow-left {
- margin:0 0 0 5px;
- }
- #arrow-right {
- margin-left:0;
- }
- .app-list-container {
- margin: 37px 0 0 23px;
- }
- div#list-clip {
- width:468px;
- }
- </style>
-<![endif]-->
-
-<script type="text/javascript">
-
-// * -- carousel dictionary -- * //
- /* layout: imgLeft, imgRight, imgTop
- icon: image for carousel entry. cropped (height:70px, width:90px)
- name: string for carousel entry
- img: image for bulletin post. cropped (height: 170, width:230px)
- title: header for bulletin (optional, insert "" value to skip
- desc: the bulletin post. must include html tags.
- */
-
- var droidList = {
- 'sdk': {
- 'layout':"imgLeft",
- 'icon':"sdk-small.png",
- 'name':"Android 2.0",
- 'img':"eclair-android.png",
- 'title':"Android 2.0",
- 'desc': "<p>Android 2.0 の最新バージョンが公開されました。このリリースには Android 2.0 用の API、最新版デベロッパーツール、複数プラットフォーム(バージョン)サポート、そして Google API のアドオンが含まれています。</p><p><a href='{@docRoot}sdk/index.html'>Android SDK をダウンロード &raquo;</a></p>"
- },
-
- 'io': {
- 'layout':"imgLeft",
- 'icon':"io-small.png",
- 'name':"Google I/O",
- 'img':"io-large.png",
- 'title':"Google I/O Developer Conference",
- 'desc': "<p>Google I/O は、サンフランシスコの Moscone Center で 5 月 27~28 日に開催された開発者会議です。このイベントに参加できなかった方は、各アンドロイド向けセッションを、YouTube ビデオ資料で体験する事が可能<nobr>です</nobr>。</p><p><a href='{@docRoot}videos/index.html'>セッションを参照してください &raquo;</a></p>"
- },
-
- 'mapskey': {
- 'layout':"imgLeft",
- 'icon':"maps-small.png",
- 'name':"Maps API キー",
- 'img':"maps-large.png",
- 'title':"Maps API キー",
- 'desc':"<p>MapView から Google マップを利用する Android アプリケーションを開発する場合は、アプリケーションを登録して Maps API キーを取得する必要があります。この API キーが無いアプリケーションは、Android 上で動作しません。キーの取得は、簡単な手順で行うことができます。</p><p><a href='http://code.google.com/android/add-ons/google-apis/maps-overview.html'>詳細 &raquo;</a></p>"
- },
-
- 'devphone': {
- 'layout':"imgLeft",
- 'icon':"devphone-small.png",
- 'name':"Dev Phone 1",
- 'img':"devphone-large.png",
- 'title':"Android Dev Phone 1",
- 'desc': "<p>この携帯電話を使用することで、開発した Android アプリケーションの実行とデバッグを行うことができます。Android オペレーティングシステムを変更してからリビルドし、携帯電話に書き込むことができます。Android Dev Phone 1 は携帯通信会社に依存しておらず、<a href='http://play.google.com/apps/publish'>Android マーケット</a>に登録済みのデベロッパーなら誰でも購入可能です。</p><p><a href='/tools/device.html#dev-phone-1'>Android Dev Phone 1 の詳細&raquo;</a></p>"
- }
-
- }
-</script>
-<script type="text/javascript" src="{@docRoot}assets/carousel.js"></script>
-<script type="text/javascript">
- initCarousel("sdk");
-</script>
diff --git a/drm/jni/Android.mk b/drm/jni/Android.mk
index f8ecc8c..fff7eee 100644
--- a/drm/jni/Android.mk
+++ b/drm/jni/Android.mk
@@ -35,7 +35,8 @@ LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
$(TOP)/frameworks/av/drm/libdrmframework/include \
$(TOP)/frameworks/av/drm/libdrmframework/plugins/common/include \
- $(TOP)/frameworks/av/include
+ $(TOP)/frameworks/av/include \
+ $(TOP)/libcore/include
diff --git a/drm/jni/android_drm_DrmManagerClient.cpp b/drm/jni/android_drm_DrmManagerClient.cpp
index 14ec4d6..fb685a2 100644
--- a/drm/jni/android_drm_DrmManagerClient.cpp
+++ b/drm/jni/android_drm_DrmManagerClient.cpp
@@ -20,6 +20,7 @@
#include <jni.h>
#include <JNIHelp.h>
+#include <ScopedLocalRef.h>
#include <android_runtime/AndroidRuntime.h>
#include <drm/DrmInfo.h>
@@ -250,16 +251,18 @@ static jobject android_drm_DrmManagerClient_getConstraintsFromContent(
= getDrmManagerClientImpl(env, thiz)->getConstraints(uniqueId, &pathString, usage);
jclass localRef = env->FindClass("android/content/ContentValues");
+ jmethodID ContentValues_putByteArray =
+ env->GetMethodID(localRef, "put", "(Ljava/lang/String;[B)V");
+ jmethodID ContentValues_putString =
+ env->GetMethodID(localRef, "put", "(Ljava/lang/String;Ljava/lang/String;)V");
+ jmethodID ContentValues_constructor = env->GetMethodID(localRef, "<init>", "()V");
jobject constraints = NULL;
if (NULL != localRef && NULL != pConstraints) {
- // Get the constructor id
- jmethodID constructorId = env->GetMethodID(localRef, "<init>", "()V");
// create the java DrmConstraints object
- constraints = env->NewObject(localRef, constructorId);
+ constraints = env->NewObject(localRef, ContentValues_constructor);
DrmConstraints::KeyIterator keyIt = pConstraints->keyIterator();
-
while (keyIt.hasNext()) {
String8 key = keyIt.next();
@@ -267,18 +270,18 @@ static jobject android_drm_DrmManagerClient_getConstraintsFromContent(
if (DrmConstraints::EXTENDED_METADATA == key) {
const char* value = pConstraints->getAsByteArray(&key);
if (NULL != value) {
- jbyteArray dataArray = env->NewByteArray(strlen(value));
- env->SetByteArrayRegion(dataArray, 0, strlen(value), (jbyte*)value);
- env->CallVoidMethod(
- constraints, env->GetMethodID(localRef, "put", "(Ljava/lang/String;[B)V"),
- env->NewStringUTF(key.string()), dataArray);
+ ScopedLocalRef<jbyteArray> dataArray(env, env->NewByteArray(strlen(value)));
+ ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
+ env->SetByteArrayRegion(dataArray.get(), 0, strlen(value), (jbyte*)value);
+ env->CallVoidMethod(constraints, ContentValues_putByteArray,
+ keyString.get(), dataArray.get());
}
} else {
String8 value = pConstraints->get(key);
- env->CallVoidMethod(
- constraints,
- env->GetMethodID(localRef, "put", "(Ljava/lang/String;Ljava/lang/String;)V"),
- env->NewStringUTF(key.string()), env->NewStringUTF(value.string()));
+ ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
+ ScopedLocalRef<jstring> valueString(env, env->NewStringUTF(value.string()));
+ env->CallVoidMethod(constraints, ContentValues_putString,
+ keyString.get(), valueString.get());
}
}
}
@@ -297,8 +300,10 @@ static jobject android_drm_DrmManagerClient_getMetadataFromContent(
jobject metadata = NULL;
- jclass localRef = NULL;
- localRef = env->FindClass("android/content/ContentValues");
+ jclass localRef = env->FindClass("android/content/ContentValues");
+ jmethodID ContentValues_putString =
+ env->GetMethodID(localRef, "put", "(Ljava/lang/String;Ljava/lang/String;)V");
+
if (NULL != localRef && NULL != pMetadata) {
// Get the constructor id
jmethodID constructorId = NULL;
@@ -313,9 +318,10 @@ static jobject android_drm_DrmManagerClient_getMetadataFromContent(
// insert the entry<constraintKey, constraintValue>
// to newly created java object
String8 value = pMetadata->get(key);
- env->CallVoidMethod(metadata, env->GetMethodID(localRef, "put",
- "(Ljava/lang/String;Ljava/lang/String;)V"),
- env->NewStringUTF(key.string()), env->NewStringUTF(value.string()));
+ ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
+ ScopedLocalRef<jstring> valueString(env, env->NewStringUTF(value.string()));
+ env->CallVoidMethod(metadata, ContentValues_putString,
+ keyString.get(), valueString.get());
}
}
}
@@ -426,29 +432,30 @@ static jobject android_drm_DrmManagerClient_processDrmInfo(
DrmInfo drmInfo(mInfoType, buffer, mMimeType);
jclass clazz = env->FindClass("android/drm/DrmInfo");
+ jmethodID DrmInfo_get = env->GetMethodID(clazz, "get", "(Ljava/lang/String;)Ljava/lang/Object;");
jobject keyIterator
= env->CallObjectMethod(drmInfoObject,
env->GetMethodID(clazz, "keyIterator", "()Ljava/util/Iterator;"));
- jmethodID hasNextId = env->GetMethodID(env->FindClass("java/util/Iterator"), "hasNext", "()Z");
-
- while (env->CallBooleanMethod(keyIterator, hasNextId)) {
- jstring key = (jstring) env->CallObjectMethod(keyIterator,
- env->GetMethodID(env->FindClass("java/util/Iterator"),
- "next", "()Ljava/lang/Object;"));
-
- jobject valueObject = env->CallObjectMethod(drmInfoObject,
- env->GetMethodID(clazz, "get", "(Ljava/lang/String;)Ljava/lang/Object;"), key);
-
- jstring valString = NULL;
- if (NULL != valueObject) {
- valString = (jstring) env->CallObjectMethod(valueObject,
- env->GetMethodID(env->FindClass("java/lang/Object"),
- "toString", "()Ljava/lang/String;"));
+ jclass Iterator_class = env->FindClass("java/util/Iterator");
+ jmethodID Iterator_hasNext = env->GetMethodID(Iterator_class, "hasNext", "()Z");
+ jmethodID Iterator_next = env->GetMethodID(Iterator_class, "next", "()Ljava/lang/Object;");
+
+ jclass Object_class = env->FindClass("java/lang/Object");
+ jmethodID Object_toString = env->GetMethodID(Object_class, "toString", "()Ljava/lang/String;");
+
+ while (env->CallBooleanMethod(keyIterator, Iterator_hasNext)) {
+ ScopedLocalRef<jstring> key(env,
+ (jstring) env->CallObjectMethod(keyIterator, Iterator_next));
+ ScopedLocalRef<jobject> valueObject(env,
+ env->CallObjectMethod(drmInfoObject, DrmInfo_get, key.get()));
+ ScopedLocalRef<jstring> valString(env, NULL);
+ if (NULL != valueObject.get()) {
+ valString.reset((jstring) env->CallObjectMethod(valueObject.get(), Object_toString));
}
- String8 keyString = Utility::getStringValue(env, key);
- String8 valueString = Utility::getStringValue(env, valString);
+ String8 keyString = Utility::getStringValue(env, key.get());
+ String8 valueString = Utility::getStringValue(env, valString.get());
ALOGV("Key: %s | Value: %s", keyString.string(), valueString.string());
drmInfo.put(keyString, valueString);
@@ -508,20 +515,21 @@ static jobject android_drm_DrmManagerClient_acquireDrmInfo(
jobject keyIterator
= env->CallObjectMethod(drmInfoRequest,
env->GetMethodID(clazz, "keyIterator", "()Ljava/util/Iterator;"));
+ jmethodID DrmInfoRequest_get = env->GetMethodID(clazz,
+ "get", "(Ljava/lang/String;)Ljava/lang/Object;");
- jmethodID hasNextId = env->GetMethodID(env->FindClass("java/util/Iterator"), "hasNext", "()Z");
+ jclass Iterator_class = env->FindClass("java/util/Iterator");
+ jmethodID Iterator_hasNext = env->GetMethodID(Iterator_class, "hasNext", "()Z");
+ jmethodID Iterator_next = env->GetMethodID(Iterator_class, "next", "()Ljava/lang/Object;");
- while (env->CallBooleanMethod(keyIterator, hasNextId)) {
- jstring key
- = (jstring) env->CallObjectMethod(keyIterator,
- env->GetMethodID(env->FindClass("java/util/Iterator"),
- "next", "()Ljava/lang/Object;"));
+ while (env->CallBooleanMethod(keyIterator, Iterator_hasNext)) {
+ ScopedLocalRef<jstring> key(env,
+ (jstring) env->CallObjectMethod(keyIterator, Iterator_next));
+ ScopedLocalRef<jstring> value(env,
+ (jstring) env->CallObjectMethod(drmInfoRequest, DrmInfoRequest_get, key.get()));
- jstring value = (jstring) env->CallObjectMethod(drmInfoRequest,
- env->GetMethodID(clazz, "get", "(Ljava/lang/String;)Ljava/lang/Object;"), key);
-
- String8 keyString = Utility::getStringValue(env, key);
- String8 valueString = Utility::getStringValue(env, value);
+ String8 keyString = Utility::getStringValue(env, key.get());
+ String8 valueString = Utility::getStringValue(env, value.get());
ALOGV("Key: %s | Value: %s", keyString.string(), valueString.string());
drmInfoReq.put(keyString, valueString);
@@ -552,9 +560,10 @@ static jobject android_drm_DrmManagerClient_acquireDrmInfo(
while (it.hasNext()) {
String8 key = it.next();
String8 value = pDrmInfo->get(key);
-
+ ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
+ ScopedLocalRef<jstring> valueString(env, env->NewStringUTF(value.string()));
env->CallVoidMethod(drmInfoObject, putMethodId,
- env->NewStringUTF(key.string()), env->NewStringUTF(value.string()));
+ keyString.get(), valueString.get());
}
}
delete [] pDrmInfo->getData().data;
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java
new file mode 100644
index 0000000..a629f8d
--- /dev/null
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
+
+import android.util.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyStoreException;
+import java.security.KeyStoreSpi;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * A java.security.KeyStore interface for the Android KeyStore. This class is
+ * hidden from the Android API, but an instance of it can be created via the
+ * {@link java.security.KeyStore#getInstance(String)
+ * KeyStore.getInstance("AndroidKeyStore")} interface. This returns a
+ * java.security.KeyStore backed by this "AndroidKeyStore" implementation.
+ * <p>
+ * This is built on top of Android's keystore daemon. The convention of alias
+ * use is:
+ * <p>
+ * PrivateKeyEntry will have a Credentials.USER_PRIVATE_KEY as the private key,
+ * Credentials.USER_CERTIFICATE as the first certificate in the chain (the one
+ * that corresponds to the private key), and then a Credentials.CA_CERTIFICATE
+ * entry which will have the rest of the chain concatenated in BER format.
+ * <p>
+ * TrustedCertificateEntry will just have a Credentials.CA_CERTIFICATE entry
+ * with a single certificate.
+ *
+ * @hide
+ */
+public class AndroidKeyStore extends KeyStoreSpi {
+ public static final String NAME = "AndroidKeyStore";
+
+ private android.security.KeyStore mKeyStore;
+
+ @Override
+ public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException,
+ UnrecoverableKeyException {
+ if (!isKeyEntry(alias)) {
+ return null;
+ }
+
+ final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
+ try {
+ return engine.getPrivateKeyById(Credentials.USER_PRIVATE_KEY + alias);
+ } catch (InvalidKeyException e) {
+ UnrecoverableKeyException t = new UnrecoverableKeyException("Can't get key");
+ t.initCause(e);
+ throw t;
+ }
+ }
+
+ @Override
+ public Certificate[] engineGetCertificateChain(String alias) {
+ final X509Certificate leaf = (X509Certificate) engineGetCertificate(alias);
+ if (leaf == null) {
+ return null;
+ }
+
+ final Certificate[] caList;
+
+ final byte[] caBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+ if (caBytes != null) {
+ final Collection<X509Certificate> caChain = toCertificates(caBytes);
+
+ caList = new Certificate[caChain.size() + 1];
+
+ final Iterator<X509Certificate> it = caChain.iterator();
+ int i = 1;
+ while (it.hasNext()) {
+ caList[i++] = it.next();
+ }
+ } else {
+ caList = new Certificate[1];
+ }
+
+ caList[0] = leaf;
+
+ return caList;
+ }
+
+ @Override
+ public Certificate engineGetCertificate(String alias) {
+ byte[] certificate = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
+ if (certificate != null) {
+ return toCertificate(certificate);
+ }
+
+ certificate = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+ if (certificate != null) {
+ return toCertificate(certificate);
+ }
+
+ return null;
+ }
+
+ private static X509Certificate toCertificate(byte[] bytes) {
+ try {
+ final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ return (X509Certificate) certFactory
+ .generateCertificate(new ByteArrayInputStream(bytes));
+ } catch (CertificateException e) {
+ Log.w(NAME, "Couldn't parse certificate in keystore", e);
+ return null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Collection<X509Certificate> toCertificates(byte[] bytes) {
+ try {
+ final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ return (Collection<X509Certificate>) certFactory
+ .generateCertificates(new ByteArrayInputStream(bytes));
+ } catch (CertificateException e) {
+ Log.w(NAME, "Couldn't parse certificates in keystore", e);
+ return new ArrayList<X509Certificate>();
+ }
+ }
+
+ private Date getModificationDate(String alias) {
+ final long epochMillis = mKeyStore.getmtime(alias);
+ if (epochMillis == -1L) {
+ return null;
+ }
+
+ return new Date(epochMillis);
+ }
+
+ @Override
+ public Date engineGetCreationDate(String alias) {
+ Date d = getModificationDate(Credentials.USER_PRIVATE_KEY + alias);
+ if (d != null) {
+ return d;
+ }
+
+ d = getModificationDate(Credentials.USER_CERTIFICATE + alias);
+ if (d != null) {
+ return d;
+ }
+
+ return getModificationDate(Credentials.CA_CERTIFICATE + alias);
+ }
+
+ @Override
+ public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain)
+ throws KeyStoreException {
+ if ((password != null) && (password.length > 0)) {
+ throw new KeyStoreException("entries cannot be protected with passwords");
+ }
+
+ if (key instanceof PrivateKey) {
+ setPrivateKeyEntry(alias, (PrivateKey) key, chain);
+ } else {
+ throw new KeyStoreException("Only PrivateKeys are supported");
+ }
+ }
+
+ private void setPrivateKeyEntry(String alias, PrivateKey key, Certificate[] chain)
+ throws KeyStoreException {
+ // Make sure the PrivateKey format is the one we support.
+ final String keyFormat = key.getFormat();
+ if ((keyFormat == null) || (!"PKCS#8".equals(keyFormat))) {
+ throw new KeyStoreException(
+ "Only PrivateKeys that can be encoded into PKCS#8 are supported");
+ }
+
+ // Make sure we can actually encode the key.
+ final byte[] keyBytes = key.getEncoded();
+ if (keyBytes == null) {
+ throw new KeyStoreException("PrivateKey has no encoding");
+ }
+
+ // Make sure the chain exists since this is a PrivateKey
+ if ((chain == null) || (chain.length == 0)) {
+ throw new KeyStoreException("Must supply at least one Certificate with PrivateKey");
+ }
+
+ // Do chain type checking.
+ X509Certificate[] x509chain = new X509Certificate[chain.length];
+ for (int i = 0; i < chain.length; i++) {
+ if (!"X.509".equals(chain[i].getType())) {
+ throw new KeyStoreException("Certificates must be in X.509 format: invalid cert #"
+ + i);
+ }
+
+ if (!(chain[i] instanceof X509Certificate)) {
+ throw new KeyStoreException("Certificates must be in X.509 format: invalid cert #"
+ + i);
+ }
+
+ x509chain[i] = (X509Certificate) chain[i];
+ }
+
+ final byte[] userCertBytes;
+ try {
+ userCertBytes = x509chain[0].getEncoded();
+ } catch (CertificateEncodingException e) {
+ throw new KeyStoreException("Couldn't encode certificate #1", e);
+ }
+
+ /*
+ * If we have a chain, store it in the CA certificate slot for this
+ * alias as concatenated DER-encoded certificates. These can be
+ * deserialized by {@link CertificateFactory#generateCertificates}.
+ */
+ final byte[] chainBytes;
+ if (chain.length > 1) {
+ /*
+ * The chain is passed in as {user_cert, ca_cert_1, ca_cert_2, ...}
+ * so we only need the certificates starting at index 1.
+ */
+ final byte[][] certsBytes = new byte[x509chain.length - 1][];
+ int totalCertLength = 0;
+ for (int i = 0; i < certsBytes.length; i++) {
+ try {
+ certsBytes[i] = x509chain[i + 1].getEncoded();
+ totalCertLength += certsBytes[i].length;
+ } catch (CertificateEncodingException e) {
+ throw new KeyStoreException("Can't encode Certificate #" + i, e);
+ }
+ }
+
+ /*
+ * Serialize this into one byte array so we can later call
+ * CertificateFactory#generateCertificates to recover them.
+ */
+ chainBytes = new byte[totalCertLength];
+ int outputOffset = 0;
+ for (int i = 0; i < certsBytes.length; i++) {
+ final int certLength = certsBytes[i].length;
+ System.arraycopy(certsBytes[i], 0, chainBytes, outputOffset, certLength);
+ outputOffset += certLength;
+ certsBytes[i] = null;
+ }
+ } else {
+ chainBytes = null;
+ }
+
+ /*
+ * Make sure we clear out all the types we know about before trying to
+ * write.
+ */
+ deleteAllTypesForAlias(alias);
+
+ if (!mKeyStore.importKey(Credentials.USER_PRIVATE_KEY + alias, keyBytes)) {
+ throw new KeyStoreException("Couldn't put private key in keystore");
+ } else if (!mKeyStore.put(Credentials.USER_CERTIFICATE + alias, userCertBytes)) {
+ throw new KeyStoreException("Couldn't put certificate #1 in keystore");
+ } else if (chainBytes != null
+ && !mKeyStore.put(Credentials.CA_CERTIFICATE + alias, chainBytes)) {
+ throw new KeyStoreException("Couldn't put certificate chain in keystore");
+ }
+ }
+
+ @Override
+ public void engineSetKeyEntry(String alias, byte[] userKey, Certificate[] chain)
+ throws KeyStoreException {
+ throw new RuntimeException("Operation not supported because key encoding is unknown");
+ }
+
+ @Override
+ public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException {
+ if (isKeyEntry(alias)) {
+ throw new KeyStoreException("Entry exists and is not a trusted certificate");
+ }
+
+ final byte[] encoded;
+ try {
+ encoded = cert.getEncoded();
+ } catch (CertificateEncodingException e) {
+ throw new KeyStoreException(e);
+ }
+
+ if (!mKeyStore.put(Credentials.CA_CERTIFICATE + alias, encoded)) {
+ throw new KeyStoreException("Couldn't insert certificate; is KeyStore initialized?");
+ }
+ }
+
+ @Override
+ public void engineDeleteEntry(String alias) throws KeyStoreException {
+ if (!deleteAllTypesForAlias(alias)) {
+ throw new KeyStoreException("No such entry " + alias);
+ }
+ }
+
+ /**
+ * Delete all types (private key, certificate, CA certificate) for a
+ * particular {@code alias}. All three can exist for any given alias.
+ * Returns {@code true} if there was at least one of those types.
+ */
+ private boolean deleteAllTypesForAlias(String alias) {
+ /*
+ * Make sure every type is deleted. There can be all three types, so
+ * don't use a conditional here.
+ */
+ return mKeyStore.delKey(Credentials.USER_PRIVATE_KEY + alias)
+ | mKeyStore.delete(Credentials.USER_CERTIFICATE + alias)
+ | mKeyStore.delete(Credentials.CA_CERTIFICATE + alias);
+ }
+
+ private Set<String> getUniqueAliases() {
+ final String[] rawAliases = mKeyStore.saw("");
+ if (rawAliases == null) {
+ return new HashSet<String>();
+ }
+
+ final Set<String> aliases = new HashSet<String>(rawAliases.length);
+ for (String alias : rawAliases) {
+ final int idx = alias.indexOf('_');
+ if ((idx == -1) || (alias.length() <= idx)) {
+ Log.e(NAME, "invalid alias: " + alias);
+ continue;
+ }
+
+ aliases.add(new String(alias.substring(idx + 1)));
+ }
+
+ return aliases;
+ }
+
+ @Override
+ public Enumeration<String> engineAliases() {
+ return Collections.enumeration(getUniqueAliases());
+ }
+
+ @Override
+ public boolean engineContainsAlias(String alias) {
+ return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias)
+ || mKeyStore.contains(Credentials.USER_CERTIFICATE + alias)
+ || mKeyStore.contains(Credentials.CA_CERTIFICATE + alias);
+ }
+
+ @Override
+ public int engineSize() {
+ return getUniqueAliases().size();
+ }
+
+ @Override
+ public boolean engineIsKeyEntry(String alias) {
+ return isKeyEntry(alias);
+ }
+
+ private boolean isKeyEntry(String alias) {
+ return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias);
+ }
+
+ @Override
+ public boolean engineIsCertificateEntry(String alias) {
+ return !isKeyEntry(alias) && mKeyStore.contains(Credentials.CA_CERTIFICATE + alias);
+ }
+
+ @Override
+ public String engineGetCertificateAlias(Certificate cert) {
+ if (cert == null) {
+ return null;
+ }
+
+ final Set<String> nonCaEntries = new HashSet<String>();
+
+ /*
+ * First scan the PrivateKeyEntry types. The KeyStoreSpi documentation
+ * says to only compare the first certificate in the chain which is
+ * equivalent to the USER_CERTIFICATE prefix for the Android keystore
+ * convention.
+ */
+ final String[] certAliases = mKeyStore.saw(Credentials.USER_CERTIFICATE);
+ for (String alias : certAliases) {
+ final byte[] certBytes = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
+ if (certBytes == null) {
+ continue;
+ }
+
+ final Certificate c = toCertificate(certBytes);
+ nonCaEntries.add(alias);
+
+ if (cert.equals(c)) {
+ return alias;
+ }
+ }
+
+ /*
+ * Look at all the TrustedCertificateEntry types. Skip all the
+ * PrivateKeyEntry we looked at above.
+ */
+ final String[] caAliases = mKeyStore.saw(Credentials.CA_CERTIFICATE);
+ for (String alias : caAliases) {
+ if (nonCaEntries.contains(alias)) {
+ continue;
+ }
+
+ final byte[] certBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+ if (certBytes == null) {
+ continue;
+ }
+
+ final Certificate c = toCertificate(mKeyStore.get(Credentials.CA_CERTIFICATE + alias));
+ if (cert.equals(c)) {
+ return alias;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public void engineStore(OutputStream stream, char[] password) throws IOException,
+ NoSuchAlgorithmException, CertificateException {
+ throw new UnsupportedOperationException("Can not serialize AndroidKeyStore to OutputStream");
+ }
+
+ @Override
+ public void engineLoad(InputStream stream, char[] password) throws IOException,
+ NoSuchAlgorithmException, CertificateException {
+ if (stream != null) {
+ throw new IllegalArgumentException("InputStream not supported");
+ }
+
+ if (password != null) {
+ throw new IllegalArgumentException("password not supported");
+ }
+
+ // Unfortunate name collision.
+ mKeyStore = android.security.KeyStore.getInstance();
+ }
+
+}
diff --git a/keystore/java/android/security/AndroidKeyStoreProvider.java b/keystore/java/android/security/AndroidKeyStoreProvider.java
new file mode 100644
index 0000000..df22f58
--- /dev/null
+++ b/keystore/java/android/security/AndroidKeyStoreProvider.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import java.security.Provider;
+
+/**
+ * A provider focused on providing JCA interfaces for the Android KeyStore.
+ *
+ * @hide
+ */
+public class AndroidKeyStoreProvider extends Provider {
+ public static final String PROVIDER_NAME = "AndroidKeyStoreProvider";
+
+ public AndroidKeyStoreProvider() {
+ super(PROVIDER_NAME, 1.0, "Android KeyStore security provider");
+
+ put("KeyStore." + AndroidKeyStore.NAME, AndroidKeyStore.class.getName());
+ }
+}
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index f49c429..4637991 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -26,6 +26,7 @@ import java.io.UTFDataFormatException;
import java.nio.charset.Charsets;
import java.nio.charset.ModifiedUtf8;
import java.util.ArrayList;
+import java.util.Date;
/**
* @hide This should not be made public in its present form because it
@@ -228,6 +229,23 @@ public class KeyStore {
return ungrant(getKeyBytes(key), getUidBytes(uid));
}
+ private long getmtime(byte[] key) {
+ final ArrayList<byte[]> values = execute('c', key);
+ if (values == null || values.isEmpty()) {
+ return -1L;
+ }
+
+ return Long.parseLong(new String(values.get(0))) * 1000L;
+ }
+
+ /**
+ * Returns the last modification time of the key in milliseconds since the
+ * epoch. Will return -1L if the key could not be found or other error.
+ */
+ public long getmtime(String key) {
+ return getmtime(getKeyBytes(key));
+ }
+
public int getLastError() {
return mError;
}
diff --git a/keystore/tests/src/android/security/AndroidKeyStoreTest.java b/keystore/tests/src/android/security/AndroidKeyStoreTest.java
new file mode 100644
index 0000000..bff01b8
--- /dev/null
+++ b/keystore/tests/src/android/security/AndroidKeyStoreTest.java
@@ -0,0 +1,1383 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.test.AndroidTestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.KeyStore.Entry;
+import java.security.KeyStore.PrivateKeyEntry;
+import java.security.KeyStore.TrustedCertificateEntry;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+public class AndroidKeyStoreTest extends AndroidTestCase {
+ private android.security.KeyStore mAndroidKeyStore;
+
+ private java.security.KeyStore mKeyStore;
+
+ private static final String TEST_ALIAS_1 = "test1";
+
+ private static final String TEST_ALIAS_2 = "test2";
+
+ private static final String TEST_ALIAS_3 = "test3";
+
+ /*
+ * The keys and certificates below are generated with:
+ *
+ * openssl req -new -x509 -days 3650 -extensions v3_ca -keyout cakey.pem -out cacert.pem
+ * openssl req -newkey rsa:1024 -keyout userkey.pem -nodes -days 3650 -out userkey.req
+ * mkdir -p demoCA/newcerts
+ * touch demoCA/index.txt
+ * echo "01" > demoCA/serial
+ * openssl ca -out usercert.pem -in userkey.req -cert cacert.pem -keyfile cakey.pem -days 3650
+ */
+
+ /**
+ * Generated from above and converted with:
+ *
+ * openssl x509 -outform d -in cacert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
+ */
+ private static final byte[] FAKE_CA_1 = {
+ (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0xce, (byte) 0x30, (byte) 0x82,
+ (byte) 0x02, (byte) 0x37, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+ (byte) 0x02, (byte) 0x02, (byte) 0x09, (byte) 0x00, (byte) 0xe1, (byte) 0x6a,
+ (byte) 0xa2, (byte) 0xf4, (byte) 0x2e, (byte) 0x55, (byte) 0x48, (byte) 0x0a,
+ (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+ (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+ (byte) 0x05, (byte) 0x05, (byte) 0x00, (byte) 0x30, (byte) 0x4f, (byte) 0x31,
+ (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+ (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53,
+ (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03,
+ (byte) 0x55, (byte) 0x04, (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43,
+ (byte) 0x41, (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06,
+ (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d,
+ (byte) 0x4d, (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61,
+ (byte) 0x69, (byte) 0x6e, (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65,
+ (byte) 0x77, (byte) 0x31, (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06,
+ (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12,
+ (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69,
+ (byte) 0x64, (byte) 0x20, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74,
+ (byte) 0x20, (byte) 0x43, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73,
+ (byte) 0x30, (byte) 0x1e, (byte) 0x17, (byte) 0x0d, (byte) 0x31, (byte) 0x32,
+ (byte) 0x30, (byte) 0x38, (byte) 0x31, (byte) 0x34, (byte) 0x31, (byte) 0x36,
+ (byte) 0x35, (byte) 0x35, (byte) 0x34, (byte) 0x34, (byte) 0x5a, (byte) 0x17,
+ (byte) 0x0d, (byte) 0x32, (byte) 0x32, (byte) 0x30, (byte) 0x38, (byte) 0x31,
+ (byte) 0x32, (byte) 0x31, (byte) 0x36, (byte) 0x35, (byte) 0x35, (byte) 0x34,
+ (byte) 0x34, (byte) 0x5a, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b,
+ (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+ (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31,
+ (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+ (byte) 0x04, (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41,
+ (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03,
+ (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d,
+ (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69,
+ (byte) 0x6e, (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77,
+ (byte) 0x31, (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03,
+ (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41,
+ (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64,
+ (byte) 0x20, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20,
+ (byte) 0x43, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x30,
+ (byte) 0x81, (byte) 0x9f, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09,
+ (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d,
+ (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x03,
+ (byte) 0x81, (byte) 0x8d, (byte) 0x00, (byte) 0x30, (byte) 0x81, (byte) 0x89,
+ (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xa3, (byte) 0x72,
+ (byte) 0xab, (byte) 0xd0, (byte) 0xe4, (byte) 0xad, (byte) 0x2f, (byte) 0xe7,
+ (byte) 0xe2, (byte) 0x79, (byte) 0x07, (byte) 0x36, (byte) 0x3d, (byte) 0x0c,
+ (byte) 0x8d, (byte) 0x42, (byte) 0x9a, (byte) 0x0a, (byte) 0x33, (byte) 0x64,
+ (byte) 0xb3, (byte) 0xcd, (byte) 0xb2, (byte) 0xd7, (byte) 0x3a, (byte) 0x42,
+ (byte) 0x06, (byte) 0x77, (byte) 0x45, (byte) 0x29, (byte) 0xe9, (byte) 0xcb,
+ (byte) 0xb7, (byte) 0x4a, (byte) 0xd6, (byte) 0xee, (byte) 0xad, (byte) 0x01,
+ (byte) 0x91, (byte) 0x9b, (byte) 0x0c, (byte) 0x59, (byte) 0xa1, (byte) 0x03,
+ (byte) 0xfa, (byte) 0xf0, (byte) 0x5a, (byte) 0x7c, (byte) 0x4f, (byte) 0xf7,
+ (byte) 0x8d, (byte) 0x36, (byte) 0x0f, (byte) 0x1f, (byte) 0x45, (byte) 0x7d,
+ (byte) 0x1b, (byte) 0x31, (byte) 0xa1, (byte) 0x35, (byte) 0x0b, (byte) 0x00,
+ (byte) 0xed, (byte) 0x7a, (byte) 0xb6, (byte) 0xc8, (byte) 0x4e, (byte) 0xa9,
+ (byte) 0x86, (byte) 0x4c, (byte) 0x7b, (byte) 0x99, (byte) 0x57, (byte) 0x41,
+ (byte) 0x12, (byte) 0xef, (byte) 0x6b, (byte) 0xbc, (byte) 0x3d, (byte) 0x60,
+ (byte) 0xf2, (byte) 0x99, (byte) 0x1a, (byte) 0xcd, (byte) 0xed, (byte) 0x56,
+ (byte) 0xa4, (byte) 0xe5, (byte) 0x36, (byte) 0x9f, (byte) 0x24, (byte) 0x1f,
+ (byte) 0xdc, (byte) 0x89, (byte) 0x40, (byte) 0xc8, (byte) 0x99, (byte) 0x92,
+ (byte) 0xab, (byte) 0x4a, (byte) 0xb5, (byte) 0x61, (byte) 0x45, (byte) 0x62,
+ (byte) 0xff, (byte) 0xa3, (byte) 0x45, (byte) 0x65, (byte) 0xaf, (byte) 0xf6,
+ (byte) 0x27, (byte) 0x30, (byte) 0x51, (byte) 0x0e, (byte) 0x0e, (byte) 0xeb,
+ (byte) 0x79, (byte) 0x0c, (byte) 0xbe, (byte) 0xb3, (byte) 0x0a, (byte) 0x6f,
+ (byte) 0x29, (byte) 0x06, (byte) 0xdc, (byte) 0x2f, (byte) 0x6b, (byte) 0x51,
+ (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xa3,
+ (byte) 0x81, (byte) 0xb1, (byte) 0x30, (byte) 0x81, (byte) 0xae, (byte) 0x30,
+ (byte) 0x1d, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e,
+ (byte) 0x04, (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0x33, (byte) 0x05,
+ (byte) 0xee, (byte) 0xfe, (byte) 0x6f, (byte) 0x60, (byte) 0xc7, (byte) 0xf9,
+ (byte) 0xa9, (byte) 0xd2, (byte) 0x73, (byte) 0x5c, (byte) 0x8f, (byte) 0x6d,
+ (byte) 0xa2, (byte) 0x2f, (byte) 0x97, (byte) 0x8e, (byte) 0x5d, (byte) 0x51,
+ (byte) 0x30, (byte) 0x7f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d,
+ (byte) 0x23, (byte) 0x04, (byte) 0x78, (byte) 0x30, (byte) 0x76, (byte) 0x80,
+ (byte) 0x14, (byte) 0x33, (byte) 0x05, (byte) 0xee, (byte) 0xfe, (byte) 0x6f,
+ (byte) 0x60, (byte) 0xc7, (byte) 0xf9, (byte) 0xa9, (byte) 0xd2, (byte) 0x73,
+ (byte) 0x5c, (byte) 0x8f, (byte) 0x6d, (byte) 0xa2, (byte) 0x2f, (byte) 0x97,
+ (byte) 0x8e, (byte) 0x5d, (byte) 0x51, (byte) 0xa1, (byte) 0x53, (byte) 0xa4,
+ (byte) 0x51, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+ (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06,
+ (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b,
+ (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+ (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31,
+ (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+ (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d, (byte) 0x6f,
+ (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e,
+ (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31,
+ (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+ (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e,
+ (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20,
+ (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43,
+ (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x82, (byte) 0x09,
+ (byte) 0x00, (byte) 0xe1, (byte) 0x6a, (byte) 0xa2, (byte) 0xf4, (byte) 0x2e,
+ (byte) 0x55, (byte) 0x48, (byte) 0x0a, (byte) 0x30, (byte) 0x0c, (byte) 0x06,
+ (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x13, (byte) 0x04, (byte) 0x05,
+ (byte) 0x30, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0xff, (byte) 0x30,
+ (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48,
+ (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x05,
+ (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x81, (byte) 0x00,
+ (byte) 0x8c, (byte) 0x30, (byte) 0x42, (byte) 0xfa, (byte) 0xeb, (byte) 0x1a,
+ (byte) 0x26, (byte) 0xeb, (byte) 0xda, (byte) 0x56, (byte) 0x32, (byte) 0xf2,
+ (byte) 0x9d, (byte) 0xa5, (byte) 0x24, (byte) 0xd8, (byte) 0x3a, (byte) 0xda,
+ (byte) 0x30, (byte) 0xa6, (byte) 0x8b, (byte) 0x46, (byte) 0xfe, (byte) 0xfe,
+ (byte) 0xdb, (byte) 0xf1, (byte) 0xe6, (byte) 0xe1, (byte) 0x7c, (byte) 0x1b,
+ (byte) 0xe7, (byte) 0x77, (byte) 0x00, (byte) 0xa1, (byte) 0x1c, (byte) 0x19,
+ (byte) 0x17, (byte) 0x73, (byte) 0xb0, (byte) 0xf0, (byte) 0x9d, (byte) 0xf3,
+ (byte) 0x4f, (byte) 0xb6, (byte) 0xbc, (byte) 0xc7, (byte) 0x47, (byte) 0x85,
+ (byte) 0x2a, (byte) 0x4a, (byte) 0xa1, (byte) 0xa5, (byte) 0x58, (byte) 0xf5,
+ (byte) 0xc5, (byte) 0x1a, (byte) 0x51, (byte) 0xb1, (byte) 0x04, (byte) 0x80,
+ (byte) 0xee, (byte) 0x3a, (byte) 0xec, (byte) 0x2f, (byte) 0xe1, (byte) 0xfd,
+ (byte) 0x58, (byte) 0xeb, (byte) 0xed, (byte) 0x82, (byte) 0x9e, (byte) 0x38,
+ (byte) 0xa3, (byte) 0x24, (byte) 0x75, (byte) 0xf7, (byte) 0x3e, (byte) 0xc2,
+ (byte) 0xc5, (byte) 0x27, (byte) 0xeb, (byte) 0x6f, (byte) 0x7b, (byte) 0x50,
+ (byte) 0xda, (byte) 0x43, (byte) 0xdc, (byte) 0x3b, (byte) 0x0b, (byte) 0x6f,
+ (byte) 0x78, (byte) 0x8f, (byte) 0xb0, (byte) 0x66, (byte) 0xe1, (byte) 0x12,
+ (byte) 0x87, (byte) 0x5f, (byte) 0x97, (byte) 0x7b, (byte) 0xca, (byte) 0x14,
+ (byte) 0x79, (byte) 0xf7, (byte) 0xe8, (byte) 0x6c, (byte) 0x72, (byte) 0xdb,
+ (byte) 0x91, (byte) 0x65, (byte) 0x17, (byte) 0x54, (byte) 0xe0, (byte) 0x74,
+ (byte) 0x1d, (byte) 0xac, (byte) 0x47, (byte) 0x04, (byte) 0x12, (byte) 0xe0,
+ (byte) 0xc3, (byte) 0x66, (byte) 0x19, (byte) 0x05, (byte) 0x2e, (byte) 0x7e,
+ (byte) 0xf1, (byte) 0x61
+ };
+
+ /**
+ * Generated from above and converted with:
+ *
+ * openssl pkcs8 -topk8 -outform d -in userkey.pem -nocrypt | xxd -i | sed 's/0x/(byte) 0x/g'
+ */
+ private static final byte[] FAKE_KEY_1 = new byte[] {
+ (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x78, (byte) 0x02, (byte) 0x01,
+ (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a,
+ (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01,
+ (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x82,
+ (byte) 0x02, (byte) 0x62, (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x5e,
+ (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x81, (byte) 0x81,
+ (byte) 0x00, (byte) 0xce, (byte) 0x29, (byte) 0xeb, (byte) 0xf6, (byte) 0x5b,
+ (byte) 0x25, (byte) 0xdc, (byte) 0xa1, (byte) 0xa6, (byte) 0x2c, (byte) 0x66,
+ (byte) 0xcb, (byte) 0x20, (byte) 0x90, (byte) 0x27, (byte) 0x86, (byte) 0x8a,
+ (byte) 0x44, (byte) 0x71, (byte) 0x50, (byte) 0xda, (byte) 0xd3, (byte) 0x02,
+ (byte) 0x77, (byte) 0x55, (byte) 0xe9, (byte) 0xe8, (byte) 0x08, (byte) 0xf3,
+ (byte) 0x36, (byte) 0x9a, (byte) 0xae, (byte) 0xab, (byte) 0x04, (byte) 0x6d,
+ (byte) 0x00, (byte) 0x99, (byte) 0xbf, (byte) 0x7d, (byte) 0x0f, (byte) 0x67,
+ (byte) 0x8b, (byte) 0x1d, (byte) 0xd4, (byte) 0x2b, (byte) 0x7c, (byte) 0xcb,
+ (byte) 0xcd, (byte) 0x33, (byte) 0xc7, (byte) 0x84, (byte) 0x30, (byte) 0xe2,
+ (byte) 0x45, (byte) 0x21, (byte) 0xb3, (byte) 0x75, (byte) 0xf5, (byte) 0x79,
+ (byte) 0x02, (byte) 0xda, (byte) 0x50, (byte) 0xa3, (byte) 0x8b, (byte) 0xce,
+ (byte) 0xc3, (byte) 0x8e, (byte) 0x0f, (byte) 0x25, (byte) 0xeb, (byte) 0x08,
+ (byte) 0x2c, (byte) 0xdd, (byte) 0x1c, (byte) 0xcf, (byte) 0xff, (byte) 0x3b,
+ (byte) 0xde, (byte) 0xb6, (byte) 0xaa, (byte) 0x2a, (byte) 0xa9, (byte) 0xc4,
+ (byte) 0x8a, (byte) 0x24, (byte) 0x24, (byte) 0xe6, (byte) 0x29, (byte) 0x0d,
+ (byte) 0x98, (byte) 0x4c, (byte) 0x32, (byte) 0xa1, (byte) 0x7b, (byte) 0x23,
+ (byte) 0x2b, (byte) 0x42, (byte) 0x30, (byte) 0xee, (byte) 0x78, (byte) 0x08,
+ (byte) 0x47, (byte) 0xad, (byte) 0xf2, (byte) 0x96, (byte) 0xd5, (byte) 0xf1,
+ (byte) 0x62, (byte) 0x42, (byte) 0x2d, (byte) 0x35, (byte) 0x19, (byte) 0xb4,
+ (byte) 0x3c, (byte) 0xc9, (byte) 0xc3, (byte) 0x5f, (byte) 0x03, (byte) 0x16,
+ (byte) 0x3a, (byte) 0x23, (byte) 0xac, (byte) 0xcb, (byte) 0xce, (byte) 0x9e,
+ (byte) 0x51, (byte) 0x2e, (byte) 0x6d, (byte) 0x02, (byte) 0x03, (byte) 0x01,
+ (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x81, (byte) 0x80, (byte) 0x16,
+ (byte) 0x59, (byte) 0xc3, (byte) 0x24, (byte) 0x1d, (byte) 0x33, (byte) 0x98,
+ (byte) 0x9c, (byte) 0xc9, (byte) 0xc8, (byte) 0x2c, (byte) 0x88, (byte) 0xbf,
+ (byte) 0x0a, (byte) 0x01, (byte) 0xce, (byte) 0xfb, (byte) 0x34, (byte) 0x7a,
+ (byte) 0x58, (byte) 0x7a, (byte) 0xb0, (byte) 0xbf, (byte) 0xa6, (byte) 0xb2,
+ (byte) 0x60, (byte) 0xbe, (byte) 0x70, (byte) 0x21, (byte) 0xf5, (byte) 0xfc,
+ (byte) 0x85, (byte) 0x0d, (byte) 0x33, (byte) 0x58, (byte) 0xa1, (byte) 0xe5,
+ (byte) 0x09, (byte) 0x36, (byte) 0x84, (byte) 0xb2, (byte) 0x04, (byte) 0x0a,
+ (byte) 0x02, (byte) 0xd3, (byte) 0x88, (byte) 0x1f, (byte) 0x0c, (byte) 0x2b,
+ (byte) 0x1d, (byte) 0xe9, (byte) 0x3d, (byte) 0xe7, (byte) 0x79, (byte) 0xf9,
+ (byte) 0x32, (byte) 0x5c, (byte) 0x8a, (byte) 0x75, (byte) 0x49, (byte) 0x12,
+ (byte) 0xe4, (byte) 0x05, (byte) 0x26, (byte) 0xd4, (byte) 0x2e, (byte) 0x9e,
+ (byte) 0x1f, (byte) 0xcc, (byte) 0x54, (byte) 0xad, (byte) 0x33, (byte) 0x8d,
+ (byte) 0x99, (byte) 0x00, (byte) 0xdc, (byte) 0xf5, (byte) 0xb4, (byte) 0xa2,
+ (byte) 0x2f, (byte) 0xba, (byte) 0xe5, (byte) 0x62, (byte) 0x30, (byte) 0x6d,
+ (byte) 0xe6, (byte) 0x3d, (byte) 0xeb, (byte) 0x24, (byte) 0xc2, (byte) 0xdc,
+ (byte) 0x5f, (byte) 0xb7, (byte) 0x16, (byte) 0x35, (byte) 0xa3, (byte) 0x98,
+ (byte) 0x98, (byte) 0xa8, (byte) 0xef, (byte) 0xe8, (byte) 0xc4, (byte) 0x96,
+ (byte) 0x6d, (byte) 0x38, (byte) 0xab, (byte) 0x26, (byte) 0x6d, (byte) 0x30,
+ (byte) 0xc2, (byte) 0xa0, (byte) 0x44, (byte) 0xe4, (byte) 0xff, (byte) 0x7e,
+ (byte) 0xbe, (byte) 0x7c, (byte) 0x33, (byte) 0xa5, (byte) 0x10, (byte) 0xad,
+ (byte) 0xd7, (byte) 0x1e, (byte) 0x13, (byte) 0x20, (byte) 0xb3, (byte) 0x1f,
+ (byte) 0x41, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xf1, (byte) 0x89,
+ (byte) 0x07, (byte) 0x0f, (byte) 0xe8, (byte) 0xcf, (byte) 0xab, (byte) 0x13,
+ (byte) 0x2a, (byte) 0x8f, (byte) 0x88, (byte) 0x80, (byte) 0x11, (byte) 0x9a,
+ (byte) 0x79, (byte) 0xb6, (byte) 0x59, (byte) 0x3a, (byte) 0x50, (byte) 0x6e,
+ (byte) 0x57, (byte) 0x37, (byte) 0xab, (byte) 0x2a, (byte) 0xd2, (byte) 0xaa,
+ (byte) 0xd9, (byte) 0x72, (byte) 0x73, (byte) 0xff, (byte) 0x8b, (byte) 0x47,
+ (byte) 0x76, (byte) 0xdd, (byte) 0xdc, (byte) 0xf5, (byte) 0x97, (byte) 0x44,
+ (byte) 0x3a, (byte) 0x78, (byte) 0xbe, (byte) 0x17, (byte) 0xb4, (byte) 0x22,
+ (byte) 0x6f, (byte) 0xe5, (byte) 0x23, (byte) 0x70, (byte) 0x1d, (byte) 0x10,
+ (byte) 0x5d, (byte) 0xba, (byte) 0x16, (byte) 0x81, (byte) 0xf1, (byte) 0x45,
+ (byte) 0xce, (byte) 0x30, (byte) 0xb4, (byte) 0xab, (byte) 0x80, (byte) 0xe4,
+ (byte) 0x98, (byte) 0x31, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xda,
+ (byte) 0x82, (byte) 0x9d, (byte) 0x3f, (byte) 0xca, (byte) 0x2f, (byte) 0xe1,
+ (byte) 0xd4, (byte) 0x86, (byte) 0x77, (byte) 0x48, (byte) 0xa6, (byte) 0xab,
+ (byte) 0xab, (byte) 0x1c, (byte) 0x42, (byte) 0x5c, (byte) 0xd5, (byte) 0xc7,
+ (byte) 0x46, (byte) 0x59, (byte) 0x91, (byte) 0x3f, (byte) 0xfc, (byte) 0xcc,
+ (byte) 0xec, (byte) 0xc2, (byte) 0x40, (byte) 0x12, (byte) 0x2c, (byte) 0x8d,
+ (byte) 0x1f, (byte) 0xa2, (byte) 0x18, (byte) 0x88, (byte) 0xee, (byte) 0x82,
+ (byte) 0x4a, (byte) 0x5a, (byte) 0x5e, (byte) 0x88, (byte) 0x20, (byte) 0xe3,
+ (byte) 0x7b, (byte) 0xe0, (byte) 0xd8, (byte) 0x3a, (byte) 0x52, (byte) 0x9a,
+ (byte) 0x26, (byte) 0x6a, (byte) 0x04, (byte) 0xec, (byte) 0xe8, (byte) 0xb9,
+ (byte) 0x48, (byte) 0x40, (byte) 0xe1, (byte) 0xe1, (byte) 0x83, (byte) 0xa6,
+ (byte) 0x67, (byte) 0xa6, (byte) 0xfd, (byte) 0x02, (byte) 0x41, (byte) 0x00,
+ (byte) 0x89, (byte) 0x72, (byte) 0x3e, (byte) 0xb0, (byte) 0x90, (byte) 0xfd,
+ (byte) 0x4c, (byte) 0x0e, (byte) 0xd6, (byte) 0x13, (byte) 0x63, (byte) 0xcb,
+ (byte) 0xed, (byte) 0x38, (byte) 0x88, (byte) 0xb6, (byte) 0x79, (byte) 0xc4,
+ (byte) 0x33, (byte) 0x6c, (byte) 0xf6, (byte) 0xf8, (byte) 0xd8, (byte) 0xd0,
+ (byte) 0xbf, (byte) 0x9d, (byte) 0x35, (byte) 0xac, (byte) 0x69, (byte) 0xd2,
+ (byte) 0x2b, (byte) 0xc1, (byte) 0xf9, (byte) 0x24, (byte) 0x7b, (byte) 0xce,
+ (byte) 0xcd, (byte) 0xcb, (byte) 0xa7, (byte) 0xb2, (byte) 0x7a, (byte) 0x0a,
+ (byte) 0x27, (byte) 0x19, (byte) 0xc9, (byte) 0xaf, (byte) 0x0d, (byte) 0x21,
+ (byte) 0x89, (byte) 0x88, (byte) 0x7c, (byte) 0xad, (byte) 0x9e, (byte) 0x8d,
+ (byte) 0x47, (byte) 0x6d, (byte) 0x3f, (byte) 0xce, (byte) 0x7b, (byte) 0xa1,
+ (byte) 0x74, (byte) 0xf1, (byte) 0xa0, (byte) 0xa1, (byte) 0x02, (byte) 0x41,
+ (byte) 0x00, (byte) 0xd9, (byte) 0xa8, (byte) 0xf5, (byte) 0xfe, (byte) 0xce,
+ (byte) 0xe6, (byte) 0x77, (byte) 0x6b, (byte) 0xfe, (byte) 0x2d, (byte) 0xe0,
+ (byte) 0x1e, (byte) 0xb6, (byte) 0x2e, (byte) 0x12, (byte) 0x4e, (byte) 0x40,
+ (byte) 0xaf, (byte) 0x6a, (byte) 0x7b, (byte) 0x37, (byte) 0x49, (byte) 0x2a,
+ (byte) 0x96, (byte) 0x25, (byte) 0x83, (byte) 0x49, (byte) 0xd4, (byte) 0x0c,
+ (byte) 0xc6, (byte) 0x78, (byte) 0x25, (byte) 0x24, (byte) 0x90, (byte) 0x90,
+ (byte) 0x06, (byte) 0x15, (byte) 0x9e, (byte) 0xfe, (byte) 0xf9, (byte) 0xdf,
+ (byte) 0x5b, (byte) 0xf3, (byte) 0x7e, (byte) 0x38, (byte) 0x70, (byte) 0xeb,
+ (byte) 0x57, (byte) 0xd0, (byte) 0xd9, (byte) 0xa7, (byte) 0x0e, (byte) 0x14,
+ (byte) 0xf7, (byte) 0x95, (byte) 0x68, (byte) 0xd5, (byte) 0xc8, (byte) 0xab,
+ (byte) 0x9d, (byte) 0x3a, (byte) 0x2b, (byte) 0x51, (byte) 0xf9, (byte) 0x02,
+ (byte) 0x41, (byte) 0x00, (byte) 0x96, (byte) 0xdf, (byte) 0xe9, (byte) 0x67,
+ (byte) 0x6c, (byte) 0xdc, (byte) 0x90, (byte) 0x14, (byte) 0xb4, (byte) 0x1d,
+ (byte) 0x22, (byte) 0x33, (byte) 0x4a, (byte) 0x31, (byte) 0xc1, (byte) 0x9d,
+ (byte) 0x2e, (byte) 0xff, (byte) 0x9a, (byte) 0x2a, (byte) 0x95, (byte) 0x4b,
+ (byte) 0x27, (byte) 0x74, (byte) 0xcb, (byte) 0x21, (byte) 0xc3, (byte) 0xd2,
+ (byte) 0x0b, (byte) 0xb2, (byte) 0x46, (byte) 0x87, (byte) 0xf8, (byte) 0x28,
+ (byte) 0x01, (byte) 0x8b, (byte) 0xd8, (byte) 0xb9, (byte) 0x4b, (byte) 0xcd,
+ (byte) 0x9a, (byte) 0x96, (byte) 0x41, (byte) 0x0e, (byte) 0x36, (byte) 0x6d,
+ (byte) 0x40, (byte) 0x42, (byte) 0xbc, (byte) 0xd9, (byte) 0xd3, (byte) 0x7b,
+ (byte) 0xbc, (byte) 0xa7, (byte) 0x92, (byte) 0x90, (byte) 0xdd, (byte) 0xa1,
+ (byte) 0x9c, (byte) 0xce, (byte) 0xa1, (byte) 0x87, (byte) 0x11, (byte) 0x51
+ };
+
+ /**
+ * Generated from above and converted with:
+ *
+ * openssl x509 -outform d -in usercert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
+ */
+ private static final byte[] FAKE_USER_1 = new byte[] {
+ (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x95, (byte) 0x30, (byte) 0x82,
+ (byte) 0x01, (byte) 0xfe, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+ (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x30, (byte) 0x0d,
+ (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
+ (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x05,
+ (byte) 0x00, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+ (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06,
+ (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b,
+ (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+ (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31,
+ (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+ (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d, (byte) 0x6f,
+ (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e,
+ (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31,
+ (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+ (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e,
+ (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20,
+ (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43,
+ (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x30, (byte) 0x1e,
+ (byte) 0x17, (byte) 0x0d, (byte) 0x31, (byte) 0x32, (byte) 0x30, (byte) 0x38,
+ (byte) 0x31, (byte) 0x34, (byte) 0x32, (byte) 0x33, (byte) 0x32, (byte) 0x35,
+ (byte) 0x34, (byte) 0x38, (byte) 0x5a, (byte) 0x17, (byte) 0x0d, (byte) 0x32,
+ (byte) 0x32, (byte) 0x30, (byte) 0x38, (byte) 0x31, (byte) 0x32, (byte) 0x32,
+ (byte) 0x33, (byte) 0x32, (byte) 0x35, (byte) 0x34, (byte) 0x38, (byte) 0x5a,
+ (byte) 0x30, (byte) 0x55, (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09,
+ (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06, (byte) 0x13,
+ (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+ (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x08,
+ (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31, (byte) 0x1b,
+ (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+ (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e, (byte) 0x64,
+ (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20, (byte) 0x54,
+ (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43, (byte) 0x61,
+ (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x31, (byte) 0x1c, (byte) 0x30,
+ (byte) 0x1a, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x03,
+ (byte) 0x13, (byte) 0x13, (byte) 0x73, (byte) 0x65, (byte) 0x72, (byte) 0x76,
+ (byte) 0x65, (byte) 0x72, (byte) 0x31, (byte) 0x2e, (byte) 0x65, (byte) 0x78,
+ (byte) 0x61, (byte) 0x6d, (byte) 0x70, (byte) 0x6c, (byte) 0x65, (byte) 0x2e,
+ (byte) 0x63, (byte) 0x6f, (byte) 0x6d, (byte) 0x30, (byte) 0x81, (byte) 0x9f,
+ (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+ (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+ (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x8d,
+ (byte) 0x00, (byte) 0x30, (byte) 0x81, (byte) 0x89, (byte) 0x02, (byte) 0x81,
+ (byte) 0x81, (byte) 0x00, (byte) 0xce, (byte) 0x29, (byte) 0xeb, (byte) 0xf6,
+ (byte) 0x5b, (byte) 0x25, (byte) 0xdc, (byte) 0xa1, (byte) 0xa6, (byte) 0x2c,
+ (byte) 0x66, (byte) 0xcb, (byte) 0x20, (byte) 0x90, (byte) 0x27, (byte) 0x86,
+ (byte) 0x8a, (byte) 0x44, (byte) 0x71, (byte) 0x50, (byte) 0xda, (byte) 0xd3,
+ (byte) 0x02, (byte) 0x77, (byte) 0x55, (byte) 0xe9, (byte) 0xe8, (byte) 0x08,
+ (byte) 0xf3, (byte) 0x36, (byte) 0x9a, (byte) 0xae, (byte) 0xab, (byte) 0x04,
+ (byte) 0x6d, (byte) 0x00, (byte) 0x99, (byte) 0xbf, (byte) 0x7d, (byte) 0x0f,
+ (byte) 0x67, (byte) 0x8b, (byte) 0x1d, (byte) 0xd4, (byte) 0x2b, (byte) 0x7c,
+ (byte) 0xcb, (byte) 0xcd, (byte) 0x33, (byte) 0xc7, (byte) 0x84, (byte) 0x30,
+ (byte) 0xe2, (byte) 0x45, (byte) 0x21, (byte) 0xb3, (byte) 0x75, (byte) 0xf5,
+ (byte) 0x79, (byte) 0x02, (byte) 0xda, (byte) 0x50, (byte) 0xa3, (byte) 0x8b,
+ (byte) 0xce, (byte) 0xc3, (byte) 0x8e, (byte) 0x0f, (byte) 0x25, (byte) 0xeb,
+ (byte) 0x08, (byte) 0x2c, (byte) 0xdd, (byte) 0x1c, (byte) 0xcf, (byte) 0xff,
+ (byte) 0x3b, (byte) 0xde, (byte) 0xb6, (byte) 0xaa, (byte) 0x2a, (byte) 0xa9,
+ (byte) 0xc4, (byte) 0x8a, (byte) 0x24, (byte) 0x24, (byte) 0xe6, (byte) 0x29,
+ (byte) 0x0d, (byte) 0x98, (byte) 0x4c, (byte) 0x32, (byte) 0xa1, (byte) 0x7b,
+ (byte) 0x23, (byte) 0x2b, (byte) 0x42, (byte) 0x30, (byte) 0xee, (byte) 0x78,
+ (byte) 0x08, (byte) 0x47, (byte) 0xad, (byte) 0xf2, (byte) 0x96, (byte) 0xd5,
+ (byte) 0xf1, (byte) 0x62, (byte) 0x42, (byte) 0x2d, (byte) 0x35, (byte) 0x19,
+ (byte) 0xb4, (byte) 0x3c, (byte) 0xc9, (byte) 0xc3, (byte) 0x5f, (byte) 0x03,
+ (byte) 0x16, (byte) 0x3a, (byte) 0x23, (byte) 0xac, (byte) 0xcb, (byte) 0xce,
+ (byte) 0x9e, (byte) 0x51, (byte) 0x2e, (byte) 0x6d, (byte) 0x02, (byte) 0x03,
+ (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xa3, (byte) 0x7b, (byte) 0x30,
+ (byte) 0x79, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+ (byte) 0x1d, (byte) 0x13, (byte) 0x04, (byte) 0x02, (byte) 0x30, (byte) 0x00,
+ (byte) 0x30, (byte) 0x2c, (byte) 0x06, (byte) 0x09, (byte) 0x60, (byte) 0x86,
+ (byte) 0x48, (byte) 0x01, (byte) 0x86, (byte) 0xf8, (byte) 0x42, (byte) 0x01,
+ (byte) 0x0d, (byte) 0x04, (byte) 0x1f, (byte) 0x16, (byte) 0x1d, (byte) 0x4f,
+ (byte) 0x70, (byte) 0x65, (byte) 0x6e, (byte) 0x53, (byte) 0x53, (byte) 0x4c,
+ (byte) 0x20, (byte) 0x47, (byte) 0x65, (byte) 0x6e, (byte) 0x65, (byte) 0x72,
+ (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x64, (byte) 0x20, (byte) 0x43,
+ (byte) 0x65, (byte) 0x72, (byte) 0x74, (byte) 0x69, (byte) 0x66, (byte) 0x69,
+ (byte) 0x63, (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x30, (byte) 0x1d,
+ (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e, (byte) 0x04,
+ (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0x32, (byte) 0xa1, (byte) 0x1e,
+ (byte) 0x6b, (byte) 0x69, (byte) 0x04, (byte) 0xfe, (byte) 0xb3, (byte) 0xcd,
+ (byte) 0xf8, (byte) 0xbb, (byte) 0x14, (byte) 0xcd, (byte) 0xff, (byte) 0xd4,
+ (byte) 0x16, (byte) 0xc3, (byte) 0xab, (byte) 0x44, (byte) 0x2f, (byte) 0x30,
+ (byte) 0x1f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x23,
+ (byte) 0x04, (byte) 0x18, (byte) 0x30, (byte) 0x16, (byte) 0x80, (byte) 0x14,
+ (byte) 0x33, (byte) 0x05, (byte) 0xee, (byte) 0xfe, (byte) 0x6f, (byte) 0x60,
+ (byte) 0xc7, (byte) 0xf9, (byte) 0xa9, (byte) 0xd2, (byte) 0x73, (byte) 0x5c,
+ (byte) 0x8f, (byte) 0x6d, (byte) 0xa2, (byte) 0x2f, (byte) 0x97, (byte) 0x8e,
+ (byte) 0x5d, (byte) 0x51, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09,
+ (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d,
+ (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x05, (byte) 0x00, (byte) 0x03,
+ (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0x46, (byte) 0x42, (byte) 0xef,
+ (byte) 0x56, (byte) 0x89, (byte) 0x78, (byte) 0x90, (byte) 0x38, (byte) 0x24,
+ (byte) 0x9f, (byte) 0x8c, (byte) 0x7a, (byte) 0xce, (byte) 0x7a, (byte) 0xa5,
+ (byte) 0xb5, (byte) 0x1e, (byte) 0x74, (byte) 0x96, (byte) 0x34, (byte) 0x49,
+ (byte) 0x8b, (byte) 0xed, (byte) 0x44, (byte) 0xb3, (byte) 0xc9, (byte) 0x05,
+ (byte) 0xd7, (byte) 0x48, (byte) 0x55, (byte) 0x52, (byte) 0x59, (byte) 0x15,
+ (byte) 0x0b, (byte) 0xaa, (byte) 0x16, (byte) 0x86, (byte) 0xd2, (byte) 0x8e,
+ (byte) 0x16, (byte) 0x99, (byte) 0xe8, (byte) 0x5f, (byte) 0x11, (byte) 0x71,
+ (byte) 0x42, (byte) 0x55, (byte) 0xd1, (byte) 0xc4, (byte) 0x6f, (byte) 0x2e,
+ (byte) 0xa9, (byte) 0x64, (byte) 0x6f, (byte) 0xd8, (byte) 0xfd, (byte) 0x43,
+ (byte) 0x13, (byte) 0x24, (byte) 0xaa, (byte) 0x67, (byte) 0xe6, (byte) 0xf5,
+ (byte) 0xca, (byte) 0x80, (byte) 0x5e, (byte) 0x3a, (byte) 0x3e, (byte) 0xcc,
+ (byte) 0x4f, (byte) 0xba, (byte) 0x87, (byte) 0xe6, (byte) 0xae, (byte) 0xbf,
+ (byte) 0x8f, (byte) 0xd5, (byte) 0x28, (byte) 0x38, (byte) 0x58, (byte) 0x30,
+ (byte) 0x24, (byte) 0xf6, (byte) 0x53, (byte) 0x5b, (byte) 0x41, (byte) 0x53,
+ (byte) 0xe6, (byte) 0x45, (byte) 0xbc, (byte) 0xbe, (byte) 0xe6, (byte) 0xbb,
+ (byte) 0x5d, (byte) 0xd8, (byte) 0xa7, (byte) 0xf9, (byte) 0x64, (byte) 0x99,
+ (byte) 0x04, (byte) 0x43, (byte) 0x75, (byte) 0xd7, (byte) 0x2d, (byte) 0x32,
+ (byte) 0x0a, (byte) 0x94, (byte) 0xaf, (byte) 0x06, (byte) 0x34, (byte) 0xae,
+ (byte) 0x46, (byte) 0xbd, (byte) 0xda, (byte) 0x00, (byte) 0x0e, (byte) 0x25,
+ (byte) 0xc2, (byte) 0xf7, (byte) 0xc9, (byte) 0xc3, (byte) 0x65, (byte) 0xd2,
+ (byte) 0x08, (byte) 0x41, (byte) 0x0a, (byte) 0xf3, (byte) 0x72
+ };
+
+ /**
+ * The amount of time to allow before and after expected time for variance
+ * in timing tests.
+ */
+ private static final long SLOP_TIME_MILLIS = 15000L;
+
+ @Override
+ protected void setUp() throws Exception {
+ mAndroidKeyStore = android.security.KeyStore.getInstance();
+
+ assertTrue(mAndroidKeyStore.reset());
+
+ assertEquals(android.security.KeyStore.State.UNINITIALIZED, mAndroidKeyStore.state());
+
+ assertTrue(mAndroidKeyStore.password("1111"));
+
+ assertEquals(android.security.KeyStore.State.UNLOCKED, mAndroidKeyStore.state());
+
+ assertEquals(0, mAndroidKeyStore.saw("").length);
+
+ mKeyStore = java.security.KeyStore.getInstance(AndroidKeyStore.NAME);
+ }
+
+ private void assertAliases(final String[] expectedAliases) throws KeyStoreException {
+ final Enumeration<String> aliases = mKeyStore.aliases();
+ int count = 0;
+
+ final Set<String> expectedSet = new HashSet<String>();
+ expectedSet.addAll(Arrays.asList(expectedAliases));
+
+ while (aliases.hasMoreElements()) {
+ count++;
+ final String alias = aliases.nextElement();
+ assertTrue("The alias should be in the expected set", expectedSet.contains(alias));
+ expectedSet.remove(alias);
+ }
+ assertTrue("The expected set and actual set should be exactly equal", expectedSet.isEmpty());
+ assertEquals("There should be the correct number of keystore entries",
+ expectedAliases.length, count);
+ }
+
+ public void testKeyStore_Aliases_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertAliases(new String[] {});
+
+ assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1));
+
+ assertAliases(new String[] { TEST_ALIAS_1 });
+
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+ assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2 });
+ }
+
+ public void testKeyStore_Aliases_NotInitialized_Failure() throws Exception {
+ try {
+ mKeyStore.aliases();
+ fail("KeyStore should throw exception when not initialized");
+ } catch (KeyStoreException success) {
+ }
+ }
+
+ public void testKeyStore_ContainsAliases_PrivateAndCA_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertAliases(new String[] {});
+
+ assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1));
+
+ assertTrue("Should contain generated private key", mKeyStore.containsAlias(TEST_ALIAS_1));
+
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+ assertTrue("Should contain added CA certificate", mKeyStore.containsAlias(TEST_ALIAS_2));
+
+ assertFalse("Should not contain unadded certificate alias",
+ mKeyStore.containsAlias(TEST_ALIAS_3));
+ }
+
+ public void testKeyStore_ContainsAliases_CAOnly_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+ assertTrue("Should contain added CA certificate", mKeyStore.containsAlias(TEST_ALIAS_2));
+ }
+
+ public void testKeyStore_ContainsAliases_NonExistent_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertFalse("Should contain added CA certificate", mKeyStore.containsAlias(TEST_ALIAS_1));
+ }
+
+ public void testKeyStore_DeleteEntry_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ // TEST_ALIAS_1
+ assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+ FAKE_KEY_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ // TEST_ALIAS_2
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+ // TEST_ALIAS_3
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_3, FAKE_CA_1));
+
+ assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2, TEST_ALIAS_3 });
+
+ mKeyStore.deleteEntry(TEST_ALIAS_1);
+
+ assertAliases(new String[] { TEST_ALIAS_2, TEST_ALIAS_3 });
+
+ mKeyStore.deleteEntry(TEST_ALIAS_3);
+
+ assertAliases(new String[] { TEST_ALIAS_2 });
+
+ mKeyStore.deleteEntry(TEST_ALIAS_2);
+
+ assertAliases(new String[] { });
+ }
+
+ public void testKeyStore_DeleteEntry_EmptyStore_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ try {
+ mKeyStore.deleteEntry(TEST_ALIAS_1);
+ fail("Should throw KeyStoreException with non-existent alias");
+ } catch (KeyStoreException success) {
+ }
+ }
+
+ public void testKeyStore_DeleteEntry_NonExistent_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ // TEST_ALIAS_1
+ assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+ FAKE_KEY_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ try {
+ mKeyStore.deleteEntry(TEST_ALIAS_2);
+ fail("Should throw KeyStoreException with non-existent alias");
+ } catch (KeyStoreException success) {
+ }
+ }
+
+ public void testKeyStore_GetCertificate_Single_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ assertAliases(new String[] { TEST_ALIAS_1 });
+
+ assertNull("Certificate should not exist in keystore",
+ mKeyStore.getCertificate(TEST_ALIAS_2));
+
+ Certificate retrieved = mKeyStore.getCertificate(TEST_ALIAS_1);
+
+ assertNotNull("Retrieved certificate should not be null", retrieved);
+
+ CertificateFactory f = CertificateFactory.getInstance("X.509");
+ Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ assertEquals("Actual and retrieved certificates should be the same", actual, retrieved);
+ }
+
+ public void testKeyStore_GetCertificate_NonExist_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertNull("Certificate should not exist in keystore",
+ mKeyStore.getCertificate(TEST_ALIAS_1));
+ }
+
+ public void testKeyStore_GetCertificateAlias_CAEntry_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ CertificateFactory f = CertificateFactory.getInstance("X.509");
+ Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ assertEquals("Stored certificate alias should be found", TEST_ALIAS_1,
+ mKeyStore.getCertificateAlias(actual));
+ }
+
+ public void testKeyStore_GetCertificateAlias_PrivateKeyEntry_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+ FAKE_KEY_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ CertificateFactory f = CertificateFactory.getInstance("X.509");
+ Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+
+ assertEquals("Stored certificate alias should be found", TEST_ALIAS_1,
+ mKeyStore.getCertificateAlias(actual));
+ }
+
+ public void testKeyStore_GetCertificateAlias_CAEntry_WithPrivateKeyUsingCA_Success()
+ throws Exception {
+ mKeyStore.load(null, null);
+
+ // Insert TrustedCertificateEntry with CA name
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+ // Insert PrivateKeyEntry that uses the same CA
+ assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+ FAKE_KEY_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ CertificateFactory f = CertificateFactory.getInstance("X.509");
+ Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ assertEquals("Stored certificate alias should be found", TEST_ALIAS_2,
+ mKeyStore.getCertificateAlias(actual));
+ }
+
+ public void testKeyStore_GetCertificateAlias_NonExist_Empty_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ CertificateFactory f = CertificateFactory.getInstance("X.509");
+ Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ assertNull("Stored certificate alias should not be found",
+ mKeyStore.getCertificateAlias(actual));
+ }
+
+ public void testKeyStore_GetCertificateAlias_NonExist_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ CertificateFactory f = CertificateFactory.getInstance("X.509");
+ Certificate userCert = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+
+ assertNull("Stored certificate alias should be found",
+ mKeyStore.getCertificateAlias(userCert));
+ }
+
+ public void testKeyStore_GetCertificateChain_SingleLength_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+ FAKE_KEY_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ Certificate[] expected = new Certificate[2];
+ expected[0] = cf.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+ expected[1] = cf.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ Certificate[] actual = mKeyStore.getCertificateChain(TEST_ALIAS_1);
+
+ assertNotNull("Returned certificate chain should not be null", actual);
+ assertEquals("Returned certificate chain should be correct size", expected.length,
+ actual.length);
+ assertEquals("First certificate should be user certificate", expected[0], actual[0]);
+ assertEquals("Second certificate should be CA certificate", expected[1], actual[1]);
+
+ // Negative test when keystore is populated.
+ assertNull("Stored certificate alias should not be found",
+ mKeyStore.getCertificateChain(TEST_ALIAS_2));
+ }
+
+ public void testKeyStore_GetCertificateChain_NonExist_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertNull("Stored certificate alias should not be found",
+ mKeyStore.getCertificateChain(TEST_ALIAS_1));
+ }
+
+ public void testKeyStore_GetCreationDate_PrivateKeyEntry_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+ FAKE_KEY_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ Date now = new Date();
+ Date actual = mKeyStore.getCreationDate(TEST_ALIAS_1);
+
+ Date expectedAfter = new Date(now.getTime() - SLOP_TIME_MILLIS);
+ Date expectedBefore = new Date(now.getTime() + SLOP_TIME_MILLIS);
+
+ assertTrue("Time should be close to current time", actual.before(expectedBefore));
+ assertTrue("Time should be close to current time", actual.after(expectedAfter));
+ }
+
+ public void testKeyStore_GetCreationDate_CAEntry_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ Date now = new Date();
+ Date actual = mKeyStore.getCreationDate(TEST_ALIAS_1);
+ assertNotNull("Certificate should be found", actual);
+
+ Date expectedAfter = new Date(now.getTime() - SLOP_TIME_MILLIS);
+ Date expectedBefore = new Date(now.getTime() + SLOP_TIME_MILLIS);
+
+ assertTrue("Time should be close to current time", actual.before(expectedBefore));
+ assertTrue("Time should be close to current time", actual.after(expectedAfter));
+ }
+
+ public void testKeyStore_GetEntry_NullParams_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+ FAKE_KEY_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ Entry entry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Entry should exist", entry);
+
+ assertTrue("Should be a PrivateKeyEntry", entry instanceof PrivateKeyEntry);
+
+ PrivateKeyEntry keyEntry = (PrivateKeyEntry) entry;
+
+ assertPrivateKeyEntryEquals(keyEntry, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+ }
+
+ private void assertPrivateKeyEntryEquals(PrivateKeyEntry keyEntry, byte[] key, byte[] cert,
+ byte[] ca) throws Exception {
+ KeyFactory keyFact = KeyFactory.getInstance("RSA");
+ PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(key));
+
+ assertEquals("Returned PrivateKey should be what we inserted", expectedKey,
+ keyEntry.getPrivateKey());
+
+ CertificateFactory certFact = CertificateFactory.getInstance("X.509");
+ Certificate expectedCert = certFact.generateCertificate(new ByteArrayInputStream(cert));
+
+ assertEquals("Returned Certificate should be what we inserted", expectedCert,
+ keyEntry.getCertificate());
+
+ Certificate[] actualChain = keyEntry.getCertificateChain();
+
+ assertEquals("First certificate in chain should be user cert", expectedCert, actualChain[0]);
+
+ if (ca == null) {
+ assertEquals("Certificate chain should not include CAs", 1, actualChain.length);
+ } else {
+ @SuppressWarnings("unchecked")
+ Collection<Certificate> expectedChain = (Collection<Certificate>) certFact
+ .generateCertificates(new ByteArrayInputStream(ca));
+
+ int i = 1;
+ final Iterator<Certificate> it = expectedChain.iterator();
+ while (it.hasNext()) {
+ assertEquals("CA chain certificate should equal what we put in", it.next(),
+ actualChain[i++]);
+ }
+ }
+ }
+
+ public void testKeyStore_GetEntry_Nonexistent_NullParams_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertNull("A non-existent entry should return null",
+ mKeyStore.getEntry(TEST_ALIAS_1, null));
+ }
+
+ public void testKeyStore_GetKey_NoPassword_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+ FAKE_KEY_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ Key key = mKeyStore.getKey(TEST_ALIAS_1, null);
+ assertNotNull("Key should exist", key);
+
+ assertTrue("Should be a RSAPrivateKey", key instanceof RSAPrivateKey);
+
+ RSAPrivateKey actualKey = (RSAPrivateKey) key;
+
+ KeyFactory keyFact = KeyFactory.getInstance("RSA");
+ PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+
+ assertEquals("Inserted key should be same as retrieved key", actualKey, expectedKey);
+ }
+
+ public void testKeyStore_GetKey_Certificate_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ assertNull("Certificate entries should return null", mKeyStore.getKey(TEST_ALIAS_1, null));
+ }
+
+ public void testKeyStore_GetKey_NonExistent_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertNull("A non-existent entry should return null", mKeyStore.getKey(TEST_ALIAS_1, null));
+ }
+
+ public void testKeyStore_GetProvider_Success() throws Exception {
+ assertEquals(AndroidKeyStoreProvider.PROVIDER_NAME, mKeyStore.getProvider().getName());
+ }
+
+ public void testKeyStore_GetType_Success() throws Exception {
+ assertEquals(AndroidKeyStore.NAME, mKeyStore.getType());
+ }
+
+ public void testKeyStore_IsCertificateEntry_CA_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ assertTrue("Should return true for CA certificate",
+ mKeyStore.isCertificateEntry(TEST_ALIAS_1));
+ }
+
+ public void testKeyStore_IsCertificateEntry_PrivateKey_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+ FAKE_KEY_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ assertFalse("Should return false for PrivateKeyEntry",
+ mKeyStore.isCertificateEntry(TEST_ALIAS_1));
+ }
+
+ public void testKeyStore_IsCertificateEntry_NonExist_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertFalse("Should return false for non-existent entry",
+ mKeyStore.isCertificateEntry(TEST_ALIAS_1));
+ }
+
+ public void testKeyStore_IsKeyEntry_PrivateKey_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+ FAKE_KEY_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ assertTrue("Should return true for PrivateKeyEntry", mKeyStore.isKeyEntry(TEST_ALIAS_1));
+ }
+
+ public void testKeyStore_IsKeyEntry_CA_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ assertFalse("Should return false for CA certificate", mKeyStore.isKeyEntry(TEST_ALIAS_1));
+ }
+
+ public void testKeyStore_IsKeyEntry_NonExist_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertFalse("Should return false for non-existent entry",
+ mKeyStore.isKeyEntry(TEST_ALIAS_1));
+ }
+
+ public void testKeyStore_SetCertificate_CA_Success() throws Exception {
+ final CertificateFactory f = CertificateFactory.getInstance("X.509");
+ final Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ mKeyStore.load(null, null);
+
+ mKeyStore.setCertificateEntry(TEST_ALIAS_1, actual);
+ assertAliases(new String[] { TEST_ALIAS_1 });
+
+ Certificate retrieved = mKeyStore.getCertificate(TEST_ALIAS_1);
+
+ assertEquals("Retrieved certificate should be the same as the one inserted", actual,
+ retrieved);
+ }
+
+ public void testKeyStore_SetCertificate_CAExists_Overwrite_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ assertAliases(new String[] { TEST_ALIAS_1 });
+
+ final CertificateFactory f = CertificateFactory.getInstance("X.509");
+ final Certificate cert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ // TODO have separate FAKE_CA for second test
+ mKeyStore.setCertificateEntry(TEST_ALIAS_1, cert);
+
+ assertAliases(new String[] { TEST_ALIAS_1 });
+ }
+
+ public void testKeyStore_SetCertificate_PrivateKeyExists_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+ FAKE_KEY_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ assertAliases(new String[] { TEST_ALIAS_1 });
+
+ final CertificateFactory f = CertificateFactory.getInstance("X.509");
+ final Certificate cert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ try {
+ mKeyStore.setCertificateEntry(TEST_ALIAS_1, cert);
+ fail("Should throw when trying to overwrite a PrivateKey entry with a Certificate");
+ } catch (KeyStoreException success) {
+ }
+ }
+
+ public void testKeyStore_SetEntry_PrivateKeyEntry_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ KeyFactory keyFact = KeyFactory.getInstance("RSA");
+ PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+
+ final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+ final Certificate[] expectedChain = new Certificate[2];
+ expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+ expectedChain[1] = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ PrivateKeyEntry expected = new PrivateKeyEntry(expectedKey, expectedChain);
+
+ mKeyStore.setEntry(TEST_ALIAS_1, expected, null);
+
+ Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Retrieved entry should exist", actualEntry);
+
+ assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+ actualEntry instanceof PrivateKeyEntry);
+
+ PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+ assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+ }
+
+ public void testKeyStore_SetEntry_PrivateKeyEntry_Overwrites_PrivateKeyEntry_Success()
+ throws Exception {
+ mKeyStore.load(null, null);
+
+ final KeyFactory keyFact = KeyFactory.getInstance("RSA");
+ final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+ // Start with PrivateKeyEntry
+ {
+ PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+
+ final Certificate[] expectedChain = new Certificate[2];
+ expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+ expectedChain[1] = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ PrivateKeyEntry expected = new PrivateKeyEntry(expectedKey, expectedChain);
+
+ mKeyStore.setEntry(TEST_ALIAS_1, expected, null);
+
+ Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Retrieved entry should exist", actualEntry);
+
+ assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+ actualEntry instanceof PrivateKeyEntry);
+
+ PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+ assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+ }
+
+ // TODO make entirely new test vector for the overwrite
+ // Replace with PrivateKeyEntry
+ {
+ PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+
+ final Certificate[] expectedChain = new Certificate[2];
+ expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+ expectedChain[1] = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ PrivateKeyEntry expected = new PrivateKeyEntry(expectedKey, expectedChain);
+
+ mKeyStore.setEntry(TEST_ALIAS_1, expected, null);
+
+ Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Retrieved entry should exist", actualEntry);
+
+ assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+ actualEntry instanceof PrivateKeyEntry);
+
+ PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+ assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+ }
+ }
+
+ public void testKeyStore_SetEntry_CAEntry_Overwrites_PrivateKeyEntry_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+ // Start with TrustedCertificateEntry
+ {
+ final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ TrustedCertificateEntry expectedCertEntry = new TrustedCertificateEntry(caCert);
+ mKeyStore.setEntry(TEST_ALIAS_1, expectedCertEntry, null);
+
+ Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Retrieved entry should exist", actualEntry);
+ assertTrue("Retrieved entry should be of type TrustedCertificateEntry",
+ actualEntry instanceof TrustedCertificateEntry);
+ TrustedCertificateEntry actualCertEntry = (TrustedCertificateEntry) actualEntry;
+ assertEquals("Stored and retrieved certificates should be the same",
+ expectedCertEntry.getTrustedCertificate(),
+ actualCertEntry.getTrustedCertificate());
+ }
+
+ // Replace with PrivateKeyEntry
+ {
+ KeyFactory keyFact = KeyFactory.getInstance("RSA");
+ PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+ final Certificate[] expectedChain = new Certificate[2];
+ expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+ expectedChain[1] = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ PrivateKeyEntry expectedPrivEntry = new PrivateKeyEntry(expectedKey, expectedChain);
+
+ mKeyStore.setEntry(TEST_ALIAS_1, expectedPrivEntry, null);
+
+ Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Retrieved entry should exist", actualEntry);
+ assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+ actualEntry instanceof PrivateKeyEntry);
+
+ PrivateKeyEntry actualPrivEntry = (PrivateKeyEntry) actualEntry;
+ assertPrivateKeyEntryEquals(actualPrivEntry, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+ }
+ }
+
+ public void testKeyStore_SetEntry_PrivateKeyEntry_Overwrites_CAEntry_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+ final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ // Start with PrivateKeyEntry
+ {
+ KeyFactory keyFact = KeyFactory.getInstance("RSA");
+ PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+ final Certificate[] expectedChain = new Certificate[2];
+ expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+ expectedChain[1] = caCert;
+
+ PrivateKeyEntry expectedPrivEntry = new PrivateKeyEntry(expectedKey, expectedChain);
+
+ mKeyStore.setEntry(TEST_ALIAS_1, expectedPrivEntry, null);
+
+ Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Retrieved entry should exist", actualEntry);
+ assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+ actualEntry instanceof PrivateKeyEntry);
+
+ PrivateKeyEntry actualPrivEntry = (PrivateKeyEntry) actualEntry;
+ assertPrivateKeyEntryEquals(actualPrivEntry, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+ }
+
+ // Replace with TrustedCertificateEntry
+ {
+ TrustedCertificateEntry expectedCertEntry = new TrustedCertificateEntry(caCert);
+ mKeyStore.setEntry(TEST_ALIAS_1, expectedCertEntry, null);
+
+ Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Retrieved entry should exist", actualEntry);
+ assertTrue("Retrieved entry should be of type TrustedCertificateEntry",
+ actualEntry instanceof TrustedCertificateEntry);
+ TrustedCertificateEntry actualCertEntry = (TrustedCertificateEntry) actualEntry;
+ assertEquals("Stored and retrieved certificates should be the same",
+ expectedCertEntry.getTrustedCertificate(),
+ actualCertEntry.getTrustedCertificate());
+ }
+ }
+
+ public void testKeyStore_SetEntry_PrivateKeyEntry_Overwrites_ShortPrivateKeyEntry_Success()
+ throws Exception {
+ mKeyStore.load(null, null);
+
+ final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+ final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ // Start with PrivateKeyEntry
+ {
+ KeyFactory keyFact = KeyFactory.getInstance("RSA");
+ PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+ final Certificate[] expectedChain = new Certificate[2];
+ expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+ expectedChain[1] = caCert;
+
+ PrivateKeyEntry expectedPrivEntry = new PrivateKeyEntry(expectedKey, expectedChain);
+
+ mKeyStore.setEntry(TEST_ALIAS_1, expectedPrivEntry, null);
+
+ Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Retrieved entry should exist", actualEntry);
+ assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+ actualEntry instanceof PrivateKeyEntry);
+
+ PrivateKeyEntry actualPrivEntry = (PrivateKeyEntry) actualEntry;
+ assertPrivateKeyEntryEquals(actualPrivEntry, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+ }
+
+ // Replace with PrivateKeyEntry that has no chain
+ {
+ KeyFactory keyFact = KeyFactory.getInstance("RSA");
+ PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+ final Certificate[] expectedChain = new Certificate[1];
+ expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+
+ PrivateKeyEntry expectedPrivEntry = new PrivateKeyEntry(expectedKey, expectedChain);
+
+ mKeyStore.setEntry(TEST_ALIAS_1, expectedPrivEntry, null);
+
+ Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Retrieved entry should exist", actualEntry);
+ assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+ actualEntry instanceof PrivateKeyEntry);
+
+ PrivateKeyEntry actualPrivEntry = (PrivateKeyEntry) actualEntry;
+ assertPrivateKeyEntryEquals(actualPrivEntry, FAKE_KEY_1, FAKE_USER_1, null);
+ }
+ }
+
+ public void testKeyStore_SetEntry_CAEntry_Overwrites_CAEntry_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+ // Insert TrustedCertificateEntry
+ {
+ final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ TrustedCertificateEntry expectedCertEntry = new TrustedCertificateEntry(caCert);
+ mKeyStore.setEntry(TEST_ALIAS_1, expectedCertEntry, null);
+
+ Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Retrieved entry should exist", actualEntry);
+ assertTrue("Retrieved entry should be of type TrustedCertificateEntry",
+ actualEntry instanceof TrustedCertificateEntry);
+ TrustedCertificateEntry actualCertEntry = (TrustedCertificateEntry) actualEntry;
+ assertEquals("Stored and retrieved certificates should be the same",
+ expectedCertEntry.getTrustedCertificate(),
+ actualCertEntry.getTrustedCertificate());
+ }
+
+ // Replace with TrustedCertificateEntry of USER
+ {
+ final Certificate userCert = f
+ .generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+
+ TrustedCertificateEntry expectedUserEntry = new TrustedCertificateEntry(userCert);
+ mKeyStore.setEntry(TEST_ALIAS_1, expectedUserEntry, null);
+
+ Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Retrieved entry should exist", actualEntry);
+ assertTrue("Retrieved entry should be of type TrustedCertificateEntry",
+ actualEntry instanceof TrustedCertificateEntry);
+ TrustedCertificateEntry actualUserEntry = (TrustedCertificateEntry) actualEntry;
+ assertEquals("Stored and retrieved certificates should be the same",
+ expectedUserEntry.getTrustedCertificate(),
+ actualUserEntry.getTrustedCertificate());
+ }
+ }
+
+ public void testKeyStore_SetKeyEntry_ProtectedKey_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+ final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ KeyFactory keyFact = KeyFactory.getInstance("RSA");
+ PrivateKey privKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+ final Certificate[] chain = new Certificate[2];
+ chain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+ chain[1] = caCert;
+
+ try {
+ mKeyStore.setKeyEntry(TEST_ALIAS_1, privKey, "foo".toCharArray(), chain);
+ fail("Should fail when a password is specified");
+ } catch (KeyStoreException success) {
+ }
+ }
+
+ public void testKeyStore_SetKeyEntry_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+ final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ KeyFactory keyFact = KeyFactory.getInstance("RSA");
+ PrivateKey privKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+ final Certificate[] chain = new Certificate[2];
+ chain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+ chain[1] = caCert;
+
+ mKeyStore.setKeyEntry(TEST_ALIAS_1, privKey, null, chain);
+
+ Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Retrieved entry should exist", actualEntry);
+
+ assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+ actualEntry instanceof PrivateKeyEntry);
+
+ PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+ assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+ }
+
+ public void testKeyStore_SetKeyEntry_Replaced_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+ final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+ // Insert initial key
+ {
+ KeyFactory keyFact = KeyFactory.getInstance("RSA");
+ PrivateKey privKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+ final Certificate[] chain = new Certificate[2];
+ chain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+ chain[1] = caCert;
+
+ mKeyStore.setKeyEntry(TEST_ALIAS_1, privKey, null, chain);
+
+ Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Retrieved entry should exist", actualEntry);
+
+ assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+ actualEntry instanceof PrivateKeyEntry);
+
+ PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+ assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+ }
+
+ // TODO make a separate key
+ // Replace key
+ {
+ KeyFactory keyFact = KeyFactory.getInstance("RSA");
+ PrivateKey privKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+ final Certificate[] chain = new Certificate[2];
+ chain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+ chain[1] = caCert;
+
+ mKeyStore.setKeyEntry(TEST_ALIAS_1, privKey, null, chain);
+
+ Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+ assertNotNull("Retrieved entry should exist", actualEntry);
+
+ assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+ actualEntry instanceof PrivateKeyEntry);
+
+ PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+ assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+ }
+ }
+
+ public void testKeyStore_Size_Success() throws Exception {
+ mKeyStore.load(null, null);
+
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+ assertEquals("The keystore size should match expected", 1, mKeyStore.size());
+ assertAliases(new String[] { TEST_ALIAS_1 });
+
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+ assertEquals("The keystore size should match expected", 2, mKeyStore.size());
+ assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2 });
+
+ assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_3));
+
+ assertEquals("The keystore size should match expected", 3, mKeyStore.size());
+ assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2, TEST_ALIAS_3 });
+
+ assertTrue(mAndroidKeyStore.delete(Credentials.CA_CERTIFICATE + TEST_ALIAS_1));
+
+ assertEquals("The keystore size should match expected", 2, mKeyStore.size());
+ assertAliases(new String[] { TEST_ALIAS_2, TEST_ALIAS_3 });
+
+ assertTrue(mAndroidKeyStore.delKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_3));
+
+ assertEquals("The keystore size should match expected", 1, mKeyStore.size());
+ assertAliases(new String[] { TEST_ALIAS_2 });
+ }
+
+ public void testKeyStore_Store_LoadStoreParam_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ try {
+ mKeyStore.store(null);
+ fail("Should throw UnsupportedOperationException when trying to store");
+ } catch (UnsupportedOperationException success) {
+ }
+ }
+
+ public void testKeyStore_Load_InputStreamSupplied_Failure() throws Exception {
+ byte[] buf = "FAKE KEYSTORE".getBytes();
+ ByteArrayInputStream is = new ByteArrayInputStream(buf);
+
+ try {
+ mKeyStore.load(is, null);
+ fail("Should throw IllegalArgumentException when InputStream is supplied");
+ } catch (IllegalArgumentException success) {
+ }
+ }
+
+ public void testKeyStore_Load_PasswordSupplied_Failure() throws Exception {
+ try {
+ mKeyStore.load(null, "password".toCharArray());
+ fail("Should throw IllegalArgumentException when password is supplied");
+ } catch (IllegalArgumentException success) {
+ }
+ }
+
+ public void testKeyStore_Store_OutputStream_Failure() throws Exception {
+ mKeyStore.load(null, null);
+
+ OutputStream sink = new ByteArrayOutputStream();
+ try {
+ mKeyStore.store(sink, null);
+ fail("Should throw UnsupportedOperationException when trying to store");
+ } catch (UnsupportedOperationException success) {
+ }
+
+ try {
+ mKeyStore.store(sink, "blah".toCharArray());
+ fail("Should throw UnsupportedOperationException when trying to store");
+ } catch (UnsupportedOperationException success) {
+ }
+ }
+}
diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java
index 9f35b8d..07a2d7b 100755
--- a/keystore/tests/src/android/security/KeyStoreTest.java
+++ b/keystore/tests/src/android/security/KeyStoreTest.java
@@ -19,9 +19,11 @@ package android.security;
import android.app.Activity;
import android.security.KeyStore;
import android.test.ActivityUnitTestCase;
+import android.test.AssertionFailedError;
import android.test.suitebuilder.annotation.MediumTest;
import java.nio.charset.Charsets;
import java.util.Arrays;
+import java.util.Date;
import java.util.HashSet;
/**
@@ -403,4 +405,52 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
assertFalse("Should fail to ungrant key to other user second time",
mKeyStore.ungrant(TEST_KEYNAME, 0));
}
+
+ /**
+ * The amount of time to allow before and after expected time for variance
+ * in timing tests.
+ */
+ private static final long SLOP_TIME_MILLIS = 15000L;
+
+ public void testGetmtime_Success() throws Exception {
+ assertTrue("Password should work for keystore",
+ mKeyStore.password(TEST_PASSWD));
+
+ assertTrue("Should be able to import key when unlocked",
+ mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+
+ long now = System.currentTimeMillis();
+ long actual = mKeyStore.getmtime(TEST_KEYNAME);
+
+ long expectedAfter = now - SLOP_TIME_MILLIS;
+ long expectedBefore = now + SLOP_TIME_MILLIS;
+
+ assertLessThan("Time should be close to current time", expectedBefore, actual);
+ assertGreaterThan("Time should be close to current time", expectedAfter, actual);
+ }
+
+ private static void assertLessThan(String explanation, long expectedBefore, long actual) {
+ if (actual >= expectedBefore) {
+ throw new AssertionFailedError(explanation + ": actual=" + actual
+ + ", expected before: " + expectedBefore);
+ }
+ }
+
+ private static void assertGreaterThan(String explanation, long expectedAfter, long actual) {
+ if (actual <= expectedAfter) {
+ throw new AssertionFailedError(explanation + ": actual=" + actual
+ + ", expected after: " + expectedAfter);
+ }
+ }
+
+ public void testGetmtime_NonExist_Failure() throws Exception {
+ assertTrue("Password should work for keystore",
+ mKeyStore.password(TEST_PASSWD));
+
+ assertTrue("Should be able to import key when unlocked",
+ mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+
+ assertEquals("-1 should be returned for non-existent key",
+ -1L, mKeyStore.getmtime(TEST_KEYNAME2));
+ }
}
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index b352ffc..27e198c 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -109,11 +109,11 @@ CacheBlock* CacheBlock::removeBlock(CacheBlock* head, CacheBlock *blockToRemove)
}
///////////////////////////////////////////////////////////////////////////////
-// CacheTextureLine
+// CacheTexture
///////////////////////////////////////////////////////////////////////////////
-bool CacheTextureLine::fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
- if (glyph.fHeight + TEXTURE_BORDER_SIZE > mMaxHeight) {
+bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
+ if (glyph.fHeight + TEXTURE_BORDER_SIZE > mHeight) {
return false;
}
@@ -138,7 +138,7 @@ bool CacheTextureLine::fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uin
roundedUpW = glyphW;
}
*retOriginX = cacheBlock->mX;
- *retOriginY = mCurrentRow + cacheBlock->mY;
+ *retOriginY = cacheBlock->mY;
// If this is the remainder space, create a new cache block for this column. Otherwise,
// adjust the info about this column.
if (cacheBlock->mY == TEXTURE_BORDER_SIZE) {
@@ -146,10 +146,10 @@ bool CacheTextureLine::fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uin
// Adjust remainder space dimensions
cacheBlock->mWidth -= roundedUpW;
cacheBlock->mX += roundedUpW;
- if (mMaxHeight - glyphH >= glyphH) {
+ if (mHeight - glyphH >= glyphH) {
// There's enough height left over to create a new CacheBlock
- CacheBlock *newBlock = new CacheBlock(oldX, glyphH, roundedUpW,
- mMaxHeight - glyphH);
+ CacheBlock *newBlock = new CacheBlock(oldX, glyphH + TEXTURE_BORDER_SIZE,
+ roundedUpW, mHeight - glyphH - TEXTURE_BORDER_SIZE);
#if DEBUG_FONT_RENDERER
ALOGD("fitBitmap: Created new block: this, x, y, w, h = %p, %d, %d, %d, %d",
newBlock, newBlock->mX, newBlock->mY,
@@ -213,10 +213,10 @@ Font::~Font() {
}
}
-void Font::invalidateTextureCache(CacheTextureLine *cacheLine) {
+void Font::invalidateTextureCache(CacheTexture *cacheTexture) {
for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueAt(i);
- if (cacheLine == NULL || cachedGlyph->mCachedTextureLine == cacheLine) {
+ if (cacheTexture == NULL || cachedGlyph->mCacheTexture == cacheTexture) {
cachedGlyph->mIsValid = false;
}
}
@@ -260,7 +260,7 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
mState->appendMeshQuad(nPenX, nPenY, u1, v2,
nPenX + width, nPenY, u2, v2,
nPenX + width, nPenY - height, u2, v1,
- nPenX, nPenY - height, u1, v1, glyph->mCachedTextureLine->mCacheTexture);
+ nPenX, nPenY - height, u1, v1, glyph->mCacheTexture);
}
void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
@@ -271,7 +271,7 @@ void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
uint32_t endX = glyph->mStartX + glyph->mBitmapWidth;
uint32_t endY = glyph->mStartY + glyph->mBitmapHeight;
- CacheTexture *cacheTexture = glyph->mCachedTextureLine->mCacheTexture;
+ CacheTexture *cacheTexture = glyph->mCacheTexture;
uint32_t cacheWidth = cacheTexture->mWidth;
const uint8_t* cacheBuffer = cacheTexture->mTexture;
@@ -325,7 +325,7 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float
position->fY + destination[2].fY, u2, v1,
position->fX + destination[3].fX,
position->fY + destination[3].fY, u1, v1,
- glyph->mCachedTextureLine->mCacheTexture);
+ glyph->mCacheTexture);
}
CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit) {
@@ -556,8 +556,8 @@ void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyp
glyph->mBitmapWidth = skiaGlyph.fWidth;
glyph->mBitmapHeight = skiaGlyph.fHeight;
- uint32_t cacheWidth = glyph->mCachedTextureLine->mCacheTexture->mWidth;
- uint32_t cacheHeight = glyph->mCachedTextureLine->mCacheTexture->mHeight;
+ uint32_t cacheWidth = glyph->mCacheTexture->mWidth;
+ uint32_t cacheHeight = glyph->mCacheTexture->mHeight;
glyph->mBitmapMinU = startX / (float) cacheWidth;
glyph->mBitmapMinV = startY / (float) cacheHeight;
@@ -620,10 +620,6 @@ FontRenderer::FontRenderer() {
mTextMeshPtr = NULL;
mCurrentCacheTexture = NULL;
mLastCacheTexture = NULL;
- mCacheTextureSmall = NULL;
- mCacheTexture128 = NULL;
- mCacheTexture256 = NULL;
- mCacheTexture512 = NULL;
mLinearFiltering = false;
@@ -659,10 +655,10 @@ FontRenderer::FontRenderer() {
}
FontRenderer::~FontRenderer() {
- for (uint32_t i = 0; i < mCacheLines.size(); i++) {
- delete mCacheLines[i];
+ for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+ delete mCacheTextures[i];
}
- mCacheLines.clear();
+ mCacheTextures.clear();
if (mInitialized) {
// Unbinding the buffer shouldn't be necessary but it crashes with some drivers
@@ -670,10 +666,6 @@ FontRenderer::~FontRenderer() {
glDeleteBuffers(1, &mIndexBufferID);
delete[] mTextMeshPtr;
- delete mCacheTextureSmall;
- delete mCacheTexture128;
- delete mCacheTexture256;
- delete mCacheTexture512;
}
Vector<Font*> fontsToDereference = mActiveFonts;
@@ -692,29 +684,19 @@ void FontRenderer::flushAllAndInvalidate() {
mActiveFonts[i]->invalidateTextureCache();
}
- uint16_t totalGlyphs = 0;
- for (uint32_t i = 0; i < mCacheLines.size(); i++) {
- totalGlyphs += mCacheLines[i]->mNumGlyphs;
- mCacheLines[i]->init();
+ for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+ mCacheTextures[i]->init();
}
-#if DEBUG_FONT_RENDERER
- // Erase caches, just as a debugging facility
- if (mCacheTextureSmall && mCacheTextureSmall->mTexture) {
- memset(mCacheTextureSmall->mTexture, 0,
- mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight);
- }
- if (mCacheTexture128 && mCacheTexture128->mTexture) {
- memset(mCacheTexture128->mTexture, 0,
- mCacheTexture128->mWidth * mCacheTexture128->mHeight);
- }
- if (mCacheTexture256 && mCacheTexture256->mTexture) {
- memset(mCacheTexture256->mTexture, 0,
- mCacheTexture256->mWidth * mCacheTexture256->mHeight);
- }
- if (mCacheTexture512 && mCacheTexture512->mTexture) {
- memset(mCacheTexture512->mTexture, 0,
- mCacheTexture512->mWidth * mCacheTexture512->mHeight);
+ #if DEBUG_FONT_RENDERER
+ uint16_t totalGlyphs = 0;
+ for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+ totalGlyphs += mCacheTextures[i]->mNumGlyphs;
+ // Erase caches, just as a debugging facility
+ if (mCacheTextures[i]->mTexture) {
+ memset(mCacheTextures[i]->mTexture, 0,
+ mCacheTextures[i]->mWidth * mCacheTextures[i]->mHeight);
+ }
}
ALOGD("Flushing caches: glyphs cached = %d", totalGlyphs);
#endif
@@ -730,38 +712,17 @@ void FontRenderer::deallocateTextureMemory(CacheTexture *cacheTexture) {
}
void FontRenderer::flushLargeCaches() {
- if ((!mCacheTexture128 || !mCacheTexture128->mTexture) &&
- (!mCacheTexture256 || !mCacheTexture256->mTexture) &&
- (!mCacheTexture512 || !mCacheTexture512->mTexture)) {
- // Typical case; no large glyph caches allocated
- return;
- }
-
- for (uint32_t i = 0; i < mCacheLines.size(); i++) {
- CacheTextureLine* cacheLine = mCacheLines[i];
- if ((cacheLine->mCacheTexture == mCacheTexture128 ||
- cacheLine->mCacheTexture == mCacheTexture256 ||
- cacheLine->mCacheTexture == mCacheTexture512) &&
- cacheLine->mCacheTexture->mTexture != NULL) {
-#if DEBUG_FONT_RENDERER
- if (cacheLine->mCacheTexture == mCacheTexture128) {
- ALOGD("flushing cacheTexture128");
- } else if (cacheLine->mCacheTexture == mCacheTexture256) {
- ALOGD("flushing cacheTexture256");
- } else {
- ALOGD("flushing cacheTexture512");
- }
-#endif
- cacheLine->init();
- for (uint32_t i = 0; i < mActiveFonts.size(); i++) {
- mActiveFonts[i]->invalidateTextureCache(cacheLine);
+ // Start from 1; don't deallocate smallest/default texture
+ for (uint32_t i = 1; i < mCacheTextures.size(); i++) {
+ CacheTexture* cacheTexture = mCacheTextures[i];
+ if (cacheTexture->mTexture != NULL) {
+ cacheTexture->init();
+ for (uint32_t j = 0; j < mActiveFonts.size(); j++) {
+ mActiveFonts[j]->invalidateTextureCache(cacheTexture);
}
+ deallocateTextureMemory(cacheTexture);
}
}
-
- deallocateTextureMemory(mCacheTexture128);
- deallocateTextureMemory(mCacheTexture256);
- deallocateTextureMemory(mCacheTexture512);
}
void FontRenderer::allocateTextureMemory(CacheTexture* cacheTexture) {
@@ -789,12 +750,24 @@ void FontRenderer::allocateTextureMemory(CacheTexture* cacheTexture) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
+CacheTexture* FontRenderer::cacheBitmapInTexture(const SkGlyph& glyph,
+ uint32_t* startX, uint32_t* startY) {
+ for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+ if (mCacheTextures[i]->fitBitmap(glyph, startX, startY)) {
+ return mCacheTextures[i];
+ }
+ }
+ // Could not fit glyph into current cache textures
+ return NULL;
+}
+
void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
uint32_t* retOriginX, uint32_t* retOriginY) {
checkInit();
cachedGlyph->mIsValid = false;
// If the glyph is too tall, don't cache it
- if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
+ if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 >
+ mCacheTextures[mCacheTextures.size() - 1]->mHeight) {
ALOGE("Font size too large to fit in cache. width, height = %i, %i",
(int) glyph.fWidth, (int) glyph.fHeight);
return;
@@ -804,36 +777,22 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
uint32_t startX = 0;
uint32_t startY = 0;
- bool bitmapFit = false;
- CacheTextureLine *cacheLine;
- for (uint32_t i = 0; i < mCacheLines.size(); i++) {
- bitmapFit = mCacheLines[i]->fitBitmap(glyph, &startX, &startY);
- if (bitmapFit) {
- cacheLine = mCacheLines[i];
- break;
- }
- }
+ CacheTexture* cacheTexture = cacheBitmapInTexture(glyph, &startX, &startY);
// If the new glyph didn't fit, flush the state so far and invalidate everything
- if (!bitmapFit) {
+ if (!cacheTexture) {
flushAllAndInvalidate();
// Try to fit it again
- for (uint32_t i = 0; i < mCacheLines.size(); i++) {
- bitmapFit = mCacheLines[i]->fitBitmap(glyph, &startX, &startY);
- if (bitmapFit) {
- cacheLine = mCacheLines[i];
- break;
- }
- }
+ cacheTexture = cacheBitmapInTexture(glyph, &startX, &startY);
// if we still don't fit, something is wrong and we shouldn't draw
- if (!bitmapFit) {
+ if (!cacheTexture) {
return;
}
}
- cachedGlyph->mCachedTextureLine = cacheLine;
+ cachedGlyph->mCacheTexture = cacheTexture;
*retOriginX = startX;
*retOriginY = startY;
@@ -841,9 +800,8 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
uint32_t endX = startX + glyph.fWidth;
uint32_t endY = startY + glyph.fHeight;
- uint32_t cacheWidth = cacheLine->mMaxWidth;
+ uint32_t cacheWidth = cacheTexture->mWidth;
- CacheTexture* cacheTexture = cacheLine->mCacheTexture;
if (!cacheTexture->mTexture) {
// Large-glyph texture memory is allocated only as needed
allocateTextureMemory(cacheTexture);
@@ -896,17 +854,10 @@ CacheTexture* FontRenderer::createCacheTexture(int width, int height, bool alloc
}
void FontRenderer::initTextTexture() {
- for (uint32_t i = 0; i < mCacheLines.size(); i++) {
- delete mCacheLines[i];
- }
- mCacheLines.clear();
-
- if (mCacheTextureSmall) {
- delete mCacheTextureSmall;
- delete mCacheTexture128;
- delete mCacheTexture256;
- delete mCacheTexture512;
+ for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+ delete mCacheTextures[i];
}
+ mCacheTextures.clear();
// Next, use other, separate caches for large glyphs.
uint16_t maxWidth = 0;
@@ -918,35 +869,12 @@ void FontRenderer::initTextTexture() {
maxWidth = MAX_TEXT_CACHE_WIDTH;
}
- mCacheTextureSmall = createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, true);
- mCacheTexture128 = createCacheTexture(maxWidth, 256, false);
- mCacheTexture256 = createCacheTexture(maxWidth, 256, false);
- mCacheTexture512 = createCacheTexture(maxWidth, 512, false);
- mCurrentCacheTexture = mCacheTextureSmall;
-
mUploadTexture = false;
- // Split up our default cache texture into lines of certain widths
- int nextLine = 0;
- mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 18, nextLine, mCacheTextureSmall));
- nextLine += mCacheLines.top()->mMaxHeight;
- mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 26, nextLine, mCacheTextureSmall));
- nextLine += mCacheLines.top()->mMaxHeight;
- mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 26, nextLine, mCacheTextureSmall));
- nextLine += mCacheLines.top()->mMaxHeight;
- mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 34, nextLine, mCacheTextureSmall));
- nextLine += mCacheLines.top()->mMaxHeight;
- mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 34, nextLine, mCacheTextureSmall));
- nextLine += mCacheLines.top()->mMaxHeight;
- mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 42, nextLine, mCacheTextureSmall));
- nextLine += mCacheLines.top()->mMaxHeight;
- mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, mSmallCacheHeight - nextLine,
- nextLine, mCacheTextureSmall));
-
- // The first cache is split into 2 lines of height 128, the rest have just one cache line.
- mCacheLines.push(new CacheTextureLine(maxWidth, 128, 0, mCacheTexture128));
- mCacheLines.push(new CacheTextureLine(maxWidth, 128, 128, mCacheTexture128));
- mCacheLines.push(new CacheTextureLine(maxWidth, 256, 0, mCacheTexture256));
- mCacheLines.push(new CacheTextureLine(maxWidth, 512, 0, mCacheTexture512));
+ mCacheTextures.push(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, true));
+ mCacheTextures.push(createCacheTexture(maxWidth, 256, false));
+ mCacheTextures.push(createCacheTexture(maxWidth, 256, false));
+ mCacheTextures.push(createCacheTexture(maxWidth, 512, false));
+ mCurrentCacheTexture = mCacheTextures[0];
}
// Avoid having to reallocate memory and render quad by quad
@@ -1001,16 +929,14 @@ void FontRenderer::checkTextureUpdate() {
Caches& caches = Caches::getInstance();
GLuint lastTextureId = 0;
- // Iterate over all the cache lines and see which ones need to be updated
- for (uint32_t i = 0; i < mCacheLines.size(); i++) {
- CacheTextureLine* cl = mCacheLines[i];
- if (cl->mDirty && cl->mCacheTexture->mTexture != NULL) {
- CacheTexture* cacheTexture = cl->mCacheTexture;
+ // Iterate over all the cache textures and see which ones need to be updated
+ for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+ CacheTexture* cacheTexture = mCacheTextures[i];
+ if (cacheTexture->mDirty && cacheTexture->mTexture != NULL) {
uint32_t xOffset = 0;
- uint32_t yOffset = cl->mCurrentRow;
- uint32_t width = cl->mMaxWidth;
- uint32_t height = cl->mMaxHeight;
- void* textureData = cacheTexture->mTexture + (yOffset * width);
+ uint32_t width = cacheTexture->mWidth;
+ uint32_t height = cacheTexture->mHeight;
+ void* textureData = cacheTexture->mTexture;
if (cacheTexture->mTextureId != lastTextureId) {
caches.activeTexture(0);
@@ -1018,13 +944,13 @@ void FontRenderer::checkTextureUpdate() {
lastTextureId = cacheTexture->mTextureId;
}
#if DEBUG_FONT_RENDERER
- ALOGD("glTextSubimage for cacheLine %d: xOff, yOff, width height = %d, %d, %d, %d", i,
- xOffset, yOffset, width, height);
+ ALOGD("glTextSubimage for cacheTexture %d: xOff, width height = %d, %d, %d",
+ i, xOffset, width, height);
#endif
- glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, width, height,
+ glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, 0, width, height,
GL_ALPHA, GL_UNSIGNED_BYTE, textureData);
- cl->mDirty = false;
+ cacheTexture->mDirty = false;
}
}
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 8b1d10c..febae17 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -61,35 +61,14 @@ namespace uirenderer {
class FontRenderer;
-class CacheTexture {
-public:
- CacheTexture(uint16_t width, uint16_t height) :
- mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height),
- mLinearFiltering(false) { }
- ~CacheTexture() {
- if (mTexture) {
- delete[] mTexture;
- }
- if (mTextureId) {
- glDeleteTextures(1, &mTextureId);
- }
- }
-
- uint8_t* mTexture;
- GLuint mTextureId;
- uint16_t mWidth;
- uint16_t mHeight;
- bool mLinearFiltering;
-};
-
/**
- * CacheBlock is a noce in a linked list of current free space areas in a CacheTextureLine.
- * Using CacheBlocks enables us to pack the cache line from top to bottom as well as left to right.
+ * CacheBlock is a node in a linked list of current free space areas in a CacheTexture.
+ * Using CacheBlocks enables us to pack the cache from top to bottom as well as left to right.
* When we add a glyph to the cache, we see if it fits within one of the existing columns that
* have already been started (this is the case if the glyph fits vertically as well as
* horizontally, and if its width is sufficiently close to the column width to avoid
* sub-optimal packing of small glyphs into wide columns). If there is no column in which the
- * glyph fits, we check the final node, which is the remaining space in the cache line, creating
+ * glyph fits, we check the final node, which is the remaining space in the cache, creating
* a new column as appropriate.
*
* As columns fill up, we remove their CacheBlock from the list to avoid having to check
@@ -122,21 +101,22 @@ struct CacheBlock {
}
};
-class CacheTextureLine {
+class CacheTexture {
public:
- CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
- CacheTexture* cacheTexture):
- mMaxHeight(maxHeight),
- mMaxWidth(maxWidth),
- mCurrentRow(currentRow),
- mDirty(false),
- mNumGlyphs(0),
- mCacheTexture(cacheTexture) {
+ CacheTexture(uint16_t width, uint16_t height) :
+ mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height),
+ mLinearFiltering(false), mDirty(false), mNumGlyphs(0) {
mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
- maxWidth - TEXTURE_BORDER_SIZE, maxHeight - TEXTURE_BORDER_SIZE, true);
+ mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true);
}
- ~CacheTextureLine() {
+ ~CacheTexture() {
+ if (mTexture) {
+ delete[] mTexture;
+ }
+ if (mTextureId) {
+ glDeleteTextures(1, &mTextureId);
+ }
reset();
}
@@ -154,17 +134,18 @@ public:
// reset, then create a new remainder space to start again
reset();
mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
- mMaxWidth - TEXTURE_BORDER_SIZE, mMaxHeight - TEXTURE_BORDER_SIZE, true);
+ mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true);
}
bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
- uint16_t mMaxHeight;
- uint16_t mMaxWidth;
- uint32_t mCurrentRow;
+ uint8_t* mTexture;
+ GLuint mTextureId;
+ uint16_t mWidth;
+ uint16_t mHeight;
+ bool mLinearFiltering;
bool mDirty;
uint16_t mNumGlyphs;
- CacheTexture* mCacheTexture;
CacheBlock* mCacheBlocks;
};
@@ -193,7 +174,7 @@ struct CachedGlyphInfo {
// Auto-kerning
SkFixed mLsbDelta;
SkFixed mRsbDelta;
- CacheTextureLine* mCachedTextureLine;
+ CacheTexture* mCacheTexture;
};
@@ -260,7 +241,7 @@ protected:
// Cache of glyphs
DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
- void invalidateTextureCache(CacheTextureLine *cacheLine = NULL);
+ void invalidateTextureCache(CacheTexture *cacheTexture = NULL);
CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
@@ -364,17 +345,11 @@ public:
uint32_t getCacheSize() const {
uint32_t size = 0;
- if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
- size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
- }
- if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
- size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
- }
- if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
- size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
- }
- if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
- size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
+ for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+ CacheTexture* cacheTexture = mCacheTextures[i];
+ if (cacheTexture != NULL && cacheTexture->mTexture != NULL) {
+ size += cacheTexture->mWidth * cacheTexture->mHeight;
+ }
}
return size;
}
@@ -390,6 +365,7 @@ protected:
CacheTexture* createCacheTexture(int width, int height, bool allocate);
void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
uint32_t *retOriginX, uint32_t *retOriginY);
+ CacheTexture* cacheBitmapInTexture(const SkGlyph& glyph, uint32_t* startX, uint32_t* startY);
void flushAllAndInvalidate();
void initVertexArrayBuffers();
@@ -415,17 +391,13 @@ protected:
uint32_t mSmallCacheWidth;
uint32_t mSmallCacheHeight;
- Vector<CacheTextureLine*> mCacheLines;
+ Vector<CacheTexture*> mCacheTextures;
Font* mCurrentFont;
Vector<Font*> mActiveFonts;
CacheTexture* mCurrentCacheTexture;
CacheTexture* mLastCacheTexture;
- CacheTexture* mCacheTextureSmall;
- CacheTexture* mCacheTexture128;
- CacheTexture* mCacheTexture256;
- CacheTexture* mCacheTexture512;
void checkTextureUpdate();
bool mUploadTexture;
diff --git a/location/java/android/location/Criteria.java b/location/java/android/location/Criteria.java
index 6258a43..68fb4a0 100644
--- a/location/java/android/location/Criteria.java
+++ b/location/java/android/location/Criteria.java
@@ -24,7 +24,9 @@ import android.os.Parcelable;
* location provider. Providers maybe ordered according to accuracy,
* power usage, ability to report altitude, speed,
* and bearing, and monetary cost.
- * @deprecated {@link LocationRequest} instead
+ *
+ * @deprecated use {@link LocationRequest} instead, and also see notes
+ * at {@link LocationManager}
*/
@Deprecated
public class Criteria implements Parcelable {
diff --git a/location/java/android/location/Geofence.java b/location/java/android/location/Geofence.java
index 353a1ca..03cca84 100644
--- a/location/java/android/location/Geofence.java
+++ b/location/java/android/location/Geofence.java
@@ -20,7 +20,11 @@ import android.os.Parcel;
import android.os.Parcelable;
/**
- * Represents a Geofence
+ * Represents a geographical boundary, also known as a geofence.
+ *
+ * <p>Currently only circular geofences are supported, but this object
+ * is opaque so could be used in the future to represent polygons or other
+ * shapes.
*/
public final class Geofence implements Parcelable {
/** @hide */
@@ -33,6 +37,7 @@ public final class Geofence implements Parcelable {
/**
* Create a horizontal, circular geofence.
+ *
* @param latitude latitude in degrees
* @param longitude longitude in degrees
* @param radius radius in meters
@@ -152,6 +157,9 @@ public final class Geofence implements Parcelable {
return result;
}
+ /**
+ * Two geofences are equal if they have identical properties.
+ */
@Override
public boolean equals(Object obj) {
if (this == obj)
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index a2ce606..f663e0a 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -45,7 +45,7 @@ interface ILocationManager
in PendingIntent intent, String packageName);
void removeGeofence(in Geofence fence, in PendingIntent intent, String packageName);
- Location getLastLocation(in LocationRequest request);
+ Location getLastLocation(in LocationRequest request, String packageName);
boolean addGpsStatusListener(IGpsStatusListener listener);
void removeGpsStatusListener(IGpsStatusListener listener);
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index ece4500..40cb1a8 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -27,15 +27,15 @@ import java.text.DecimalFormat;
import java.util.StringTokenizer;
/**
- * A class representing a geographic location sensed at a particular
- * time (a "fix"). A location consists of a latitude and longitude, a
- * UTC timestamp. and optionally information on altitude, speed, and
- * bearing.
+ * A data class representing a geographic location.
*
- * <p> Information specific to a particular provider or class of
- * providers may be communicated to the application using getExtras,
- * which returns a Bundle of key/value pairs. Each provider will only
- * provide those entries for which information is available.
+ * <p>A location can consist of a latitude, longitude, timestamp,
+ * and other information such as bearing, altitude and velocity.
+ *
+ * <p>All locations generated by the {@link LocationManager} are
+ * guaranteed to have a valid latitude, longitude, and timestamp
+ * (both UTC time and elapsed real-time since boot), all other
+ * parameters are optional.
*/
public class Location implements Parcelable {
/**
@@ -86,20 +86,19 @@ public class Location implements Parcelable {
private float[] mResults = new float[2];
/**
- * Constructs a new Location. By default, time, latitude,
- * longitude, and numSatellites are 0; hasAltitude, hasSpeed, and
- * hasBearing are false; and there is no extra information.
+ * Construct a new Location with a named provider.
+ *
+ * <p>By default time, latitude and longitude are 0, and the location
+ * has no bearing, altitude, speed, accuracy or extras.
*
- * @param provider the name of the location provider that generated this
- * location fix.
+ * @param provider the name of the provider that generated this location
*/
public Location(String provider) {
mProvider = provider;
}
/**
- * Constructs a new Location object that is a copy of the given
- * location.
+ * Construct a new Location object that is copied from an existing one.
*/
public Location(Location l) {
set(l);
@@ -447,9 +446,19 @@ public class Location implements Parcelable {
}
/**
- * Returns the name of the provider that generated this fix,
- * or null if it is not associated with a provider.
+ * Returns the name of the provider that generated this fix.
+ *
+ * <p class="note">At API version 17 we deprecated {@link LocationProvider}
+ * and all API methods that request a provider by name. The new API methods
+ * will produce locations that could come from different sources, and even
+ * locations that are fused from several sources. So you should generally
+ * not care what provider is associated with a location object.
+ *
+ * @return the provider, or null if it has not been set
+ *
+ * @deprecated locations can now be sourced from many providers, or even fused
*/
+ @Deprecated
public String getProvider() {
return mProvider;
}
@@ -462,16 +471,19 @@ public class Location implements Parcelable {
}
/**
- * Return the UTC time of this fix, in milliseconds since January 1,
- * 1970.
+ * Return the UTC time of this fix, in milliseconds since January 1, 1970.
+ *
* <p>Note that the UTC time on a device is not monotonic: it
* can jump forwards or backwards unpredictably. So always use
- * {@link #getElapsedRealtimeNano()} when calculating time deltas.
- * <p>On the other hand, {@link #getTime()} is useful for presenting
+ * {@link #getElapsedRealtimeNano} when calculating time deltas.
+ *
+ * <p>On the other hand, {@link #getTime} is useful for presenting
* a human readable time to the user, or for carefully comparing
* location fixes across reboot or across devices.
- * <p>This method will always return a valid timestamp on
- * Locations generated by a {@link LocationProvider}.
+ *
+ * <p>All locations generated by the {@link LocationManager}
+ * are guaranteed to have a valid UTC time, however remember that
+ * the system time may have changed since the location was generated.
*
* @return time of fix, in milliseconds since January 1, 1970.
*/
@@ -491,13 +503,16 @@ public class Location implements Parcelable {
/**
* Return the time of this fix, in elapsed real-time since system boot.
+ *
* <p>This value can be reliably compared to
- * {@link android.os.SystemClock#elapsedRealtimeNano()},
- * to calculate the age of a fix, and to compare Location fixes, since
- * elapsed real-time is guaranteed monotonic for each system boot, and
- * continues to increment even when the system is in deep sleep.
- * <p>This method will always return a valid timestamp on
- * Locations generated by a {@link LocationProvider}.
+ * {@link android.os.SystemClock#elapsedRealtimeNano},
+ * to calculate the age of a fix and to compare Location fixes. This
+ * is reliable because elapsed real-time is guaranteed monotonic for
+ * each system boot and continues to increment even when the system
+ * is in deep sleep (unlike {@link #getTime}.
+ *
+ * <p>All locations generated by the {@link LocationManager}
+ * are guaranteed to have a valid elapsed real-time.
*
* @return elapsed real-time of fix, in nanoseconds since system boot.
*/
@@ -515,56 +530,59 @@ public class Location implements Parcelable {
}
/**
- * Return the latitude of this fix.
- * <p>This method will always return a valid latitude on
- * Locations generated by a {@link LocationProvider}.
+ * Get the latitude, in degrees.
+ *
+ * <p>All locations generated by the {@link LocationManager}
+ * will have a valid latitude.
*/
public double getLatitude() {
return mLatitude;
}
/**
- * Sets the latitude of this fix.
+ * Set the latitude, in degrees.
*/
public void setLatitude(double latitude) {
mLatitude = latitude;
}
/**
- * Return the longitude of this fix.
- * <p>This method will always return a valid longitude on
- * Locations generated by a {@link LocationProvider}.
+ * Get the longitude, in degrees.
+ *
+ * <p>All locations generated by the {@link LocationManager}
+ * will have a valid longitude.
*/
public double getLongitude() {
return mLongitude;
}
/**
- * Sets the longitude of this fix.
+ * Set the longitude, in degrees.
*/
public void setLongitude(double longitude) {
mLongitude = longitude;
}
/**
- * Returns true if this fix contains altitude information, false
- * otherwise.
+ * True if this location has an altitude.
*/
public boolean hasAltitude() {
return mHasAltitude;
}
/**
- * Returns the altitude of this fix. If {@link #hasAltitude} is false,
- * 0.0f is returned.
+ * Get the altitude if available, in meters above sea level.
+ *
+ * <p>If this location does not have an altitude then 0.0 is returned.
*/
public double getAltitude() {
return mAltitude;
}
/**
- * Sets the altitude of this fix. Following this call,
- * hasAltitude() will return true.
+ * Set the altitude, in meters above sea level.
+ *
+ * <p>Following this call {@link #hasAltitude} will return true.
*/
public void setAltitude(double altitude) {
mAltitude = altitude;
@@ -572,8 +590,10 @@ public class Location implements Parcelable {
}
/**
- * Clears the altitude of this fix. Following this call,
- * hasAltitude() will return false.
+ * Remove the altitude from this location.
+ *
+ * <p>Following this call {@link #hasAltitude} will return false,
+ * and {@link #getAltitude} will return 0.0.
*/
public void removeAltitude() {
mAltitude = 0.0f;
@@ -581,24 +601,25 @@ public class Location implements Parcelable {
}
/**
- * Returns true if this fix contains speed information, false
- * otherwise. The default implementation returns false.
+ * True if this location has a speed.
*/
public boolean hasSpeed() {
return mHasSpeed;
}
/**
- * Returns the speed of the device over ground in meters/second.
- * If hasSpeed() is false, 0.0f is returned.
+ * Get the speed if it is available, in meters/second over ground.
+ *
+ * <p>If this location does not have a speed then 0.0 is returned.
*/
public float getSpeed() {
return mSpeed;
}
/**
- * Sets the speed of this fix, in meters/second. Following this
- * call, hasSpeed() will return true.
+ * Set the speed, in meters/second over ground.
+ *
+ * <p>Following this call {@link #hasSpeed} will return true.
*/
public void setSpeed(float speed) {
mSpeed = speed;
@@ -606,8 +627,10 @@ public class Location implements Parcelable {
}
/**
- * Clears the speed of this fix. Following this call, hasSpeed()
- * will return false.
+ * Remove the speed from this location.
+ *
+ * <p>Following this call {@link #hasSpeed} will return false,
+ * and {@link #getSpeed} will return 0.0.
*/
public void removeSpeed() {
mSpeed = 0.0f;
@@ -615,24 +638,32 @@ public class Location implements Parcelable {
}
/**
- * Returns true if the provider is able to report bearing information,
- * false otherwise. The default implementation returns false.
+ * True if this location has a bearing.
*/
public boolean hasBearing() {
return mHasBearing;
}
/**
- * Returns the direction of travel in degrees East of true
- * North. If hasBearing() is false, 0.0 is returned.
+ * Get the bearing, in degrees.
+ *
+ * <p>Bearing is the horizontal direction of travel of this device,
+ * and is not related to the device orientation. It is guaranteed to
+ * be in the range (0.0, 360.0] if the device has a bearing.
+ *
+ * <p>If this location does not have a bearing then 0.0 is returned.
*/
public float getBearing() {
return mBearing;
}
/**
- * Sets the bearing of this fix. Following this call, hasBearing()
- * will return true.
+ * Set the bearing, in degrees.
+ *
+ * <p>Bearing is the horizontal direction of travel of this device,
+ * and is not related to the device orientation.
+ *
+ * <p>The input will be wrapped into the range (0.0, 360.0].
*/
public void setBearing(float bearing) {
while (bearing < 0.0f) {
@@ -646,8 +677,10 @@ public class Location implements Parcelable {
}
/**
- * Clears the bearing of this fix. Following this call, hasBearing()
- * will return false.
+ * Remove the bearing from this location.
+ *
+ * <p>Following this call {@link #hasBearing} will return false,
+ * and {@link #getBearing} will return 0.0.
*/
public void removeBearing() {
mBearing = 0.0f;
@@ -655,35 +688,47 @@ public class Location implements Parcelable {
}
/**
- * Return true if this Location has an associated accuracy.
- * <p>All Location objects generated by a {@link LocationProvider}
- * will have an accuracy.
+ * True if this location has an accuracy.
+ *
+ * <p>All locations generated by the {@link LocationManager} have an
+ * accuracy.
*/
public boolean hasAccuracy() {
return mHasAccuracy;
}
/**
- * Return the accuracy of this Location fix.
- * <p>Accuracy is measured in meters, and indicates the
- * radius of 95% confidence.
- * In other words, there is a 95% probability that the
- * true location is within a circle centered at the reported
- * location, with radius of the reported accuracy.
- * <p>This is only a measure of horizontal accuracy, and does
- * not indicate the accuracy of bearing, velocity or altitude
- * if those are included in this Location.
- * <p>If {@link #hasAccuracy} is false, 0.0 is returned.
- * <p>All Location object generated by a {@link LocationProvider}
- * will have a valid accuracy.
+ * Get the estimated accuracy of this location, in meters.
+ *
+ * <p>We define accuracy as the radius of 68% confidence. In other
+ * words, if you draw a circle centered at this location's
+ * latitude and longitude, and with a radius equal to the accuracy,
+ * then there is a 68% probability that the true location is inside
+ * the circle.
+ *
+ * <p>In statistical terms, it is assumed that location errors
+ * are random with a normal distribution, so the 68% confidence circle
+ * represents one standard deviation. Note that in practice, location
+ * errors do not always follow such a simple distribution.
+ *
+ * <p>This accuracy estimation is only concerned with horizontal
+ * accuracy, and does not indicate the accuracy of bearing,
+ * velocity or altitude if those are included in this Location.
+ *
+ * <p>If this location does not have an accuracy, then 0.0 is returned.
+ * All locations generated by the {@link LocationManager} include
+ * an accuracy.
*/
public float getAccuracy() {
return mAccuracy;
}
/**
- * Sets the accuracy of this fix. Following this call, hasAccuracy()
- * will return true.
+ * Set the estimated accuracy of this location, meters.
+ *
+ * <p>See {@link #getAccuracy} for the definition of accuracy.
+ *
+ * <p>Following this call {@link #hasAccuracy} will return true.
*/
public void setAccuracy(float accuracy) {
mAccuracy = accuracy;
@@ -691,8 +736,10 @@ public class Location implements Parcelable {
}
/**
- * Clears the accuracy of this fix. Following this call, hasAccuracy()
- * will return false.
+ * Remove the accuracy from this location.
+ *
+ * <p>Following this call {@link #hasAccuracy} will return false, and
+ * {@link #getAccuracy} will return 0.0.
*/
public void removeAccuracy() {
mAccuracy = 0.0f;
@@ -700,8 +747,14 @@ public class Location implements Parcelable {
}
/**
- * Return true if this Location object has enough data set to
- * be considered a valid fix from a {@link LocationProvider}.
+ * Return true if this Location object is complete.
+ *
+ * <p>A location object is currently considered complete if it has
+ * a valid provider, accuracy, wall-clock time and elapsed real-time.
+ *
+ * <p>All locations supplied by the {@link LocationManager} to
+ * applications must be complete.
+ *
* @see #makeComplete
* @hide
*/
@@ -714,9 +767,11 @@ public class Location implements Parcelable {
}
/**
- * Helper to fill in incomplete fields.
- * Only use this to assist in backwards compatibility
- * with Location objects received from applications.
+ * Helper to fill incomplete fields.
+ *
+ * <p>Used to assist in backwards compatibility with
+ * Location objects received from applications.
+ *
* @see #isComplete
* @hide
*/
@@ -770,9 +825,8 @@ public class Location implements Parcelable {
if (mElapsedRealtimeNano == 0) {
s.append(" et=?!?");
} else {
- long age = SystemClock.elapsedRealtimeNano() - mElapsedRealtimeNano;
- s.append(" age=");
- TimeUtils.formatDuration(age / 1000000L, s);
+ s.append(" et=");
+ TimeUtils.formatDuration(mElapsedRealtimeNano / 1000000L, s);
}
if (mHasAltitude) s.append(" alt=").append(mAltitude);
if (mHasSpeed) s.append(" vel=").append(mSpeed);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 5f87c84..bef363b 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -46,12 +46,41 @@ import com.android.internal.location.ProviderProperties;
* {@link android.content.Context#getSystemService
* Context.getSystemService(Context.LOCATION_SERVICE)}.
*
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>For more information about using location services, read the
- * <a href="{@docRoot}guide/topics/location/index.html">Location and Maps</a>
- * developer guide.</p>
- * </div>
+ * <p>At API version 17 the Location API's were simplified.
+ * Previously applications would need to explicitly enumerate, select, and
+ * track Location Providers (such as GPS or Network).
+ * This has been replaced by the concept of
+ * <em>Fused Location</em>. Now applications just specify the quality of service
+ * required for location updates (using the new {@link LocationRequest} class),
+ * and the system will fuse results from individual location providers
+ * as necessary before returning the result to the application.
+ *
+ * <p>As a result of this change, the {@link LocationProvider} and
+ * {@link Criteria} classes have been deprecated, in favor of
+ * {@link LocationRequest}. Furthermore, all Location Manager
+ * methods involving Criteria or explicitly named Providers have
+ * been deprecated, in favor of new variants that use
+ * {@link LocationRequest}.
+ *
+ * <p>A single {@link LocationRequest} object can trigger the use
+ * of all providers (including GPS, Network, and the passive) provider
+ * as necessary. This should result in a lot less work for your application. You
+ * no longer need to track the status and availability of each
+ * location provider. Just set the quality of locations required
+ * in {@link LocationRequest}, and let the system manage the rest.
+ *
+ * <p class="note">Unless noted, all Location API methods require
+ * the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} or
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permissions.
+ * If your application only has the Coarse permission then it will still
+ * receive location results, but the update rate will be throttled and
+ * the exact location will be obfuscated to a coarse level of accuracy.
+ *
+ * <p> class="note">Before API level 17, the use of 'fine' location
+ * providers such as GPS required the fine permission. As of API level
+ * 17, applications with only the coarse permission may use all providers,
+ * including GPS, but the locations are obfuscated (made coarse) before
+ * being sent to the application.
*/
public class LocationManager {
private static final String TAG = "LocationManager";
@@ -65,56 +94,69 @@ public class LocationManager {
private final GpsStatus mGpsStatus = new GpsStatus();
/**
- * Name of the network location provider. This provider determines location based on
+ * Name of the network location provider.
+ * <p>This provider determines location based on
* availability of cell tower and WiFi access points. Results are retrieved
* by means of a network lookup.
*
- * Requires either of the permissions android.permission.ACCESS_COARSE_LOCATION
- * or android.permission.ACCESS_FINE_LOCATION.
- * @deprecated use the {@link Criteria} class instead
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public static final String NETWORK_PROVIDER = "network";
/**
- * Name of the GPS location provider. This provider determines location using
+ * Name of the GPS location provider.
+ *
+ * <p>This provider determines location using
* satellites. Depending on conditions, this provider may take a while to return
* a location fix.
*
- * Requires the permission android.permission.ACCESS_FINE_LOCATION.
+ * <p>Before API version 17, this provider required the
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission.
+ * From API version 17 and onwards, this provider can also be used with
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}, however
+ * the locations returned will be obfuscated to a coarse level of accuracy.
*
* <p> The extras Bundle for the GPS location provider can contain the
* following key/value pairs:
- *
* <ul>
* <li> satellites - the number of satellites used to derive the fix
* </ul>
- * @deprecated use the {@link Criteria} class instead
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public static final String GPS_PROVIDER = "gps";
/**
* A special location provider for receiving locations without actually initiating
- * a location fix. This provider can be used to passively receive location updates
+ * a location fix.
+ *
+ * <p>This provider can be used to passively receive location updates
* when other applications or services request them without actually requesting
* the locations yourself. This provider will return locations generated by other
* providers. You can query the {@link Location#getProvider()} method to determine
* the origin of the location update.
*
- * Requires the permission android.permission.ACCESS_FINE_LOCATION, although if the GPS
- * is not enabled this provider might only return coarse fixes.
- * @deprecated use the {@link Criteria} class instead
+ * <p>Before API version 17, this provider required the
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission.
+ * From API version 17 and onwards, this provider can also be used with
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}, however
+ * the locations returned will be obfuscated to a coarse level of accuracy.
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public static final String PASSIVE_PROVIDER = "passive";
/**
- * Name of the Fused location provider.<p>
- * This provider combines inputs for all possible location sources
- * to provide the best possible Location fix.<p>
+ * Name of the Fused location provider.
+ *
+ * <p>This provider combines inputs for all possible location sources
+ * to provide the best possible Location fix. It is implicitly
+ * used for all API's that involve the {@link LocationRequest}
+ * object.
*
- * Requires the permission android.permission.ACCESS_FINE_LOCATION.
* @hide
*/
public static final String FUSED_PROVIDER = "fused";
@@ -128,7 +170,8 @@ public class LocationManager {
/**
* Key used for a Bundle extra holding an Integer status value
* when a status change is broadcast using a PendingIntent.
- * @deprecated use the {@link Criteria} class instead
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public static final String KEY_STATUS_CHANGED = "status";
@@ -136,7 +179,8 @@ public class LocationManager {
/**
* Key used for a Bundle extra holding an Boolean status value
* when a provider enabled/disabled event is broadcast using a PendingIntent.
- * @deprecated use the {@link Criteria} class instead
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
@@ -153,7 +197,7 @@ public class LocationManager {
* where {@code true} means enabled.
* @see #EXTRA_GPS_ENABLED
*
- * {@hide}
+ * @hide
*/
public static final String GPS_ENABLED_CHANGE_ACTION =
"android.location.GPS_ENABLED_CHANGE";
@@ -161,7 +205,8 @@ public class LocationManager {
/**
* Broadcast intent action when the configured location providers
* change.
- * @deprecated use the {@link Criteria} class instead
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public static final String PROVIDERS_CHANGED_ACTION =
@@ -173,7 +218,7 @@ public class LocationManager {
* boolean, where {@code true} means that the GPS is actively receiving fixes.
* @see #EXTRA_GPS_ENABLED
*
- * {@hide}
+ * @hide
*/
public static final String GPS_FIX_CHANGE_ACTION =
"android.location.GPS_FIX_CHANGE";
@@ -183,7 +228,7 @@ public class LocationManager {
* disabled. {@code true} means GPS is enabled. Retrieve it with
* {@link android.content.Intent#getBooleanExtra(String,boolean)}.
*
- * {@hide}
+ * @hide
*/
public static final String EXTRA_GPS_ENABLED = "enabled";
@@ -285,6 +330,7 @@ public class LocationManager {
}
}
}
+
/**
* @hide - hide this constructor because it has a parameter
* of type ILocationManager, which is a system private class. The
@@ -301,12 +347,13 @@ public class LocationManager {
}
/**
- * Returns a list of the names of all known location providers. All
- * providers are returned, including ones that are not permitted to be
- * accessed by the calling activity or are currently disabled.
+ * Returns a list of the names of all known location providers.
+ * <p>All providers are returned, including ones that are not permitted to
+ * be accessed by the calling activity or are currently disabled.
*
- * @return list of Strings containing names of the providers
- * @deprecated use the {@link Criteria} class instead
+ * @return list of Strings containing names of the provider
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public List<String> getAllProviders() {
@@ -319,15 +366,13 @@ public class LocationManager {
}
/**
- * Returns a list of the names of location providers. Only providers that
- * are permitted to be accessed by the calling activity will be returned.
+ * Returns a list of the names of location providers.
*
* @param enabledOnly if true then only the providers which are currently
* enabled are returned.
* @return list of Strings containing names of the providers
- * @deprecated The {@link LocationProvider} class is deprecated. So
- * use the {@link Criteria} class to request location instead of
- * enumerating providers.
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public List<String> getProviders(boolean enabledOnly) {
@@ -346,12 +391,11 @@ public class LocationManager {
* @param name the provider name
* @return a LocationProvider, or null
*
- * @throws IllegalArgumentException if name is null or does not exisit
+ * @throws IllegalArgumentException if name is null or does not exist
* @throws SecurityException if the caller is not permitted to access the
* given provider.
- * @deprecated The {@link LocationProvider} class is deprecated. So
- * use the {@link Criteria} class to request location instead of
- * enumerating providers.
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public LocationProvider getProvider(String name) {
@@ -377,9 +421,8 @@ public class LocationManager {
* @param enabledOnly if true then only the providers which are currently
* enabled are returned.
* @return list of Strings containing names of the providers
- * @deprecated The {@link LocationProvider} class is deprecated. So
- * use the {@link Criteria} class to request location instead of
- * enumerating providers.
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
@@ -413,7 +456,8 @@ public class LocationManager {
* @param criteria the criteria that need to be matched
* @param enabledOnly if true then only a provider that is currently enabled is returned
* @return name of the provider that best matches the requirements
- * @deprecated using an explicit provider doesn't allow fused location
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public String getBestProvider(Criteria criteria, boolean enabledOnly) {
@@ -427,64 +471,11 @@ public class LocationManager {
}
/**
- * Registers the current activity to be notified periodically by
- * the named provider. Periodically, the supplied LocationListener will
- * be called with the current Location or with status updates.
- *
- * <p> It may take a while to receive the first location update. If
- * an immediate location is required, applications may use the
- * {@link #getLastKnownLocation(String)} method.
- *
- * <p> In case the provider is disabled by the user, updates will stop,
- * and the {@link LocationListener#onProviderDisabled(String)}
- * method will be called. As soon as the provider is enabled again,
- * the {@link LocationListener#onProviderEnabled(String)} method will
- * be called and location updates will start again.
- *
- * <p> The update interval can be controlled using the minTime parameter.
- * The elapsed time between location updates will never be less than
- * minTime, although it can be more depending on the Location Provider
- * implementation and the update interval requested by other applications.
- *
- * <p> Choosing a sensible value for minTime is important to conserve
- * battery life. Each location update requires power from
- * GPS, WIFI, Cell and other radios. Select a minTime value as high as
- * possible while still providing a reasonable user experience.
- * If your application is not in the foreground and showing
- * location to the user then your application should avoid using an active
- * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}),
- * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes)
- * or greater. If your application is in the foreground and showing
- * location to the user then it is appropriate to select a faster
- * update interval.
+ * Register for location updates using the named provider, and a
+ * pending intent.
*
- * <p> The minDistance parameter can also be used to control the
- * frequency of location updates. If it is greater than 0 then the
- * location provider will only send your application an update when
- * the location has changed by at least minDistance meters, AND
- * at least minTime milliseconds have passed. However it is more
- * difficult for location providers to save power using the minDistance
- * parameter, so minTime should be the primary tool to conserving battery
- * life.
- *
- * <p> If your application wants to passively observe location
- * updates triggered by other applications, but not consume
- * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER}
- * This provider does not actively turn on or modify active location
- * providers, so you do not need to be as careful about minTime and
- * minDistance. However if your application performs heavy work
- * on a location update (such as network activity) then you should
- * select non-zero values for minTime and/or minDistance to rate-limit
- * your update frequency in the case another application enables a
- * location provider with extremely fast updates.
- *
- * <p> The calling thread must be a {@link android.os.Looper} thread such as
- * the main thread of the calling Activity.
- *
- * <p class="note"> Prior to Jellybean, the minTime parameter was
- * only a hint, and some location provider implementations ignored it.
- * From Jellybean and onwards it is mandatory for Android compatible
- * devices to observe both the minTime and minDistance parameters.
+ * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+ * for more detail on how to use this (deprecated) method.
*
* @param provider the name of the provider with which to register
* @param minTime minimum time interval between location updates, in milliseconds
@@ -497,8 +488,8 @@ public class LocationManager {
* on this device
* @throws IllegalArgumentException if listener is null
* @throws RuntimeException if the calling thread has no Looper
- * @throws SecurityException if no suitable permission is present for the provider.
- * @deprecated use the {@link LocationRequest} class instead
+ * @throws SecurityException if no suitable permission is present
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public void requestLocationUpdates(String provider, long minTime, float minDistance,
@@ -512,63 +503,11 @@ public class LocationManager {
}
/**
- * Registers the current activity to be notified periodically by
- * the named provider. Periodically, the supplied LocationListener will
- * be called with the current Location or with status updates.
- *
- * <p> It may take a while to receive the first location update. If
- * an immediate location is required, applications may use the
- * {@link #getLastKnownLocation(String)} method.
+ * Register for location updates using the named provider, and a callback on
+ * the specified looper thread.
*
- * <p> In case the provider is disabled by the user, updates will stop,
- * and the {@link LocationListener#onProviderDisabled(String)}
- * method will be called. As soon as the provider is enabled again,
- * the {@link LocationListener#onProviderEnabled(String)} method will
- * be called and location updates will start again.
- *
- * <p> The update interval can be controlled using the minTime parameter.
- * The elapsed time between location updates will never be less than
- * minTime, although it can be more depending on the Location Provider
- * implementation and the update interval requested by other applications.
- *
- * <p> Choosing a sensible value for minTime is important to conserve
- * battery life. Each location update requires power from
- * GPS, WIFI, Cell and other radios. Select a minTime value as high as
- * possible while still providing a reasonable user experience.
- * If your application is not in the foreground and showing
- * location to the user then your application should avoid using an active
- * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}),
- * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes)
- * or greater. If your application is in the foreground and showing
- * location to the user then it is appropriate to select a faster
- * update interval.
- *
- * <p> The minDistance parameter can also be used to control the
- * frequency of location updates. If it is greater than 0 then the
- * location provider will only send your application an update when
- * the location has changed by at least minDistance meters, AND
- * at least minTime milliseconds have passed. However it is more
- * difficult for location providers to save power using the minDistance
- * parameter, so minTime should be the primary tool to conserving battery
- * life.
- *
- * <p> If your application wants to passively observe location
- * updates triggered by other applications, but not consume
- * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER}
- * This provider does not actively turn on or modify active location
- * providers, so you do not need to be as careful about minTime and
- * minDistance. However if your application performs heavy work
- * on a location update (such as network activity) then you should
- * select non-zero values for minTime and/or minDistance to rate-limit
- * your update frequency in the case another application enables a
- * location provider with extremely fast updates.
- *
- * <p> The supplied Looper is used to implement the callback mechanism.
- *
- * <p class="note"> Prior to Jellybean, the minTime parameter was
- * only a hint, and some location provider implementations ignored it.
- * From Jellybean and onwards it is mandatory for Android compatible
- * devices to observe both the minTime and minDistance parameters.
+ * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+ * for more detail on how to use this (deprecated) method.
*
* @param provider the name of the provider with which to register
* @param minTime minimum time interval between location updates, in milliseconds
@@ -577,13 +516,14 @@ public class LocationManager {
* {@link LocationListener#onLocationChanged} method will be called for
* each location update
* @param looper a Looper object whose message queue will be used to
- * implement the callback mechanism, or null to make callbacks on the
- * main thread
+ * implement the callback mechanism, or null to make callbacks on the calling
+ * thread
*
* @throws IllegalArgumentException if provider is null or doesn't exist
* @throws IllegalArgumentException if listener is null
- * @throws SecurityException if no suitable permission is present for the provider.
- * @deprecated use the {@link LocationRequest} class instead
+ * @throws SecurityException if no suitable permission is present
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public void requestLocationUpdates(String provider, long minTime, float minDistance,
@@ -597,52 +537,11 @@ public class LocationManager {
}
/**
- * Registers the current activity to be notified periodically based on
- * the supplied criteria. Periodically, the supplied LocationListener will
- * be called with the current Location or with status updates.
+ * Register for location updates using a Criteria, and a callback
+ * on the specified looper thread.
*
- * <p> It may take a while to receive the first location update. If
- * an immediate location is required, applications may use the
- * {@link #getLastKnownLocation(String)} method.
- *
- * <p> In case the provider is disabled by the user, updates will stop,
- * and the {@link LocationListener#onProviderDisabled(String)}
- * method will be called. As soon as the provider is enabled again,
- * the {@link LocationListener#onProviderEnabled(String)} method will
- * be called and location updates will start again.
- *
- * <p> The update interval can be controlled using the minTime parameter.
- * The elapsed time between location updates will never be less than
- * minTime, although it can be more depending on the Location Provider
- * implementation and the update interval requested by other applications.
- *
- * <p> Choosing a sensible value for minTime is important to conserve
- * battery life. Each location update requires power from
- * GPS, WIFI, Cell and other radios. Select a minTime value as high as
- * possible while still providing a reasonable user experience.
- * If your application is not in the foreground and showing
- * location to the user then your application should avoid using an active
- * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}),
- * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes)
- * or greater. If your application is in the foreground and showing
- * location to the user then it is appropriate to select a faster
- * update interval.
- *
- * <p> The minDistance parameter can also be used to control the
- * frequency of location updates. If it is greater than 0 then the
- * location provider will only send your application an update when
- * the location has changed by at least minDistance meters, AND
- * at least minTime milliseconds have passed. However it is more
- * difficult for location providers to save power using the minDistance
- * parameter, so minTime should be the primary tool to conserving battery
- * life.
- *
- * <p> The supplied Looper is used to implement the callback mechanism.
- *
- * <p class="note"> Prior to Jellybean, the minTime parameter was
- * only a hint, and some location provider implementations ignored it.
- * From Jellybean and onwards it is mandatory for Android compatible
- * devices to observe both the minTime and minDistance parameters.
+ * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+ * for more detail on how to use this (deprecated) method.
*
* @param minTime minimum time interval between location updates, in milliseconds
* @param minDistance minimum distance between location updates, in meters
@@ -652,13 +551,14 @@ public class LocationManager {
* {@link LocationListener#onLocationChanged} method will be called for
* each location update
* @param looper a Looper object whose message queue will be used to
- * implement the callback mechanism, or null to make callbacks on the
- * main thread.
+ * implement the callback mechanism, or null to make callbacks on the calling
+ * thread
*
* @throws IllegalArgumentException if criteria is null
* @throws IllegalArgumentException if listener is null
- * @throws SecurityException if no suitable permission is present for the provider.
- * @deprecated use the {@link LocationRequest} class instead
+ * @throws SecurityException if no suitable permission is present
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria,
@@ -672,70 +572,11 @@ public class LocationManager {
}
/**
- * Registers the current activity to be notified periodically by
- * the named provider. Periodically, the supplied PendingIntent will
- * be broadcast with the current Location or with status updates.
- *
- * <p> Location updates are sent with a key of
- * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value.
- *
- * <p> It may take a while to receive the first location update. If
- * an immediate location is required, applications may use the
- * {@link #getLastKnownLocation(String)} method.
- *
- * <p> The update interval can be controlled using the minTime parameter.
- * The elapsed time between location updates will never be less than
- * minTime, although it can be more depending on the Location Provider
- * implementation and the update interval requested by other applications.
- *
- * <p> Choosing a sensible value for minTime is important to conserve
- * battery life. Each location update requires power from
- * GPS, WIFI, Cell and other radios. Select a minTime value as high as
- * possible while still providing a reasonable user experience.
- * If your application is not in the foreground and showing
- * location to the user then your application should avoid using an active
- * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}),
- * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes)
- * or greater. If your application is in the foreground and showing
- * location to the user then it is appropriate to select a faster
- * update interval.
- *
- * <p> The minDistance parameter can also be used to control the
- * frequency of location updates. If it is greater than 0 then the
- * location provider will only send your application an update when
- * the location has changed by at least minDistance meters, AND
- * at least minTime milliseconds have passed. However it is more
- * difficult for location providers to save power using the minDistance
- * parameter, so minTime should be the primary tool to conserving battery
- * life.
- *
- * <p> If your application wants to passively observe location
- * updates triggered by other applications, but not consume
- * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER}
- * This provider does not actively turn on or modify active location
- * providers, so you do not need to be as careful about minTime and
- * minDistance. However if your application performs heavy work
- * on a location update (such as network activity) then you should
- * select non-zero values for minTime and/or minDistance to rate-limit
- * your update frequency in the case another application enables a
- * location provider with extremely fast updates.
+ * Register for location updates using the named provider, and a
+ * pending intent.
*
- * <p> If the provider is disabled by the user, updates will stop,
- * and an intent will be sent with an extra with key
- * {@link #KEY_PROVIDER_ENABLED} and a boolean value of false.
- * If the provider is re-enabled, an intent will be sent with an
- * extra with key {@link #KEY_PROVIDER_ENABLED} and a boolean value of
- * true and location updates will start again.
- *
- * <p> If the provider's status changes, an intent will be sent with
- * an extra with key {@link #KEY_STATUS_CHANGED} and an integer value
- * indicating the new status. Any extras associated with the status
- * update will be sent as well.
- *
- * <p class="note"> Prior to Jellybean, the minTime parameter was
- * only a hint, and some location provider implementations ignored it.
- * From Jellybean and onwards it is mandatory for Android compatible
- * devices to observe both the minTime and minDistance parameters.
+ * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+ * for more detail on how to use this (deprecated) method.
*
* @param provider the name of the provider with which to register
* @param minTime minimum time interval between location updates, in milliseconds
@@ -745,8 +586,9 @@ public class LocationManager {
* @throws IllegalArgumentException if provider is null or doesn't exist
* on this device
* @throws IllegalArgumentException if intent is null
- * @throws SecurityException if no suitable permission is present for the provider.
- * @deprecated use the {@link LocationRequest} class instead
+ * @throws SecurityException if no suitable permission is present
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public void requestLocationUpdates(String provider, long minTime, float minDistance,
@@ -760,18 +602,28 @@ public class LocationManager {
}
/**
- * Registers the current activity to be notified periodically based on
- * the supplied criteria. Periodically, the supplied PendingIntent will
- * be broadcast with the current Location or with status updates.
+ * Register for location updates using a Criteria and pending intent.
+ *
+ * <p>The <code>requestLocationUpdates()</code> and
+ * <code>requestSingleUpdate()</code> methods involving
+ * an explicit String provider or {@link Criteria} are deprecated.
*
- * <p> Location updates are sent with a key of
- * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value.
+ * <p>They register the current activity to be updated
+ * periodically by the named provider, or by the provider matching
+ * the specified {@link Criteria}, with location and status updates.
*
* <p> It may take a while to receive the first location update. If
* an immediate location is required, applications may use the
* {@link #getLastKnownLocation(String)} method.
*
- * <p> The update interval can be controlled using the minTime parameter.
+ * <p> Location updates are received either by {@link LocationListener}
+ * callbacks, or by broadcast intents to a supplied {@link PendingIntent}.
+ *
+ * <p> If the caller supplied a pending intent, then location updates
+ * are sent with a key of {@link #KEY_LOCATION_CHANGED} and a
+ * {@link android.location.Location} value.
+ *
+ * <p> The location update interval can be controlled using the minTime parameter.
* The elapsed time between location updates will never be less than
* minTime, although it can be more depending on the Location Provider
* implementation and the update interval requested by other applications.
@@ -797,17 +649,36 @@ public class LocationManager {
* parameter, so minTime should be the primary tool to conserving battery
* life.
*
- * <p> If the provider is disabled by the user, updates will stop,
- * and an intent will be sent with an extra with key
- * {@link #KEY_PROVIDER_ENABLED} and a boolean value of false.
- * If the provider is re-enabled, an intent will be sent with an
- * extra with key {@link #KEY_PROVIDER_ENABLED} and a boolean value of
- * true and location updates will start again.
+ * <p> If your application wants to passively observe location
+ * updates triggered by other applications, but not consume
+ * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER}
+ * This provider does not actively turn on or modify active location
+ * providers, so you do not need to be as careful about minTime and
+ * minDistance. However if your application performs heavy work
+ * on a location update (such as network activity) then you should
+ * select non-zero values for minTime and/or minDistance to rate-limit
+ * your update frequency in the case another application enables a
+ * location provider with extremely fast updates.
*
- * <p> If the provider's status changes, an intent will be sent with
- * an extra with key {@link #KEY_STATUS_CHANGED} and an integer value
- * indicating the new status. Any extras associated with the status
- * update will be sent as well.
+ * <p>In case the provider is disabled by the user, updates will stop,
+ * and a provider availability update will be sent.
+ * As soon as the provider is enabled again,
+ * location updates will immediately resume and a provider availability
+ * update sent. Providers can also send status updates, at any time,
+ * with extra's specific to the provider. If a callback was supplied
+ * then status and availability updates are via
+ * {@link LocationListener#onProviderDisabled},
+ * {@link LocationListener#onProviderEnabled} or
+ * {@link LocationListener#onStatusChanged}. Alternately, if a
+ * pending intent was supplied then status and availability updates
+ * are broadcast intents with extra keys of
+ * {@link #KEY_PROVIDER_ENABLED} or {@link #KEY_STATUS_CHANGED}.
+ *
+ * <p> If a {@link LocationListener} is used but with no Looper specified
+ * then the calling thread must already
+ * be a {@link android.os.Looper} thread such as the main thread of the
+ * calling Activity. If a Looper is specified with a {@link LocationListener}
+ * then callbacks are made on the supplied Looper thread.
*
* <p class="note"> Prior to Jellybean, the minTime parameter was
* only a hint, and some location provider implementations ignored it.
@@ -822,8 +693,9 @@ public class LocationManager {
*
* @throws IllegalArgumentException if criteria is null
* @throws IllegalArgumentException if intent is null
- * @throws SecurityException if no suitable permission is present for the provider.
- * @deprecated use the {@link LocationRequest} class instead
+ * @throws SecurityException if no suitable permission is present
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria,
@@ -837,32 +709,25 @@ public class LocationManager {
}
/**
- * Requests a single location update from the named provider.
- *
- * <p> It may take a while to receive the most recent location. If
- * an immediate location is required, applications may use the
- * {@link #getLastKnownLocation(String)} method.
- *
- * <p> In case the provider is disabled by the user, the update will not be received,
- * and the {@link LocationListener#onProviderDisabled(String)}
- * method will be called. As soon as the provider is enabled again,
- * the {@link LocationListener#onProviderEnabled(String)} method will
- * be called and location updates will start again.
+ * Register for a single location update using the named provider and
+ * a callback.
*
- * <p> The supplied Looper is used to implement the callback mechanism.
+ * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+ * for more detail on how to use this (deprecated) method.
*
* @param provider the name of the provider with which to register
* @param listener a {#link LocationListener} whose
* {@link LocationListener#onLocationChanged} method will be called when
* the location update is available
* @param looper a Looper object whose message queue will be used to
- * implement the callback mechanism, or null to make callbacks on the
- * main thread
+ * implement the callback mechanism, or null to make callbacks on the calling
+ * thread
*
* @throws IllegalArgumentException if provider is null or doesn't exist
* @throws IllegalArgumentException if listener is null
- * @throws SecurityException if no suitable permission is present for the provider
- * @deprecated use the {@link LocationRequest} class instead
+ * @throws SecurityException if no suitable permission is present
+ *
+ * @deprecated Use {@link LocationRequest#setNumUpdates} instead
*/
@Deprecated
public void requestSingleUpdate(String provider, LocationListener listener, Looper looper) {
@@ -875,19 +740,11 @@ public class LocationManager {
}
/**
- * Requests a single location update based on the specified criteria.
- *
- * <p> It may take a while to receive the most recent location. If
- * an immediate location is required, applications may use the
- * {@link #getLastKnownLocation(String)} method.
- *
- * <p> In case the provider is disabled by the user, the update will not be received,
- * and the {@link LocationListener#onProviderDisabled(String)}
- * method will be called. As soon as the provider is enabled again,
- * the {@link LocationListener#onProviderEnabled(String)} method will
- * be called and location updates will start again.
+ * Register for a single location update using a Criteria and
+ * a callback.
*
- * <p> The supplied Looper is used to implement the callback mechanism.
+ * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+ * for more detail on how to use this (deprecated) method.
*
* @param criteria contains parameters for the location manager to choose the
* appropriate provider and parameters to compute the location
@@ -895,14 +752,14 @@ public class LocationManager {
* {@link LocationListener#onLocationChanged} method will be called when
* the location update is available
* @param looper a Looper object whose message queue will be used to
- * implement the callback mechanism, or null to make callbacks on the
- * main thread
+ * implement the callback mechanism, or null to make callbacks on the calling
+ * thread
*
* @throws IllegalArgumentException if criteria is null
* @throws IllegalArgumentException if listener is null
- * @throws SecurityException if no suitable permission is present to access
- * the location services
- * @deprecated use the {@link LocationRequest} class instead
+ * @throws SecurityException if no suitable permission is present
+ *
+ * @deprecated Use {@link LocationRequest#setNumUpdates} instead
*/
@Deprecated
public void requestSingleUpdate(Criteria criteria, LocationListener listener, Looper looper) {
@@ -915,28 +772,19 @@ public class LocationManager {
}
/**
- * Requests a single location update from the named provider.
- *
- * <p> It may take a while to receive the most recent location. If
- * an immediate location is required, applications may use the
- * {@link #getLastKnownLocation(String)} method.
- *
- * <p> Location updates are sent with a key of
- * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value.
+ * Register for a single location update using a named provider and pending intent.
*
- * <p> In case the provider is disabled by the user, the update will not be received,
- * and the {@link LocationListener#onProviderDisabled(String)}
- * method will be called. As soon as the provider is enabled again,
- * the {@link LocationListener#onProviderEnabled(String)} method will
- * be called and location updates will start again.
+ * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+ * for more detail on how to use this (deprecated) method.
*
* @param provider the name of the provider with which to register
* @param intent a {#link PendingIntent} to be sent for the location update
*
* @throws IllegalArgumentException if provider is null or doesn't exist
* @throws IllegalArgumentException if intent is null
- * @throws SecurityException if no suitable permission is present for the provider
- * @deprecated use the {@link LocationRequest} class instead
+ * @throws SecurityException if no suitable permission is present
+ *
+ * @deprecated Use {@link LocationRequest#setNumUpdates} instead
*/
@Deprecated
public void requestSingleUpdate(String provider, PendingIntent intent) {
@@ -949,21 +797,10 @@ public class LocationManager {
}
/**
- * Requests a single location update based on the specified criteria.
- *
- * <p> It may take a while to receive the most recent location. If
- * an immediate location is required, applications may use the
- * {@link #getLastKnownLocation(String)} method.
+ * Register for a single location update using a Criteria and pending intent.
*
- * <p> Location updates are sent with a key of
- * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value.
- *
- * <p> If the provider is disabled by the user, an update will not be
- * received, and an intent will be sent with an extra with key
- * {@link #KEY_PROVIDER_ENABLED} and a boolean value of false.
- * If the provider is re-enabled, an intent will be sent with an
- * extra with key {@link #KEY_PROVIDER_ENABLED} and a boolean value of
- * true and the location update will occur.
+ * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+ * for more detail on how to use this (deprecated) method.
*
* @param criteria contains parameters for the location manager to choose the
* appropriate provider and parameters to compute the location
@@ -971,8 +808,9 @@ public class LocationManager {
*
* @throws IllegalArgumentException if provider is null or doesn't exist
* @throws IllegalArgumentException if intent is null
- * @throws SecurityException if no suitable permission is present for the provider
- * @deprecated use the {@link LocationRequest} class instead
+ * @throws SecurityException if no suitable permission is present
+ *
+ * @deprecated Use {@link LocationRequest#setNumUpdates} instead
*/
@Deprecated
public void requestSingleUpdate(Criteria criteria, PendingIntent intent) {
@@ -984,12 +822,74 @@ public class LocationManager {
requestLocationUpdates(request, null, null, intent);
}
+ /**
+ * Register for fused location updates using a LocationRequest and callback.
+ *
+ * <p>The system will automatically select and enable the best providers
+ * to compute a location for your application. It may use only passive
+ * locations, or just a single location source, or it may fuse together
+ * multiple location sources in order to produce the best possible
+ * result, depending on the quality of service requested in the
+ * {@link LocationRequest}.
+ *
+ * <p>LocationRequest can be null, in which case the system will choose
+ * default, low power parameters for location updates. You will occasionally
+ * receive location updates as available, without a major power impact on the
+ * system. If your application just needs an occasional location update
+ * without any strict demands, then pass a null LocationRequest.
+ *
+ * <p>Only one LocationRequest can be registered for each unique callback
+ * or pending intent. So a subsequent request with the same callback or
+ * pending intent will over-write the previous LocationRequest.
+ *
+ * <p> If a pending intent is supplied then location updates
+ * are sent with a key of {@link #KEY_LOCATION_CHANGED} and a
+ * {@link android.location.Location} value. If a callback is supplied
+ * then location updates are made using the
+ * {@link LocationListener#onLocationChanged} callback, on the specified
+ * Looper thread. If a {@link LocationListener} is used
+ * but with a null Looper then the calling thread must already
+ * be a {@link android.os.Looper} thread (such as the main thread) and
+ * callbacks will occur on this thread.
+ *
+ * <p> Provider status updates and availability updates are deprecated
+ * because the system is performing provider fusion on the applications
+ * behalf. So {@link LocationListener#onProviderDisabled},
+ * {@link LocationListener#onProviderEnabled}, {@link LocationListener#onStatusChanged}
+ * will not be called, and intents with extra keys of
+ * {@link #KEY_PROVIDER_ENABLED} or {@link #KEY_STATUS_CHANGED} will not
+ * be received.
+ *
+ * @param request quality of service required, null for default low power
+ * @param listener a {#link LocationListener} whose
+ * {@link LocationListener#onLocationChanged} method will be called when
+ * the location update is available
+ * @param looper a Looper object whose message queue will be used to
+ * implement the callback mechanism, or null to make callbacks on the calling
+ * thread
+ *
+ * @throws IllegalArgumentException if listener is null
+ * @throws SecurityException if no suitable permission is present
+ */
public void requestLocationUpdates(LocationRequest request, LocationListener listener,
Looper looper) {
checkListener(listener);
requestLocationUpdates(request, listener, looper, null);
}
+
+ /**
+ * Register for fused location updates using a LocationRequest and a pending intent.
+ *
+ * <p> See {@link #requestLocationUpdates(LocationRequest, LocationListener, Looper)}
+ * for more detail.
+ *
+ * @param request quality of service required, null for default low power
+ * @param intent a {#link PendingIntent} to be sent for the location update
+ *
+ * @throws IllegalArgumentException if intent is null
+ * @throws SecurityException if no suitable permission is present
+ */
public void requestLocationUpdates(LocationRequest request, PendingIntent intent) {
checkPendingIntent(intent);
requestLocationUpdates(request, null, null, intent);
@@ -1023,11 +923,12 @@ public class LocationManager {
}
/**
- * Removes any current registration for location updates of the current activity
- * with the given LocationListener. Following this call, updates will no longer
+ * Removes all location updates for the specified LocationListener.
+ *
+ * <p>Following this call, updates will no longer
* occur for this listener.
*
- * @param listener {#link LocationListener} object that no longer needs location updates
+ * @param listener listener object that no longer needs location updates
* @throws IllegalArgumentException if listener is null
*/
public void removeUpdates(LocationListener listener) {
@@ -1048,11 +949,11 @@ public class LocationManager {
}
/**
- * Removes any current registration for location updates of the current activity
- * with the given PendingIntent. Following this call, updates will no longer
- * occur for this intent.
+ * Removes all location updates for the specified pending intent.
+ *
+ * <p>Following this call, updates will no longer for this pending intent.
*
- * @param intent {#link PendingIntent} object that no longer needs location updates
+ * @param intent pending intent object that no longer needs location updates
* @throws IllegalArgumentException if intent is null
*/
public void removeUpdates(PendingIntent intent) {
@@ -1067,8 +968,10 @@ public class LocationManager {
}
/**
- * Sets a proximity alert for the location given by the position
- * (latitude, longitude) and the given radius. When the device
+ * Set a proximity alert for the location given by the position
+ * (latitude, longitude) and the given radius.
+ *
+ * <p> When the device
* detects that it has entered or exited the area surrounding the
* location, the given PendingIntent will be used to create an Intent
* to be fired.
@@ -1088,10 +991,6 @@ public class LocationManager {
* alert and no longer monitor it. A value of -1 indicates that
* there should be no expiration time.
*
- * <p> In case the screen goes to sleep, checks for proximity alerts
- * happen only once every 4 minutes. This conserves battery life by
- * ensuring that the device isn't perpetually awake.
- *
* <p> Internally, this method uses both {@link #NETWORK_PROVIDER}
* and {@link #GPS_PROVIDER}.
*
@@ -1106,9 +1005,9 @@ public class LocationManager {
* @param intent a PendingIntent that will be used to generate an Intent to
* fire when entry to or exit from the alert region is detected
*
- * @throws SecurityException if no permission exists for the required
- * providers.
- * @deprecated use the {@link LocationRequest} class instead
+ * @throws SecurityException if no suitable permission is present
+ *
+ * @deprecated Use {@link LocationRequest} and {@link Geofence} instead
*/
@Deprecated
public void addProximityAlert(double latitude, double longitude, float radius, long expiration,
@@ -1125,7 +1024,40 @@ public class LocationManager {
}
}
- public void requestGeofence(LocationRequest request, Geofence fence, PendingIntent intent) {
+ /**
+ * Add a geofence with the specified LocationRequest quality of service.
+ *
+ * <p> When the device
+ * detects that it has entered or exited the area surrounding the
+ * location, the given PendingIntent will be used to create an Intent
+ * to be fired.
+ *
+ * <p> The fired Intent will have a boolean extra added with key
+ * {@link #KEY_PROXIMITY_ENTERING}. If the value is true, the device is
+ * entering the proximity region; if false, it is exiting.
+ *
+ * <p> The geofence engine fuses results from all location providers to
+ * provide the best balance between accuracy and power. Applications
+ * can choose the quality of service required using the
+ * {@link LocationRequest} object. If it is null then a default,
+ * low power geo-fencing implementation is used. It is possible to cross
+ * a geo-fence without notification, but the system will do its best
+ * to detect, using {@link LocationRequest} as a hint to trade-off
+ * accuracy and power.
+ *
+ * <p> The power required by the geofence engine can depend on many factors,
+ * such as quality and interval requested in {@link LocationRequest},
+ * distance to nearest geofence and current device velocity.
+ *
+ * @param request quality of service required, null for default low power
+ * @param fence a geographical description of the geofence area
+ * @param intent pending intent to receive geofence updates
+ *
+ * @throws IllegalArgumentException if fence is null
+ * @throws IllegalArgumentException if intent is null
+ * @throws SecurityException if no suitable permission is present
+ */
+ public void addGeofence(LocationRequest request, Geofence fence, PendingIntent intent) {
checkPendingIntent(intent);
checkGeofence(fence);
@@ -1141,7 +1073,11 @@ public class LocationManager {
*
* @param intent the PendingIntent that no longer needs to be notified of
* proximity alerts
- * @deprecated use the {@link LocationRequest} class instead
+ *
+ * @throws IllegalArgumentException if intent is null
+ * @throws SecurityException if no suitable permission is present
+ *
+ * @deprecated Use {@link LocationRequest} and {@link Geofence} instead
*/
@Deprecated
public void removeProximityAlert(PendingIntent intent) {
@@ -1155,6 +1091,19 @@ public class LocationManager {
}
}
+ /**
+ * Remove a single geofence.
+ *
+ * <p>This removes only the specified geofence associated with the
+ * specified pending intent. All other geofences remain unchanged.
+ *
+ * @param fence a geofence previously passed to {@link #addGeofence}
+ * @param intent a pending intent previously passed to {@link #addGeofence}
+ *
+ * @throws IllegalArgumentException if fence is null
+ * @throws IllegalArgumentException if intent is null
+ * @throws SecurityException if no suitable permission is present
+ */
public void removeGeofence(Geofence fence, PendingIntent intent) {
checkPendingIntent(intent);
checkGeofence(fence);
@@ -1167,6 +1116,14 @@ public class LocationManager {
}
}
+ /**
+ * Remove all geofences registered to the specified pending intent.
+ *
+ * @param intent a pending intent previously passed to {@link #addGeofence}
+ *
+ * @throws IllegalArgumentException if intent is null
+ * @throws SecurityException if no suitable permission is present
+ */
public void removeAllGeofences(PendingIntent intent) {
checkPendingIntent(intent);
String packageName = mContext.getPackageName();
@@ -1179,16 +1136,18 @@ public class LocationManager {
}
/**
- * Returns the current enabled/disabled status of the given provider. If the
- * user has enabled this provider in the Settings menu, true is returned
- * otherwise false is returned
+ * Returns the current enabled/disabled status of the given provider.
+ *
+ * <p>If the user has enabled this provider in the Settings menu, true
+ * is returned otherwise false is returned
*
* @param provider the name of the provider
* @return true if the provider is enabled
*
- * @throws SecurityException if no suitable permission is present for the provider.
* @throws IllegalArgumentException if provider is null
- * @deprecated use the {@link LocationRequest} class instead
+ * @throws SecurityException if no suitable permission is present
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public boolean isProviderEnabled(String provider) {
@@ -1202,19 +1161,34 @@ public class LocationManager {
}
}
- public Location getLastLocation(LocationRequest request) {
+ /**
+ * Get the last known location.
+ *
+ * <p>This location could be very old so use
+ * {@link Location#getElapsedRealtimeNano} to calculate its age. It can
+ * also return null if no previous location is available.
+ *
+ * <p>Always returns immediately.
+ *
+ * @return The last known location, or null if not available
+ * @throws SecurityException if no suitable permission is present
+ */
+ public Location getLastLocation() {
+ String packageName = mContext.getPackageName();
+
try {
- return mService.getLastLocation(request);
+ return mService.getLastLocation(null, packageName);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException", e);
return null;
}
}
-
/**
* Returns a Location indicating the data from the last known
- * location fix obtained from the given provider. This can be done
+ * location fix obtained from the given provider.
+ *
+ * <p> This can be done
* without starting the provider. Note that this location could
* be out-of-date, for example if the device was turned off and
* moved to another location.
@@ -1224,46 +1198,41 @@ public class LocationManager {
* @param provider the name of the provider
* @return the last known location for the provider, or null
*
- * @throws SecurityException if no suitable permission is present for the provider.
+ * @throws SecurityException if no suitable permission is present
* @throws IllegalArgumentException if provider is null or doesn't exist
- * @deprecated use the {@link LocationRequest} class instead
+ *
+ * @deprecated Use {@link #getLastLocation} instead
*/
@Deprecated
public Location getLastKnownLocation(String provider) {
checkProvider(provider);
-
+ String packageName = mContext.getPackageName();
LocationRequest request = LocationRequest.createFromDeprecatedProvider(
provider, 0, 0, true);
try {
- return mService.getLastLocation(request);
+ return mService.getLastLocation(request, packageName);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException", e);
return null;
}
}
- // Mock provider support
+ // --- Mock provider support ---
+ // TODO: It would be fantastic to deprecate mock providers entirely, and replace
+ // with something closer to LocationProviderBase.java
/**
* Creates a mock location provider and adds it to the set of active providers.
*
* @param name the provider name
- * @param requiresNetwork
- * @param requiresSatellite
- * @param requiresCell
- * @param hasMonetaryCost
- * @param supportsAltitude
- * @param supportsSpeed
- * @param supportsBearing
- * @param powerRequirement
- * @param accuracy
*
* @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present
* or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
* Settings.Secure.ALLOW_MOCK_LOCATION} system setting is not enabled
* @throws IllegalArgumentException if a provider with the given name already exists
- * @deprecated use the {@link LocationRequest} class instead
+ *
+ * @deprecated requesting location providers by name is deprecated
*/
@Deprecated
public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
@@ -1292,7 +1261,8 @@ public class LocationManager {
* or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
* Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
* @throws IllegalArgumentException if no provider with the given name exists
- * @deprecated use the {@link LocationRequest} class instead
+ *
+ * @deprecated requesting location providers by name is deprecated
*/
@Deprecated
public void removeTestProvider(String provider) {
@@ -1318,7 +1288,8 @@ public class LocationManager {
* Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
* @throws IllegalArgumentException if no provider with the given name exists
* @throws IllegalArgumentException if the location is incomplete
- * @deprecated use the {@link LocationRequest} class instead
+ *
+ * @deprecated requesting location providers by name is deprecated
*/
@Deprecated
public void setTestProviderLocation(String provider, Location loc) {
@@ -1351,7 +1322,8 @@ public class LocationManager {
* or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
* Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
* @throws IllegalArgumentException if no provider with the given name exists
- * @deprecated use the {@link LocationRequest} class instead
+ *
+ * @deprecated requesting location providers by name is deprecated
*/
@Deprecated
public void clearTestProviderLocation(String provider) {
@@ -1373,7 +1345,8 @@ public class LocationManager {
* or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
* Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
* @throws IllegalArgumentException if no provider with the given name exists
- * @deprecated use the {@link LocationRequest} class instead
+ *
+ * @deprecated requesting location providers by name is deprecated
*/
@Deprecated
public void setTestProviderEnabled(String provider, boolean enabled) {
@@ -1393,7 +1366,8 @@ public class LocationManager {
* or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
* Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
* @throws IllegalArgumentException if no provider with the given name exists
- * @deprecated use the {@link LocationRequest} class instead
+ *
+ * @deprecated requesting location providers by name is deprecated
*/
@Deprecated
public void clearTestProviderEnabled(String provider) {
@@ -1417,7 +1391,8 @@ public class LocationManager {
* or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
* Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
* @throws IllegalArgumentException if no provider with the given name exists
- * @deprecated use the {@link LocationRequest} class instead
+ *
+ * @deprecated requesting location providers by name is deprecated
*/
@Deprecated
public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
@@ -1437,7 +1412,8 @@ public class LocationManager {
* or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
* Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
* @throws IllegalArgumentException if no provider with the given name exists
- * @deprecated use the {@link LocationRequest} class instead
+ *
+ * @deprecated requesting location providers by name is deprecated
*/
@Deprecated
public void clearTestProviderStatus(String provider) {
@@ -1448,7 +1424,7 @@ public class LocationManager {
}
}
- // GPS-specific support
+ // --- GPS-specific support ---
// This class is used to send GPS status events to the client's main thread.
private class GpsStatusListenerTransport extends IGpsStatusListener.Stub {
@@ -1682,7 +1658,8 @@ public class LocationManager {
* The provider may optionally fill the extras Bundle with results from the command.
*
* @return true if the command succeeds.
- * @deprecated use the {@link LocationRequest} class instead
+ *
+ * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
@Deprecated
public boolean sendExtraCommand(String provider, String command, Bundle extras) {
@@ -1698,7 +1675,7 @@ public class LocationManager {
* Used by NetInitiatedActivity to report user response
* for network initiated GPS fix requests.
*
- * {@hide}
+ * @hide
*/
public boolean sendNiResponse(int notifId, int userResponse) {
try {
@@ -1720,6 +1697,7 @@ public class LocationManager {
throw new IllegalArgumentException("invalid criteria: " + criteria);
}
}
+
private static void checkListener(LocationListener listener) {
if (listener == null) {
throw new IllegalArgumentException("invalid listener: " + listener);
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 3110196..b1863b8 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -21,24 +21,140 @@ import android.os.Parcelable;
import android.os.SystemClock;
import android.util.TimeUtils;
+
+/**
+ * A data object that contains quality of service parameters for requests
+ * to the {@link LocationManager}.
+ *
+ * <p>LocationRequest objects are used to request a quality of service
+ * for location updates from the Location Manager.
+ *
+ * <p>For example, if your application wants high accuracy location
+ * it should create a location request with {@link #setQuality} set to
+ * {@link #ACCURACY_FINE} or {@link #POWER_HIGH}, and it should set
+ * {@link #setInterval} to less than one second. This would be
+ * appropriate for mapping applications that are showing your location
+ * in real-time.
+ *
+ * <p>At the other extreme, if you want negligible power
+ * impact, but to still receive location updates when available, then use
+ * {@link #setQuality} with {@link #POWER_NONE}. With this request your
+ * application will not trigger (and therefore will not receive any
+ * power blame) any location updates, but will receive locations
+ * triggered by other applications. This would be appropriate for
+ * applications that have no firm requirement for location, but can
+ * take advantage when available.
+ *
+ * <p>In between these two extremes is a very common use-case, where
+ * applications definitely want to receive
+ * updates at a specified interval, and can receive them faster when
+ * available, but still want a low power impact. These applications
+ * should consider {@link #POWER_LOW} combined with a faster
+ * {@link #setFastestInterval} (such as 1 minute) and a slower
+ * {@link #setInterval} (such as 60 minutes). They will only be assigned
+ * power blame for the interval set by {@link #setInterval}, but can
+ * still receive locations triggered by other applications at a rate up
+ * to {@link #setFastestInterval}. This style of request is appropriate for
+ * many location aware applications, including background usage. Do be
+ * careful to also throttle {@link #setFastestInterval} if you perform
+ * heavy-weight work after receiving an update - such as using the network.
+ *
+ * <p>Activities should strongly consider removing all location
+ * request when entering the background
+ * (for example at {@link android.app.Activity#onPause}), or
+ * at least swap the request to a larger interval and lower quality.
+ * Future version of the location manager may automatically perform background
+ * throttling on behalf of applications.
+ *
+ * <p>Applications cannot specify the exact location sources that are
+ * used by Android's <em>Fusion Engine</em>. In fact, the system
+ * may have multiple location sources (providers) running and may
+ * fuse the results from several sources into a single Location object.
+ *
+ * <p>Location requests from applications with
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} and not
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} will
+ * be automatically throttled to a slower interval, and the location
+ * object will be obfuscated to only show a coarse level of accuracy.
+ *
+ * <p>All location requests are considered hints, and you may receive
+ * locations that are more accurate, less accurate, and slower
+ * than requested.
+ */
public final class LocationRequest implements Parcelable {
- // QOS control
- public static final int ACCURACY_FINE = 100; // ~1 meter
- public static final int ACCURACY_BLOCK = 102; // ~100 meters
- public static final int ACCURACY_CITY = 104; // ~10 km
+ /**
+ * Used with {@link #setQuality} to request the most accurate locations available.
+ *
+ * <p>This may be up to 1 meter accuracy, although this is implementation dependent.
+ */
+ public static final int ACCURACY_FINE = 100;
+
+ /**
+ * Used with {@link #setQuality} to request "block" level accuracy.
+ *
+ * <p>Block level accuracy is considered to be about 100 meter accuracy,
+ * although this is implementation dependent. Using a coarse accuracy
+ * such as this often consumes less power.
+ */
+ public static final int ACCURACY_BLOCK = 102;
+
+ /**
+ * Used with {@link #setQuality} to request "city" level accuracy.
+ *
+ * <p>City level accuracy is considered to be about 10km accuracy,
+ * although this is implementation dependent. Using a coarse accuracy
+ * such as this often consumes less power.
+ */
+ public static final int ACCURACY_CITY = 104;
+
+ /**
+ * Used with {@link #setQuality} to require no direct power impact (passive locations).
+ *
+ * <p>This location request will not trigger any active location requests,
+ * but will receive locations triggered by other applications. Your application
+ * will not receive any direct power blame for location work.
+ */
public static final int POWER_NONE = 200;
+
+ /**
+ * Used with {@link #setQuality} to request low power impact.
+ *
+ * <p>This location request will avoid high power location work where
+ * possible.
+ */
public static final int POWER_LOW = 201;
+
+ /**
+ * Used with {@link #setQuality} to allow high power consumption for location.
+ *
+ * <p>This location request will allow high power location work.
+ */
public static final int POWER_HIGH = 203;
+ /**
+ * By default, mFastestInterval = FASTEST_INTERVAL_MULTIPLE * mInterval
+ */
+ private static final double FASTEST_INTERVAL_FACTOR = 6.0; // 6x
+
private int mQuality = POWER_LOW;
- private long mFastestInterval = 6 * 1000; // 6 seconds
- private long mInterval = 60 * 1000; // 1 minute
+ private long mInterval = 60 * 60 * 1000; // 60 minutes
+ private long mFastestInterval = (long)(mInterval / FASTEST_INTERVAL_FACTOR); // 10 minutes
+ private boolean mExplicitFastestInterval = false;
private long mExpireAt = Long.MAX_VALUE; // no expiry
private int mNumUpdates = Integer.MAX_VALUE; // no expiry
private float mSmallestDisplacement = 0.0f; // meters
private String mProvider = null; // for deprecated API's that explicitly request a provider
+ /**
+ * Create a location request with default parameters.
+ *
+ * <p>Default parameters are for a low power, slowly updated location.
+ * It can then be adjusted as required by the applications before passing
+ * to the {@link LocationManager}
+ *
+ * @return a new location request
+ */
public static LocationRequest create() {
LocationRequest request = new LocationRequest();
return request;
@@ -105,52 +221,217 @@ public final class LocationRequest implements Parcelable {
/** @hide */
public LocationRequest() { }
+ /**
+ * Set the quality of the request.
+ *
+ * <p>Use with a accuracy constant such as {@link #ACCURACY_FINE}, or a power
+ * constant such as {@link #POWER_LOW}. You cannot request both and accuracy and
+ * power, only one or the other can be specified. The system will then
+ * maximize accuracy or minimize power as appropriate.
+ *
+ * <p>The quality of the request is a strong hint to the system for which
+ * location sources to use. For example, {@link #ACCURACY_FINE} is more likely
+ * to use GPS, and {@link #POWER_LOW} is more likely to use WIFI & Cell tower
+ * positioning, but it also depends on many other factors (such as which sources
+ * are available) and is implementation dependent.
+ *
+ * <p>{@link #setQuality} and {@link #setInterval} are the most important parameters
+ * on a location request.
+ *
+ * @param quality an accuracy or power constant
+ * @throws InvalidArgumentException if the quality constant is not valid
+ * @return the same object, so that setters can be chained
+ */
public LocationRequest setQuality(int quality) {
checkQuality(quality);
mQuality = quality;
return this;
}
+ /**
+ * Get the quality of the request.
+ *
+ * @return an accuracy or power constant
+ */
public int getQuality() {
return mQuality;
}
+ /**
+ * Set the desired interval for active location updates, in milliseconds.
+ *
+ * <p>The location manager will actively try to obtain location updates
+ * for your application at this interval, so it has a
+ * direct influence on the amount of power used by your application.
+ * Choose your interval wisely.
+ *
+ * <p>This interval is inexact. You may not receive updates at all (if
+ * no location sources are available), or you may receive them
+ * slower than requested. You may also receive them faster than
+ * requested (if other applications are requesting location at a
+ * faster interval). The fastest rate that that you will receive
+ * updates can be controlled with {@link #setFastestInterval}.
+ *
+ * <p>Applications with only the coarse location permission may have their
+ * interval silently throttled.
+ *
+ * <p>An interval of 0 is allowed, but not recommended, since
+ * location updates may be extremely fast on future implementations.
+ *
+ * <p>{@link #setQuality} and {@link #setInterval} are the most important parameters
+ * on a location request.
+ *
+ * @param millis desired interval in millisecond, inexact
+ * @throws InvalidArgumentException if the interval is less than zero
+ * @return the same object, so that setters can be chained
+ */
public LocationRequest setInterval(long millis) {
checkInterval(millis);
mInterval = millis;
+ if (!mExplicitFastestInterval) {
+ mFastestInterval = (long)(mInterval / FASTEST_INTERVAL_FACTOR);
+ }
return this;
}
+ /**
+ * Get the desired interval of this request, in milliseconds.
+ *
+ * @return desired interval in milliseconds, inexact
+ */
public long getInterval() {
return mInterval;
}
+ /**
+ * Explicitly set the fastest interval for location updates, in
+ * milliseconds.
+ *
+ * <p>This controls the fastest rate at which your application will
+ * receive location updates, which might be faster than
+ * {@link #setInterval} in some situations (for example, if other
+ * applications are triggering location updates).
+ *
+ * <p>This allows your application to passively acquire locations
+ * at a rate faster than it actively acquires locations, saving power.
+ *
+ * <p>Unlike {@link #setInterval}, this parameter is exact. Your
+ * application will never receive updates faster than this value.
+ *
+ * <p>If you don't call this method, a fastest interval
+ * will be selected for you. It will be a value faster than your
+ * active interval ({@link #setInterval}).
+ *
+ * <p>An interval of 0 is allowed, but not recommended, since
+ * location updates may be extremely fast on future implementations.
+ *
+ * <p>If {@link #setFastestInterval} is set slower than {@link #setInterval},
+ * then your effective fastest interval is {@link #setInterval}.
+ *
+ * @param millis fastest interval for updates in milliseconds, exact
+ * @throws InvalidArgumentException if the interval is less than zero
+ * @return the same object, so that setters can be chained
+ */
public LocationRequest setFastestInterval(long millis) {
checkInterval(millis);
+ mExplicitFastestInterval = true;
mFastestInterval = millis;
return this;
}
+ /**
+ * Get the fastest interval of this request, in milliseconds.
+ *
+ * <p>The system will never provide location updates faster
+ * than the minimum of {@link #getFastestInterval} and
+ * {@link #getInterval}.
+ *
+ * @return fastest interval in milliseconds, exact
+ */
public long getFastestInterval() {
return mFastestInterval;
}
+ /**
+ * Set the duration of this request, in milliseconds.
+ *
+ * <p>The duration begins immediately (and not when the request
+ * is passed to the location manager), so call this method again
+ * if the request is re-used at a later time.
+ *
+ * <p>The location manager will automatically stop updates after
+ * the request expires.
+ *
+ * <p>The duration includes suspend time. Values less than 0
+ * are allowed, but indicate that the request has already expired.
+ *
+ * @param millis duration of request in milliseconds
+ * @return the same object, so that setters can be chained
+ */
public LocationRequest setExpireIn(long millis) {
mExpireAt = millis + SystemClock.elapsedRealtime();
if (mExpireAt < 0) mExpireAt = 0;
return this;
}
+ /**
+ * Set the request expiration time, in millisecond since boot.
+ *
+ * <p>This expiration time uses the same time base as {@link SystemClock#elapsedRealtime}.
+ *
+ * <p>The location manager will automatically stop updates after
+ * the request expires.
+ *
+ * <p>The duration includes suspend time. Values before {@link SystemClock#elapsedRealtime}
+ * are allowed, but indicate that the request has already expired.
+ *
+ * @param millis expiration time of request, in milliseconds since boot including suspend
+ * @return the same object, so that setters can be chained
+ */
public LocationRequest setExpireAt(long millis) {
mExpireAt = millis;
if (mExpireAt < 0) mExpireAt = 0;
return this;
}
+ /**
+ * Get the request expiration time, in milliseconds since boot.
+ *
+ * <p>This value can be compared to {@link SystemClock#elapsedRealtime} to determine
+ * the time until expiration.
+ *
+ * @return expiration time of request, in milliseconds since boot including suspend
+ */
public long getExpireAt() {
return mExpireAt;
}
+ /**
+ * Set the number of location updates.
+ *
+ * <p>By default locations are continuously updated until the request is explicitly
+ * removed, however you can optionally request a set number of updates.
+ * For example, if your application only needs a single fresh location,
+ * then call this method with a value of 1 before passing the request
+ * to the location manager.
+ *
+ * @param numUpdates the number of location updates requested
+ * @throws InvalidArgumentException if numUpdates is 0 or less
+ * @return the same object, so that setters can be chained
+ */
+ public LocationRequest setNumUpdates(int numUpdates) {
+ if (numUpdates <= 0) throw new IllegalArgumentException("invalid numUpdates: " + numUpdates);
+ mNumUpdates = numUpdates;
+ return this;
+ }
+
+ /**
+ * Get the number of updates requested.
+ *
+ * <p>By default this is {@link Integer#MAX_VALUE}, which indicates that
+ * locations are updated until the request is explicitly removed.
+ * @return number of updates
+ */
public int getNumUpdates() {
return mNumUpdates;
}
@@ -165,11 +446,6 @@ public final class LocationRequest implements Parcelable {
}
}
- public LocationRequest setNumUpdates(int numUpdates) {
- if (numUpdates < 0) throw new IllegalArgumentException("invalid numUpdates: " + numUpdates);
- mNumUpdates = numUpdates;
- return this;
- }
/** @hide */
public LocationRequest setProvider(String provider) {
@@ -195,20 +471,6 @@ public final class LocationRequest implements Parcelable {
return mSmallestDisplacement;
}
- /** @hide */
- public LocationRequest applyCoarsePermissionRestrictions() {
- switch (mQuality) {
- case ACCURACY_FINE:
- mQuality = ACCURACY_BLOCK;
- break;
- }
- // cap fastest interval to 6 seconds
- if (mFastestInterval < 6 * 1000) mFastestInterval = 6 * 1000;
- // cap requested interval to 1 minute
- if (mInterval < 60 * 1000) mInterval = 60 * 1000;
- return this;
- }
-
private static void checkInterval(long millis) {
if (millis < 0) {
throw new IllegalArgumentException("invalid interval: " + millis);
@@ -261,10 +523,12 @@ public final class LocationRequest implements Parcelable {
return new LocationRequest[size];
}
};
+
@Override
public int describeContents() {
return 0;
}
+
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mQuality);
diff --git a/location/java/com/android/internal/location/ProviderProperties.java b/location/java/com/android/internal/location/ProviderProperties.java
index 08aed80..def96f0 100644
--- a/location/java/com/android/internal/location/ProviderProperties.java
+++ b/location/java/com/android/internal/location/ProviderProperties.java
@@ -145,7 +145,7 @@ public final class ProviderProperties implements Parcelable {
parcel.writeInt(mHasMonetaryCost ? 1 : 0);
parcel.writeInt(mSupportsAltitude ? 1 : 0);
parcel.writeInt(mSupportsSpeed ? 1 : 0);
- parcel.writeInt(mSupportsSpeed ? 1 : 0);
+ parcel.writeInt(mSupportsBearing ? 1 : 0);
parcel.writeInt(mPowerRequirement);
parcel.writeInt(mAccuracy);
}
diff --git a/location/lib/README.txt b/location/lib/README.txt
new file mode 100644
index 0000000..400a7dd
--- /dev/null
+++ b/location/lib/README.txt
@@ -0,0 +1,30 @@
+This library (com.android.location.provider.jar) is a shared java library
+containing classes required by unbundled location providers.
+
+--- Rules of this library ---
+o This library is effectively a PUBLIC API for unbundled location providers
+ that may be distributed outside the system image. So it MUST BE API STABLE.
+ You can add but not remove. The rules are the same as for the
+ public platform SDK API.
+o This library can see and instantiate internal platform classes (such as
+ ProviderRequest.java), but it must not expose them in any public method
+ (or by extending them via inheritance). This would break clients of the
+ library because they cannot see the internal platform classes.
+
+This library is distributed in the system image, and loaded as
+a shared library. So you can change the implementation, but not
+the interface. In this way it is like framework.jar.
+
+--- Why does this library exists? ---
+
+Unbundled location providers (such as the NetworkLocationProvider)
+can not use internal platform classes.
+
+So ideally all of these classes would be part of the public platform SDK API,
+but that doesn't seem like a great idea when only applications with a special
+signature can implement this API.
+
+The compromise is this library.
+
+It wraps internal platform classes (like ProviderRequest) with a stable
+API that does not leak the internal classes.
diff --git a/location/lib/java/com/android/location/provider/GeocodeProvider.java b/location/lib/java/com/android/location/provider/GeocodeProvider.java
index 666bb02..d7a34af 100644
--- a/location/lib/java/com/android/location/provider/GeocodeProvider.java
+++ b/location/lib/java/com/android/location/provider/GeocodeProvider.java
@@ -25,12 +25,14 @@ import android.location.IGeocodeProvider;
import java.util.List;
/**
- * An abstract superclass for geocode providers that are implemented
- * outside of the core android platform.
- * Geocode providers can be implemented as services and return the result of
+ * Base class for geocode providers implemented as unbundled services.
+ *
+ * <p>Geocode providers can be implemented as services and return the result of
* {@link GeocodeProvider#getBinder()} in its getBinder() method.
*
- * @hide
+ * <p>IMPORTANT: This class is effectively a public API for unbundled
+ * applications, and must remain API stable. See README.txt in the root
+ * of this package for more information.
*/
public abstract class GeocodeProvider {
diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java
index 53b0cae..b0e5d2c 100644
--- a/location/lib/java/com/android/location/provider/LocationProviderBase.java
+++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java
@@ -34,10 +34,22 @@ import com.android.internal.location.ILocationProvider;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
-
/**
- * Base class for location providers implemented as services.
- * @hide
+ * Base class for location providers implemented as unbundled services.
+ *
+ * <p>The network location provider must export a service with action
+ * "com.android.location.service.v2.NetworkLocationProvider"
+ * and a valid minor version in a meta-data field on the service, and
+ * then return the result of {@link #getBinder()} on service binding.
+ *
+ * <p>The fused location provider must export a service with action
+ * "com.android.location.service.FusedLocationProvider"
+ * and a valid minor version in a meta-data field on the service, and
+ * then return the result of {@link #getBinder()} on service binding.
+ *
+ * <p>IMPORTANT: This class is effectively a public API for unbundled
+ * applications, and must remain API stable. See README.txt in the root
+ * of this package for more information.
*/
public abstract class LocationProviderBase {
private final String TAG;
diff --git a/location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java b/location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java
index c8bdda4..9ee4df2 100644
--- a/location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java
+++ b/location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java
@@ -19,9 +19,11 @@ package com.android.location.provider;
import com.android.internal.location.ProviderProperties;
/**
- * This class is a public API for unbundled providers,
- * that hides the (hidden framework) ProviderProperties.
- * <p>Do _not_ remove public methods on this class.
+ * This class is an interface to Provider Properties for unbundled applications.
+ *
+ * <p>IMPORTANT: This class is effectively a public API for unbundled
+ * applications, and must remain API stable. See README.txt in the root
+ * of this package for more information.
*/
public final class ProviderPropertiesUnbundled {
private final ProviderProperties mProperties;
diff --git a/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
index 3ff19ca..3605381 100644
--- a/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
+++ b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
@@ -23,9 +23,11 @@ import android.location.LocationRequest;
import com.android.internal.location.ProviderRequest;
/**
- * This class is a public API for unbundled providers,
- * that hides the (hidden framework) ProviderRequest.
- * <p>Do _not_ remove public methods on this class.
+ * This class is an interface to Provider Requests for unbundled applications.
+ *
+ * <p>IMPORTANT: This class is effectively a public API for unbundled
+ * applications, and must remain API stable. See README.txt in the root
+ * of this package for more information.
*/
public final class ProviderRequestUnbundled {
private final ProviderRequest mRequest;
diff --git a/media/jni/mediaeditor/VideoEditorClasses.cpp b/media/jni/mediaeditor/VideoEditorClasses.cpp
index 4e0e0f2..4982a47 100755
--- a/media/jni/mediaeditor/VideoEditorClasses.cpp
+++ b/media/jni/mediaeditor/VideoEditorClasses.cpp
@@ -1853,6 +1853,9 @@ videoEditClasses_getEditSettings(
// Get the clip settings.
videoEditClasses_getClipSettings(pResult, pEnv, clipSettings,
&pSettings->pClipList[i]);
+
+ // Free the local references to avoid memory leaks
+ pEnv->DeleteLocalRef(clipSettings);
}
}
}
@@ -1877,6 +1880,9 @@ videoEditClasses_getEditSettings(
// Get the transition settings.
videoEditClasses_getTransitionSettings(pResult, pEnv,
transitionSettings, &pSettings->pTransitionList[i]);
+
+ // Free the local references to avoid memory leaks
+ pEnv->DeleteLocalRef(transitionSettings);
}
}
}
@@ -1900,6 +1906,9 @@ videoEditClasses_getEditSettings(
// Get the effect settings.
videoEditClasses_getEffectSettings(pResult, pEnv, effectSettings,
&pSettings->Effects[i]);
+
+ // Free the local references to avoid memory leaks
+ pEnv->DeleteLocalRef(effectSettings);
}
}
}
diff --git a/media/jni/mediaeditor/VideoEditorJava.cpp b/media/jni/mediaeditor/VideoEditorJava.cpp
index ec8050f..bcf9099 100755
--- a/media/jni/mediaeditor/VideoEditorJava.cpp
+++ b/media/jni/mediaeditor/VideoEditorJava.cpp
@@ -387,6 +387,9 @@ videoEditJava_getString(
(*pLength) = length;
}
}
+
+ // Delete local references to avoid memory leaks
+ pEnv->DeleteLocalRef(string);
}
// Return the string.
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
index 41ec120..41c28c0 100755
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorMain.cpp
@@ -380,6 +380,9 @@ getClipSetting(
pEnv->GetIntField(object,fid);
M4OSA_TRACE1_1("videoRotation = %d",
pSettings->ClipProperties.videoRotationDegrees);
+
+ // Free the local references to avoid memory leaks
+ pEnv->DeleteLocalRef(clazz);
}
static void jniPreviewProgressCallback (void* cookie, M4OSA_UInt32 msgType,
@@ -1849,7 +1852,9 @@ videoEditor_populateSettings(
"not initialized");
if (needToBeLoaded) {
getClipSetting(pEnv,properties, pContext->pEditSettings->pClipList[i]);
+ pEnv->DeleteLocalRef(properties);
} else {
+ pEnv->DeleteLocalRef(properties);
goto videoEditor_populateSettings_cleanup;
}
}
diff --git a/media/libdrm/mobile1/src/objmng/drm_api.c b/media/libdrm/mobile1/src/objmng/drm_api.c
index 249cdbe..232d9f4 100644
--- a/media/libdrm/mobile1/src/objmng/drm_api.c
+++ b/media/libdrm/mobile1/src/objmng/drm_api.c
@@ -1478,13 +1478,13 @@ static int32_t drm_readBinaryContentFromInputStream(T_DRM_Session_Node* s, int32
if (NULL != s->readBuf && s->readBufLen > 0) { /* read from backup buffer */
if (leftLen <= s->readBufLen) {
- memcpy(mediaBuf, s->readBuf + s->readBufOff, leftLen);
+ memcpy(mediaBuf + readBytes, s->readBuf + s->readBufOff, leftLen);
s->readBufOff += leftLen;
s->readBufLen -= leftLen;
readBytes += leftLen;
leftLen = 0;
} else {
- memcpy(mediaBuf, s->readBuf + s->readBufOff, s->readBufLen);
+ memcpy(mediaBuf + readBytes, s->readBuf + s->readBufOff, s->readBufLen);
s->readBufOff += s->readBufLen;
leftLen -= s->readBufLen;
readBytes += s->readBufLen;
diff --git a/media/mca/filterpacks/java/android/filterpacks/videosrc/MediaSource.java b/media/mca/filterpacks/java/android/filterpacks/videosrc/MediaSource.java
index 9c40cec..0be6c62 100644
--- a/media/mca/filterpacks/java/android/filterpacks/videosrc/MediaSource.java
+++ b/media/mca/filterpacks/java/android/filterpacks/videosrc/MediaSource.java
@@ -35,6 +35,7 @@ import android.filterfw.core.ShaderProgram;
import android.filterfw.format.ImageFormat;
import android.graphics.SurfaceTexture;
import android.media.MediaPlayer;
+import android.net.Uri;
import android.os.ConditionVariable;
import android.opengl.Matrix;
import android.view.Surface;
@@ -64,6 +65,12 @@ public class MediaSource extends Filter {
@GenerateFieldPort(name = "sourceAsset", hasDefault = true)
private AssetFileDescriptor mSourceAsset = null;
+ /** The context for the MediaPlayer to resolve the sourceUrl.
+ * Make sure this is set before the sourceUrl to avoid unexpected result.
+ * If the sourceUrl is not a content URI, it is OK to keep this as null. */
+ @GenerateFieldPort(name = "context", hasDefault = true)
+ private Context mContext = null;
+
/** Whether the media source is a URL or an asset file descriptor. Defaults
* to false.
*/
@@ -459,7 +466,11 @@ public class MediaSource extends Filter {
try {
if (useUrl) {
if (mLogVerbose) Log.v(TAG, "Setting MediaPlayer source to URI " + mSourceUrl);
- mMediaPlayer.setDataSource(mSourceUrl);
+ if (mContext == null) {
+ mMediaPlayer.setDataSource(mSourceUrl);
+ } else {
+ mMediaPlayer.setDataSource(mContext, Uri.parse(mSourceUrl.toString()));
+ }
} else {
if (mLogVerbose) Log.v(TAG, "Setting MediaPlayer source to asset " + mSourceAsset);
mMediaPlayer.setDataSource(mSourceAsset.getFileDescriptor(), mSourceAsset.getStartOffset(), mSourceAsset.getLength());
diff --git a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java
index 436e579..f11b499 100644
--- a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java
+++ b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java
@@ -119,7 +119,7 @@ public class FakeApp extends Application {
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
- if (ActivityManager.isHighEndGfx(display)) {
+ if (ActivityManager.isHighEndGfx()) {
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
diff --git a/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java b/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java
index 38a6091..1c22c7a 100644
--- a/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java
+++ b/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java
@@ -22,7 +22,6 @@ import java.util.HashMap;
import com.android.location.provider.ProviderRequestUnbundled;
-
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 676bfd0..2eee31d 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -15,7 +15,7 @@
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<uses-permission android:name="android.permission.REMOTE_AUDIO_PLAYBACK" />
- <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
+ <uses-permission android:name="android.permission.MANAGE_USERS" />
<!-- Networking and telephony -->
<uses-permission android:name="android.permission.BLUETOOTH" />
@@ -132,6 +132,14 @@
android:excludeFromRecents="true">
</activity>
+ <!-- started from UsbDebuggingManager -->
+ <activity android:name=".usb.UsbDebuggingActivity"
+ android:permission="android.permission.MANAGE_USB"
+ android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+ android:finishOnCloseSystemDialogs="true"
+ android:excludeFromRecents="true">
+ </activity>
+
<!-- started from NetworkPolicyManagerService -->
<activity
android:name=".net.NetworkOverLimitActivity"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 2db520a..b63ed4a 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Sien"</string>
<string name="always_use_device" msgid="1450287437017315906">"Gebruik by verstek vir hierdie USB-toestel"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Gebruik by verstek vir hierdie USB-toebehoorsel"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Zoem om skerm te vul"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Strek om skerm te vul"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Versoenbaarheidszoem"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 93547c1..0d41cc7 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"ዕይታ"</string>
<string name="always_use_device" msgid="1450287437017315906">"ለዚህ USB መሣሪያ በነባሪነት ተጠቀም"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"ለዚህ USB ተቀጥላ በነባሪነት ተጠቀም"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"የUSB ማረሚያ ይፈቀድ?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"የUSB ማረም ከዚህ ኮምፒውተር ይፈቀድ?"\n"የእርስዎ RSA ቁልፍ ጣት አሻራ "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g> ነው"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"ለዚህ ኮምፒውተር ሁልጊዜ ፍቀድ"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"ማያ እንዲሞላ አጉላ"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"ማያ ለመሙለት ሳብ"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"የተኳኋኝነት አጉላ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 9b975fe..d3d4c7f 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"عرض"</string>
<string name="always_use_device" msgid="1450287437017315906">"الاستخدام بشكل افتراضي لجهاز USB هذا"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"الاستخدام بشكل افتراضي لملحق USB هذا"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"تكبير/تصغير لملء الشاشة"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"توسيع بملء الشاشة"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"تكبير/تصغير التوافق"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index a8a17f0..8216e2b 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"Прагляд"</string>
<string name="always_use_device" msgid="1450287437017315906">"Выкарыстоўваць налады па змаўчанні для дадзенай USB-прылады"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Выкарыстоўваць налады па змаўчанні для дадзенай USB-прылады"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"Дазволіць адладку USB?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"Дазволіць USB-адладку з гэтага камп\'ютара?"\n"Ваш адбiтак ключа RSA"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Дазваляць гэтаму камп\'ютару"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Павял. на ўвесь экран"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Расцягн. на ўвесь экран"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Маштабаванне для сумяшчальнасцi"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 0270678..ba57e91 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Преглед"</string>
<string name="always_use_device" msgid="1450287437017315906">"Използване по подразб. за това USB устройство"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Използване по подразб. за този аксесоар за USB"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Мащаб – запълва екрана"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Разпъване – запълва екрана"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Промяна на мащаба за съвместимост"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 2e48570..3eb078d 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"Mostra"</string>
<string name="always_use_device" msgid="1450287437017315906">"Utilitza de manera predet. per al dispositiu USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Utilitza de manera predet. per a l\'accessori USB"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"Vols permetre la depuració USB?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"Vols permetre la depuració USB des d\'aquest equip?"\n"L\'empremta de la teva clau RSA és"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Dóna sempre permís a aquest equip"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Zoom per omplir pantalla"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Estira per omplir pant."</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilitat"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index c9b6a52..fb6584e 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Zobrazit"</string>
<string name="always_use_device" msgid="1450287437017315906">"Pro toto zařízení USB použít jako výchozí"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Pro toto periferní zařízení USB použít jako výchozí"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Přiblížit na celou obrazovku"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Na celou obrazovku"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Úprava velikosti z důvodu kompatibility"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 370865c..48cab36 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"Vis"</string>
<string name="always_use_device" msgid="1450287437017315906">"Brug som standard til denne USB-enhed"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Brug som standard til dette USB-tilbehør"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"Vil du tillade USB-fejlretning?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"Vil du tillade USB-fejlretning fra denne computer?"\n"Dit fingeraftryk for RSA-nøglen er"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Tillad altid denne computer"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Zoom til fuld skærm"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Stræk til fuld skærm"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitetszoom"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 65c870f..4bcbc31 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"Anzeigen"</string>
<string name="always_use_device" msgid="1450287437017315906">"Standardmäßig für dieses USB-Gerät verwenden"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Standardmäßig für dieses USB-Zubehör verwenden"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"USB-Debugging zulassen?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"USB-Debugging auf diesem Computer zulassen?"\n"Ihr Fingerabdruck des RSA-Schlüssels lautet"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>."</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Auf diesem Computer immer zulassen"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Zoom auf Bildschirmgröße"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Auf Bildschirmgröße anpassen"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitätszoom"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 6e147e2..2231a8c 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"Προβολή"</string>
<string name="always_use_device" msgid="1450287437017315906">"Χρήση από προεπιλογή για αυτή τη συσκευή USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Χρήση από προεπιλογή για αυτό το εξάρτημα USB"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"Να επιτρέπεται ο εντοπισμός σφαλμάτων USB;"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"Να επιτρέπεται ο εντοπισμός σφαλμάτων USB από αυτόν τον υπολογιστή;"\n"Το αποτύπωμα κλειδιού σας RSA είναι"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Να επιτρέπεται πάντα σε αυτόν τον υπολογιστή"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Ζουμ σε πλήρη οθόνη"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Προβoλή σε πλήρη οθ."</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Ζουμ για συμβατότητα"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index afabd34..671ac1b 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"View"</string>
<string name="always_use_device" msgid="1450287437017315906">"Use by default for this USB device"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Use by default for this USB accessory"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"Allow USB Debugging?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"Allow USB Debugging from this computer?"\n"Your RSA key fingerprint is"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Always allow this computer"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Zoom to fill screen"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Compatibility zoom"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index b83aad5..4c07d9f 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Ver"</string>
<string name="always_use_device" msgid="1450287437017315906">"Se usa de forma predeterminada para este dispositivo USB."</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Se usa de forma predeterminada para este accesorio USB."</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ocupar la pantalla"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Estirar p/ ocupar la pantalla"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilidad"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index c0cab22..cd03d92 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"Ver"</string>
<string name="always_use_device" msgid="1450287437017315906">"Usar de forma predeterminada para este dispositivo USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Usar de forma predeterminada para este accesorio USB"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"¿Permitir depuración USB?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"¿Quieres permitir la depuración USB en este ordenador?"\n"La huella digital de tu clave RSA es:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Permitir siempre en este ordenador"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ajustar"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Expandir para ajustar"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilidad"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 8adf8ed..17484377 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Kuva"</string>
<string name="always_use_device" msgid="1450287437017315906">"Kasuta vaikimisi selle USB-seadme jaoks"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Vaikimisi kasuta seda USB-lisaseadet"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Suumi ekraani täitmiseks"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Venita ekraani täitmiseks"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Sobivussuum"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 2c66897..e75d5f0 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"مشاهده"</string>
<string name="always_use_device" msgid="1450287437017315906">"استفاده به صورت پیش‌فرض برای این دستگاه USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"استفاده به صورت پیش‌فرض برای این دستگاه USB"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"بزرگنمایی برای پر کردن صفحه"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"گسترده کردن برای پر کردن صفحه"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"بزرگنمایی سازگاری"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index bec1b48..5132502 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"Näytä"</string>
<string name="always_use_device" msgid="1450287437017315906">"Käytä oletuksena tällä USB-laitteella"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Käytä oletuksena tällä USB-lisälaitteella"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"Sallitaanko USB-vianetsintä?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"Sallitaanko USB-vianetsintä tällä tietokoneella?"\n"RSA-avaimesi sormenjälki on"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Salli vianetsintä tällä tietokoneella aina"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Zoomaa koko näyttöön"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Venytä koko näyttöön"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Yhteensopivuuszoomaus"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 15489f5..d862df8 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Afficher"</string>
<string name="always_use_device" msgid="1450287437017315906">"Utiliser par défaut pour ce périphérique USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Utiliser par défaut pour cet accessoire USB"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Zoomer pour remplir l\'écran"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Étirer pour remplir l\'écran"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilité"</string>
@@ -135,7 +141,7 @@
<string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"Données désactivées"</string>
<string name="data_usage_disabled_dialog" msgid="3853117269051806280">"Vous avez atteint le plafond de consommation de données spécifié."\n\n"Si vous utilisez des données supplémentaires, celles-ci pourront être facturées par l\'opérateur."</string>
<string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Réactiver connexion données"</string>
- <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Aucune connexion"</string>
+ <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Aucune connexion Internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Connecté au Wi-Fi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Recherche de GPS..."</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Position définie par GPS"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index c66b680..b45b4ce 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"देखें"</string>
<string name="always_use_device" msgid="1450287437017315906">"इस USB उपकरण के लिए डिफ़ॉल्‍ट रूप से उपयोग करें"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"इस USB एसेसरी के लिए डिफ़ॉल्‍ट रूप से उपयोग करें"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"स्‍क्रीन भरने हेतु ज़ूम करें"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"स्‍क्रीन को भरने के लिए खींचें"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"संगतता ज़ूम"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 1a10ecb..620e193 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Prikaži"</string>
<string name="always_use_device" msgid="1450287437017315906">"Koristi se prema zadanim postavkama za ovaj USB uređaj"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Koristi se prema zadanim postavkama za ovaj USB pribor"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Zumiraj i ispuni zaslon"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Rastegni i ispuni zaslon"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilno zumiranje"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 25f3e54..1805ce0 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Megtekintés"</string>
<string name="always_use_device" msgid="1450287437017315906">"Alapértelmezett használat ehhez az USB-eszközhöz"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Alapértelmezett használat ehhez az USB-kiegészítőhöz"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Nagyítás a kitöltéshez"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Nyújtás kitöltéshez"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitás -- nagyítás/kicsinyítés"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 3ad4fd1..65e47dd 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"Lihat"</string>
<string name="always_use_device" msgid="1450287437017315906">"Gunakan secara default untuk perangkat USB ini"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Gunakan secara default untuk aksesori USB ini"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"Izinkan Debugging USB?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"Izinkan Debugging USB dari komputer ini?"\n"Sidik jari kunci RSA Anda adalah"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Selalu izinkan komputer ini"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Perbesar utk mengisi layar"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Rentangkn utk mngisi layar"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Perbesar/perkecil untuk kompatibilitas"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index df7f188..49b0fb0 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"Visualizza"</string>
<string name="always_use_device" msgid="1450287437017315906">"Usa per impostazione predef. per dispositivo USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Usa per impostazione predef. per accessorio USB"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"Consentire debug USB?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"Consentire il debug USB da questo computer? "\n"La fingerprint della tua chiave RSA è "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Consenti sempre da questo computer"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Zoom per riempire schermo"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Estendi per riemp. schermo"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom compatibilità"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 2e75e72..59730af 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"הצג"</string>
<string name="always_use_device" msgid="1450287437017315906">"השתמש כברירת מחדל עבור מכשיר USB זה"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"השתמש כברירת מחדל עבור אביזר USB זה"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"האם לאפשר ניקוי באגים ב-USB?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"האם להרשות ניקוי באגים ב-USB ממחשב זה?"\n"טביעת האצבע של מפתח ה-RSA שלך היא"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"הרשה תמיד במחשב זה"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"הגדל תצוגה כדי למלא את המסך"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"מתח כדי למלא את המסך"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"שינוי מרחק מתצוגה לצורך תאימות"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 2d73518..8eda13f 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"表示"</string>
<string name="always_use_device" msgid="1450287437017315906">"このUSBデバイスにデフォルトで使用する"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"このUSBアクセサリにデフォルトで使用する"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"画面サイズに合わせて拡大"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"画面サイズに合わせて拡大"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"互換ズーム"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 438734e..9562237 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"보기"</string>
<string name="always_use_device" msgid="1450287437017315906">"이 USB 기기에 기본값으로 사용"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"이 USB 액세서리에 기본값으로 사용"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"전체화면 모드로 확대"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"전체화면 모드로 확대"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"호환성 확대/축소"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 62c6a06..daacca5 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Žiūrėti"</string>
<string name="always_use_device" msgid="1450287437017315906">"Šiam USB įreng. naudoti pagal numat. nustatymus"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Šiam USB priedui naudoti pagal numat. nustatymus"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Keisti mast., kad atit. ekr."</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Ištempti, kad atit. ekr."</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Suderinamumo mastelio keitimas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 5929240..b189fd2 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Skatīt"</string>
<string name="always_use_device" msgid="1450287437017315906">"Pēc noklusējuma izmantot šai USB ierīcei"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Pēc noklusējuma izmantot šim USB piederumam"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Tālumm., lai aizp. ekr."</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Stiepiet, lai aizp. ekr."</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Saderības tālummaiņa"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 5bf9811..8da9ed5 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Lihat"</string>
<string name="always_use_device" msgid="1450287437017315906">"Gunakan secara lalai untuk peranti USB ini"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Gunakan secara lalai untuk aksesori USB ini"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Zum untuk memenuhi skrin"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Regang utk memenuhi skrin"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Zum keserasian"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 9a0b2de..e7005fa 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"Vis"</string>
<string name="always_use_device" msgid="1450287437017315906">"Bruk som standard for denne USB-enheten"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Bruk som standard for dette USB-tilbehøret"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"Vil du tillate USB-feilsøking?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"Vil du tillate USB-feilsøking fra denne datamaskinen?"\n"Nøkkelfingeravtrykket ditt for RSA er"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Gi alltid tillatelse til denne datamaskinen"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Zoom for å fylle skjermen"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Strekk for å fylle skjerm"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitets-zooming"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 33bab76..d5e8444 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"Weergeven"</string>
<string name="always_use_device" msgid="1450287437017315906">"Standaard gebruiken voor dit USB-apparaat"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Standaard gebruiken voor dit USB-accessoire"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"USB-foutopsporing toestaan?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"USB-foutopsporing toestaan vanaf deze computer?"\n"Uw RSA-sleutelvingerafdruk is"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Deze computer altijd toestaan"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Zoom om scherm te vullen"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Rek uit v. schermvulling"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Compatibiliteitszoom"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 6a7639f..50d5e3b 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Wyświetl"</string>
<string name="always_use_device" msgid="1450287437017315906">"Używaj domyślnie dla tego urządzenia USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Używaj domyślnie dla tego akcesorium USB"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Powiększ, aby wypełnić ekran"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Rozciągnij, aby wypełnić ekran"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Powiększenie w trybie zgodności"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 655c46e..b583aea 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Ver"</string>
<string name="always_use_device" msgid="1450287437017315906">"Utilizar por predefinição para este aparelho USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Utilizar por predefinição para este acessório USB"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Zoom para preencher o ecrã"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Esticar p. caber em ec. int."</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilidade"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 5fabdfd..bae61d0 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Visualizar"</string>
<string name="always_use_device" msgid="1450287437017315906">"Usar por padrão para este dispositivo USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Usar por padrão para este acessório USB"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Zoom p/ preencher a tela"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Ampliar p/ preencher tela"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom em modo de compatibilidade"</string>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index e0c0886..ea88ddd 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -86,6 +86,12 @@
<skip />
<!-- no translation found for always_use_accessory (1210954576979621596) -->
<skip />
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<!-- no translation found for compat_mode_on (6623839244840638213) -->
<skip />
<!-- no translation found for compat_mode_off (4434467572461327898) -->
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 58a9a9b..5580f01 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Afişaţi"</string>
<string name="always_use_device" msgid="1450287437017315906">"Utilizaţi în mod prestabilit pt. acest dispoz. USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Utiliz. în mod prestabilit pt. acest accesoriu USB"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Zoom pt. a umple ecranul"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Înt. pt. a umple ecranul"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilitate"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 155238a..567d1de 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -25,7 +25,7 @@
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Показать уведомления"</string>
<string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Удаление из списка"</string>
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"О приложении"</string>
- <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"Нет данных"</string>
+ <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"В последнее время вы не запускали приложения."</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Закрыть недавние приложения"</string>
<plurals name="status_bar_accessibility_recent_apps">
<item quantity="one" msgid="5854176083865845541">"Недавних приложений: 1"</item>
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Просмотр"</string>
<string name="always_use_device" msgid="1450287437017315906">"Использовать по умолчанию для этого USB-устройства"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Использовать по умолчанию для этого USB-аксессуара"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Подогнать по размерам экрана"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Растянуть на весь экран"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Масштаб и совместимость"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 0c15f6c..01a8606 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Zobraziť"</string>
<string name="always_use_device" msgid="1450287437017315906">"Pre toto zariadenie USB použiť ako predvolené"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Pre toto periférne zar. USB použiť ako predvolené"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Priblížiť na celú obrazovku"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Na celú obrazovku"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Úprava veľkosti z dôvodu kompatibility"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 2b385fc..1bed89b 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"Prikaži"</string>
<string name="always_use_device" msgid="1450287437017315906">"Privzeto uporabi za to napravo USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Privzeto uporabi za ta dodatek USB"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"Ali dovolite odpravljanje težav s povezavo USB?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"Ali dovolite odpravljanje težav s povezavo USB v tem računalniku?"\n"Prstni odtis ključa RSA je"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Vedno dovoli za ta računalnik"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Povečava čez cel zaslon"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Raztegnitev čez zaslon"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Razširitev združljivosti"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index c43b66f..3987d76 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Прикажи"</string>
<string name="always_use_device" msgid="1450287437017315906">"Користи подразумевано за овај USB уређај"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Користи подразумевано за овај USB додатак"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Зумирај на целом екрану"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Развуци на цео екран"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Компатибилно зумирање"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index e3a1481..f09dc2a 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"Visa"</string>
<string name="always_use_device" msgid="1450287437017315906">"Använd som standard för den här USB-enheten"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Använd som standard för det här USB-tillbehöret"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"Ska USB-felsökning tillåtas?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"Vill du tillåta USB-felsökning från den här datorn?"\n"Din RSA-fingeravtrycksnyckel är"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Tillåt alltid för den här datorn"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Zooma för att fylla skärm"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Dra för att fylla skärmen"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom i kompatibilitetsläge"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index b333bbe..a6fec13 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -56,6 +56,9 @@
<string name="label_view" msgid="6304565553218192990">"Ona"</string>
<string name="always_use_device" msgid="1450287437017315906">"Kwa kifaa hiki cha USB tumia chaguo-msingi"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Tumia kama chaguo-msingi ya kifuasi hiki cha USB"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"Ruhusu Utatuaji USB?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"Ruhusu Utatuaji wa USB kutoka kwenye kompyuta hii?"\n"Kitufe chako RSA cha alama ya kidole ni "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Kila wakati ruhusu kompyuta hii"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Kuza ili kujaza skrini"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Tanua ili kujaza skrini"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Kukuza kwa Utangamanifu"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 4d46a5d..0c42f87 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"ดู"</string>
<string name="always_use_device" msgid="1450287437017315906">"ใช้ค่าเริ่มต้นสำหรับอุปกรณ์ USB นี้"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"ใช้ค่าเริ่มต้นสำหรับอุปกรณ์เสริม USB นี้"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"ขยายจนเต็มหน้าจอ"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"ยืดจนเต็มหน้าจอ"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"ความเข้ากันได้ของการย่อ/ขยาย"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index a93e511..bb0a2bf 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Tingnan"</string>
<string name="always_use_device" msgid="1450287437017315906">"Gamitin bilang default para sa USB device"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Gamitin bilang default sa USB accessory na ito"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"I-zoom upang punan screen"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"I-stretch upang mapuno screen"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom sa pagiging Tugma"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 0f6af69..6c30abe 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Görüntüle"</string>
<string name="always_use_device" msgid="1450287437017315906">"Bu USB cihazı için varsayılan olarak kullan"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Bu USB aksesuar için varsayılan olarak kullan"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Yakınlaştır (ekranı kaplasın)"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Genişlet (ekran kapansın)"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Uyumluluk yakınlaştırması"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 5922e24..973c6bc 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -58,6 +58,9 @@
<string name="label_view" msgid="6304565553218192990">"Переглянути"</string>
<string name="always_use_device" msgid="1450287437017315906">"Використовувати за умовчанням для пристрою USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Використовувати за умовчанням для аксесуара USB"</string>
+ <string name="usb_debugging_title" msgid="1114766024068112429">"Дозволити налагодження USB?"</string>
+ <string name="usb_debugging_message" msgid="719863946976291180">"Дозволити налагодження USB на цьому комп’ютері?"\n"Цифровий відбиток вашого ключа RSA:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="4253099426793114693">"Завжди дозволяти цьому комп’ютеру"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Масштабув. на весь екран"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Розтягнути на весь екран"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Масштабування для сумісності"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 15141c9..cef38ec 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Xem"</string>
<string name="always_use_device" msgid="1450287437017315906">"Sử dụng theo mặc định cho thiết bị USB này"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Sử dụng theo mặc định cho phụ kiện USB này"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"T.phóng để lấp đầy m.hình"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Giãn ra để lấp đầy m.hình"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Thu phóng tương thích"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 19470e6..d0f4a9c 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"查看"</string>
<string name="always_use_device" msgid="1450287437017315906">"默认情况下用于该 USB 设备"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"默认情况下用于该 USB 配件"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"缩放以填满屏幕"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"拉伸以填满屏幕"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"兼容性缩放"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index fa2e9d1..2e5211f 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"查看"</string>
<string name="always_use_device" msgid="1450287437017315906">"預設用於這個 USB 裝置"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"預設用於這個 USB 配件"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"放大為全螢幕"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"放大為全螢幕"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"相容性縮放"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 1e11f04..07c9f0f 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -58,6 +58,12 @@
<string name="label_view" msgid="6304565553218192990">"Buka"</string>
<string name="always_use_device" msgid="1450287437017315906">"Sebenzisa ngokuzenzakalelayo yale divayisi ye-USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Sebenzisa ngokuzenzakalelayo kule-accessory ye-USB"</string>
+ <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+ <skip />
+ <!-- no translation found for usb_debugging_message (719863946976291180) -->
+ <skip />
+ <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+ <skip />
<string name="compat_mode_on" msgid="6623839244840638213">"Sondeza ukugcwalisa isikrini"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Nweba ukugcwalisa isikrini"</string>
<string name="compat_mode_help_header" msgid="7969493989397529910">"Ukuhambelana Kokusondeza"</string>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 2ce950f..5747f22 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -154,6 +154,15 @@
<!-- Checkbox label for USB accessory dialogs. [CHAR LIMIT=50] -->
<string name="always_use_accessory">Use by default for this USB accessory</string>
+ <!-- Title of confirmation dialog for USB debugging -->
+ <string name="usb_debugging_title">Allow USB Debugging?</string>
+
+ <!-- Message of confirmation dialog for USB debugging -->
+ <string name="usb_debugging_message">Allow USB Debugging from this computer?\nYour RSA key fingerprint is\n<xliff:g id="fingerprint">%1$s</xliff:g></string>
+
+ <!-- Option to always allow USB debugging from the attached computer -->
+ <string name="usb_debugging_always">Always allow this computer</string>
+
<!-- Checkbox label for application compatibility mode ON (zooming app to look like it's running
on a phone). [CHAR LIMIT=25] -->
<string name="compat_mode_on">Zoom to fill screen</string>
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index a72074e..2512c02 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -74,10 +74,7 @@ public class ImageWallpaper extends WallpaperService {
//noinspection PointlessBooleanExpression,ConstantConditions
if (FIXED_SIZED_SURFACE && USE_OPENGL) {
if (!isEmulator()) {
- WindowManager windowManager =
- (WindowManager) getSystemService(Context.WINDOW_SERVICE);
- Display display = windowManager.getDefaultDisplay();
- mIsHwAccelerated = ActivityManager.isHighEndGfx(display);
+ mIsHwAccelerated = ActivityManager.isHighEndGfx();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index a2f43fd..281f25f 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -82,7 +82,8 @@ public class SearchPanelView extends FrameLayout implements
R.anim.search_launch_enter, R.anim.search_launch_exit,
getHandler(), this);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.USER_CURRENT);
+ mContext.startActivityAsUser(intent, opts.toBundle(),
+ new UserHandle(UserHandle.USER_CURRENT));
} catch (ActivityNotFoundException e) {
Slog.w(TAG, "Activity not found for " + intent.getAction());
onAnimationStarted();
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 0a57499..1bde949 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -31,6 +31,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Slog;
import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
public class SystemUIService extends Service {
static final String TAG = "SystemUIService";
@@ -67,8 +68,7 @@ public class SystemUIService extends Service {
@Override
public void onCreate() {
// Pick status bar or system bar.
- IWindowManager wm = IWindowManager.Stub.asInterface(
- ServiceManager.getService(Context.WINDOW_SERVICE));
+ IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
try {
SERVICES[0] = wm.hasSystemNavBar()
? R.string.config_systemBarComponent
diff --git a/packages/SystemUI/src/com/android/systemui/UniverseBackground.java b/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
index 4852a3e..7628754 100644
--- a/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
+++ b/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
@@ -33,6 +33,7 @@ import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewRootImpl;
import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
import android.view.animation.Transformation;
import android.widget.FrameLayout;
@@ -96,7 +97,7 @@ public class UniverseBackground extends FrameLayout {
public UniverseBackground(Context context) {
super(context);
setBackgroundColor(0xff000000);
- mSession = ViewRootImpl.getWindowSession(context.getMainLooper());
+ mSession = WindowManagerGlobal.getWindowSession(context.getMainLooper());
mContent = View.inflate(context, R.layout.universe, null);
addView(mContent);
mContent.findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
@@ -155,7 +156,7 @@ public class UniverseBackground extends FrameLayout {
}
}
- public WindowManager.LayoutParams getLayoutParams(Display display) {
+ public WindowManager.LayoutParams getLayoutParams() {
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND,
@@ -165,7 +166,7 @@ public class UniverseBackground extends FrameLayout {
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
PixelFormat.OPAQUE);
// this will allow the window to run in an overlay on devices that support this
- if (ActivityManager.isHighEndGfx(display)) {
+ if (ActivityManager.isHighEndGfx()) {
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
lp.setTitle("UniverseBackground");
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 7d36152..b407078 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -49,6 +49,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
@@ -488,9 +489,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener
mChoreo = new Choreographer(this, mRecentsScrim, mRecentsContainer, mRecentsNoApps, this);
if (mRecentsScrim != null) {
- Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
- .getDefaultDisplay();
- mHighEndGfx = ActivityManager.isHighEndGfx(d);
+ mHighEndGfx = ActivityManager.isHighEndGfx();
if (!mHighEndGfx) {
mRecentsScrim.setBackground(null);
} else if (mRecentsScrim.getBackground() instanceof BitmapDrawable) {
@@ -733,8 +732,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener
if (mTransitionBg == null) {
mTransitionBg = (View) findViewById(R.id.recents_transition_background);
- IWindowManager wm = IWindowManager.Stub.asInterface(
- ServiceManager.getService(Context.WINDOW_SERVICE));
+ IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
try {
if (!wm.hasSystemNavBar()) {
FrameLayout.LayoutParams lp =
@@ -767,7 +765,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener
show(false, true);
mThumbnailScaleUpStarted = false;
- ActivityOptions opts = ActivityOptions.makeDelayedThumbnailScaleUpAnimation(
+ ActivityOptions opts = ActivityOptions.makeThumbnailScaleUpAnimation(
holder.thumbnailViewImage, bm, 0, 0,
new ActivityOptions.OnAnimationStartedListener() {
@Override public void onAnimationStarted() {
@@ -790,7 +788,8 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener
| Intent.FLAG_ACTIVITY_TASK_ON_HOME
| Intent.FLAG_ACTIVITY_NEW_TASK);
if (DEBUG) Log.v(TAG, "Starting activity " + intent);
- context.startActivityAsUser(intent, opts.toBundle(), UserHandle.USER_CURRENT);
+ context.startActivityAsUser(intent, opts.toBundle(),
+ new UserHandle(UserHandle.USER_CURRENT));
}
if (usingDrawingCache) {
holder.thumbnailViewImage.setDrawingCacheEnabled(false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 7598537..e9e043e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -61,9 +61,9 @@ import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManagerGlobal;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
-import android.view.WindowManagerImpl;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
@@ -127,17 +127,11 @@ public abstract class BaseStatusBar extends SystemUI implements
*/
protected abstract void createAndAddWindows();
+ protected WindowManager mWindowManager;
+ protected IWindowManager mWindowManagerService;
protected Display mDisplay;
- private IWindowManager mWindowManager;
- private boolean mDeviceProvisioned = false;
-
- public IWindowManager getWindowManager() {
- return mWindowManager;
- }
- public Display getDisplay() {
- return mDisplay;
- }
+ private boolean mDeviceProvisioned = false;
public IStatusBarService getStatusBarService() {
return mBarService;
@@ -189,17 +183,15 @@ public abstract class BaseStatusBar extends SystemUI implements
};
public void start() {
- mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
- .getDefaultDisplay();
+ mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
+ mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
+ mDisplay = mWindowManager.getDefaultDisplay();
mProvisioningObserver.onChange(false); // set up
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.DEVICE_PROVISIONED), true,
mProvisioningObserver);
- mWindowManager = IWindowManager.Stub.asInterface(
- ServiceManager.getService(Context.WINDOW_SERVICE));
-
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -274,7 +266,7 @@ public abstract class BaseStatusBar extends SystemUI implements
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USERID, -1);
+ mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
if (true) Slog.v(TAG, "userId " + mCurrentUserId + " is in the house");
userSwitched(mCurrentUserId);
}
@@ -436,7 +428,7 @@ public abstract class BaseStatusBar extends SystemUI implements
boolean firstScreenful = false;
if (mRecentsPanel != null) {
visible = mRecentsPanel.isShowing();
- WindowManagerImpl.getDefault().removeView(mRecentsPanel);
+ mWindowManager.removeView(mRecentsPanel);
if (visible) {
recentTasksList = mRecentsPanel.getRecentTasksList();
firstScreenful = mRecentsPanel.getFirstScreenful();
@@ -456,7 +448,7 @@ public abstract class BaseStatusBar extends SystemUI implements
WindowManager.LayoutParams lp = getRecentsLayoutParams(mRecentsPanel.getLayoutParams());
- WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
+ mWindowManager.addView(mRecentsPanel, lp);
mRecentsPanel.setBar(this);
if (visible) {
mRecentsPanel.show(true, false, recentTasksList, firstScreenful);
@@ -469,7 +461,7 @@ public abstract class BaseStatusBar extends SystemUI implements
boolean visible = false;
if (mSearchPanelView != null) {
visible = mSearchPanelView.isShowing();
- WindowManagerImpl.getDefault().removeView(mSearchPanelView);
+ mWindowManager.removeView(mSearchPanelView);
}
// Provide SearchPanel with a temporary parent to allow layout params to work.
@@ -482,7 +474,7 @@ public abstract class BaseStatusBar extends SystemUI implements
WindowManager.LayoutParams lp = getSearchLayoutParams(mSearchPanelView.getLayoutParams());
- WindowManagerImpl.getDefault().addView(mSearchPanelView, lp);
+ mWindowManager.addView(mSearchPanelView, lp);
mSearchPanelView.setBar(this);
if (visible) {
mSearchPanelView.show(true, false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 63c9b79..33973b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -18,13 +18,11 @@ package com.android.systemui.statusbar.phone;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
import android.app.StatusBarManager;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
@@ -34,19 +32,14 @@ import android.util.Slog;
import android.view.animation.AccelerateInterpolator;
import android.view.Display;
import android.view.MotionEvent;
-import android.view.VelocityTracker;
import android.view.View;
-import android.view.ViewGroup;
import android.view.Surface;
-import android.view.Window;
import android.view.WindowManager;
-import android.view.WindowManagerImpl;
import android.widget.ImageView;
import android.widget.LinearLayout;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.lang.StringBuilder;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.R;
@@ -244,7 +237,8 @@ public class NavigationBarView extends LinearLayout {
} else {
return;
}
- WindowManagerImpl.getDefault().updateViewLayout(this, lp);
+ WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
+ wm.updateViewLayout(this, lp);
}
}
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 b595257..33f467f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -66,6 +66,7 @@ public class PanelView extends FrameLayout {
private final Runnable mStopAnimator = new Runnable() { public void run() {
if (mTimeAnimator.isStarted()) {
mTimeAnimator.end();
+ mRubberbanding = false;
}
}};
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 a20576f..2886441 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -60,9 +60,9 @@ import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManagerGlobal;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
-import android.view.WindowManagerImpl;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
@@ -150,7 +150,6 @@ public class PhoneStatusBar extends BaseStatusBar {
int mIconHPadding = -1;
Display mDisplay;
- IWindowManager mWindowManager;
IDreamManager mDreamManager;
StatusBarWindowView mStatusBarWindow;
@@ -261,9 +260,6 @@ public class PhoneStatusBar extends BaseStatusBar {
mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
- mWindowManager = IWindowManager.Stub.asInterface(
- ServiceManager.getService(Context.WINDOW_SERVICE));
-
mDreamManager = IDreamManager.Stub.asInterface(
ServiceManager.checkService("dreams"));
@@ -332,7 +328,7 @@ public class PhoneStatusBar extends BaseStatusBar {
mSettingsPanel = (PanelView) mStatusBarWindow.findViewById(R.id.settings_panel);
mSettingsPanel.setOnTouchListener(clickStopper);
- if (!ActivityManager.isHighEndGfx(mDisplay)) {
+ if (!ActivityManager.isHighEndGfx()) {
mStatusBarWindow.setBackground(null);
mNotificationPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
R.color.notification_panel_solid_background)));
@@ -352,7 +348,7 @@ public class PhoneStatusBar extends BaseStatusBar {
updateShowSearchHoldoff();
try {
- boolean showNav = mWindowManager.hasNavigationBar();
+ boolean showNav = mWindowManagerService.hasNavigationBar();
if (DEBUG) Slog.v(TAG, "hasNavigationBar=" + showNav);
if (showNav) {
mNavigationBarView =
@@ -474,7 +470,7 @@ public class PhoneStatusBar extends BaseStatusBar {
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
(opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
- if (ActivityManager.isHighEndGfx(mDisplay)) {
+ if (ActivityManager.isHighEndGfx()) {
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
} else {
lp.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
@@ -499,7 +495,7 @@ public class PhoneStatusBar extends BaseStatusBar {
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
(opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
- if (ActivityManager.isHighEndGfx(mDisplay)) {
+ if (ActivityManager.isHighEndGfx()) {
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
@@ -535,7 +531,7 @@ public class PhoneStatusBar extends BaseStatusBar {
WindowManager.LayoutParams lp =
(android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
- WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
+ mWindowManager.updateViewLayout(mNavigationBarView, lp);
}
@Override
@@ -544,7 +540,7 @@ public class PhoneStatusBar extends BaseStatusBar {
WindowManager.LayoutParams lp =
(android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
- WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
+ mWindowManager.updateViewLayout(mNavigationBarView, lp);
}
protected int getStatusBarGravity() {
@@ -620,8 +616,7 @@ public class PhoneStatusBar extends BaseStatusBar {
prepareNavigationBarView();
- WindowManagerImpl.getDefault().addView(
- mNavigationBarView, getNavigationBarLayoutParams());
+ mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
}
private void repositionNavigationBar() {
@@ -629,8 +624,7 @@ public class PhoneStatusBar extends BaseStatusBar {
prepareNavigationBarView();
- WindowManagerImpl.getDefault().updateViewLayout(
- mNavigationBarView, getNavigationBarLayoutParams());
+ mWindowManager.updateViewLayout(mNavigationBarView, getNavigationBarLayoutParams());
}
private WindowManager.LayoutParams getNavigationBarLayoutParams() {
@@ -644,7 +638,7 @@ public class PhoneStatusBar extends BaseStatusBar {
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
PixelFormat.OPAQUE);
// this will allow the navbar to run in an overlay on devices that support this
- if (ActivityManager.isHighEndGfx(mDisplay)) {
+ if (ActivityManager.isHighEndGfx()) {
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
@@ -671,7 +665,7 @@ public class PhoneStatusBar extends BaseStatusBar {
lp.packageName = mContext.getPackageName();
lp.windowAnimations = R.style.Animation_StatusBar_IntruderAlert;
- WindowManagerImpl.getDefault().addView(mIntruderAlertView, lp);
+ mWindowManager.addView(mIntruderAlertView, lp);
}
public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
@@ -1157,8 +1151,7 @@ public class PhoneStatusBar extends BaseStatusBar {
lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
- final WindowManager wm = WindowManagerImpl.getDefault();
- wm.updateViewLayout(mStatusBarWindow, lp);
+ mWindowManager.updateViewLayout(mStatusBarWindow, lp);
// Updating the window layout will force an expensive traversal/redraw.
// Kick off the reveal animation after this is complete to avoid animation latency.
@@ -1231,8 +1224,7 @@ public class PhoneStatusBar extends BaseStatusBar {
lp.height = getStatusBarHeight();
lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
lp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- final WindowManager wm = WindowManagerImpl.getDefault();
- wm.updateViewLayout(mStatusBarWindow, lp);
+ mWindowManager.updateViewLayout(mStatusBarWindow, lp);
if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
@@ -1409,7 +1401,7 @@ public class PhoneStatusBar extends BaseStatusBar {
private void notifyUiVisibilityChanged() {
try {
- mWindowManager.statusBarVisibilityChanged(mSystemUiVisibility);
+ mWindowManagerService.statusBarVisibilityChanged(mSystemUiVisibility);
} catch (RemoteException ex) {
}
}
@@ -1615,7 +1607,7 @@ public class PhoneStatusBar extends BaseStatusBar {
lp.packageName = mContext.getPackageName();
makeStatusBarView();
- WindowManagerImpl.getDefault().addView(mStatusBarWindow, lp);
+ mWindowManager.addView(mStatusBarWindow, lp);
}
void setNotificationIconVisibility(boolean visible, int anim) {
@@ -1783,7 +1775,8 @@ public class PhoneStatusBar extends BaseStatusBar {
} catch (RemoteException e) {
}
v.getContext().startActivityAsUser(new Intent(Settings.ACTION_SETTINGS)
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), UserHandle.USER_CURRENT);
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
+ new UserHandle(UserHandle.USER_CURRENT));
animateCollapse();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 2a96d6d..6d47493 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -140,7 +140,7 @@ public class PhoneStatusBarView extends PanelBar {
super.panelExpansionChanged(pv, frac);
if (mFadingPanel == pv
- && mScrimColor != 0 && ActivityManager.isHighEndGfx(mBar.mDisplay)) {
+ && mScrimColor != 0 && ActivityManager.isHighEndGfx()) {
// woo, special effects
final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2.2f))));
// attenuate background color alpha by k
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
index ffe69e2..c45ac3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
@@ -119,7 +119,8 @@ public class SettingsView extends LinearLayout implements View.OnClickListener {
// ----------------------------
private void onClickSettings() {
getContext().startActivityAsUser(new Intent(Settings.ACTION_SETTINGS)
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), UserHandle.USER_CURRENT);
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
+ new UserHandle(UserHandle.USER_CURRENT));
getStatusBarManager().collapse();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
index ddb43b8..2924cc9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
@@ -34,7 +34,6 @@ import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
-import android.view.WindowManagerImpl;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index cbd8831..84697e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -53,7 +53,6 @@ import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
-import android.view.WindowManagerImpl;
import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -124,8 +123,6 @@ public class TabletStatusBar extends BaseStatusBar implements
int mMenuNavIconWidth = -1;
private int mMaxNotificationIcons = 5;
- IWindowManager mWindowManager;
-
TabletStatusBarView mStatusBarView;
View mNotificationArea;
View mNotificationTrigger;
@@ -241,7 +238,7 @@ public class TabletStatusBar extends BaseStatusBar implements
lp.gravity = getStatusBarGravity();
lp.setTitle("SystemBar");
lp.packageName = mContext.getPackageName();
- WindowManagerImpl.getDefault().addView(sb, lp);
+ mWindowManager.addView(sb, lp);
}
protected void addPanelWindows() {
@@ -306,7 +303,7 @@ public class TabletStatusBar extends BaseStatusBar implements
lp.windowAnimations = com.android.internal.R.style.Animation; // == no animation
// lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
- WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
+ mWindowManager.addView(mNotificationPanel, lp);
// Recents Panel
mRecentTasksLoader = new RecentTasksLoader(context);
@@ -338,7 +335,7 @@ public class TabletStatusBar extends BaseStatusBar implements
lp.setTitle("InputMethodsPanel");
lp.windowAnimations = R.style.Animation_RecentPanel;
- WindowManagerImpl.getDefault().addView(mInputMethodsPanel, lp);
+ mWindowManager.addView(mInputMethodsPanel, lp);
// Compatibility mode selector panel
mCompatModePanel = (CompatModePanel) View.inflate(context,
@@ -361,7 +358,7 @@ public class TabletStatusBar extends BaseStatusBar implements
lp.setTitle("CompatModePanel");
lp.windowAnimations = android.R.style.Animation_Dialog;
- WindowManagerImpl.getDefault().addView(mCompatModePanel, lp);
+ mWindowManager.addView(mCompatModePanel, lp);
mRecentButton.setOnTouchListener(mRecentsPanel);
@@ -380,7 +377,7 @@ public class TabletStatusBar extends BaseStatusBar implements
private int getNotificationPanelHeight() {
final Resources res = mContext.getResources();
- final Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
+ final Display d = mWindowManager.getDefaultDisplay();
final Point size = new Point();
d.getRealSize(size);
return Math.max(res.getDimensionPixelSize(R.dimen.notification_panel_min_height), size.y);
@@ -395,8 +392,7 @@ public class TabletStatusBar extends BaseStatusBar implements
protected void onConfigurationChanged(Configuration newConfig) {
loadDimens();
mNotificationPanelParams.height = getNotificationPanelHeight();
- WindowManagerImpl.getDefault().updateViewLayout(mNotificationPanel,
- mNotificationPanelParams);
+ mWindowManager.updateViewLayout(mNotificationPanel, mNotificationPanelParams);
mRecentsPanel.updateValuesFromResources();
mShowSearchHoldoff = mContext.getResources().getInteger(
R.integer.config_show_search_delay);
@@ -456,9 +452,6 @@ public class TabletStatusBar extends BaseStatusBar implements
protected View makeStatusBarView() {
final Context context = mContext;
- mWindowManager = IWindowManager.Stub.asInterface(
- ServiceManager.getService(Context.WINDOW_SERVICE));
-
loadDimens();
final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
@@ -470,7 +463,7 @@ public class TabletStatusBar extends BaseStatusBar implements
try {
// Sanity-check that someone hasn't set up the config wrong and asked for a navigation
// bar on a tablet that has only the system bar
- if (mWindowManager.hasNavigationBar()) {
+ if (mWindowManagerService.hasNavigationBar()) {
Slog.e(TAG, "Tablet device cannot show navigation bar and system bar");
}
} catch (RemoteException ex) {
@@ -648,7 +641,7 @@ public class TabletStatusBar extends BaseStatusBar implements
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
(opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
- if (ActivityManager.isHighEndGfx(mDisplay)) {
+ if (ActivityManager.isHighEndGfx()) {
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
} else {
lp.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
@@ -681,7 +674,7 @@ public class TabletStatusBar extends BaseStatusBar implements
WindowManager.LayoutParams lp =
(android.view.WindowManager.LayoutParams) mStatusBarView.getLayoutParams();
lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
- WindowManagerImpl.getDefault().updateViewLayout(mStatusBarView, lp);
+ mWindowManager.updateViewLayout(mStatusBarView, lp);
}
@Override
@@ -690,7 +683,7 @@ public class TabletStatusBar extends BaseStatusBar implements
WindowManager.LayoutParams lp =
(android.view.WindowManager.LayoutParams) mStatusBarView.getLayoutParams();
lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
- WindowManagerImpl.getDefault().updateViewLayout(mStatusBarView, lp);
+ mWindowManager.updateViewLayout(mStatusBarView, lp);
}
public int getStatusBarHeight() {
@@ -712,8 +705,7 @@ public class TabletStatusBar extends BaseStatusBar implements
}
if (lp.height != height) {
lp.height = height;
- final WindowManager wm = WindowManagerImpl.getDefault();
- wm.updateViewLayout(mStatusBarView, lp);
+ mWindowManager.updateViewLayout(mStatusBarView, lp);
}
}
@@ -1068,7 +1060,7 @@ public class TabletStatusBar extends BaseStatusBar implements
private void notifyUiVisibilityChanged() {
try {
- mWindowManager.statusBarVisibilityChanged(mSystemUiVisibility);
+ mWindowManagerService.statusBarVisibilityChanged(mSystemUiVisibility);
} catch (RemoteException ex) {
}
}
@@ -1160,12 +1152,12 @@ public class TabletStatusBar extends BaseStatusBar implements
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
- WindowManagerImpl.getDefault().addView(mCompatibilityHelpDialog, lp);
+ mWindowManager.addView(mCompatibilityHelpDialog, lp);
}
private void hideCompatibilityHelp() {
if (mCompatibilityHelpDialog != null) {
- WindowManagerImpl.getDefault().removeView(mCompatibilityHelpDialog);
+ mWindowManager.removeView(mCompatibilityHelpDialog);
mCompatibilityHelpDialog = null;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index d4ebe6d..932b035 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -35,7 +35,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
-import android.view.WindowManagerImpl;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.FrameLayout;
@@ -62,7 +61,8 @@ public class TabletTicker
private static final int ADVANCE_DELAY = 5000; // 5 seconds
- private Context mContext;
+ private final Context mContext;
+ private final WindowManager mWindowManager;
private ViewGroup mWindow;
private IBinder mCurrentKey;
@@ -83,6 +83,7 @@ public class TabletTicker
public TabletTicker(TabletStatusBar bar) {
mBar = bar;
mContext = bar.getContext();
+ mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
final Resources res = mContext.getResources();
mLargeIconHeight = res.getDimensionPixelSize(
android.R.dimen.notification_large_icon_height);
@@ -178,7 +179,7 @@ public class TabletTicker
if (mCurrentView != null) {
if (mWindow == null) {
mWindow = makeWindow();
- WindowManagerImpl.getDefault().addView(mWindow, mWindow.getLayoutParams());
+ mWindowManager.addView(mWindow, mWindow.getLayoutParams());
}
mWindow.addView(mCurrentView);
@@ -242,7 +243,7 @@ public class TabletTicker
public void endTransition(LayoutTransition transition, ViewGroup container,
View view, int transitionType) {
if (mWindowShouldClose) {
- WindowManagerImpl.getDefault().removeView(mWindow);
+ mWindowManager.removeView(mWindow);
mWindow = null;
mWindowShouldClose = false;
mBar.doneTicking();
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
new file mode 100644
index 0000000..9146ccd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.usb;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Typeface;
+import android.hardware.usb.IUsbManager;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.app.AlertActivity;
+import com.android.internal.app.AlertController;
+
+import com.android.systemui.R;
+
+public class UsbDebuggingActivity extends AlertActivity
+ implements DialogInterface.OnClickListener {
+ private static final String TAG = "UsbDebuggingActivity";
+
+ private CheckBox mAlwaysAllow;
+ private UsbDisconnectedReceiver mDisconnectedReceiver;
+ private String mKey;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ mDisconnectedReceiver = new UsbDisconnectedReceiver(this);
+ Intent intent = getIntent();
+ String fingerprints = intent.getStringExtra("fingerprints");
+ mKey = intent.getStringExtra("key");
+
+ if (fingerprints == null || mKey == null) {
+ finish();
+ return;
+ }
+
+ final AlertController.AlertParams ap = mAlertParams;
+ ap.mTitle = getString(R.string.usb_debugging_title);
+ ap.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
+ ap.mMessage = getString(R.string.usb_debugging_message, fingerprints);
+ ap.mPositiveButtonText = getString(android.R.string.ok);
+ ap.mNegativeButtonText = getString(android.R.string.cancel);
+ ap.mPositiveButtonListener = this;
+ ap.mNegativeButtonListener = this;
+
+ // add "always allow" checkbox
+ LayoutInflater inflater = LayoutInflater.from(ap.mContext);
+ View checkbox = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
+ mAlwaysAllow = (CheckBox)checkbox.findViewById(com.android.internal.R.id.alwaysUse);
+ mAlwaysAllow.setText(getString(R.string.usb_debugging_always));
+ ap.mView = checkbox;
+
+ setupAlert();
+ }
+
+ private class UsbDisconnectedReceiver extends BroadcastReceiver {
+ private final Activity mActivity;
+ public UsbDisconnectedReceiver(Activity activity) {
+ mActivity = activity;
+ }
+
+ @Override
+ public void onReceive(Context content, Intent intent) {
+ String action = intent.getAction();
+ if (!UsbManager.ACTION_USB_STATE.equals(action)) {
+ return;
+ }
+ boolean connected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
+ if (!connected) {
+ mActivity.finish();
+ }
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_STATE);
+ registerReceiver(mDisconnectedReceiver, filter);
+ }
+
+ @Override
+ protected void onStop() {
+ if (mDisconnectedReceiver != null) {
+ unregisterReceiver(mDisconnectedReceiver);
+ }
+ super.onStop();
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ boolean allow = (which == AlertDialog.BUTTON_POSITIVE);
+ boolean alwaysAllow = allow && mAlwaysAllow.isChecked();
+ try {
+ IBinder b = ServiceManager.getService(USB_SERVICE);
+ IUsbManager service = IUsbManager.Stub.asInterface(b);
+ if (allow) {
+ service.allowUsbDebugging(alwaysAllow, mKey);
+ } else {
+ service.denyUsbDebugging();
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to notify Usb service", e);
+ }
+ finish();
+ }
+}
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index a0e3e3c..8d19f34 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -50,6 +50,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicy.WindowManagerFuncs;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
@@ -90,8 +91,6 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
private boolean mHasTelephony;
private boolean mHasVibrator;
- private IWindowManager mIWindowManager;
-
/**
* @param context everything needs a context :(
*/
@@ -210,11 +209,11 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
public void onPress() {
// shutdown by making sure radio and power are handled accordingly.
- mWindowManagerFuncs.shutdown();
+ mWindowManagerFuncs.shutdown(true);
}
public boolean onLongPress() {
- mWindowManagerFuncs.rebootSafeMode();
+ mWindowManagerFuncs.rebootSafeMode(true);
return true;
}
@@ -300,7 +299,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
public void onPress() {
try {
ActivityManagerNative.getDefault().switchUser(user.id);
- getWindowManager().lockNow();
+ WindowManagerGlobal.getWindowManagerService().lockNow();
} catch (RemoteException re) {
Log.e(TAG, "Couldn't switch user " + re);
}
@@ -873,12 +872,4 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
mAirplaneState = on ? ToggleAction.State.On : ToggleAction.State.Off;
}
}
-
- private IWindowManager getWindowManager() {
- if (mIWindowManager == null) {
- IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE);
- mIWindowManager = IWindowManager.Stub.asInterface(b);
- }
- return mIWindowManager;
- }
}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index a939222..5c0cd4f 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -178,10 +178,10 @@ public class KeyguardUpdateMonitor {
mHandler.sendMessage(mHandler.obtainMessage(MSG_DPM_STATE_CHANGED));
} else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED,
- intent.getIntExtra(Intent.EXTRA_USERID, 0), 0));
+ intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED,
- intent.getIntExtra(Intent.EXTRA_USERID, 0), 0));
+ intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
}
}
};
@@ -259,7 +259,8 @@ public class KeyguardUpdateMonitor {
*/
boolean isPluggedIn() {
return plugged == BatteryManager.BATTERY_PLUGGED_AC
- || plugged == BatteryManager.BATTERY_PLUGGED_USB;
+ || plugged == BatteryManager.BATTERY_PLUGGED_USB
+ || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
}
/**
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index fb6ff24..d521c05 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -123,8 +123,7 @@ public class KeyguardViewManager implements KeyguardWindowController {
if (!mNeedsInput) {
flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
}
- if (ActivityManager.isHighEndGfx(((WindowManager)mContext.getSystemService(
- Context.WINDOW_SERVICE)).getDefaultDisplay())) {
+ if (ActivityManager.isHighEndGfx()) {
flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
@@ -132,8 +131,7 @@ public class KeyguardViewManager implements KeyguardWindowController {
flags, PixelFormat.TRANSLUCENT);
lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen;
- if (ActivityManager.isHighEndGfx(((WindowManager)mContext.getSystemService(
- Context.WINDOW_SERVICE)).getDefaultDisplay())) {
+ if (ActivityManager.isHighEndGfx()) {
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
lp.privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 66ccdac..4d05a87 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -44,7 +44,7 @@ import android.telephony.TelephonyManager;
import android.util.EventLog;
import android.util.Log;
import android.view.KeyEvent;
-import android.view.WindowManagerImpl;
+import android.view.WindowManager;
import android.view.WindowManagerPolicy;
@@ -376,9 +376,9 @@ public class KeyguardViewMediator implements KeyguardViewCallback {
mKeyguardViewProperties
= new LockPatternKeyguardViewProperties(mLockPatternUtils, mUpdateMonitor);
+ WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
mKeyguardViewManager = new KeyguardViewManager(
- context, WindowManagerImpl.getDefault(), this,
- mKeyguardViewProperties, mUpdateMonitor);
+ context, wm, this, mKeyguardViewProperties, mUpdateMonitor);
mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT);
mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 5f5c105..91b5ca1 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -354,7 +354,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen {
Log.w(TAG, "can't dismiss keyguard on launch");
}
try {
- mContext.startActivityAsUser(intent, UserHandle.USER_CURRENT);
+ mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
} catch (ActivityNotFoundException e) {
Log.w(TAG, "Activity not found for intent + " + intent.getAction());
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 40db612..209ad38 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -42,6 +42,7 @@ import android.media.AudioManager;
import android.media.IAudioService;
import android.os.BatteryManager;
import android.os.Bundle;
+import android.os.FactoryTest;
import android.os.Handler;
import android.os.IBinder;
import android.os.IRemoteCallback;
@@ -82,6 +83,7 @@ import android.view.InputEventReceiver;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.WindowManagerGlobal;
import android.view.WindowOrientationListener;
import android.view.Surface;
import android.view.View;
@@ -132,7 +134,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
-import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
@@ -172,6 +173,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final int LONG_PRESS_POWER_NOTHING = 0;
static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
static final int LONG_PRESS_POWER_SHUT_OFF = 2;
+ static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
// These need to match the documentation/constant in
// core/res/res/values/config.xml
@@ -716,8 +718,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void run() {
// The context isn't read
if (mLongPressOnPowerBehavior < 0) {
- mLongPressOnPowerBehavior = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_longPressOnPowerBehavior);
+ if (FactoryTest.isLongPressOnPowerOffEnabled()) {
+ mLongPressOnPowerBehavior = LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
+ } else {
+ mLongPressOnPowerBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_longPressOnPowerBehavior);
+ }
}
switch (mLongPressOnPowerBehavior) {
case LONG_PRESS_POWER_NOTHING:
@@ -729,10 +735,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
showGlobalActionsDialog();
break;
case LONG_PRESS_POWER_SHUT_OFF:
+ case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
mPowerKeyHandled = true;
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
- mWindowManagerFuncs.shutdown();
+ mWindowManagerFuncs.shutdown(
+ mLongPressOnPowerBehavior == LONG_PRESS_POWER_SHUT_OFF);
break;
}
}
@@ -1172,7 +1180,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
|| type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
- return WindowManagerImpl.ADD_OKAY;
+ return WindowManagerGlobal.ADD_OKAY;
}
String permission = null;
switch (type) {
@@ -1199,10 +1207,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (permission != null) {
if (mContext.checkCallingOrSelfPermission(permission)
!= PackageManager.PERMISSION_GRANTED) {
- return WindowManagerImpl.ADD_PERMISSION_DENIED;
+ return WindowManagerGlobal.ADD_PERMISSION_DENIED;
}
}
- return WindowManagerImpl.ADD_OKAY;
+ return WindowManagerGlobal.ADD_OKAY;
}
public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
@@ -1499,7 +1507,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Only return the view if it was successfully added to the
// window manager... which we can tell by it having a parent.
return view.getParent() != null ? view : null;
- } catch (WindowManagerImpl.BadTokenException e) {
+ } catch (WindowManager.BadTokenException e) {
// ignore
Log.w(TAG, appToken + " already running, starting window not displayed");
} catch (RuntimeException e) {
@@ -1538,7 +1546,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
* @param win The window to be added
* @param attrs Information about the window to be added
*
- * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons, WindowManagerImpl.ADD_MULTIPLE_SINGLETON
+ * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons,
+ * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
*/
public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
switch (attrs.type) {
@@ -1548,7 +1557,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
"PhoneWindowManager");
if (mStatusBar != null) {
if (mStatusBar.isAlive()) {
- return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+ return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
}
}
mStatusBar = win;
@@ -1559,7 +1568,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
"PhoneWindowManager");
if (mNavigationBar != null) {
if (mNavigationBar.isAlive()) {
- return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+ return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
}
}
mNavigationBar = win;
@@ -1582,12 +1591,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
break;
case TYPE_KEYGUARD:
if (mKeyguard != null) {
- return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+ return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
}
mKeyguard = win;
break;
}
- return WindowManagerImpl.ADD_OKAY;
+ return WindowManagerGlobal.ADD_OKAY;
}
/** {@inheritDoc} */
@@ -2066,7 +2075,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (searchManager != null) {
searchManager.stopSearch();
}
- mContext.startActivityAsUser(intent, UserHandle.USER_CURRENT);
+ mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
} catch (ActivityNotFoundException e) {
Slog.w(TAG, "No activity to handle assist long press action.", e);
}
@@ -2081,7 +2090,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
- mContext.startActivityAsUser(intent, UserHandle.USER_CURRENT);
+ mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
} catch (ActivityNotFoundException e) {
Slog.w(TAG, "No activity to handle assist action.", e);
}
diff --git a/services/common_time/common_time_server.cpp b/services/common_time/common_time_server.cpp
index 17f99b9..21e706f 100644
--- a/services/common_time/common_time_server.cpp
+++ b/services/common_time/common_time_server.cpp
@@ -53,9 +53,9 @@
namespace android {
-const char* CommonTimeServer::kDefaultMasterElectionAddr = "239.195.128.88";
-const uint16_t CommonTimeServer::kDefaultMasterElectionPort = 8887;
-const uint64_t CommonTimeServer::kDefaultSyncGroupID = 0;
+const char* CommonTimeServer::kDefaultMasterElectionAddr = "255.255.255.255";
+const uint16_t CommonTimeServer::kDefaultMasterElectionPort = 8886;
+const uint64_t CommonTimeServer::kDefaultSyncGroupID = 1;
const uint8_t CommonTimeServer::kDefaultMasterPriority = 1;
const uint32_t CommonTimeServer::kDefaultMasterAnnounceIntervalMs = 10000;
const uint32_t CommonTimeServer::kDefaultSyncRequestIntervalMs = 1000;
@@ -752,6 +752,9 @@ bool CommonTimeServer::handleTimeoutWaitForElection() {
bool CommonTimeServer::handleWhoIsMasterRequest(
const WhoIsMasterRequestPacket* request,
const sockaddr_storage& srcAddr) {
+ // Skip our own messages which come back via broadcast loopback.
+ if (request->senderDeviceID == mDeviceID)
+ return true;
char srcEPStr[64];
sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
@@ -829,6 +832,10 @@ bool CommonTimeServer::handleWhoIsMasterRequest(
bool CommonTimeServer::handleWhoIsMasterResponse(
const WhoIsMasterResponsePacket* response,
const sockaddr_storage& srcAddr) {
+ // Skip our own messages which come back via broadcast loopback.
+ if (response->deviceID == mDeviceID)
+ return true;
+
char srcEPStr[64];
sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
mElectionLog.log("RXed WhoIs master response while in state %s. "
@@ -996,6 +1003,10 @@ bool CommonTimeServer::handleMasterAnnouncement(
uint8_t newDevicePrio = packet->devicePriority;
uint64_t newTimelineID = packet->timelineID;
+ // Skip our own messages which come back via broadcast loopback.
+ if (newDeviceID == mDeviceID)
+ return true;
+
char srcEPStr[64];
sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
mElectionLog.log("RXed master announcement while in state %s. "
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 38f4554..8e341df 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -177,7 +177,7 @@ class AppWidgetService extends IAppWidgetService.Stub
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- onUserRemoved(intent.getIntExtra(Intent.EXTRA_USERID, -1));
+ onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1));
}
}, userFilter);
}
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index 5250dfc..539e561 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -499,7 +499,7 @@ class AppWidgetServiceImpl {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DELETED);
intent.setComponent(p.info.provider);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id.appWidgetId);
- mContext.sendBroadcastToUser(intent, mUserId);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
if (p.instances.size() == 0) {
// cancel the future updates
cancelBroadcasts(p);
@@ -507,7 +507,7 @@ class AppWidgetServiceImpl {
// send the broacast saying that the provider is not in use any more
intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DISABLED);
intent.setComponent(p.info.provider);
- mContext.sendBroadcastToUser(intent, mUserId);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
}
}
}
@@ -880,7 +880,7 @@ class AppWidgetServiceImpl {
intent.setComponent(p.info.provider);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id.appWidgetId);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
- mContext.sendBroadcastToUser(intent, mUserId);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
}
}
@@ -1205,7 +1205,7 @@ class AppWidgetServiceImpl {
void sendEnableIntentLocked(Provider p) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_ENABLED);
intent.setComponent(p.info.provider);
- mContext.sendBroadcastToUser(intent, mUserId);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
}
void sendUpdateIntentLocked(Provider p, int[] appWidgetIds) {
@@ -1213,7 +1213,7 @@ class AppWidgetServiceImpl {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
intent.setComponent(p.info.provider);
- mContext.sendBroadcastToUser(intent, mUserId);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
}
}
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index 0a6f23c..6ae16a4 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -93,6 +93,7 @@ public class BatteryService extends Binder {
private boolean mAcOnline;
private boolean mUsbOnline;
+ private boolean mWirelessOnline;
private int mBatteryStatus;
private int mBatteryHealth;
private boolean mBatteryPresent;
@@ -150,7 +151,8 @@ public class BatteryService extends Binder {
public final boolean isPowered() {
// assume we are powered if battery state is unknown so the "stay on while plugged in" option will work.
- return (mAcOnline || mUsbOnline || mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN);
+ return (mAcOnline || mUsbOnline || mWirelessOnline
+ || mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN);
}
public final boolean isPowered(int plugTypeSet) {
@@ -169,6 +171,9 @@ public class BatteryService extends Binder {
if (mUsbOnline) {
plugTypeBit |= BatteryManager.BATTERY_PLUGGED_USB;
}
+ if (mWirelessOnline) {
+ plugTypeBit |= BatteryManager.BATTERY_PLUGGED_WIRELESS;
+ }
return (plugTypeSet & plugTypeBit) != 0;
}
@@ -243,6 +248,8 @@ public class BatteryService extends Binder {
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
} else if (mUsbOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
+ } else if (mWirelessOnline) {
+ mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
} else {
mPlugType = BATTERY_PLUGGED_NONE;
}
@@ -398,6 +405,7 @@ public class BatteryService extends Binder {
" temperature: " + mBatteryTemperature +
" technology: " + mBatteryTechnology +
" AC powered:" + mAcOnline + " USB powered:" + mUsbOnline +
+ " Wireless powered:" + mWirelessOnline +
" icon:" + icon + " invalid charger:" + mInvalidCharger);
}
@@ -503,6 +511,7 @@ public class BatteryService extends Binder {
pw.println("Current Battery Service state:");
pw.println(" AC powered: " + mAcOnline);
pw.println(" USB powered: " + mUsbOnline);
+ pw.println(" Wireless powered: " + mWirelessOnline);
pw.println(" status: " + mBatteryStatus);
pw.println(" health: " + mBatteryHealth);
pw.println(" present: " + mBatteryPresent);
@@ -523,6 +532,8 @@ public class BatteryService extends Binder {
mAcOnline = Integer.parseInt(value) != 0;
} else if ("usb".equals(key)) {
mUsbOnline = Integer.parseInt(value) != 0;
+ } else if ("wireless".equals(key)) {
+ mWirelessOnline = Integer.parseInt(value) != 0;
} else if ("status".equals(key)) {
mBatteryStatus = Integer.parseInt(value);
} else if ("level".equals(key)) {
@@ -603,4 +614,3 @@ public class BatteryService extends Binder {
}
}
}
-
diff --git a/services/java/com/android/server/ClipboardService.java b/services/java/com/android/server/ClipboardService.java
index baf33a9..0bf7aad 100644
--- a/services/java/com/android/server/ClipboardService.java
+++ b/services/java/com/android/server/ClipboardService.java
@@ -96,7 +96,7 @@ public class ClipboardService extends IClipboard.Stub {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_USER_REMOVED.equals(action)) {
- removeClipboard(intent.getIntExtra(Intent.EXTRA_USERID, 0));
+ removeClipboard(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
}
}
}, userFilter);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 375ba68..cb6ce4b 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -2592,6 +2592,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
// @see bug/4455071
handleConnectivityChange(info.getType(), false);
break;
+ case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED:
+ info = (NetworkInfo) msg.obj;
+ type = info.getType();
+ updateNetworkSettings(mNetTrackers[type]);
+ break;
}
}
}
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 8bdd7be..ef09b01 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -18,10 +18,6 @@ package com.android.server;
import static android.provider.Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK;
-import com.android.server.power.PowerManagerService;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -30,6 +26,7 @@ import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -47,7 +44,7 @@ import java.io.FileReader;
/**
* <p>DockObserver monitors for a docking station.
*/
-class DockObserver extends UEventObserver {
+final class DockObserver extends UEventObserver {
private static final String TAG = DockObserver.class.getSimpleName();
private static final boolean LOG = false;
@@ -56,7 +53,9 @@ class DockObserver extends UEventObserver {
private static final int DEFAULT_DOCK = 1;
- private static final int MSG_DOCK_STATE = 0;
+ private static final int MSG_DOCK_STATE_CHANGED = 0;
+
+ private final Object mLock = new Object();
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
private int mPreviousDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
@@ -78,7 +77,7 @@ class DockObserver extends UEventObserver {
Slog.v(TAG, "Dock UEVENT: " + event.toString());
}
- synchronized (this) {
+ synchronized (mLock) {
try {
int newState = Integer.parseInt(event.get("SWITCH_STATE"));
if (newState != mDockState) {
@@ -96,7 +95,7 @@ class DockObserver extends UEventObserver {
(PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
pm.wakeUp(SystemClock.uptimeMillis());
}
- update();
+ updateLocked();
}
}
} catch (NumberFormatException e) {
@@ -105,132 +104,142 @@ class DockObserver extends UEventObserver {
}
}
- private final void init() {
- char[] buffer = new char[1024];
-
- try {
- FileReader file = new FileReader(DOCK_STATE_PATH);
- int len = file.read(buffer, 0, 1024);
- file.close();
- mPreviousDockState = mDockState = Integer.valueOf((new String(buffer, 0, len)).trim());
- } catch (FileNotFoundException e) {
- Slog.w(TAG, "This kernel does not have dock station support");
- } catch (Exception e) {
- Slog.e(TAG, "" , e);
+ private void init() {
+ synchronized (mLock) {
+ try {
+ char[] buffer = new char[1024];
+ FileReader file = new FileReader(DOCK_STATE_PATH);
+ try {
+ int len = file.read(buffer, 0, 1024);
+ mDockState = Integer.valueOf((new String(buffer, 0, len)).trim());
+ mPreviousDockState = mDockState;
+ } finally {
+ file.close();
+ }
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, "This kernel does not have dock station support");
+ } catch (Exception e) {
+ Slog.e(TAG, "" , e);
+ }
}
}
void systemReady() {
- synchronized (this) {
+ synchronized (mLock) {
// don't bother broadcasting undocked here
if (mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
- update();
+ updateLocked();
}
mSystemReady = true;
}
}
- private final void update() {
- mHandler.sendEmptyMessage(MSG_DOCK_STATE);
+ private void updateLocked() {
+ mHandler.sendEmptyMessage(MSG_DOCK_STATE_CHANGED);
}
- private static boolean isScreenSaverActivatedOnDock(Context context) {
- return 0 != Settings.Secure.getInt(
- context.getContentResolver(), SCREENSAVER_ACTIVATE_ON_DOCK, DEFAULT_DOCK);
- }
+ private void handleDockStateChange() {
+ synchronized (mLock) {
+ Slog.i(TAG, "Dock state changed: " + mDockState);
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_DOCK_STATE:
- synchronized (this) {
- Slog.i(TAG, "Dock state changed: " + mDockState);
+ final ContentResolver cr = mContext.getContentResolver();
- final ContentResolver cr = mContext.getContentResolver();
+ if (Settings.Secure.getInt(cr,
+ Settings.Secure.DEVICE_PROVISIONED, 0) == 0) {
+ Slog.i(TAG, "Device not provisioned, skipping dock broadcast");
+ return;
+ }
- if (Settings.Secure.getInt(cr,
- Settings.Secure.DEVICE_PROVISIONED, 0) == 0) {
- Slog.i(TAG, "Device not provisioned, skipping dock broadcast");
- return;
- }
- // Pack up the values and broadcast them to everyone
- Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
-
- // Check if this is Bluetooth Dock
- // TODO(BT): Get Dock address.
- String address = null;
- if (address != null)
- intent.putExtra(BluetoothDevice.EXTRA_DEVICE,
- BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address));
-
- // User feedback to confirm dock connection. Particularly
- // useful for flaky contact pins...
- if (Settings.System.getInt(cr,
- Settings.System.DOCK_SOUNDS_ENABLED, 1) == 1)
- {
- String whichSound = null;
- if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
- if ((mPreviousDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
- (mPreviousDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
- (mPreviousDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
- whichSound = Settings.System.DESK_UNDOCK_SOUND;
- } else if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_CAR) {
- whichSound = Settings.System.CAR_UNDOCK_SOUND;
- }
- } else {
- if ((mDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
- (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
- (mDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
- whichSound = Settings.System.DESK_DOCK_SOUND;
- } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
- whichSound = Settings.System.CAR_DOCK_SOUND;
- }
- }
+ // Pack up the values and broadcast them to everyone
+ Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
+
+ // Check if this is Bluetooth Dock
+ // TODO(BT): Get Dock address.
+ // String address = null;
+ // if (address != null) {
+ // intent.putExtra(BluetoothDevice.EXTRA_DEVICE,
+ // BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address));
+ // }
+
+ // User feedback to confirm dock connection. Particularly
+ // useful for flaky contact pins...
+ if (Settings.System.getInt(cr,
+ Settings.System.DOCK_SOUNDS_ENABLED, 1) == 1) {
+ String whichSound = null;
+ if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
+ if ((mPreviousDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
+ (mPreviousDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
+ (mPreviousDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
+ whichSound = Settings.System.DESK_UNDOCK_SOUND;
+ } else if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+ whichSound = Settings.System.CAR_UNDOCK_SOUND;
+ }
+ } else {
+ if ((mDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
+ (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
+ (mDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
+ whichSound = Settings.System.DESK_DOCK_SOUND;
+ } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+ whichSound = Settings.System.CAR_DOCK_SOUND;
+ }
+ }
- if (whichSound != null) {
- final String soundPath = Settings.System.getString(cr, whichSound);
- if (soundPath != null) {
- final Uri soundUri = Uri.parse("file://" + soundPath);
- if (soundUri != null) {
- final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
- if (sfx != null) {
- sfx.setStreamType(AudioManager.STREAM_SYSTEM);
- sfx.play();
- }
- }
- }
+ if (whichSound != null) {
+ final String soundPath = Settings.System.getString(cr, whichSound);
+ if (soundPath != null) {
+ final Uri soundUri = Uri.parse("file://" + soundPath);
+ if (soundUri != null) {
+ final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
+ if (sfx != null) {
+ sfx.setStreamType(AudioManager.STREAM_SYSTEM);
+ sfx.play();
}
}
+ }
+ }
+ }
- IDreamManager mgr = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams"));
- if (mgr != null) {
- // dreams feature enabled
- boolean undocked = mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED;
- if (undocked) {
- try {
- if (mgr.isDreaming()) {
- mgr.awaken();
- }
- } catch (RemoteException e) {
- Slog.w(TAG, "Unable to awaken!", e);
- }
- } else {
- if (isScreenSaverActivatedOnDock(mContext)) {
- try {
- mgr.dream();
- } catch (RemoteException e) {
- Slog.w(TAG, "Unable to dream!", e);
- }
- }
- }
- } else {
- // dreams feature not enabled, send legacy intent
- mContext.sendStickyBroadcast(intent);
+ IDreamManager mgr = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams"));
+ if (mgr != null) {
+ // dreams feature enabled
+ boolean undocked = mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED;
+ if (undocked) {
+ try {
+ if (mgr.isDreaming()) {
+ mgr.awaken();
}
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Unable to awaken!", e);
}
+ } else {
+ if (isScreenSaverActivatedOnDock(mContext)) {
+ try {
+ mgr.dream();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Unable to dream!", e);
+ }
+ }
+ }
+ } else {
+ // dreams feature not enabled, send legacy intent
+ mContext.sendStickyBroadcast(intent);
+ }
+ }
+ }
+
+ private static boolean isScreenSaverActivatedOnDock(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ SCREENSAVER_ACTIVATE_ON_DOCK, DEFAULT_DOCK) != 0;
+ }
+
+ private final Handler mHandler = new Handler(Looper.myLooper(), null, true) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_DOCK_STATE_CHANGED:
+ handleDockStateChange();
break;
}
}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index e219e8d..23b2706 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -47,7 +47,6 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
-import android.os.Parcelable;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
@@ -64,6 +63,8 @@ import com.android.internal.location.ProviderRequest;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
import com.android.server.location.GpsLocationProvider;
+import com.android.server.location.LocationBlacklist;
+import com.android.server.location.LocationFudger;
import com.android.server.location.LocationProviderInterface;
import com.android.server.location.LocationProviderProxy;
import com.android.server.location.MockProvider;
@@ -110,19 +111,6 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
private static final int MSG_LOCATION_CHANGED = 1;
- // Accuracy in meters above which a location is considered coarse
- private static final double COARSE_ACCURACY_M = 100.0;
- private static final String EXTRA_COARSE_LOCATION = "coarseLocation";
-
- private static final int APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR = 111000;
-
- /**
- * Maximum latitude of 1 meter from the pole.
- * This keeps cosine(MAX_LATITUDE) to a non-zero value;
- */
- private static final double MAX_LATITUDE =
- 90.0 - (1.0 / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR);
-
// Location Providers may sometimes deliver location updates
// slightly faster that requested - provide grace period so
// we don't unnecessarily filter events that are otherwise on
@@ -137,6 +125,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
private final Object mLock = new Object();
// --- fields below are final after init() ---
+ private LocationFudger mLocationFudger;
private GeofenceManager mGeofenceManager;
private PowerManager.WakeLock mWakeLock;
private PackageManager mPackageManager;
@@ -144,8 +133,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
private IGpsStatusProvider mGpsStatusProvider;
private INetInitiatedListener mNetInitiatedListener;
private LocationWorkerHandler mLocationHandler;
- // track the passive provider for some special cases
- private PassiveProvider mPassiveProvider;
+ private PassiveProvider mPassiveProvider; // track passive provider for special cases
+ private LocationBlacklist mBlacklist;
// --- fields below are protected by mWakeLock ---
private int mPendingBroadcasts;
@@ -220,7 +209,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
synchronized (mLock) {
loadProvidersLocked();
}
- mGeofenceManager = new GeofenceManager(mContext);
+ mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
+ mBlacklist.init();
+ mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
+ mLocationFudger = new LocationFudger();
// Register for Network (Wifi or Mobile) updates
IntentFilter filter = new IntentFilter();
@@ -907,7 +899,25 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
String perm = checkPermission();
if (ACCESS_COARSE_LOCATION.equals(perm)) {
- request.applyCoarsePermissionRestrictions();
+ switch (request.getQuality()) {
+ case LocationRequest.ACCURACY_FINE:
+ request.setQuality(LocationRequest.ACCURACY_BLOCK);
+ break;
+ case LocationRequest.POWER_HIGH:
+ request.setQuality(LocationRequest.POWER_LOW);
+ break;
+ }
+ // throttle
+ if (request.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
+ request.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
+ }
+ if (request.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
+ request.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
+ }
+ }
+ // make getFastestInterval() the minimum of interval and fastest interval
+ if (request.getFastestInterval() > request.getInterval()) {
+ request.setFastestInterval(request.getInterval());
}
return perm;
}
@@ -958,7 +968,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
final int uid = Binder.getCallingUid();
Receiver recevier = checkListenerOrIntent(listener, intent, pid, uid, packageName);
- // so wakelock calls will succeed (not totally sure this is still needed)
+ // providers may use public location API's, need to clear identity
long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -1008,7 +1018,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
final int uid = Binder.getCallingUid();
Receiver receiver = checkListenerOrIntent(listener, intent, pid, uid, packageName);
- // so wakelock calls will succeed (not totally sure this is still needed)
+ // providers may use public location API's, need to clear identity
long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -1056,10 +1066,17 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
}
@Override
- public Location getLastLocation(LocationRequest request) {
+ public Location getLastLocation(LocationRequest request, String packageName) {
if (D) Log.d(TAG, "getLastLocation: " + request);
if (request == null) request = DEFAULT_LOCATION_REQUEST;
String perm = checkPermissionAndRequest(request);
+ checkPackageName(packageName);
+
+ if (mBlacklist.isBlacklisted(packageName)) {
+ if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
+ packageName);
+ return null;
+ }
synchronized (mLock) {
// Figure out the provider. Either its explicitly request (deprecated API's),
@@ -1075,7 +1092,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
if (ACCESS_FINE_LOCATION.equals(perm)) {
return location;
} else {
- return getCoarseLocationExtra(location);
+ return mLocationFudger.getOrCreate(location);
}
}
}
@@ -1090,7 +1107,14 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
if (D) Log.d(TAG, "requestGeofence: " + request + " " + geofence + " " + intent);
- mGeofenceManager.addFence(request, geofence, intent, Binder.getCallingUid(), packageName);
+ // geo-fence manager uses the public location API, need to clear identity
+ int uid = Binder.getCallingUid();
+ long identity = Binder.clearCallingIdentity();
+ try {
+ mGeofenceManager.addFence(request, geofence, intent, uid, packageName);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
@Override
@@ -1101,7 +1125,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
- mGeofenceManager.removeFence(geofence, intent);
+ // geo-fence manager uses the public location API, need to clear identity
+ long identity = Binder.clearCallingIdentity();
+ try {
+ mGeofenceManager.removeFence(geofence, intent);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
@@ -1283,6 +1313,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
}
private void handleLocationChangedLocked(Location location, boolean passive) {
+ if (D) Log.d(TAG, "incoming location: " + location);
+
long now = SystemClock.elapsedRealtime();
String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
@@ -1291,11 +1323,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) return;
- // Add the coarse location as an extra, if not already present
- Location coarse = getCoarseLocationExtra(location);
- if (coarse == null) {
- coarse = addCoarseLocationExtra(location);
- }
+ // Add the coarse location as an extra
+ Location coarse = mLocationFudger.getOrCreate(location);
// Update last known locations
Location lastLocation = mLastLocation.get(provider);
@@ -1319,6 +1348,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
for (UpdateRecord r : records) {
Receiver receiver = r.mReceiver;
boolean receiverDead = false;
+
+ if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
+ if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
+ receiver.mPackageName);
+ continue;
+ }
+
if (ACCESS_FINE_LOCATION.equals(receiver.mPermission)) {
location = lastLocation; // use fine location
} else {
@@ -1530,7 +1566,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
MockProvider provider = new MockProvider(name, this, properties);
// remove the real provider if we are replacing GPS or network provider
if (LocationManager.GPS_PROVIDER.equals(name)
- || LocationManager.NETWORK_PROVIDER.equals(name)) {
+ || LocationManager.NETWORK_PROVIDER.equals(name)
+ || LocationManager.FUSED_PROVIDER.equals(name)) {
LocationProviderInterface p = mProvidersByName.get(name);
if (p != null) {
removeProviderLocked(p);
@@ -1660,106 +1697,6 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
}
}
- private static double wrapLatitude(double lat) {
- if (lat > MAX_LATITUDE) lat = MAX_LATITUDE;
- if (lat < -MAX_LATITUDE) lat = -MAX_LATITUDE;
- return lat;
- }
-
- private static double wrapLongitude(double lon) {
- if (lon >= 180.0) lon -= 360.0;
- if (lon < -180.0) lon += 360.0;
- return lon;
- }
-
- private static double distanceToDegreesLatitude(double distance) {
- return distance / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR;
- }
-
- /**
- * Requires latitude since longitudinal distances change with distance from equator.
- */
- private static double distanceToDegreesLongitude(double distance, double lat) {
- return distance / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR / Math.cos(lat);
- }
-
- /**
- * Fudge a location into a coarse location.
- * <p>Add a random offset, then quantize the result (snap-to-grid).
- * Random offsets alone can be low-passed pretty easily.
- * Snap-to-grid on its own is excellent unless you are sitting on a
- * grid boundary and bouncing between quantizations.
- * The combination is quite hard to reverse engineer.
- * <p>The random offset used is smaller than the goal accuracy
- * ({@link #COARSE_ACCURACY_M}), in order to give relatively stable
- * results after quantization.
- */
- private static Location createCoarse(Location fine) {
- Location coarse = new Location(fine);
-
- coarse.removeBearing();
- coarse.removeSpeed();
- coarse.removeAltitude();
-
- double lat = coarse.getLatitude();
- double lon = coarse.getLongitude();
-
- // wrap
- lat = wrapLatitude(lat);
- lon = wrapLongitude(lon);
-
- if (coarse.getAccuracy() < COARSE_ACCURACY_M / 2) {
- // apply a random offset
- double fudgeDistance = COARSE_ACCURACY_M / 2.0 - coarse.getAccuracy();
- lat += (Math.random() - 0.5) * distanceToDegreesLatitude(fudgeDistance);
- lon += (Math.random() - 0.5) * distanceToDegreesLongitude(fudgeDistance, lat);
- }
-
- // wrap
- lat = wrapLatitude(lat);
- lon = wrapLongitude(lon);
-
- // quantize (snap-to-grid)
- double latGranularity = distanceToDegreesLatitude(COARSE_ACCURACY_M);
- double lonGranularity = distanceToDegreesLongitude(COARSE_ACCURACY_M, lat);
- long latQuantized = Math.round(lat / latGranularity);
- long lonQuantized = Math.round(lon / lonGranularity);
- lat = latQuantized * latGranularity;
- lon = lonQuantized * lonGranularity;
-
- // wrap again
- lat = wrapLatitude(lat);
- lon = wrapLongitude(lon);
-
- // apply
- coarse.setLatitude(lat);
- coarse.setLongitude(lon);
- coarse.setAccuracy((float)COARSE_ACCURACY_M);
-
- return coarse;
- }
-
-
- private static Location getCoarseLocationExtra(Location location) {
- Bundle extras = location.getExtras();
- if (extras == null) return null;
- Parcelable parcel = extras.getParcelable(EXTRA_COARSE_LOCATION);
- if (parcel == null) return null;
- if (!(parcel instanceof Location)) return null;
- Location coarse = (Location) parcel;
- if (coarse.getAccuracy() < COARSE_ACCURACY_M) return null;
- return coarse;
- }
-
- private static Location addCoarseLocationExtra(Location location) {
- Bundle extras = location.getExtras();
- if (extras == null) extras = new Bundle();
- Location coarse = createCoarse(location);
- extras.putParcelable(EXTRA_COARSE_LOCATION, coarse);
- location.setExtras(extras);
- return coarse;
- }
-
private void log(String log) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Slog.d(TAG, log);
@@ -1810,8 +1747,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
for (String i : mDisabledProviders) {
pw.println(" " + i);
}
-
}
+ pw.append(" ");
+ mBlacklist.dump(pw);
if (mMockProviders.size() > 0) {
pw.println(" Mock Providers:");
for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
@@ -1819,6 +1757,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
}
}
+ pw.append(" fudger: ");
+ mLocationFudger.dump(fd, pw, args);
+
if (args.length > 0 && "short".equals(args[0])) {
return;
}
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index a565d08..d6fed39 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -1272,7 +1272,7 @@ public class NotificationManagerService extends INotificationManager.Stub
void checkCallerIsSystem() {
int uid = Binder.getCallingUid();
- if (uid == Process.SYSTEM_UID || uid == 0) {
+ if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
return;
}
throw new SecurityException("Disallowed call for uid " + uid);
@@ -1280,7 +1280,7 @@ public class NotificationManagerService extends INotificationManager.Stub
void checkCallerIsSystemOrSameApp(String pkg) {
int uid = Binder.getCallingUid();
- if (uid == Process.SYSTEM_UID || uid == 0) {
+ if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
return;
}
try {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c471dd2..a117b06 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -155,13 +155,12 @@ class ServerThread extends Thread {
power = new PowerManagerService();
ServiceManager.addService(Context.POWER_SERVICE, power);
- Slog.i(TAG, "Display Manager");
- display = new DisplayManagerService();
- ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
-
Slog.i(TAG, "Activity Manager");
context = ActivityManagerService.main(factoryTest);
- display.setContext(context);
+
+ Slog.i(TAG, "Display Manager");
+ display = new DisplayManagerService(context);
+ ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
Slog.i(TAG, "Telephony Registry");
ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index c5243a2..afd7d0e 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -45,6 +45,7 @@ import android.os.RemoteException;
import android.os.FileObserver;
import android.os.ParcelFileDescriptor;
import android.os.RemoteCallbackList;
+import android.os.SELinux;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -422,9 +423,9 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- switchUser(intent.getIntExtra(Intent.EXTRA_USERID, 0));
+ switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
- removeUser(intent.getIntExtra(Intent.EXTRA_USERID, 0));
+ removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
}
}
}, userFilter);
@@ -639,8 +640,12 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
-1, -1);
}
- ParcelFileDescriptor fd = ParcelFileDescriptor.open(new File(dir, WALLPAPER),
+ File file = new File(dir, WALLPAPER);
+ ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
MODE_CREATE|MODE_READ_WRITE);
+ if (!SELinux.restorecon(file)) {
+ return null;
+ }
wallpaper.name = name;
return fd;
} catch (FileNotFoundException e) {
@@ -763,10 +768,6 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
intent.setComponent(componentName);
int serviceUserId = wallpaper.userId;
- // Because the image wallpaper is running in the system ui
- if (componentName.equals(wallpaper.imageWallpaperComponent)) {
- serviceUserId = 0;
- }
intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
com.android.internal.R.string.wallpaper_binding_label);
intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java
index 96ac493..56c0fdf 100644
--- a/services/java/com/android/server/WiredAccessoryObserver.java
+++ b/services/java/com/android/server/WiredAccessoryObserver.java
@@ -16,12 +16,12 @@
package com.android.server;
-import android.app.ActivityManagerNative;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
@@ -39,7 +39,7 @@ import java.util.List;
/**
* <p>WiredAccessoryObserver monitors for a wired headset on the main board or dock.
*/
-class WiredAccessoryObserver extends UEventObserver {
+final class WiredAccessoryObserver extends UEventObserver {
private static final String TAG = WiredAccessoryObserver.class.getSimpleName();
private static final boolean LOG = true;
private static final int BIT_HEADSET = (1 << 0);
@@ -50,122 +50,32 @@ class WiredAccessoryObserver extends UEventObserver {
private static final int SUPPORTED_HEADSETS = (BIT_HEADSET|BIT_HEADSET_NO_MIC|
BIT_USB_HEADSET_ANLG|BIT_USB_HEADSET_DGTL|
BIT_HDMI_AUDIO);
- private static final int HEADSETS_WITH_MIC = BIT_HEADSET;
- private static class UEventInfo {
- private final String mDevName;
- private final int mState1Bits;
- private final int mState2Bits;
-
- public UEventInfo(String devName, int state1Bits, int state2Bits) {
- mDevName = devName;
- mState1Bits = state1Bits;
- mState2Bits = state2Bits;
- }
-
- public String getDevName() { return mDevName; }
-
- public String getDevPath() {
- return String.format("/devices/virtual/switch/%s", mDevName);
- }
-
- public String getSwitchStatePath() {
- return String.format("/sys/class/switch/%s/state", mDevName);
- }
-
- public boolean checkSwitchExists() {
- File f = new File(getSwitchStatePath());
- return ((null != f) && f.exists());
- }
-
- public int computeNewHeadsetState(int headsetState, int switchState) {
- int preserveMask = ~(mState1Bits | mState2Bits);
- int setBits = ((switchState == 1) ? mState1Bits :
- ((switchState == 2) ? mState2Bits : 0));
-
- return ((headsetState & preserveMask) | setBits);
- }
- }
-
- private static List<UEventInfo> makeObservedUEventList() {
- List<UEventInfo> retVal = new ArrayList<UEventInfo>();
- UEventInfo uei;
-
- // Monitor h2w
- uei = new UEventInfo("h2w", BIT_HEADSET, BIT_HEADSET_NO_MIC);
- if (uei.checkSwitchExists()) {
- retVal.add(uei);
- } else {
- Slog.w(TAG, "This kernel does not have wired headset support");
- }
-
- // Monitor USB
- uei = new UEventInfo("usb_audio", BIT_USB_HEADSET_ANLG, BIT_USB_HEADSET_DGTL);
- if (uei.checkSwitchExists()) {
- retVal.add(uei);
- } else {
- Slog.w(TAG, "This kernel does not have usb audio support");
- }
+ private final Object mLock = new Object();
- // Monitor HDMI
- //
- // If the kernel has support for the "hdmi_audio" switch, use that. It will be signalled
- // only when the HDMI driver has a video mode configured, and the downstream sink indicates
- // support for audio in its EDID.
- //
- // If the kernel does not have an "hdmi_audio" switch, just fall back on the older "hdmi"
- // switch instead.
- uei = new UEventInfo("hdmi_audio", BIT_HDMI_AUDIO, 0);
- if (uei.checkSwitchExists()) {
- retVal.add(uei);
- } else {
- uei = new UEventInfo("hdmi", BIT_HDMI_AUDIO, 0);
- if (uei.checkSwitchExists()) {
- retVal.add(uei);
- } else {
- Slog.w(TAG, "This kernel does not have HDMI audio support");
- }
- }
-
- return retVal;
- }
-
- private static List<UEventInfo> uEventInfo = makeObservedUEventList();
+ private final Context mContext;
+ private final WakeLock mWakeLock; // held while there is a pending route change
+ private final AudioManager mAudioManager;
+ private final List<UEventInfo> mUEventInfo;
private int mHeadsetState;
private int mPrevHeadsetState;
private String mHeadsetName;
- private final Context mContext;
- private final WakeLock mWakeLock; // held while there is a pending route change
-
- private final AudioManager mAudioManager;
-
public WiredAccessoryObserver(Context context) {
mContext = context;
+
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryObserver");
mWakeLock.setReferenceCounted(false);
mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
+ mUEventInfo = makeObservedUEventList();
+
context.registerReceiver(new BootCompletedReceiver(),
new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
}
- private final class BootCompletedReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- // At any given time accessories could be inserted
- // one on the board, one on the dock and one on HDMI:
- // observe three UEVENTs
- init(); // set initial status
- for (int i = 0; i < uEventInfo.size(); ++i) {
- UEventInfo uei = uEventInfo.get(i);
- startObserving("DEVPATH="+uei.getDevPath());
- }
- }
- }
-
@Override
public void onUEvent(UEventObserver.UEvent event) {
if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString());
@@ -174,56 +84,64 @@ class WiredAccessoryObserver extends UEventObserver {
String devPath = event.get("DEVPATH");
String name = event.get("SWITCH_NAME");
int state = Integer.parseInt(event.get("SWITCH_STATE"));
- updateState(devPath, name, state);
+ synchronized (mLock) {
+ updateStateLocked(devPath, name, state);
+ }
} catch (NumberFormatException e) {
Slog.e(TAG, "Could not parse switch state from event " + event);
}
}
- private synchronized final void updateState(String devPath, String name, int state)
- {
- for (int i = 0; i < uEventInfo.size(); ++i) {
- UEventInfo uei = uEventInfo.get(i);
- if (devPath.equals(uei.getDevPath())) {
- update(name, uei.computeNewHeadsetState(mHeadsetState, state));
- return;
+ private void bootCompleted() {
+ synchronized (mLock) {
+ char[] buffer = new char[1024];
+ mPrevHeadsetState = mHeadsetState;
+
+ if (LOG) Slog.v(TAG, "init()");
+
+ for (int i = 0; i < mUEventInfo.size(); ++i) {
+ UEventInfo uei = mUEventInfo.get(i);
+ try {
+ int curState;
+ FileReader file = new FileReader(uei.getSwitchStatePath());
+ int len = file.read(buffer, 0, 1024);
+ file.close();
+ curState = Integer.valueOf((new String(buffer, 0, len)).trim());
+
+ if (curState > 0) {
+ updateStateLocked(uei.getDevPath(), uei.getDevName(), curState);
+ }
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, uei.getSwitchStatePath() +
+ " not found while attempting to determine initial switch state");
+ } catch (Exception e) {
+ Slog.e(TAG, "" , e);
+ }
}
}
- }
-
- private synchronized final void init() {
- char[] buffer = new char[1024];
- mPrevHeadsetState = mHeadsetState;
-
- if (LOG) Slog.v(TAG, "init()");
- for (int i = 0; i < uEventInfo.size(); ++i) {
- UEventInfo uei = uEventInfo.get(i);
- try {
- int curState;
- FileReader file = new FileReader(uei.getSwitchStatePath());
- int len = file.read(buffer, 0, 1024);
- file.close();
- curState = Integer.valueOf((new String(buffer, 0, len)).trim());
-
- if (curState > 0) {
- updateState(uei.getDevPath(), uei.getDevName(), curState);
- }
+ // At any given time accessories could be inserted
+ // one on the board, one on the dock and one on HDMI:
+ // observe three UEVENTs
+ for (int i = 0; i < mUEventInfo.size(); ++i) {
+ UEventInfo uei = mUEventInfo.get(i);
+ startObserving("DEVPATH="+uei.getDevPath());
+ }
+ }
- } catch (FileNotFoundException e) {
- Slog.w(TAG, uei.getSwitchStatePath() +
- " not found while attempting to determine initial switch state");
- } catch (Exception e) {
- Slog.e(TAG, "" , e);
+ private void updateStateLocked(String devPath, String name, int state) {
+ for (int i = 0; i < mUEventInfo.size(); ++i) {
+ UEventInfo uei = mUEventInfo.get(i);
+ if (devPath.equals(uei.getDevPath())) {
+ updateLocked(name, uei.computeNewHeadsetState(mHeadsetState, state));
+ return;
}
}
}
- private synchronized final void update(String newName, int newState) {
+ private void updateLocked(String newName, int newState) {
// Retain only relevant bits
int headsetState = newState & SUPPORTED_HEADSETS;
- int newOrOld = headsetState | mHeadsetState;
- int delay = 0;
int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG;
int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL;
int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC);
@@ -254,28 +172,26 @@ class WiredAccessoryObserver extends UEventObserver {
mHeadsetState = headsetState;
mWakeLock.acquire();
- mHandler.sendMessage(mHandler.obtainMessage(0,
- mHeadsetState,
- mPrevHeadsetState,
- mHeadsetName));
+
+ Message msg = mHandler.obtainMessage(0, mHeadsetState, mPrevHeadsetState, mHeadsetName);
+ mHandler.sendMessage(msg);
}
- private synchronized final void setDevicesState(int headsetState,
- int prevHeadsetState,
- String headsetName) {
- int allHeadsets = SUPPORTED_HEADSETS;
- for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {
- if ((curHeadset & allHeadsets) != 0) {
- setDeviceState(curHeadset, headsetState, prevHeadsetState, headsetName);
- allHeadsets &= ~curHeadset;
+ private void setDevicesState(
+ int headsetState, int prevHeadsetState, String headsetName) {
+ synchronized (mLock) {
+ int allHeadsets = SUPPORTED_HEADSETS;
+ for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {
+ if ((curHeadset & allHeadsets) != 0) {
+ setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName);
+ allHeadsets &= ~curHeadset;
+ }
}
}
}
- private final void setDeviceState(int headset,
- int headsetState,
- int prevHeadsetState,
- String headsetName) {
+ private void setDeviceStateLocked(int headset,
+ int headsetState, int prevHeadsetState, String headsetName) {
if ((headsetState & headset) != (prevHeadsetState & headset)) {
int device;
int state;
@@ -308,11 +224,96 @@ class WiredAccessoryObserver extends UEventObserver {
}
}
- private final Handler mHandler = new Handler() {
+ private static List<UEventInfo> makeObservedUEventList() {
+ List<UEventInfo> retVal = new ArrayList<UEventInfo>();
+ UEventInfo uei;
+
+ // Monitor h2w
+ uei = new UEventInfo("h2w", BIT_HEADSET, BIT_HEADSET_NO_MIC);
+ if (uei.checkSwitchExists()) {
+ retVal.add(uei);
+ } else {
+ Slog.w(TAG, "This kernel does not have wired headset support");
+ }
+
+ // Monitor USB
+ uei = new UEventInfo("usb_audio", BIT_USB_HEADSET_ANLG, BIT_USB_HEADSET_DGTL);
+ if (uei.checkSwitchExists()) {
+ retVal.add(uei);
+ } else {
+ Slog.w(TAG, "This kernel does not have usb audio support");
+ }
+
+ // Monitor HDMI
+ //
+ // If the kernel has support for the "hdmi_audio" switch, use that. It will be signalled
+ // only when the HDMI driver has a video mode configured, and the downstream sink indicates
+ // support for audio in its EDID.
+ //
+ // If the kernel does not have an "hdmi_audio" switch, just fall back on the older "hdmi"
+ // switch instead.
+ uei = new UEventInfo("hdmi_audio", BIT_HDMI_AUDIO, 0);
+ if (uei.checkSwitchExists()) {
+ retVal.add(uei);
+ } else {
+ uei = new UEventInfo("hdmi", BIT_HDMI_AUDIO, 0);
+ if (uei.checkSwitchExists()) {
+ retVal.add(uei);
+ } else {
+ Slog.w(TAG, "This kernel does not have HDMI audio support");
+ }
+ }
+
+ return retVal;
+ }
+
+ private final Handler mHandler = new Handler(Looper.myLooper(), null, true) {
@Override
public void handleMessage(Message msg) {
setDevicesState(msg.arg1, msg.arg2, (String)msg.obj);
mWakeLock.release();
}
};
+
+ private static final class UEventInfo {
+ private final String mDevName;
+ private final int mState1Bits;
+ private final int mState2Bits;
+
+ public UEventInfo(String devName, int state1Bits, int state2Bits) {
+ mDevName = devName;
+ mState1Bits = state1Bits;
+ mState2Bits = state2Bits;
+ }
+
+ public String getDevName() { return mDevName; }
+
+ public String getDevPath() {
+ return String.format("/devices/virtual/switch/%s", mDevName);
+ }
+
+ public String getSwitchStatePath() {
+ return String.format("/sys/class/switch/%s/state", mDevName);
+ }
+
+ public boolean checkSwitchExists() {
+ File f = new File(getSwitchStatePath());
+ return ((null != f) && f.exists());
+ }
+
+ public int computeNewHeadsetState(int headsetState, int switchState) {
+ int preserveMask = ~(mState1Bits | mState2Bits);
+ int setBits = ((switchState == 1) ? mState1Bits :
+ ((switchState == 2) ? mState2Bits : 0));
+
+ return ((headsetState & preserveMask) | setBits);
+ }
+ }
+
+ private final class BootCompletedReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ bootCompleted();
+ }
+ }
}
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index d8ccabb..e222936 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -1725,21 +1725,53 @@ public class ActiveServices {
ArrayList<ActivityManager.RunningServiceInfo> res
= new ArrayList<ActivityManager.RunningServiceInfo>();
- int userId = UserHandle.getUserId(Binder.getCallingUid());
- if (mServiceMap.getAllServices(userId).size() > 0) {
- Iterator<ServiceRecord> it
- = mServiceMap.getAllServices(userId).iterator();
- while (it.hasNext() && res.size() < maxNum) {
- res.add(makeRunningServiceInfoLocked(it.next()));
- }
- }
+ final int uid = Binder.getCallingUid();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (ActivityManager.checkUidPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ uid) == PackageManager.PERMISSION_GRANTED) {
+ List<UserInfo> users = mAm.getUserManager().getUsers();
+ for (int ui=0; ui<users.size() && res.size() < maxNum; ui++) {
+ final UserInfo user = users.get(ui);
+ if (mServiceMap.getAllServices(user.id).size() > 0) {
+ Iterator<ServiceRecord> it = mServiceMap.getAllServices(
+ user.id).iterator();
+ while (it.hasNext() && res.size() < maxNum) {
+ res.add(makeRunningServiceInfoLocked(it.next()));
+ }
+ }
+ }
+
+ for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
+ ServiceRecord r = mRestartingServices.get(i);
+ ActivityManager.RunningServiceInfo info =
+ makeRunningServiceInfoLocked(r);
+ info.restarting = r.nextRestartTime;
+ res.add(info);
+ }
+ } else {
+ int userId = UserHandle.getUserId(uid);
+ if (mServiceMap.getAllServices(userId).size() > 0) {
+ Iterator<ServiceRecord> it
+ = mServiceMap.getAllServices(userId).iterator();
+ while (it.hasNext() && res.size() < maxNum) {
+ res.add(makeRunningServiceInfoLocked(it.next()));
+ }
+ }
- for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
- ServiceRecord r = mRestartingServices.get(i);
- ActivityManager.RunningServiceInfo info =
- makeRunningServiceInfoLocked(r);
- info.restarting = r.nextRestartTime;
- res.add(info);
+ for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
+ ServiceRecord r = mRestartingServices.get(i);
+ if (r.userId == userId) {
+ ActivityManager.RunningServiceInfo info =
+ makeRunningServiceInfoLocked(r);
+ info.restarting = r.nextRestartTime;
+ res.add(info);
+ }
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
return res;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 0eb9983..7f2b69f 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -27,7 +27,6 @@ import com.android.server.ProcessMap;
import com.android.server.SystemServer;
import com.android.server.Watchdog;
import com.android.server.am.ActivityStack.ActivityState;
-import com.android.server.pm.UserManagerService;
import com.android.server.wm.WindowManagerService;
import dalvik.system.Zygote;
@@ -52,7 +51,6 @@ import android.app.Instrumentation;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
-import android.app.Service;
import android.app.backup.IBackupManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
@@ -145,7 +143,6 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -1980,10 +1977,20 @@ public final class ActivityManagerService extends ActivityManagerNative
int uid = app.uid;
int[] gids = null;
+ int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
try {
- gids = mContext.getPackageManager().getPackageGids(
- app.info.packageName);
+ final PackageManager pm = mContext.getPackageManager();
+ gids = pm.getPackageGids(app.info.packageName);
+ if (pm.checkPermission(
+ android.Manifest.permission.READ_EXTERNAL_STORAGE, app.info.packageName)
+ == PERMISSION_GRANTED) {
+ if (Environment.isExternalStorageEmulated()) {
+ mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
+ } else {
+ mountExternal = Zygote.MOUNT_EXTERNAL_SINGLEUSER;
+ }
+ }
} catch (PackageManager.NameNotFoundException e) {
Slog.w(TAG, "Unable to retrieve gids", e);
}
@@ -2025,7 +2032,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
- app.processName, uid, uid, gids, debugFlags,
+ app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, null, null);
BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
@@ -2529,7 +2536,6 @@ public final class ActivityManagerService extends ActivityManagerNative
// This is so super not safe, that only the system (or okay root)
// can do it.
- int userId = Binder.getOrigCallingUser();
final int callingUid = Binder.getCallingUid();
if (callingUid != 0 && callingUid != Process.myUid()) {
throw new SecurityException(
@@ -2538,7 +2544,7 @@ public final class ActivityManagerService extends ActivityManagerNative
int ret = mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags,
- null, null, null, null, options, userId);
+ null, null, null, null, options, UserHandle.getUserId(uid));
return ret;
}
@@ -8382,11 +8388,19 @@ public final class ActivityManagerService extends ActivityManagerNative
// assume our apps are happy - lazy create the list
List<ActivityManager.ProcessErrorStateInfo> errList = null;
+ final boolean allUsers = ActivityManager.checkUidPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ Binder.getCallingUid()) == PackageManager.PERMISSION_GRANTED;
+ int userId = UserHandle.getUserId(Binder.getCallingUid());
+
synchronized (this) {
// iterate across all processes
for (int i=mLruProcesses.size()-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
+ if (!allUsers && app.userId != userId) {
+ continue;
+ }
if ((app.thread != null) && (app.crashing || app.notResponding)) {
// This one's in trouble, so we'll generate a report for it
// crashes are higher priority (in case there's a crash *and* an anr)
@@ -8450,6 +8464,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (app.persistent) {
outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
}
+ if (app.hasActivities) {
+ outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HAS_ACTIVITIES;
+ }
outInfo.lastTrimLevel = app.trimMemoryLevel;
int adj = app.curAdj;
outInfo.importance = oomAdjToImportance(adj, outInfo);
@@ -8460,10 +8477,17 @@ public final class ActivityManagerService extends ActivityManagerNative
enforceNotIsolatedCaller("getRunningAppProcesses");
// Lazy instantiation of list
List<ActivityManager.RunningAppProcessInfo> runList = null;
+ final boolean allUsers = ActivityManager.checkUidPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ Binder.getCallingUid()) == PackageManager.PERMISSION_GRANTED;
+ int userId = UserHandle.getUserId(Binder.getCallingUid());
synchronized (this) {
// Iterate across all processes
for (int i=mLruProcesses.size()-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
+ if (!allUsers && app.userId != userId) {
+ continue;
+ }
if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
// Generate process state info for running application
ActivityManager.RunningAppProcessInfo currApp =
@@ -13482,8 +13506,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// Inform of user switch
Intent addedIntent = new Intent(Intent.ACTION_USER_SWITCHED);
- addedIntent.putExtra(Intent.EXTRA_USERID, userId);
- mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
+ addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_USERS);
return true;
}
@@ -13499,7 +13523,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
private void onUserRemoved(Intent intent) {
- int extraUserId = intent.getIntExtra(Intent.EXTRA_USERID, -1);
+ int extraUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
if (extraUserId < 1) return;
// Kill all the processes for the user
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index b0d480c..c70650d 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -614,14 +614,14 @@ final class ActivityRecord {
pendingOptions.getStartY()+pendingOptions.getStartHeight()));
}
break;
- case ActivityOptions.ANIM_THUMBNAIL:
- case ActivityOptions.ANIM_THUMBNAIL_DELAYED:
- boolean delayed = (animationType == ActivityOptions.ANIM_THUMBNAIL_DELAYED);
+ case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP:
+ case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN:
+ boolean scaleUp = (animationType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP);
service.mWindowManager.overridePendingAppTransitionThumb(
pendingOptions.getThumbnail(),
pendingOptions.getStartX(), pendingOptions.getStartY(),
pendingOptions.getOnAnimationStartListener(),
- delayed);
+ scaleUp);
if (intent.getSourceBounds() == null) {
intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
pendingOptions.getStartY(),
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 1e0827f..ccea41a 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -3014,8 +3014,8 @@ final class ActivityStack {
// Collect information about the target of the Intent.
ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
profileFile, profileFd, userId);
- if (aInfo != null && mService.isSingleton(aInfo.processName, aInfo.applicationInfo,
- null, 0)) {
+ if (aInfo != null && (aInfo.flags & ActivityInfo.FLAG_MULTIPROCESS) == 0
+ && mService.isSingleton(aInfo.processName, aInfo.applicationInfo, null, 0)) {
userId = 0;
}
aInfo = mService.getActivityInfoForUser(aInfo, userId);
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index 0106114..5b3ff8d 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -18,6 +18,7 @@ package com.android.server.am;
import android.app.IServiceConnection;
import android.app.PendingIntent;
+import android.content.Context;
import java.io.PrintWriter;
@@ -62,6 +63,33 @@ class ConnectionRecord {
sb.append("ConnectionRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
+ if ((flags&Context.BIND_AUTO_CREATE) != 0) {
+ sb.append("CR ");
+ }
+ if ((flags&Context.BIND_DEBUG_UNBIND) != 0) {
+ sb.append("DBG ");
+ }
+ if ((flags&Context.BIND_NOT_FOREGROUND) != 0) {
+ sb.append("NOTFG ");
+ }
+ if ((flags&Context.BIND_ABOVE_CLIENT) != 0) {
+ sb.append("ABCLT ");
+ }
+ if ((flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
+ sb.append("OOM ");
+ }
+ if ((flags&Context.BIND_WAIVE_PRIORITY) != 0) {
+ sb.append("WPRI ");
+ }
+ if ((flags&Context.BIND_IMPORTANT) != 0) {
+ sb.append("IMP ");
+ }
+ if ((flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
+ sb.append("ACT ");
+ }
+ if ((flags&Context.BIND_NOT_VISIBLE) != 0) {
+ sb.append("NOTVIS ");
+ }
if (serviceDead) {
sb.append("DEAD ");
}
diff --git a/services/java/com/android/server/am/IntentBindRecord.java b/services/java/com/android/server/am/IntentBindRecord.java
index c94f714..0a92964 100644
--- a/services/java/com/android/server/am/IntentBindRecord.java
+++ b/services/java/com/android/server/am/IntentBindRecord.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
@@ -78,6 +79,20 @@ class IntentBindRecord {
intent = _intent;
}
+ int collectFlags() {
+ int flags = 0;
+ if (apps.size() > 0) {
+ for (AppBindRecord app : apps.values()) {
+ if (app.connections.size() > 0) {
+ for (ConnectionRecord conn : app.connections) {
+ flags |= conn.flags;
+ }
+ }
+ }
+ }
+ return flags;
+ }
+
public String toString() {
if (stringName != null) {
return stringName;
@@ -86,6 +101,9 @@ class IntentBindRecord {
sb.append("IntentBindRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
+ if ((collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
+ sb.append("CR ");
+ }
sb.append(service.shortName);
sb.append(':');
if (intent != null) {
diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/java/com/android/server/am/ProviderMap.java
index ab2e428..15fbb98 100644
--- a/services/java/com/android/server/am/ProviderMap.java
+++ b/services/java/com/android/server/am/ProviderMap.java
@@ -127,7 +127,12 @@ public class ProviderMap {
Slog.i(TAG,
"Removing from providersByName name=" + name + " user="
+ (optionalUserId == -1 ? Binder.getOrigCallingUser() : optionalUserId));
- getProvidersByName(optionalUserId).remove(name);
+ HashMap<String, ContentProviderRecord> map = getProvidersByName(optionalUserId);
+ // map returned by getProvidersByName wouldn't be null
+ map.remove(name);
+ if (map.size() == 0) {
+ mProvidersByNamePerUser.remove(optionalUserId);
+ }
}
}
@@ -141,7 +146,12 @@ public class ProviderMap {
Slog.i(TAG,
"Removing from providersByClass name=" + name + " user="
+ (optionalUserId == -1 ? Binder.getOrigCallingUser() : optionalUserId));
- getProvidersByClass(optionalUserId).remove(name);
+ HashMap<ComponentName, ContentProviderRecord> map = getProvidersByClass(optionalUserId);
+ // map returned by getProvidersByClass wouldn't be null
+ map.remove(name);
+ if (map.size() == 0) {
+ mProvidersByClassPerUser.remove(optionalUserId);
+ }
}
}
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 41386e4..5d60b9c 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -23,6 +23,7 @@ import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -260,6 +261,9 @@ class ServiceRecord extends Binder {
IntentBindRecord b = it.next();
pw.print(prefix); pw.print("* IntentBindRecord{");
pw.print(Integer.toHexString(System.identityHashCode(b)));
+ if ((b.collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
+ pw.append(" CREATE");
+ }
pw.println("}:");
b.dumpInService(pw, prefix + " ");
}
diff --git a/services/java/com/android/server/display/DisplayAdapter.java b/services/java/com/android/server/display/DisplayAdapter.java
index b623906..f9fa7a8 100644
--- a/services/java/com/android/server/display/DisplayAdapter.java
+++ b/services/java/com/android/server/display/DisplayAdapter.java
@@ -16,38 +16,33 @@
package com.android.server.display;
-import android.view.Display;
-
/**
- * A display adapter makes a single display devices available to the system.
+ * A display adapter makes zero or more display devices available to the system
+ * and provides facilities for discovering when displays are connected or disconnected.
* <p>
* For now, all display adapters are registered in the system server but
* in principle it could be done from other processes.
* </p>
*/
public abstract class DisplayAdapter {
- /** The current logical Display assignment for this adapter. Will change if other logical
- * display is assigned to this adapter */
- private int mDisplayId = Display.NO_DISPLAY;
-
- /** Assign the displayId
- * @hide */
- public void setDisplayId(int displayId) {
- mDisplayId = displayId;
- }
-
- /** Retrieve the displayId
- * @hide */
- public int getDisplayId() {
- return mDisplayId;
- }
-
/**
- * Gets the display adapter name.
+ * Gets the display adapter name for debugging purposes.
+ *
* @return The display adapter name.
*/
public abstract String getName();
- // TODO: dynamically register display devices
- public abstract DisplayDevice getDisplayDevice();
+ /**
+ * Registers the display adapter with the display manager.
+ * The display adapter should register any built-in display devices now.
+ * Other display devices can be registered dynamically later.
+ *
+ * @param listener The listener for callbacks.
+ */
+ public abstract void register(Listener listener);
+
+ public interface Listener {
+ public void onDisplayDeviceAdded(DisplayDevice device);
+ public void onDisplayDeviceRemoved(DisplayDevice device);
+ }
}
diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/java/com/android/server/display/DisplayDevice.java
index 6d723f2..57002ff 100644
--- a/services/java/com/android/server/display/DisplayDevice.java
+++ b/services/java/com/android/server/display/DisplayDevice.java
@@ -18,8 +18,20 @@ package com.android.server.display;
/**
* Represents a physical display device such as the built-in display
- * or an external monitor.
+ * an external monitor, or a WiFi display.
*/
public abstract class DisplayDevice {
+ /**
+ * Gets the display adapter that makes the display device available.
+ *
+ * @return The display adapter.
+ */
+ public abstract DisplayAdapter getAdapter();
+
+ /**
+ * Gets information about the display device.
+ *
+ * @param outInfo The object to populate with the information.
+ */
public abstract void getInfo(DisplayDeviceInfo outInfo);
}
diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/java/com/android/server/display/DisplayDeviceInfo.java
index c60c2e9..9c0f964 100644
--- a/services/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/java/com/android/server/display/DisplayDeviceInfo.java
@@ -21,6 +21,12 @@ package com.android.server.display;
*/
public final class DisplayDeviceInfo {
/**
+ * Gets the name of the display device, which may be derived from
+ * EDID or other sources. The name may be displayed to the user.
+ */
+ public String name;
+
+ /**
* The width of the display in its natural orientation, in pixels.
* This value is not affected by display rotation.
*/
@@ -38,6 +44,7 @@ public final class DisplayDeviceInfo {
public float yDpi;
public void copyFrom(DisplayDeviceInfo other) {
+ name = other.name;
width = other.width;
height = other.height;
refreshRate = other.refreshRate;
@@ -46,9 +53,10 @@ public final class DisplayDeviceInfo {
yDpi = other.yDpi;
}
+ // For debugging purposes
@Override
public String toString() {
- return width + " x " + height + ", " + refreshRate + " fps, "
+ return "\"" + name + "\": " + width + " x " + height + ", " + refreshRate + " fps, "
+ "density " + densityDpi + ", " + xDpi + " x " + yDpi + " dpi";
}
}
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java
index 468bf21..2ebad1d 100644
--- a/services/java/com/android/server/display/DisplayManagerService.java
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -19,11 +19,10 @@ package com.android.server.display;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.hardware.display.DisplayManager;
import android.hardware.display.IDisplayManager;
import android.os.Binder;
import android.os.SystemProperties;
-import android.util.Slog;
-import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -47,41 +46,27 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
private final Object mLock = new Object();
- private Context mContext;
+ private final Context mContext;
private final boolean mHeadless;
- private int mDisplayIdSeq = Display.DEFAULT_DISPLAY;
-
- /** All registered DisplayAdapters. */
private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
+ private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo();
- /** All the DisplayAdapters showing the given displayId. */
- private final SparseArray<ArrayList<DisplayAdapter>> mLogicalToPhysicals =
- new SparseArray<ArrayList<DisplayAdapter>>();
-
- /** All the DisplayInfos in the system indexed by deviceId */
- private final SparseArray<DisplayInfo> mDisplayInfos = new SparseArray<DisplayInfo>();
-
- private final ArrayList<DisplayCallback> mCallbacks =
- new ArrayList<DisplayManagerService.DisplayCallback>();
-
- public DisplayManagerService() {
+ public DisplayManagerService(Context context) {
+ mContext = context;
mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
+
registerDefaultDisplayAdapter();
}
private void registerDefaultDisplayAdapter() {
if (mHeadless) {
- registerDisplayAdapter(new HeadlessDisplayAdapter());
+ registerDisplayAdapter(new HeadlessDisplayAdapter(mContext));
} else {
- registerDisplayAdapter(new SurfaceFlingerDisplayAdapter());
+ registerDisplayAdapter(new SurfaceFlingerDisplayAdapter(mContext));
}
}
- public void setContext(Context context) {
- mContext = context;
- }
-
// FIXME: this isn't the right API for the long term
public void getDefaultExternalDisplayDeviceInfo(DisplayDeviceInfo info) {
// hardcoded assuming 720p touch screen plugged into HDMI and USB
@@ -90,6 +75,11 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
info.height = 720;
}
+ /**
+ * Returns true if the device is headless.
+ *
+ * @return True if the device is headless.
+ */
public boolean isHeadless() {
return mHeadless;
}
@@ -101,12 +91,10 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
*/
public void setDisplayInfo(int displayId, DisplayInfo info) {
synchronized (mLock) {
- DisplayInfo localInfo = mDisplayInfos.get(displayId);
- if (localInfo == null) {
- localInfo = new DisplayInfo();
- mDisplayInfos.put(displayId, localInfo);
+ if (displayId != Display.DEFAULT_DISPLAY) {
+ throw new UnsupportedOperationException();
}
- localInfo.copyFrom(info);
+ mDefaultDisplayInfo.copyFrom(info);
}
}
@@ -118,177 +106,32 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
@Override // Binder call
public boolean getDisplayInfo(int displayId, DisplayInfo outInfo) {
synchronized (mLock) {
- DisplayInfo localInfo = mDisplayInfos.get(displayId);
- if (localInfo == null) {
+ if (displayId != Display.DEFAULT_DISPLAY) {
return false;
}
- outInfo.copyFrom(localInfo);
+ outInfo.copyFrom(mDefaultDisplayInfo);
return true;
}
}
- /**
- * Inform the service of a new physical display. A new logical displayId is created and the new
- * physical display is immediately bound to it. Use removeAdapterFromDisplay to disconnect it.
- *
- * @param adapter The wrapper for information associated with the physical display.
- */
- public void registerDisplayAdapter(DisplayAdapter adapter) {
-
- int displayId;
- DisplayCallback[] callbacks;
-
- synchronized (mLock) {
- displayId = mDisplayIdSeq;
- do {
- // Find the next unused displayId. (Pretend like it might ever wrap around).
- mDisplayIdSeq++;
- if (mDisplayIdSeq < 0) {
- mDisplayIdSeq = Display.DEFAULT_DISPLAY + 1;
- }
- } while (mDisplayInfos.get(mDisplayIdSeq) != null);
-
- adapter.setDisplayId(displayId);
-
- createDisplayInfoLocked(displayId, adapter);
-
- ArrayList<DisplayAdapter> list = new ArrayList<DisplayAdapter>();
- list.add(adapter);
- mLogicalToPhysicals.put(displayId, list);
-
- mDisplayAdapters.add(adapter);
- callbacks = mCallbacks.toArray(new DisplayCallback[mCallbacks.size()]);
- }
-
- for (int i = callbacks.length - 1; i >= 0; i--) {
- callbacks[i].displayAdded(displayId);
- }
-
- // TODO: Notify SurfaceFlinger of new addition.
- }
-
- /**
- * Connect a logical display to a physical display. Will remove the physical display from any
- * logical display it is currently attached to.
- *
- * @param displayId The logical display. Will be created if it does not already exist.
- * @param adapter The physical display.
- */
- public void addAdapterToDisplay(int displayId, DisplayAdapter adapter) {
- if (adapter == null) {
- // TODO: Or throw NPE?
- Slog.e(TAG, "addDeviceToDisplay: Attempt to add null adapter");
- return;
- }
-
- synchronized (mLock) {
- if (!mDisplayAdapters.contains(adapter)) {
- // TOOD: Handle unregistered adapter with exception or return value.
- Slog.e(TAG, "addDeviceToDisplay: Attempt to add an unregistered adapter");
- return;
- }
-
- DisplayInfo displayInfo = mDisplayInfos.get(displayId);
- if (displayInfo == null) {
- createDisplayInfoLocked(displayId, adapter);
- }
-
- Integer oldDisplayId = adapter.getDisplayId();
- if (oldDisplayId != Display.NO_DISPLAY) {
- if (oldDisplayId == displayId) {
- // adapter already added to displayId.
- return;
- }
-
- removeAdapterLocked(adapter);
- }
-
- ArrayList<DisplayAdapter> list = mLogicalToPhysicals.get(displayId);
- if (list == null) {
- list = new ArrayList<DisplayAdapter>();
- mLogicalToPhysicals.put(displayId, list);
- }
- list.add(adapter);
- adapter.setDisplayId(displayId);
- }
-
- // TODO: Notify SurfaceFlinger of new addition.
- }
-
- /**
- * Disconnect the physical display from whichever logical display it is attached to.
- * @param adapter The physical display to detach.
- */
- public void removeAdapterFromDisplay(DisplayAdapter adapter) {
- if (adapter == null) {
- // TODO: Or throw NPE?
- return;
- }
-
- synchronized (mLock) {
- if (!mDisplayAdapters.contains(adapter)) {
- // TOOD: Handle unregistered adapter with exception or return value.
- Slog.e(TAG, "removeDeviceFromDisplay: Attempt to remove an unregistered adapter");
- return;
+ private void registerDisplayAdapter(DisplayAdapter adapter) {
+ mDisplayAdapters.add(adapter);
+ adapter.register(new DisplayAdapter.Listener() {
+ @Override
+ public void onDisplayDeviceAdded(DisplayDevice device) {
+ DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
+ device.getInfo(deviceInfo);
+ copyDisplayInfoFromDeviceInfo(mDefaultDisplayInfo, deviceInfo);
}
- removeAdapterLocked(adapter);
- }
-
- // TODO: Notify SurfaceFlinger of removal.
- }
-
- public void registerDisplayCallback(final DisplayCallback callback) {
- synchronized (mLock) {
- if (!mCallbacks.contains(callback)) {
- mCallbacks.add(callback);
+ @Override
+ public void onDisplayDeviceRemoved(DisplayDevice device) {
}
- }
+ });
}
- public void unregisterDisplayCallback(final DisplayCallback callback) {
- synchronized (mLock) {
- mCallbacks.remove(callback);
- }
- }
-
- /**
- * Create a new logical DisplayInfo and fill it in with information from the physical display.
- * @param displayId The logical identifier.
- * @param adapter The physical display for initial values.
- */
- private void createDisplayInfoLocked(int displayId, DisplayAdapter adapter) {
- DisplayInfo displayInfo = new DisplayInfo();
- DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
- adapter.getDisplayDevice().getInfo(deviceInfo);
- copyDisplayInfoFromDeviceInfo(displayInfo, deviceInfo);
- mDisplayInfos.put(displayId, displayInfo);
- }
-
- /**
- * Disconnect a physical display from its logical display. If there are no more physical
- * displays attached to the logical display, delete the logical display.
- * @param adapter The physical display to detach.
- */
- void removeAdapterLocked(DisplayAdapter adapter) {
- int displayId = adapter.getDisplayId();
- adapter.setDisplayId(Display.NO_DISPLAY);
-
- ArrayList<DisplayAdapter> list = mLogicalToPhysicals.get(displayId);
- if (list != null) {
- list.remove(adapter);
- if (list.isEmpty()) {
- mLogicalToPhysicals.remove(displayId);
- // TODO: Keep count of Windows attached to logical display and don't delete if
- // there are any outstanding. Also, what keeps the WindowManager from continuing
- // to use the logical display?
- mDisplayInfos.remove(displayId);
- }
- }
- }
-
- private void copyDisplayInfoFromDeviceInfo(DisplayInfo displayInfo,
- DisplayDeviceInfo deviceInfo) {
+ private void copyDisplayInfoFromDeviceInfo(
+ DisplayInfo displayInfo, DisplayDeviceInfo deviceInfo) {
// Bootstrap the logical display using the physical display.
displayInfo.appWidth = deviceInfo.width;
displayInfo.appHeight = deviceInfo.height;
@@ -319,19 +162,15 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
pw.println("Headless: " + mHeadless);
- DisplayDeviceInfo info = new DisplayDeviceInfo();
- for (DisplayAdapter adapter : mDisplayAdapters) {
- pw.println("Display for adapter " + adapter.getName()
- + " assigned to Display " + adapter.getDisplayId());
- DisplayDevice device = adapter.getDisplayDevice();
- pw.print(" ");
- device.getInfo(info);
- pw.println(info);
+ synchronized (mLock) {
+ for (DisplayAdapter adapter : mDisplayAdapters) {
+ pw.println("Adapter: " + adapter.getName());
+ }
+
+ pw.println("Default display info: " + mDefaultDisplayInfo);
}
- }
- public interface DisplayCallback {
- public void displayAdded(int displayId);
- public void displayRemoved(int displayId);
+ pw.println("Default display: "
+ + DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY));
}
}
diff --git a/services/java/com/android/server/display/HeadlessDisplayAdapter.java b/services/java/com/android/server/display/HeadlessDisplayAdapter.java
index 3eaf40f..17c2360 100644
--- a/services/java/com/android/server/display/HeadlessDisplayAdapter.java
+++ b/services/java/com/android/server/display/HeadlessDisplayAdapter.java
@@ -16,15 +16,41 @@
package com.android.server.display;
+import android.content.Context;
import android.util.DisplayMetrics;
/**
* Provides a fake default display for headless systems.
*/
public final class HeadlessDisplayAdapter extends DisplayAdapter {
- private final DisplayDevice mDefaultDisplay = new DisplayDevice() {
+ private final Context mContext;
+ private final HeadlessDisplayDevice mDefaultDisplayDevice;
+
+ public HeadlessDisplayAdapter(Context context) {
+ mContext = context;
+ mDefaultDisplayDevice = new HeadlessDisplayDevice();
+ }
+
+ @Override
+ public String getName() {
+ return "HeadlessDisplayAdapter";
+ }
+
+ @Override
+ public void register(Listener listener) {
+ listener.onDisplayDeviceAdded(mDefaultDisplayDevice);
+ }
+
+ private final class HeadlessDisplayDevice extends DisplayDevice {
+ @Override
+ public DisplayAdapter getAdapter() {
+ return HeadlessDisplayAdapter.this;
+ }
+
@Override
public void getInfo(DisplayDeviceInfo outInfo) {
+ outInfo.name = mContext.getResources().getString(
+ com.android.internal.R.string.display_manager_built_in_display);
outInfo.width = 640;
outInfo.height = 480;
outInfo.refreshRate = 60;
@@ -32,15 +58,5 @@ public final class HeadlessDisplayAdapter extends DisplayAdapter {
outInfo.xDpi = 160;
outInfo.yDpi = 160;
}
- };
-
- @Override
- public String getName() {
- return "HeadlessDisplayAdapter";
- }
-
- @Override
- public DisplayDevice getDisplayDevice() {
- return mDefaultDisplay;
}
}
diff --git a/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java b/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java
index 539f7c1..9531acb 100644
--- a/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java
+++ b/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java
@@ -16,18 +16,21 @@
package com.android.server.display;
+import android.content.Context;
+
/**
* A display adapter for the displays managed by Surface Flinger.
*/
public final class SurfaceFlingerDisplayAdapter extends DisplayAdapter {
+ private final Context mContext;
+ private final SurfaceFlingerDisplayDevice mDefaultDisplayDevice;
+
private static native void nativeGetDefaultDisplayDeviceInfo(DisplayDeviceInfo outInfo);
- private final DisplayDevice mDefaultDisplay = new DisplayDevice() {
- @Override
- public void getInfo(DisplayDeviceInfo outInfo) {
- nativeGetDefaultDisplayDeviceInfo(outInfo);
- }
- };
+ public SurfaceFlingerDisplayAdapter(Context context) {
+ mContext = context;
+ mDefaultDisplayDevice = new SurfaceFlingerDisplayDevice();
+ }
@Override
public String getName() {
@@ -35,7 +38,21 @@ public final class SurfaceFlingerDisplayAdapter extends DisplayAdapter {
}
@Override
- public DisplayDevice getDisplayDevice() {
- return mDefaultDisplay;
+ public void register(Listener listener) {
+ listener.onDisplayDeviceAdded(mDefaultDisplayDevice);
+ }
+
+ private final class SurfaceFlingerDisplayDevice extends DisplayDevice {
+ @Override
+ public DisplayAdapter getAdapter() {
+ return SurfaceFlingerDisplayAdapter.this;
+ }
+
+ @Override
+ public void getInfo(DisplayDeviceInfo outInfo) {
+ outInfo.name = mContext.getResources().getString(
+ com.android.internal.R.string.display_manager_built_in_display);
+ nativeGetDefaultDisplayDeviceInfo(outInfo);
+ }
}
}
diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java
index 21100e2..0b8ff62 100644
--- a/services/java/com/android/server/input/InputManagerService.java
+++ b/services/java/com/android/server/input/InputManagerService.java
@@ -1218,8 +1218,12 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog.
}
// Native callback.
- private void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
- mCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
+ private void notifySwitch(long whenNanos, int switchCode, int switchValue) {
+ switch (switchCode) {
+ case SW_LID:
+ mCallbacks.notifyLidSwitchChanged(whenNanos, switchValue == 0);
+ break;
+ }
}
// Native callback.
diff --git a/services/java/com/android/server/location/GeofenceManager.java b/services/java/com/android/server/location/GeofenceManager.java
index 338cd5d..26d9c15 100644
--- a/services/java/com/android/server/location/GeofenceManager.java
+++ b/services/java/com/android/server/location/GeofenceManager.java
@@ -34,9 +34,13 @@ import android.os.Bundle;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemClock;
+import android.util.Log;
+
+import com.android.server.LocationManagerService;
public class GeofenceManager implements LocationListener, PendingIntent.OnFinished {
private static final String TAG = "GeofenceManager";
+ private static final boolean D = LocationManagerService.D;
/**
* Assume a maximum land speed, as a heuristic to throttle location updates.
@@ -49,6 +53,7 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
private final LocationManager mLocationManager;
private final PowerManager.WakeLock mWakeLock;
private final Looper mLooper; // looper thread to take location updates on
+ private final LocationBlacklist mBlacklist;
private Object mLock = new Object();
@@ -56,12 +61,13 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
private Location mLastLocation;
private List<GeofenceState> mFences = new LinkedList<GeofenceState>();
- public GeofenceManager(Context context) {
+ public GeofenceManager(Context context, LocationBlacklist blacklist) {
mContext = context;
mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mLooper = Looper.myLooper();
+ mBlacklist = blacklist;
LocationRequest request = new LocationRequest()
.setQuality(LocationRequest.POWER_NONE)
@@ -145,6 +151,12 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
removeExpiredFencesLocked();
for (GeofenceState state : mFences) {
+ if (mBlacklist.isBlacklisted(state.mPackageName)) {
+ if (D) Log.d(TAG, "skipping geofence processing for blacklisted app: " +
+ state.mPackageName);
+ continue;
+ }
+
int event = state.processLocation(location);
if ((event & GeofenceState.FLAG_ENTER) != 0) {
enterIntents.add(state.mIntent);
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 3cd767d..2d4fa2b 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -496,6 +496,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ALARM_WAKEUP);
intentFilter.addAction(ALARM_TIMEOUT);
+ intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mContext.registerReceiver(mBroadcastReciever, intentFilter);
}
@@ -845,6 +846,9 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
}
}
+
+ // save current uids
+ mClientUids = uids;
}
@Override
diff --git a/services/java/com/android/server/location/LocationBlacklist.java b/services/java/com/android/server/location/LocationBlacklist.java
new file mode 100644
index 0000000..71fa9f9
--- /dev/null
+++ b/services/java/com/android/server/location/LocationBlacklist.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.server.location;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.server.LocationManagerService;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Allows applications to be blacklisted from location updates at run-time.
+ *
+ * This is a silent blacklist. Applications can still call Location Manager
+ * API's, but they just won't receive any locations.
+ */
+public final class LocationBlacklist extends ContentObserver {
+ private static final String TAG = "LocationBlacklist";
+ private static final boolean D = LocationManagerService.D;
+ private static final String BLACKLIST_CONFIG_NAME = "locationPackagePrefixBlacklist";
+ private static final String WHITELIST_CONFIG_NAME = "locationPackagePrefixWhitelist";
+
+ private final Context mContext;
+ private final Object mLock = new Object();
+
+ // all fields below synchronized on mLock
+ private String[] mWhitelist = new String[0];
+ private String[] mBlacklist = new String[0];
+
+ public LocationBlacklist(Context context, Handler handler) {
+ super(handler);
+ mContext = context;
+ }
+
+ public void init() {
+ mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
+ BLACKLIST_CONFIG_NAME), false, this);
+// mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
+// WHITELIST_CONFIG_NAME), false, this);
+ reloadBlacklist();
+ }
+
+ private void reloadBlacklist() {
+ String blacklist[] = getStringArray(BLACKLIST_CONFIG_NAME);
+ String whitelist[] = getStringArray(WHITELIST_CONFIG_NAME);
+ synchronized (mLock) {
+ mWhitelist = whitelist;
+ Slog.i(TAG, "whitelist: " + Arrays.toString(mWhitelist));
+ mBlacklist = blacklist;
+ Slog.i(TAG, "blacklist: " + Arrays.toString(mBlacklist));
+ }
+ }
+
+ /**
+ * Return true if in blacklist
+ * (package name matches blacklist, and does not match whitelist)
+ */
+ public boolean isBlacklisted(String packageName) {
+ synchronized (mLock) {
+ for (String black : mBlacklist) {
+ if (packageName.startsWith(black)) {
+ if (inWhitelist(packageName)) {
+ continue;
+ } else {
+ if (D) Log.d(TAG, "dropping location (blacklisted): "
+ + packageName + " matches " + black);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return true if any of packages are in whitelist
+ */
+ private boolean inWhitelist(String pkg) {
+ synchronized (mLock) {
+ for (String white : mWhitelist) {
+ if (pkg.startsWith(white)) return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ reloadBlacklist();
+ }
+
+ private String[] getStringArray(String key) {
+ String flatString = Settings.Secure.getString(mContext.getContentResolver(), key);
+ if (flatString == null) {
+ return new String[0];
+ }
+ String[] splitStrings = flatString.split(",");
+ ArrayList<String> result = new ArrayList<String>();
+ for (String pkg : splitStrings) {
+ pkg = pkg.trim();
+ if (pkg.isEmpty()) {
+ continue;
+ }
+ result.add(pkg);
+ }
+ return result.toArray(new String[result.size()]);
+ }
+
+ public void dump(PrintWriter pw) {
+ pw.println("mWhitelist=" + Arrays.toString(mWhitelist) + " mBlacklist=" +
+ Arrays.toString(mBlacklist));
+ }
+}
diff --git a/services/java/com/android/server/location/LocationFudger.java b/services/java/com/android/server/location/LocationFudger.java
new file mode 100644
index 0000000..57bc1c5
--- /dev/null
+++ b/services/java/com/android/server/location/LocationFudger.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.location;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.security.SecureRandom;
+import android.location.Location;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.os.SystemClock;
+import android.util.Log;
+
+
+/**
+ * Contains the logic to obfuscate (fudge) locations for coarse applications.
+ *
+ * <p>The goal is just to prevent applications with only
+ * the coarse location permission from receiving a fine location.
+ */
+public class LocationFudger {
+ private static final boolean D = false;
+ private static final String TAG = "LocationFudge";
+
+ private static final String EXTRA_COARSE_LOCATION = "coarseLocation";
+
+ /**
+ * This is the main control: Best location accuracy allowed for coarse applications.
+ */
+ private static final float ACCURACY_METERS = 200.0f;
+
+ /**
+ * The distance between grids for snap-to-grid. See {@link #createCoarse}.
+ */
+ private static final double GRID_SIZE_METERS = ACCURACY_METERS;
+
+ /**
+ * Standard deviation of the (normally distributed) random offset applied
+ * to coarse locations. It does not need to be as large as
+ * {@link #COARSE_ACCURACY_METERS} because snap-to-grid is the primary obfuscation
+ * method. See further details in the implementation.
+ */
+ private static final double STANDARD_DEVIATION_METERS = GRID_SIZE_METERS / 4.0;
+
+ /**
+ * This is the fastest interval that applications can receive coarse
+ * locations.
+ */
+ public static final long FASTEST_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
+
+ /**
+ * The duration until we change the random offset.
+ */
+ private static final long CHANGE_INTERVAL_MS = 60 * 60 * 1000; // 1 hour
+
+ /**
+ * The percentage that we change the random offset at every interval.
+ *
+ * <p>0.0 indicates the random offset doesn't change. 1.0
+ * indicates the random offset is completely replaced every interval.
+ */
+ private static final double CHANGE_PER_INTERVAL = 0.03; // 3% change
+
+ // Pre-calculated weights used to move the random offset.
+ //
+ // The goal is to iterate on the previous offset, but keep
+ // the resulting standard deviation the same. The variance of
+ // two gaussian distributions summed together is equal to the
+ // sum of the variance of each distribution. So some quick
+ // algebra results in the following sqrt calculation to
+ // weigh in a new offset while keeping the final standard
+ // deviation unchanged.
+ private static final double NEW_WEIGHT = CHANGE_PER_INTERVAL;
+ private static final double PREVIOUS_WEIGHT = Math.sqrt(1 - NEW_WEIGHT * NEW_WEIGHT);
+
+ /**
+ * This number actually varies because the earth is not round, but
+ * 111,000 meters is considered generally acceptable.
+ */
+ private static final int APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR = 111000;
+
+ /**
+ * Maximum latitude.
+ *
+ * <p>We pick a value 1 meter away from 90.0 degrees in order
+ * to keep cosine(MAX_LATITUDE) to a non-zero value, so that we avoid
+ * divide by zero fails.
+ */
+ private static final double MAX_LATITUDE = 90.0 -
+ (1.0 / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR);
+
+ private final Object mLock = new Object();
+ private final SecureRandom mRandom = new SecureRandom();
+
+ // all fields below protected by mLock
+ private double mOffsetLatitudeMeters;
+ private double mOffsetLongitudeMeters;
+ private long mNextInterval;
+
+ public LocationFudger() {
+ mOffsetLatitudeMeters = nextOffset();
+ mOffsetLongitudeMeters = nextOffset();
+ mNextInterval = SystemClock.elapsedRealtime() + CHANGE_INTERVAL_MS;
+ }
+
+ /**
+ * Get the cached coarse location, or generate a new one and cache it.
+ */
+ public Location getOrCreate(Location location) {
+ Bundle extras = location.getExtras();
+ if (extras == null) {
+ return addCoarseLocationExtra(location);
+ }
+ Parcelable parcel = extras.getParcelable(EXTRA_COARSE_LOCATION);
+ if (parcel == null) {
+ return addCoarseLocationExtra(location);
+ }
+ if (!(parcel instanceof Location)) {
+ return addCoarseLocationExtra(location);
+ }
+ Location coarse = (Location) parcel;
+ if (coarse.getAccuracy() < ACCURACY_METERS) {
+ return addCoarseLocationExtra(location);
+ }
+ return coarse;
+ }
+
+ private Location addCoarseLocationExtra(Location location) {
+ Bundle extras = location.getExtras();
+ if (extras == null) extras = new Bundle();
+ Location coarse = createCoarse(location);
+ extras.putParcelable(EXTRA_COARSE_LOCATION, coarse);
+ location.setExtras(extras);
+ return coarse;
+ }
+
+ /**
+ * Create a coarse location.
+ *
+ * <p>Two techniques are used: random offsets and snap-to-grid.
+ *
+ * <p>First we add a random offset. This mitigates against detecting
+ * grid transitions. Without a random offset it is possible to detect
+ * a users position very accurately when they cross a grid boundary.
+ * The random offset changes very slowly over time, to mitigate against
+ * taking many location samples and averaging them out.
+ *
+ * <p>Second we snap-to-grid (quantize). This has the nice property of
+ * producing stable results, and mitigating against taking many samples
+ * to average out a random offset.
+ */
+ private Location createCoarse(Location fine) {
+ Location coarse = new Location(fine);
+
+ // clean all the optional information off the location, because
+ // this can leak detailed location information
+ coarse.removeBearing();
+ coarse.removeSpeed();
+ coarse.removeAltitude();
+ coarse.setExtras(null);
+
+ double lat = coarse.getLatitude();
+ double lon = coarse.getLongitude();
+
+ // wrap
+ lat = wrapLatitude(lat);
+ lon = wrapLongitude(lon);
+
+ // Step 1) apply a random offset
+ //
+ // The goal of the random offset is to prevent the application
+ // from determining that the device is on a grid boundary
+ // when it crosses from one grid to the next.
+ //
+ // We apply the offset even if the location already claims to be
+ // inaccurate, because it may be more accurate than claimed.
+ synchronized (mLock) {
+ updateRandomOffsetLocked();
+ // perform lon first whilst lat is still within bounds
+ lon += metersToDegreesLongitude(mOffsetLongitudeMeters, lat);
+ lat += metersToDegreesLatitude(mOffsetLatitudeMeters);
+ if (D) Log.d(TAG, String.format("applied offset of %.0f, %.0f (meters)",
+ mOffsetLongitudeMeters, mOffsetLatitudeMeters));
+ }
+
+ // wrap
+ lat = wrapLatitude(lat);
+ lon = wrapLongitude(lon);
+
+ // Step 2) Snap-to-grid (quantize)
+ //
+ // This is the primary means of obfuscation. It gives nice consistent
+ // results and is very effective at hiding the true location
+ // (as long as you are not sitting on a grid boundary, which
+ // step 1 mitigates).
+ //
+ // Note we quantize the latitude first, since the longitude
+ // quantization depends on the latitude value and so leaks information
+ // about the latitude
+ double latGranularity = metersToDegreesLatitude(GRID_SIZE_METERS);
+ lat = Math.round(lat / latGranularity) * latGranularity;
+ double lonGranularity = metersToDegreesLongitude(GRID_SIZE_METERS, lat);
+ lon = Math.round(lon / lonGranularity) * lonGranularity;
+
+ // wrap again
+ lat = wrapLatitude(lat);
+ lon = wrapLongitude(lon);
+
+ // apply
+ coarse.setLatitude(lat);
+ coarse.setLongitude(lon);
+ coarse.setAccuracy(Math.max(ACCURACY_METERS, coarse.getAccuracy()));
+
+ if (D) Log.d(TAG, "fudged " + fine + " to " + coarse);
+ return coarse;
+ }
+
+ /**
+ * Update the random offset over time.
+ *
+ * <p>If the random offset was new for every location
+ * fix then an application can more easily average location results
+ * over time,
+ * especially when the location is near a grid boundary. On the
+ * other hand if the random offset is constant then if an application
+ * found a way to reverse engineer the offset they would be able
+ * to detect location at grid boundaries very accurately. So
+ * we choose a random offset and then very slowly move it, to
+ * make both approaches very hard.
+ *
+ * <p>The random offset does not need to be large, because snap-to-grid
+ * is the primary obfuscation mechanism. It just needs to be large
+ * enough to stop information leakage as we cross grid boundaries.
+ */
+ private void updateRandomOffsetLocked() {
+ long now = SystemClock.elapsedRealtime();
+ if (now < mNextInterval) {
+ return;
+ }
+
+ if (D) Log.d(TAG, String.format("old offset: %.0f, %.0f (meters)",
+ mOffsetLongitudeMeters, mOffsetLatitudeMeters));
+
+ // ok, need to update the random offset
+ mNextInterval = now + CHANGE_INTERVAL_MS;
+
+ mOffsetLatitudeMeters *= PREVIOUS_WEIGHT;
+ mOffsetLatitudeMeters += NEW_WEIGHT * nextOffset();
+ mOffsetLongitudeMeters *= PREVIOUS_WEIGHT;
+ mOffsetLongitudeMeters += NEW_WEIGHT * nextOffset();
+
+ if (D) Log.d(TAG, String.format("new offset: %.0f, %.0f (meters)",
+ mOffsetLongitudeMeters, mOffsetLatitudeMeters));
+ }
+
+ private double nextOffset() {
+ return mRandom.nextGaussian() * STANDARD_DEVIATION_METERS;
+ }
+
+ private static double wrapLatitude(double lat) {
+ if (lat > MAX_LATITUDE) {
+ lat = MAX_LATITUDE;
+ }
+ if (lat < -MAX_LATITUDE) {
+ lat = -MAX_LATITUDE;
+ }
+ return lat;
+ }
+
+ private static double wrapLongitude(double lon) {
+ lon %= 360.0; // wraps into range (-360.0, +360.0)
+ if (lon >= 180.0) {
+ lon -= 360.0;
+ }
+ if (lon < -180.0) {
+ lon += 360.0;
+ }
+ return lon;
+ }
+
+ private static double metersToDegreesLatitude(double distance) {
+ return distance / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR;
+ }
+
+ /**
+ * Requires latitude since longitudinal distances change with distance from equator.
+ */
+ private static double metersToDegreesLongitude(double distance, double lat) {
+ return distance / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR / Math.cos(Math.toRadians(lat));
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println(String.format("offset: %.0f, %.0f (meters)", mOffsetLongitudeMeters,
+ mOffsetLatitudeMeters));
+ }
+}
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 48004bb..d4fe3fb 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -338,12 +338,14 @@ class Installer {
return execute(builder.toString());
}
- public int getSizeInfo(String pkgName, String apkPath, String fwdLockApkPath,
+ public int getSizeInfo(String pkgName, int persona, String apkPath, String fwdLockApkPath,
String asecPath, PackageStats pStats) {
StringBuilder builder = new StringBuilder("getsize");
builder.append(' ');
builder.append(pkgName);
builder.append(' ');
+ builder.append(persona);
+ builder.append(' ');
builder.append(apkPath);
builder.append(' ');
builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 9e94333..a76f854 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -79,6 +79,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
import android.content.pm.ManifestDigest;
+import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VerifierInfo;
import android.net.Uri;
@@ -97,6 +98,7 @@ import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
+import android.os.SELinux;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
@@ -145,6 +147,7 @@ import java.util.Set;
import libcore.io.ErrnoException;
import libcore.io.IoUtils;
import libcore.io.Libcore;
+import libcore.io.StructStat;
/**
* Keep track of all those .apks everywhere.
@@ -304,8 +307,6 @@ public class PackageManagerService extends IPackageManager.Stub {
File mScanningPath;
int mLastScanError;
- final int[] mOutPermissions = new int[3];
-
// ----------------------------------------------------------------
// Keys are String (package name), values are Package. This also serves
@@ -2422,6 +2423,9 @@ public class PackageManagerService extends IPackageManager.Stub {
final int M = prefs.size();
for (int i=0; i<M; i++) {
final PreferredActivity pa = prefs.get(i);
+ if (pa.mUserId != userId) {
+ continue;
+ }
if (pa.mPref.mMatch != match) {
continue;
}
@@ -3789,14 +3793,18 @@ public class PackageManagerService extends IPackageManager.Stub {
boolean uidError = false;
if (dataPath.exists()) {
- // XXX should really do this check for each user.
- mOutPermissions[1] = 0;
- FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
+ int currentUid = 0;
+ try {
+ StructStat stat = Libcore.os.stat(dataPath.getPath());
+ currentUid = stat.st_uid;
+ } catch (ErrnoException e) {
+ Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e);
+ }
// If we have mismatched owners for the data path, we have a problem.
- if (mOutPermissions[1] != pkg.applicationInfo.uid) {
+ if (currentUid != pkg.applicationInfo.uid) {
boolean recovered = false;
- if (mOutPermissions[1] == 0) {
+ if (currentUid == 0) {
// The directory somehow became owned by root. Wow.
// This is probably because the system was stopped while
// installd was in the middle of messing with its libs
@@ -3825,7 +3833,7 @@ public class PackageManagerService extends IPackageManager.Stub {
? "System package " : "Third party package ";
String msg = prefix + pkg.packageName
+ " has changed from uid: "
- + mOutPermissions[1] + " to "
+ + currentUid + " to "
+ pkg.applicationInfo.uid + "; old data erased";
reportSettingsProblem(Log.WARN, msg);
recovered = true;
@@ -3857,11 +3865,11 @@ public class PackageManagerService extends IPackageManager.Stub {
if (!recovered) {
pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
+ pkg.applicationInfo.uid + "/fs_"
- + mOutPermissions[1];
+ + currentUid;
pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
String msg = "Package " + pkg.packageName
+ " has mismatched uid: "
- + mOutPermissions[1] + " on disk, "
+ + currentUid + " on disk, "
+ pkg.applicationInfo.uid + " in settings";
// writer
synchronized (mPackages) {
@@ -5344,7 +5352,17 @@ public class PackageManagerService extends IPackageManager.Stub {
public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
int flags, String installerPackageName, Uri verificationURI,
ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
+ VerificationParams verificationParams = new VerificationParams(verificationURI, null, null,
+ manifestDigest);
+ installPackageWithVerificationAndEncryption(packageURI, observer, flags,
+ installerPackageName, verificationParams, encryptionParams);
+ }
+
+ public void installPackageWithVerificationAndEncryption(Uri packageURI,
+ IPackageInstallObserver observer, int flags, String installerPackageName,
+ VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
+ null);
final int uid = Binder.getCallingUid();
@@ -5361,7 +5379,7 @@ public class PackageManagerService extends IPackageManager.Stub {
final Message msg = mHandler.obtainMessage(INIT_COPY);
msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
- verificationURI, manifestDigest, encryptionParams);
+ verificationParams, encryptionParams);
mHandler.sendMessage(msg);
}
@@ -5725,7 +5743,7 @@ public class PackageManagerService extends IPackageManager.Stub {
@Override
void handleStartCopy() throws RemoteException {
synchronized (mInstallLock) {
- mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats);
+ mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats.userHandle, mStats);
}
final boolean mounted;
@@ -5791,8 +5809,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private final Uri mPackageURI;
final String installerPackageName;
- final Uri verificationURI;
- final ManifestDigest manifestDigest;
+ final VerificationParams verificationParams;
private InstallArgs mArgs;
private int mRet;
private File mTempPackage;
@@ -5800,17 +5817,23 @@ public class PackageManagerService extends IPackageManager.Stub {
InstallParams(Uri packageURI,
IPackageInstallObserver observer, int flags,
- String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest,
+ String installerPackageName, VerificationParams verificationParams,
ContainerEncryptionParams encryptionParams) {
this.mPackageURI = packageURI;
this.flags = flags;
this.observer = observer;
this.installerPackageName = installerPackageName;
- this.verificationURI = verificationURI;
- this.manifestDigest = manifestDigest;
+ this.verificationParams = verificationParams;
this.encryptionParams = encryptionParams;
}
+ public ManifestDigest getManifestDigest() {
+ if (verificationParams == null) {
+ return null;
+ }
+ return verificationParams.getManifestDigest();
+ }
+
private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
String packageName = pkgLite.packageName;
int installLocation = pkgLite.installLocation;
@@ -5999,9 +6022,19 @@ public class PackageManagerService extends IPackageManager.Stub {
verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, flags);
- if (verificationURI != null) {
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
- verificationURI);
+ if (verificationParams != null) {
+ if (verificationParams.getVerificationURI() != null) {
+ verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
+ verificationParams.getVerificationURI());
+ }
+ if (verificationParams.getOriginatingURI() != null) {
+ verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
+ verificationParams.getOriginatingURI());
+ }
+ if (verificationParams.getReferrer() != null) {
+ verification.putExtra(Intent.EXTRA_REFERRER,
+ verificationParams.getReferrer());
+ }
}
final PackageVerificationState verificationState = new PackageVerificationState(
@@ -6337,7 +6370,7 @@ public class PackageManagerService extends IPackageManager.Stub {
FileInstallArgs(InstallParams params) {
super(params.getPackageUri(), params.observer, params.flags,
- params.installerPackageName, params.manifestDigest);
+ params.installerPackageName, params.getManifestDigest());
}
FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
@@ -6484,6 +6517,10 @@ public class PackageManagerService extends IPackageManager.Stub {
return false;
}
+ if (!SELinux.restorecon(newCodeFile)) {
+ return false;
+ }
+
return true;
}
}
@@ -6620,7 +6657,7 @@ public class PackageManagerService extends IPackageManager.Stub {
AsecInstallArgs(InstallParams params) {
super(params.getPackageUri(), params.observer, params.flags,
- params.installerPackageName, params.manifestDigest);
+ params.installerPackageName, params.getManifestDigest());
}
AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
@@ -7465,6 +7502,9 @@ public class PackageManagerService extends IPackageManager.Stub {
FileUtils.setPermissions(
tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
-1, -1);
+ if (!SELinux.restorecon(tmpPackageFile)) {
+ return null;
+ }
} catch (IOException e) {
Slog.e(TAG, "Trouble getting the canoncical path for a temp file.");
return null;
@@ -7634,7 +7674,7 @@ public class PackageManagerService extends IPackageManager.Stub {
mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
}
}
- clearPackagePreferredActivitiesLPw(deletedPs.name);
+ clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
}
}
// can downgrade to reader
@@ -7996,12 +8036,12 @@ public class PackageManagerService extends IPackageManager.Stub {
return true;
}
- public void getPackageSizeInfo(final String packageName,
+ public void getPackageSizeInfo(final String packageName, int userHandle,
final IPackageStatsObserver observer) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.GET_PACKAGE_SIZE, null);
- PackageStats stats = new PackageStats(packageName);
+ PackageStats stats = new PackageStats(packageName, userHandle);
/*
* Queue up an async operation since the package measurement may take a
@@ -8012,7 +8052,8 @@ public class PackageManagerService extends IPackageManager.Stub {
mHandler.sendMessage(msg);
}
- private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
+ private boolean getPackageSizeInfoLI(String packageName, int userHandle,
+ PackageStats pStats) {
if (packageName == null) {
Slog.w(TAG, "Attempt to get size of null packageName.");
return false;
@@ -8049,7 +8090,7 @@ public class PackageManagerService extends IPackageManager.Stub {
publicSrcDir = applicationInfo.publicSourceDir;
}
}
- int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir,
+ int res = mInstaller.getSizeInfo(packageName, userHandle, p.mPath, publicSrcDir,
asecPath, pStats);
if (res < 0) {
return false;
@@ -8101,26 +8142,28 @@ public class PackageManagerService extends IPackageManager.Stub {
}
public void addPreferredActivity(IntentFilter filter, int match,
- ComponentName[] set, ComponentName activity) {
+ ComponentName[] set, ComponentName activity, int userId) {
// writer
+ int callingUid = Binder.getCallingUid();
+ checkValidCaller(callingUid, userId);
synchronized (mPackages) {
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
!= PackageManager.PERMISSION_GRANTED) {
- if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
+ if (getUidTargetSdkVersionLockedLPr(callingUid)
< Build.VERSION_CODES.FROYO) {
Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
- + Binder.getCallingUid());
+ + callingUid);
return;
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
}
-
- Slog.i(TAG, "Adding preferred activity " + activity + ":");
+
+ Slog.i(TAG, "Adding preferred activity " + activity + " for user " + userId + " :");
filter.dump(new LogPrinter(Log.INFO, TAG), " ");
mSettings.mPreferredActivities.addFilter(
- new PreferredActivity(filter, match, set, activity));
+ new PreferredActivity(filter, match, set, activity, userId));
scheduleWriteSettingsLocked();
}
}
@@ -8156,13 +8199,15 @@ public class PackageManagerService extends IPackageManager.Stub {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
}
-
+
+ final int callingUserId = UserHandle.getCallingUserId();
ArrayList<PreferredActivity> removed = null;
Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
String action = filter.getAction(0);
String category = filter.getCategory(0);
while (it.hasNext()) {
PreferredActivity pa = it.next();
+ if (pa.mUserId != callingUserId) continue;
if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
if (removed == null) {
removed = new ArrayList<PreferredActivity>();
@@ -8178,7 +8223,7 @@ public class PackageManagerService extends IPackageManager.Stub {
mSettings.mPreferredActivities.removeFilter(pa);
}
}
- addPreferredActivity(filter, match, set, activity);
+ addPreferredActivity(filter, match, set, activity, callingUserId);
}
}
@@ -8202,17 +8247,21 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- if (clearPackagePreferredActivitiesLPw(packageName)) {
+ if (clearPackagePreferredActivitiesLPw(packageName, UserHandle.getCallingUserId())) {
scheduleWriteSettingsLocked();
}
}
}
- boolean clearPackagePreferredActivitiesLPw(String packageName) {
+ /** This method takes a specific user id as well as UserHandle.USER_ALL. */
+ boolean clearPackagePreferredActivitiesLPw(String packageName, int userId) {
ArrayList<PreferredActivity> removed = null;
Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
while (it.hasNext()) {
PreferredActivity pa = it.next();
+ if (userId != UserHandle.USER_ALL && pa.mUserId != userId) {
+ continue;
+ }
if (pa.mPref.mComponent.getPackageName().equals(packageName)) {
if (removed == null) {
removed = new ArrayList<PreferredActivity>();
@@ -8234,11 +8283,15 @@ public class PackageManagerService extends IPackageManager.Stub {
List<ComponentName> outActivities, String packageName) {
int num = 0;
+ final int userId = UserHandle.getCallingUserId();
// reader
synchronized (mPackages) {
final Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
while (it.hasNext()) {
final PreferredActivity pa = it.next();
+ if (pa.mUserId != userId) {
+ continue;
+ }
if (packageName == null
|| pa.mPref.mComponent.getPackageName().equals(packageName)) {
if (outFilters != null) {
diff --git a/services/java/com/android/server/pm/PreferredActivity.java b/services/java/com/android/server/pm/PreferredActivity.java
index b100eb1..5539e84 100644
--- a/services/java/com/android/server/pm/PreferredActivity.java
+++ b/services/java/com/android/server/pm/PreferredActivity.java
@@ -33,22 +33,38 @@ class PreferredActivity extends IntentFilter implements PreferredComponent.Callb
private static final String TAG = "PreferredActivity";
private static final boolean DEBUG_FILTERS = false;
+ static final String ATTR_USER_ID = "userId";
final PreferredComponent mPref;
+ final int mUserId;
PreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity) {
+ this(filter, match, set, activity, 0);
+ }
+
+ PreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity,
+ int userId) {
super(filter);
+ mUserId = userId;
mPref = new PreferredComponent(this, match, set, activity);
}
PreferredActivity(XmlPullParser parser) throws XmlPullParserException, IOException {
+ String userIdString = parser.getAttributeValue(null, ATTR_USER_ID);
+ if (userIdString != null && userIdString.length() > 0) {
+ mUserId = Integer.parseInt(userIdString);
+ } else {
+ // Old format with no userId specified - assume primary user
+ mUserId = 0;
+ }
mPref = new PreferredComponent(this, parser);
}
public void writeToXml(XmlSerializer serializer) throws IOException {
+ serializer.attribute(null, ATTR_USER_ID, Integer.toString(mUserId));
mPref.writeToXml(serializer);
serializer.startTag(null, "filter");
- super.writeToXml(serializer);
+ super.writeToXml(serializer);
serializer.endTag(null, "filter");
}
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index 725d67d..c292bbc 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -22,6 +22,7 @@ import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -35,6 +36,7 @@ import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -55,22 +57,17 @@ import org.xmlpull.v1.XmlSerializer;
public class UserManagerService extends IUserManager.Stub {
- private static final String TAG = "UserManagerService";
+ private static final String LOG_TAG = "UserManagerService";
private static final String TAG_NAME = "name";
-
private static final String ATTR_FLAGS = "flags";
-
private static final String ATTR_ICON_PATH = "icon";
-
private static final String ATTR_ID = "id";
-
+ private static final String ATTR_SERIAL_NO = "serialNumber";
+ private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
private static final String TAG_USERS = "users";
-
private static final String TAG_USER = "user";
- private static final String LOG_TAG = "UserManager";
-
private static final String USER_INFO_DIR = "system" + File.separator + "users";
private static final String USER_LIST_FILENAME = "userlist.xml";
private static final String USER_PHOTO_FILENAME = "photo.png";
@@ -81,6 +78,7 @@ public class UserManagerService extends IUserManager.Stub {
private final File mUserListFile;
private int[] mUserIds;
private boolean mGuestEnabled;
+ private int mNextSerialNumber;
private Installer mInstaller;
private File mBaseUserPath;
@@ -125,7 +123,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public List<UserInfo> getUsers() {
- enforceSystemOrRoot("Only the system can query users");
+ checkManageUsersPermission("query users");
synchronized (mUsers) {
ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
for (int i = 0; i < mUsers.size(); i++) {
@@ -137,7 +135,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public UserInfo getUserInfo(int userId) {
- enforceSystemOrRoot("Only the system can query user");
+ checkManageUsersPermission("query user");
synchronized (mUsers) {
UserInfo info = mUsers.get(userId);
return info;
@@ -152,7 +150,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public void setUserName(int userId, String name) {
- enforceSystemOrRoot("Only the system can rename users");
+ checkManageUsersPermission("rename users");
synchronized (mUsers) {
UserInfo info = mUsers.get(userId);
if (name != null && !name.equals(info.name)) {
@@ -164,7 +162,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public ParcelFileDescriptor setUserIcon(int userId) {
- enforceSystemOrRoot("Only the system can update users");
+ checkManageUsersPermission("update users");
synchronized (mUsers) {
UserInfo info = mUsers.get(userId);
if (info == null) return null;
@@ -178,7 +176,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public void setGuestEnabled(boolean enable) {
- enforceSystemOrRoot("Only the system can enable guest users");
+ checkManageUsersPermission("enable guest users");
synchronized (mUsers) {
if (mGuestEnabled != enable) {
mGuestEnabled = enable;
@@ -209,7 +207,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public void wipeUser(int userHandle) {
- enforceSystemOrRoot("Only the system can wipe users");
+ checkManageUsersPermission("wipe user");
// TODO:
}
@@ -220,10 +218,13 @@ public class UserManagerService extends IUserManager.Stub {
* @param message used as message if SecurityException is thrown
* @throws SecurityException if the caller is not system or root
*/
- private static final void enforceSystemOrRoot(String message) {
+ private static final void checkManageUsersPermission(String message) {
final int uid = Binder.getCallingUid();
- if (uid != Process.SYSTEM_UID && uid != 0) {
- throw new SecurityException(message);
+ if (uid != Process.SYSTEM_UID && uid != 0
+ && ActivityManager.checkComponentPermission(
+ android.Manifest.permission.MANAGE_USERS,
+ uid, -1, true) != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("You need MANAGE_USERS permission to: " + message);
}
}
@@ -243,7 +244,7 @@ public class UserManagerService extends IUserManager.Stub {
info.iconPath = file.getAbsolutePath();
return fd;
} catch (FileNotFoundException e) {
- Slog.w(TAG, "Error setting photo for user ", e);
+ Slog.w(LOG_TAG, "Error setting photo for user ", e);
}
return null;
}
@@ -270,8 +271,9 @@ public class UserManagerService extends IUserManager.Stub {
return;
}
FileInputStream fis = null;
+ AtomicFile userListFile = new AtomicFile(mUserListFile);
try {
- fis = new FileInputStream(mUserListFile);
+ fis = userListFile.openRead();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(fis, null);
int type;
@@ -286,15 +288,26 @@ public class UserManagerService extends IUserManager.Stub {
return;
}
+ mNextSerialNumber = -1;
+ if (parser.getName().equals(TAG_USERS)) {
+ String lastSerialNumber = parser.getAttributeValue(null, ATTR_NEXT_SERIAL_NO);
+ if (lastSerialNumber != null) {
+ mNextSerialNumber = Integer.parseInt(lastSerialNumber);
+ }
+ }
+
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) {
String id = parser.getAttributeValue(null, ATTR_ID);
UserInfo user = readUser(Integer.parseInt(id));
if (user != null) {
mUsers.put(user.id, user);
- }
- if (user.isGuest()) {
- mGuestEnabled = true;
+ if (user.isGuest()) {
+ mGuestEnabled = true;
+ }
+ if (mNextSerialNumber < 0 || mNextSerialNumber <= user.id) {
+ mNextSerialNumber = user.id + 1;
+ }
}
}
}
@@ -333,9 +346,9 @@ public class UserManagerService extends IUserManager.Stub {
*/
private void writeUserLocked(UserInfo userInfo) {
FileOutputStream fos = null;
+ AtomicFile userFile = new AtomicFile(new File(mUsersDir, userInfo.id + ".xml"));
try {
- final File mUserFile = new File(mUsersDir, userInfo.id + ".xml");
- fos = new FileOutputStream(mUserFile);
+ fos = userFile.startWrite();
final BufferedOutputStream bos = new BufferedOutputStream(fos);
// XmlSerializer serializer = XmlUtils.serializerInstance();
@@ -346,6 +359,7 @@ public class UserManagerService extends IUserManager.Stub {
serializer.startTag(null, TAG_USER);
serializer.attribute(null, ATTR_ID, Integer.toString(userInfo.id));
+ serializer.attribute(null, ATTR_SERIAL_NO, Integer.toString(userInfo.serialNumber));
serializer.attribute(null, ATTR_FLAGS, Integer.toString(userInfo.flags));
if (userInfo.iconPath != null) {
serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath);
@@ -358,30 +372,26 @@ public class UserManagerService extends IUserManager.Stub {
serializer.endTag(null, TAG_USER);
serializer.endDocument();
- } catch (IOException ioe) {
+ userFile.finishWrite(fos);
+ } catch (Exception ioe) {
Slog.e(LOG_TAG, "Error writing user info " + userInfo.id + "\n" + ioe);
- } finally {
- if (fos != null) {
- try {
- fos.close();
- } catch (IOException ioe) {
- }
- }
+ userFile.failWrite(fos);
}
}
/*
* Writes the user list file in this format:
*
- * <users>
+ * <users nextSerialNumber="3">
* <user id="0"></user>
* <user id="2"></user>
* </users>
*/
private void writeUserListLocked() {
FileOutputStream fos = null;
+ AtomicFile userListFile = new AtomicFile(mUserListFile);
try {
- fos = new FileOutputStream(mUserListFile);
+ fos = userListFile.startWrite();
final BufferedOutputStream bos = new BufferedOutputStream(fos);
// XmlSerializer serializer = XmlUtils.serializerInstance();
@@ -391,6 +401,7 @@ public class UserManagerService extends IUserManager.Stub {
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startTag(null, TAG_USERS);
+ serializer.attribute(null, ATTR_NEXT_SERIAL_NO, Integer.toString(mNextSerialNumber));
for (int i = 0; i < mUsers.size(); i++) {
UserInfo user = mUsers.valueAt(i);
@@ -402,27 +413,24 @@ public class UserManagerService extends IUserManager.Stub {
serializer.endTag(null, TAG_USERS);
serializer.endDocument();
- } catch (IOException ioe) {
+ userListFile.finishWrite(fos);
+ } catch (Exception e) {
+ userListFile.failWrite(fos);
Slog.e(LOG_TAG, "Error writing user list");
- } finally {
- if (fos != null) {
- try {
- fos.close();
- } catch (IOException ioe) {
- }
- }
}
}
private UserInfo readUser(int id) {
int flags = 0;
+ int serialNumber = id;
String name = null;
String iconPath = null;
FileInputStream fis = null;
try {
- File userFile = new File(mUsersDir, Integer.toString(id) + ".xml");
- fis = new FileInputStream(userFile);
+ AtomicFile userFile =
+ new AtomicFile(new File(mUsersDir, Integer.toString(id) + ".xml"));
+ fis = userFile.openRead();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(fis, null);
int type;
@@ -442,6 +450,10 @@ public class UserManagerService extends IUserManager.Stub {
Slog.e(LOG_TAG, "User id does not match the file name");
return null;
}
+ String serialNumberValue = parser.getAttributeValue(null, ATTR_SERIAL_NO);
+ if (serialNumberValue != null) {
+ serialNumber = Integer.parseInt(serialNumberValue);
+ }
String flagString = parser.getAttributeValue(null, ATTR_FLAGS);
flags = Integer.parseInt(flagString);
iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
@@ -458,6 +470,7 @@ public class UserManagerService extends IUserManager.Stub {
}
UserInfo userInfo = new UserInfo(id, name, iconPath, flags);
+ userInfo.serialNumber = serialNumber;
return userInfo;
} catch (IOException ioe) {
@@ -475,7 +488,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public UserInfo createUser(String name, int flags) {
- enforceSystemOrRoot("Only the system can create users");
+ checkManageUsersPermission("Only the system can create users");
int userId = getNextAvailableId();
UserInfo userInfo = new UserInfo(userId, name, null, flags);
File userPath = new File(mBaseUserPath, Integer.toString(userId));
@@ -483,6 +496,7 @@ public class UserManagerService extends IUserManager.Stub {
return null;
}
synchronized (mUsers) {
+ userInfo.serialNumber = mNextSerialNumber++;
mUsers.put(userId, userInfo);
writeUserListLocked();
writeUserLocked(userInfo);
@@ -490,8 +504,10 @@ public class UserManagerService extends IUserManager.Stub {
}
if (userInfo != null) {
Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
- addedIntent.putExtra(Intent.EXTRA_USERID, userInfo.id);
- mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
+ addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id);
+ mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_USERS);
+ mContext.sendBroadcastAsUser(new Intent(Intent.ACTION_BOOT_COMPLETED),
+ new UserHandle(userInfo.id));
}
return userInfo;
}
@@ -502,9 +518,34 @@ public class UserManagerService extends IUserManager.Stub {
* @param id the user's id
*/
public boolean removeUser(int userHandle) {
- enforceSystemOrRoot("Only the system can remove users");
+ checkManageUsersPermission("Only the system can remove users");
+ boolean result;
+ synchronized (mUsers) {
+ result = removeUserLocked(userHandle);
+ }
+ // Let other services shutdown any activity
+ Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
+ addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
+ mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_USERS);
+ return result;
+ }
+
+ @Override
+ public int getUserSerialNumber(int userHandle) {
+ synchronized (mUsers) {
+ if (!exists(userHandle)) return -1;
+ return getUserInfo(userHandle).serialNumber;
+ }
+ }
+
+ @Override
+ public int getUserHandle(int userSerialNumber) {
synchronized (mUsers) {
- return removeUserLocked(userHandle);
+ for (int userId : mUserIds) {
+ if (getUserInfo(userId).serialNumber == userSerialNumber) return userId;
+ }
+ // Not found
+ return -1;
}
}
@@ -519,17 +560,12 @@ public class UserManagerService extends IUserManager.Stub {
// Remove this user from the list
mUsers.remove(userHandle);
// Remove user file
- File userFile = new File(mUsersDir, userHandle + ".xml");
+ AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml"));
userFile.delete();
// Update the user list
writeUserListLocked();
updateUserIdsLocked();
- // Let other services shutdown any activity
- Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
- addedIntent.putExtra(Intent.EXTRA_USERID, userHandle);
- mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
-
removePackageFolders(userHandle);
return true;
}
diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/java/com/android/server/power/DisplayPowerController.java
index b0c79fa..cf12b20 100644
--- a/services/java/com/android/server/power/DisplayPowerController.java
+++ b/services/java/com/android/server/power/DisplayPowerController.java
@@ -27,6 +27,7 @@ import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.SystemSensorManager;
+import android.hardware.display.DisplayManager;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
@@ -35,6 +36,7 @@ import android.os.SystemClock;
import android.util.Slog;
import android.util.Spline;
import android.util.TimeUtils;
+import android.view.Display;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -70,6 +72,12 @@ final class DisplayPowerController {
private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false;
+ // If true, uses the electron beam on animation.
+ // We might want to turn this off if we cannot get a guarantee that the screen
+ // actually turns on and starts showing new content after the call to set the
+ // screen state returns. Playing the animation can also be somewhat slow.
+ private static final boolean USE_ELECTRON_BEAM_ON_ANIMATION = false;
+
private static final int ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS = 300;
private static final int ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS = 600;
@@ -92,15 +100,15 @@ final class DisplayPowerController {
// Brightness animation ramp rate in brightness units per second.
private static final int BRIGHTNESS_RAMP_RATE_FAST = 200;
- private static final int BRIGHTNESS_RAMP_RATE_SLOW = 50;
+ private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
// Filter time constant in milliseconds for computing a moving
// average of light samples. Different constants are used
// to calculate the average light level when adapting to brighter or
// dimmer environments.
// This parameter only controls the filtering of light samples.
- private static final long BRIGHTENING_LIGHT_TIME_CONSTANT = 500;
- private static final long DIMMING_LIGHT_TIME_CONSTANT = 2000;
+ private static final long BRIGHTENING_LIGHT_TIME_CONSTANT = 600;
+ private static final long DIMMING_LIGHT_TIME_CONSTANT = 4000;
// Stability requirements in milliseconds for accepting a new brightness
// level. This is used for debouncing the light sensor. Different constants
@@ -422,7 +430,8 @@ final class DisplayPowerController {
private void initialize() {
final Executor executor = AsyncTask.THREAD_POOL_EXECUTOR;
- mPowerState = new DisplayPowerState(new ElectronBeam(),
+ Display display = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
+ mPowerState = new DisplayPowerState(new ElectronBeam(display),
new PhotonicModulator(executor,
mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT),
mSuspendBlocker));
@@ -470,11 +479,13 @@ final class DisplayPowerController {
if (mPowerRequest == null) {
mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
+ mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mustInitialize = true;
} else if (mPendingRequestChangedLocked) {
mPowerRequest.copyFrom(mPendingRequestLocked);
mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
+ mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mDisplayReadyLocked = false;
}
@@ -487,24 +498,33 @@ final class DisplayPowerController {
initialize();
}
- // Clear a request to wait for negative proximity if needed.
- if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_OFF
- || mProximity == PROXIMITY_NEGATIVE
- || mProximitySensor == null) {
- mWaitingForNegativeProximity = false;
- }
-
- // Turn on the proximity sensor if needed.
+ // Apply the proximity sensor.
if (mProximitySensor != null) {
- setProximitySensorEnabled(mPowerRequest.useProximitySensor
- || mWaitingForNegativeProximity);
- if (mProximitySensorEnabled && mProximity == PROXIMITY_POSITIVE) {
- mScreenOffBecauseOfProximity = true;
- setScreenOn(false);
- } else if (mScreenOffBecauseOfProximity) {
+ if (mPowerRequest.useProximitySensor
+ && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
+ setProximitySensorEnabled(true);
+ if (!mScreenOffBecauseOfProximity
+ && mProximity == PROXIMITY_POSITIVE) {
+ mScreenOffBecauseOfProximity = true;
+ setScreenOn(false);
+ }
+ } else if (mWaitingForNegativeProximity
+ && mScreenOffBecauseOfProximity
+ && mProximity == PROXIMITY_POSITIVE
+ && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
+ setProximitySensorEnabled(true);
+ } else {
+ setProximitySensorEnabled(false);
+ mWaitingForNegativeProximity = false;
+ }
+ if (mScreenOffBecauseOfProximity
+ && mProximity != PROXIMITY_POSITIVE) {
mScreenOffBecauseOfProximity = false;
+ setScreenOn(true);
sendOnProximityNegative();
}
+ } else {
+ mWaitingForNegativeProximity = false;
}
// Turn on the light sensor if needed.
@@ -550,14 +570,19 @@ final class DisplayPowerController {
// on animation immediately then the results are pretty ugly.
if (!mElectronBeamOffAnimator.isStarted()) {
setScreenOn(true);
- if (!mElectronBeamOnAnimator.isStarted()) {
- if (mPowerState.getElectronBeamLevel() == 1.0f) {
- mPowerState.dismissElectronBeam();
- } else if (mPowerState.prepareElectronBeam(true)) {
- mElectronBeamOnAnimator.start();
- } else {
- mElectronBeamOnAnimator.end();
+ if (USE_ELECTRON_BEAM_ON_ANIMATION) {
+ if (!mElectronBeamOnAnimator.isStarted()) {
+ if (mPowerState.getElectronBeamLevel() == 1.0f) {
+ mPowerState.dismissElectronBeam();
+ } else if (mPowerState.prepareElectronBeam(true)) {
+ mElectronBeamOnAnimator.start();
+ } else {
+ mElectronBeamOnAnimator.end();
+ }
}
+ } else {
+ mPowerState.setElectronBeamLevel(1.0f);
+ mPowerState.dismissElectronBeam();
}
}
} else {
diff --git a/services/java/com/android/server/power/DisplayPowerState.java b/services/java/com/android/server/power/DisplayPowerState.java
index f618725..64a0462 100644
--- a/services/java/com/android/server/power/DisplayPowerState.java
+++ b/services/java/com/android/server/power/DisplayPowerState.java
@@ -242,8 +242,9 @@ final class DisplayPowerState {
mElectronBeam.draw(mElectronBeamLevel);
}
- if ((mDirty & (DIRTY_BRIGHTNESS | DIRTY_SCREEN_ON)) != 0) {
- mScreenBrightnessModulator.setBrightness(mScreenOn ? mScreenBrightness : 0);
+ if ((mDirty & (DIRTY_BRIGHTNESS | DIRTY_SCREEN_ON | DIRTY_ELECTRON_BEAM)) != 0) {
+ mScreenBrightnessModulator.setBrightness(mScreenOn ?
+ (int)(mScreenBrightness * mElectronBeamLevel) : 0);
}
if ((mDirty & DIRTY_SCREEN_ON) != 0 && mScreenOn) {
diff --git a/services/java/com/android/server/power/ElectronBeam.java b/services/java/com/android/server/power/ElectronBeam.java
index 5472148..2d24249 100644
--- a/services/java/com/android/server/power/ElectronBeam.java
+++ b/services/java/com/android/server/power/ElectronBeam.java
@@ -33,7 +33,6 @@ import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
import android.view.SurfaceSession;
-import android.view.WindowManagerImpl;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
@@ -68,6 +67,7 @@ final class ElectronBeam {
private boolean mPrepared;
private boolean mWarmUp;
+ private final Display mDisplay;
private final DisplayInfo mDisplayInfo = new DisplayInfo();
private int mDisplayLayerStack; // layer stack associated with primary display
private int mDisplayRotation;
@@ -90,7 +90,8 @@ final class ElectronBeam {
private final FloatBuffer mVertexBuffer = createNativeFloatBuffer(8);
private final FloatBuffer mTexCoordBuffer = createNativeFloatBuffer(8);
- public ElectronBeam() {
+ public ElectronBeam(Display display) {
+ mDisplay = display;
}
/**
@@ -109,9 +110,8 @@ final class ElectronBeam {
mWarmUp = warmUp;
// Get the display size and adjust it for rotation.
- Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
- display.getDisplayInfo(mDisplayInfo);
- mDisplayLayerStack = display.getDisplayId();
+ mDisplay.getDisplayInfo(mDisplayInfo);
+ mDisplayLayerStack = mDisplay.getLayerStack();
mDisplayRotation = mDisplayInfo.rotation;
if (mDisplayRotation == Surface.ROTATION_90
|| mDisplayRotation == Surface.ROTATION_270) {
diff --git a/services/java/com/android/server/usb/UsbDebuggingManager.java b/services/java/com/android/server/usb/UsbDebuggingManager.java
new file mode 100644
index 0000000..a3b45c7
--- /dev/null
+++ b/services/java/com/android/server/usb/UsbDebuggingManager.java
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions an
+ * limitations under the License.
+ */
+
+package com.android.server.usb;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Environment;
+import android.os.FileUtils;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.Base64;
+
+import java.lang.Thread;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.security.MessageDigest;
+import java.util.Arrays;
+
+public class UsbDebuggingManager implements Runnable {
+ private static final String TAG = "UsbDebuggingManager";
+ private static final boolean DEBUG = false;
+
+ private final String ADBD_SOCKET = "adbd";
+ private final String ADB_DIRECTORY = "misc/adb";
+ private final String ADB_KEYS_FILE = "adb_keys";
+ private final int BUFFER_SIZE = 4096;
+
+ private final Context mContext;
+ private final Thread mThread;
+ private final Handler mHandler;
+ private final HandlerThread mHandlerThread;
+ private boolean mAdbEnabled = false;
+ private String mFingerprints;
+ private LocalSocket mSocket = null;
+ private OutputStream mOutputStream = null;
+
+ public UsbDebuggingManager(Context context) {
+ mThread = new Thread(this);
+ mHandlerThread = new HandlerThread("UsbDebuggingHandler");
+ mHandlerThread.start();
+ mHandler = new UsbDebuggingHandler(mHandlerThread.getLooper());
+ mContext = context;
+ }
+
+ private void listenToSocket() throws IOException {
+ try {
+ byte[] buffer = new byte[BUFFER_SIZE];
+ LocalSocketAddress address = new LocalSocketAddress(ADBD_SOCKET,
+ LocalSocketAddress.Namespace.RESERVED);
+ InputStream inputStream = null;
+
+ mSocket = new LocalSocket();
+ mSocket.connect(address);
+
+ mOutputStream = mSocket.getOutputStream();
+ inputStream = mSocket.getInputStream();
+
+ while (true) {
+ int count = inputStream.read(buffer);
+ if (count < 0) {
+ Slog.e(TAG, "got " + count + " reading");
+ break;
+ }
+
+ if (buffer[0] == 'P' && buffer[1] == 'K') {
+ String key = new String(Arrays.copyOfRange(buffer, 2, count));
+ Slog.d(TAG, "Received public key: " + key);
+ Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_CONFIRM);
+ msg.obj = key;
+ mHandler.sendMessage(msg);
+ }
+ else {
+ Slog.e(TAG, "Wrong message: " + (new String(Arrays.copyOfRange(buffer, 0, 2))));
+ break;
+ }
+ }
+ } catch (IOException ex) {
+ Slog.e(TAG, "Communication error: ", ex);
+ throw ex;
+ } finally {
+ closeSocket();
+ }
+ }
+
+ @Override
+ public void run() {
+ while (mAdbEnabled) {
+ try {
+ listenToSocket();
+ } catch (Exception e) {
+ /* Don't loop too fast if adbd dies, before init restarts it */
+ SystemClock.sleep(1000);
+ }
+ }
+ }
+
+ private void closeSocket() {
+ try {
+ mOutputStream.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed closing output stream: " + e);
+ }
+
+ try {
+ mSocket.close();
+ } catch (IOException ex) {
+ Slog.e(TAG, "Failed closing socket: " + ex);
+ }
+ }
+
+ private void sendResponse(String msg) {
+ if (mOutputStream != null) {
+ try {
+ mOutputStream.write(msg.getBytes());
+ }
+ catch (IOException ex) {
+ Slog.e(TAG, "Failed to write response:", ex);
+ }
+ }
+ }
+
+ class UsbDebuggingHandler extends Handler {
+ private static final int MESSAGE_ADB_ENABLED = 1;
+ private static final int MESSAGE_ADB_DISABLED = 2;
+ private static final int MESSAGE_ADB_ALLOW = 3;
+ private static final int MESSAGE_ADB_DENY = 4;
+ private static final int MESSAGE_ADB_CONFIRM = 5;
+
+ public UsbDebuggingHandler(Looper looper) {
+ super(looper);
+ }
+
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_ADB_ENABLED:
+ if (mAdbEnabled)
+ break;
+
+ mAdbEnabled = true;
+
+ mThread.start();
+
+ break;
+
+ case MESSAGE_ADB_DISABLED:
+ if (!mAdbEnabled)
+ break;
+
+ mAdbEnabled = false;
+ closeSocket();
+
+ try {
+ mThread.join();
+ } catch (Exception ex) {
+ }
+
+ mOutputStream = null;
+ mSocket = null;
+
+ case MESSAGE_ADB_ALLOW: {
+ String key = (String)msg.obj;
+ String fingerprints = getFingerprints(key);
+
+ if (!fingerprints.equals(mFingerprints)) {
+ Slog.e(TAG, "Fingerprints do not match. Got "
+ + fingerprints + ", expected " + mFingerprints);
+ break;
+ }
+
+ if (msg.arg1 == 1) {
+ writeKey(key);
+ }
+
+ sendResponse("OK");
+ break;
+ }
+
+ case MESSAGE_ADB_DENY:
+ sendResponse("NO");
+ break;
+
+ case MESSAGE_ADB_CONFIRM: {
+ String key = (String)msg.obj;
+ mFingerprints = getFingerprints(key);
+ showConfirmationDialog(key, mFingerprints);
+ break;
+ }
+ }
+ }
+ }
+
+ private String getFingerprints(String key) {
+ String hex = "0123456789ABCDEF";
+ StringBuilder sb = new StringBuilder();
+ MessageDigest digester;
+
+ try {
+ digester = MessageDigest.getInstance("MD5");
+ } catch (Exception ex) {
+ Slog.e(TAG, "Error getting digester: " + ex);
+ return "";
+ }
+
+ byte[] base64_data = key.split("\\s+")[0].getBytes();
+ byte[] digest = digester.digest(Base64.decode(base64_data, Base64.DEFAULT));
+
+ for (int i = 0; i < digest.length; i++) {
+ sb.append(hex.charAt((digest[i] >> 4) & 0xf));
+ sb.append(hex.charAt(digest[i] & 0xf));
+ if (i < digest.length - 1)
+ sb.append(":");
+ }
+ return sb.toString();
+ }
+
+ private void showConfirmationDialog(String key, String fingerprints) {
+ Intent dialogIntent = new Intent();
+
+ dialogIntent.setClassName("com.android.systemui",
+ "com.android.systemui.usb.UsbDebuggingActivity");
+ dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ dialogIntent.putExtra("key", key);
+ dialogIntent.putExtra("fingerprints", fingerprints);
+ try {
+ mContext.startActivity(dialogIntent);
+ } catch (ActivityNotFoundException e) {
+ Slog.e(TAG, "unable to start UsbDebuggingActivity");
+ }
+ }
+
+ private void writeKey(String key) {
+ File dataDir = Environment.getDataDirectory();
+ File adbDir = new File(dataDir, ADB_DIRECTORY);
+
+ if (!adbDir.exists()) {
+ Slog.e(TAG, "ADB data directory does not exist");
+ return;
+ }
+
+ try {
+ File keyFile = new File(adbDir, ADB_KEYS_FILE);
+
+ if (!keyFile.exists()) {
+ keyFile.createNewFile();
+ FileUtils.setPermissions(keyFile.toString(),
+ FileUtils.S_IRUSR | FileUtils.S_IWUSR |
+ FileUtils.S_IRGRP, -1, -1);
+ }
+
+ FileOutputStream fo = new FileOutputStream(keyFile, true);
+ fo.write(key.getBytes());
+ fo.write('\n');
+ fo.close();
+ }
+ catch (IOException ex) {
+ Slog.e(TAG, "Error writing key:" + ex);
+ }
+ }
+
+
+ public void setAdbEnabled(boolean enabled) {
+ mHandler.sendEmptyMessage(enabled ? UsbDebuggingHandler.MESSAGE_ADB_ENABLED
+ : UsbDebuggingHandler.MESSAGE_ADB_DISABLED);
+ }
+
+ public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
+ Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_ALLOW);
+ msg.arg1 = alwaysAllow ? 1 : 0;
+ msg.obj = publicKey;
+ mHandler.sendMessage(msg);
+ }
+
+ public void denyUsbDebugging() {
+ mHandler.sendEmptyMessage(UsbDebuggingHandler.MESSAGE_ADB_DENY);
+ }
+
+
+ public void dump(FileDescriptor fd, PrintWriter pw) {
+ pw.println(" USB Debugging State:");
+ pw.println(" Connected to adbd: " + (mOutputStream != null));
+ pw.println(" Last key received: " + mFingerprints);
+ pw.println(" User keys:");
+ try {
+ pw.println(FileUtils.readTextFile(new File("/data/misc/adb/adb_keys"), 0, null));
+ } catch (IOException e) {
+ pw.println("IOException: " + e);
+ }
+ pw.println(" System keys:");
+ try {
+ pw.println(FileUtils.readTextFile(new File("/adb_keys"), 0, null));
+ } catch (IOException e) {
+ pw.println("IOException: " + e);
+ }
+ }
+}
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index a115345..ddecf14 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -114,6 +114,7 @@ public class UsbDeviceManager {
private boolean mAudioSourceEnabled;
private Map<String, List<Pair<String, String>>> mOemModeMap;
private String[] mAccessoryStrings;
+ private UsbDebuggingManager mDebuggingManager;
private class AdbSettingsObserver extends ContentObserver {
public AdbSettingsObserver() {
@@ -166,6 +167,10 @@ public class UsbDeviceManager {
if (DEBUG) Slog.d(TAG, "accessory attached at boot");
startAccessoryMode();
}
+
+ if ("1".equals(SystemProperties.get("ro.adb.secure"))) {
+ mDebuggingManager = new UsbDebuggingManager(context);
+ }
}
public void systemReady() {
@@ -425,6 +430,9 @@ public class UsbDeviceManager {
setEnabledFunctions(mDefaultFunctions, true);
updateAdbNotification();
}
+ if (mDebuggingManager != null) {
+ mDebuggingManager.setAdbEnabled(mAdbEnabled);
+ }
}
private void setEnabledFunctions(String functions, boolean makeDefault) {
@@ -601,6 +609,9 @@ public class UsbDeviceManager {
if (mCurrentAccessory != null) {
mSettingsManager.accessoryAttached(mCurrentAccessory);
}
+ if (mDebuggingManager != null) {
+ mDebuggingManager.setAdbEnabled(mAdbEnabled);
+ }
break;
}
}
@@ -802,10 +813,25 @@ public class UsbDeviceManager {
return usbFunctions;
}
+ public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
+ if (mDebuggingManager != null) {
+ mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey);
+ }
+ }
+
+ public void denyUsbDebugging() {
+ if (mDebuggingManager != null) {
+ mDebuggingManager.denyUsbDebugging();
+ }
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw) {
if (mHandler != null) {
mHandler.dump(fd, pw);
}
+ if (mDebuggingManager != null) {
+ mDebuggingManager.dump(fd, pw);
+ }
}
private native String[] nativeGetAccessoryStrings();
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index 0205ef8..bebcd56 100644
--- a/services/java/com/android/server/usb/UsbService.java
+++ b/services/java/com/android/server/usb/UsbService.java
@@ -164,6 +164,16 @@ public class UsbService extends IUsbManager.Stub {
}
}
+ public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+ mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
+ }
+
+ public void denyUsbDebugging() {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+ mDeviceManager.denyUsbDebugging();
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
index 691e2aa..c25f010 100644
--- a/services/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -47,7 +47,7 @@ public class AppWindowAnimator {
final Transformation thumbnailTransformation = new Transformation();
/** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */
- ArrayList<WindowStateAnimator> mAllAppWinAnimators;
+ ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<WindowStateAnimator>();
static final Animation sDummyAnimation = new DummyAnimation();
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 142c60d..7d85d89 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -42,6 +42,7 @@ class ScreenRotationAnimation {
static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200;
final Context mContext;
+ final Display mDisplay;
Surface mSurface;
BlackFrame mCustomBlackFrame;
BlackFrame mExitingBlackFrame;
@@ -186,9 +187,10 @@ class ScreenRotationAnimation {
pw.println();
}
- public ScreenRotationAnimation(Context context, SurfaceSession session,
+ public ScreenRotationAnimation(Context context, Display display, SurfaceSession session,
boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) {
mContext = context;
+ mDisplay = display;
// Screenshot does NOT include rotation!
if (originalRotation == Surface.ROTATION_90
@@ -213,13 +215,13 @@ class ScreenRotationAnimation {
try {
try {
if (WindowManagerService.DEBUG_SURFACE_TRACE) {
- mSurface = new SurfaceTrace(session, 0, "FreezeSurface", Display.DEFAULT_DISPLAY,
- mWidth, mHeight,
- PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
+ mSurface = new SurfaceTrace(session, 0, "FreezeSurface",
+ mDisplay.getLayerStack(), mWidth, mHeight,
+ PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
} else {
- mSurface = new Surface(session, 0, "FreezeSurface", Display.DEFAULT_DISPLAY,
- mWidth, mHeight,
- PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
+ mSurface = new Surface(session, 0, "FreezeSurface",
+ mDisplay.getLayerStack(), mWidth, mHeight,
+ PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
}
if (!mSurface.isValid()) {
// Screenshot failed, punt.
diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/java/com/android/server/wm/StrictModeFlash.java
index 4b072c3..775aa0f 100644
--- a/services/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/java/com/android/server/wm/StrictModeFlash.java
@@ -22,8 +22,6 @@ import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Region;
-import android.util.DisplayMetrics;
-import android.util.Slog;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceSession;
@@ -39,7 +37,7 @@ class StrictModeFlash {
public StrictModeFlash(Display display, SurfaceSession session) {
try {
- mSurface = new Surface(session, 0, "StrictModeFlash", Display.DEFAULT_DISPLAY,
+ mSurface = new Surface(session, 0, "StrictModeFlash", display.getLayerStack(),
1, 1, PixelFormat.TRANSLUCENT, 0);
} catch (Surface.OutOfResourcesException e) {
return;
diff --git a/services/java/com/android/server/wm/Watermark.java b/services/java/com/android/server/wm/Watermark.java
index 12076d8..5901cc8 100644
--- a/services/java/com/android/server/wm/Watermark.java
+++ b/services/java/com/android/server/wm/Watermark.java
@@ -35,6 +35,7 @@ import android.view.Surface.OutOfResourcesException;
* Displays a watermark on top of the window manager's windows.
*/
class Watermark {
+ final Display mDisplay;
final String[] mTokens;
final String mText;
final Paint mTextPaint;
@@ -50,7 +51,7 @@ class Watermark {
int mLastDH;
boolean mDrawNeeded;
- Watermark(DisplayMetrics dm, SurfaceSession session, String[] tokens) {
+ Watermark(Display display, DisplayMetrics dm, SurfaceSession session, String[] tokens) {
if (false) {
Log.i(WindowManagerService.TAG, "*********************** WATERMARK");
for (int i=0; i<tokens.length; i++) {
@@ -58,6 +59,7 @@ class Watermark {
}
}
+ mDisplay = display;
mTokens = tokens;
StringBuilder builder = new StringBuilder(32);
@@ -112,7 +114,7 @@ class Watermark {
try {
mSurface = new Surface(session, 0,
- "WatermarkSurface", Display.DEFAULT_DISPLAY,
+ "WatermarkSurface", mDisplay.getLayerStack(),
1, 1, PixelFormat.TRANSLUCENT, 0);
mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER*100);
mSurface.setPosition(0, 0);
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index 0dbe692..1defa49 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -190,8 +190,8 @@ public class WindowAnimator {
for (int i = 0; i < N; i++) {
final AppWindowAnimParams params = layoutToAnim.mAppWindowAnimParams.get(i);
AppWindowAnimator appAnimator = params.mAppAnimator;
- appAnimator.mAllAppWinAnimators =
- new ArrayList<WindowStateAnimator>(params.mWinAnimators);
+ appAnimator.mAllAppWinAnimators.clear();
+ appAnimator.mAllAppWinAnimators.addAll(params.mWinAnimators);
mAppAnimators.add(appAnimator);
}
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 27c298c..fd90082 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -127,7 +127,7 @@ import android.view.SurfaceSession;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicy;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerPolicy.FakeWindow;
@@ -318,15 +318,25 @@ public class WindowManagerService extends IWindowManager.Stub
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- mPolicy.enableKeyguard(true);
- synchronized(mKeyguardTokenWatcher) {
- // lazily evaluate this next time we're asked to disable keyguard
- mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
- mKeyguardDisabled = false;
+ final String action = intent.getAction();
+ if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
+ mPolicy.enableKeyguard(true);
+ synchronized(mKeyguardTokenWatcher) {
+ // lazily evaluate this next time we're asked to disable keyguard
+ mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
+ mKeyguardDisabled = false;
+ }
+ } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ final int newUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+ Slog.v(TAG, "Switching user from " + mCurrentUserId + " to " + newUserId);
+ mCurrentUserId = newUserId;
}
}
};
+ // Current user when multi-user is enabled. Don't show windows of non-current user.
+ int mCurrentUserId;
+
final Context mContext;
final boolean mHaveInputMethods;
@@ -512,7 +522,8 @@ public class WindowManagerService extends IWindowManager.Stub
int mNextAppTransitionType = ActivityOptions.ANIM_NONE;
String mNextAppTransitionPackage;
Bitmap mNextAppTransitionThumbnail;
- boolean mNextAppTransitionDelayed;
+ // Used for thumbnail transitions. True if we're scaling up, false if scaling down
+ boolean mNextAppTransitionScaleUp;
IRemoteCallback mNextAppTransitionCallback;
int mNextAppTransitionEnter;
int mNextAppTransitionExit;
@@ -907,6 +918,8 @@ public class WindowManagerService extends IWindowManager.Stub
// Track changes to DevicePolicyManager state so we can enable/disable keyguard.
IntentFilter filter = new IntentFilter();
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+ // Track user switching.
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
mContext.registerReceiver(mBroadcastReceiver, filter);
mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
@@ -2140,7 +2153,7 @@ public class WindowManagerService extends IWindowManager.Stub
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, InputChannel outInputChannel) {
int res = mPolicy.checkAddPermission(attrs);
- if (res != WindowManagerImpl.ADD_OKAY) {
+ if (res != WindowManagerGlobal.ADD_OKAY) {
return res;
}
@@ -2156,7 +2169,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (mWindowMap.containsKey(client.asBinder())) {
Slog.w(TAG, "Window " + client + " is already added");
- return WindowManagerImpl.ADD_DUPLICATE_ADD;
+ return WindowManagerGlobal.ADD_DUPLICATE_ADD;
}
if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
@@ -2164,13 +2177,13 @@ public class WindowManagerService extends IWindowManager.Stub
if (attachedWindow == null) {
Slog.w(TAG, "Attempted to add window with token that is not a window: "
+ attrs.token + ". Aborting.");
- return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
+ return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
}
if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
&& attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
+ attrs.token + ". Aborting.");
- return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
+ return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
}
}
@@ -2181,22 +2194,22 @@ public class WindowManagerService extends IWindowManager.Stub
&& attrs.type <= LAST_APPLICATION_WINDOW) {
Slog.w(TAG, "Attempted to add application window with unknown token "
+ attrs.token + ". Aborting.");
- return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+ return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
if (attrs.type == TYPE_INPUT_METHOD) {
Slog.w(TAG, "Attempted to add input method window with unknown token "
+ attrs.token + ". Aborting.");
- return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+ return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
if (attrs.type == TYPE_WALLPAPER) {
Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
+ attrs.token + ". Aborting.");
- return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+ return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
if (attrs.type == TYPE_DREAM) {
Slog.w(TAG, "Attempted to add Dream window with unknown token "
+ attrs.token + ". Aborting.");
- return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+ return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
token = new WindowToken(this, attrs.token, -1, false);
addToken = true;
@@ -2206,35 +2219,35 @@ public class WindowManagerService extends IWindowManager.Stub
if (atoken == null) {
Slog.w(TAG, "Attempted to add window with non-application token "
+ token + ". Aborting.");
- return WindowManagerImpl.ADD_NOT_APP_TOKEN;
+ return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
} else if (atoken.removed) {
Slog.w(TAG, "Attempted to add window with exiting application token "
+ token + ". Aborting.");
- return WindowManagerImpl.ADD_APP_EXITING;
+ return WindowManagerGlobal.ADD_APP_EXITING;
}
if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
// No need for this guy!
if (localLOGV) Slog.v(
TAG, "**** NO NEED TO START: " + attrs.getTitle());
- return WindowManagerImpl.ADD_STARTING_NOT_NEEDED;
+ return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
}
} else if (attrs.type == TYPE_INPUT_METHOD) {
if (token.windowType != TYPE_INPUT_METHOD) {
Slog.w(TAG, "Attempted to add input method window with bad token "
+ attrs.token + ". Aborting.");
- return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+ return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
} else if (attrs.type == TYPE_WALLPAPER) {
if (token.windowType != TYPE_WALLPAPER) {
Slog.w(TAG, "Attempted to add wallpaper window with bad token "
+ attrs.token + ". Aborting.");
- return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+ return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
} else if (attrs.type == TYPE_DREAM) {
if (token.windowType != TYPE_DREAM) {
Slog.w(TAG, "Attempted to add Dream window with bad token "
+ attrs.token + ". Aborting.");
- return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+ return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
}
@@ -2246,13 +2259,13 @@ public class WindowManagerService extends IWindowManager.Stub
// continue.
Slog.w(TAG, "Adding window client " + client.asBinder()
+ " that is dead, aborting.");
- return WindowManagerImpl.ADD_APP_EXITING;
+ return WindowManagerGlobal.ADD_APP_EXITING;
}
mPolicy.adjustWindowParamsLw(win.mAttrs);
res = mPolicy.prepareAddWindowLw(win, attrs);
- if (res != WindowManagerImpl.ADD_OKAY) {
+ if (res != WindowManagerGlobal.ADD_OKAY) {
return res;
}
@@ -2268,7 +2281,7 @@ public class WindowManagerService extends IWindowManager.Stub
// From now on, no exceptions or errors allowed!
- res = WindowManagerImpl.ADD_OKAY;
+ res = WindowManagerGlobal.ADD_OKAY;
origId = Binder.clearCallingIdentity();
@@ -2312,10 +2325,10 @@ public class WindowManagerService extends IWindowManager.Stub
mPolicy.getContentInsetHintLw(attrs, outContentInsets);
if (mInTouchMode) {
- res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
+ res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
}
if (win.mAppToken == null || !win.mAppToken.clientHidden) {
- res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
+ res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
}
mInputMonitor.setUpdateInputWindowsNeededLw();
@@ -2747,7 +2760,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
winAnimator.mSurfaceDestroyDeferred =
- (flags&WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
+ (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
int attrChanges = 0;
int flagChanges = 0;
@@ -2966,7 +2979,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
mLayoutNeeded = true;
- win.mGivenInsetsPending = (flags&WindowManagerImpl.RELAYOUT_INSETS_PENDING) != 0;
+ win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
if (assignLayers) {
assignLayersLocked(win.getWindowList());
}
@@ -3009,10 +3022,10 @@ public class WindowManagerService extends IWindowManager.Stub
Binder.restoreCallingIdentity(origId);
- return (inTouchMode ? WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE : 0)
- | (toBeDisplayed ? WindowManagerImpl.RELAYOUT_RES_FIRST_TIME : 0)
- | (surfaceChanged ? WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED : 0)
- | (animating ? WindowManagerImpl.RELAYOUT_RES_ANIMATING : 0);
+ return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0)
+ | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0)
+ | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0)
+ | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0);
}
public void performDeferredDestroyWindow(Session session, IWindow client) {
@@ -3224,7 +3237,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
private Animation createThumbnailAnimationLocked(int transit,
- boolean enter, boolean thumb, boolean delayed) {
+ boolean enter, boolean thumb, boolean scaleUp) {
Animation a;
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
@@ -3234,7 +3247,6 @@ public class WindowManagerService extends IWindowManager.Stub
// it is the standard duration for that. Otherwise we use the longer
// task transition duration.
int duration;
- int delayDuration = delayed ? 270 : 0;
switch (transit) {
case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
@@ -3242,7 +3254,7 @@ public class WindowManagerService extends IWindowManager.Stub
com.android.internal.R.integer.config_shortAnimTime);
break;
default:
- duration = delayed ? 250 : 300;
+ duration = 250;
break;
}
// TOOD(multidisplay): For now assume all app animation is on the main screen.
@@ -3250,48 +3262,86 @@ public class WindowManagerService extends IWindowManager.Stub
if (thumb) {
// Animation for zooming thumbnail from its initial size to
// filling the screen.
- float scaleW = displayInfo.appWidth/thumbWidth;
- float scaleH = displayInfo.appHeight/thumbHeight;
-
- Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
- computePivot(mNextAppTransitionStartX, 1/scaleW),
- computePivot(mNextAppTransitionStartY, 1/scaleH));
- AnimationSet set = new AnimationSet(true);
- Animation alpha = new AlphaAnimation(1, 0);
- scale.setDuration(duration);
- scale.setInterpolator(
- new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
- set.addAnimation(scale);
- alpha.setDuration(duration);
- set.addAnimation(alpha);
- set.setFillBefore(true);
- if (delayDuration > 0) {
- set.setStartOffset(delayDuration);
+ if (scaleUp) {
+ float scaleW = displayInfo.appWidth / thumbWidth;
+ float scaleH = displayInfo.appHeight / thumbHeight;
+
+ Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
+ computePivot(mNextAppTransitionStartX, 1 / scaleW),
+ computePivot(mNextAppTransitionStartY, 1 / scaleH));
+ AnimationSet set = new AnimationSet(true);
+ Animation alpha = new AlphaAnimation(1, 0);
+ scale.setDuration(duration);
+ scale.setInterpolator(
+ new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
+ set.addAnimation(scale);
+ alpha.setDuration(duration);
+ set.addAnimation(alpha);
+ set.setFillBefore(true);
+ a = set;
+ } else {
+ float scaleW = displayInfo.appWidth / thumbWidth;
+ float scaleH = displayInfo.appHeight / thumbHeight;
+
+ Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
+ computePivot(mNextAppTransitionStartX, 1 / scaleW),
+ computePivot(mNextAppTransitionStartY, 1 / scaleH));
+ AnimationSet set = new AnimationSet(true);
+ Animation alpha = new AlphaAnimation(1, 1);
+ scale.setDuration(duration);
+ scale.setInterpolator(
+ new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
+ set.addAnimation(scale);
+ alpha.setDuration(duration);
+ set.addAnimation(alpha);
+ set.setFillBefore(true);
+
+ a = set;
}
- a = set;
} else if (enter) {
// Entering app zooms out from the center of the thumbnail.
- float scaleW = thumbWidth / displayInfo.appWidth;
- float scaleH = thumbHeight / displayInfo.appHeight;
- Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
- computePivot(mNextAppTransitionStartX, scaleW),
- computePivot(mNextAppTransitionStartY, scaleH));
- scale.setDuration(duration);
- scale.setInterpolator(
- new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
- scale.setFillBefore(true);
- if (delayDuration > 0) {
- scale.setStartOffset(delayDuration);
+ if (scaleUp) {
+ float scaleW = thumbWidth / displayInfo.appWidth;
+ float scaleH = thumbHeight / displayInfo.appHeight;
+ Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
+ computePivot(mNextAppTransitionStartX, scaleW),
+ computePivot(mNextAppTransitionStartY, scaleH));
+ scale.setDuration(duration);
+ scale.setInterpolator(
+ new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
+ scale.setFillBefore(true);
+ a = scale;
+ } else {
+ // noop animation
+ a = new AlphaAnimation(1, 1);
+ a.setDuration(duration);
}
- a = scale;
} else {
- if (delayed) {
- a = new AlphaAnimation(1, 0);
- a.setStartOffset(0);
- a.setDuration(delayDuration - 120);
- a.setBackgroundColor(0xFF000000);
+ // Exiting app
+ if (scaleUp) {
+ // noop animation
+ a = new AlphaAnimation(1, 1);
+ a.setDuration(duration);
} else {
- a = createExitAnimationLocked(transit, duration);
+ float scaleW = thumbWidth / displayInfo.appWidth;
+ float scaleH = thumbHeight / displayInfo.appHeight;
+ Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
+ computePivot(mNextAppTransitionStartX, scaleW),
+ computePivot(mNextAppTransitionStartY, scaleH));
+ scale.setDuration(duration);
+ scale.setInterpolator(
+ new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
+ scale.setFillBefore(true);
+ AnimationSet set = new AnimationSet(true);
+ Animation alpha = new AlphaAnimation(1, 0);
+ set.addAnimation(scale);
+ alpha.setDuration(duration);
+ alpha.setInterpolator(new DecelerateInterpolator(
+ THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
+ set.addAnimation(alpha);
+ set.setFillBefore(true);
+ set.setZAdjustment(Animation.ZORDER_TOP);
+ a = set;
}
}
a.setFillAfter(true);
@@ -3326,14 +3376,14 @@ public class WindowManagerService extends IWindowManager.Stub
"applyAnimation: wtoken=" + wtoken
+ " anim=" + a + " nextAppTransition=ANIM_SCALE_UP"
+ " transit=" + transit + " Callers " + Debug.getCallers(3));
- } else if (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL ||
- mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_DELAYED) {
- boolean delayed = (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_DELAYED);
- a = createThumbnailAnimationLocked(transit, enter, false, delayed);
+ } else if (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP ||
+ mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN) {
+ boolean scaleUp = (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP);
+ a = createThumbnailAnimationLocked(transit, enter, false, scaleUp);
initialized = true;
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
- String animName = delayed ? "ANIM_THUMBNAIL_DELAYED" : "ANIM_THUMBNAIL";
+ String animName = scaleUp ? "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
+ " anim=" + a + " nextAppTransition=" + animName
+ " transit=" + transit + " Callers " + Debug.getCallers(3));
@@ -4008,14 +4058,14 @@ public class WindowManagerService extends IWindowManager.Stub
}
public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
- int startY, IRemoteCallback startedCallback, boolean delayed) {
+ int startY, IRemoteCallback startedCallback, boolean scaleUp) {
synchronized(mWindowMap) {
if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
- mNextAppTransitionType = delayed
- ? ActivityOptions.ANIM_THUMBNAIL_DELAYED : ActivityOptions.ANIM_THUMBNAIL;
+ mNextAppTransitionType = scaleUp
+ ? ActivityOptions.ANIM_THUMBNAIL_SCALE_UP : ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
mNextAppTransitionPackage = null;
mNextAppTransitionThumbnail = srcThumb;
- mNextAppTransitionDelayed = delayed;
+ mNextAppTransitionScaleUp = scaleUp;
mNextAppTransitionStartX = startX;
mNextAppTransitionStartY = startY;
scheduleAnimationCallback(mNextAppTransitionCallback);
@@ -5219,14 +5269,14 @@ public class WindowManagerService extends IWindowManager.Stub
// Called by window manager policy. Not exposed externally.
@Override
- public void shutdown() {
- ShutdownThread.shutdown(mContext, true);
+ public void shutdown(boolean confirm) {
+ ShutdownThread.shutdown(mContext, confirm);
}
// Called by window manager policy. Not exposed externally.
@Override
- public void rebootSafeMode() {
- ShutdownThread.rebootSafeMode(mContext, true);
+ public void rebootSafeMode(boolean confirm) {
+ ShutdownThread.rebootSafeMode(mContext, confirm);
}
public void setInputFilter(IInputFilter filter) {
@@ -8329,15 +8379,23 @@ public class WindowManagerService extends IWindowManager.Stub
NN = mOpeningApps.size();
for (i=0; i<NN; i++) {
AppWindowToken wtoken = mOpeningApps.get(i);
+ final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
- wtoken.mAppAnimator.clearThumbnail();
+ appAnimator.clearThumbnail();
wtoken.reportedVisible = false;
wtoken.inPendingTransaction = false;
- wtoken.mAppAnimator.animation = null;
+ appAnimator.animation = null;
setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
wtoken.updateReportedVisibilityLocked();
wtoken.waitingToShow = false;
- mAnimator.mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked();
+
+ appAnimator.mAllAppWinAnimators.clear();
+ final int N = wtoken.allAppWindows.size();
+ for (int j = 0; j < N; j++) {
+ appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
+ }
+ mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
+
if (animLp != null) {
int layer = -1;
for (int j=0; j<wtoken.windows.size(); j++) {
@@ -8392,7 +8450,7 @@ public class WindowManagerService extends IWindowManager.Stub
drawSurface.release();
topOpeningApp.mAppAnimator.thumbnailLayer = topOpeningLayer;
Animation anim = createThumbnailAnimationLocked(
- transit, true, true, mNextAppTransitionDelayed);
+ transit, true, true, mNextAppTransitionScaleUp);
topOpeningApp.mAppAnimator.thumbnailAnimation = anim;
anim.restrictDuration(MAX_ANIMATION_DURATION);
anim.scaleCurrentDuration(mTransitionAnimationScale);
@@ -9591,7 +9649,7 @@ public class WindowManagerService extends IWindowManager.Stub
// TODO(multidisplay): rotation on main screen only.
DisplayInfo displayInfo = getDefaultDisplayContent().getDisplayInfo();
- mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
+ mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext, mDisplay,
mFxSession, inTransaction, displayInfo.logicalWidth, displayInfo.logicalHeight,
mDisplay.getRotation());
}
@@ -9704,7 +9762,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (line != null) {
String[] toks = line.split("%");
if (toks != null && toks.length > 0) {
- mWatermark = new Watermark(mRealDisplayMetrics, mFxSession, toks);
+ mWatermark = new Watermark(mDisplay, mRealDisplayMetrics, mFxSession, toks);
}
}
} catch (FileNotFoundException e) {
@@ -10163,15 +10221,15 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(" mNextAppTransitionStartHeight=");
pw.println(mNextAppTransitionStartHeight);
break;
- case ActivityOptions.ANIM_THUMBNAIL:
- case ActivityOptions.ANIM_THUMBNAIL_DELAYED:
+ case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP:
+ case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN:
pw.print(" mNextAppTransitionThumbnail=");
pw.print(mNextAppTransitionThumbnail);
pw.print(" mNextAppTransitionStartX=");
pw.print(mNextAppTransitionStartX);
pw.print(" mNextAppTransitionStartY=");
pw.println(mNextAppTransitionStartY);
- pw.print(" mNextAppTransitionDelayed="); pw.println(mNextAppTransitionDelayed);
+ pw.print(" mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp);
break;
}
if (mNextAppTransitionCallback != null) {
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 43ff398..a52e1d7 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -22,6 +22,9 @@ import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import com.android.server.input.InputWindowHandle;
@@ -33,7 +36,9 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.IBinder;
+import android.os.Process;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.Gravity;
@@ -257,6 +262,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {
DisplayContent mDisplayContent;
+ // UserId and appId of the owner. Don't display windows of non-current user.
+ final int mOwnerUid;
+
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState attachedWindow, int seq, WindowManager.LayoutParams a,
int viewVisibility, final DisplayContent displayContent) {
@@ -264,6 +272,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mSession = s;
mClient = c;
mToken = token;
+ mOwnerUid = s.mUid;
mAttrs.copyFrom(a);
mViewVisibility = viewVisibility;
mDisplayContent = displayContent;
@@ -894,6 +903,11 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
boolean showLw(boolean doAnimation, boolean requestAnim) {
+ if (isOtherUsersAppWindow()) {
+ Slog.w(TAG, "Current user " + mService.mCurrentUserId + " trying to display "
+ + this + ", type " + mAttrs.type + ", belonging to " + mOwnerUid);
+ return false;
+ }
if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
// Already showing.
return false;
@@ -970,6 +984,17 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return mClient.asBinder().isBinderAlive();
}
+ boolean isOtherUsersAppWindow() {
+ final int type = mAttrs.type;
+ if ((UserHandle.getUserId(mOwnerUid) != mService.mCurrentUserId)
+ && (mOwnerUid != Process.SYSTEM_UID)
+ && (type >= TYPE_BASE_APPLICATION) && (type <= LAST_APPLICATION_WINDOW)
+ && (type != TYPE_APPLICATION_STARTING)) {
+ return true;
+ }
+ return false;
+ }
+
private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
outRegion.set(
frame.left + inset.left, frame.top + inset.top,
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index d931426..69bad81 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -474,24 +474,14 @@ class WindowStateAnimator {
private final Point mSize = new Point();
private final Rect mWindowCrop = new Rect();
private boolean mShown = false;
- private int mDisplayId;
- private String mName = "Not named";
+ private int mLayerStack;
+ private String mName;
public SurfaceTrace(SurfaceSession s,
- int pid, int displayId, int w, int h, int format, int flags) throws
- OutOfResourcesException {
- super(s, pid, displayId, w, h, format, flags);
- mSize.set(w, h);
- mDisplayId = displayId;
- Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by "
- + Debug.getCallers(3));
- }
-
- public SurfaceTrace(SurfaceSession s,
- int pid, String name, int displayId, int w, int h, int format, int flags)
+ int pid, String name, int layerStack, int w, int h, int format, int flags)
throws OutOfResourcesException {
- super(s, pid, name, displayId, w, h, format, flags);
- mName = name;
+ super(s, pid, name, layerStack, w, h, format, flags);
+ mName = name != null ? name : "Not named";
mSize.set(w, h);
Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by "
+ Debug.getCallers(3));
@@ -550,10 +540,10 @@ class WindowStateAnimator {
}
@Override
- public void setDisplayId(int displayId) {
- super.setDisplayId(displayId);
- mDisplayId = displayId;
- Slog.v(SURFACE_TAG, "setDisplayId: " + this + ". Called by " + Debug.getCallers(3));
+ public void setLayerStack(int layerStack) {
+ super.setLayerStack(layerStack);
+ mLayerStack = layerStack;
+ Slog.v(SURFACE_TAG, "setLayerStack: " + this + ". Called by " + Debug.getCallers(3));
}
@Override
@@ -597,7 +587,7 @@ class WindowStateAnimator {
@Override
public String toString() {
return "Surface " + Integer.toHexString(System.identityHashCode(this)) + " "
- + mName + " (" + mDisplayId + "): shown=" + mShown + " layer=" + mLayer
+ + mName + " (" + mLayerStack + "): shown=" + mShown + " layer=" + mLayer
+ " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y
+ " " + mSize.x + "x" + mSize.y
+ " crop=" + mWindowCrop.toShortString();
@@ -1300,6 +1290,11 @@ class WindowStateAnimator {
// This must be called while inside a transaction.
boolean performShowLocked() {
+ if (mWin.isOtherUsersAppWindow()) {
+ Slog.w(TAG, "Current user " + mService.mCurrentUserId + " trying to display "
+ + this + ", type " + mWin.mAttrs.type + ", belonging to " + mWin.mOwnerUid);
+ return false;
+ }
if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW &&
mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) {
RuntimeException e = null;
diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp
index ca6f206..e6133af 100644
--- a/services/jni/com_android_server_BatteryService.cpp
+++ b/services/jni/com_android_server_BatteryService.cpp
@@ -42,6 +42,7 @@ struct FieldIds {
// members
jfieldID mAcOnline;
jfieldID mUsbOnline;
+ jfieldID mWirelessOnline;
jfieldID mBatteryStatus;
jfieldID mBatteryHealth;
jfieldID mBatteryPresent;
@@ -71,6 +72,7 @@ static BatteryManagerConstants gConstants;
struct PowerSupplyPaths {
char* acOnlinePath;
char* usbOnlinePath;
+ char* wirelessOnlinePath;
char* batteryStatusPath;
char* batteryHealthPath;
char* batteryPresentPath;
@@ -88,8 +90,8 @@ static jint getBatteryStatus(const char* status)
switch (status[0]) {
case 'C': return gConstants.statusCharging; // Charging
case 'D': return gConstants.statusDischarging; // Discharging
- case 'F': return gConstants.statusFull; // Not charging
- case 'N': return gConstants.statusNotCharging; // Full
+ case 'F': return gConstants.statusFull; // Full
+ case 'N': return gConstants.statusNotCharging; // Not charging
case 'U': return gConstants.statusUnknown; // Unknown
default: {
@@ -198,6 +200,7 @@ static void android_server_BatteryService_update(JNIEnv* env, jobject obj)
{
setBooleanField(env, obj, gPaths.acOnlinePath, gFieldIds.mAcOnline);
setBooleanField(env, obj, gPaths.usbOnlinePath, gFieldIds.mUsbOnline);
+ setBooleanField(env, obj, gPaths.wirelessOnlinePath, gFieldIds.mWirelessOnline);
setBooleanField(env, obj, gPaths.batteryPresentPath, gFieldIds.mBatteryPresent);
setIntField(env, obj, gPaths.batteryCapacityPath, gFieldIds.mBatteryLevel);
@@ -260,6 +263,11 @@ int register_android_server_BatteryService(JNIEnv* env)
if (access(path, R_OK) == 0)
gPaths.usbOnlinePath = strdup(path);
}
+ else if (strcmp(buf, "Wireless") == 0) {
+ snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0)
+ gPaths.wirelessOnlinePath = strdup(path);
+ }
else if (strcmp(buf, "Battery") == 0) {
snprintf(path, sizeof(path), "%s/%s/status", POWER_SUPPLY_PATH, name);
if (access(path, R_OK) == 0)
@@ -307,6 +315,8 @@ int register_android_server_BatteryService(JNIEnv* env)
ALOGE("acOnlinePath not found");
if (!gPaths.usbOnlinePath)
ALOGE("usbOnlinePath not found");
+ if (!gPaths.wirelessOnlinePath)
+ ALOGE("wirelessOnlinePath not found");
if (!gPaths.batteryStatusPath)
ALOGE("batteryStatusPath not found");
if (!gPaths.batteryHealthPath)
@@ -331,6 +341,7 @@ int register_android_server_BatteryService(JNIEnv* env)
gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");
gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z");
+ gFieldIds.mWirelessOnline = env->GetFieldID(clazz, "mWirelessOnline", "Z");
gFieldIds.mBatteryStatus = env->GetFieldID(clazz, "mBatteryStatus", "I");
gFieldIds.mBatteryHealth = env->GetFieldID(clazz, "mBatteryHealth", "I");
gFieldIds.mBatteryPresent = env->GetFieldID(clazz, "mBatteryPresent", "Z");
@@ -341,6 +352,7 @@ int register_android_server_BatteryService(JNIEnv* env)
LOG_FATAL_IF(gFieldIds.mAcOnline == NULL, "Unable to find BatteryService.AC_ONLINE_PATH");
LOG_FATAL_IF(gFieldIds.mUsbOnline == NULL, "Unable to find BatteryService.USB_ONLINE_PATH");
+ LOG_FATAL_IF(gFieldIds.mWirelessOnline == NULL, "Unable to find BatteryService.WIRELESS_ONLINE_PATH");
LOG_FATAL_IF(gFieldIds.mBatteryStatus == NULL, "Unable to find BatteryService.BATTERY_STATUS_PATH");
LOG_FATAL_IF(gFieldIds.mBatteryHealth == NULL, "Unable to find BatteryService.BATTERY_HEALTH_PATH");
LOG_FATAL_IF(gFieldIds.mBatteryPresent == NULL, "Unable to find BatteryService.BATTERY_PRESENT_PATH");
diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp
index 701b15a..495d4ab 100644
--- a/services/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/jni/com_android_server_input_InputManagerService.cpp
@@ -63,7 +63,7 @@ static const float POINTER_SPEED_EXPONENT = 1.0f / 4;
static struct {
jmethodID notifyConfigurationChanged;
jmethodID notifyInputDevicesChanged;
- jmethodID notifyLidSwitchChanged;
+ jmethodID notifySwitch;
jmethodID notifyInputChannelBroken;
jmethodID notifyANR;
jmethodID filterInputEvent;
@@ -578,14 +578,9 @@ void NativeInputManager::notifySwitch(nsecs_t when, int32_t switchCode,
JNIEnv* env = jniEnv();
- switch (switchCode) {
- case SW_LID:
- // When switch value is set indicates lid is closed.
- env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyLidSwitchChanged,
- when, switchValue == 0 /*lidOpen*/);
- checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
- break;
- }
+ env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifySwitch,
+ when, switchCode, switchValue);
+ checkAndClearExceptionFromCallback(env, "notifySwitch");
}
void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
@@ -1410,8 +1405,8 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_METHOD_ID(gServiceClassInfo.notifyInputDevicesChanged, clazz,
"notifyInputDevicesChanged", "([Landroid/view/InputDevice;)V");
- GET_METHOD_ID(gServiceClassInfo.notifyLidSwitchChanged, clazz,
- "notifyLidSwitchChanged", "(JZ)V");
+ GET_METHOD_ID(gServiceClassInfo.notifySwitch, clazz,
+ "notifySwitch", "(JII)V");
GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz,
"notifyInputChannelBroken", "(Lcom/android/server/input/InputWindowHandle;)V");
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 3f66de6..89b2474 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -33,6 +33,7 @@
<uses-permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING" />
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.MANAGE_USERS" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index bc3649c..59a86c2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -16,35 +16,23 @@
package com.android.server.pm;
-import com.android.server.pm.UserManagerService;
-
+import android.content.Context;
import android.content.pm.UserInfo;
import android.os.Debug;
import android.os.Environment;
+import android.os.UserManager;
import android.test.AndroidTestCase;
import java.util.List;
-/** Test {@link UserManagerService} functionality. */
+/** Test {@link UserManager} functionality. */
public class UserManagerTest extends AndroidTestCase {
- UserManagerService mUserManager = null;
+ UserManager mUserManager = null;
@Override
public void setUp() throws Exception {
- mUserManager = new UserManagerService(Environment.getExternalStorageDirectory(),
- Environment.getExternalStorageDirectory());
- }
-
- @Override
- public void tearDown() throws Exception {
- List<UserInfo> users = mUserManager.getUsers();
- // Remove all except the primary user
- for (UserInfo user : users) {
- if (!user.isPrimary()) {
- mUserManager.removeUser(user.id);
- }
- }
+ mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
}
public void testHasPrimary() throws Exception {
@@ -52,12 +40,10 @@ public class UserManagerTest extends AndroidTestCase {
}
public void testAddUser() throws Exception {
- final UserManagerService details = mUserManager;
-
- UserInfo userInfo = details.createUser("Guest 1", UserInfo.FLAG_GUEST);
+ UserInfo userInfo = mUserManager.createUser("Guest 1", UserInfo.FLAG_GUEST);
assertTrue(userInfo != null);
- List<UserInfo> list = details.getUsers();
+ List<UserInfo> list = mUserManager.getUsers();
boolean found = false;
for (UserInfo user : list) {
if (user.id == userInfo.id && user.name.equals("Guest 1")
@@ -68,13 +54,12 @@ public class UserManagerTest extends AndroidTestCase {
}
}
assertTrue(found);
+ mUserManager.removeUser(userInfo.id);
}
public void testAdd2Users() throws Exception {
- final UserManagerService details = mUserManager;
-
- UserInfo user1 = details.createUser("Guest 1", UserInfo.FLAG_GUEST);
- UserInfo user2 = details.createUser("User 2", UserInfo.FLAG_ADMIN);
+ UserInfo user1 = mUserManager.createUser("Guest 1", UserInfo.FLAG_GUEST);
+ UserInfo user2 = mUserManager.createUser("User 2", UserInfo.FLAG_ADMIN);
assertTrue(user1 != null);
assertTrue(user2 != null);
@@ -82,14 +67,14 @@ public class UserManagerTest extends AndroidTestCase {
assertTrue(findUser(0));
assertTrue(findUser(user1.id));
assertTrue(findUser(user2.id));
+ mUserManager.removeUser(user1.id);
+ mUserManager.removeUser(user2.id);
}
public void testRemoveUser() throws Exception {
- final UserManagerService details = mUserManager;
+ UserInfo userInfo = mUserManager.createUser("Guest 1", UserInfo.FLAG_GUEST);
- UserInfo userInfo = details.createUser("Guest 1", UserInfo.FLAG_GUEST);
-
- details.removeUser(userInfo.id);
+ mUserManager.removeUser(userInfo.id);
assertFalse(findUser(userInfo.id));
}
@@ -104,4 +89,18 @@ public class UserManagerTest extends AndroidTestCase {
}
return false;
}
+
+ public void testSerialNumber() {
+ UserInfo user1 = mUserManager.createUser("User 1", UserInfo.FLAG_RESTRICTED);
+ int serialNumber1 = user1.serialNumber;
+ assertEquals(serialNumber1, mUserManager.getUserSerialNumber(user1.id));
+ assertEquals(user1.id, mUserManager.getUserHandle(serialNumber1));
+ mUserManager.removeUser(user1.id);
+ UserInfo user2 = mUserManager.createUser("User 2", UserInfo.FLAG_RESTRICTED);
+ int serialNumber2 = user2.serialNumber;
+ assertFalse(serialNumber1 == serialNumber2);
+ assertEquals(serialNumber2, mUserManager.getUserSerialNumber(user2.id));
+ assertEquals(user2.id, mUserManager.getUserHandle(serialNumber2));
+ mUserManager.removeUser(user2.id);
+ }
}
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 36f2c14..12ad4fe 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -38,6 +38,8 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.os.UserHandle;
+import android.view.CompatibilityInfoHolder;
import java.io.File;
import java.io.FileInputStream;
@@ -304,12 +306,12 @@ public class MockContext extends Context {
}
@Override
- public void sendBroadcastToUser(Intent intent, int userId) {
+ public void sendBroadcastAsUser(Intent intent, UserHandle user) {
throw new UnsupportedOperationException();
}
@Override
- public void sendOrderedBroadcastToUser(Intent intent, int userId,
+ public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
BroadcastReceiver resultReceiver, Handler scheduler,
int initialCode, String initialData, Bundle initialExtras) {
throw new UnsupportedOperationException();
@@ -486,4 +488,10 @@ public class MockContext extends Context {
public boolean isRestricted() {
throw new UnsupportedOperationException();
}
+
+ /** @hide */
+ @Override
+ public CompatibilityInfoHolder getCompatibilityInfo() {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index ef14404..0fb51f0 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -39,6 +39,7 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
@@ -479,7 +480,8 @@ public class MockPackageManager extends PackageManager {
* @hide - to match hiding in superclass
*/
@Override
- public void getPackageSizeInfo(String packageName, IPackageStatsObserver observer) {
+ public void getPackageSizeInfo(String packageName, int userHandle,
+ IPackageStatsObserver observer) {
throw new UnsupportedOperationException();
}
@@ -519,6 +521,16 @@ public class MockPackageManager extends PackageManager {
throw new UnsupportedOperationException();
}
+ /**
+ * @hide
+ */
+ @Override
+ public void installPackageWithVerificationAndEncryption(Uri packageURI,
+ IPackageInstallObserver observer, int flags, String installerPackageName,
+ VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public void verifyPendingInstall(int id, int verificationCode) {
throw new UnsupportedOperationException();
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index 0577dbb..9599b19 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -30,6 +30,7 @@ import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.graphics.Bitmap;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -187,7 +188,7 @@ public class ActivityTestMain extends Activity {
menu.add("Send to user 1!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override public boolean onMenuItemClick(MenuItem item) {
Intent intent = new Intent(ActivityTestMain.this, UserTarget.class);
- sendOrderedBroadcastToUser(intent, 1, new BroadcastResultReceiver(),
+ sendOrderedBroadcastAsUser(intent, new UserHandle(1), new BroadcastResultReceiver(),
null, Activity.RESULT_OK, null, null);
return true;
}
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/SingleUserProvider.java b/tests/ActivityTests/src/com/google/android/test/activity/SingleUserProvider.java
index 83785e4..1e7b8f4 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/SingleUserProvider.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/SingleUserProvider.java
@@ -21,7 +21,7 @@ import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Process;
+import android.os.UserHandle;
public class SingleUserProvider extends ContentProvider {
static final String AUTHORITY = "com.google.android.test.activity.single_user";
@@ -60,7 +60,7 @@ public class SingleUserProvider extends ContentProvider {
@Override
public Bundle call(String method, String arg, Bundle extras) {
Bundle res = new Bundle();
- res.putInt("user", Process.myUserHandle());
+ res.putInt("user", UserHandle.myUserId());
return res;
}
}
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/SingleUserReceiver.java b/tests/ActivityTests/src/com/google/android/test/activity/SingleUserReceiver.java
index 9295cf4..8afa478 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/SingleUserReceiver.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/SingleUserReceiver.java
@@ -21,12 +21,13 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Process;
+import android.os.UserHandle;
public class SingleUserReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle res = getResultExtras(true);
- res.putInt("user", Process.myUserHandle());
+ res.putInt("user", UserHandle.myUserId());
setResultExtras(res);
}
}
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/UserTarget.java b/tests/ActivityTests/src/com/google/android/test/activity/UserTarget.java
index 9c6a9f1..47539a1 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/UserTarget.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/UserTarget.java
@@ -21,6 +21,7 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Process;
+import android.os.UserHandle;
import android.util.Log;
public class UserTarget extends BroadcastReceiver {
@@ -28,7 +29,7 @@ public class UserTarget extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Log.i("ActivityTest", "Received: " + intent);
Bundle res = getResultExtras(true);
- res.putInt("user", Process.myUserHandle());
+ res.putInt("user", UserHandle.myUserId());
setResultExtras(res);
}
}
diff --git a/tests/MemoryUsage/Android.mk b/tests/MemoryUsage/Android.mk
new file mode 100644
index 0000000..e7bfb4f
--- /dev/null
+++ b/tests/MemoryUsage/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := MemoryUsage
+
+LOCAL_SDK_VERSION := 7
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH)) \ No newline at end of file
diff --git a/tests/MemoryUsage/AndroidManifest.xml b/tests/MemoryUsage/AndroidManifest.xml
new file mode 100644
index 0000000..3932e5b
--- /dev/null
+++ b/tests/MemoryUsage/AndroidManifest.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.memoryusage">
+ <instrumentation android:label="Memory usage instrumentation"
+ android:name="com.android.tests.memoryusage.MemoryUsageInstrumentation"
+ android:targetPackage="com.android.tests.memoryusage" />
+
+ <application android:label="Memory Usage Test">
+ <uses-library android:name="android.test.runner" />
+ </application>
+</manifest> \ No newline at end of file
diff --git a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageInstrumentation.java b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageInstrumentation.java
new file mode 100644
index 0000000..ed6d7e6
--- /dev/null
+++ b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageInstrumentation.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tests.memoryusage;
+
+import android.os.Bundle;
+import android.test.InstrumentationTestRunner;
+
+/**
+ * InstrumentationTestRunner for use with the {@link MemoryUsageTest}.
+ */
+public class MemoryUsageInstrumentation extends InstrumentationTestRunner {
+
+ private Bundle arguments;
+
+ @Override
+ public void onCreate(Bundle arguments) {
+ this.arguments = arguments;
+ super.onCreate(arguments);
+ }
+
+ public Bundle getBundle() {
+ return arguments;
+ }
+
+}
diff --git a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
new file mode 100644
index 0000000..f26edc6
--- /dev/null
+++ b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tests.memoryusage;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessErrorStateInfo;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.Debug.MemoryInfo;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This test is intended to measure the amount of memory applications use when
+ * they start. Names of the applications are passed in command line, and the
+ * test starts each application, waits until its memory usage is stabilized and
+ * reports the total PSS in kilobytes of each processes.
+ * The instrumentation expects the following key to be passed on the command line:
+ * apps - A list of applications to start and their corresponding result keys
+ * in the following format:
+ * -e apps <app name>^<result key>|<app name>^<result key>
+ */
+public class MemoryUsageTest extends InstrumentationTestCase {
+
+ private static final int SLEEP_TIME = 1000;
+ private static final int THRESHOLD = 1024;
+ private static final int MAX_ITERATIONS = 10;
+ private static final int MIN_ITERATIONS = 4;
+
+ private static final String TAG = "MemoryUsageInstrumentation";
+ private static final String KEY_APPS = "apps";
+
+ private Map<String, Intent> nameToIntent;
+ private Map<String, String> nameToProcess;
+ private Map<String, String> nameToResultKey;
+
+ public void testMemory() {
+ MemoryUsageInstrumentation instrumentation =
+ (MemoryUsageInstrumentation) getInstrumentation();
+ Bundle args = instrumentation.getBundle();
+
+ createMappings();
+ parseArgs(args);
+
+ Bundle results = new Bundle();
+ for (String app : nameToResultKey.keySet()) {
+ String processName;
+ try {
+ processName = startApp(app);
+ measureMemory(app, processName, results);
+ } catch (NameNotFoundException e) {
+ Log.i(TAG, "Application " + app + " not found");
+ }
+
+ }
+ instrumentation.sendStatus(0, results);
+ }
+
+ private void parseArgs(Bundle args) {
+ nameToResultKey = new HashMap<String, String>();
+ String appList = args.getString(KEY_APPS);
+
+ if (appList == null)
+ return;
+
+ String appNames[] = appList.split("\\|");
+ for (String pair : appNames) {
+ String[] parts = pair.split("\\^");
+ if (parts.length != 2) {
+ Log.e(TAG, "The apps key is incorectly formatted");
+ fail();
+ }
+
+ nameToResultKey.put(parts[0], parts[1]);
+ }
+ }
+
+ private void createMappings() {
+ nameToIntent = new HashMap<String, Intent>();
+ nameToProcess = new HashMap<String, String>();
+
+ PackageManager pm = getInstrumentation().getContext()
+ .getPackageManager();
+ Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
+ intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
+ List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
+ if (ris == null || ris.isEmpty()) {
+ Log.i(TAG, "Could not find any apps");
+ } else {
+ for (ResolveInfo ri : ris) {
+ Log.i(TAG, "Name: " + ri.loadLabel(pm).toString()
+ + " package: " + ri.activityInfo.packageName
+ + " name: " + ri.activityInfo.name);
+ Intent startIntent = new Intent(intentToResolve);
+ startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ startIntent.setClassName(ri.activityInfo.packageName,
+ ri.activityInfo.name);
+ nameToIntent.put(ri.loadLabel(pm).toString(), startIntent);
+ nameToProcess.put(ri.loadLabel(pm).toString(),
+ ri.activityInfo.processName);
+ }
+ }
+ }
+
+ private String startApp(String appName) throws NameNotFoundException {
+ Log.i(TAG, "Starting " + appName);
+
+ if (!nameToProcess.containsKey(appName))
+ throw new NameNotFoundException("Could not find: " + appName);
+
+ String process = nameToProcess.get(appName);
+ Intent startIntent = nameToIntent.get(appName);
+ getInstrumentation().getContext().startActivity(startIntent);
+ return process;
+ }
+
+ private void measureMemory(String appName, String processName,
+ Bundle results) {
+ List<Integer> pssData = new ArrayList<Integer>();
+ int pss = 0;
+ int iteration = 0;
+ while (iteration < MAX_ITERATIONS) {
+ sleep();
+ pss = getPss(processName);
+ Log.i(TAG, appName + "=" + pss);
+ if (pss < 0) {
+ reportError(appName, processName, results);
+ return;
+ }
+ pssData.add(pss);
+ if (iteration >= MIN_ITERATIONS && stabilized(pssData)) {
+ results.putInt(nameToResultKey.get(appName), pss);
+ return;
+ }
+ iteration++;
+ }
+
+ Log.w(TAG, appName + " memory usage did not stabilize");
+ results.putInt(appName, average(pssData));
+ }
+
+ private int average(List<Integer> pssData) {
+ int sum = 0;
+ for (int sample : pssData) {
+ sum += sample;
+ }
+
+ return sum / pssData.size();
+ }
+
+ private boolean stabilized(List<Integer> pssData) {
+ if (pssData.size() < 3)
+ return false;
+ int diff1 = Math.abs(pssData.get(pssData.size() - 1) - pssData.get(pssData.size() - 2));
+ int diff2 = Math.abs(pssData.get(pssData.size() - 2) - pssData.get(pssData.size() - 3));
+
+ Log.i(TAG, "diff1=" + diff1 + " diff2=" + diff2);
+
+ return (diff1 + diff2) < THRESHOLD;
+ }
+
+ private void sleep() {
+ try {
+ Thread.sleep(SLEEP_TIME);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+
+ private void reportError(String appName, String processName, Bundle results) {
+ ActivityManager am = (ActivityManager) getInstrumentation()
+ .getContext().getSystemService(Context.ACTIVITY_SERVICE);
+ List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState();
+ if (crashes != null) {
+ for (ProcessErrorStateInfo crash : crashes) {
+ if (!crash.processName.equals(processName))
+ continue;
+
+ Log.w(TAG, appName + " crashed: " + crash.shortMsg);
+ results.putString(nameToResultKey.get(appName), crash.shortMsg);
+ return;
+ }
+ }
+
+ results.putString(nameToResultKey.get(appName),
+ "Crashed for unknown reason");
+ Log.w(TAG, appName
+ + " not found in process list, most likely it is crashed");
+ }
+
+ private int getPss(String processName) {
+ ActivityManager am = (ActivityManager) getInstrumentation()
+ .getContext().getSystemService(Context.ACTIVITY_SERVICE);
+ List<RunningAppProcessInfo> apps = am.getRunningAppProcesses();
+
+ for (RunningAppProcessInfo proc : apps) {
+ if (!proc.processName.equals(processName)) {
+ continue;
+ }
+
+ int[] pids = {
+ proc.pid };
+
+ MemoryInfo meminfo = am.getProcessMemoryInfo(pids)[0];
+ return meminfo.getTotalPss();
+
+ }
+ return -1;
+ }
+}
diff --git a/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/BallsView.java b/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/BallsView.java
index b3b3756..041782d 100644
--- a/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/BallsView.java
+++ b/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/BallsView.java
@@ -105,7 +105,7 @@ public class BallsView extends RSSurfaceView {
}
void setAccel(float x, float y, float z) {
- if (mRender == null) {
+ if ((mRender == null) || (mRS == null)) {
return;
}
mRender.setAccel(x, -y);
diff --git a/tests/RenderScriptTests/ComputeBenchmark/Android.mk b/tests/RenderScriptTests/ComputeBenchmark/Android.mk
new file mode 100644
index 0000000..8d47e89
--- /dev/null
+++ b/tests/RenderScriptTests/ComputeBenchmark/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+ $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RsComputeBenchmark
+
+include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/ComputeBenchmark/AndroidManifest.xml b/tests/RenderScriptTests/ComputeBenchmark/AndroidManifest.xml
new file mode 100644
index 0000000..c8fcc17
--- /dev/null
+++ b/tests/RenderScriptTests/ComputeBenchmark/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.rs.computebench">
+
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-sdk android:minSdkVersion="17" />
+ <application android:label="_RS_Compute_Bench">
+ <activity android:name="ComputeBench">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/RenderScriptTests/ComputeBenchmark/res/layout/main.xml b/tests/RenderScriptTests/ComputeBenchmark/res/layout/main.xml
new file mode 100644
index 0000000..9e9dab8
--- /dev/null
+++ b/tests/RenderScriptTests/ComputeBenchmark/res/layout/main.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ImageView
+ android:id="@+id/displayin"
+ android:layout_width="320dip"
+ android:layout_height="266dip" />
+
+ <ImageView
+ android:id="@+id/displayout"
+ android:layout_width="320dip"
+ android:layout_height="266dip" />
+
+</LinearLayout>
diff --git a/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/Benchmark.java b/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/Benchmark.java
new file mode 100644
index 0000000..ec80719
--- /dev/null
+++ b/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/Benchmark.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.rs.computebench;
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class Benchmark implements Runnable {
+ private final RenderScript mRS;
+ private ScriptC_compute_benchmark mScript;
+
+ public Benchmark(RenderScript rs, Resources res) {
+ mRS = rs;
+ mScript = new ScriptC_compute_benchmark(mRS, res, R.raw.compute_benchmark);
+ }
+
+ public void run() {
+ long t = java.lang.System.currentTimeMillis();
+ mScript.invoke_bench();
+ mRS.finish();
+ t = java.lang.System.currentTimeMillis() - t;
+ android.util.Log.v("ComputeBench", "Total benchmark took " + t + " ms");
+ }
+
+}
diff --git a/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/ComputeBench.java b/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/ComputeBench.java
new file mode 100644
index 0000000..2d3e843
--- /dev/null
+++ b/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/ComputeBench.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.rs.computebench;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.renderscript.RenderScript;
+
+public class ComputeBench extends Activity {
+ private RenderScript mRS;
+ private Benchmark mBenchmark;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ mRS = RenderScript.create(this);
+
+ mBenchmark = new Benchmark(mRS, getResources());
+ mBenchmark.run();
+ }
+}
diff --git a/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs b/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
new file mode 100644
index 0000000..7b8ec04
--- /dev/null
+++ b/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
@@ -0,0 +1,408 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.rs.computebench)
+
+// Test configuration (accessible from Java)
+uint priming_runs = 1000000;
+uint timing_runs = 5000000;
+
+// Reused variables
+
+static volatile int64_t bench_time;
+static float inv_timing_runs;
+
+#define DECL_VAR_SET(prefix) \
+static volatile float prefix##_f_1 = 1; \
+static volatile float2 prefix##_f_2 = 1; \
+static volatile float3 prefix##_f_3 = 1; \
+static volatile float4 prefix##_f_4 = 1; \
+static volatile char prefix##_c_1 = 1; \
+static volatile char2 prefix##_c_2 = 1; \
+static volatile char3 prefix##_c_3 = 1; \
+static volatile char4 prefix##_c_4 = 1; \
+static volatile uchar prefix##_uc_1 = 1; \
+static volatile uchar2 prefix##_uc_2 = 1; \
+static volatile uchar3 prefix##_uc_3 = 1; \
+static volatile uchar4 prefix##_uc_4 = 1; \
+static volatile short prefix##_s_1 = 1; \
+static volatile short2 prefix##_s_2 = 1; \
+static volatile short3 prefix##_s_3 = 1; \
+static volatile short4 prefix##_s_4 = 1; \
+static volatile ushort prefix##_us_1 = 1; \
+static volatile ushort2 prefix##_us_2 = 1; \
+static volatile ushort3 prefix##_us_3 = 1; \
+static volatile ushort4 prefix##_us_4 = 1; \
+static volatile int prefix##_i_1 = 1; \
+static volatile int2 prefix##_i_2 = 1; \
+static volatile int3 prefix##_i_3 = 1; \
+static volatile int4 prefix##_i_4 = 1; \
+static volatile uint prefix##_ui_1 = 1; \
+static volatile uint2 prefix##_ui_2 = 1; \
+static volatile uint3 prefix##_ui_3 = 1; \
+static volatile uint4 prefix##_ui_4 = 1; \
+static volatile long prefix##_l_1 = 1; \
+static volatile long2 prefix##_l_2 = 1; \
+static volatile long3 prefix##_l_3 = 1; \
+static volatile long4 prefix##_l_4 = 1; \
+static volatile ulong prefix##_ul_1 = 1; \
+static volatile ulong2 prefix##_ul_2 = 1; \
+static volatile ulong3 prefix##_ul_3 = 1; \
+static volatile ulong4 prefix##_ul_4 = 1; \
+
+DECL_VAR_SET(res)
+DECL_VAR_SET(src1)
+DECL_VAR_SET(src2)
+DECL_VAR_SET(src3)
+
+
+// Testing macros
+
+#define RUN_BENCH(line, op) \
+ for (int i = priming_runs - 1; i >= 0; --i) { \
+ line; \
+ } \
+ bench_time = rsUptimeMillis(); \
+ for (int i = timing_runs - 1; i >= 0; --i) { \
+ line; \
+ } \
+ bench_time = rsUptimeMillis() - bench_time; \
+ rsDebug(" " op " took ns", (float)bench_time * inv_timing_runs);
+
+#define BENCH_BASIC_OP_TYPE(op, type) \
+ RUN_BENCH(res_##type##_1 = src1_##type##_1 op src2_##type##_1, #type "1 " #op " " #type "1") \
+ RUN_BENCH(res_##type##_2 = src1_##type##_2 op src2_##type##_2, #type "2 " #op " " #type "2") \
+ RUN_BENCH(res_##type##_3 = src1_##type##_3 op src2_##type##_3, #type "3 " #op " " #type "3") \
+ RUN_BENCH(res_##type##_4 = src1_##type##_4 op src2_##type##_4, #type "4 " #op " " #type "4") \
+
+#define BENCH_BASIC_INT_OP(op) \
+ rsDebug("Testing basic operation " #op, 0); \
+ BENCH_BASIC_OP_TYPE(op, c) \
+ BENCH_BASIC_OP_TYPE(op, uc) \
+ BENCH_BASIC_OP_TYPE(op, s) \
+ BENCH_BASIC_OP_TYPE(op, us) \
+ BENCH_BASIC_OP_TYPE(op, i) \
+ BENCH_BASIC_OP_TYPE(op, ui) \
+ RUN_BENCH(res_l_1 = src1_l_1 op src2_l_1, "l1 " #op " l1") \
+ RUN_BENCH(res_ul_1 = src1_ul_1 op src2_ul_1, "ul1 " #op " ul1")
+
+#define BENCH_BASIC_OP(op) \
+ BENCH_BASIC_INT_OP(op) \
+ BENCH_BASIC_OP_TYPE(op, f)
+
+#define BENCH_CVT(to, from, type) \
+ rsDebug("Testing convert from " #from " to " #to, 0); \
+ RUN_BENCH(res_##to##_1 = (type)src1_##from##_1, "(" #to ")" #from) \
+ RUN_BENCH(res_##to##_2 = convert_##type##2(src1_##from##_2), #to "2 convert_" #type "2(" #from "2)") \
+ RUN_BENCH(res_##to##_3 = convert_##type##3(src1_##from##_3), #to "3 convert_" #type "3(" #from "3)") \
+ RUN_BENCH(res_##to##_4 = convert_##type##4(src1_##from##_4), #to "4 convert_" #type "4(" #from "4)")
+
+#define BENCH_CVT_MATRIX(to, type) \
+ BENCH_CVT(to, c, type); \
+ BENCH_CVT(to, uc, type); \
+ BENCH_CVT(to, s, type); \
+ BENCH_CVT(to, us, type); \
+ BENCH_CVT(to, i, type); \
+ BENCH_CVT(to, ui, type); \
+ BENCH_CVT(to, f, type); \
+
+#define BENCH_XN_FUNC_YN(typeout, fnc, typein) \
+ RUN_BENCH(res_##typeout##_1 = fnc(src1_##typein##_1);, #typeout "1 " #fnc "(" #typein "1)") \
+ RUN_BENCH(res_##typeout##_2 = fnc(src1_##typein##_2);, #typeout "2 " #fnc "(" #typein "2)") \
+ RUN_BENCH(res_##typeout##_3 = fnc(src1_##typein##_3);, #typeout "3 " #fnc "(" #typein "3)") \
+ RUN_BENCH(res_##typeout##_4 = fnc(src1_##typein##_4);, #typeout "4 " #fnc "(" #typein "4)")
+
+#define BENCH_XN_FUNC_XN_XN(type, fnc) \
+ RUN_BENCH(res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1), #type "1 " #fnc "(" #type "1, " #type "1)") \
+ RUN_BENCH(res_##type##_2 = fnc(src1_##type##_2, src2_##type##_2), #type "2 " #fnc "(" #type "2, " #type "2)") \
+ RUN_BENCH(res_##type##_3 = fnc(src1_##type##_3, src2_##type##_3), #type "3 " #fnc "(" #type "3, " #type "3)") \
+ RUN_BENCH(res_##type##_4 = fnc(src1_##type##_4, src2_##type##_4), #type "4 " #fnc "(" #type "4, " #type "4)") \
+
+#define BENCH_X_FUNC_X_X_X(type, fnc) \
+ RUN_BENCH(res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1, src3_##type##_1), #type "1 " #fnc "(" #type "1, " #type "1, " #type "1)")
+
+#define BENCH_IN_FUNC_IN(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ BENCH_XN_FUNC_YN(uc, fnc, uc) \
+ BENCH_XN_FUNC_YN(c, fnc, c) \
+ BENCH_XN_FUNC_YN(us, fnc, us) \
+ BENCH_XN_FUNC_YN(s, fnc, s) \
+ BENCH_XN_FUNC_YN(ui, fnc, ui) \
+ BENCH_XN_FUNC_YN(i, fnc, i)
+
+#define BENCH_UIN_FUNC_IN(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ BENCH_XN_FUNC_YN(uc, fnc, c) \
+ BENCH_XN_FUNC_YN(us, fnc, s) \
+ BENCH_XN_FUNC_YN(ui, fnc, i) \
+
+#define BENCH_IN_FUNC_IN_IN(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ BENCH_XN_FUNC_XN_XN(uc, fnc) \
+ BENCH_XN_FUNC_XN_XN(c, fnc) \
+ BENCH_XN_FUNC_XN_XN(us, fnc) \
+ BENCH_XN_FUNC_XN_XN(s, fnc) \
+ BENCH_XN_FUNC_XN_XN(ui, fnc) \
+ BENCH_XN_FUNC_XN_XN(i, fnc)
+
+#define BENCH_I_FUNC_I_I_I(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ BENCH_X_FUNC_X_X_X(uc, fnc) \
+ BENCH_X_FUNC_X_X_X(c, fnc) \
+ BENCH_X_FUNC_X_X_X(us, fnc) \
+ BENCH_X_FUNC_X_X_X(s, fnc) \
+ BENCH_X_FUNC_X_X_X(ui, fnc) \
+ BENCH_X_FUNC_X_X_X(i, fnc)
+
+#define BENCH_FN_FUNC_FN(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ RUN_BENCH(res_f_1 = fnc(src1_f_1), "f1 " #fnc "(f1)") \
+ RUN_BENCH(res_f_2 = fnc(src1_f_2), "f2 " #fnc "(f2)") \
+ RUN_BENCH(res_f_3 = fnc(src1_f_3), "f3 " #fnc "(f3)") \
+ RUN_BENCH(res_f_4 = fnc(src1_f_4), "f4 " #fnc "(f4)")
+
+#define BENCH_FN_FUNC_FN_PFN(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ RUN_BENCH(res_f_1 = fnc(src1_f_1, (float*) &src2_f_1), "f1 " #fnc "(f1, f1*)") \
+ RUN_BENCH(res_f_2 = fnc(src1_f_2, (float2*) &src2_f_2), "f2 " #fnc "(f2, f2*)") \
+ RUN_BENCH(res_f_3 = fnc(src1_f_3, (float3*) &src2_f_3), "f3 " #fnc "(f3, f3*)") \
+ RUN_BENCH(res_f_4 = fnc(src1_f_4, (float4*) &src2_f_4), "f4 " #fnc "(f4, f4*)")
+
+#define BENCH_FN_FUNC_FN_FN(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1), "f1 " #fnc "(f1, f1)") \
+ RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_2), "f2 " #fnc "(f2, f2)") \
+ RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3), "f3 " #fnc "(f3, f3)") \
+ RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4), "f4 " #fnc "(f4, f4)")
+
+#define BENCH_F34_FUNC_F34_F34(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3), "f3 " #fnc "(f3, f3)") \
+ RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4), "f4 " #fnc "(f4, f4)")
+
+#define BENCH_FN_FUNC_FN_F(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1), "f1 " #fnc "(f1, f1)") \
+ RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_1), "f2 " #fnc "(f2, f1)") \
+ RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_1), "f3 " #fnc "(f3, f1)") \
+ RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_1), "f4 " #fnc "(f4, f1)")
+
+#define BENCH_F_FUNC_FN(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ RUN_BENCH(res_f_1 = fnc(src1_f_1), "f1 " #fnc "(f1)") \
+ RUN_BENCH(res_f_1 = fnc(src1_f_2), "f1 " #fnc "(f2)") \
+ RUN_BENCH(res_f_1 = fnc(src1_f_3), "f1 " #fnc "(f3)") \
+ RUN_BENCH(res_f_1 = fnc(src1_f_4), "f1 " #fnc "(f4)")
+
+#define BENCH_F_FUNC_FN_FN(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1), "f1 " #fnc "(f1, f1)") \
+ RUN_BENCH(res_f_1 = fnc(src1_f_2, src2_f_2), "f1 " #fnc "(f2, f2)") \
+ RUN_BENCH(res_f_1 = fnc(src1_f_3, src2_f_3), "f1 " #fnc "(f3, f3)") \
+ RUN_BENCH(res_f_1 = fnc(src1_f_4, src2_f_4), "f1 " #fnc "(f4, f4)")
+
+#define BENCH_FN_FUNC_FN_IN(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ RUN_BENCH(res_f_1 = fnc(src1_f_1, src1_i_1), "f1 " #fnc "(f1, i1)") \
+ RUN_BENCH(res_f_2 = fnc(src1_f_2, src1_i_2), "f2 " #fnc "(f2, i2)") \
+ RUN_BENCH(res_f_3 = fnc(src1_f_3, src1_i_3), "f3 " #fnc "(f3, i3)") \
+ RUN_BENCH(res_f_4 = fnc(src1_f_4, src1_i_4), "f4 " #fnc "(f4, i4)")
+
+#define BENCH_FN_FUNC_FN_I(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ RUN_BENCH(res_f_1 = fnc(src1_f_1, src1_i_1), "f1 " #fnc "(f1, i1)") \
+ RUN_BENCH(res_f_2 = fnc(src1_f_2, src1_i_1), "f2 " #fnc "(f2, i1)") \
+ RUN_BENCH(res_f_3 = fnc(src1_f_3, src1_i_1), "f3 " #fnc "(f3, i1)") \
+ RUN_BENCH(res_f_4 = fnc(src1_f_4, src1_i_1), "f4 " #fnc "(f4, i1)")
+
+#define BENCH_FN_FUNC_FN_FN_FN(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1, src3_f_1), "f1 " #fnc "(f1, f1, f1)") \
+ RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_2, src3_f_2), "f2 " #fnc "(f2, f2, f2)") \
+ RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3, src3_f_3), "f3 " #fnc "(f3, f3, f3)") \
+ RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4, src3_f_4), "f4 " #fnc "(f4, f4, f4)")
+
+#define BENCH_FN_FUNC_FN_FN_F(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1, src3_f_1), "f1 " #fnc "(f1, f1, f1)") \
+ RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_2, src3_f_1), "f2 " #fnc "(f2, f2, f1)") \
+ RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3, src3_f_1), "f3 " #fnc "(f3, f3, f1)") \
+ RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4, src3_f_1), "f4 " #fnc "(f4, f4, f1)")
+
+#define BENCH_FN_FUNC_FN_PIN(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ RUN_BENCH(res_f_1 = fnc(src1_f_1, (int*) &src1_i_1), "f1 " #fnc "(f1, i1*)") \
+ RUN_BENCH(res_f_2 = fnc(src1_f_2, (int2*) &src1_i_2), "f2 " #fnc "(f2, i2*)") \
+ RUN_BENCH(res_f_3 = fnc(src1_f_3, (int3*) &src1_i_3), "f3 " #fnc "(f3, i3*)") \
+ RUN_BENCH(res_f_4 = fnc(src1_f_4, (int4*) &src1_i_4), "f4 " #fnc "(f4, i4*)")
+
+#define BENCH_FN_FUNC_FN_FN_PIN(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1, (int*) &src1_i_1), "f1 " #fnc "(f1, f1, i1*)") \
+ RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_2, (int2*) &src1_i_2), "f2 " #fnc "(f2, f2, i2*)") \
+ RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3, (int3*) &src1_i_3), "f3 " #fnc "(f3, f3, i3*)") \
+ RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4, (int4*) &src1_i_4), "f4 " #fnc "(f4, f4, i4*)")
+
+#define BENCH_IN_FUNC_FN(fnc) \
+ rsDebug("Testing " #fnc, 0); \
+ RUN_BENCH(res_i_1 = fnc(src1_f_1), "i1 " #fnc "(f1)") \
+ RUN_BENCH(res_i_2 = fnc(src1_f_2), "i2 " #fnc "(f2)") \
+ RUN_BENCH(res_i_3 = fnc(src1_f_3), "i3 " #fnc "(f3)") \
+ RUN_BENCH(res_i_4 = fnc(src1_f_4), "i4 " #fnc "(f4)")
+
+
+// Testing functions
+
+static void bench_basic_operators() {
+ int i = 0;
+ BENCH_BASIC_OP(+);
+ BENCH_BASIC_OP(-);
+ BENCH_BASIC_OP(*);
+ BENCH_BASIC_OP(/);
+ BENCH_BASIC_INT_OP(%);
+ BENCH_BASIC_INT_OP(<<);
+ BENCH_BASIC_INT_OP(>>);
+}
+
+static void bench_convert() {
+ BENCH_CVT_MATRIX(c, char);
+ BENCH_CVT_MATRIX(uc, uchar);
+ BENCH_CVT_MATRIX(s, short);
+ BENCH_CVT_MATRIX(us, ushort);
+ BENCH_CVT_MATRIX(i, int);
+ BENCH_CVT_MATRIX(ui, uint);
+ BENCH_CVT_MATRIX(f, float);
+}
+
+static void bench_int_math() {
+ BENCH_UIN_FUNC_IN(abs);
+ BENCH_IN_FUNC_IN(clz);
+ BENCH_IN_FUNC_IN_IN(min);
+ BENCH_IN_FUNC_IN_IN(max);
+ BENCH_I_FUNC_I_I_I(rsClamp);
+}
+
+static void bench_fp_math() {
+ BENCH_FN_FUNC_FN(acos);
+ BENCH_FN_FUNC_FN(acosh);
+ BENCH_FN_FUNC_FN(acospi);
+ BENCH_FN_FUNC_FN(asin);
+ BENCH_FN_FUNC_FN(asinh);
+ BENCH_FN_FUNC_FN(asinpi);
+ BENCH_FN_FUNC_FN(atan);
+ BENCH_FN_FUNC_FN_FN(atan2);
+ BENCH_FN_FUNC_FN(atanh);
+ BENCH_FN_FUNC_FN(atanpi);
+ BENCH_FN_FUNC_FN_FN(atan2pi);
+ BENCH_FN_FUNC_FN(cbrt);
+ BENCH_FN_FUNC_FN(ceil);
+ BENCH_FN_FUNC_FN_FN_FN(clamp);
+ BENCH_FN_FUNC_FN_FN_F(clamp);
+ BENCH_FN_FUNC_FN_FN(copysign);
+ BENCH_FN_FUNC_FN(cos);
+ BENCH_FN_FUNC_FN(cosh);
+ BENCH_FN_FUNC_FN(cospi);
+ BENCH_F34_FUNC_F34_F34(cross);
+ BENCH_FN_FUNC_FN(degrees);
+ BENCH_F_FUNC_FN_FN(distance);
+ BENCH_F_FUNC_FN_FN(dot);
+ BENCH_FN_FUNC_FN(erfc);
+ BENCH_FN_FUNC_FN(erf);
+ BENCH_FN_FUNC_FN(exp);
+ BENCH_FN_FUNC_FN(exp2);
+ BENCH_FN_FUNC_FN(exp10);
+ BENCH_FN_FUNC_FN(expm1);
+ BENCH_FN_FUNC_FN(fabs);
+ BENCH_FN_FUNC_FN_FN(fdim);
+ BENCH_FN_FUNC_FN(floor);
+ BENCH_FN_FUNC_FN_FN_FN(fma);
+ BENCH_FN_FUNC_FN_FN(fmax);
+ BENCH_FN_FUNC_FN_F(fmax);
+ BENCH_FN_FUNC_FN_FN(fmin);
+ BENCH_FN_FUNC_FN_F(fmin);
+ BENCH_FN_FUNC_FN_FN(fmod);
+ BENCH_FN_FUNC_FN_PFN(fract);
+ BENCH_FN_FUNC_FN_PIN(frexp);
+ BENCH_FN_FUNC_FN_FN(hypot);
+ BENCH_IN_FUNC_FN(ilogb);
+ BENCH_FN_FUNC_FN_IN(ldexp);
+ BENCH_FN_FUNC_FN_I(ldexp);
+ BENCH_F_FUNC_FN(length);
+ BENCH_FN_FUNC_FN(lgamma);
+ BENCH_FN_FUNC_FN_PIN(lgamma);
+ BENCH_FN_FUNC_FN(log);
+ BENCH_FN_FUNC_FN(log2);
+ BENCH_FN_FUNC_FN(log10);
+ BENCH_FN_FUNC_FN(log1p);
+ BENCH_FN_FUNC_FN(logb);
+ BENCH_FN_FUNC_FN_FN_FN(mad);
+ BENCH_FN_FUNC_FN_FN(max);
+ BENCH_FN_FUNC_FN_F(max);
+ BENCH_FN_FUNC_FN_FN(min);
+ BENCH_FN_FUNC_FN_F(min);
+ BENCH_FN_FUNC_FN_FN_FN(mix);
+ BENCH_FN_FUNC_FN_FN_F(mix);
+ BENCH_FN_FUNC_FN_PFN(modf);
+ BENCH_FN_FUNC_FN_FN(nextafter);
+ BENCH_FN_FUNC_FN(normalize);
+ BENCH_FN_FUNC_FN_FN(pow);
+ BENCH_FN_FUNC_FN_IN(pown);
+ BENCH_FN_FUNC_FN_FN(powr);
+ BENCH_FN_FUNC_FN(radians);
+ BENCH_FN_FUNC_FN_FN(remainder);
+ BENCH_FN_FUNC_FN_FN_PIN(remquo);
+ BENCH_FN_FUNC_FN(rint);
+ BENCH_FN_FUNC_FN_IN(rootn);
+ BENCH_FN_FUNC_FN(round);
+ BENCH_FN_FUNC_FN(rsqrt);
+ BENCH_FN_FUNC_FN(sign);
+ BENCH_FN_FUNC_FN(sin);
+ BENCH_FN_FUNC_FN_PFN(sincos);
+ BENCH_FN_FUNC_FN(sinh);
+ BENCH_FN_FUNC_FN(sinpi);
+ BENCH_FN_FUNC_FN(sqrt);
+ BENCH_FN_FUNC_FN_FN(step);
+ BENCH_FN_FUNC_FN_F(step);
+ BENCH_FN_FUNC_FN(tan);
+ BENCH_FN_FUNC_FN(tanh);
+ BENCH_FN_FUNC_FN(tanpi);
+ BENCH_FN_FUNC_FN(tgamma);
+ BENCH_FN_FUNC_FN(trunc);
+}
+
+static void bench_approx_math() {
+ BENCH_FN_FUNC_FN(approx_recip);
+ BENCH_FN_FUNC_FN(approx_sqrt);
+ BENCH_FN_FUNC_FN(approx_rsqrt);
+ BENCH_FN_FUNC_FN(approx_length);
+ BENCH_FN_FUNC_FN_FN(approx_distance);
+ BENCH_FN_FUNC_FN(approx_normalize);
+ BENCH_FN_FUNC_FN(approx_atan);
+}
+
+void bench() {
+ rsDebug("RS Compute Benchmark", 0);
+ rsDebug("Current configuration:", 0);
+ rsDebug("Priming runs", priming_runs);
+ rsDebug("Timing runs", timing_runs);
+ rsDebug("Beginning test", 0);
+ inv_timing_runs = 1000000.f / (float)timing_runs;
+ bench_basic_operators();
+ bench_convert();
+ bench_int_math();
+ bench_fp_math();
+ bench_approx_math();
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Fisheye.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Fisheye.java
index bf68f91..81868b1 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Fisheye.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Fisheye.java
@@ -26,12 +26,16 @@ import android.widget.TextView;
public class Fisheye extends TestBase {
private ScriptC_fisheye_full mScript_full = null;
private ScriptC_fisheye_relaxed mScript_relaxed = null;
+ private ScriptC_fisheye_approx_full mScript_approx_full = null;
+ private ScriptC_fisheye_approx_relaxed mScript_approx_relaxed = null;
+ private final boolean approx;
private final boolean relaxed;
private float center_x = 0.5f;
private float center_y = 0.5f;
private float scale = 0.5f;
- public Fisheye(boolean relaxed) {
+ public Fisheye(boolean approx, boolean relaxed) {
+ this.approx = approx;
this.relaxed = relaxed;
}
@@ -68,7 +72,18 @@ public class Fisheye extends TestBase {
}
private void do_init() {
- if (relaxed)
+ if (approx) {
+ if (relaxed)
+ mScript_approx_relaxed.invoke_init_filter(
+ mInPixelsAllocation.getType().getX(),
+ mInPixelsAllocation.getType().getY(), center_x,
+ center_y, scale);
+ else
+ mScript_approx_full.invoke_init_filter(
+ mInPixelsAllocation.getType().getX(),
+ mInPixelsAllocation.getType().getY(), center_x,
+ center_y, scale);
+ } else if (relaxed)
mScript_relaxed.invoke_init_filter(
mInPixelsAllocation.getType().getX(),
mInPixelsAllocation.getType().getY(), center_x, center_y,
@@ -81,7 +96,19 @@ public class Fisheye extends TestBase {
}
public void createTest(android.content.res.Resources res) {
- if (relaxed) {
+ if (approx) {
+ if (relaxed) {
+ mScript_approx_relaxed = new ScriptC_fisheye_approx_relaxed(mRS,
+ res, R.raw.fisheye_approx_relaxed);
+ mScript_approx_relaxed.set_in_alloc(mInPixelsAllocation);
+ mScript_approx_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+ } else {
+ mScript_approx_full = new ScriptC_fisheye_approx_full(mRS, res,
+ R.raw.fisheye_approx_full);
+ mScript_approx_full.set_in_alloc(mInPixelsAllocation);
+ mScript_approx_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+ }
+ } else if (relaxed) {
mScript_relaxed = new ScriptC_fisheye_relaxed(mRS, res,
R.raw.fisheye_relaxed);
mScript_relaxed.set_in_alloc(mInPixelsAllocation);
@@ -96,7 +123,12 @@ public class Fisheye extends TestBase {
}
public void runTest() {
- if (relaxed)
+ if (approx) {
+ if (relaxed)
+ mScript_approx_relaxed.forEach_root(mOutPixelsAllocation);
+ else
+ mScript_approx_full.forEach_root(mOutPixelsAllocation);
+ } else if (relaxed)
mScript_relaxed.forEach_root(mOutPixelsAllocation);
else
mScript_full.forEach_root(mOutPixelsAllocation);
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index 3eec7f5..07626a3 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -144,30 +144,36 @@ public class ImageProcessingActivity extends Activity
mTest = new Grain();
break;
case 7:
- mTest = new Fisheye(false);
+ mTest = new Fisheye(false, false);
break;
case 8:
- mTest = new Fisheye(true);
+ mTest = new Fisheye(false, true);
break;
case 9:
- mTest = new Vignette(false, false);
+ mTest = new Fisheye(true, false);
break;
case 10:
- mTest = new Vignette(false, true);
+ mTest = new Fisheye(true, true);
break;
case 11:
- mTest = new Vignette(true, false);
+ mTest = new Vignette(false, false);
break;
case 12:
- mTest = new Vignette(true, true);
+ mTest = new Vignette(false, true);
break;
case 13:
- mTest = new GroupTest(true);
+ mTest = new Vignette(true, false);
break;
case 14:
- mTest = new GroupTest(false);
+ mTest = new Vignette(true, true);
break;
case 15:
+ mTest = new GroupTest(true);
+ break;
+ case 16:
+ mTest = new GroupTest(false);
+ break;
+ case 17:
mTest = new Intrinsics(0);
break;
}
@@ -182,7 +188,7 @@ public class ImageProcessingActivity extends Activity
}
void setupTests() {
- mTestNames = new String[16];
+ mTestNames = new String[18];
mTestNames[0] = "Levels Vec3 Relaxed";
mTestNames[1] = "Levels Vec4 Relaxed";
mTestNames[2] = "Levels Vec3 Full";
@@ -192,13 +198,15 @@ public class ImageProcessingActivity extends Activity
mTestNames[6] = "Grain";
mTestNames[7] = "Fisheye Full";
mTestNames[8] = "Fisheye Relaxed";
- mTestNames[9] = "Vignette Full";
- mTestNames[10] = "Vignette Relaxed";
- mTestNames[11] = "Vignette Approximate Full";
- mTestNames[12] = "Vignette Approximate Relaxed";
- mTestNames[13] = "Group Test (emulated)";
- mTestNames[14] = "Group Test (native)";
- mTestNames[15] = "Intrinsics Convolve 3x3";
+ mTestNames[9] = "Fisheye Approximate Full";
+ mTestNames[10] = "Fisheye Approximate Relaxed";
+ mTestNames[11] = "Vignette Full";
+ mTestNames[12] = "Vignette Relaxed";
+ mTestNames[13] = "Vignette Approximate Full";
+ mTestNames[14] = "Vignette Approximate Relaxed";
+ mTestNames[15] = "Group Test (emulated)";
+ mTestNames[16] = "Group Test (native)";
+ mTestNames[17] = "Intrinsics Convolve 3x3";
mTestSpinner.setAdapter(new ArrayAdapter<String>(
this, R.layout.spinner_layout, mTestNames));
}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye.rsh b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye.rsh
index 4dcfc1d..3809912 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye.rsh
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye.rsh
@@ -17,46 +17,41 @@
rs_allocation in_alloc;
rs_sampler sampler;
-static float2 center, dimensions;
-static float2 scale;
-static float alpha;
-static float radius2;
-static float factor;
-
-void init_filter(uint32_t dim_x, uint32_t dim_y, float focus_x, float focus_y, float k) {
- center.x = focus_x;
- center.y = focus_y;
- dimensions.x = (float)dim_x;
- dimensions.y = (float)dim_y;
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+ center.x = center_x;
+ center.y = center_y;
+ neg_center = -center;
+ inv_dimensions.x = 1.f / (float)dim_x;
+ inv_dimensions.y = 1.f / (float)dim_y;
alpha = k * 2.0 + 0.75;
- float bound2 = 0.25;
- if (dim_x > dim_y) {
- scale.x = 1.0;
- scale.y = dimensions.y / dimensions.x;
- bound2 *= (scale.y*scale.y + 1);
- } else {
- scale.x = dimensions.x / dimensions.y;
- scale.y = 1.0;
- bound2 *= (scale.x*scale.x + 1);
- }
+
+ axis_scale = (float2)1.f;
+ if (dim_x > dim_y)
+ axis_scale.y = (float)dim_y / (float)dim_x;
+ else
+ axis_scale.x = (float)dim_x / (float)dim_y;
+
+ const float bound2 = 0.25 * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
const float bound = sqrt(bound2);
const float radius = 1.15 * bound;
radius2 = radius*radius;
- const float max_radian = 0.5f * M_PI - atan(alpha / bound * sqrt(radius2 - bound2));
+ const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
factor = bound / max_radian;
}
void root(uchar4 *out, uint32_t x, uint32_t y) {
// Convert x and y to floating point coordinates with center as origin
- float2 coord;
- coord.x = (float)x / dimensions.x;
- coord.y = (float)y / dimensions.y;
- coord -= center;
- const float dist = length(scale * coord);
- const float radian = M_PI_2 - atan((alpha * sqrt(radius2 - dist * dist)) / dist);
- const float scalar = radian * factor / dist;
- const float2 new_coord = coord * scalar + center;
+ const float2 inCoord = {(float)x, (float)y};
+ const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+ const float2 scaledCoord = axis_scale * coord;
+ const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+ const float inv_dist = rsqrt(dist2);
+ const float radian = M_PI_2 - atan((alpha * sqrt(radius2 - dist2)) * inv_dist);
+ const float scalar = radian * factor * inv_dist;
+ const float2 new_coord = mad(coord, scalar, center);
const float4 fout = rsSample(in_alloc, sampler, new_coord);
*out = rsPackColorTo8888(fout);
}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx.rsh b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx.rsh
new file mode 100644
index 0000000..008acbe
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx.rsh
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+ center.x = center_x;
+ center.y = center_y;
+ neg_center = -center;
+ inv_dimensions.x = 1.f / (float)dim_x;
+ inv_dimensions.y = 1.f / (float)dim_y;
+ alpha = k * 2.0 + 0.75;
+
+ axis_scale = (float2)1.f;
+ if (dim_x > dim_y)
+ axis_scale.y = (float)dim_y / (float)dim_x;
+ else
+ axis_scale.x = (float)dim_x / (float)dim_y;
+
+ const float bound2 = 0.25 * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+ const float bound = sqrt(bound2);
+ const float radius = 1.15 * bound;
+ radius2 = radius*radius;
+ const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+ factor = bound / max_radian;
+}
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+ // Convert x and y to floating point coordinates with center as origin
+ const float2 inCoord = {(float)x, (float)y};
+ const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+ const float2 scaledCoord = axis_scale * coord;
+ const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+ const float inv_dist = approx_rsqrt(dist2);
+ const float radian = M_PI_2 - approx_atan((alpha * approx_sqrt(radius2 - dist2)) * inv_dist);
+ const float scalar = radian * factor * inv_dist;
+ const float2 new_coord = mad(coord, scalar, center);
+ const float4 fout = rsSample(in_alloc, sampler, new_coord);
+ *out = rsPackColorTo8888(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs
new file mode 100644
index 0000000..1ea37db
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+
+#include "fisheye_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.rs
new file mode 100644
index 0000000..3e76368
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.rs
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+#include "fisheye_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/Android.mk b/tests/RenderScriptTests/ImageProcessing2/Android.mk
index c81fd93..e05a518 100644
--- a/tests/RenderScriptTests/ImageProcessing2/Android.mk
+++ b/tests/RenderScriptTests/ImageProcessing2/Android.mk
@@ -25,6 +25,10 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) \
LOCAL_STATIC_JAVA_LIBRARIES := android.support.v8.renderscript
LOCAL_PACKAGE_NAME := ImageProcessing2
+LOCAL_SDK_VERSION := 8
+LOCAL_RENDERSCRIPT_TARGET_API := 17
+LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE := $(TOPDIR)external/clang/lib/Headers \
+ $(TOPDIR)frameworks/rs/scriptc
LOCAL_RENDERSCRIPT_FLAGS := -rs-package-name=android.support.v8.renderscript
LOCAL_REQUIRED_MODULES := librsjni
diff --git a/tests/RenderScriptTests/ImageProcessing2/AndroidManifest.xml b/tests/RenderScriptTests/ImageProcessing2/AndroidManifest.xml
index 1ef04c2..20ee053 100644
--- a/tests/RenderScriptTests/ImageProcessing2/AndroidManifest.xml
+++ b/tests/RenderScriptTests/ImageProcessing2/AndroidManifest.xml
@@ -2,9 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.rs.image2">
- <uses-sdk android:minSdkVersion="11" />
- <application android:label="IP GB"
- android:hardwareAccelerated="true">
+ <uses-sdk android:minSdkVersion="8" />
+ <application android:label="IP GB">
<activity android:name="ImageProcessingActivity2">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
index 97d9969..4901f72 100644
--- a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
+++ b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
@@ -19,6 +19,7 @@ package android.view;
import com.android.layoutlib.bridge.android.BridgeWindow;
import com.android.layoutlib.bridge.android.BridgeWindowSession;
+import android.content.Context;
import android.os.Handler;
import android.view.View.AttachInfo;
@@ -28,8 +29,12 @@ import android.view.View.AttachInfo;
public class AttachInfo_Accessor {
public static void setAttachInfo(View view) {
+ Context context = view.getContext();
+ WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+ Display display = wm.getDefaultDisplay();
+ ViewRootImpl root = new ViewRootImpl(context, display);
AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(),
- new ViewRootImpl(view.getContext()), new Handler(), null);
+ display, root, new Handler(), null);
info.mHasWindowFocus = true;
info.mWindowVisibility = View.VISIBLE;
info.mInTouchMode = false; // this is so that we can display selections.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 292e4fc..3d45bff 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -61,10 +61,12 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
+import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.BridgeInflater;
+import android.view.CompatibilityInfoHolder;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
@@ -1193,12 +1195,12 @@ public final class BridgeContext extends Context {
}
@Override
- public void sendBroadcastToUser(Intent intent, int userId) {
+ public void sendBroadcastAsUser(Intent intent, UserHandle user) {
// pass
}
@Override
- public void sendOrderedBroadcastToUser(Intent intent, int userId,
+ public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
BroadcastReceiver resultReceiver, Handler scheduler,
int initialCode, String initialData, Bundle initialExtras) {
// pass
@@ -1317,4 +1319,10 @@ public final class BridgeContext extends Context {
Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null);
return null;
}
+
+ @Override
+ public CompatibilityInfoHolder getCompatibilityInfo() {
+ // pass
+ return null;
+ }
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
index f548b46..5516339 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -225,7 +225,7 @@ public class BridgeWindowManager implements IWindowManager {
@Override
public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
- IRemoteCallback startedCallback, boolean delayed) throws RemoteException {
+ IRemoteCallback startedCallback, boolean scaleUp) throws RemoteException {
// TODO Auto-generated method stub
}
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 32261de..3e20756 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -47,19 +47,37 @@ public class ScanResult implements Parcelable {
public int frequency;
/**
+ * Time Synchronization Function (tsf) timestamp in microseconds when
+ * this result was last seen.
+ */
+ public long timestamp;
+
+ /**
* We'd like to obtain the following attributes,
* but they are not reported via the socket
* interface, even though they are known
* internally by wpa_supplicant.
* {@hide}
*/
- public ScanResult(String SSID, String BSSID, String caps, int level, int frequency) {
+ public ScanResult(String SSID, String BSSID, String caps, int level, int frequency, long tsf) {
this.SSID = SSID;
this.BSSID = BSSID;
this.capabilities = caps;
this.level = level;
this.frequency = frequency;
- //networkConfig = null;
+ this.timestamp = tsf;
+ }
+
+ /** copy constructor {@hide} */
+ public ScanResult(ScanResult source) {
+ if (source != null) {
+ SSID = source.SSID;
+ BSSID = source.BSSID;
+ capabilities = source.capabilities;
+ level = source.level;
+ frequency = source.frequency;
+ timestamp = source.timestamp;
+ }
}
@Override
@@ -76,7 +94,9 @@ public class ScanResult implements Parcelable {
append(", level: ").
append(level).
append(", frequency: ").
- append(frequency);
+ append(frequency).
+ append(", timestamp: ").
+ append(timestamp);
return sb.toString();
}
@@ -93,6 +113,7 @@ public class ScanResult implements Parcelable {
dest.writeString(capabilities);
dest.writeInt(level);
dest.writeInt(frequency);
+ dest.writeLong(timestamp);
}
/** Implement the Parcelable interface {@hide} */
@@ -104,7 +125,8 @@ public class ScanResult implements Parcelable {
in.readString(),
in.readString(),
in.readInt(),
- in.readInt()
+ in.readInt(),
+ in.readLong()
);
}
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 84c565b..1b7e378 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -197,8 +197,22 @@ public class WifiNative {
return null;
}
+ /**
+ * Format of results:
+ * =================
+ * bssid=68:7f:74:d7:1b:6e
+ * freq=2412
+ * level=-43
+ * tsf=1344621975160944
+ * age=2623
+ * flags=[WPA2-PSK-CCMP][WPS][ESS]
+ * ssid=zubyb
+ *
+ * RANGE=ALL gets all scan results
+ * MASK=<N> see wpa_supplicant/src/common/wpa_ctrl.h for details
+ */
public String scanResults() {
- return doStringCommand("SCAN_RESULTS");
+ return doStringCommand("BSS RANGE=ALL MASK=0x1986");
}
public boolean startDriver() {
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 6abca65..1d06c76 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -114,7 +114,7 @@ public class WifiStateMachine extends StateMachine {
private final String mPrimaryDeviceType;
/* Scan results handling */
- private List<ScanResult> mScanResults;
+ private List<ScanResult> mScanResults = new ArrayList<ScanResult>();
private static final Pattern scanResultPattern = Pattern.compile("\t+");
private static final int SCAN_RESULT_CACHE_SIZE = 80;
private final LruCache<String, ScanResult> mScanResultCache;
@@ -891,7 +891,13 @@ public class WifiStateMachine extends StateMachine {
* TODO: doc
*/
public List<ScanResult> syncGetScanResultsList() {
- return mScanResults;
+ synchronized (mScanResultCache) {
+ List<ScanResult> scanList = new ArrayList<ScanResult>();
+ for(ScanResult result: mScanResults) {
+ scanList.add(new ScanResult(result));
+ }
+ return scanList;
+ }
}
/**
@@ -1357,131 +1363,103 @@ public class WifiStateMachine extends StateMachine {
mContext.sendStickyBroadcast(intent);
}
+ private static final String BSSID_STR = "bssid=";
+ private static final String FREQ_STR = "freq=";
+ private static final String LEVEL_STR = "level=";
+ private static final String TSF_STR = "tsf=";
+ private static final String FLAGS_STR = "flags=";
+ private static final String SSID_STR = "ssid=";
+ private static final String DELIMITER_STR = "====";
/**
- * Parse the scan result line passed to us by wpa_supplicant (helper).
- * @param line the line to parse
- * @return the {@link ScanResult} object
+ * Format:
+ * bssid=68:7f:76:d7:1a:6e
+ * freq=2412
+ * level=-44
+ * tsf=1344626243700342
+ * flags=[WPA2-PSK-CCMP][WPS][ESS]
+ * ssid=zfdy
+ * ====
+ * bssid=68:5f:74:d7:1a:6f
+ * freq=5180
+ * level=-73
+ * tsf=1344626243700373
+ * flags=[WPA2-PSK-CCMP][WPS][ESS]
+ * ssid=zuby
+ * ====
*/
- private ScanResult parseScanResult(String line) {
- ScanResult scanResult = null;
- if (line != null) {
- /*
- * Cache implementation (LinkedHashMap) is not synchronized, thus,
- * must synchronized here!
- */
- synchronized (mScanResultCache) {
- String[] result = scanResultPattern.split(line);
- if (3 <= result.length && result.length <= 5) {
- String bssid = result[0];
- // bssid | frequency | level | flags | ssid
- int frequency;
- int level;
+ private void setScanResults(String scanResults) {
+ String bssid = "";
+ int level = 0;
+ int freq = 0;
+ long tsf = 0;
+ String flags = "";
+ String ssid = "";
+
+ if (scanResults == null) {
+ return;
+ }
+
+ synchronized(mScanResultCache) {
+ mScanResults = new ArrayList<ScanResult>();
+ String[] lines = scanResults.split("\n");
+
+ for (String line : lines) {
+ if (line.startsWith(BSSID_STR)) {
+ bssid = line.substring(BSSID_STR.length());
+ } else if (line.startsWith(FREQ_STR)) {
try {
- frequency = Integer.parseInt(result[1]);
- level = Integer.parseInt(result[2]);
+ freq = Integer.parseInt(line.substring(FREQ_STR.length()));
+ } catch (NumberFormatException e) {
+ freq = 0;
+ }
+ } else if (line.startsWith(LEVEL_STR)) {
+ try {
+ level = Integer.parseInt(line.substring(LEVEL_STR.length()));
/* some implementations avoid negative values by adding 256
* so we need to adjust for that here.
*/
if (level > 0) level -= 256;
- } catch (NumberFormatException e) {
- frequency = 0;
+ } catch(NumberFormatException e) {
level = 0;
}
-
- /*
- * The formatting of the results returned by
- * wpa_supplicant is intended to make the fields
- * line up nicely when printed,
- * not to make them easy to parse. So we have to
- * apply some heuristics to figure out which field
- * is the SSID and which field is the flags.
- */
- String ssid;
- String flags;
- if (result.length == 4) {
- if (result[3].charAt(0) == '[') {
- flags = result[3];
- ssid = "";
+ } else if (line.startsWith(TSF_STR)) {
+ try {
+ tsf = Long.parseLong(line.substring(TSF_STR.length()));
+ } catch (NumberFormatException e) {
+ tsf = 0;
+ }
+ } else if (line.startsWith(FLAGS_STR)) {
+ flags = line.substring(FLAGS_STR.length());
+ } else if (line.startsWith(SSID_STR)) {
+ ssid = line.substring(SSID_STR.length());
+ if (ssid == null) ssid = "";
+ } else if (line.startsWith(DELIMITER_STR)) {
+ if (bssid != null) {
+ String key = bssid + ssid;
+ ScanResult scanResult = mScanResultCache.get(key);
+ if (scanResult != null) {
+ scanResult.level = level;
+ scanResult.SSID = ssid;
+ scanResult.capabilities = flags;
+ scanResult.frequency = freq;
+ scanResult.timestamp = tsf;
} else {
- flags = "";
- ssid = result[3];
- }
- } else if (result.length == 5) {
- flags = result[3];
- ssid = result[4];
- } else {
- // Here, we must have 3 fields: no flags and ssid
- // set
- flags = "";
- ssid = "";
- }
-
- // bssid + ssid is the hash key
- String key = bssid + ssid;
- scanResult = mScanResultCache.get(key);
- if (scanResult != null) {
- scanResult.level = level;
- scanResult.SSID = ssid;
- scanResult.capabilities = flags;
- scanResult.frequency = frequency;
- } else {
- // Do not add scan results that have no SSID set
- if (0 < ssid.trim().length()) {
scanResult =
new ScanResult(
- ssid, bssid, flags, level, frequency);
+ ssid, bssid, flags, level, freq, tsf);
mScanResultCache.put(key, scanResult);
}
- }
- } else {
- loge("Misformatted scan result text with " +
- result.length + " fields: " + line);
- }
- }
- }
-
- return scanResult;
- }
-
- /**
- * scanResults input format
- * 00:bb:cc:dd:cc:ee 2427 166 [WPA-EAP-TKIP][WPA2-EAP-CCMP] Net1
- * 00:bb:cc:dd:cc:ff 2412 165 [WPA-EAP-TKIP][WPA2-EAP-CCMP] Net2
- */
- private void setScanResults(String scanResults) {
- if (scanResults == null) {
- return;
- }
-
- List<ScanResult> scanList = new ArrayList<ScanResult>();
-
- int lineCount = 0;
-
- int scanResultsLen = scanResults.length();
- // Parse the result string, keeping in mind that the last line does
- // not end with a newline.
- for (int lineBeg = 0, lineEnd = 0; lineEnd <= scanResultsLen; ++lineEnd) {
- if (lineEnd == scanResultsLen || scanResults.charAt(lineEnd) == '\n') {
- ++lineCount;
-
- if (lineCount == 1) {
- lineBeg = lineEnd + 1;
- continue;
+ mScanResults.add(scanResult);
+ }
+ bssid = null;
+ level = 0;
+ freq = 0;
+ tsf = 0;
+ flags = "";
+ ssid = "";
}
- if (lineEnd > lineBeg) {
- String line = scanResults.substring(lineBeg, lineEnd);
- ScanResult scanResult = parseScanResult(line);
- if (scanResult != null) {
- scanList.add(scanResult);
- } else {
- //TODO: hidden network handling
- }
- }
- lineBeg = lineEnd + 1;
}
}
-
- mScanResults = scanList;
}
/*
@@ -2828,7 +2806,7 @@ public class WifiStateMachine extends StateMachine {
if (DBG) log(getName() + "\n");
mIsRunning = false;
updateBatteryWorkSource(null);
- mScanResults = null;
+ mScanResults = new ArrayList<ScanResult>();
if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P);
mContext.unregisterReceiver(mScreenReceiver);