summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.txt29
-rw-r--r--api/system-current.txt33
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java5
-rw-r--r--core/java/android/app/ActivityManager.java23
-rw-r--r--core/java/android/app/ActivityManagerNative.java8
-rw-r--r--core/java/android/app/ApplicationPackageManager.java4
-rw-r--r--core/java/android/app/Fragment.java10
-rw-r--r--core/java/android/app/FragmentController.java1
-rw-r--r--core/java/android/app/FragmentManager.java11
-rw-r--r--core/java/android/app/IActivityManager.java2
-rw-r--r--core/java/android/app/SystemServiceRegistry.java2
-rw-r--r--core/java/android/app/admin/DeviceAdminInfo.java2
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java88
-rw-r--r--core/java/android/content/pm/UserInfo.java11
-rw-r--r--core/java/android/content/res/Configuration.java100
-rw-r--r--core/java/android/net/ConnectivityManager.java6
-rw-r--r--core/java/android/net/NetworkScoreManager.java3
-rw-r--r--core/java/android/os/RecoverySystem.java2
-rw-r--r--core/java/android/os/StrictMode.java2
-rw-r--r--core/java/android/os/storage/VolumeInfo.java2
-rw-r--r--core/java/android/provider/DocumentsContract.java5
-rw-r--r--core/java/android/view/ThreadedRenderer.java61
-rw-r--r--core/java/android/view/View.java17
-rw-r--r--core/java/android/view/ViewRootImpl.java4
-rw-r--r--core/java/android/view/WindowManager.java8
-rw-r--r--core/java/android/widget/AbsSeekBar.java27
-rw-r--r--core/java/android/widget/ProgressBar.java148
-rw-r--r--core/java/android/widget/Switch.java2
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java17
-rw-r--r--core/java/com/android/internal/os/InstallerConnection.java7
-rw-r--r--core/java/com/android/internal/os/WrapperInit.java18
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java2
-rw-r--r--core/java/com/android/internal/view/FloatingActionMode.java5
-rw-r--r--core/java/com/android/internal/view/menu/MenuItemImpl.java2
-rw-r--r--core/java/com/android/internal/view/menu/SubMenuBuilder.java2
-rw-r--r--core/java/com/android/internal/widget/FloatingToolbar.java5
-rw-r--r--core/java/com/android/server/LocalServices.java12
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rwxr-xr-xcore/jni/android/graphics/Bitmap.cpp2
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp4
-rw-r--r--core/jni/android/graphics/BitmapRegionDecoder.cpp2
-rw-r--r--core/jni/android/graphics/Camera.cpp2
-rw-r--r--core/jni/android/graphics/CanvasProperty.cpp2
-rw-r--r--core/jni/android/graphics/ColorFilter.cpp8
-rw-r--r--core/jni/android/graphics/DrawFilter.cpp4
-rw-r--r--core/jni/android/graphics/FontFamily.cpp2
-rw-r--r--core/jni/android/graphics/Interpolator.cpp2
-rw-r--r--core/jni/android/graphics/MaskFilter.cpp8
-rw-r--r--core/jni/android/graphics/Matrix.cpp2
-rw-r--r--core/jni/android/graphics/Movie.cpp2
-rw-r--r--core/jni/android/graphics/NinePatch.cpp2
-rw-r--r--core/jni/android/graphics/Paint.cpp2
-rw-r--r--core/jni/android/graphics/Path.cpp2
-rw-r--r--core/jni/android/graphics/PathEffect.cpp14
-rw-r--r--core/jni/android/graphics/PathMeasure.cpp2
-rw-r--r--core/jni/android/graphics/PorterDuff.cpp2
-rw-r--r--core/jni/android/graphics/Rasterizer.cpp4
-rw-r--r--core/jni/android/graphics/Region.cpp4
-rw-r--r--core/jni/android/graphics/Shader.cpp14
-rw-r--r--core/jni/android/graphics/SurfaceTexture.cpp2
-rw-r--r--core/jni/android/graphics/Typeface.cpp2
-rw-r--r--core/jni/android/graphics/Xfermode.cpp6
-rw-r--r--core/jni/android/graphics/YuvToJpegEncoder.cpp2
-rw-r--r--core/jni/android/graphics/pdf/PdfDocument.cpp2
-rw-r--r--core/jni/android/graphics/pdf/PdfEditor.cpp2
-rw-r--r--core/jni/android/graphics/pdf/PdfRenderer.cpp2
-rw-r--r--core/jni/android/opengl/util.cpp14
-rw-r--r--core/jni/android_animation_PropertyValuesHolder.cpp2
-rw-r--r--core/jni/android_content_res_ObbScanner.cpp2
-rw-r--r--core/jni/android_database_CursorWindow.cpp2
-rw-r--r--core/jni/android_database_SQLiteConnection.cpp2
-rw-r--r--core/jni/android_database_SQLiteDebug.cpp2
-rw-r--r--core/jni/android_database_SQLiteGlobal.cpp2
-rw-r--r--core/jni/android_ddm_DdmHandleNativeHeap.cpp2
-rw-r--r--core/jni/android_graphics_Canvas.cpp2
-rw-r--r--core/jni/android_graphics_Picture.cpp2
-rw-r--r--core/jni/android_hardware_Camera.cpp2
-rw-r--r--core/jni/android_hardware_SensorManager.cpp4
-rw-r--r--core/jni/android_hardware_SerialPort.cpp2
-rw-r--r--core/jni/android_hardware_SoundTrigger.cpp4
-rw-r--r--core/jni/android_hardware_UsbDevice.cpp2
-rw-r--r--core/jni/android_hardware_UsbDeviceConnection.cpp2
-rw-r--r--core/jni/android_hardware_UsbRequest.cpp2
-rw-r--r--core/jni/android_hardware_camera2_CameraMetadata.cpp2
-rw-r--r--core/jni/android_hardware_camera2_DngCreator.cpp2
-rw-r--r--core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp2
-rw-r--r--core/jni/android_hardware_camera2_legacy_PerfMeasurement.cpp2
-rw-r--r--core/jni/android_hardware_location_ActivityRecognitionHardware.cpp2
-rw-r--r--core/jni/android_media_AudioRecord.cpp2
-rw-r--r--core/jni/android_media_AudioSystem.cpp4
-rw-r--r--core/jni/android_media_AudioTrack.cpp2
-rw-r--r--core/jni/android_media_JetPlayer.cpp2
-rw-r--r--core/jni/android_media_RemoteDisplay.cpp2
-rw-r--r--core/jni/android_media_ToneGenerator.cpp2
-rw-r--r--core/jni/android_net_LocalSocketImpl.cpp2
-rw-r--r--core/jni/android_net_NetUtils.cpp2
-rw-r--r--core/jni/android_net_TrafficStats.cpp2
-rw-r--r--core/jni/android_opengl_EGL14.cpp2
-rw-r--r--core/jni/android_opengl_EGLExt.cpp2
-rw-r--r--core/jni/android_opengl_GLES10.cpp2
-rw-r--r--core/jni/android_opengl_GLES10Ext.cpp2
-rw-r--r--core/jni/android_opengl_GLES11.cpp2
-rw-r--r--core/jni/android_opengl_GLES11Ext.cpp2
-rw-r--r--core/jni/android_opengl_GLES20.cpp2
-rw-r--r--core/jni/android_opengl_GLES30.cpp2
-rw-r--r--core/jni/android_opengl_GLES31.cpp2
-rw-r--r--core/jni/android_opengl_GLES31Ext.cpp2
-rw-r--r--core/jni/android_os_Debug.cpp2
-rw-r--r--core/jni/android_os_MessageQueue.cpp2
-rw-r--r--core/jni/android_os_SELinux.cpp2
-rw-r--r--core/jni/android_os_SystemClock.cpp2
-rw-r--r--core/jni/android_os_SystemProperties.cpp2
-rw-r--r--core/jni/android_os_Trace.cpp2
-rw-r--r--core/jni/android_os_UEventObserver.cpp2
-rw-r--r--core/jni/android_server_NetworkManagementSocketTagger.cpp2
-rw-r--r--core/jni/android_text_AndroidBidi.cpp2
-rw-r--r--core/jni/android_text_AndroidCharacter.cpp2
-rw-r--r--core/jni/android_text_StaticLayout.cpp2
-rw-r--r--core/jni/android_util_AssetManager.cpp2
-rw-r--r--core/jni/android_util_EventLog.cpp2
-rw-r--r--core/jni/android_util_FileObserver.cpp2
-rw-r--r--core/jni/android_util_Log.cpp2
-rw-r--r--core/jni/android_util_StringBlock.cpp2
-rw-r--r--core/jni/android_util_XmlBlock.cpp2
-rw-r--r--core/jni/android_view_DisplayEventReceiver.cpp2
-rw-r--r--core/jni/android_view_GraphicBuffer.cpp2
-rw-r--r--core/jni/android_view_HardwareLayer.cpp2
-rw-r--r--core/jni/android_view_InputChannel.cpp2
-rw-r--r--core/jni/android_view_InputEventReceiver.cpp2
-rw-r--r--core/jni/android_view_InputEventSender.cpp2
-rw-r--r--core/jni/android_view_KeyCharacterMap.cpp2
-rw-r--r--core/jni/android_view_MotionEvent.cpp2
-rw-r--r--core/jni/android_view_RenderNode.cpp2
-rw-r--r--core/jni/android_view_RenderNodeAnimator.cpp2
-rw-r--r--core/jni/android_view_Surface.cpp2
-rw-r--r--core/jni/android_view_SurfaceControl.cpp2
-rw-r--r--core/jni/android_view_SurfaceSession.cpp2
-rw-r--r--core/jni/android_view_TextureView.cpp2
-rw-r--r--core/jni/android_view_ThreadedRenderer.cpp34
-rw-r--r--core/jni/android_view_VelocityTracker.cpp2
-rw-r--r--core/jni/com_android_internal_content_NativeLibraryHelper.cpp2
-rw-r--r--core/jni/com_android_internal_net_NetworkStatsFactory.cpp2
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp2
-rw-r--r--core/jni/com_android_internal_util_VirtualRefBasePtr.cpp2
-rw-r--r--core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp2
-rw-r--r--core/jni/com_google_android_gles_jni_EGLImpl.cpp2
-rw-r--r--core/jni/com_google_android_gles_jni_GLImpl.cpp2
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--core/res/res/layout/docked_stack_divider.xml21
-rw-r--r--core/res/res/values/attrs.xml2
-rw-r--r--core/res/res/values/config.xml3
-rw-r--r--core/res/res/values/dimens.xml3
-rw-r--r--core/res/res/values/public.xml1
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp2
-rw-r--r--core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp4
-rw-r--r--core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp4
-rw-r--r--core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp4
-rw-r--r--docs/html/training/location/geofencing.jd4
-rw-r--r--drm/jni/android_drm_DrmManagerClient.cpp2
-rw-r--r--graphics/java/android/graphics/drawable/ScaleDrawable.java43
-rw-r--r--graphics/java/android/graphics/drawable/VectorDrawable.java181
-rw-r--r--libs/hwui/Android.mk4
-rw-r--r--libs/hwui/Caches.cpp41
-rw-r--r--libs/hwui/Caches.h7
-rw-r--r--libs/hwui/Debug.h3
-rw-r--r--libs/hwui/DeferredDisplayList.cpp2
-rw-r--r--libs/hwui/DisplayListOp.h4
-rw-r--r--libs/hwui/Extensions.cpp66
-rw-r--r--libs/hwui/Extensions.h10
-rw-r--r--libs/hwui/FontRenderer.cpp32
-rw-r--r--libs/hwui/FontRenderer.h6
-rw-r--r--libs/hwui/GammaFontRenderer.cpp213
-rw-r--r--libs/hwui/GammaFontRenderer.h159
-rw-r--r--libs/hwui/GlopBuilder.cpp2
-rw-r--r--libs/hwui/OpenGLRenderer.cpp6
-rw-r--r--libs/hwui/PathCache.cpp4
-rw-r--r--libs/hwui/Program.h17
-rw-r--r--libs/hwui/ProgramCache.cpp48
-rw-r--r--libs/hwui/Properties.cpp13
-rw-r--r--libs/hwui/Properties.h28
-rw-r--r--libs/hwui/TessellationCache.cpp4
-rw-r--r--libs/hwui/TreeInfo.h2
-rw-r--r--libs/hwui/renderstate/Blend.cpp21
-rw-r--r--libs/hwui/renderstate/Blend.h3
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp115
-rw-r--r--libs/hwui/renderthread/CanvasContext.h24
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp6
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.h3
-rw-r--r--libs/hwui/renderthread/EglManager.cpp10
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp62
-rw-r--r--libs/hwui/renderthread/RenderProxy.h5
-rw-r--r--libs/hwui/unit_tests/StringUtilsTests.cpp41
-rw-r--r--libs/hwui/utils/StringUtils.cpp40
-rw-r--r--libs/hwui/utils/StringUtils.h36
-rw-r--r--media/java/android/media/midi/MidiManager.java7
-rw-r--r--media/jni/android_media_AmrInputStream.cpp2
-rw-r--r--media/jni/android_media_ImageReader.cpp4
-rw-r--r--media/jni/android_media_MediaCodec.cpp2
-rw-r--r--media/jni/android_media_MediaCodecList.cpp2
-rw-r--r--media/jni/android_media_MediaCrypto.cpp2
-rw-r--r--media/jni/android_media_MediaDrm.cpp2
-rw-r--r--media/jni/android_media_MediaExtractor.cpp2
-rw-r--r--media/jni/android_media_MediaHTTPConnection.cpp2
-rw-r--r--media/jni/android_media_MediaMetadataRetriever.cpp2
-rw-r--r--media/jni/android_media_MediaMuxer.cpp2
-rw-r--r--media/jni/android_media_MediaPlayer.cpp2
-rw-r--r--media/jni/android_media_MediaProfiles.cpp8
-rw-r--r--media/jni/android_media_MediaRecorder.cpp2
-rw-r--r--media/jni/android_media_MediaScanner.cpp2
-rw-r--r--media/jni/android_media_ResampleInputStream.cpp2
-rw-r--r--media/jni/android_mtp_MtpDatabase.cpp4
-rw-r--r--media/jni/android_mtp_MtpDevice.cpp2
-rw-r--r--media/jni/android_mtp_MtpServer.cpp2
-rw-r--r--media/jni/audioeffect/android_media_AudioEffect.cpp2
-rw-r--r--media/jni/audioeffect/android_media_Visualizer.cpp2
-rw-r--r--media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java10
-rw-r--r--packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java3
-rw-r--r--packages/DocumentsUI/AndroidManifest.xml10
-rw-r--r--packages/DocumentsUI/res/drawable/progress_indeterminate_horizontal_material_trimmed.xml28
-rw-r--r--packages/DocumentsUI/res/drawable/vector_drawable_progress_indeterminate_horizontal_trimmed.xml53
-rw-r--r--packages/DocumentsUI/res/layout/fragment_directory.xml22
-rw-r--r--packages/DocumentsUI/res/values/styles.xml10
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java55
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java120
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java75
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java60
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java7
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/MessageBar.java2
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java59
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java117
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RootsCache.java29
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/Shared.java2
-rw-r--r--packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java17
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java7
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java26
-rw-r--r--packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp2
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/RecentsComponent.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIApplication.java69
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java94
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java112
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/Classifier.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/DistanceRatioEvaluator.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/DurationCountEvaluator.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthEvaluator.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioEvaluator.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java112
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java80
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/Point.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/PointerCountEvaluator.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java93
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/ProximityEvaluator.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceClassifier.java124
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/Stroke.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/QWifiTile.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Recents.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java59
-rw-r--r--packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp2
-rw-r--r--rs/jni/android_renderscript_RenderScript.cpp2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java7
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AutoclickController.java108
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java4
-rw-r--r--services/core/java/com/android/server/DropBoxManagerService.java6
-rw-r--r--services/core/java/com/android/server/EventLogTags.logtags3
-rw-r--r--services/core/java/com/android/server/GestureLauncherService.java37
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java7
-rw-r--r--services/core/java/com/android/server/MountService.java5
-rw-r--r--services/core/java/com/android/server/NetworkScoreService.java4
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java100
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java69
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java129
-rw-r--r--services/core/java/com/android/server/am/CompatModePackages.java3
-rw-r--r--services/core/java/com/android/server/am/EventLogTags.logtags4
-rw-r--r--services/core/java/com/android/server/am/TaskRecord.java2
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java2
-rw-r--r--services/core/java/com/android/server/location/GeofenceProxy.java2
-rw-r--r--services/core/java/com/android/server/pm/Installer.java17
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java19
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java106
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java314
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java2
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java7
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java5
-rw-r--r--services/core/java/com/android/server/telecom/TelecomLoaderService.java2
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java46
-rw-r--r--services/core/java/com/android/server/wm/DockedStackDividerController.java117
-rw-r--r--services/core/java/com/android/server/wm/Task.java57
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioner.java84
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java57
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java60
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java17
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java13
-rw-r--r--services/core/jni/com_android_server_AlarmManagerService.cpp2
-rw-r--r--services/core/jni/com_android_server_AssetAtlasService.cpp2
-rw-r--r--services/core/jni/com_android_server_ConsumerIrService.cpp2
-rw-r--r--services/core/jni/com_android_server_PersistentDataBlockService.cpp2
-rw-r--r--services/core/jni/com_android_server_SerialService.cpp2
-rw-r--r--services/core/jni/com_android_server_SystemServer.cpp2
-rw-r--r--services/core/jni/com_android_server_UsbDeviceManager.cpp2
-rw-r--r--services/core/jni/com_android_server_UsbHostManager.cpp2
-rw-r--r--services/core/jni/com_android_server_VibratorService.cpp2
-rw-r--r--services/core/jni/com_android_server_am_ActivityManagerService.cpp1
-rw-r--r--services/core/jni/com_android_server_am_BatteryStatsService.cpp2
-rw-r--r--services/core/jni/com_android_server_connectivity_Vpn.cpp2
-rw-r--r--services/core/jni/com_android_server_hdmi_HdmiCecController.cpp2
-rw-r--r--services/core/jni/com_android_server_input_InputApplicationHandle.cpp2
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp2
-rw-r--r--services/core/jni/com_android_server_input_InputWindowHandle.cpp2
-rw-r--r--services/core/jni/com_android_server_lights_LightsService.cpp2
-rw-r--r--services/core/jni/com_android_server_location_FlpHardwareProvider.cpp2
-rw-r--r--services/core/jni/com_android_server_location_GpsLocationProvider.cpp2
-rw-r--r--services/core/jni/com_android_server_power_PowerManagerService.cpp2
-rw-r--r--services/core/jni/com_android_server_tv_TvInputHal.cpp2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java693
-rw-r--r--services/midi/java/com/android/server/midi/MidiService.java21
-rw-r--r--services/net/java/android/net/ip/IpReachabilityMonitor.java (renamed from core/java/android/net/IpReachabilityMonitor.java)2
-rw-r--r--services/net/java/android/net/netlink/NetlinkConstants.java (renamed from core/java/android/net/netlink/NetlinkConstants.java)0
-rw-r--r--services/net/java/android/net/netlink/NetlinkErrorMessage.java (renamed from core/java/android/net/netlink/NetlinkErrorMessage.java)0
-rw-r--r--services/net/java/android/net/netlink/NetlinkMessage.java (renamed from core/java/android/net/netlink/NetlinkMessage.java)0
-rw-r--r--services/net/java/android/net/netlink/NetlinkSocket.java (renamed from core/java/android/net/netlink/NetlinkSocket.java)0
-rw-r--r--services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java (renamed from core/java/android/net/netlink/RtNetlinkNeighborMessage.java)0
-rw-r--r--services/net/java/android/net/netlink/StructNdMsg.java (renamed from core/java/android/net/netlink/StructNdMsg.java)0
-rw-r--r--services/net/java/android/net/netlink/StructNdaCacheInfo.java (renamed from core/java/android/net/netlink/StructNdaCacheInfo.java)0
-rw-r--r--services/net/java/android/net/netlink/StructNlAttr.java (renamed from core/java/android/net/netlink/StructNlAttr.java)0
-rw-r--r--services/net/java/android/net/netlink/StructNlMsgErr.java (renamed from core/java/android/net/netlink/StructNlMsgErr.java)0
-rw-r--r--services/net/java/android/net/netlink/StructNlMsgHdr.java (renamed from core/java/android/net/netlink/StructNlMsgHdr.java)0
-rw-r--r--services/tests/servicestests/AndroidManifest.xml27
-rw-r--r--services/tests/servicestests/src/android/net/netlink/NetlinkErrorMessageTest.java (renamed from core/tests/coretests/src/android/net/netlink/NetlinkErrorMessageTest.java)0
-rw-r--r--services/tests/servicestests/src/android/net/netlink/NetlinkSocketTest.java (renamed from core/tests/coretests/src/android/net/netlink/NetlinkSocketTest.java)0
-rw-r--r--services/tests/servicestests/src/android/net/netlink/RtNetlinkNeighborMessageTest.java (renamed from core/tests/coretests/src/android/net/netlink/RtNetlinkNeighborMessageTest.java)0
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java218
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java404
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTestable.java36
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java345
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java13
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java50
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmins.java27
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java80
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java107
-rw-r--r--services/usb/java/com/android/server/usb/UsbSettingsManager.java2
-rw-r--r--tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java3
-rw-r--r--tests/HwAccelerationTest/AndroidManifest.xml9
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java347
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable01.xml8
-rw-r--r--tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java22
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/BridgeResources.java5
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java20
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java4
-rw-r--r--wifi/java/android/net/wifi/IWifiManager.aidl5
-rw-r--r--wifi/java/android/net/wifi/ScanInfo.aidl19
-rw-r--r--wifi/java/android/net/wifi/ScanInfo.java189
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java24
378 files changed, 6325 insertions, 2456 deletions
diff --git a/Android.mk b/Android.mk
index f1e16b841585..9029f4ef1f53 100644
--- a/Android.mk
+++ b/Android.mk
@@ -483,6 +483,7 @@ aidl_files := \
frameworks/base/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.aidl \
frameworks/base/wifi/java/android/net/wifi/WpsInfo.aidl \
frameworks/base/wifi/java/android/net/wifi/ScanResult.aidl \
+ frameworks/base/wifi/java/android/net/wifi/ScanInfo.aidl \
frameworks/base/wifi/java/android/net/wifi/WifiEnterpriseConfig.aidl \
frameworks/base/wifi/java/android/net/wifi/WifiConfiguration.aidl \
frameworks/base/wifi/java/android/net/wifi/WifiInfo.aidl \
diff --git a/api/current.txt b/api/current.txt
index 00b5ec02891f..758851c79abe 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -779,6 +779,7 @@ package android {
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
field public static final int letterSpacing = 16843958; // 0x10104b6
+ field public static final int level = 16844031; // 0x10104ff
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -18250,6 +18251,7 @@ package android.net {
field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
field public static final java.lang.String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
+ field public static final java.lang.String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
field public static final java.lang.String EXTRA_NETWORK = "android.net.extra.NETWORK";
@@ -19156,6 +19158,22 @@ package android.net.sip {
package android.net.wifi {
+ public class ScanInfo implements android.os.Parcelable {
+ ctor public ScanInfo(android.net.wifi.ScanResult);
+ ctor public ScanInfo(long, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, byte[], int);
+ method public int describeContents();
+ method public long getBssid();
+ method public byte[] getIconData();
+ method public java.lang.String getIconType();
+ method public java.lang.String getName();
+ method public int getOsuIdentity();
+ method public int getRssi();
+ method public android.net.wifi.ScanResult getScanResult();
+ method public java.lang.String getServiceDescription();
+ method public java.lang.String getSsid();
+ method public void writeToParcel(android.os.Parcel, int);
+ }
+
public class ScanResult implements android.os.Parcelable {
method public int describeContents();
method public boolean is80211mcResponder();
@@ -19356,6 +19374,7 @@ package android.net.wifi {
method public java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks();
method public android.net.wifi.WifiInfo getConnectionInfo();
method public android.net.DhcpInfo getDhcpInfo();
+ method public java.util.List<android.net.wifi.ScanInfo> getScanInfos();
method public java.util.List<android.net.wifi.ScanResult> getScanResults();
method public int getWifiState();
method public boolean is5GHzBandSupported();
@@ -19371,6 +19390,7 @@ package android.net.wifi {
method public boolean reconnect();
method public boolean removeNetwork(int);
method public boolean saveConfiguration();
+ method public void setOsuSelection(int);
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiEnabled(boolean);
@@ -40972,6 +40992,7 @@ package android.widget {
method public void setInterpolator(android.view.animation.Interpolator);
method public synchronized void setMax(int);
method public synchronized void setProgress(int);
+ method public void setProgress(int, boolean);
method public void setProgressBackgroundTintList(android.content.res.ColorStateList);
method public void setProgressBackgroundTintMode(android.graphics.PorterDuff.Mode);
method public void setProgressDrawable(android.graphics.drawable.Drawable);
@@ -45328,7 +45349,10 @@ package java.lang.reflect {
}
public final class Constructor extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
+ method public boolean equals(java.lang.Object);
method public A getAnnotation(java.lang.Class<A>);
+ method public java.lang.annotation.Annotation[] getAnnotations();
+ method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public java.lang.Class<T> getDeclaringClass();
method public java.lang.Class<?>[] getExceptionTypes();
method public java.lang.reflect.Type[] getGenericExceptionTypes();
@@ -45338,6 +45362,7 @@ package java.lang.reflect {
method public java.lang.annotation.Annotation[][] getParameterAnnotations();
method public java.lang.Class<?>[] getParameterTypes();
method public java.lang.reflect.TypeVariable<java.lang.reflect.Constructor<T>>[] getTypeParameters();
+ method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
method public boolean isSynthetic();
method public boolean isVarArgs();
method public T newInstance(java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException;
@@ -45411,7 +45436,10 @@ package java.lang.reflect {
}
public final class Method extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
+ method public boolean equals(java.lang.Object);
method public A getAnnotation(java.lang.Class<A>);
+ method public java.lang.annotation.Annotation[] getAnnotations();
+ method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public java.lang.Class<?> getDeclaringClass();
method public java.lang.Object getDefaultValue();
method public java.lang.Class<?>[] getExceptionTypes();
@@ -45425,6 +45453,7 @@ package java.lang.reflect {
method public java.lang.Class<?> getReturnType();
method public java.lang.reflect.TypeVariable<java.lang.reflect.Method>[] getTypeParameters();
method public java.lang.Object invoke(java.lang.Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
+ method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
method public boolean isBridge();
method public boolean isSynthetic();
method public boolean isVarArgs();
diff --git a/api/system-current.txt b/api/system-current.txt
index b2803b7ffafc..256824010308 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -871,6 +871,7 @@ package android {
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
field public static final int letterSpacing = 16843958; // 0x10104b6
+ field public static final int level = 16844031; // 0x10104ff
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -19762,6 +19763,7 @@ package android.net {
field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
field public static final java.lang.String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
+ field public static final java.lang.String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
field public static final java.lang.String EXTRA_NETWORK = "android.net.extra.NETWORK";
@@ -20909,6 +20911,22 @@ package android.net.wifi {
field public byte id;
}
+ public class ScanInfo implements android.os.Parcelable {
+ ctor public ScanInfo(android.net.wifi.ScanResult);
+ ctor public ScanInfo(long, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, byte[], int);
+ method public int describeContents();
+ method public long getBssid();
+ method public byte[] getIconData();
+ method public java.lang.String getIconType();
+ method public java.lang.String getName();
+ method public int getOsuIdentity();
+ method public int getRssi();
+ method public android.net.wifi.ScanResult getScanResult();
+ method public java.lang.String getServiceDescription();
+ method public java.lang.String getSsid();
+ method public void writeToParcel(android.os.Parcel, int);
+ }
+
public class ScanResult implements android.os.Parcelable {
method public int describeContents();
method public boolean is80211mcResponder();
@@ -21134,6 +21152,7 @@ package android.net.wifi {
method public android.net.wifi.WifiConnectionStatistics getConnectionStatistics();
method public android.net.DhcpInfo getDhcpInfo();
method public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
+ method public java.util.List<android.net.wifi.ScanInfo> getScanInfos();
method public java.util.List<android.net.wifi.ScanResult> getScanResults();
method public int getWifiState();
method public boolean is5GHzBandSupported();
@@ -21153,6 +21172,7 @@ package android.net.wifi {
method public boolean reconnect();
method public boolean removeNetwork(int);
method public boolean saveConfiguration();
+ method public void setOsuSelection(int);
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiEnabled(boolean);
@@ -25667,8 +25687,8 @@ package android.os {
ctor public UserHandle(android.os.Parcel);
method public int describeContents();
method public int getIdentifier();
- method public final boolean isOwner();
- method public static final int myUserId();
+ method public boolean isOwner();
+ method public static int myUserId();
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);
@@ -43580,6 +43600,7 @@ package android.widget {
method public void setInterpolator(android.view.animation.Interpolator);
method public synchronized void setMax(int);
method public synchronized void setProgress(int);
+ method public void setProgress(int, boolean);
method public void setProgressBackgroundTintList(android.content.res.ColorStateList);
method public void setProgressBackgroundTintMode(android.graphics.PorterDuff.Mode);
method public void setProgressDrawable(android.graphics.drawable.Drawable);
@@ -47936,7 +47957,10 @@ package java.lang.reflect {
}
public final class Constructor extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
+ method public boolean equals(java.lang.Object);
method public A getAnnotation(java.lang.Class<A>);
+ method public java.lang.annotation.Annotation[] getAnnotations();
+ method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public java.lang.Class<T> getDeclaringClass();
method public java.lang.Class<?>[] getExceptionTypes();
method public java.lang.reflect.Type[] getGenericExceptionTypes();
@@ -47946,6 +47970,7 @@ package java.lang.reflect {
method public java.lang.annotation.Annotation[][] getParameterAnnotations();
method public java.lang.Class<?>[] getParameterTypes();
method public java.lang.reflect.TypeVariable<java.lang.reflect.Constructor<T>>[] getTypeParameters();
+ method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
method public boolean isSynthetic();
method public boolean isVarArgs();
method public T newInstance(java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException;
@@ -48019,7 +48044,10 @@ package java.lang.reflect {
}
public final class Method extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
+ method public boolean equals(java.lang.Object);
method public A getAnnotation(java.lang.Class<A>);
+ method public java.lang.annotation.Annotation[] getAnnotations();
+ method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public java.lang.Class<?> getDeclaringClass();
method public java.lang.Object getDefaultValue();
method public java.lang.Class<?>[] getExceptionTypes();
@@ -48033,6 +48061,7 @@ package java.lang.reflect {
method public java.lang.Class<?> getReturnType();
method public java.lang.reflect.TypeVariable<java.lang.reflect.Method>[] getTypeParameters();
method public java.lang.Object invoke(java.lang.Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
+ method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
method public boolean isBridge();
method public boolean isSynthetic();
method public boolean isVarArgs();
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 9185d7ac127a..20ac8d83ebad 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -19,6 +19,8 @@
package com.android.commands.am;
import static android.app.ActivityManager.DOCKED_STACK_ID;
+import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
+import static android.app.ActivityManager.RESIZE_MODE_USER;
import android.app.ActivityManager;
import android.app.ActivityManager.StackInfo;
@@ -2271,7 +2273,8 @@ public class Am extends BaseCommand {
private void taskResize(int taskId, Rect bounds, int delay_ms, boolean pretendUserResize) {
try {
- mAm.resizeTask(taskId, bounds, pretendUserResize);
+ final int resizeMode = pretendUserResize ? RESIZE_MODE_USER : RESIZE_MODE_SYSTEM;
+ mAm.resizeTask(taskId, bounds, resizeMode);
Thread.sleep(delay_ms);
} catch (RemoteException e) {
System.err.println("Error changing task bounds: " + e);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 9ef51c8554d3..4191dce79be8 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -468,6 +468,29 @@ public class ActivityManager {
*/
public static final int DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT = 1;
+
+ /**
+ * Input parameter to {@link android.app.IActivityManager#resizeTask} which indicates
+ * that the resize is from the window manager (instead of the user).
+ * @hide
+ */
+ public static final int RESIZE_MODE_SYSTEM = 0;
+
+ /**
+ * Input parameter to {@link android.app.IActivityManager#resizeTask} which indicates
+ * that the resize is initiated by the user (most likely via a drag action on the
+ * window's edge or corner).
+ * @hide
+ */
+ public static final int RESIZE_MODE_USER = 1;
+
+ /**
+ * Input parameter to {@link android.app.IActivityManager#resizeTask} which indicates
+ * that the resize should be performed even if the bounds appears unchanged.
+ * @hide
+ */
+ public static final int RESIZE_MODE_FORCED = 2;
+
/** @hide */
public int getFrontActivityScreenCompatMode() {
try {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index da6fc592e69a..3864a4bba1f9 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2452,9 +2452,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
case RESIZE_TASK_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int taskId = data.readInt();
- final boolean resizedByUser = data.readInt() == 1;
+ int resizeMode = data.readInt();
Rect r = Rect.CREATOR.createFromParcel(data);
- resizeTask(taskId, r, resizedByUser);
+ resizeTask(taskId, r, resizeMode);
reply.writeNoException();
return true;
}
@@ -5900,13 +5900,13 @@ class ActivityManagerProxy implements IActivityManager
}
@Override
- public void resizeTask(int taskId, Rect r, boolean resizedByUser) throws RemoteException
+ public void resizeTask(int taskId, Rect r, int resizeMode) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(taskId);
- data.writeInt(resizedByUser ? 1 : 0);
+ data.writeInt(resizeMode);
r.writeToParcel(data, 0);
mRemote.transact(RESIZE_TASK_TRANSACTION, data, reply, 0);
reply.readException();
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 0cd02dd397c1..5544a7150625 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -93,8 +93,8 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
-/*package*/
-final class ApplicationPackageManager extends PackageManager {
+/** @hide */
+public class ApplicationPackageManager extends PackageManager {
private static final String TAG = "ApplicationPackageManager";
private final static boolean DEBUG_ICONS = false;
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index f70423fbbc9a..b44aab717174 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -63,6 +63,7 @@ final class FragmentState implements Parcelable {
final boolean mRetainInstance;
final boolean mDetached;
final Bundle mArguments;
+ final boolean mHidden;
Bundle mSavedFragmentState;
@@ -78,6 +79,7 @@ final class FragmentState implements Parcelable {
mRetainInstance = frag.mRetainInstance;
mDetached = frag.mDetached;
mArguments = frag.mArguments;
+ mHidden = frag.mHidden;
}
public FragmentState(Parcel in) {
@@ -90,6 +92,7 @@ final class FragmentState implements Parcelable {
mRetainInstance = in.readInt() != 0;
mDetached = in.readInt() != 0;
mArguments = in.readBundle();
+ mHidden = in.readInt() != 0;
mSavedFragmentState = in.readBundle();
}
@@ -117,6 +120,7 @@ final class FragmentState implements Parcelable {
mInstance.mTag = mTag;
mInstance.mRetainInstance = mRetainInstance;
mInstance.mDetached = mDetached;
+ mInstance.mHidden = mHidden;
mInstance.mFragmentManager = host.mFragmentManager;
if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
"Instantiated fragment " + mInstance);
@@ -138,6 +142,7 @@ final class FragmentState implements Parcelable {
dest.writeInt(mRetainInstance ? 1 : 0);
dest.writeInt(mDetached ? 1 : 0);
dest.writeBundle(mArguments);
+ dest.writeInt(mHidden ? 1 : 0);
dest.writeBundle(mSavedFragmentState);
}
@@ -460,6 +465,9 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
// If set this fragment is being retained across the current config change.
boolean mRetaining;
+ // If set this fragment's loaders are being retained across the current config change.
+ boolean mRetainLoader;
+
// If set this fragment has menu items to contribute.
boolean mHasMenu;
@@ -2407,7 +2415,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
}
if (mLoaderManager != null) {
- if (mRetaining) {
+ if (mRetainLoader) {
mLoaderManager.doRetain();
} else {
mLoaderManager.doStop();
diff --git a/core/java/android/app/FragmentController.java b/core/java/android/app/FragmentController.java
index 28dadfa78b32..1b45137fb7c9 100644
--- a/core/java/android/app/FragmentController.java
+++ b/core/java/android/app/FragmentController.java
@@ -341,6 +341,7 @@ public class FragmentController {
*/
public void doLoaderStop(boolean retain) {
mHost.doLoaderStop(retain);
+ mHost.mFragmentManager.setRetainLoader(retain);
}
/**
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 132ffef861e6..51d613247c87 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -869,6 +869,17 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
}
}
+ void setRetainLoader(boolean retain) {
+ if (mActive != null) {
+ for (int i=0; i<mActive.size(); i++) {
+ Fragment f = mActive.get(i);
+ if (f != null) {
+ f.mRetainLoader = retain;
+ }
+ }
+ }
+ }
+
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
if (DEBUG && false) Log.v(TAG, "moveToState: " + f
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 7bd832bf5f95..2180bcc1e4b9 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -491,7 +491,7 @@ public interface IActivityManager extends IInterface {
public void setTaskDescription(IBinder token, ActivityManager.TaskDescription values)
throws RemoteException;
public void setTaskResizeable(int taskId, boolean resizeable) throws RemoteException;
- public void resizeTask(int taskId, Rect bounds, boolean resizedByUser) throws RemoteException;
+ public void resizeTask(int taskId, Rect bounds, int resizeMode) throws RemoteException;
public Rect getTaskBounds(int taskId) throws RemoteException;
public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 3d264c6f2cba..288a2cb5fa4f 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -240,7 +240,7 @@ final class SystemServiceRegistry {
new CachedServiceFetcher<DevicePolicyManager>() {
@Override
public DevicePolicyManager createService(ContextImpl ctx) {
- return DevicePolicyManager.create(ctx, ctx.mMainThread.getHandler());
+ return DevicePolicyManager.create(ctx);
}});
registerService(Context.DOWNLOAD_SERVICE, DownloadManager.class,
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index d1e40ae9bd5e..4e9adf09c351 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -20,6 +20,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -360,6 +361,7 @@ public final class DeviceAdminInfo implements Parcelable {
/**
* Return the component of the receiver that implements this device admin.
*/
+ @NonNull
public ComponentName getComponent() {
return new ComponentName(mReceiver.activityInfo.packageName,
mReceiver.activityInfo.name);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ac50699ca110..e6484e965ee0 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -32,7 +32,6 @@ import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.net.ProxyInfo;
import android.os.Bundle;
-import android.os.Handler;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteCallback;
@@ -45,6 +44,7 @@ import android.security.Credentials;
import android.service.restrictions.RestrictionsReceiver;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.org.conscrypt.TrustedCertificateStore;
import org.xmlpull.v1.XmlPullParserException;
@@ -87,18 +87,30 @@ public class DevicePolicyManager {
private final Context mContext;
private final IDevicePolicyManager mService;
- private DevicePolicyManager(Context context, Handler handler) {
+ private DevicePolicyManager(Context context) {
+ this(context, IDevicePolicyManager.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)));
+ }
+
+ /** @hide */
+ @VisibleForTesting
+ protected DevicePolicyManager(Context context, IDevicePolicyManager service) {
mContext = context;
- mService = IDevicePolicyManager.Stub.asInterface(
- ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
+ mService = service;
}
/** @hide */
- public static DevicePolicyManager create(Context context, Handler handler) {
- DevicePolicyManager me = new DevicePolicyManager(context, handler);
+ public static DevicePolicyManager create(Context context) {
+ DevicePolicyManager me = new DevicePolicyManager(context);
return me.mService != null ? me : null;
}
+ /** @hide test will override it. */
+ @VisibleForTesting
+ protected int myUserId() {
+ return UserHandle.myUserId();
+ }
+
/**
* Activity action: Starts the provisioning flow which sets up a managed profile.
*
@@ -823,7 +835,7 @@ public class DevicePolicyManager {
* active (enabled) in the system.
*/
public boolean isAdminActive(@NonNull ComponentName admin) {
- return isAdminActiveAsUser(admin, UserHandle.myUserId());
+ return isAdminActiveAsUser(admin, myUserId());
}
/**
@@ -863,7 +875,7 @@ public class DevicePolicyManager {
* returned.
*/
public List<ComponentName> getActiveAdmins() {
- return getActiveAdminsAsUser(UserHandle.myUserId());
+ return getActiveAdminsAsUser(myUserId());
}
/**
@@ -889,7 +901,7 @@ public class DevicePolicyManager {
public boolean packageHasActiveAdmins(String packageName) {
if (mService != null) {
try {
- return mService.packageHasActiveAdmins(packageName, UserHandle.myUserId());
+ return mService.packageHasActiveAdmins(packageName, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -906,7 +918,7 @@ public class DevicePolicyManager {
public void removeActiveAdmin(@NonNull ComponentName admin) {
if (mService != null) {
try {
- mService.removeActiveAdmin(admin, UserHandle.myUserId());
+ mService.removeActiveAdmin(admin, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -925,7 +937,7 @@ public class DevicePolicyManager {
public boolean hasGrantedPolicy(@NonNull ComponentName admin, int usesPolicy) {
if (mService != null) {
try {
- return mService.hasGrantedPolicy(admin, usesPolicy, UserHandle.myUserId());
+ return mService.hasGrantedPolicy(admin, usesPolicy, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1040,7 +1052,7 @@ public class DevicePolicyManager {
* all admins.
*/
public int getPasswordQuality(@Nullable ComponentName admin) {
- return getPasswordQuality(admin, UserHandle.myUserId());
+ return getPasswordQuality(admin, myUserId());
}
/** @hide per-user version */
@@ -1093,7 +1105,7 @@ public class DevicePolicyManager {
* all admins.
*/
public int getPasswordMinimumLength(@Nullable ComponentName admin) {
- return getPasswordMinimumLength(admin, UserHandle.myUserId());
+ return getPasswordMinimumLength(admin, myUserId());
}
/** @hide per-user version */
@@ -1154,7 +1166,7 @@ public class DevicePolicyManager {
* password.
*/
public int getPasswordMinimumUpperCase(@Nullable ComponentName admin) {
- return getPasswordMinimumUpperCase(admin, UserHandle.myUserId());
+ return getPasswordMinimumUpperCase(admin, myUserId());
}
/** @hide per-user version */
@@ -1215,7 +1227,7 @@ public class DevicePolicyManager {
* password.
*/
public int getPasswordMinimumLowerCase(@Nullable ComponentName admin) {
- return getPasswordMinimumLowerCase(admin, UserHandle.myUserId());
+ return getPasswordMinimumLowerCase(admin, myUserId());
}
/** @hide per-user version */
@@ -1273,7 +1285,7 @@ public class DevicePolicyManager {
* @return The minimum number of letters required in the password.
*/
public int getPasswordMinimumLetters(@Nullable ComponentName admin) {
- return getPasswordMinimumLetters(admin, UserHandle.myUserId());
+ return getPasswordMinimumLetters(admin, myUserId());
}
/** @hide per-user version */
@@ -1332,7 +1344,7 @@ public class DevicePolicyManager {
* @return The minimum number of numerical digits required in the password.
*/
public int getPasswordMinimumNumeric(@Nullable ComponentName admin) {
- return getPasswordMinimumNumeric(admin, UserHandle.myUserId());
+ return getPasswordMinimumNumeric(admin, myUserId());
}
/** @hide per-user version */
@@ -1390,7 +1402,7 @@ public class DevicePolicyManager {
* @return The minimum number of symbols required in the password.
*/
public int getPasswordMinimumSymbols(@Nullable ComponentName admin) {
- return getPasswordMinimumSymbols(admin, UserHandle.myUserId());
+ return getPasswordMinimumSymbols(admin, myUserId());
}
/** @hide per-user version */
@@ -1449,7 +1461,7 @@ public class DevicePolicyManager {
* @return The minimum number of letters required in the password.
*/
public int getPasswordMinimumNonLetter(@Nullable ComponentName admin) {
- return getPasswordMinimumNonLetter(admin, UserHandle.myUserId());
+ return getPasswordMinimumNonLetter(admin, myUserId());
}
/** @hide per-user version */
@@ -1540,7 +1552,7 @@ public class DevicePolicyManager {
public long getPasswordExpirationTimeout(@Nullable ComponentName admin) {
if (mService != null) {
try {
- return mService.getPasswordExpirationTimeout(admin, UserHandle.myUserId());
+ return mService.getPasswordExpirationTimeout(admin, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1561,7 +1573,7 @@ public class DevicePolicyManager {
public long getPasswordExpiration(@Nullable ComponentName admin) {
if (mService != null) {
try {
- return mService.getPasswordExpiration(admin, UserHandle.myUserId());
+ return mService.getPasswordExpiration(admin, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1577,7 +1589,7 @@ public class DevicePolicyManager {
* @return The length of the password history
*/
public int getPasswordHistoryLength(@Nullable ComponentName admin) {
- return getPasswordHistoryLength(admin, UserHandle.myUserId());
+ return getPasswordHistoryLength(admin, myUserId());
}
/** @hide per-user version */
@@ -1617,7 +1629,7 @@ public class DevicePolicyManager {
public boolean isActivePasswordSufficient() {
if (mService != null) {
try {
- return mService.isActivePasswordSufficient(UserHandle.myUserId());
+ return mService.isActivePasswordSufficient(myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1636,7 +1648,7 @@ public class DevicePolicyManager {
public int getCurrentFailedPasswordAttempts() {
if (mService != null) {
try {
- return mService.getCurrentFailedPasswordAttempts(UserHandle.myUserId());
+ return mService.getCurrentFailedPasswordAttempts(myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1698,7 +1710,7 @@ public class DevicePolicyManager {
* all admins.
*/
public int getMaximumFailedPasswordsForWipe(@Nullable ComponentName admin) {
- return getMaximumFailedPasswordsForWipe(admin, UserHandle.myUserId());
+ return getMaximumFailedPasswordsForWipe(admin, myUserId());
}
/** @hide per-user version */
@@ -1818,7 +1830,7 @@ public class DevicePolicyManager {
* all admins if admin is null. Returns 0 if there are no restrictions.
*/
public long getMaximumTimeToLock(@Nullable ComponentName admin) {
- return getMaximumTimeToLock(admin, UserHandle.myUserId());
+ return getMaximumTimeToLock(admin, myUserId());
}
/** @hide per-user version */
@@ -1881,7 +1893,7 @@ public class DevicePolicyManager {
public void wipeData(int flags) {
if (mService != null) {
try {
- mService.wipeData(flags, UserHandle.myUserId());
+ mService.wipeData(flags, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1995,7 +2007,7 @@ public class DevicePolicyManager {
public ComponentName getGlobalProxyAdmin() {
if (mService != null) {
try {
- return mService.getGlobalProxyAdmin(UserHandle.myUserId());
+ return mService.getGlobalProxyAdmin(myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -2145,7 +2157,7 @@ public class DevicePolicyManager {
public boolean getStorageEncryption(@Nullable ComponentName admin) {
if (mService != null) {
try {
- return mService.getStorageEncryption(admin, UserHandle.myUserId());
+ return mService.getStorageEncryption(admin, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -2173,7 +2185,7 @@ public class DevicePolicyManager {
* or {@link #ENCRYPTION_STATUS_ACTIVE}.
*/
public int getStorageEncryptionStatus() {
- return getStorageEncryptionStatus(UserHandle.myUserId());
+ return getStorageEncryptionStatus(myUserId());
}
/** @hide per-user version */
@@ -2410,7 +2422,7 @@ public class DevicePolicyManager {
* have disabled the camera
*/
public boolean getCameraDisabled(@Nullable ComponentName admin) {
- return getCameraDisabled(admin, UserHandle.myUserId());
+ return getCameraDisabled(admin, myUserId());
}
/** @hide per-user version */
@@ -2457,7 +2469,7 @@ public class DevicePolicyManager {
* have disabled screen capture.
*/
public boolean getScreenCaptureDisabled(@Nullable ComponentName admin) {
- return getScreenCaptureDisabled(admin, UserHandle.myUserId());
+ return getScreenCaptureDisabled(admin, myUserId());
}
/** @hide per-user version */
@@ -2557,7 +2569,7 @@ public class DevicePolicyManager {
* for a list.
*/
public int getKeyguardDisabledFeatures(@Nullable ComponentName admin) {
- return getKeyguardDisabledFeatures(admin, UserHandle.myUserId());
+ return getKeyguardDisabledFeatures(admin, myUserId());
}
/** @hide per-user version */
@@ -2590,7 +2602,7 @@ public class DevicePolicyManager {
* @hide
*/
public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing) {
- setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId());
+ setActiveAdmin(policyReceiver, refreshing, myUserId());
}
/**
@@ -2627,7 +2639,7 @@ public class DevicePolicyManager {
public void getRemoveWarning(@Nullable ComponentName admin, RemoteCallback result) {
if (mService != null) {
try {
- mService.getRemoveWarning(admin, result, UserHandle.myUserId());
+ mService.getRemoveWarning(admin, result, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -2956,7 +2968,7 @@ public class DevicePolicyManager {
throws IllegalArgumentException {
if (mService != null) {
try {
- final int myUserId = UserHandle.myUserId();
+ final int myUserId = myUserId();
mService.setActiveAdmin(admin, false, myUserId);
return mService.setProfileOwner(admin, ownerName, myUserId);
} catch (RemoteException re) {
@@ -3301,7 +3313,7 @@ public class DevicePolicyManager {
*/
public List<PersistableBundle> getTrustAgentConfiguration(@Nullable ComponentName admin,
@NonNull ComponentName agent) {
- return getTrustAgentConfiguration(admin, agent, UserHandle.myUserId());
+ return getTrustAgentConfiguration(admin, agent, myUserId());
}
/** @hide per-user version */
@@ -3927,7 +3939,7 @@ public class DevicePolicyManager {
* @see #setAccountManagementDisabled
*/
public String[] getAccountTypesWithManagementDisabled() {
- return getAccountTypesWithManagementDisabledAsUser(UserHandle.myUserId());
+ return getAccountTypesWithManagementDisabledAsUser(myUserId());
}
/**
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 73925633f741..d7c221510942 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -136,7 +136,16 @@ public class UserInfo implements Parcelable {
* the method always returns false.
*/
public boolean isSystemOnly() {
- return id == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser();
+ return isSystemOnly(id);
+ }
+
+ /**
+ * Returns true if the given user is a split system user.
+ * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
+ * the method always returns false.
+ */
+ public static boolean isSystemOnly(int userId) {
+ return userId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser();
}
/**
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 927c02f9ecfd..477b62cd86fa 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -61,7 +61,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* resource qualifier. 0 if undefined.
*/
public int mcc;
-
+
/**
* IMSI MNC (Mobile Network Code), corresponding to
* <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mnc</a>
@@ -199,7 +199,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* @hide
*/
public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000;
-
+
/**
* Bit mask of overall layout of the screen. Currently there are two
* fields:
@@ -207,11 +207,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* of the screen. They may be one of
* {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL},
* {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}.</p>
- *
+ *
* <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen
* is wider/taller than normal. They may be one of
* {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.</p>
- *
+ *
* <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout
* is either LTR or RTL. They may be one of
* {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.</p>
@@ -295,6 +295,62 @@ public final class Configuration implements Parcelable, Comparable<Configuration
return curLayout;
}
+ /** @hide */
+ public static String configurationDiffToString(int diff) {
+ ArrayList<String> list = new ArrayList<>();
+ if ((diff & ActivityInfo.CONFIG_MCC) != 0) {
+ list.add("CONFIG_MCC");
+ }
+ if ((diff & ActivityInfo.CONFIG_MNC) != 0) {
+ list.add("CONFIG_MNC");
+ }
+ if ((diff & ActivityInfo.CONFIG_LOCALE) != 0) {
+ list.add("CONFIG_LOCALE");
+ }
+ if ((diff & ActivityInfo.CONFIG_TOUCHSCREEN) != 0) {
+ list.add("CONFIG_TOUCHSCREEN");
+ }
+ if ((diff & ActivityInfo.CONFIG_KEYBOARD) != 0) {
+ list.add("CONFIG_KEYBOARD");
+ }
+ if ((diff & ActivityInfo.CONFIG_KEYBOARD_HIDDEN) != 0) {
+ list.add("CONFIG_KEYBOARD_HIDDEN");
+ }
+ if ((diff & ActivityInfo.CONFIG_NAVIGATION) != 0) {
+ list.add("CONFIG_NAVIGATION");
+ }
+ if ((diff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
+ list.add("CONFIG_ORIENTATION");
+ }
+ if ((diff & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) {
+ list.add("CONFIG_SCREEN_LAYOUT");
+ }
+ if ((diff & ActivityInfo.CONFIG_UI_MODE) != 0) {
+ list.add("CONFIG_UI_MODE");
+ }
+ if ((diff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) {
+ list.add("CONFIG_SCREEN_SIZE");
+ }
+ if ((diff & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
+ list.add("CONFIG_SMALLEST_SCREEN_SIZE");
+ }
+ if ((diff & ActivityInfo.CONFIG_LAYOUT_DIRECTION) != 0) {
+ list.add("CONFIG_LAYOUT_DIRECTION");
+ }
+ if ((diff & ActivityInfo.CONFIG_FONT_SCALE) != 0) {
+ list.add("CONFIG_FONT_SCALE");
+ }
+ StringBuilder builder = new StringBuilder("{");
+ for (int i = 0, n = list.size(); i < n; i++) {
+ builder.append(list.get(i));
+ if (i != n - 1) {
+ builder.append(", ");
+ }
+ }
+ builder.append("}");
+ return builder.toString();
+ }
+
/**
* Check if the Configuration's current {@link #screenLayout} is at
* least the given size.
@@ -323,7 +379,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a>
* resource qualifier. */
public static final int TOUCHSCREEN_FINGER = 3;
-
+
/**
* The kind of touch screen attached to the device.
* One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_FINGER}.
@@ -344,7 +400,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">12key</a>
* resource qualifier. */
public static final int KEYBOARD_12KEY = 3;
-
+
/**
* The kind of keyboard attached to the device.
* One of: {@link #KEYBOARD_NOKEYS}, {@link #KEYBOARD_QWERTY},
@@ -364,7 +420,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
public static final int KEYBOARDHIDDEN_YES = 2;
/** Constant matching actual resource implementation. {@hide} */
public static final int KEYBOARDHIDDEN_SOFT = 3;
-
+
/**
* A flag indicating whether any keyboard is available. Unlike
* {@link #hardKeyboardHidden}, this also takes into account a soft
@@ -373,7 +429,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}.
*/
public int keyboardHidden;
-
+
/** Constant for {@link #hardKeyboardHidden}: a value indicating that no value has been set. */
public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0;
/** Constant for {@link #hardKeyboardHidden}, value corresponding to the
@@ -382,7 +438,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
/** Constant for {@link #hardKeyboardHidden}, value corresponding to the
* physical keyboard being hidden. */
public static final int HARDKEYBOARDHIDDEN_YES = 2;
-
+
/**
* A flag indicating whether the hard keyboard has been hidden. This will
* be set on a device with a mechanism to hide the keyboard from the
@@ -390,7 +446,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}.
*/
public int hardKeyboardHidden;
-
+
/** Constant for {@link #navigation}: a value indicating that no value has been set. */
public static final int NAVIGATION_UNDEFINED = 0;
/** Constant for {@link #navigation}, value corresponding to the
@@ -409,14 +465,14 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a>
* resource qualifier. */
public static final int NAVIGATION_WHEEL = 4;
-
+
/**
* The kind of navigation method available on the device.
* One of: {@link #NAVIGATION_NONAV}, {@link #NAVIGATION_DPAD},
* {@link #NAVIGATION_TRACKBALL}, {@link #NAVIGATION_WHEEL}.
*/
public int navigation;
-
+
/** Constant for {@link #navigationHidden}: a value indicating that no value has been set. */
public static final int NAVIGATIONHIDDEN_UNDEFINED = 0;
/** Constant for {@link #navigationHidden}, value corresponding to the
@@ -427,7 +483,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a>
* resource qualifier. */
public static final int NAVIGATIONHIDDEN_YES = 2;
-
+
/**
* A flag indicating whether any 5-way or DPAD navigation available.
* This will be set on a device with a mechanism to hide the navigation
@@ -435,7 +491,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}.
*/
public int navigationHidden;
-
+
/** Constant for {@link #orientation}: a value indicating that no value has been set. */
public static final int ORIENTATION_UNDEFINED = 0;
/** Constant for {@link #orientation}, value corresponding to the
@@ -448,7 +504,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
public static final int ORIENTATION_LANDSCAPE = 2;
/** @deprecated Not currently supported or used. */
@Deprecated public static final int ORIENTATION_SQUARE = 3;
-
+
/**
* Overall orientation of the screen. May be one of
* {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}.
@@ -692,7 +748,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
seq = o.seq;
}
-
+
public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append("{");
@@ -861,7 +917,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
@Deprecated public void makeDefault() {
setToDefaults();
}
-
+
/**
* Copy the fields from delta into this Configuration object, keeping
* track of which ones have changed. Any undefined fields in
@@ -1001,7 +1057,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
if (delta.seq != 0) {
seq = delta.seq;
}
-
+
return changed;
}
@@ -1119,12 +1175,12 @@ public final class Configuration implements Parcelable, Comparable<Configuration
/**
* Determine if a new resource needs to be loaded from the bit set of
* configuration changes returned by {@link #updateFrom(Configuration)}.
- *
+ *
* @param configChanges The mask of changes configurations as returned by
* {@link #updateFrom(Configuration)}.
* @param interestingChanges The configuration changes that the resource
* can handled, as given in {@link android.util.TypedValue#changingConfigurations}.
- *
+ *
* @return Return true if the resource needs to be loaded, else false.
*/
public static boolean needNewResources(int configChanges, int interestingChanges) {
@@ -1159,7 +1215,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
}
return diff > 0;
}
-
+
/**
* Parcelable methods
*/
@@ -1236,7 +1292,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
compatSmallestScreenWidthDp = source.readInt();
seq = source.readInt();
}
-
+
public static final Parcelable.Creator<Configuration> CREATOR
= new Parcelable.Creator<Configuration>() {
public Configuration createFromParcel(Parcel source) {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 9a2a24128b92..444548faad42 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -208,6 +208,12 @@ public class ConnectivityManager {
* {@link android.content.Intent#getParcelableExtra(String)}.
*/
public static final String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
+
+ /**
+ * Key for passing a URL to the captive portal login activity.
+ */
+ public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
+
/**
* Broadcast action to indicate the change of data activity status
* (idle or active) on a network in a recent period.
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index a939ccee4ca7..3f36d65e577c 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -245,7 +245,8 @@ public class NetworkScoreManager {
intent.putExtra(EXTRA_NETWORKS_TO_SCORE, networks);
// A scorer should never become active if its package doesn't hold SCORE_NETWORKS, but
// ensure the package still holds it to be extra safe.
- mContext.sendBroadcastAsUser(intent, UserHandle.OWNER, Manifest.permission.SCORE_NETWORKS);
+ // TODO: http://b/23422763
+ mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM, Manifest.permission.SCORE_NETWORKS);
return true;
}
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 8c544f44f244..41de579201a5 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -410,7 +410,7 @@ public class RecoverySystem {
Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- context.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER,
+ context.sendOrderedBroadcastAsUser(intent, UserHandle.SYSTEM,
android.Manifest.permission.MASTER_CLEAR,
new BroadcastReceiver() {
@Override
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 87ce12cbe37c..8b2c74f07598 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1923,7 +1923,7 @@ public final class StrictMode {
if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i);
ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
if (info.crashInfo.stackTrace != null && info.crashInfo.stackTrace.length() > 30000) {
- String front = info.crashInfo.stackTrace.substring(256);
+ String front = info.crashInfo.stackTrace.substring(0, 256);
// 30000 characters is way too large for this to be any sane kind of
// strict mode collection of stacks. We've had a problem where we leave
// strict mode violations associated with the thread, and it keeps tacking
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 688859479713..c368e5a24a1b 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -438,6 +438,8 @@ public class VolumeInfo implements Parcelable {
final Intent intent = new Intent(DocumentsContract.ACTION_BROWSE_DOCUMENT_ROOT);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(uri);
+ intent.putExtra(DocumentsContract.EXTRA_SHOW_FILESIZE, true);
+ intent.putExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, true);
return intent;
}
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 59609f94546a..1a83cd567dc0 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -93,6 +93,9 @@ public final class DocumentsContract {
public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED";
/** {@hide} */
+ public static final String EXTRA_SHOW_FILESIZE = "android.content.extra.SHOW_FILESIZE";
+
+ /** {@hide} */
public static final String EXTRA_TARGET_URI = "android.content.extra.TARGET_URI";
/**
@@ -266,7 +269,7 @@ public final class DocumentsContract {
* writability of a document may change over time, for example due to
* remote access changes. This flag indicates that a document client can
* expect {@link ContentResolver#openOutputStream(Uri)} to succeed.
- *
+ *
* @see #COLUMN_FLAGS
*/
public static final int FLAG_SUPPORTS_WRITE = 1 << 1;
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 420f7a174d53..dcef14267b7f 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -108,6 +108,11 @@ public class ThreadedRenderer extends HardwareRenderer {
private Choreographer mChoreographer;
private boolean mRootNodeNeedsUpdate;
+ // In case of multi threaded render nodes, these bounds indicate the content bounds against
+ // which the backdrop needs to be cropped against.
+ private final Rect mCurrentContentBounds = new Rect();
+ private final Rect mStagedContentBounds = new Rect();
+
ThreadedRenderer(Context context, boolean translucent) {
final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
@@ -307,6 +312,47 @@ public class ThreadedRenderer extends HardwareRenderer {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
+ /**
+ * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
+ * rendernode of the UI thread.
+ * @param node The node to add.
+ * @param placeFront If true, the render node will be placed in front of the content node,
+ * otherwise behind the content node.
+ */
+ public void addRenderNode(RenderNode node, boolean placeFront) {
+ nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
+ }
+
+ /**
+ * Only especially added render nodes can be removed.
+ * @param node The node which was added via addRenderNode which should get removed again.
+ */
+ public void removeRenderNode(RenderNode node) {
+ nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
+ }
+
+ /**
+ * Draws a particular render node. If the node is not the content node, only the additional
+ * nodes will get drawn and the content remains untouched.
+ * @param node The node to be drawn.
+ */
+ public void drawRenderNode(RenderNode node) {
+ nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
+ }
+
+ /**
+ * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
+ * will be prevented to overdraw this area. It will be synchronized with the draw call.
+ * This should be updated in the content view's draw call.
+ * @param left The left side of the protected bounds.
+ * @param top The top side of the protected bounds.
+ * @param right The right side of the protected bounds.
+ * @param bottom The bottom side of the protected bounds.
+ */
+ public void setContentOverdrawProtectionBounds(int left, int top, int right, int bottom) {
+ mStagedContentBounds.set(left, top, right, bottom);
+ }
+
@Override
void invalidateRoot() {
mRootNodeNeedsUpdate = true;
@@ -320,6 +366,14 @@ public class ThreadedRenderer extends HardwareRenderer {
choreographer.mFrameInfo.markDrawStart();
updateRootDisplayList(view, callbacks);
+ // The main content view was updating the content bounds and we transfer them to the
+ // renderer.
+ if (!mCurrentContentBounds.equals(mStagedContentBounds)) {
+ mCurrentContentBounds.set(mStagedContentBounds);
+ nSetContentOverdrawProtectionBounds(mNativeProxy, mCurrentContentBounds.left,
+ mCurrentContentBounds.top, mCurrentContentBounds.right,
+ mCurrentContentBounds.bottom);
+ }
attachInfo.mIgnoreDirtyState = false;
@@ -541,4 +595,11 @@ public class ThreadedRenderer extends HardwareRenderer {
private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
@DumpFlags int dumpFlags);
private static native void nDumpProfileData(byte[] data, FileDescriptor fd);
+
+ private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
+ boolean placeFront);
+ private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
+ private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
+ private static native void nSetContentOverdrawProtectionBounds(long nativeProxy, int left,
+ int top, int right, int bottom);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4d95294453ac..2a1d757feb7b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7373,6 +7373,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Compute the view's coordinate within the surface.
+ *
+ * <p>Computes the coordinates of this view in its surface. The argument
+ * must be an array of two integers. After the method returns, the array
+ * contains the x and y location in that order.</p>
+ * @hide
+ * @param location an array of two integers in which to hold the coordinates
+ */
+ public void getLocationInSurface(@Size(2) int[] location) {
+ getLocationInWindow(location);
+ if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
+ location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
+ location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
+ }
+ }
+
+ /**
* Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
* only available if the view is attached.
*
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 85b6a096bba9..8403c46e85bc 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1787,10 +1787,6 @@ public final class ViewRootImpl implements ViewParent,
|| mHeight != hardwareRenderer.getHeight()) {
hardwareRenderer.setup(mWidth, mHeight, mAttachInfo,
mWindowAttributes.surfaceInsets);
- if (!hwInitialized) {
- hardwareRenderer.invalidate(mSurface);
- mFullRedrawNeeded = true;
- }
}
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 45bc1df33469..92e473db556f 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -226,6 +226,7 @@ public interface WindowManager extends ViewManager {
@ViewDebug.IntToString(from = TYPE_PRIVATE_PRESENTATION, to = "TYPE_PRIVATE_PRESENTATION"),
@ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION, to = "TYPE_VOICE_INTERACTION"),
@ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION_STARTING, to = "TYPE_VOICE_INTERACTION_STARTING"),
+ @ViewDebug.IntToString(from = TYPE_DOCK_DIVIDER, to = "TYPE_DOCK_DIVIDER"),
})
public int type;
@@ -565,6 +566,13 @@ public interface WindowManager extends ViewManager {
public static final int TYPE_VOICE_INTERACTION_STARTING = FIRST_SYSTEM_WINDOW+33;
/**
+ * Window for displaying a handle used for resizing docked stacks. This window is owned
+ * by the system process.
+ * @hide
+ */
+ public static final int TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW+34;
+
+ /**
* End of types of system windows.
*/
public static final int LAST_SYSTEM_WINDOW = 2999;
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 6883db266e99..68855ff72531 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -385,17 +385,19 @@ public abstract class AbsSeekBar extends ProgressBar {
}
@Override
- void onProgressRefresh(float scale, boolean fromUser, int progress) {
- super.onProgressRefresh(scale, fromUser, progress);
+ void onVisualProgressChanged(int id, float scale) {
+ super.onVisualProgressChanged(id, scale);
- final Drawable thumb = mThumb;
- if (thumb != null) {
- setThumbPos(getWidth(), thumb, scale, Integer.MIN_VALUE);
+ if (id == R.id.progress) {
+ final Drawable thumb = mThumb;
+ if (thumb != null) {
+ setThumbPos(getWidth(), thumb, scale, Integer.MIN_VALUE);
- // Since we draw translated, the drawable's bounds that it signals
- // for invalidation won't be the actual bounds we want invalidated,
- // so just invalidate this whole view.
- invalidate();
+ // Since we draw translated, the drawable's bounds that it signals
+ // for invalidation won't be the actual bounds we want invalidated,
+ // so just invalidate this whole view.
+ invalidate();
+ }
}
}
@@ -709,8 +711,7 @@ public abstract class AbsSeekBar extends ProgressBar {
case KeyEvent.KEYCODE_DPAD_RIGHT:
increment = isLayoutRtl() ? -increment : increment;
- // Let progress bar handle clamping values.
- if (setProgress(getProgress() + increment, true)) {
+ if (setProgressInternal(getProgress() + increment, true, true)) {
onKeyChange();
return true;
}
@@ -764,7 +765,7 @@ public abstract class AbsSeekBar extends ProgressBar {
}
float value = arguments.getFloat(
AccessibilityNodeInfo.ACTION_ARGUMENT_PROGRESS_VALUE);
- return setProgress((int) value, true);
+ return setProgressInternal((int) value, true, true);
}
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
@@ -777,7 +778,7 @@ public abstract class AbsSeekBar extends ProgressBar {
}
// Let progress bar handle clamping values.
- if (setProgress(getProgress() + increment, true)) {
+ if (setProgressInternal(getProgress() + increment, true, true)) {
onKeyChange();
return true;
}
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index fce3754749ef..04c68ae600ea 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -16,10 +16,13 @@
package android.widget;
+import android.animation.ObjectAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.PorterDuff;
+import android.util.FloatProperty;
+import android.util.IntProperty;
import android.view.accessibility.AccessibilityNodeInfo;
import com.android.internal.R;
@@ -28,7 +31,6 @@ import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.Shader;
@@ -38,7 +40,6 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.StateListDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.graphics.drawable.shapes.Shape;
@@ -57,6 +58,7 @@ import android.view.accessibility.AccessibilityManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;
@@ -198,9 +200,17 @@ import java.util.ArrayList;
*/
@RemoteView
public class ProgressBar extends View {
+
private static final int MAX_LEVEL = 10000;
private static final int TIMEOUT_SEND_ACCESSIBILITY_EVENT = 200;
+ /** Interpolator used for smooth progress animations. */
+ private static final DecelerateInterpolator PROGRESS_ANIM_INTERPOLATOR =
+ new DecelerateInterpolator();
+
+ /** Duration of smooth progress animations. */
+ private static final int PROGRESS_ANIM_DURATION = 80;
+
int mMinWidth;
int mMaxWidth;
int mMinHeight;
@@ -234,6 +244,9 @@ public class ProgressBar extends View {
private boolean mAttached;
private boolean mRefreshIsPosted;
+ /** Value used to track progress animation, in the range [0...1]. */
+ private float mVisualProgress;
+
boolean mMirrorForRtl = false;
private final ArrayList<RefreshData> mRefreshData = new ArrayList<RefreshData>();
@@ -814,8 +827,8 @@ public class ProgressBar extends View {
updateDrawableBounds(getWidth(), getHeight());
updateDrawableState();
- doRefreshProgress(R.id.progress, mProgress, false, false);
- doRefreshProgress(R.id.secondaryProgress, mSecondaryProgress, false, false);
+ doRefreshProgress(R.id.progress, mProgress, false, false, false);
+ doRefreshProgress(R.id.secondaryProgress, mSecondaryProgress, false, false, false);
}
}
@@ -1246,7 +1259,7 @@ public class ProgressBar extends View {
final int count = mRefreshData.size();
for (int i = 0; i < count; i++) {
final RefreshData rd = mRefreshData.get(i);
- doRefreshProgress(rd.id, rd.progress, rd.fromUser, true);
+ doRefreshProgress(rd.id, rd.progress, rd.fromUser, true, rd.animate);
rd.recycle();
}
mRefreshData.clear();
@@ -1263,8 +1276,9 @@ public class ProgressBar extends View {
public int id;
public int progress;
public boolean fromUser;
+ public boolean animate;
- public static RefreshData obtain(int id, int progress, boolean fromUser) {
+ public static RefreshData obtain(int id, int progress, boolean fromUser, boolean animate) {
RefreshData rd = sPool.acquire();
if (rd == null) {
rd = new RefreshData();
@@ -1272,6 +1286,7 @@ public class ProgressBar extends View {
rd.id = id;
rd.progress = progress;
rd.fromUser = fromUser;
+ rd.animate = animate;
return rd;
}
@@ -1281,26 +1296,21 @@ public class ProgressBar extends View {
}
private synchronized void doRefreshProgress(int id, int progress, boolean fromUser,
- boolean callBackToApp) {
- float scale = mMax > 0 ? (float) progress / (float) mMax : 0;
- final Drawable d = mCurrentDrawable;
- if (d != null) {
- Drawable progressDrawable = null;
-
- if (d instanceof LayerDrawable) {
- progressDrawable = ((LayerDrawable) d).findDrawableByLayerId(id);
- if (progressDrawable != null && canResolveLayoutDirection()) {
- progressDrawable.setLayoutDirection(getLayoutDirection());
- }
- }
-
- final int level = (int) (scale * MAX_LEVEL);
- (progressDrawable != null ? progressDrawable : d).setLevel(level);
+ boolean callBackToApp, boolean animate) {
+ final float scale = mMax > 0 ? progress / (float) mMax : 0;
+ final boolean isPrimary = id == R.id.progress;
+
+ if (isPrimary && animate) {
+ final ObjectAnimator animator = ObjectAnimator.ofFloat(this, VISUAL_PROGRESS, scale);
+ animator.setAutoCancel(true);
+ animator.setDuration(PROGRESS_ANIM_DURATION);
+ animator.setInterpolator(PROGRESS_ANIM_INTERPOLATOR);
+ animator.start();
} else {
- invalidate();
+ setVisualProgress(id, scale);
}
- if (callBackToApp && id == R.id.progress) {
+ if (isPrimary && callBackToApp) {
onProgressRefresh(scale, fromUser, progress);
}
}
@@ -1311,15 +1321,51 @@ public class ProgressBar extends View {
}
}
- private synchronized void refreshProgress(int id, int progress, boolean fromUser) {
+ /**
+ * Sets the visual state of a progress indicator.
+ *
+ * @param id the identifier of the progress indicator
+ * @param progress the visual progress in the range [0...1]
+ */
+ private void setVisualProgress(int id, float progress) {
+ mVisualProgress = progress;
+
+ Drawable d = mCurrentDrawable;
+
+ if (d instanceof LayerDrawable) {
+ d = ((LayerDrawable) d).findDrawableByLayerId(id);
+ }
+
+ if (d != null) {
+ final int level = (int) (progress * MAX_LEVEL);
+ d.setLevel(level);
+ } else {
+ invalidate();
+ }
+
+ onVisualProgressChanged(id, progress);
+ }
+
+ /**
+ * Called when the visual state of a progress indicator changes.
+ *
+ * @param id the identifier of the progress indicator
+ * @param progress the visual progress in the range [0...1]
+ */
+ void onVisualProgressChanged(int id, float progress) {
+ // Stub method.
+ }
+
+ private synchronized void refreshProgress(int id, int progress, boolean fromUser,
+ boolean animate) {
if (mUiThreadId == Thread.currentThread().getId()) {
- doRefreshProgress(id, progress, fromUser, true);
+ doRefreshProgress(id, progress, fromUser, true, animate);
} else {
if (mRefreshProgressRunnable == null) {
mRefreshProgressRunnable = new RefreshProgressRunnable();
}
- final RefreshData rd = RefreshData.obtain(id, progress, fromUser);
+ final RefreshData rd = RefreshData.obtain(id, progress, fromUser, animate);
mRefreshData.add(rd);
if (mAttached && !mRefreshIsPosted) {
post(mRefreshProgressRunnable);
@@ -1329,8 +1375,8 @@ public class ProgressBar extends View {
}
/**
- * <p>Set the current progress to the specified value. Does not do anything
- * if the progress bar is in indeterminate mode.</p>
+ * Sets the current progress to the specified value. Does not do anything
+ * if the progress bar is in indeterminate mode.
*
* @param progress the new progress, between 0 and {@link #getMax()}
*
@@ -1341,11 +1387,26 @@ public class ProgressBar extends View {
*/
@android.view.RemotableViewMethod
public synchronized void setProgress(int progress) {
- setProgress(progress, false);
+ setProgressInternal(progress, false, false);
+ }
+
+ /**
+ * Sets the current progress to the specified value, optionally animating
+ * between the current and target values.
+ * <p>
+ * Animation does not affect the result of {@link #getProgress()}, which
+ * will return the target value immediately after this method is called.
+ *
+ * @param progress the new progress value, between 0 and {@link #getMax()}
+ * @param animate {@code true} to animate between the current and target
+ * values or {@code false} to not animate
+ */
+ public void setProgress(int progress, boolean animate) {
+ setProgressInternal(progress, false, animate);
}
@android.view.RemotableViewMethod
- synchronized boolean setProgress(int progress, boolean fromUser) {
+ synchronized boolean setProgressInternal(int progress, boolean fromUser, boolean animate) {
if (mIndeterminate) {
// Not applicable.
return false;
@@ -1359,7 +1420,7 @@ public class ProgressBar extends View {
}
mProgress = progress;
- refreshProgress(R.id.progress, mProgress, fromUser);
+ refreshProgress(R.id.progress, mProgress, fromUser, animate);
return true;
}
@@ -1391,7 +1452,7 @@ public class ProgressBar extends View {
if (secondaryProgress != mSecondaryProgress) {
mSecondaryProgress = secondaryProgress;
- refreshProgress(R.id.secondaryProgress, mSecondaryProgress, false);
+ refreshProgress(R.id.secondaryProgress, mSecondaryProgress, false, false);
}
}
@@ -1464,7 +1525,7 @@ public class ProgressBar extends View {
if (mProgress > max) {
mProgress = max;
}
- refreshProgress(R.id.progress, mProgress, false);
+ refreshProgress(R.id.progress, mProgress, false, false);
}
}
@@ -1847,7 +1908,7 @@ public class ProgressBar extends View {
final int count = mRefreshData.size();
for (int i = 0; i < count; i++) {
final RefreshData rd = mRefreshData.get(i);
- doRefreshProgress(rd.id, rd.progress, rd.fromUser, true);
+ doRefreshProgress(rd.id, rd.progress, rd.fromUser, true, rd.animate);
rd.recycle();
}
mRefreshData.clear();
@@ -1956,4 +2017,23 @@ public class ProgressBar extends View {
boolean mHasSecondaryProgressTint;
boolean mHasSecondaryProgressTintMode;
}
+
+ /**
+ * Property wrapper around the visual state of the {@code progress} functionality
+ * handled by the {@link ProgressBar#setProgress(int, boolean)} method. This does
+ * not correspond directly to the actual progress -- only the visual state.
+ */
+ private final FloatProperty<ProgressBar> VISUAL_PROGRESS =
+ new FloatProperty<ProgressBar>("visual_progress") {
+ @Override
+ public void setValue(ProgressBar object, float value) {
+ object.setVisualProgress(R.id.progress, value);
+ object.mVisualProgress = value;
+ }
+
+ @Override
+ public Float get(ProgressBar object) {
+ return object.mVisualProgress;
+ }
+ };
}
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 6f3a711c8aff..434516da1346 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -1387,7 +1387,7 @@ public class Switch extends CompoundButton {
mTrackDrawable.jumpToCurrentState();
}
- if (mPositionAnimator != null && mPositionAnimator.isRunning()) {
+ if (mPositionAnimator != null && mPositionAnimator.isStarted()) {
mPositionAnimator.end();
mPositionAnimator = null;
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 6ccdd08498ce..e39bf607e53e 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -8044,6 +8044,10 @@ public final class BatteryStatsImpl extends BatteryStats {
* wakelocks. If the screen is on, we just assign the actual cpu time an app used.
*/
public void updateCpuTimeLocked() {
+ if (mPowerProfile == null) {
+ return;
+ }
+
if (DEBUG_ENERGY_CPU) {
Slog.d(TAG, "!Cpu updating!");
}
@@ -8131,14 +8135,19 @@ public final class BatteryStatsImpl extends BatteryStats {
// Add the cpu speeds to this UID. These are used as a ratio
// for computing the power this UID used.
- if (u.mCpuClusterSpeed == null) {
- u.mCpuClusterSpeed = new LongSamplingCounter[clusterSpeeds.length][];
+ final int numClusters = mPowerProfile.getNumCpuClusters();
+ if (u.mCpuClusterSpeed == null || u.mCpuClusterSpeed.length !=
+ numClusters) {
+ u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
}
for (int cluster = 0; cluster < clusterSpeeds.length; cluster++) {
- if (u.mCpuClusterSpeed[cluster] == null) {
+ final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(
+ cluster);
+ if (u.mCpuClusterSpeed[cluster] == null || speedsInCluster !=
+ u.mCpuClusterSpeed[cluster].length) {
u.mCpuClusterSpeed[cluster] =
- new LongSamplingCounter[clusterSpeeds[cluster].length];
+ new LongSamplingCounter[speedsInCluster];
}
final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeed[cluster];
diff --git a/core/java/com/android/internal/os/InstallerConnection.java b/core/java/com/android/internal/os/InstallerConnection.java
index dcc6a5e8cb33..db2b41f52b8c 100644
--- a/core/java/com/android/internal/os/InstallerConnection.java
+++ b/core/java/com/android/internal/os/InstallerConnection.java
@@ -92,14 +92,14 @@ public class InstallerConnection {
}
public int dexopt(String apkPath, int uid, boolean isPublic,
- String instructionSet, int dexoptNeeded) {
+ String instructionSet, int dexoptNeeded, boolean bootComplete) {
return dexopt(apkPath, uid, isPublic, "*", instructionSet, dexoptNeeded,
- false, false, null);
+ false, false, null, bootComplete);
}
public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName,
String instructionSet, int dexoptNeeded, boolean vmSafeMode,
- boolean debuggable, String outputPath) {
+ boolean debuggable, String outputPath, boolean bootComplete) {
StringBuilder builder = new StringBuilder("dexopt");
builder.append(' ');
builder.append(apkPath);
@@ -116,6 +116,7 @@ public class InstallerConnection {
builder.append(debuggable ? " 1" : " 0");
builder.append(' ');
builder.append(outputPath != null ? outputPath : "!");
+ builder.append(bootComplete ? " 1" : " 0");
return execute(builder.toString());
}
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index 34ae58a287b2..c558cf8d1ee7 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -121,22 +121,4 @@ public class WrapperInit {
Zygote.appendQuotedShellArgs(command, args);
Zygote.execShell(command.toString());
}
-
- /**
- * Executes a standalone application with a wrapper command.
- * This method never returns.
- *
- * @param invokeWith The wrapper command.
- * @param classPath The class path.
- * @param className The class name to invoke.
- * @param args Arguments for the main() method of the specified class.
- */
- public static void execStandalone(String invokeWith, String classPath, String className,
- String[] args) {
- StringBuilder command = new StringBuilder(invokeWith);
- command.append(" /system/bin/dalvikvm -classpath '").append(classPath);
- command.append("' ").append(className);
- Zygote.appendQuotedShellArgs(command, args);
- Zygote.execShell(command.toString());
- }
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index af730978fd13..eee8b0812ea0 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -487,7 +487,7 @@ public class ZygoteInit {
classPathElement, "*", instructionSet, false /* defer */);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
installer.dexopt(classPathElement, Process.SYSTEM_UID, false,
- instructionSet, dexoptNeeded);
+ instructionSet, dexoptNeeded, false /* boot complete */);
}
}
} catch (IOException ioe) {
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index 44df0ce89133..b44baa2b8422 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -35,7 +35,7 @@ import java.util.Arrays;
public class FloatingActionMode extends ActionMode {
private static final int MAX_HIDE_DURATION = 3000;
- private static final int MOVING_HIDE_DELAY = 300;
+ private static final int MOVING_HIDE_DELAY = 50;
private final Context mContext;
private final ActionMode.Callback2 mCallback;
@@ -181,7 +181,6 @@ public class FloatingActionMode extends ActionMode {
// Content rect is moving.
mOriginatingView.removeCallbacks(mMovingOff);
mFloatingToolbarVisibilityHelper.setMoving(true);
- mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
mOriginatingView.postDelayed(mMovingOff, MOVING_HIDE_DELAY);
mFloatingToolbar.setContentRect(mContentRectOnScreen);
@@ -189,9 +188,9 @@ public class FloatingActionMode extends ActionMode {
}
} else {
mFloatingToolbarVisibilityHelper.setOutOfBounds(true);
- mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
mContentRectOnScreen.setEmpty();
}
+ mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
mPreviousContentRectOnScreen.set(mContentRectOnScreen);
}
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 08d4e8616795..624c9e24e945 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -149,7 +149,7 @@ public final class MenuItemImpl implements MenuItem {
return true;
}
- if (mMenu.dispatchMenuItemSelected(mMenu.getRootMenu(), this)) {
+ if (mMenu.dispatchMenuItemSelected(mMenu, this)) {
return true;
}
diff --git a/core/java/com/android/internal/view/menu/SubMenuBuilder.java b/core/java/com/android/internal/view/menu/SubMenuBuilder.java
index 92acf8cda8f5..cf741bf5bb02 100644
--- a/core/java/com/android/internal/view/menu/SubMenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/SubMenuBuilder.java
@@ -73,7 +73,7 @@ public class SubMenuBuilder extends MenuBuilder implements SubMenu {
@Override
public MenuBuilder getRootMenu() {
- return mParentMenu;
+ return mParentMenu.getRootMenu();
}
@Override
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index ca6fe619f528..2a25db6b64c4 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -1488,10 +1488,9 @@ public final class FloatingToolbar {
private static AnimatorSet createEnterAnimation(View view) {
AnimatorSet animation = new AnimatorSet();
animation.playTogether(
- ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1).setDuration(200),
+ ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1).setDuration(150),
// Make sure that view.x is always fixed throughout the duration of this animation.
ObjectAnimator.ofFloat(view, View.X, view.getX(), view.getX()));
- animation.setStartDelay(50);
return animation;
}
@@ -1506,7 +1505,7 @@ public final class FloatingToolbar {
View view, int startDelay, Animator.AnimatorListener listener) {
AnimatorSet animation = new AnimatorSet();
animation.playTogether(
- ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0).setDuration(200));
+ ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0).setDuration(100));
animation.setStartDelay(startDelay);
animation.addListener(listener);
return animation;
diff --git a/core/java/com/android/server/LocalServices.java b/core/java/com/android/server/LocalServices.java
index 25dcb308b55a..9c632ea725a9 100644
--- a/core/java/com/android/server/LocalServices.java
+++ b/core/java/com/android/server/LocalServices.java
@@ -16,6 +16,8 @@
package com.android.server;
+import com.android.internal.annotations.VisibleForTesting;
+
import android.util.ArrayMap;
/**
@@ -57,4 +59,14 @@ public final class LocalServices {
sLocalServiceObjects.put(type, service);
}
}
+
+ /**
+ * Remove a service instance, must be only used in tests.
+ */
+ @VisibleForTesting
+ public static <T> void removeServiceForTest(Class<T> type) {
+ synchronized (sLocalServiceObjects) {
+ sLocalServiceObjects.remove(type);
+ }
+ }
}
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index e4bc80013b9c..ffc69a93f106 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -217,7 +217,7 @@ static void com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup(JNIE
/*
* JNI registration.
*/
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nativeFinishInit", "()V",
(void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
{ "nativeZygoteInit", "()V",
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index fbe3ececc348..e6c7c2bcf9d7 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -1348,7 +1348,7 @@ static jlong Bitmap_refPixelRef(JNIEnv* env, jobject, jlong bitmapHandle) {
///////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gBitmapMethods[] = {
+static const JNINativeMethod gBitmapMethods[] = {
{ "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;",
(void*)Bitmap_creator },
{ "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 20a54e538ea8..28bc7fe47dd2 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -542,7 +542,7 @@ jobject decodeBitmap(JNIEnv* env, void* data, size_t size) {
///////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nativeDecodeStream",
"(Ljava/io/InputStream;[BLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;",
(void*)nativeDecodeStream
@@ -569,7 +569,7 @@ static JNINativeMethod gMethods[] = {
},
};
-static JNINativeMethod gOptionsMethods[] = {
+static const JNINativeMethod gOptionsMethods[] = {
{ "requestCancel", "()V", (void*)nativeRequestCancel }
};
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 1bbbb08990ce..2df3a4641aeb 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -261,7 +261,7 @@ static void nativeClean(JNIEnv* env, jobject, jlong brdHandle) {
///////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gBitmapRegionDecoderMethods[] = {
+static const JNINativeMethod gBitmapRegionDecoderMethods[] = {
{ "nativeDecodeRegion",
"(JIIIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;",
(void*)nativeDecodeRegion},
diff --git a/core/jni/android/graphics/Camera.cpp b/core/jni/android/graphics/Camera.cpp
index 036ece1cec28..6fcf6892d490 100644
--- a/core/jni/android/graphics/Camera.cpp
+++ b/core/jni/android/graphics/Camera.cpp
@@ -115,7 +115,7 @@ static jfloat Camera_dotWithNormal(JNIEnv* env, jobject obj,
/*
* JNI registration.
*/
-static JNINativeMethod gCameraMethods[] = {
+static const JNINativeMethod gCameraMethods[] = {
/* name, signature, funcPtr */
{ "nativeConstructor", "()V", (void*)Camera_constructor },
diff --git a/core/jni/android/graphics/CanvasProperty.cpp b/core/jni/android/graphics/CanvasProperty.cpp
index deb4971a8a01..728bc1c3677e 100644
--- a/core/jni/android/graphics/CanvasProperty.cpp
+++ b/core/jni/android/graphics/CanvasProperty.cpp
@@ -39,7 +39,7 @@ static jlong createPaint(JNIEnv* env, jobject clazz, jlong paintPtr) {
// JNI Glue
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nCreateFloat", "(F)J", (void*) createFloat },
{ "nCreatePaint", "(J)J", (void*) createPaint },
};
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index d03bcf0fe3ac..83fd07382fe0 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -57,19 +57,19 @@ public:
}
};
-static JNINativeMethod colorfilter_methods[] = {
+static const JNINativeMethod colorfilter_methods[] = {
{"destroyFilter", "(J)V", (void*) SkColorFilterGlue::finalizer}
};
-static JNINativeMethod porterduff_methods[] = {
+static const JNINativeMethod porterduff_methods[] = {
{ "native_CreatePorterDuffFilter", "(II)J", (void*) SkColorFilterGlue::CreatePorterDuffFilter },
};
-static JNINativeMethod lighting_methods[] = {
+static const JNINativeMethod lighting_methods[] = {
{ "native_CreateLightingFilter", "(II)J", (void*) SkColorFilterGlue::CreateLightingFilter },
};
-static JNINativeMethod colormatrix_methods[] = {
+static const JNINativeMethod colormatrix_methods[] = {
{ "nativeColorMatrixFilter", "([F)J", (void*) SkColorFilterGlue::CreateColorMatrixFilter },
};
diff --git a/core/jni/android/graphics/DrawFilter.cpp b/core/jni/android/graphics/DrawFilter.cpp
index 90ef6c0745cd..c1dc0dd025b6 100644
--- a/core/jni/android/graphics/DrawFilter.cpp
+++ b/core/jni/android/graphics/DrawFilter.cpp
@@ -97,11 +97,11 @@ public:
}
};
-static JNINativeMethod drawfilter_methods[] = {
+static const JNINativeMethod drawfilter_methods[] = {
{"nativeDestructor", "(J)V", (void*) SkDrawFilterGlue::finalizer}
};
-static JNINativeMethod paintflags_methods[] = {
+static const JNINativeMethod paintflags_methods[] = {
{"nativeConstructor","(II)J", (void*) SkDrawFilterGlue::CreatePaintFlagsDF}
};
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 38db76b0b183..dac6d96eb7df 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -124,7 +124,7 @@ static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPt
///////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gFontFamilyMethods[] = {
+static const JNINativeMethod gFontFamilyMethods[] = {
{ "nCreateFamily", "(Ljava/lang/String;I)J", (void*)FontFamily_create },
{ "nUnrefFamily", "(J)V", (void*)FontFamily_unref },
{ "nAddFont", "(JLjava/lang/String;)Z", (void*)FontFamily_addFont },
diff --git a/core/jni/android/graphics/Interpolator.cpp b/core/jni/android/graphics/Interpolator.cpp
index 3593d1a4ab32..fa28359281db 100644
--- a/core/jni/android/graphics/Interpolator.cpp
+++ b/core/jni/android/graphics/Interpolator.cpp
@@ -71,7 +71,7 @@ static jint Interpolator_timeToValues(JNIEnv* env, jobject clazz, jlong interpHa
/*
* JNI registration.
*/
-static JNINativeMethod gInterpolatorMethods[] = {
+static const JNINativeMethod gInterpolatorMethods[] = {
{ "nativeConstructor", "(II)J", (void*)Interpolator_constructor },
{ "nativeDestructor", "(J)V", (void*)Interpolator_destructor },
{ "nativeReset", "(JII)V", (void*)Interpolator_reset },
diff --git a/core/jni/android/graphics/MaskFilter.cpp b/core/jni/android/graphics/MaskFilter.cpp
index d65864312196..2b4a1abbd673 100644
--- a/core/jni/android/graphics/MaskFilter.cpp
+++ b/core/jni/android/graphics/MaskFilter.cpp
@@ -61,19 +61,19 @@ public:
}
};
-static JNINativeMethod gMaskFilterMethods[] = {
+static const JNINativeMethod gMaskFilterMethods[] = {
{ "nativeDestructor", "(J)V", (void*)SkMaskFilterGlue::destructor }
};
-static JNINativeMethod gBlurMaskFilterMethods[] = {
+static const JNINativeMethod gBlurMaskFilterMethods[] = {
{ "nativeConstructor", "(FI)J", (void*)SkMaskFilterGlue::createBlur }
};
-static JNINativeMethod gEmbossMaskFilterMethods[] = {
+static const JNINativeMethod gEmbossMaskFilterMethods[] = {
{ "nativeConstructor", "([FFFF)J", (void*)SkMaskFilterGlue::createEmboss }
};
-static JNINativeMethod gTableMaskFilterMethods[] = {
+static const JNINativeMethod gTableMaskFilterMethods[] = {
{ "nativeNewTable", "([B)J", (void*)SkMaskFilterGlue::createTable },
{ "nativeNewClip", "(II)J", (void*)SkMaskFilterGlue::createClipTable },
{ "nativeNewGamma", "(F)J", (void*)SkMaskFilterGlue::createGammaTable }
diff --git a/core/jni/android/graphics/Matrix.cpp b/core/jni/android/graphics/Matrix.cpp
index 101e2ba603e6..b0f3bb4b965a 100644
--- a/core/jni/android/graphics/Matrix.cpp
+++ b/core/jni/android/graphics/Matrix.cpp
@@ -302,7 +302,7 @@ public:
}
};
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"finalizer", "(J)V", (void*) SkMatrixGlue::finalizer},
{"native_create","(J)J", (void*) SkMatrixGlue::create},
diff --git a/core/jni/android/graphics/Movie.cpp b/core/jni/android/graphics/Movie.cpp
index d67ed10e9ef1..498c5902e5fd 100644
--- a/core/jni/android/graphics/Movie.cpp
+++ b/core/jni/android/graphics/Movie.cpp
@@ -135,7 +135,7 @@ static void movie_destructor(JNIEnv* env, jobject, jlong movieHandle) {
//////////////////////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "width", "()I", (void*)movie_width },
{ "height", "()I", (void*)movie_height },
{ "isOpaque", "()Z", (void*)movie_isOpaque },
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index 1c282623f455..3ccbb35cc960 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -108,7 +108,7 @@ public:
/////////////////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gNinePatchMethods[] = {
+static const JNINativeMethod gNinePatchMethods[] = {
{ "isNinePatchChunk", "([B)Z", (void*) SkNinePatchGlue::isNinePatchChunk },
{ "validateNinePatchChunk", "([B)J",
(void*) SkNinePatchGlue::validateNinePatchChunk },
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 988d13aa7ea8..520dc4fdb496 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -1095,7 +1095,7 @@ public:
};
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"finalizer", "(J)V", (void*) PaintGlue::finalizer},
{"native_init","()J", (void*) PaintGlue::init},
{"native_initWithPaint","(J)J", (void*) PaintGlue::initWithPaint},
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index dbd7c89805ab..2998c99a273e 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -475,7 +475,7 @@ public:
}
};
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"finalizer", "(J)V", (void*) SkPathGlue::finalizer},
{"init1","()J", (void*) SkPathGlue::init1},
{"init2","(J)J", (void*) SkPathGlue::init2},
diff --git a/core/jni/android/graphics/PathEffect.cpp b/core/jni/android/graphics/PathEffect.cpp
index 265944e216e2..b289b21a3d8b 100644
--- a/core/jni/android/graphics/PathEffect.cpp
+++ b/core/jni/android/graphics/PathEffect.cpp
@@ -69,31 +69,31 @@ public:
////////////////////////////////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gPathEffectMethods[] = {
+static const JNINativeMethod gPathEffectMethods[] = {
{ "nativeDestructor", "(J)V", (void*)SkPathEffectGlue::destructor }
};
-static JNINativeMethod gComposePathEffectMethods[] = {
+static const JNINativeMethod gComposePathEffectMethods[] = {
{ "nativeCreate", "(JJ)J", (void*)SkPathEffectGlue::Compose_constructor }
};
-static JNINativeMethod gSumPathEffectMethods[] = {
+static const JNINativeMethod gSumPathEffectMethods[] = {
{ "nativeCreate", "(JJ)J", (void*)SkPathEffectGlue::Sum_constructor }
};
-static JNINativeMethod gDashPathEffectMethods[] = {
+static const JNINativeMethod gDashPathEffectMethods[] = {
{ "nativeCreate", "([FF)J", (void*)SkPathEffectGlue::Dash_constructor }
};
-static JNINativeMethod gPathDashPathEffectMethods[] = {
+static const JNINativeMethod gPathDashPathEffectMethods[] = {
{ "nativeCreate", "(JFFI)J", (void*)SkPathEffectGlue::OneD_constructor }
};
-static JNINativeMethod gCornerPathEffectMethods[] = {
+static const JNINativeMethod gCornerPathEffectMethods[] = {
{ "nativeCreate", "(F)J", (void*)SkPathEffectGlue::Corner_constructor }
};
-static JNINativeMethod gDiscretePathEffectMethods[] = {
+static const JNINativeMethod gDiscretePathEffectMethods[] = {
{ "nativeCreate", "(FF)J", (void*)SkPathEffectGlue::Discrete_constructor }
};
diff --git a/core/jni/android/graphics/PathMeasure.cpp b/core/jni/android/graphics/PathMeasure.cpp
index fec5d9db3a6a..70e528d4be6f 100644
--- a/core/jni/android/graphics/PathMeasure.cpp
+++ b/core/jni/android/graphics/PathMeasure.cpp
@@ -143,7 +143,7 @@ public:
}
};
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"native_create", "(JZ)J", (void*) SkPathMeasureGlue::create },
{"native_setPath", "(JJZ)V", (void*) SkPathMeasureGlue::setPath },
{"native_getLength", "(J)F", (void*) SkPathMeasureGlue::getLength },
diff --git a/core/jni/android/graphics/PorterDuff.cpp b/core/jni/android/graphics/PorterDuff.cpp
index fed90a5d2f83..dfc3c9d7ed13 100644
--- a/core/jni/android/graphics/PorterDuff.cpp
+++ b/core/jni/android/graphics/PorterDuff.cpp
@@ -58,7 +58,7 @@ public:
};
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"nativeCreateXfermode","(I)J", (void*) SkPorterDuffGlue::CreateXfermode},
};
diff --git a/core/jni/android/graphics/Rasterizer.cpp b/core/jni/android/graphics/Rasterizer.cpp
index cfc23ac8ecb3..a106ecfeb65f 100644
--- a/core/jni/android/graphics/Rasterizer.cpp
+++ b/core/jni/android/graphics/Rasterizer.cpp
@@ -61,7 +61,7 @@ public:
}
};
-static JNINativeMethod gRasterizerMethods[] = {
+static const JNINativeMethod gRasterizerMethods[] = {
{"finalizer", "(J)V", (void*) SkRasterizerGlue::finalizer}
};
@@ -85,7 +85,7 @@ public:
}
};
-static JNINativeMethod gLayerRasterizerMethods[] = {
+static const JNINativeMethod gLayerRasterizerMethods[] = {
{ "nativeConstructor", "()J", (void*)SkLayerRasterizerGlue::create },
{ "nativeAddLayer", "(JJFF)V", (void*)SkLayerRasterizerGlue::addLayer }
};
diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp
index e99bdfcc63fa..bcd0b60308bb 100644
--- a/core/jni/android/graphics/Region.cpp
+++ b/core/jni/android/graphics/Region.cpp
@@ -306,13 +306,13 @@ static jboolean RegionIter_next(JNIEnv* env, jobject, jlong pairHandle, jobject
////////////////////////////////////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gRegionIterMethods[] = {
+static const JNINativeMethod gRegionIterMethods[] = {
{ "nativeConstructor", "(J)J", (void*)RegionIter_constructor },
{ "nativeDestructor", "(J)V", (void*)RegionIter_destructor },
{ "nativeNext", "(JLandroid/graphics/Rect;)Z", (void*)RegionIter_next }
};
-static JNINativeMethod gRegionMethods[] = {
+static const JNINativeMethod gRegionMethods[] = {
// these are static methods
{ "nativeConstructor", "()J", (void*)Region_constructor },
{ "nativeDestructor", "(J)V", (void*)Region_destructor },
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 49c377e9c97f..799ed835197d 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -240,36 +240,36 @@ static jlong ComposeShader_create2(JNIEnv* env, jobject o,
///////////////////////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gColorMethods[] = {
+static const JNINativeMethod gColorMethods[] = {
{ "nativeRGBToHSV", "(III[F)V", (void*)Color_RGBToHSV },
{ "nativeHSVToColor", "(I[F)I", (void*)Color_HSVToColor }
};
-static JNINativeMethod gShaderMethods[] = {
+static const JNINativeMethod gShaderMethods[] = {
{ "nativeDestructor", "(J)V", (void*)Shader_destructor },
{ "nativeSetLocalMatrix", "(JJ)J", (void*)Shader_setLocalMatrix }
};
-static JNINativeMethod gBitmapShaderMethods[] = {
+static const JNINativeMethod gBitmapShaderMethods[] = {
{ "nativeCreate", "(Landroid/graphics/Bitmap;II)J", (void*)BitmapShader_constructor },
};
-static JNINativeMethod gLinearGradientMethods[] = {
+static const JNINativeMethod gLinearGradientMethods[] = {
{ "nativeCreate1", "(FFFF[I[FI)J", (void*)LinearGradient_create1 },
{ "nativeCreate2", "(FFFFIII)J", (void*)LinearGradient_create2 },
};
-static JNINativeMethod gRadialGradientMethods[] = {
+static const JNINativeMethod gRadialGradientMethods[] = {
{ "nativeCreate1", "(FFF[I[FI)J", (void*)RadialGradient_create1 },
{ "nativeCreate2", "(FFFIII)J", (void*)RadialGradient_create2 },
};
-static JNINativeMethod gSweepGradientMethods[] = {
+static const JNINativeMethod gSweepGradientMethods[] = {
{ "nativeCreate1", "(FF[I[F)J", (void*)SweepGradient_create1 },
{ "nativeCreate2", "(FFII)J", (void*)SweepGradient_create2 },
};
-static JNINativeMethod gComposeShaderMethods[] = {
+static const JNINativeMethod gComposeShaderMethods[] = {
{ "nativeCreate1", "(JJJ)J", (void*)ComposeShader_create1 },
{ "nativeCreate2", "(JJI)J", (void*)ComposeShader_create2 },
};
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 80de52611735..61dc6e425ddf 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -359,7 +359,7 @@ static jboolean SurfaceTexture_isReleased(JNIEnv* env, jobject thiz)
// ----------------------------------------------------------------------------
-static JNINativeMethod gSurfaceTextureMethods[] = {
+static const JNINativeMethod gSurfaceTextureMethods[] = {
{"nativeClassInit", "()V", (void*)SurfaceTexture_classInit },
{"nativeInit", "(ZIZLjava/lang/ref/WeakReference;)V", (void*)SurfaceTexture_init },
{"nativeFinalize", "()V", (void*)SurfaceTexture_finalize },
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index e0cbc9efbd18..e97b768dd0cc 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -68,7 +68,7 @@ static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) {
///////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gTypefaceMethods[] = {
+static const JNINativeMethod gTypefaceMethods[] = {
{ "nativeCreateFromTypeface", "(JI)J", (void*)Typeface_createFromTypeface },
{ "nativeCreateWeightAlias", "(JI)J", (void*)Typeface_createWeightAlias },
{ "nativeUnref", "(J)V", (void*)Typeface_unref },
diff --git a/core/jni/android/graphics/Xfermode.cpp b/core/jni/android/graphics/Xfermode.cpp
index 4a424aeb09a3..7441acc95cea 100644
--- a/core/jni/android/graphics/Xfermode.cpp
+++ b/core/jni/android/graphics/Xfermode.cpp
@@ -47,15 +47,15 @@ public:
///////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gXfermodeMethods[] = {
+static const JNINativeMethod gXfermodeMethods[] = {
{"finalizer", "(J)V", (void*) SkXfermodeGlue::finalizer}
};
-static JNINativeMethod gAvoidMethods[] = {
+static const JNINativeMethod gAvoidMethods[] = {
{"nativeCreate", "(III)J", (void*) SkXfermodeGlue::avoid_create}
};
-static JNINativeMethod gPixelXorMethods[] = {
+static const JNINativeMethod gPixelXorMethods[] = {
{"nativeCreate", "(I)J", (void*) SkXfermodeGlue::pixelxor_create}
};
diff --git a/core/jni/android/graphics/YuvToJpegEncoder.cpp b/core/jni/android/graphics/YuvToJpegEncoder.cpp
index 5eede2aee286..7d0c39cca018 100644
--- a/core/jni/android/graphics/YuvToJpegEncoder.cpp
+++ b/core/jni/android/graphics/YuvToJpegEncoder.cpp
@@ -243,7 +243,7 @@ static jboolean YuvImage_compressToJpeg(JNIEnv* env, jobject, jbyteArray inYuv,
}
///////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gYuvImageMethods[] = {
+static const JNINativeMethod gYuvImageMethods[] = {
{ "nativeCompressToJpeg", "([BIII[I[IILjava/io/OutputStream;[B)Z",
(void*)YuvImage_compressToJpeg }
};
diff --git a/core/jni/android/graphics/pdf/PdfDocument.cpp b/core/jni/android/graphics/pdf/PdfDocument.cpp
index a91b15b7fa41..7a13fe427b00 100644
--- a/core/jni/android/graphics/pdf/PdfDocument.cpp
+++ b/core/jni/android/graphics/pdf/PdfDocument.cpp
@@ -150,7 +150,7 @@ static void nativeClose(JNIEnv* env, jobject thiz, jlong documentPtr) {
document->close();
}
-static JNINativeMethod gPdfDocument_Methods[] = {
+static const JNINativeMethod gPdfDocument_Methods[] = {
{"nativeCreateDocument", "()J", (void*) nativeCreateDocument},
{"nativeStartPage", "(JIIIIII)J", (void*) nativeStartPage},
{"nativeFinishPage", "(J)V", (void*) nativeFinishPage},
diff --git a/core/jni/android/graphics/pdf/PdfEditor.cpp b/core/jni/android/graphics/pdf/PdfEditor.cpp
index 52b69e02e894..0177635f26b0 100644
--- a/core/jni/android/graphics/pdf/PdfEditor.cpp
+++ b/core/jni/android/graphics/pdf/PdfEditor.cpp
@@ -343,7 +343,7 @@ static void nativeSetPageCropBox(JNIEnv* env, jclass thiz, jlong documentPtr, ji
nativeSetPageBox(env, thiz, documentPtr, pageIndex, PAGE_BOX_CROP, mediaBox);
}
-static JNINativeMethod gPdfEditor_Methods[] = {
+static const JNINativeMethod gPdfEditor_Methods[] = {
{"nativeOpen", "(IJ)J", (void*) nativeOpen},
{"nativeClose", "(J)V", (void*) nativeClose},
{"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount},
diff --git a/core/jni/android/graphics/pdf/PdfRenderer.cpp b/core/jni/android/graphics/pdf/PdfRenderer.cpp
index 006eef847a12..6ddfacf442e8 100644
--- a/core/jni/android/graphics/pdf/PdfRenderer.cpp
+++ b/core/jni/android/graphics/pdf/PdfRenderer.cpp
@@ -283,7 +283,7 @@ static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong
skBitmap.notifyPixelsChanged();
}
-static JNINativeMethod gPdfRenderer_Methods[] = {
+static const JNINativeMethod gPdfRenderer_Methods[] = {
{"nativeCreate", "(IJ)J", (void*) nativeCreate},
{"nativeClose", "(J)V", (void*) nativeClose},
{"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount},
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index 40029bbe0aee..e045f5f36ada 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -1087,18 +1087,18 @@ static jint etc1_getHeight(JNIEnv *env, jclass clazz,
* JNI registration
*/
-static JNINativeMethod gMatrixMethods[] = {
+static const JNINativeMethod gMatrixMethods[] = {
{ "multiplyMM", "([FI[FI[FI)V", (void*)util_multiplyMM },
{ "multiplyMV", "([FI[FI[FI)V", (void*)util_multiplyMV },
};
-static JNINativeMethod gVisibilityMethods[] = {
+static const JNINativeMethod gVisibilityMethods[] = {
{ "computeBoundingSphere", "([FII[FI)V", (void*)util_computeBoundingSphere },
{ "frustumCullSpheres", "([FI[FII[III)I", (void*)util_frustumCullSpheres },
{ "visibilityTest", "([FI[FI[CII)I", (void*)util_visibilityTest },
};
-static JNINativeMethod gUtilsMethods[] = {
+static const JNINativeMethod gUtilsMethods[] = {
{ "native_getInternalFormat", "(Landroid/graphics/Bitmap;)I", (void*) util_getInternalFormat },
{ "native_getType", "(Landroid/graphics/Bitmap;)I", (void*) util_getType },
{ "native_texImage2D", "(IIILandroid/graphics/Bitmap;II)I", (void*)util_texImage2D },
@@ -1106,7 +1106,7 @@ static JNINativeMethod gUtilsMethods[] = {
{ "setTracingLevel", "(I)V", (void*)setTracingLevel },
};
-static JNINativeMethod gEtc1Methods[] = {
+static const JNINativeMethod gEtc1Methods[] = {
{ "encodeBlock", "(Ljava/nio/Buffer;ILjava/nio/Buffer;)V", (void*) etc1_encodeBlock },
{ "decodeBlock", "(Ljava/nio/Buffer;Ljava/nio/Buffer;)V", (void*) etc1_decodeBlock },
{ "getEncodedDataSize", "(II)I", (void*) etc1_getEncodedDataSize },
@@ -1120,11 +1120,11 @@ static JNINativeMethod gEtc1Methods[] = {
typedef struct _ClassRegistrationInfo {
const char* classPath;
- JNINativeMethod* methods;
+ const JNINativeMethod* methods;
size_t methodCount;
} ClassRegistrationInfo;
-static ClassRegistrationInfo gClasses[] = {
+static const ClassRegistrationInfo gClasses[] = {
{"android/opengl/Matrix", gMatrixMethods, NELEM(gMatrixMethods)},
{"android/opengl/Visibility", gVisibilityMethods, NELEM(gVisibilityMethods)},
{"android/opengl/GLUtils", gUtilsMethods, NELEM(gUtilsMethods)},
@@ -1136,7 +1136,7 @@ int register_android_opengl_classes(JNIEnv* env)
nativeClassInitBuffer(env);
int result = 0;
for (int i = 0; i < NELEM(gClasses); i++) {
- ClassRegistrationInfo* cri = &gClasses[i];
+ const ClassRegistrationInfo* cri = &gClasses[i];
result = RegisterMethodsOrDie(env, cri->classPath, cri->methods, cri->methodCount);
}
return result;
diff --git a/core/jni/android_animation_PropertyValuesHolder.cpp b/core/jni/android_animation_PropertyValuesHolder.cpp
index d11774189901..6065c2473978 100644
--- a/core/jni/android_animation_PropertyValuesHolder.cpp
+++ b/core/jni/android_animation_PropertyValuesHolder.cpp
@@ -139,7 +139,7 @@ static void android_animation_PropertyValuesHolder_callMultipleIntMethod(
env->ReleaseIntArrayElements(arg, intValues, JNI_ABORT);
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nGetIntMethod", "(Ljava/lang/Class;Ljava/lang/String;)J",
(void*)android_animation_PropertyValuesHolder_getIntMethod },
{ "nGetFloatMethod", "(Ljava/lang/Class;Ljava/lang/String;)J",
diff --git a/core/jni/android_content_res_ObbScanner.cpp b/core/jni/android_content_res_ObbScanner.cpp
index ef17db6b0fdf..36d78cf3aca0 100644
--- a/core/jni/android_content_res_ObbScanner.cpp
+++ b/core/jni/android_content_res_ObbScanner.cpp
@@ -76,7 +76,7 @@ static void android_content_res_ObbScanner_getObbInfo(JNIEnv* env, jobject clazz
/*
* JNI registration.
*/
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "getObbInfo_native", "(Ljava/lang/String;Landroid/content/res/ObbInfo;)V",
(void*) android_content_res_ObbScanner_getObbInfo },
diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp
index 580ac02789c5..bb09d001037d 100644
--- a/core/jni/android_database_CursorWindow.cpp
+++ b/core/jni/android_database_CursorWindow.cpp
@@ -477,7 +477,7 @@ static jboolean nativePutNull(JNIEnv* env, jclass clazz, jlong windowPtr,
return true;
}
-static JNINativeMethod sMethods[] =
+static const JNINativeMethod sMethods[] =
{
/* name, signature, funcPtr */
{ "nativeCreate", "(Ljava/lang/String;I)J",
diff --git a/core/jni/android_database_SQLiteConnection.cpp b/core/jni/android_database_SQLiteConnection.cpp
index 7a3cdf68fb18..bcc3bb09b69d 100644
--- a/core/jni/android_database_SQLiteConnection.cpp
+++ b/core/jni/android_database_SQLiteConnection.cpp
@@ -786,7 +786,7 @@ static void nativeResetCancel(JNIEnv* env, jobject clazz, jlong connectionPtr,
}
-static JNINativeMethod sMethods[] =
+static const JNINativeMethod sMethods[] =
{
/* name, signature, funcPtr */
{ "nativeOpen", "(Ljava/lang/String;ILjava/lang/String;ZZ)J",
diff --git a/core/jni/android_database_SQLiteDebug.cpp b/core/jni/android_database_SQLiteDebug.cpp
index 26e13cf10e71..4e4c36cbb7e1 100644
--- a/core/jni/android_database_SQLiteDebug.cpp
+++ b/core/jni/android_database_SQLiteDebug.cpp
@@ -58,7 +58,7 @@ static void nativeGetPagerStats(JNIEnv *env, jobject clazz, jobject statsObj)
* JNI registration.
*/
-static JNINativeMethod gMethods[] =
+static const JNINativeMethod gMethods[] =
{
{ "nativeGetPagerStats", "(Landroid/database/sqlite/SQLiteDebug$PagerStats;)V",
(void*) nativeGetPagerStats },
diff --git a/core/jni/android_database_SQLiteGlobal.cpp b/core/jni/android_database_SQLiteGlobal.cpp
index 0a1c9f75edec..03e2387f24bc 100644
--- a/core/jni/android_database_SQLiteGlobal.cpp
+++ b/core/jni/android_database_SQLiteGlobal.cpp
@@ -75,7 +75,7 @@ static jint nativeReleaseMemory(JNIEnv* env, jclass clazz) {
return sqlite3_release_memory(SOFT_HEAP_LIMIT);
}
-static JNINativeMethod sMethods[] =
+static const JNINativeMethod sMethods[] =
{
/* name, signature, funcPtr */
{ "nativeReleaseMemory", "()I", (void*)nativeReleaseMemory },
diff --git a/core/jni/android_ddm_DdmHandleNativeHeap.cpp b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
index ae96936ecba5..3e7a04efc536 100644
--- a/core/jni/android_ddm_DdmHandleNativeHeap.cpp
+++ b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
@@ -105,7 +105,7 @@ static jbyteArray DdmHandleNativeHeap_getLeakInfo(JNIEnv* env, jobject) {
return array;
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "getLeakInfo", "()[B", (void*) DdmHandleNativeHeap_getLeakInfo },
};
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 5ddf2350d278..32a877ae3398 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -746,7 +746,7 @@ static void freeTextLayoutCaches(JNIEnv* env, jobject) {
}; // namespace CanvasJNI
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"finalizer", "(J)V", (void*) CanvasJNI::finalizer},
{"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
{"native_setBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
diff --git a/core/jni/android_graphics_Picture.cpp b/core/jni/android_graphics_Picture.cpp
index fd42ddb9226e..03fcdef8fbfe 100644
--- a/core/jni/android_graphics_Picture.cpp
+++ b/core/jni/android_graphics_Picture.cpp
@@ -91,7 +91,7 @@ static void android_graphics_Picture_endRecording(JNIEnv* env, jobject, jlong pi
pict->endRecording();
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"nativeGetWidth", "(J)I", (void*) android_graphics_Picture_getWidth},
{"nativeGetHeight", "(J)I", (void*) android_graphics_Picture_getHeight},
{"nativeConstructor", "(J)J", (void*) android_graphics_Picture_newPicture},
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 4f44c262f261..414eba79f22d 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -949,7 +949,7 @@ static void android_hardware_Camera_enableFocusMoveCallback(JNIEnv *env, jobject
//-------------------------------------------------
-static JNINativeMethod camMethods[] = {
+static const JNINativeMethod camMethods[] = {
{ "getNumberOfCameras",
"()I",
(void *)android_hardware_Camera_getNumberOfCameras },
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 7d0afdcdd109..2e5cda069538 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -343,7 +343,7 @@ static jint nativeInjectSensorData(JNIEnv *env, jclass clazz, jlong eventQ, jint
}
//----------------------------------------------------------------------------
-static JNINativeMethod gSystemSensorManagerMethods[] = {
+static const JNINativeMethod gSystemSensorManagerMethods[] = {
{"nativeClassInit",
"()V",
(void*)nativeClassInit },
@@ -360,7 +360,7 @@ static JNINativeMethod gSystemSensorManagerMethods[] = {
(void*)nativeIsDataInjectionEnabled},
};
-static JNINativeMethod gBaseEventQueueMethods[] = {
+static const JNINativeMethod gBaseEventQueueMethods[] = {
{"nativeInitBaseEventQueue",
"(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;[FLjava/lang/String;ILjava/lang/String;)J",
(void*)nativeInitSensorEventQueue },
diff --git a/core/jni/android_hardware_SerialPort.cpp b/core/jni/android_hardware_SerialPort.cpp
index 2d2ff4d97cb9..393dc7b9f4fd 100644
--- a/core/jni/android_hardware_SerialPort.cpp
+++ b/core/jni/android_hardware_SerialPort.cpp
@@ -243,7 +243,7 @@ android_hardware_SerialPort_send_break(JNIEnv *env, jobject thiz)
tcsendbreak(fd, 0);
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{"native_open", "(Ljava/io/FileDescriptor;I)V",
(void *)android_hardware_SerialPort_open},
{"native_close", "()V", (void *)android_hardware_SerialPort_close},
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
index 1c4c9ecc8a09..048b3c71c2c3 100644
--- a/core/jni/android_hardware_SoundTrigger.cpp
+++ b/core/jni/android_hardware_SoundTrigger.cpp
@@ -768,14 +768,14 @@ android_hardware_SoundTrigger_stopRecognition(JNIEnv *env, jobject thiz,
return status;
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"listModules",
"(Ljava/util/ArrayList;)I",
(void *)android_hardware_SoundTrigger_listModules},
};
-static JNINativeMethod gModuleMethods[] = {
+static const JNINativeMethod gModuleMethods[] = {
{"native_setup",
"(Ljava/lang/Object;)V",
(void *)android_hardware_SoundTrigger_setup},
diff --git a/core/jni/android_hardware_UsbDevice.cpp b/core/jni/android_hardware_UsbDevice.cpp
index ef3b6463cd97..89d33e2ace1c 100644
--- a/core/jni/android_hardware_UsbDevice.cpp
+++ b/core/jni/android_hardware_UsbDevice.cpp
@@ -44,7 +44,7 @@ android_hardware_UsbDevice_get_device_name(JNIEnv *env, jobject clazz, jint id)
return result;
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
// static methods
{ "native_get_device_id", "(Ljava/lang/String;)I",
(void*)android_hardware_UsbDevice_get_device_id },
diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp
index e0cae6f3136f..1ba9fc58800c 100644
--- a/core/jni/android_hardware_UsbDeviceConnection.cpp
+++ b/core/jni/android_hardware_UsbDeviceConnection.cpp
@@ -246,7 +246,7 @@ android_hardware_UsbDeviceConnection_get_serial(JNIEnv *env, jobject thiz)
return result;
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{"native_open", "(Ljava/lang/String;Ljava/io/FileDescriptor;)Z",
(void *)android_hardware_UsbDeviceConnection_open},
{"native_close", "()V", (void *)android_hardware_UsbDeviceConnection_close},
diff --git a/core/jni/android_hardware_UsbRequest.cpp b/core/jni/android_hardware_UsbRequest.cpp
index ce99e15bffc0..399e7b16f073 100644
--- a/core/jni/android_hardware_UsbRequest.cpp
+++ b/core/jni/android_hardware_UsbRequest.cpp
@@ -190,7 +190,7 @@ android_hardware_UsbRequest_cancel(JNIEnv *env, jobject thiz)
return (usb_request_cancel(request) == 0);
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{"native_init", "(Landroid/hardware/usb/UsbDeviceConnection;IIII)Z",
(void *)android_hardware_UsbRequest_init},
{"native_close", "()V", (void *)android_hardware_UsbRequest_close},
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index fb2268911be3..793002734111 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -529,7 +529,7 @@ static void CameraMetadata_writeToParcel(JNIEnv *env, jobject thiz, jobject parc
//-------------------------------------------------
-static JNINativeMethod gCameraMetadataMethods[] = {
+static const JNINativeMethod gCameraMetadataMethods[] = {
// static methods
{ "nativeClassInit",
"()V",
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index 8b69bbd084b5..738a62ad5772 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -2280,7 +2280,7 @@ static void DngCreator_nativeWriteInputStream(JNIEnv* env, jobject thiz, jobject
} /*extern "C" */
-static JNINativeMethod gDngCreatorMethods[] = {
+static const JNINativeMethod gDngCreatorMethods[] = {
{"nativeClassInit", "()V", (void*) DngCreator_nativeClassInit},
{"nativeInit", "(Landroid/hardware/camera2/impl/CameraMetadataNative;"
"Landroid/hardware/camera2/impl/CameraMetadataNative;Ljava/lang/String;)V",
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index 63915ed1c134..f1ea7ec7e8a2 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -730,7 +730,7 @@ static jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz
} // extern "C"
-static JNINativeMethod gCameraDeviceMethods[] = {
+static const JNINativeMethod gCameraDeviceMethods[] = {
{ "nativeDetectSurfaceType",
"(Landroid/view/Surface;)I",
(void *)LegacyCameraDevice_nativeDetectSurfaceType },
diff --git a/core/jni/android_hardware_camera2_legacy_PerfMeasurement.cpp b/core/jni/android_hardware_camera2_legacy_PerfMeasurement.cpp
index 7257597ca6cf..f0420585bfa4 100644
--- a/core/jni/android_hardware_camera2_legacy_PerfMeasurement.cpp
+++ b/core/jni/android_hardware_camera2_legacy_PerfMeasurement.cpp
@@ -302,7 +302,7 @@ static jlong PerfMeasurement_nativeGetNextGlDuration(JNIEnv* env,
} // extern "C"
-static JNINativeMethod gPerfMeasurementMethods[] = {
+static const JNINativeMethod gPerfMeasurementMethods[] = {
{ "nativeCreateContext",
"(I)J",
(jlong *)PerfMeasurement_nativeCreateContext },
diff --git a/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp b/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp
index 470c5ba8e2a3..4b279f63c99f 100644
--- a/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp
+++ b/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp
@@ -275,7 +275,7 @@ static int flush(JNIEnv* env, jobject obj) {
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
// {"name", "signature", (void*) functionPointer },
{ "nativeClassInit", "()V", (void*) class_init },
{ "nativeInitialize", "()V", (void*) initialize },
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 6c2bbd45ea51..b977e377f2f3 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -682,7 +682,7 @@ static void android_media_AudioRecord_disableDeviceCallback(
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
// name, signature, funcPtr
{"native_start", "(II)I", (void *)android_media_AudioRecord_start},
{"native_stop", "()V", (void *)android_media_AudioRecord_stop},
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 91b3278c2e2b..6d3c7d7363c6 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -1616,7 +1616,7 @@ android_media_AudioSystem_systemReady(JNIEnv *env, jobject thiz)
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
{"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
{"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone},
@@ -1663,7 +1663,7 @@ static JNINativeMethod gMethods[] = {
};
-static JNINativeMethod gEventHandlerMethods[] = {
+static const JNINativeMethod gEventHandlerMethods[] = {
{"native_setup",
"(Ljava/lang/Object;)V",
(void *)android_media_AudioSystem_eventHandlerSetup},
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 5faa15008359..7860b74cc804 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -1052,7 +1052,7 @@ static void android_media_AudioTrack_disableDeviceCallback(
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
// name, signature, funcPtr
{"native_start", "()V", (void *)android_media_AudioTrack_start},
{"native_stop", "()V", (void *)android_media_AudioTrack_stop},
diff --git a/core/jni/android_media_JetPlayer.cpp b/core/jni/android_media_JetPlayer.cpp
index d441f1015dfc..873c3f2e07e1 100644
--- a/core/jni/android_media_JetPlayer.cpp
+++ b/core/jni/android_media_JetPlayer.cpp
@@ -488,7 +488,7 @@ android_media_JetPlayer_clearQueue(JNIEnv *env, jobject thiz)
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
// name, signature, funcPtr
{"native_setup", "(Ljava/lang/Object;II)Z", (void *)android_media_JetPlayer_setup},
{"native_finalize", "()V", (void *)android_media_JetPlayer_finalize},
diff --git a/core/jni/android_media_RemoteDisplay.cpp b/core/jni/android_media_RemoteDisplay.cpp
index 9bc223b57a42..bd1a6ecaf95c 100644
--- a/core/jni/android_media_RemoteDisplay.cpp
+++ b/core/jni/android_media_RemoteDisplay.cpp
@@ -177,7 +177,7 @@ static void nativeDispose(JNIEnv* env, jobject remoteDisplayObj, jlong ptr) {
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"nativeListen", "(Ljava/lang/String;Ljava/lang/String;)J",
(void*)nativeListen },
{"nativeDispose", "(J)V",
diff --git a/core/jni/android_media_ToneGenerator.cpp b/core/jni/android_media_ToneGenerator.cpp
index 243f0400775e..aec62631c559 100644
--- a/core/jni/android_media_ToneGenerator.cpp
+++ b/core/jni/android_media_ToneGenerator.cpp
@@ -123,7 +123,7 @@ static void android_media_ToneGenerator_native_finalize(JNIEnv *env,
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "startTone", "(II)Z", (void *)android_media_ToneGenerator_startTone },
{ "stopTone", "()V", (void *)android_media_ToneGenerator_stopTone },
{ "getAudioSessionId", "()I", (void *)android_media_ToneGenerator_getAudioSessionId},
diff --git a/core/jni/android_net_LocalSocketImpl.cpp b/core/jni/android_net_LocalSocketImpl.cpp
index c137b17426e0..d6d431019a6d 100644
--- a/core/jni/android_net_LocalSocketImpl.cpp
+++ b/core/jni/android_net_LocalSocketImpl.cpp
@@ -495,7 +495,7 @@ static jobject socket_get_peer_credentials(JNIEnv *env,
/*
* JNI registration.
*/
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{"connectLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V",
(void*)socket_connect_local},
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index fada7ac21b1d..ba0876d74b17 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -302,7 +302,7 @@ static jboolean android_net_utils_queryUserAccess(JNIEnv *env, jobject thiz, jin
/*
* JNI registration.
*/
-static JNINativeMethod gNetworkUtilMethods[] = {
+static const JNINativeMethod gNetworkUtilMethods[] = {
/* name, signature, funcPtr */
{ "resetConnections", "(Ljava/lang/String;I)I", (void *)android_net_utils_resetConnections },
{ "startDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_startDhcp },
diff --git a/core/jni/android_net_TrafficStats.cpp b/core/jni/android_net_TrafficStats.cpp
index 735441743516..7b7d0cf498c3 100644
--- a/core/jni/android_net_TrafficStats.cpp
+++ b/core/jni/android_net_TrafficStats.cpp
@@ -185,7 +185,7 @@ static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) {
}
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"nativeGetTotalStat", "(I)J", (void*) getTotalStat},
{"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*) getIfaceStat},
{"nativeGetUidStat", "(II)J", (void*) getUidStat},
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
index 9f5b3bc3f5b2..568473c14dc5 100644
--- a/core/jni/android_opengl_EGL14.cpp
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -1231,7 +1231,7 @@ android_eglCopyBuffers
static const char *classPathName = "android/opengl/EGL14";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"eglGetError", "()I", (void *) android_eglGetError },
{"eglGetDisplay", "(I)Landroid/opengl/EGLDisplay;", (void *) android_eglGetDisplayInt },
diff --git a/core/jni/android_opengl_EGLExt.cpp b/core/jni/android_opengl_EGLExt.cpp
index 60a3bf642915..62ccad4d85f0 100644
--- a/core/jni/android_opengl_EGLExt.cpp
+++ b/core/jni/android_opengl_EGLExt.cpp
@@ -149,7 +149,7 @@ android_eglPresentationTimeANDROID
static const char *classPathName = "android/opengl/EGLExt";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"eglPresentationTimeANDROID", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;J)Z", (void *) android_eglPresentationTimeANDROID },
};
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index dac98defbc79..f4135c213e36 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -3184,7 +3184,7 @@ android_glViewport__IIII
static const char *classPathName = "android/opengl/GLES10";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glActiveTexture", "(I)V", (void *) android_glActiveTexture__I },
{"glAlphaFunc", "(IF)V", (void *) android_glAlphaFunc__IF },
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
index 95be11bde598..4dc42339b6e5 100644
--- a/core/jni/android_opengl_GLES10Ext.cpp
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -582,7 +582,7 @@ exit:
static const char *classPathName = "android/opengl/GLES10Ext";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glQueryMatrixxOES", "([II[II)I", (void *) android_glQueryMatrixxOES___3II_3II },
{"glQueryMatrixxOES", "(Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;)I", (void *) android_glQueryMatrixxOES__Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2 },
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index 6970a3c7e180..2625e03c962e 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -3065,7 +3065,7 @@ android_glVertexPointer__IIII
static const char *classPathName = "android/opengl/GLES11";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glBindBuffer", "(II)V", (void *) android_glBindBuffer__II },
{"glBufferData", "(IILjava/nio/Buffer;I)V", (void *) android_glBufferData__IILjava_nio_Buffer_2I },
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index 6422ff28e190..fb85cb0f8d95 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -3573,7 +3573,7 @@ android_glGetTexGenxvOES__IILjava_nio_IntBuffer_2
static const char *classPathName = "android/opengl/GLES11Ext";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glBlendEquationSeparateOES", "(II)V", (void *) android_glBlendEquationSeparateOES__II },
{"glBlendFuncSeparateOES", "(IIII)V", (void *) android_glBlendFuncSeparateOES__IIII },
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index f9a0dfeb444c..b9f61a91ec90 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -6152,7 +6152,7 @@ android_glViewport__IIII
static const char *classPathName = "android/opengl/GLES20";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glActiveTexture", "(I)V", (void *) android_glActiveTexture__I },
{"glAttachShader", "(II)V", (void *) android_glAttachShader__II },
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 1d92cd46527a..8eb50444762c 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -5167,7 +5167,7 @@ android_glGetInternalformativ__IIIILjava_nio_IntBuffer_2
static const char *classPathName = "android/opengl/GLES30";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glReadBuffer", "(I)V", (void *) android_glReadBuffer__I },
{"glDrawRangeElements", "(IIIIILjava/nio/Buffer;)V", (void *) android_glDrawRangeElements__IIIIILjava_nio_Buffer_2 },
diff --git a/core/jni/android_opengl_GLES31.cpp b/core/jni/android_opengl_GLES31.cpp
index 92ecbe0b99df..e427388a10e9 100644
--- a/core/jni/android_opengl_GLES31.cpp
+++ b/core/jni/android_opengl_GLES31.cpp
@@ -3175,7 +3175,7 @@ android_glVertexBindingDivisor__II
static const char *classPathName = "android/opengl/GLES31";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glDispatchCompute", "(III)V", (void *) android_glDispatchCompute__III },
{"glDispatchComputeIndirect", "(J)V", (void *) android_glDispatchComputeIndirect },
diff --git a/core/jni/android_opengl_GLES31Ext.cpp b/core/jni/android_opengl_GLES31Ext.cpp
index 28563089e85a..180c69348853 100644
--- a/core/jni/android_opengl_GLES31Ext.cpp
+++ b/core/jni/android_opengl_GLES31Ext.cpp
@@ -1443,7 +1443,7 @@ android_glTexBufferRangeEXT__IIIII
static const char *classPathName = "android/opengl/GLES31Ext";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glBlendBarrierKHR", "()V", (void *) android_glBlendBarrierKHR__ },
{"glDebugMessageControlKHR", "(IIII[IIZ)V", (void *) android_glDebugMessageControlKHR__IIII_3IIZ },
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index b969477bf258..097bbac84e3f 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -973,7 +973,7 @@ static void android_os_Debug_dumpNativeBacktraceToFile(JNIEnv* env, jobject claz
* JNI registration.
*/
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "getNativeHeapSize", "()J",
(void*) android_os_Debug_getNativeHeapSize },
{ "getNativeHeapAllocatedSize", "()J",
diff --git a/core/jni/android_os_MessageQueue.cpp b/core/jni/android_os_MessageQueue.cpp
index d2db3c9ab5b3..e57a7190cfce 100644
--- a/core/jni/android_os_MessageQueue.cpp
+++ b/core/jni/android_os_MessageQueue.cpp
@@ -209,7 +209,7 @@ static void android_os_MessageQueue_nativeSetFileDescriptorEvents(JNIEnv* env, j
// ----------------------------------------------------------------------------
-static JNINativeMethod gMessageQueueMethods[] = {
+static const JNINativeMethod gMessageQueueMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit", "()J", (void*)android_os_MessageQueue_nativeInit },
{ "nativeDestroy", "(J)V", (void*)android_os_MessageQueue_nativeDestroy },
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index 762b88f5dbee..8ba77aed1d04 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -320,7 +320,7 @@ static jboolean native_restorecon(JNIEnv *env, jobject, jstring pathnameStr, jin
/*
* JNI registration.
*/
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
/* name, signature, funcPtr */
{ "checkSELinuxAccess" , "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z" , (void*)checkSELinuxAccess },
{ "getContext" , "()Ljava/lang/String;" , (void*)getCon },
diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp
index dfe024e8a473..d98407deb7e7 100644
--- a/core/jni/android_os_SystemClock.cpp
+++ b/core/jni/android_os_SystemClock.cpp
@@ -104,7 +104,7 @@ static jlong android_os_SystemClock_elapsedRealtimeNano(JNIEnv* env,
/*
* JNI registration.
*/
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "uptimeMillis", "()J",
(void*) android_os_SystemClock_uptimeMillis },
diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp
index 554d304290cf..5dace6b7e536 100644
--- a/core/jni/android_os_SystemProperties.cpp
+++ b/core/jni/android_os_SystemProperties.cpp
@@ -220,7 +220,7 @@ static void SystemProperties_add_change_callback(JNIEnv *env, jobject clazz)
}
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "native_get", "(Ljava/lang/String;)Ljava/lang/String;",
(void*) SystemProperties_getS },
{ "native_get", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp
index 3fd3b3c9ae15..30fc47bba751 100644
--- a/core/jni/android_os_Trace.cpp
+++ b/core/jni/android_os_Trace.cpp
@@ -105,7 +105,7 @@ static void android_os_Trace_nativeSetTracingEnabled(JNIEnv* env,
atrace_set_tracing_enabled(enabled);
}
-static JNINativeMethod gTraceMethods[] = {
+static const JNINativeMethod gTraceMethods[] = {
/* name, signature, funcPtr */
{ "nativeGetEnabledTags",
"()J",
diff --git a/core/jni/android_os_UEventObserver.cpp b/core/jni/android_os_UEventObserver.cpp
index eb36f8549cfa..30d40a2a08ad 100644
--- a/core/jni/android_os_UEventObserver.cpp
+++ b/core/jni/android_os_UEventObserver.cpp
@@ -103,7 +103,7 @@ static void nativeRemoveMatch(JNIEnv* env, jclass clazz, jstring matchStr) {
}
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nativeSetup", "()V",
(void *)nativeSetup },
{ "nativeWaitForNextEvent", "()Ljava/lang/String;",
diff --git a/core/jni/android_server_NetworkManagementSocketTagger.cpp b/core/jni/android_server_NetworkManagementSocketTagger.cpp
index ca21fd716a5f..818bf53d97a4 100644
--- a/core/jni/android_server_NetworkManagementSocketTagger.cpp
+++ b/core/jni/android_server_NetworkManagementSocketTagger.cpp
@@ -83,7 +83,7 @@ static jint QTagUid_deleteTagData(JNIEnv* env, jclass,
return (jint)res;
}
-static JNINativeMethod gQTagUidMethods[] = {
+static const JNINativeMethod gQTagUidMethods[] = {
{ "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*)QTagUid_tagSocketFd},
{ "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*)QTagUid_untagSocketFd},
{ "native_setCounterSet", "(II)I", (void*)QTagUid_setCounterSet},
diff --git a/core/jni/android_text_AndroidBidi.cpp b/core/jni/android_text_AndroidBidi.cpp
index 328542954efa..2a3f0361a9cd 100644
--- a/core/jni/android_text_AndroidBidi.cpp
+++ b/core/jni/android_text_AndroidBidi.cpp
@@ -56,7 +56,7 @@ static jint runBidi(JNIEnv* env, jobject obj, jint dir, jcharArray chsArray,
return result;
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "runBidi", "(I[C[BIZ)I", (void*) runBidi }
};
diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp
index 9258248083d0..474a74e8776c 100644
--- a/core/jni/android_text_AndroidCharacter.cpp
+++ b/core/jni/android_text_AndroidCharacter.cpp
@@ -178,7 +178,7 @@ static jchar getMirror(JNIEnv* env, jobject obj, jchar c)
return u_charMirror(c);
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "getDirectionalities", "([C[BI)V",
(void*) getDirectionalities },
{ "getEastAsianWidth", "(C)I",
diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp
index 90e4bb64133e..a151e004922d 100644
--- a/core/jni/android_text_StaticLayout.cpp
+++ b/core/jni/android_text_StaticLayout.cpp
@@ -172,7 +172,7 @@ static void nGetWidths(JNIEnv* env, jclass, jlong nativePtr, jfloatArray widths)
env->SetFloatArrayRegion(widths, 0, b->size(), b->charWidths());
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
// TODO performance: many of these are candidates for fast jni, awaiting guidance
{"nNewBuilder", "()J", (void*) nNewBuilder},
{"nFreeBuilder", "(J)V", (void*) nFreeBuilder},
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 7ca0654f9656..614e82f803ff 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -2112,7 +2112,7 @@ static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env,
/*
* JNI registration.
*/
-static JNINativeMethod gAssetManagerMethods[] = {
+static const JNINativeMethod gAssetManagerMethods[] = {
/* name, signature, funcPtr */
// Basic asset stuff.
diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp
index 05bc12563b6c..4f8a2cb91506 100644
--- a/core/jni/android_util_EventLog.cpp
+++ b/core/jni/android_util_EventLog.cpp
@@ -249,7 +249,7 @@ static void android_util_EventLog_readEvents(JNIEnv* env, jobject clazz UNUSED,
/*
* JNI registration.
*/
-static JNINativeMethod gRegisterMethods[] = {
+static const JNINativeMethod gRegisterMethods[] = {
/* name, signature, funcPtr */
{ "writeEvent", "(II)I", (void*) android_util_EventLog_writeEvent_Integer },
{ "writeEvent", "(IJ)I", (void*) android_util_EventLog_writeEvent_Long },
diff --git a/core/jni/android_util_FileObserver.cpp b/core/jni/android_util_FileObserver.cpp
index 067d298580bc..2b93b6d61905 100644
--- a/core/jni/android_util_FileObserver.cpp
+++ b/core/jni/android_util_FileObserver.cpp
@@ -127,7 +127,7 @@ static void android_os_fileobserver_stopWatching(JNIEnv* env, jobject object, ji
#endif
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{ "init", "()I", (void*)android_os_fileobserver_init },
{ "observe", "(I)V", (void*)android_os_fileobserver_observe },
diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp
index 2b1067bede5d..2d23cda5ff15 100644
--- a/core/jni/android_util_Log.cpp
+++ b/core/jni/android_util_Log.cpp
@@ -111,7 +111,7 @@ static jint android_util_Log_println_native(JNIEnv* env, jobject clazz,
/*
* JNI registration.
*/
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "isLoggable", "(Ljava/lang/String;I)Z", (void*) android_util_Log_isLoggable },
{ "println_native", "(IILjava/lang/String;Ljava/lang/String;)I", (void*) android_util_Log_println_native },
diff --git a/core/jni/android_util_StringBlock.cpp b/core/jni/android_util_StringBlock.cpp
index f83eaec409d5..b396afe62dff 100644
--- a/core/jni/android_util_StringBlock.cpp
+++ b/core/jni/android_util_StringBlock.cpp
@@ -155,7 +155,7 @@ static void android_content_StringBlock_nativeDestroy(JNIEnv* env, jobject clazz
/*
* JNI registration.
*/
-static JNINativeMethod gStringBlockMethods[] = {
+static const JNINativeMethod gStringBlockMethods[] = {
/* name, signature, funcPtr */
{ "nativeCreate", "([BII)J",
(void*) android_content_StringBlock_nativeCreate },
diff --git a/core/jni/android_util_XmlBlock.cpp b/core/jni/android_util_XmlBlock.cpp
index 375710e6faca..7ae51c89fab7 100644
--- a/core/jni/android_util_XmlBlock.cpp
+++ b/core/jni/android_util_XmlBlock.cpp
@@ -364,7 +364,7 @@ static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz,
/*
* JNI registration.
*/
-static JNINativeMethod gXmlBlockMethods[] = {
+static const JNINativeMethod gXmlBlockMethods[] = {
/* name, signature, funcPtr */
{ "nativeCreate", "([BII)J",
(void*) android_content_XmlBlock_nativeCreate },
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index 0e2ec6b85209..437bd192b70a 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -259,7 +259,7 @@ static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit",
"(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;)J",
diff --git a/core/jni/android_view_GraphicBuffer.cpp b/core/jni/android_view_GraphicBuffer.cpp
index 17d2a5eddbf8..7682dd6ca8e3 100644
--- a/core/jni/android_view_GraphicBuffer.cpp
+++ b/core/jni/android_view_GraphicBuffer.cpp
@@ -268,7 +268,7 @@ sp<GraphicBuffer> graphicBufferForJavaObject(JNIEnv* env, jobject obj) {
const char* const kClassPathName = "android/view/GraphicBuffer";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nCreateGraphicBuffer", "(IIII)J", (void*) android_view_GraphiceBuffer_create },
{ "nDestroyGraphicBuffer", "(J)V", (void*) android_view_GraphiceBuffer_destroy },
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 36ba892b51c4..3a0ddc9fa825 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -85,7 +85,7 @@ static void android_view_HardwareLayer_updateSurfaceTexture(JNIEnv* env, jobject
const char* const kClassPathName = "android/view/HardwareLayer";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nPrepare", "(JIIZ)Z", (void*) android_view_HardwareLayer_prepare },
{ "nSetLayerPaint", "(JJ)V", (void*) android_view_HardwareLayer_setLayerPaint },
{ "nSetTransform", "(JJ)V", (void*) android_view_HardwareLayer_setTransform },
diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp
index 4b42ab5d213a..092ac27176cc 100644
--- a/core/jni/android_view_InputChannel.cpp
+++ b/core/jni/android_view_InputChannel.cpp
@@ -259,7 +259,7 @@ static void android_view_InputChannel_nativeDup(JNIEnv* env, jobject obj, jobjec
// ----------------------------------------------------------------------------
-static JNINativeMethod gInputChannelMethods[] = {
+static const JNINativeMethod gInputChannelMethods[] = {
/* name, signature, funcPtr */
{ "nativeOpenInputChannelPair", "(Ljava/lang/String;)[Landroid/view/InputChannel;",
(void*)android_view_InputChannel_nativeOpenInputChannelPair },
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index 43b847108a20..8293cd8ff88d 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -395,7 +395,7 @@ static jboolean nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jlong
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit",
"(Ljava/lang/ref/WeakReference;Landroid/view/InputChannel;Landroid/os/MessageQueue;)J",
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index d61dee7a7673..3bd6917aedfa 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -289,7 +289,7 @@ static jboolean nativeSendMotionEvent(JNIEnv* env, jclass clazz, jlong senderPtr
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit",
"(Ljava/lang/ref/WeakReference;Landroid/view/InputChannel;Landroid/os/MessageQueue;)J",
diff --git a/core/jni/android_view_KeyCharacterMap.cpp b/core/jni/android_view_KeyCharacterMap.cpp
index 7653f58778dd..e5519a752c39 100644
--- a/core/jni/android_view_KeyCharacterMap.cpp
+++ b/core/jni/android_view_KeyCharacterMap.cpp
@@ -203,7 +203,7 @@ static jobjectArray nativeGetEvents(JNIEnv *env, jobject clazz, jlong ptr,
* JNI registration.
*/
-static JNINativeMethod g_methods[] = {
+static const JNINativeMethod g_methods[] = {
/* name, signature, funcPtr */
{ "nativeReadFromParcel", "(Landroid/os/Parcel;)J",
(void*)nativeReadFromParcel },
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 98c17c03b1a7..81d46c3d6988 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -752,7 +752,7 @@ static jint android_view_MotionEvent_nativeAxisFromString(JNIEnv* env, jclass cl
// ----------------------------------------------------------------------------
-static JNINativeMethod gMotionEventMethods[] = {
+static const JNINativeMethod gMotionEventMethods[] = {
/* name, signature, funcPtr */
{ "nativeInitialize",
"(JIIIIIIIFFFFJJI[Landroid/view/MotionEvent$PointerProperties;"
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index a3b370017a8e..388d36541eb8 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -467,7 +467,7 @@ static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
const char* const kClassPathName = "android/view/RenderNode";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nCreate", "(Ljava/lang/String;)J", (void*) android_view_RenderNode_create },
{ "nDestroyRenderNode", "(J)V", (void*) android_view_RenderNode_destroyRenderNode },
{ "nSetDisplayListData", "(JJ)V", (void*) android_view_RenderNode_setDisplayListData },
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index 4177ee2f7fe8..0926e9b76691 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -193,7 +193,7 @@ static void end(JNIEnv* env, jobject clazz, jlong animatorPtr) {
const char* const kClassPathName = "android/view/RenderNodeAnimator";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nCreateAnimator", "(IF)J", (void*) createAnimator },
{ "nCreateCanvasPropertyFloatAnimator", "(JF)J", (void*) createCanvasPropertyFloatAnimator },
{ "nCreateCanvasPropertyPaintAnimator", "(JIF)J", (void*) createCanvasPropertyPaintAnimator },
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 4a311d31bd82..24055e76234e 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -514,7 +514,7 @@ static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) {
namespace hwui = android::uirenderer;
-static JNINativeMethod gSurfaceMethods[] = {
+static const JNINativeMethod gSurfaceMethods[] = {
{"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J",
(void*)nativeCreateFromSurfaceTexture },
{"nativeRelease", "(J)V",
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index d1acb59a6411..65ebb6633a8f 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -572,7 +572,7 @@ static jboolean nativeGetAnimationFrameStats(JNIEnv* env, jclass clazz, jobject
// ----------------------------------------------------------------------------
-static JNINativeMethod sSurfaceControlMethods[] = {
+static const JNINativeMethod sSurfaceControlMethods[] = {
{"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)J",
(void*)nativeCreate },
{"nativeRelease", "(J)V",
diff --git a/core/jni/android_view_SurfaceSession.cpp b/core/jni/android_view_SurfaceSession.cpp
index 609c565678f2..dad6958560c0 100644
--- a/core/jni/android_view_SurfaceSession.cpp
+++ b/core/jni/android_view_SurfaceSession.cpp
@@ -56,7 +56,7 @@ static void nativeKill(JNIEnv* env, jclass clazz, jlong ptr) {
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeCreate", "()J",
(void*)nativeCreate },
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index beb83b1e01fa..b736a17c1199 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -197,7 +197,7 @@ static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject,
const char* const kClassPathName = "android/view/TextureView";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nCreateNativeWindow", "(Landroid/graphics/SurfaceTexture;)V",
(void*) android_view_TextureView_createNativeWindow },
{ "nDestroyNativeWindow", "()V",
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 6c3676b5ef05..c79f833b54a9 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -440,6 +440,32 @@ static void android_view_ThreadedRenderer_dumpProfileData(JNIEnv* env, jobject c
}
}
+static void android_view_ThreadedRenderer_addRenderNode(JNIEnv* env, jobject clazz,
+ jlong proxyPtr, jlong renderNodePtr, jboolean placeFront) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+ proxy->addRenderNode(renderNode, placeFront);
+}
+
+static void android_view_ThreadedRenderer_removeRenderNode(JNIEnv* env, jobject clazz,
+ jlong proxyPtr, jlong renderNodePtr) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+ proxy->removeRenderNode(renderNode);
+}
+
+static void android_view_ThreadedRendererd_drawRenderNode(JNIEnv* env, jobject clazz,
+ jlong proxyPtr, jlong renderNodePtr) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+ proxy->drawRenderNode(renderNode);
+}
+
+static void android_view_ThreadedRenderer_setContentOverdrawProtectionBounds(JNIEnv* env,
+ jobject clazz, jlong proxyPtr, jint left, jint top, jint right, jint bottom) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ proxy->setContentOverdrawProtectionBounds(left, top, right, bottom);
+}
// ----------------------------------------------------------------------------
// Shaders
@@ -447,7 +473,6 @@ static void android_view_ThreadedRenderer_dumpProfileData(JNIEnv* env, jobject c
static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
jstring diskCachePath) {
-
const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
egl_cache_t::get()->setCacheFilename(cacheArray);
env->ReleaseStringUTFChars(diskCachePath, cacheArray);
@@ -459,7 +484,7 @@ static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, job
const char* const kClassPathName = "android/view/ThreadedRenderer";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V", (void*) android_view_ThreadedRenderer_setAtlas },
{ "nSetProcessStatsBuffer", "(JI)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer },
{ "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
@@ -494,6 +519,11 @@ static JNINativeMethod gMethods[] = {
{ "nDumpProfileData", "([BLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileData },
{ "setupShadersDiskCache", "(Ljava/lang/String;)V",
(void*) android_view_ThreadedRenderer_setupShadersDiskCache },
+ { "nAddRenderNode", "(JJZ)V", (void*) android_view_ThreadedRenderer_addRenderNode},
+ { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
+ { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
+ { "nSetContentOverdrawProtectionBounds", "(JIIII)V",
+ (void*)android_view_ThreadedRenderer_setContentOverdrawProtectionBounds},
};
int register_android_view_ThreadedRenderer(JNIEnv* env) {
diff --git a/core/jni/android_view_VelocityTracker.cpp b/core/jni/android_view_VelocityTracker.cpp
index ddd5fc853d25..04ec7059365e 100644
--- a/core/jni/android_view_VelocityTracker.cpp
+++ b/core/jni/android_view_VelocityTracker.cpp
@@ -215,7 +215,7 @@ static jboolean android_view_VelocityTracker_nativeGetEstimator(JNIEnv* env, jcl
// --- JNI Registration ---
-static JNINativeMethod gVelocityTrackerMethods[] = {
+static const JNINativeMethod gVelocityTrackerMethods[] = {
/* name, signature, funcPtr */
{ "nativeInitialize",
"(Ljava/lang/String;)J",
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index daa6f82ea122..364ac44ee0f6 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -561,7 +561,7 @@ com_android_internal_content_NativeLibraryHelper_close(JNIEnv *env, jclass, jlon
delete reinterpret_cast<ZipFileRO*>(apkHandle);
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"nativeOpenApk",
"(Ljava/lang/String;)J",
(void *)com_android_internal_content_NativeLibraryHelper_openApk},
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index 6c0b756591f7..70134ab04a2a 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -284,7 +284,7 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats,
return 0;
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nativeReadNetworkStatsDetail",
"(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;I)I",
(void*) readNetworkStatsDetail }
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index aef70be4922a..3f1be456c199 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -647,7 +647,7 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer(
return pid;
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nativeForkAndSpecialize",
"(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",
(void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
diff --git a/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp b/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp
index 7a18c2d380ce..d20bae232656 100644
--- a/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp
+++ b/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp
@@ -36,7 +36,7 @@ static void decStrong(JNIEnv* env, jobject clazz, jlong objPtr) {
const char* const kClassPathName = "com/android/internal/util/VirtualRefBasePtr";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nIncStrong", "(J)V", (void*) incStrong },
{ "nDecStrong", "(J)V", (void*) decStrong },
};
diff --git a/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp b/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp
index 2c65d6210c2e..6781e130c860 100644
--- a/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp
+++ b/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp
@@ -78,7 +78,7 @@ static jlong createLutInterpolator(JNIEnv* env, jobject clazz, jfloatArray jlut)
const char* const kClassPathName = "com/android/internal/view/animation/NativeInterpolatorFactoryHelper";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "createAccelerateDecelerateInterpolator", "()J", (void*) createAccelerateDecelerateInterpolator },
{ "createAccelerateInterpolator", "(F)J", (void*) createAccelerateInterpolator },
{ "createAnticipateInterpolator", "(F)J", (void*) createAnticipateInterpolator },
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index baeb7dd98bc4..3d63b013e9f1 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -532,7 +532,7 @@ static const char *classPathName = "com/google/android/gles_jni/EGLImpl";
#define OBJECT "Ljava/lang/Object;"
#define STRING "Ljava/lang/String;"
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit","()V", (void*)nativeClassInit },
{"eglWaitGL", "()Z", (void*)jni_eglWaitGL },
{"eglInitialize", "(" DISPLAY "[I)Z", (void*)jni_eglInitialize },
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index f15f957d21c7..ad7d744cb693 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -8490,7 +8490,7 @@ android_glTexGenxv__IILjava_nio_IntBuffer_2
static const char *classPathName = "com/google/android/gles_jni/GLImpl";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glActiveTexture", "(I)V", (void *) android_glActiveTexture__I },
{"glAlphaFunc", "(IF)V", (void *) android_glAlphaFunc__IF },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 664e62121d1b..28dac39d7022 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -188,7 +188,7 @@
<protected-broadcast android:name="android.hardware.usb.action.USB_STATE" />
<protected-broadcast android:name="android.hardware.usb.action.USB_PORT_CHANGED" />
<protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
- <protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
+ <protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_DETACHED" />
<protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
<protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
diff --git a/core/res/res/layout/docked_stack_divider.xml b/core/res/res/layout/docked_stack_divider.xml
new file mode 100644
index 000000000000..aa6e68d57af9
--- /dev/null
+++ b/core/res/res/layout/docked_stack_divider.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="@dimen/docked_stack_divider_thickness"
+ android:layout_height="match_parent"
+ android:background="@android:color/black"
+ />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 902d40dad64f..dc96df4e9d7c 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5550,6 +5550,8 @@ i
<!-- Push object to the end of its container, not changing its size. -->
<flag name="end" value="0x00800005" />
</attr>
+ <!-- Specifies the initial drawable level in the range 0 to 10000. -->
+ <attr name="level" format="integer" />
<!-- Reference to a drawable resource to draw with the specified scale. -->
<attr name="drawable" />
<!-- Use the drawable's intrinsic width and height as minimum size values.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a19bc202c74d..9b1a613894d9 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -410,6 +410,9 @@
radio is unable to find any MCC information to infer wifi country code from -->
<bool translatable="false" name="config_wifi_revert_country_code_on_cellular_loss">false</bool>
+ <!-- Boolean indicating whether or not wifi firmware debugging is enabled -->
+ <bool translatable="false" name="config_wifi_enable_wifi_firmware_debugging">false</bool>
+
<!-- Integer specifying the basic autojoin parameters -->
<integer translatable="false" name="config_wifi_framework_5GHz_preference_boost_threshold">-65</integer>
<integer translatable="false" name="config_wifi_framework_5GHz_preference_boost_factor">5</integer>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 8635a4fac7bc..2621bc9cf219 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -45,6 +45,9 @@
<!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
<dimen name="status_bar_edge_ignore">5dp</dimen>
+ <!-- Width of a divider bar used to resize docked stacks. -->
+ <dimen name="docked_stack_divider_thickness">24dp</dimen>
+
<!-- Min width for a tablet device -->
<dimen name="min_xlarge_screen_width">800dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index b6284c93faab..89d9babbbc1e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2673,6 +2673,7 @@
<public type="attr" name="maxButtonHeight" />
<public type="attr" name="buttonGravity" />
<public type="attr" name="collapseIcon" />
+ <public type="attr" name="level" />
<public type="style" name="Theme.Material.DayNight" />
<public type="style" name="Theme.Material.DayNight.DarkActionBar" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4edc847156c3..b5efbfd2462a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -307,6 +307,7 @@
<java-symbol type="bool" name="config_wifi_enable_disconnection_debounce" />
<java-symbol type="bool" name="config_wifi_enable_5GHz_preference" />
<java-symbol type="bool" name="config_wifi_revert_country_code_on_cellular_loss" />
+ <java-symbol type="bool" name="config_wifi_enable_wifi_firmware_debugging" />
<java-symbol type="bool" name="config_supportMicNearUltrasound" />
<java-symbol type="bool" name="config_supportSpeakerNearUltrasound" />
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_threshold" />
@@ -1477,6 +1478,7 @@
<java-symbol type="bool" name="config_showNavigationBar" />
<java-symbol type="bool" name="config_supportAutoRotation" />
<java-symbol type="bool" name="target_honeycomb_needs_options_menu" />
+ <java-symbol type="dimen" name="docked_stack_divider_thickness" />
<java-symbol type="dimen" name="navigation_bar_height" />
<java-symbol type="dimen" name="navigation_bar_height_landscape" />
<java-symbol type="dimen" name="navigation_bar_width" />
@@ -1719,6 +1721,7 @@
<java-symbol type="integer" name="config_undockedHdmiRotation" />
<java-symbol type="integer" name="config_virtualKeyQuietTimeMillis" />
<java-symbol type="layout" name="am_compat_mode_dialog" />
+ <java-symbol type="layout" name="docked_stack_divider" />
<java-symbol type="layout" name="launch_warning" />
<java-symbol type="layout" name="safe_mode" />
<java-symbol type="layout" name="simple_list_item_2_single_choice" />
diff --git a/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp b/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp
index e0b616c16184..3e8301038359 100644
--- a/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp
+++ b/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp
@@ -22,7 +22,7 @@ static jint checkFunction(JNIEnv*, jclass) {
return 1;
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{ "checkFunction", "()I", (void*) checkFunction },
};
diff --git a/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
index 4c1615453289..67b12d775828 100644
--- a/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
@@ -30,7 +30,7 @@ int result = a + b;
static const char *classPathName = "com/framework/shareduid/bit32/Native";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"add", "(II)I", (void*)add },
};
@@ -38,7 +38,7 @@ static JNINativeMethod methods[] = {
* Register several native methods for one class.
*/
static int registerNativeMethods(JNIEnv* env, const char* className,
- JNINativeMethod* gMethods, int numMethods)
+ const JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;
diff --git a/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
index c2f9f529ee63..342b3bc0ac9a 100644
--- a/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
@@ -30,7 +30,7 @@ int result = a + b;
static const char *classPathName = "com/framework/shareduid/bit64/Native";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"add", "(II)I", (void*)add },
};
@@ -38,7 +38,7 @@ static JNINativeMethod methods[] = {
* Register several native methods for one class.
*/
static int registerNativeMethods(JNIEnv* env, const char* className,
- JNINativeMethod* gMethods, int numMethods)
+ const JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;
diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
index 5d3ca06968eb..9b38e3e4c437 100644
--- a/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
@@ -30,7 +30,7 @@ int result = a + b;
static const char *classPathName = "com/framework/shareduid/dual/Native";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"add", "(II)I", (void*)add },
};
@@ -38,7 +38,7 @@ static JNINativeMethod methods[] = {
* Register several native methods for one class.
*/
static int registerNativeMethods(JNIEnv* env, const char* className,
- JNINativeMethod* gMethods, int numMethods)
+ const JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;
diff --git a/docs/html/training/location/geofencing.jd b/docs/html/training/location/geofencing.jd
index 59fc4c665a53..556329cb1f7e 100644
--- a/docs/html/training/location/geofencing.jd
+++ b/docs/html/training/location/geofencing.jd
@@ -100,8 +100,8 @@ srcset="{@docRoot}images/training/geofence.png 1x, {@docRoot}images/training/geo
<h3>Create geofence objects</h3>
<p>
- First, use <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.Builder.
- html">Geofence.Builder</a></code> to create a geofence, setting the desired radius, duration, and
+ First, use <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.Builder.html">
+ Geofence.Builder</a></code> to create a geofence, setting the desired radius, duration, and
transition types for the geofence. For example, to populate a list object named
{@code mGeofenceList}:
</p>
diff --git a/drm/jni/android_drm_DrmManagerClient.cpp b/drm/jni/android_drm_DrmManagerClient.cpp
index 52597e10609a..63fe8acedd54 100644
--- a/drm/jni/android_drm_DrmManagerClient.cpp
+++ b/drm/jni/android_drm_DrmManagerClient.cpp
@@ -702,7 +702,7 @@ static jobject android_drm_DrmManagerClient_closeConvertSession(
return status;
}
-static JNINativeMethod nativeMethods[] = {
+static const JNINativeMethod nativeMethods[] = {
{"_initialize", "()I",
(void*)android_drm_DrmManagerClient_initialize},
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index 0acbeda1979e..f9206b7d3c26 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -35,19 +35,29 @@ import java.io.IOException;
/**
* A Drawable that changes the size of another Drawable based on its current
- * level value. You can control how much the child Drawable changes in width
+ * level value. You can control how much the child Drawable changes in width
* and height based on the level, as well as a gravity to control where it is
- * placed in its overall container. Most often used to implement things like
+ * placed in its overall container. Most often used to implement things like
* progress bars.
- *
- * <p>It can be defined in an XML file with the <code>&lt;scale></code> element. For more
- * information, see the guide to <a
- * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
+ * <p>
+ * The default level may be specified from XML using the
+ * {@link android.R.styleable#ScaleDrawable_level android:level} property. When
+ * this property is not specified, the default level is 0, which corresponds to
+ * zero height and/or width depending on the values specified for
+ * {@code android.R.styleable#ScaleDrawable_scaleWidth scaleWidth} and
+ * {@code android.R.styleable#ScaleDrawable_scaleHeight scaleHeight}. At run
+ * time, the level may be set via {@link #setLevel(int)}.
+ * <p>
+ * A scale drawable may be defined in an XML file with the {@code &lt;scale>}
+ * element. For more information, see the guide to
+ * <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable
+ * Resources</a>.
*
* @attr ref android.R.styleable#ScaleDrawable_scaleWidth
* @attr ref android.R.styleable#ScaleDrawable_scaleHeight
* @attr ref android.R.styleable#ScaleDrawable_scaleGravity
* @attr ref android.R.styleable#ScaleDrawable_drawable
+ * @attr ref android.R.styleable#ScaleDrawable_level
*/
public class ScaleDrawable extends DrawableWrapper {
private static final int MAX_LEVEL = 10000;
@@ -92,6 +102,8 @@ public class ScaleDrawable extends DrawableWrapper {
inflateChildDrawable(r, parser, attrs, theme);
verifyRequiredAttributes(a);
a.recycle();
+
+ updateLocalState();
}
private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
@@ -117,6 +129,8 @@ public class ScaleDrawable extends DrawableWrapper {
R.styleable.ScaleDrawable_scaleGravity, state.mGravity);
state.mUseIntrinsicSizeAsMin = a.getBoolean(
R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, state.mUseIntrinsicSizeAsMin);
+ state.mInitialLevel = a.getInt(
+ R.styleable.ScaleDrawable_level, state.mInitialLevel);
final Drawable dr = a.getDrawable(R.styleable.ScaleDrawable_drawable);
if (dr != null) {
@@ -165,6 +179,8 @@ public class ScaleDrawable extends DrawableWrapper {
// The drawable may have changed as a result of applying the theme, so
// apply the theme to the wrapped drawable last.
super.applyTheme(t);
+
+ updateLocalState();
}
@Override
@@ -239,6 +255,7 @@ public class ScaleDrawable extends DrawableWrapper {
float mScaleHeight = DO_NOT_SCALE;
int mGravity = Gravity.LEFT;
boolean mUseIntrinsicSizeAsMin = false;
+ int mInitialLevel = 0;
ScaleState(ScaleState orig) {
super(orig);
@@ -248,6 +265,7 @@ public class ScaleDrawable extends DrawableWrapper {
mScaleHeight = orig.mScaleHeight;
mGravity = orig.mGravity;
mUseIntrinsicSizeAsMin = orig.mUseIntrinsicSizeAsMin;
+ mInitialLevel = orig.mInitialLevel;
}
}
@@ -257,10 +275,23 @@ public class ScaleDrawable extends DrawableWrapper {
}
}
+ /**
+ * Creates a new ScaleDrawable based on the specified constant state.
+ * <p>
+ * The resulting drawable is guaranteed to have a new constant state.
+ *
+ * @param state constant state from which the drawable inherits
+ */
private ScaleDrawable(ScaleState state, Resources res) {
super(state, res);
mState = state;
+
+ updateLocalState();
+ }
+
+ private void updateLocalState() {
+ setLevel(mState.mInitialLevel);
}
}
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 174722538014..1105ca4b6cbc 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -126,9 +126,13 @@ import java.util.Stack;
* <dd>Defines path data using exactly same format as "d" attribute
* in the SVG's path data. This is defined in the viewport space.</dd>
* <dt><code>android:fillColor</code></dt>
- * <dd>Defines the color to fill the path (none if not present).</dd>
+ * <dd>Specifies the color used to fill the path. May be a color or (SDK 24+ only) a color state
+ * list. If this property is animated, any value set by the animation will override the original
+ * value. No path fill is drawn if this property is not specified.</dd>
* <dt><code>android:strokeColor</code></dt>
- * <dd>Defines the color to draw the path outline (none if not present).</dd>
+ * <dd>Specifies the color used to draw the path outline. May be a color or (SDK 24+ only) a color
+ * state list. If this property is animated, any value set by the animation will override the
+ * original value. No path outline is drawn if this property is not specified.</dd>
* <dt><code>android:strokeWidth</code></dt>
* <dd>The width a path stroke.</dd>
* <dt><code>android:strokeAlpha</code></dt>
@@ -374,19 +378,24 @@ public class VectorDrawable extends Drawable {
@Override
public boolean isStateful() {
- return super.isStateful() || (mVectorState != null && mVectorState.mTint != null
- && mVectorState.mTint.isStateful());
+ return super.isStateful() || (mVectorState != null && mVectorState.isStateful());
}
@Override
protected boolean onStateChange(int[] stateSet) {
+ boolean changed = false;
+
final VectorDrawableState state = mVectorState;
+ if (state.mVPathRenderer != null && state.mVPathRenderer.onStateChange(stateSet)) {
+ changed = true;
+ state.mCacheDirty = true;
+ }
if (state.mTint != null && state.mTintMode != null) {
mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
- invalidateSelf();
- return true;
+ changed = true;
}
- return false;
+
+ return changed;
}
@Override
@@ -664,7 +673,7 @@ public class VectorDrawable extends Drawable {
if (SHAPE_PATH.equals(tagName)) {
final VFullPath path = new VFullPath();
path.inflate(res, attrs, theme);
- currentGroup.mChildren.add(path);
+ currentGroup.addChild(path);
if (path.getPathName() != null) {
pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
}
@@ -673,7 +682,7 @@ public class VectorDrawable extends Drawable {
} else if (SHAPE_CLIP_PATH.equals(tagName)) {
final VClipPath path = new VClipPath();
path.inflate(res, attrs, theme);
- currentGroup.mChildren.add(path);
+ currentGroup.addChild(path);
if (path.getPathName() != null) {
pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
}
@@ -681,7 +690,7 @@ public class VectorDrawable extends Drawable {
} else if (SHAPE_GROUP.equals(tagName)) {
VGroup newChildGroup = new VGroup();
newChildGroup.inflate(res, attrs, theme);
- currentGroup.mChildren.add(newChildGroup);
+ currentGroup.addChild(newChildGroup);
groupStack.push(newChildGroup);
if (newChildGroup.getGroupName() != null) {
pathRenderer.mVGTargetsMap.put(newChildGroup.getGroupName(),
@@ -700,7 +709,7 @@ public class VectorDrawable extends Drawable {
// Print the tree out for debug.
if (DBG_VECTOR_DRAWABLE) {
- printGroupTree(pathRenderer.mRootGroup, 0);
+ pathRenderer.printGroupTree();
}
if (noPathTag) {
@@ -715,24 +724,6 @@ public class VectorDrawable extends Drawable {
}
}
- private void printGroupTree(VGroup currentGroup, int level) {
- String indent = "";
- for (int i = 0; i < level; i++) {
- indent += " ";
- }
- // Print the current node
- Log.v(LOGTAG, indent + "current group is :" + currentGroup.getGroupName()
- + " rotation is " + currentGroup.mRotate);
- Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString());
- // Then print all the children groups
- for (int i = 0; i < currentGroup.mChildren.size(); i++) {
- final VObject child = currentGroup.mChildren.get(i);
- if (child instanceof VGroup) {
- printGroupTree((VGroup) child, level + 1);
- }
- }
- }
-
@Override
public int getChangingConfigurations() {
return super.getChangingConfigurations() | mVectorState.getChangingConfigurations();
@@ -890,6 +881,11 @@ public class VectorDrawable extends Drawable {
return mChangingConfigurations
| (mTint != null ? mTint.getChangingConfigurations() : 0);
}
+
+ public boolean isStateful() {
+ return (mTint != null && mTint.isStateful())
+ || (mVPathRenderer != null && mVPathRenderer.isStateful());
+ }
}
private static class VPathRenderer {
@@ -972,21 +968,35 @@ public class VectorDrawable extends Drawable {
mRootGroup.applyTheme(t);
}
+ public boolean onStateChange(int[] stateSet) {
+ return mRootGroup.onStateChange(stateSet);
+ }
+
+ public boolean isStateful() {
+ return mRootGroup.isStateful();
+ }
+
public void draw(Canvas canvas, int w, int h, ColorFilter filter) {
final float scaleX = w / mViewportWidth;
final float scaleY = h / mViewportHeight;
mRootGroup.draw(canvas, mTempState, Matrix.IDENTITY_MATRIX, filter, scaleX, scaleY);
}
+
+ public void printGroupTree() {
+ mRootGroup.printGroupTree("");
+ }
}
private static class VGroup implements VObject {
+ private static final String GROUP_INDENT = " ";
+
// mStackedMatrix is only used temporarily when drawing, it combines all
// the parents' local matrices with the current one.
private final Matrix mStackedMatrix = new Matrix();
/////////////////////////////////////////////////////
// Variables below need to be copied (deep copy if applicable) for mutation.
- final ArrayList<VObject> mChildren = new ArrayList<>();
+ private final ArrayList<VObject> mChildren = new ArrayList<>();
private float mRotate = 0;
private float mPivotX = 0;
@@ -995,6 +1005,7 @@ public class VectorDrawable extends Drawable {
private float mScaleY = 1;
private float mTranslateX = 0;
private float mTranslateY = 0;
+ private boolean mIsStateful;
// mLocalMatrix is updated based on the update of transformation information,
// either parsed from the XML or by animation.
@@ -1011,6 +1022,7 @@ public class VectorDrawable extends Drawable {
mScaleY = copy.mScaleY;
mTranslateX = copy.mTranslateX;
mTranslateY = copy.mTranslateY;
+ mIsStateful = copy.mIsStateful;
mThemeAttrs = copy.mThemeAttrs;
mGroupName = copy.mGroupName;
mChangingConfigurations = copy.mChangingConfigurations;
@@ -1054,6 +1066,12 @@ public class VectorDrawable extends Drawable {
return mLocalMatrix;
}
+ public void addChild(VObject child) {
+ mChildren.add(child);
+
+ mIsStateful |= child.isStateful();
+ }
+
@Override
public void draw(Canvas canvas, TempState temp, Matrix currentMatrix,
ColorFilter filter, float scaleX, float scaleY) {
@@ -1109,6 +1127,26 @@ public class VectorDrawable extends Drawable {
}
@Override
+ public boolean onStateChange(int[] stateSet) {
+ boolean changed = false;
+
+ final ArrayList<VObject> children = mChildren;
+ for (int i = 0, count = children.size(); i < count; i++) {
+ final VObject child = children.get(i);
+ if (child.isStateful()) {
+ changed |= child.onStateChange(stateSet);
+ }
+ }
+
+ return changed;
+ }
+
+ @Override
+ public boolean isStateful() {
+ return mIsStateful;
+ }
+
+ @Override
public boolean canApplyTheme() {
if (mThemeAttrs != null) {
return true;
@@ -1139,6 +1177,9 @@ public class VectorDrawable extends Drawable {
final VObject child = children.get(i);
if (child.canApplyTheme()) {
child.applyTheme(t);
+
+ // Applying a theme may have made the child stateful.
+ mIsStateful |= child.isStateful();
}
}
}
@@ -1153,6 +1194,24 @@ public class VectorDrawable extends Drawable {
mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
}
+ public void printGroupTree(String indent) {
+ Log.v(LOGTAG, indent + "group:" + getGroupName() + " rotation is " + mRotate);
+ Log.v(LOGTAG, indent + "matrix:" + getLocalMatrix().toString());
+
+ final int count = mChildren.size();
+ if (count > 0) {
+ indent += GROUP_INDENT;
+ }
+
+ // Then print all the children groups.
+ for (int i = 0; i < count; i++) {
+ final VObject child = mChildren.get(i);
+ if (child instanceof VGroup) {
+ ((VGroup) child).printGroupTree(indent);
+ }
+ }
+ }
+
/* Setters and Getters, used by animator from AnimatedVectorDrawable. */
@SuppressWarnings("unused")
public float getRotation() {
@@ -1398,6 +1457,16 @@ public class VectorDrawable extends Drawable {
// No-op.
}
+ @Override
+ public boolean onStateChange(int[] stateSet) {
+ return false;
+ }
+
+ @Override
+ public boolean isStateful() {
+ return false;
+ }
+
private void updateStateFromTypedArray(TypedArray a) {
// Account for any configuration changes.
mChangingConfigurations |= a.getChangingConfigurations();
@@ -1427,9 +1496,11 @@ public class VectorDrawable extends Drawable {
// Variables below need to be copied (deep copy if applicable) for mutation.
private int[] mThemeAttrs;
+ ColorStateList mStrokeColors = null;
int mStrokeColor = Color.TRANSPARENT;
float mStrokeWidth = 0;
+ ColorStateList mFillColors = null;
int mFillColor = Color.TRANSPARENT;
float mStrokeAlpha = 1.0f;
int mFillRule;
@@ -1448,11 +1519,14 @@ public class VectorDrawable extends Drawable {
public VFullPath(VFullPath copy) {
super(copy);
+
mThemeAttrs = copy.mThemeAttrs;
+ mStrokeColors = copy.mStrokeColors;
mStrokeColor = copy.mStrokeColor;
mStrokeWidth = copy.mStrokeWidth;
mStrokeAlpha = copy.mStrokeAlpha;
+ mFillColors = copy.mFillColors;
mFillColor = copy.mFillColor;
mFillRule = copy.mFillRule;
mFillAlpha = copy.mFillAlpha;
@@ -1492,6 +1566,31 @@ public class VectorDrawable extends Drawable {
}
@Override
+ public boolean onStateChange(int[] stateSet) {
+ boolean changed = false;
+
+ if (mStrokeColors != null && mStrokeColors.isStateful()) {
+ final int strokeColor = mStrokeColor;
+ mStrokeColor = mStrokeColors.getColorForState(stateSet, strokeColor);
+ changed |= strokeColor != mStrokeColor;
+ }
+
+ if (mFillColors != null && mFillColors.isStateful()) {
+ final int fillColor = mFillColor;
+ mFillColor = mFillColors.getColorForState(stateSet, fillColor);
+ changed |= fillColor != mFillColor;
+ }
+
+ return changed;
+ }
+
+ @Override
+ public boolean isStateful() {
+ return mStrokeColors != null && mStrokeColors.isStateful()
+ || mFillColors != null && mFillColors.isStateful();
+ }
+
+ @Override
public void toPath(TempState temp, Path path) {
super.toPath(temp, path);
@@ -1614,8 +1713,20 @@ public class VectorDrawable extends Drawable {
mNodes = PathParser.createNodesFromPathData(pathData);
}
- mFillColor = a.getColor(R.styleable.VectorDrawablePath_fillColor,
- mFillColor);
+ final ColorStateList fillColors = a.getColorStateList(
+ R.styleable.VectorDrawablePath_fillColor);
+ if (fillColors != null) {
+ mFillColors = fillColors;
+ mFillColor = fillColors.getDefaultColor();
+ }
+
+ final ColorStateList strokeColors = a.getColorStateList(
+ R.styleable.VectorDrawablePath_strokeColor);
+ if (strokeColors != null) {
+ mStrokeColors = strokeColors;
+ mStrokeColor = strokeColors.getDefaultColor();
+ }
+
mFillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha,
mFillAlpha);
mStrokeLineCap = getStrokeLineCap(a.getInt(
@@ -1624,8 +1735,6 @@ public class VectorDrawable extends Drawable {
R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin);
mStrokeMiterlimit = a.getFloat(
R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
- mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_strokeColor,
- mStrokeColor);
mStrokeAlpha = a.getFloat(R.styleable.VectorDrawablePath_strokeAlpha,
mStrokeAlpha);
mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth,
@@ -1662,6 +1771,7 @@ public class VectorDrawable extends Drawable {
@SuppressWarnings("unused")
void setStrokeColor(int strokeColor) {
+ mStrokeColors = null;
mStrokeColor = strokeColor;
}
@@ -1692,6 +1802,7 @@ public class VectorDrawable extends Drawable {
@SuppressWarnings("unused")
void setFillColor(int fillColor) {
+ mFillColors = null;
mFillColor = fillColor;
}
@@ -1752,5 +1863,7 @@ public class VectorDrawable extends Drawable {
void inflate(Resources r, AttributeSet attrs, Theme theme);
boolean canApplyTheme();
void applyTheme(Theme t);
+ boolean onStateChange(int[] state);
+ boolean isStateful();
}
}
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 3eb13ab9a72d..cc0943f52fdb 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -24,6 +24,7 @@ hwui_src_files := \
utils/GLUtils.cpp \
utils/LinearAllocator.cpp \
utils/NinePatchImpl.cpp \
+ utils/StringUtils.cpp \
AmbientShadow.cpp \
AnimationContext.cpp \
Animator.cpp \
@@ -168,7 +169,8 @@ LOCAL_SRC_FILES += \
unit_tests/CanvasStateTests.cpp \
unit_tests/ClipAreaTests.cpp \
unit_tests/DamageAccumulatorTests.cpp \
- unit_tests/LinearAllocatorTests.cpp
+ unit_tests/LinearAllocatorTests.cpp \
+ unit_tests/StringUtilsTests.cpp
include $(BUILD_NATIVE_TEST)
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index ff713133e389..7c63e316ba38 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -54,7 +54,6 @@ Caches::Caches(RenderState& renderState)
, mInitialized(false) {
INIT_LOGD("Creating OpenGL renderer caches");
init();
- initFont();
initConstraints();
initStaticProperties();
initExtensions();
@@ -78,10 +77,6 @@ bool Caches::init() {
return true;
}
-void Caches::initFont() {
- fontRenderer = GammaFontRenderer::createRenderer();
-}
-
void Caches::initExtensions() {
if (mExtensions.hasDebugMarker()) {
eventMark = glInsertEventMarkerEXT;
@@ -100,15 +95,9 @@ void Caches::initConstraints() {
}
void Caches::initStaticProperties() {
- gpuPixelBuffersEnabled = false;
-
// OpenGL ES 3.0+ specific features
- if (mExtensions.hasPixelBufferObjects()) {
- char property[PROPERTY_VALUE_MAX];
- if (property_get(PROPERTY_ENABLE_GPU_PIXEL_BUFFERS, property, "true") > 0) {
- gpuPixelBuffersEnabled = !strcmp(property, "true");
- }
- }
+ gpuPixelBuffersEnabled = mExtensions.hasPixelBufferObjects()
+ && property_get_bool(PROPERTY_ENABLE_GPU_PIXEL_BUFFERS, true);
}
void Caches::terminate() {
@@ -203,14 +192,14 @@ void Caches::dumpMemoryUsage(String8 &log) {
dropShadowCache.getMaxSize());
log.appendFormat(" PatchCache %8d / %8d\n",
patchCache.getSize(), patchCache.getMaxSize());
- for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) {
- const uint32_t sizeA8 = fontRenderer->getFontRendererSize(i, GL_ALPHA);
- const uint32_t sizeRGBA = fontRenderer->getFontRendererSize(i, GL_RGBA);
- log.appendFormat(" FontRenderer %d A8 %8d / %8d\n", i, sizeA8, sizeA8);
- log.appendFormat(" FontRenderer %d RGBA %8d / %8d\n", i, sizeRGBA, sizeRGBA);
- log.appendFormat(" FontRenderer %d total %8d / %8d\n", i, sizeA8 + sizeRGBA,
- sizeA8 + sizeRGBA);
- }
+
+ const uint32_t sizeA8 = fontRenderer.getFontRendererSize(GL_ALPHA);
+ const uint32_t sizeRGBA = fontRenderer.getFontRendererSize(GL_RGBA);
+ log.appendFormat(" FontRenderer A8 %8d / %8d\n", sizeA8, sizeA8);
+ log.appendFormat(" FontRenderer RGBA %8d / %8d\n", sizeRGBA, sizeRGBA);
+ log.appendFormat(" FontRenderer total %8d / %8d\n", sizeA8 + sizeRGBA,
+ sizeA8 + sizeRGBA);
+
log.appendFormat("Other:\n");
log.appendFormat(" FboCache %8d / %8d\n",
fboCache.getSize(), fboCache.getMaxSize());
@@ -222,10 +211,8 @@ void Caches::dumpMemoryUsage(String8 &log) {
total += tessellationCache.getSize();
total += dropShadowCache.getSize();
total += patchCache.getSize();
- for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) {
- total += fontRenderer->getFontRendererSize(i, GL_ALPHA);
- total += fontRenderer->getFontRendererSize(i, GL_RGBA);
- }
+ total += fontRenderer.getFontRendererSize(GL_ALPHA);
+ total += fontRenderer.getFontRendererSize(GL_RGBA);
log.appendFormat("Total memory usage:\n");
log.appendFormat(" %d bytes, %.2f MB\n", total, total / 1024.0f / 1024.0f);
@@ -250,12 +237,12 @@ void Caches::flush(FlushMode mode) {
patchCache.clear();
dropShadowCache.clear();
gradientCache.clear();
- fontRenderer->clear();
+ fontRenderer.clear();
fboCache.clear();
dither.clear();
// fall through
case FlushMode::Moderate:
- fontRenderer->flush();
+ fontRenderer.flush();
textureCache.flush();
pathCache.clear();
tessellationCache.clear();
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 929db17a22a8..61e958d42148 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -21,6 +21,7 @@
#include "Dither.h"
#include "Extensions.h"
#include "FboCache.h"
+#include "GammaFontRenderer.h"
#include "GradientCache.h"
#include "LayerCache.h"
#include "PatchCache.h"
@@ -53,8 +54,6 @@
namespace android {
namespace uirenderer {
-class GammaFontRenderer;
-
///////////////////////////////////////////////////////////////////////////////
// Caches
///////////////////////////////////////////////////////////////////////////////
@@ -156,7 +155,7 @@ public:
TextDropShadowCache dropShadowCache;
FboCache fboCache;
- GammaFontRenderer* fontRenderer;
+ GammaFontRenderer fontRenderer;
TaskManager tasks;
@@ -178,8 +177,6 @@ public:
TextureState& textureState() { return *mTextureState; }
private:
-
- void initFont();
void initExtensions();
void initConstraints();
void initStaticProperties();
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index 5808aaca76be..e98fa0440591 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -20,9 +20,6 @@
// Turn on to check for OpenGL errors on each frame
#define DEBUG_OPENGL 1
-// Turn on to display informations about the GPU
-#define DEBUG_EXTENSIONS 0
-
// Turn on to enable initialization information
#define DEBUG_INIT 0
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 9fb1e756c00d..a81ffb9f59fa 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -631,7 +631,7 @@ static void replayBatchList(const std::vector<Batch*>& batchList,
void DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty) {
ATRACE_NAME("flush drawing commands");
- Caches::getInstance().fontRenderer->endPrecaching();
+ Caches::getInstance().fontRenderer.endPrecaching();
if (isEmpty()) return; // nothing to flush
renderer.restoreToCount(1);
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 14126a9e31a7..dc5cb8b349f1 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1246,7 +1246,7 @@ public:
virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
const DeferredDisplayState& state) override {
- FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(mPaint);
+ FontRenderer& fontRenderer = renderer.getCaches().fontRenderer.getFontRenderer();
fontRenderer.precache(mPaint, mText, mCount, SkMatrix::I());
deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
@@ -1311,7 +1311,7 @@ public:
virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
const DeferredDisplayState& state) override {
- FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(mPaint);
+ FontRenderer& fontRenderer = renderer.getCaches().fontRenderer.getFontRenderer();
SkMatrix transform;
renderer.findBestFontTransform(state.mMatrix, &transform);
if (mPrecacheTransform != transform) {
diff --git a/libs/hwui/Extensions.cpp b/libs/hwui/Extensions.cpp
index 3d350c98892b..06c8a21b019b 100644
--- a/libs/hwui/Extensions.cpp
+++ b/libs/hwui/Extensions.cpp
@@ -18,23 +18,14 @@
#include "Debug.h"
#include "Properties.h"
+#include "utils/StringUtils.h"
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
#include <GLES2/gl2ext.h>
#include <utils/Log.h>
namespace android {
-
-using namespace uirenderer;
-ANDROID_SINGLETON_STATIC_INSTANCE(Extensions);
-
namespace uirenderer {
-///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
// Debug
#if DEBUG_EXTENSIONS
#define EXT_LOGD(...) ALOGD(__VA_ARGS__)
@@ -42,20 +33,16 @@ namespace uirenderer {
#define EXT_LOGD(...)
#endif
-///////////////////////////////////////////////////////////////////////////////
-// Constructors
-///////////////////////////////////////////////////////////////////////////////
Extensions::Extensions() {
- // Query GL extensions
- findExtensions((const char*) glGetString(GL_EXTENSIONS), mGlExtensionList);
- mHasNPot = hasGlExtension("GL_OES_texture_npot");
- mHasFramebufferFetch = hasGlExtension("GL_NV_shader_framebuffer_fetch");
- mHasDiscardFramebuffer = hasGlExtension("GL_EXT_discard_framebuffer");
- mHasDebugMarker = hasGlExtension("GL_EXT_debug_marker");
- mHas1BitStencil = hasGlExtension("GL_OES_stencil1");
- mHas4BitStencil = hasGlExtension("GL_OES_stencil4");
- mHasUnpackSubImage = hasGlExtension("GL_EXT_unpack_subimage");
+ StringCollection extensions((const char*) glGetString(GL_EXTENSIONS));
+ mHasNPot = extensions.has("GL_OES_texture_npot");
+ mHasFramebufferFetch = extensions.has("GL_NV_shader_framebuffer_fetch");
+ mHasDiscardFramebuffer = extensions.has("GL_EXT_discard_framebuffer");
+ mHasDebugMarker = extensions.has("GL_EXT_debug_marker");
+ mHas1BitStencil = extensions.has("GL_OES_stencil1");
+ mHas4BitStencil = extensions.has("GL_OES_stencil4");
+ mHasUnpackSubImage = extensions.has("GL_EXT_unpack_subimage");
const char* version = (const char*) glGetString(GL_VERSION);
@@ -78,40 +65,5 @@ Extensions::Extensions() {
}
}
-///////////////////////////////////////////////////////////////////////////////
-// Methods
-///////////////////////////////////////////////////////////////////////////////
-
-bool Extensions::hasGlExtension(const char* extension) const {
- const String8 s(extension);
- return mGlExtensionList.indexOf(s) >= 0;
-}
-
-bool Extensions::hasEglExtension(const char* extension) const {
- const String8 s(extension);
- return mEglExtensionList.indexOf(s) >= 0;
-}
-
-void Extensions::findExtensions(const char* extensions, SortedVector<String8>& list) const {
- const char* current = extensions;
- const char* head = current;
- EXT_LOGD("Available extensions:");
- do {
- head = strchr(current, ' ');
- String8 s(current, head ? head - current : strlen(current));
- if (s.length()) {
- list.add(s);
- EXT_LOGD(" %s", s.string());
- }
- current = head + 1;
- } while (head);
-}
-
-void Extensions::dump() const {
- ALOGD("%s", (const char*) glGetString(GL_VERSION));
- ALOGD("Supported GL extensions:\n%s", (const char*) glGetString(GL_EXTENSIONS));
- ALOGD("Supported EGL extensions:\n%s", eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS));
-}
-
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h
index 636b631532bf..0a30d162f2e8 100644
--- a/libs/hwui/Extensions.h
+++ b/libs/hwui/Extensions.h
@@ -50,17 +50,7 @@ public:
inline int getMajorGlVersion() const { return mVersionMajor; }
inline int getMinorGlVersion() const { return mVersionMinor; }
- bool hasGlExtension(const char* extension) const;
- bool hasEglExtension(const char* extension) const;
-
- void dump() const;
-
private:
- void findExtensions(const char* extensions, SortedVector<String8>& list) const;
-
- SortedVector<String8> mGlExtensionList;
- SortedVector<String8> mEglExtensionList;
-
bool mHasNPot;
bool mHasFramebufferFetch;
bool mHasDiscardFramebuffer;
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 75c3ead68f7b..4b9d4f90675c 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -75,8 +75,8 @@ void TextDrawFunctor::draw(CacheTexture& texture, bool linearFiltering) {
static bool sLogFontRendererCreate = true;
-FontRenderer::FontRenderer()
- : mGammaTable(nullptr)
+FontRenderer::FontRenderer(const uint8_t* gammaTable)
+ : mGammaTable(gammaTable)
, mCurrentFont(nullptr)
, mActiveFonts(LruCache<Font::FontDescription, Font*>::kUnlimitedCapacity)
, mCurrentCacheTexture(nullptr)
@@ -92,27 +92,15 @@ FontRenderer::FontRenderer()
INIT_LOGD("Creating FontRenderer");
}
- mSmallCacheWidth = DEFAULT_TEXT_SMALL_CACHE_WIDTH;
- mSmallCacheHeight = DEFAULT_TEXT_SMALL_CACHE_HEIGHT;
- mLargeCacheWidth = DEFAULT_TEXT_LARGE_CACHE_WIDTH;
- mLargeCacheHeight = DEFAULT_TEXT_LARGE_CACHE_HEIGHT;
+ mSmallCacheWidth = property_get_int32(PROPERTY_TEXT_SMALL_CACHE_WIDTH,
+ DEFAULT_TEXT_SMALL_CACHE_WIDTH);
+ mSmallCacheHeight = property_get_int32(PROPERTY_TEXT_SMALL_CACHE_HEIGHT,
+ DEFAULT_TEXT_SMALL_CACHE_HEIGHT);
- char property[PROPERTY_VALUE_MAX];
- if (property_get(PROPERTY_TEXT_SMALL_CACHE_WIDTH, property, nullptr) > 0) {
- mSmallCacheWidth = atoi(property);
- }
-
- if (property_get(PROPERTY_TEXT_SMALL_CACHE_HEIGHT, property, nullptr) > 0) {
- mSmallCacheHeight = atoi(property);
- }
-
- if (property_get(PROPERTY_TEXT_LARGE_CACHE_WIDTH, property, nullptr) > 0) {
- mLargeCacheWidth = atoi(property);
- }
-
- if (property_get(PROPERTY_TEXT_LARGE_CACHE_HEIGHT, property, nullptr) > 0) {
- mLargeCacheHeight = atoi(property);
- }
+ mLargeCacheWidth = property_get_int32(PROPERTY_TEXT_LARGE_CACHE_WIDTH,
+ DEFAULT_TEXT_LARGE_CACHE_WIDTH);
+ mLargeCacheHeight = property_get_int32(PROPERTY_TEXT_LARGE_CACHE_HEIGHT,
+ DEFAULT_TEXT_LARGE_CACHE_HEIGHT);
uint32_t maxTextureSize = (uint32_t) Caches::getInstance().maxTextureSize;
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 2954975b1413..936c838bd6e4 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -72,16 +72,12 @@ public:
class FontRenderer {
public:
- FontRenderer();
+ FontRenderer(const uint8_t* gammaTable);
~FontRenderer();
void flushLargeCaches(std::vector<CacheTexture*>& cacheTextures);
void flushLargeCaches();
- void setGammaTable(const uint8_t* gammaTable) {
- mGammaTable = gammaTable;
- }
-
void setFont(const SkPaint* paint, const SkMatrix& matrix);
void precache(const SkPaint* paint, const char* text, int numGlyphs, const SkMatrix& matrix);
diff --git a/libs/hwui/GammaFontRenderer.cpp b/libs/hwui/GammaFontRenderer.cpp
index 0bcd83a1a050..96cac86386b5 100644
--- a/libs/hwui/GammaFontRenderer.cpp
+++ b/libs/hwui/GammaFontRenderer.cpp
@@ -21,231 +21,22 @@
namespace android {
namespace uirenderer {
-///////////////////////////////////////////////////////////////////////////////
-// Utils
-///////////////////////////////////////////////////////////////////////////////
-
-static int luminance(const SkPaint* paint) {
- uint32_t c = paint->getColor();
- const int r = (c >> 16) & 0xFF;
- const int g = (c >> 8) & 0xFF;
- const int b = (c ) & 0xFF;
- return (r * 2 + g * 5 + b) >> 3;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Base class GammaFontRenderer
-///////////////////////////////////////////////////////////////////////////////
-
-GammaFontRenderer* GammaFontRenderer::createRenderer() {
- // Choose the best renderer
- char property[PROPERTY_VALUE_MAX];
- if (property_get(PROPERTY_TEXT_GAMMA_METHOD, property, DEFAULT_TEXT_GAMMA_METHOD) > 0) {
- if (!strcasecmp(property, "lookup")) {
- return new LookupGammaFontRenderer();
- } else if (!strcasecmp(property, "shader")) {
- return new ShaderGammaFontRenderer(false);
- } else if (!strcasecmp(property, "shader3")) {
- return new ShaderGammaFontRenderer(true);
- }
- }
-
- return new Lookup3GammaFontRenderer();
-}
-
GammaFontRenderer::GammaFontRenderer() {
- // Get the renderer properties
- char property[PROPERTY_VALUE_MAX];
-
- // Get the gamma
- mGamma = DEFAULT_TEXT_GAMMA;
- if (property_get(PROPERTY_TEXT_GAMMA, property, nullptr) > 0) {
- INIT_LOGD(" Setting text gamma to %s", property);
- mGamma = atof(property);
- } else {
- INIT_LOGD(" Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA);
- }
-
- // Get the black gamma threshold
- mBlackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD;
- if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, nullptr) > 0) {
- INIT_LOGD(" Setting text black gamma threshold to %s", property);
- mBlackThreshold = atoi(property);
- } else {
- INIT_LOGD(" Using default text black gamma threshold of %d",
- DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD);
- }
-
- // Get the white gamma threshold
- mWhiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD;
- if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, nullptr) > 0) {
- INIT_LOGD(" Setting text white gamma threshold to %s", property);
- mWhiteThreshold = atoi(property);
- } else {
- INIT_LOGD(" Using default white black gamma threshold of %d",
- DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD);
- }
-}
-
-GammaFontRenderer::~GammaFontRenderer() {
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Shader-based renderer
-///////////////////////////////////////////////////////////////////////////////
-
-ShaderGammaFontRenderer::ShaderGammaFontRenderer(bool multiGamma)
- : GammaFontRenderer() {
- INIT_LOGD("Creating shader gamma font renderer");
- mRenderer = nullptr;
- mMultiGamma = multiGamma;
-}
-
-void ShaderGammaFontRenderer::describe(ProgramDescription& description,
- const SkPaint* paint) const {
- if (paint->getShader() == nullptr) {
- if (mMultiGamma) {
- const int l = luminance(paint);
-
- if (l <= mBlackThreshold) {
- description.hasGammaCorrection = true;
- description.gamma = mGamma;
- } else if (l >= mWhiteThreshold) {
- description.hasGammaCorrection = true;
- description.gamma = 1.0f / mGamma;
- }
- } else {
- description.hasGammaCorrection = true;
- description.gamma = 1.0f / mGamma;
- }
- }
-}
-
-void ShaderGammaFontRenderer::setupProgram(ProgramDescription& description,
- Program& program) const {
- if (description.hasGammaCorrection) {
- glUniform1f(program.getUniform("gamma"), description.gamma);
- }
-}
-
-void ShaderGammaFontRenderer::endPrecaching() {
- if (mRenderer) {
- mRenderer->endPrecaching();
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Lookup-based renderer
-///////////////////////////////////////////////////////////////////////////////
-
-LookupGammaFontRenderer::LookupGammaFontRenderer()
- : GammaFontRenderer() {
INIT_LOGD("Creating lookup gamma font renderer");
// Compute the gamma tables
- const float gamma = 1.0f / mGamma;
+ const float gamma = 1.0f / Properties::textGamma;
for (uint32_t i = 0; i <= 255; i++) {
mGammaTable[i] = uint8_t((float)::floor(pow(i / 255.0f, gamma) * 255.0f + 0.5f));
}
-
- mRenderer = nullptr;
}
-void LookupGammaFontRenderer::endPrecaching() {
+void GammaFontRenderer::endPrecaching() {
if (mRenderer) {
mRenderer->endPrecaching();
}
}
-///////////////////////////////////////////////////////////////////////////////
-// Lookup-based renderer, using 3 different correction tables
-///////////////////////////////////////////////////////////////////////////////
-
-Lookup3GammaFontRenderer::Lookup3GammaFontRenderer()
- : GammaFontRenderer() {
- INIT_LOGD("Creating lookup3 gamma font renderer");
-
- // Compute the gamma tables
- const float blackGamma = mGamma;
- const float whiteGamma = 1.0f / mGamma;
-
- for (uint32_t i = 0; i <= 255; i++) {
- const float v = i / 255.0f;
- const float black = pow(v, blackGamma);
- const float white = pow(v, whiteGamma);
-
- mGammaTable[i] = i;
- mGammaTable[256 + i] = uint8_t((float)::floor(black * 255.0f + 0.5f));
- mGammaTable[512 + i] = uint8_t((float)::floor(white * 255.0f + 0.5f));
- }
-
- memset(mRenderers, 0, sizeof(FontRenderer*) * kGammaCount);
- memset(mRenderersUsageCount, 0, sizeof(uint32_t) * kGammaCount);
-}
-
-void Lookup3GammaFontRenderer::endPrecaching() {
- for (int i = 0; i < kGammaCount; i++) {
- if (mRenderers[i]) {
- mRenderers[i]->endPrecaching();
- }
- }
-}
-
-void Lookup3GammaFontRenderer::clear() {
- for (int i = 0; i < kGammaCount; i++) {
- mRenderers[i].release();
- }
-}
-
-void Lookup3GammaFontRenderer::flush() {
- int count = 0;
- int min = -1;
- uint32_t minCount = UINT_MAX;
-
- for (int i = 0; i < kGammaCount; i++) {
- if (mRenderers[i]) {
- count++;
- if (mRenderersUsageCount[i] < minCount) {
- minCount = mRenderersUsageCount[i];
- min = i;
- }
- }
- }
-
- if (count <= 1 || min < 0) return;
-
- mRenderers[min].release();
-
- // Also eliminate the caches for large glyphs, as they consume significant memory
- for (int i = 0; i < kGammaCount; ++i) {
- if (mRenderers[i]) {
- mRenderers[i]->flushLargeCaches();
- }
- }
-}
-
-FontRenderer* Lookup3GammaFontRenderer::getRenderer(Gamma gamma) {
- if (!mRenderers[gamma]) {
- mRenderers[gamma].reset(new FontRenderer());
- mRenderers[gamma]->setGammaTable(&mGammaTable[gamma * 256]);
- }
- mRenderersUsageCount[gamma]++;
- return mRenderers[gamma].get();
-}
-
-FontRenderer& Lookup3GammaFontRenderer::getFontRenderer(const SkPaint* paint) {
- if (paint->getShader() == nullptr) {
- const int l = luminance(paint);
-
- if (l <= mBlackThreshold) {
- return *getRenderer(kGammaBlack);
- } else if (l >= mWhiteThreshold) {
- return *getRenderer(kGammaWhite);
- }
- }
- return *getRenderer(kGammaDefault);
-}
-
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h
index ca55bf1e74e0..146d385e1173 100644
--- a/libs/hwui/GammaFontRenderer.h
+++ b/libs/hwui/GammaFontRenderer.h
@@ -17,183 +17,44 @@
#ifndef ANDROID_HWUI_GAMMA_FONT_RENDERER_H
#define ANDROID_HWUI_GAMMA_FONT_RENDERER_H
-#include <SkPaint.h>
-
#include "FontRenderer.h"
#include "Program.h"
+#include <SkPaint.h>
+
namespace android {
namespace uirenderer {
class GammaFontRenderer {
public:
- virtual ~GammaFontRenderer();
-
- virtual void clear() = 0;
- virtual void flush() = 0;
-
- virtual FontRenderer& getFontRenderer(const SkPaint* paint) = 0;
-
- virtual uint32_t getFontRendererCount() const = 0;
- virtual uint32_t getFontRendererSize(uint32_t fontRenderer, GLenum format) const = 0;
-
- virtual void describe(ProgramDescription& description, const SkPaint* paint) const = 0;
- virtual void setupProgram(ProgramDescription& description, Program& program) const = 0;
-
- virtual void endPrecaching() = 0;
-
- static GammaFontRenderer* createRenderer();
-
-protected:
GammaFontRenderer();
- int mBlackThreshold;
- int mWhiteThreshold;
-
- float mGamma;
-};
-
-class ShaderGammaFontRenderer: public GammaFontRenderer {
-public:
- ~ShaderGammaFontRenderer() {
- delete mRenderer;
- }
-
- void clear() override {
- delete mRenderer;
- mRenderer = nullptr;
- }
-
- void flush() override {
- if (mRenderer) {
- mRenderer->flushLargeCaches();
- }
- }
-
- FontRenderer& getFontRenderer(const SkPaint* paint) override {
- if (!mRenderer) {
- mRenderer = new FontRenderer;
- }
- return *mRenderer;
- }
-
- uint32_t getFontRendererCount() const override {
- return 1;
- }
-
- uint32_t getFontRendererSize(uint32_t fontRenderer, GLenum format) const override {
- return mRenderer ? mRenderer->getCacheSize(format) : 0;
- }
-
- void describe(ProgramDescription& description, const SkPaint* paint) const override;
- void setupProgram(ProgramDescription& description, Program& program) const override;
-
- void endPrecaching() override;
-
-private:
- ShaderGammaFontRenderer(bool multiGamma);
-
- FontRenderer* mRenderer;
- bool mMultiGamma;
-
- friend class GammaFontRenderer;
-};
-
-class LookupGammaFontRenderer: public GammaFontRenderer {
-public:
- ~LookupGammaFontRenderer() {
- delete mRenderer;
- }
-
- void clear() override {
- delete mRenderer;
- mRenderer = nullptr;
+ void clear() {
+ mRenderer.release();
}
- void flush() override {
+ void flush() {
if (mRenderer) {
mRenderer->flushLargeCaches();
}
}
- FontRenderer& getFontRenderer(const SkPaint* paint) override {
+ FontRenderer& getFontRenderer() {
if (!mRenderer) {
- mRenderer = new FontRenderer;
- mRenderer->setGammaTable(&mGammaTable[0]);
+ mRenderer.reset(new FontRenderer(&mGammaTable[0]));
}
return *mRenderer;
}
- uint32_t getFontRendererCount() const override {
- return 1;
- }
-
- uint32_t getFontRendererSize(uint32_t fontRenderer, GLenum format) const override {
+ uint32_t getFontRendererSize(GLenum format) const {
return mRenderer ? mRenderer->getCacheSize(format) : 0;
}
- void describe(ProgramDescription& description, const SkPaint* paint) const override {
- }
-
- void setupProgram(ProgramDescription& description, Program& program) const override {
- }
-
- void endPrecaching() override;
+ void endPrecaching();
private:
- LookupGammaFontRenderer();
-
- FontRenderer* mRenderer;
+ std::unique_ptr<FontRenderer> mRenderer;
uint8_t mGammaTable[256];
-
- friend class GammaFontRenderer;
-};
-
-class Lookup3GammaFontRenderer: public GammaFontRenderer {
-public:
- void clear() override;
- void flush() override;
-
- FontRenderer& getFontRenderer(const SkPaint* paint) override;
-
- uint32_t getFontRendererCount() const override {
- return kGammaCount;
- }
-
- uint32_t getFontRendererSize(uint32_t fontRenderer, GLenum format) const override {
- if (fontRenderer >= kGammaCount) return 0;
-
- if (!mRenderers[fontRenderer]) return 0;
-
- return mRenderers[fontRenderer]->getCacheSize(format);
- }
-
- void describe(ProgramDescription& description, const SkPaint* paint) const override {
- }
-
- void setupProgram(ProgramDescription& description, Program& program) const override {
- }
-
- void endPrecaching() override;
-
-private:
- Lookup3GammaFontRenderer();
-
- enum Gamma {
- kGammaDefault = 0,
- kGammaBlack = 1,
- kGammaWhite = 2,
- kGammaCount = 3
- };
-
- FontRenderer* getRenderer(Gamma gamma);
-
- uint32_t mRenderersUsageCount[kGammaCount];
- std::unique_ptr<FontRenderer> mRenderers[kGammaCount];
-
- uint8_t mGammaTable[256 * kGammaCount];
-
- friend class GammaFontRenderer;
};
}; // namespace uirenderer
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index e27b26b1d091..69559a77c3a0 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -435,7 +435,6 @@ GlopBuilder& GlopBuilder::setFillLayer(Texture& texture, const SkColorFilter* co
mOutGlop->fill.texture = { &texture,
GL_TEXTURE_2D, GL_LINEAR, GL_CLAMP_TO_EDGE, nullptr };
- mOutGlop->fill.color = { alpha, alpha, alpha, alpha };
setFill(SK_ColorWHITE, alpha, mode, modeUsage, nullptr, colorFilter);
@@ -449,7 +448,6 @@ GlopBuilder& GlopBuilder::setFillTextureLayer(Layer& layer, float alpha) {
mOutGlop->fill.texture = { &(layer.getTexture()),
layer.getRenderTarget(), GL_LINEAR, GL_CLAMP_TO_EDGE, &layer.getTexTransform() };
- mOutGlop->fill.color = { alpha, alpha, alpha, alpha };
setFill(SK_ColorWHITE, alpha, layer.getMode(), Blend::ModeOrderSwap::NoSwap,
nullptr, layer.getColorFilter());
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index e06e34849a91..a401ce119021 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2014,7 +2014,7 @@ void OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count,
y = floorf(y + currentTransform()->getTranslateY() + 0.5f);
}
- FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
+ FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer();
fontRenderer.setFont(paint, SkMatrix::I());
int alpha;
@@ -2166,7 +2166,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
- FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
+ FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer();
if (CC_UNLIKELY(hasTextShadow(paint))) {
fontRenderer.setFont(paint, SkMatrix::I());
@@ -2234,7 +2234,7 @@ void OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
// TODO: avoid scissor by calculating maximum bounds using path bounds + font metrics
mRenderState.scissor().setEnabled(true);
- FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
+ FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer();
fontRenderer.setFont(paint, SkMatrix::I());
fontRenderer.setTextureFiltering(true);
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index f503e5d6e8ba..4031f2e13f39 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -138,10 +138,10 @@ PathCache::PathCache():
mSize(0), mMaxSize(MB(DEFAULT_PATH_CACHE_SIZE)) {
char property[PROPERTY_VALUE_MAX];
if (property_get(PROPERTY_PATH_CACHE_SIZE, property, nullptr) > 0) {
- INIT_LOGD(" Setting %s cache size to %sMB", name, property);
+ INIT_LOGD(" Setting path cache size to %sMB", property);
mMaxSize = MB(atof(property));
} else {
- INIT_LOGD(" Using default %s cache size of %.2fMB", name, DEFAULT_PATH_CACHE_SIZE);
+ INIT_LOGD(" Using default path cache size of %.2fMB", DEFAULT_PATH_CACHE_SIZE);
}
mCache.setOnEntryRemovedListener(this);
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index b09c207f6e45..e5200a516777 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -78,14 +78,12 @@ namespace uirenderer {
#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
#define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39
-#define PROGRAM_HAS_GAMMA_CORRECTION 40
+#define PROGRAM_IS_SIMPLE_GRADIENT 40
-#define PROGRAM_IS_SIMPLE_GRADIENT 41
+#define PROGRAM_HAS_COLORS 41
-#define PROGRAM_HAS_COLORS 42
-
-#define PROGRAM_HAS_DEBUG_HIGHLIGHT 43
-#define PROGRAM_HAS_ROUND_RECT_CLIP 44
+#define PROGRAM_HAS_DEBUG_HIGHLIGHT 42
+#define PROGRAM_HAS_ROUND_RECT_CLIP 43
///////////////////////////////////////////////////////////////////////////////
// Types
@@ -157,9 +155,6 @@ struct ProgramDescription {
SkXfermode::Mode framebufferMode;
bool swapSrcDst;
- bool hasGammaCorrection;
- float gamma;
-
bool hasDebugHighlight;
bool hasRoundRectClip;
@@ -199,9 +194,6 @@ struct ProgramDescription {
framebufferMode = SkXfermode::kClear_Mode;
swapSrcDst = false;
- hasGammaCorrection = false;
- gamma = 2.2f;
-
hasDebugHighlight = false;
hasRoundRectClip = false;
}
@@ -266,7 +258,6 @@ struct ProgramDescription {
if (useShadowAlphaInterp) key |= programid(0x1) << PROGRAM_USE_SHADOW_ALPHA_INTERP_SHIFT;
if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
- if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION;
if (isSimpleGradient) key |= programid(0x1) << PROGRAM_IS_SIMPLE_GRADIENT;
if (hasColors) key |= programid(0x1) << PROGRAM_HAS_COLORS;
if (hasDebugHighlight) key |= programid(0x1) << PROGRAM_HAS_DEBUG_HIGHLIGHT;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index b25a4ac9558d..05be48822fb2 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -167,8 +167,6 @@ const char* gFS_Uniforms_ColorOp[3] = {
// PorterDuff
"uniform vec4 colorBlend;\n"
};
-const char* gFS_Uniforms_Gamma =
- "uniform float gamma;\n";
const char* gFS_Uniforms_HasRoundRectClip =
"uniform vec4 roundRectInnerRectLTRB;\n"
@@ -204,18 +202,10 @@ const char* gFS_Fast_SingleA8Texture =
"\nvoid main(void) {\n"
" gl_FragColor = texture2D(baseSampler, outTexCoords);\n"
"}\n\n";
-const char* gFS_Fast_SingleA8Texture_ApplyGamma =
- "\nvoid main(void) {\n"
- " gl_FragColor = vec4(0.0, 0.0, 0.0, pow(texture2D(baseSampler, outTexCoords).a, gamma));\n"
- "}\n\n";
const char* gFS_Fast_SingleModulateA8Texture =
"\nvoid main(void) {\n"
" gl_FragColor = color * texture2D(baseSampler, outTexCoords).a;\n"
"}\n\n";
-const char* gFS_Fast_SingleModulateA8Texture_ApplyGamma =
- "\nvoid main(void) {\n"
- " gl_FragColor = color * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n"
- "}\n\n";
const char* gFS_Fast_SingleGradient[2] = {
"\nvoid main(void) {\n"
" gl_FragColor = %s + texture2D(gradientSampler, linear);\n"
@@ -250,13 +240,11 @@ const char* gFS_Main_FetchTexture[2] = {
// Modulate
" fragColor = color * texture2D(baseSampler, outTexCoords);\n"
};
-const char* gFS_Main_FetchA8Texture[4] = {
+const char* gFS_Main_FetchA8Texture[2] = {
// Don't modulate
" fragColor = texture2D(baseSampler, outTexCoords);\n",
- " fragColor = texture2D(baseSampler, outTexCoords);\n",
// Modulate
" fragColor = color * texture2D(baseSampler, outTexCoords).a;\n",
- " fragColor = color * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n"
};
const char* gFS_Main_FetchGradient[6] = {
// Linear
@@ -284,38 +272,29 @@ const char* gFS_Main_BlendShadersBG =
" fragColor = blendShaders(gradientColor, bitmapColor)";
const char* gFS_Main_BlendShadersGB =
" fragColor = blendShaders(bitmapColor, gradientColor)";
-const char* gFS_Main_BlendShaders_Modulate[6] = {
+const char* gFS_Main_BlendShaders_Modulate[3] = {
// Don't modulate
";\n",
- ";\n",
// Modulate
" * color.a;\n",
- " * color.a;\n",
// Modulate with alpha 8 texture
" * texture2D(baseSampler, outTexCoords).a;\n",
- " * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n"
};
-const char* gFS_Main_GradientShader_Modulate[6] = {
+const char* gFS_Main_GradientShader_Modulate[3] = {
// Don't modulate
" fragColor = gradientColor;\n",
- " fragColor = gradientColor;\n",
// Modulate
" fragColor = gradientColor * color.a;\n",
- " fragColor = gradientColor * color.a;\n",
// Modulate with alpha 8 texture
" fragColor = gradientColor * texture2D(baseSampler, outTexCoords).a;\n",
- " fragColor = gradientColor * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n"
};
-const char* gFS_Main_BitmapShader_Modulate[6] = {
+const char* gFS_Main_BitmapShader_Modulate[3] = {
// Don't modulate
" fragColor = bitmapColor;\n",
- " fragColor = bitmapColor;\n",
// Modulate
" fragColor = bitmapColor * color.a;\n",
- " fragColor = bitmapColor * color.a;\n",
// Modulate with alpha 8 texture
" fragColor = bitmapColor * texture2D(baseSampler, outTexCoords).a;\n",
- " fragColor = bitmapColor * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n"
};
const char* gFS_Main_FragColor =
" gl_FragColor = fragColor;\n";
@@ -540,7 +519,6 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
static bool shaderOp(const ProgramDescription& description, String8& shader,
const int modulateOp, const char** snippets) {
int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp;
- op = op * 2 + description.hasGammaCorrection;
shader.append(snippets[op]);
return description.hasAlpha8Texture;
}
@@ -596,9 +574,6 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
shader.appendFormat(gFS_Uniforms_GradientSampler[description.isSimpleGradient],
gFS_Uniforms_Dither);
}
- if (description.hasGammaCorrection) {
- shader.append(gFS_Uniforms_Gamma);
- }
if (description.hasRoundRectClip) {
shader.append(gFS_Uniforms_HasRoundRectClip);
}
@@ -633,17 +608,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
fast = true;
} else if (singleA8Texture) {
if (!description.modulate) {
- if (description.hasGammaCorrection) {
- shader.append(gFS_Fast_SingleA8Texture_ApplyGamma);
- } else {
- shader.append(gFS_Fast_SingleA8Texture);
- }
+ shader.append(gFS_Fast_SingleA8Texture);
} else {
- if (description.hasGammaCorrection) {
- shader.append(gFS_Fast_SingleModulateA8Texture_ApplyGamma);
- } else {
- shader.append(gFS_Fast_SingleModulateA8Texture);
- }
+ shader.append(gFS_Fast_SingleModulateA8Texture);
}
fast = true;
} else if (singleGradient) {
@@ -693,8 +660,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
if (description.hasTexture || description.hasExternalTexture) {
if (description.hasAlpha8Texture) {
if (!description.hasGradient && !description.hasBitmap) {
- shader.append(gFS_Main_FetchA8Texture[modulateOp * 2 +
- description.hasGammaCorrection]);
+ shader.append(gFS_Main_FetchA8Texture[modulateOp]);
}
} else {
shader.append(gFS_Main_FetchTexture[modulateOp]);
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index b8f8585e5af6..36a8dac9d0c1 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -33,6 +33,8 @@ bool Properties::swapBuffersWithDamage = true;
bool Properties::useBufferAge = true;
bool Properties::enablePartialUpdates = true;
+float Properties::textGamma = DEFAULT_TEXT_GAMMA;
+
DebugLevel Properties::debugLevel = kDebugDisabled;
OverdrawColorSet Properties::overdrawColorSet = OverdrawColorSet::Default;
StencilClipDebug Properties::debugStencilClip = StencilClipDebug::Hide;
@@ -47,6 +49,15 @@ int Properties::overrideSpotShadowStrength = -1;
ProfileType Properties::sProfileType = ProfileType::None;
bool Properties::sDisableProfileBars = false;
+static float property_get_float(const char* key, float defaultValue) {
+ char buf[PROPERTY_VALUE_MAX] = {'\0',};
+
+ if (property_get(PROPERTY_PROFILE, buf, "") > 0) {
+ return atof(buf);
+ }
+ return defaultValue;
+}
+
bool Properties::load() {
char property[PROPERTY_VALUE_MAX];
bool prevDebugLayersUpdates = debugLayersUpdates;
@@ -110,6 +121,8 @@ bool Properties::load() {
useBufferAge = property_get_bool(PROPERTY_USE_BUFFER_AGE, true);
enablePartialUpdates = property_get_bool(PROPERTY_ENABLE_PARTIAL_UPDATES, true);
+ textGamma = property_get_float(PROPERTY_TEXT_GAMMA, DEFAULT_TEXT_GAMMA);
+
return (prevDebugLayersUpdates != debugLayersUpdates)
|| (prevDebugOverdraw != debugOverdraw)
|| (prevDebugStencilClip != debugStencilClip);
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 76028482ba86..3512c36417e1 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -208,30 +208,8 @@ enum DebugLevel {
#define PROPERTY_TEXT_LARGE_CACHE_WIDTH "ro.hwui.text_large_cache_width"
#define PROPERTY_TEXT_LARGE_CACHE_HEIGHT "ro.hwui.text_large_cache_height"
-// Indicates whether gamma correction should be applied in the shaders
-// or in lookup tables. Accepted values:
-//
-// - "lookup3", correction based on lookup tables. Gamma correction
-// is different for black and white text (see thresholds below)
-//
-// - "lookup", correction based on a single lookup table
-//
-// - "shader3", correction applied by a GLSL shader. Gamma correction
-// is different for black and white text (see thresholds below)
-//
-// - "shader", correction applied by a GLSL shader
-//
-// See PROPERTY_TEXT_GAMMA, PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD and
-// PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD for more control.
-#define PROPERTY_TEXT_GAMMA_METHOD "hwui.text_gamma_correction"
-#define DEFAULT_TEXT_GAMMA_METHOD "lookup"
-
// Gamma (>= 1.0, <= 10.0)
#define PROPERTY_TEXT_GAMMA "hwui.text_gamma"
-// Luminance threshold below which black gamma correction is applied. Range: [0..255]
-#define PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD "hwui.text_gamma.black_threshold"
-// Lumincance threshold above which white gamma correction is applied. Range: [0..255]
-#define PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD "hwui.text_gamma.white_threshold"
///////////////////////////////////////////////////////////////////////////////
// Default property values
@@ -242,7 +220,7 @@ enum DebugLevel {
#define DEFAULT_RENDER_BUFFER_CACHE_SIZE 2.0f
#define DEFAULT_PATH_CACHE_SIZE 4.0f
#define DEFAULT_VERTEX_CACHE_SIZE 1.0f
-#define DEFAULT_PATCH_CACHE_SIZE 128 // in kB
+#define DEFAULT_PATCH_CACHE_SIZE 128.0f // in kB
#define DEFAULT_GRADIENT_CACHE_SIZE 0.5f
#define DEFAULT_DROP_SHADOW_CACHE_SIZE 2.0f
#define DEFAULT_FBO_CACHE_SIZE 0
@@ -250,8 +228,6 @@ enum DebugLevel {
#define DEFAULT_TEXTURE_CACHE_FLUSH_RATE 0.6f
#define DEFAULT_TEXT_GAMMA 1.4f
-#define DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD 64
-#define DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD 192
///////////////////////////////////////////////////////////////////////////////
// Misc
@@ -300,6 +276,8 @@ public:
static bool useBufferAge;
static bool enablePartialUpdates;
+ static float textGamma;
+
static DebugLevel debugLevel;
static OverdrawColorSet overdrawColorSet;
static StencilClipDebug debugStencilClip;
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index 01f5e2dba214..12a3e76c9387 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -312,10 +312,10 @@ TessellationCache::TessellationCache()
, mShadowCache(LruCache<ShadowDescription, Task<vertexBuffer_pair_t*>*>::kUnlimitedCapacity) {
char property[PROPERTY_VALUE_MAX];
if (property_get(PROPERTY_VERTEX_CACHE_SIZE, property, nullptr) > 0) {
- INIT_LOGD(" Setting %s cache size to %sMB", name, property);
+ INIT_LOGD(" Setting tessellation cache size to %sMB", property);
setMaxSize(MB(atof(property)));
} else {
- INIT_LOGD(" Using default %s cache size of %.2fMB", name, DEFAULT_VERTEX_CACHE_SIZE);
+ INIT_LOGD(" Using default tessellation cache size of %.2fMB", DEFAULT_VERTEX_CACHE_SIZE);
}
mCache.setOnEntryRemovedListener(&mBufferRemovedListener);
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index ed853f72539d..98e61468ea70 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -77,7 +77,7 @@ public:
, canvasContext(clone.canvasContext)
{}
- const TraversalMode mode;
+ TraversalMode mode;
// TODO: Remove this? Currently this is used to signal to stop preparing
// textures if we run out of cache space.
bool prepareTextures;
diff --git a/libs/hwui/renderstate/Blend.cpp b/libs/hwui/renderstate/Blend.cpp
index b21e15e8fad9..93f787d31745 100644
--- a/libs/hwui/renderstate/Blend.cpp
+++ b/libs/hwui/renderstate/Blend.cpp
@@ -98,20 +98,6 @@ Blend::Blend()
// gl blending off by default
}
-void Blend::enable(SkXfermode::Mode mode, ModeOrderSwap modeUsage) {
- GLenum srcMode;
- GLenum dstMode;
- getFactors(mode, modeUsage, &srcMode, &dstMode);
- setFactors(srcMode, dstMode);
-}
-
-void Blend::disable() {
- if (mEnabled) {
- glDisable(GL_BLEND);
- mEnabled = false;
- }
-}
-
void Blend::invalidate() {
syncEnabled();
mSrcMode = mDstMode = GL_ZERO;
@@ -132,8 +118,13 @@ void Blend::getFactors(SkXfermode::Mode mode, ModeOrderSwap modeUsage, GLenum* o
void Blend::setFactors(GLenum srcMode, GLenum dstMode) {
if (srcMode == GL_ZERO && dstMode == GL_ZERO) {
- disable();
+ // disable blending
+ if (mEnabled) {
+ glDisable(GL_BLEND);
+ mEnabled = false;
+ }
} else {
+ // enable blending
if (!mEnabled) {
glEnable(GL_BLEND);
mEnabled = true;
diff --git a/libs/hwui/renderstate/Blend.h b/libs/hwui/renderstate/Blend.h
index dcc681d4aa50..df9e5a8af879 100644
--- a/libs/hwui/renderstate/Blend.h
+++ b/libs/hwui/renderstate/Blend.h
@@ -34,9 +34,6 @@ public:
NoSwap,
Swap,
};
-
- void enable(SkXfermode::Mode mode, ModeOrderSwap modeUsage);
- void disable();
void syncEnabled();
static void getFactors(SkXfermode::Mode mode, ModeOrderSwap modeUsage,
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index b74b5088c14f..9dc5b45a7738 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -60,9 +60,10 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
, mEglManager(thread.eglManager())
, mOpaque(!translucent)
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
- , mRootRenderNode(rootRenderNode)
, mJankTracker(thread.timeLord().frameIntervalNanos())
- , mProfiler(mFrames) {
+ , mProfiler(mFrames)
+ , mContentOverdrawProtectionBounds(0, 0, 0, 0) {
+ mRenderNodes.emplace_back(rootRenderNode);
mRenderThread.renderState().registerCanvasContext(this);
mProfiler.setDensity(mRenderThread.mainDisplayInfo().density);
}
@@ -172,7 +173,8 @@ static bool wasSkipped(FrameInfo* info) {
return info && ((*info)[FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame);
}
-void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued) {
+void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
+ int64_t syncQueued, RenderNode* target) {
mRenderThread.removeFrameCallback(this);
// If the previous frame was dropped we don't need to hold onto it, so
@@ -189,7 +191,13 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy
info.canvasContext = this;
mAnimationContext->startFrame(info.mode);
- mRootRenderNode->prepareTree(info);
+ for (const sp<RenderNode>& node : mRenderNodes) {
+ // Only the primary target node will be drawn full - all other nodes would get drawn in
+ // real time mode. In case of a window, the primary node is the window content and the other
+ // node(s) are non client / filler nodes.
+ info.mode = (node.get() == target ? TreeInfo::MODE_FULL : TreeInfo::MODE_RT_ONLY);
+ node->prepareTree(info);
+ }
mAnimationContext->runRemainingAnimations(info);
freePrefetechedLayers();
@@ -299,7 +307,95 @@ void CanvasContext::draw() {
dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom, mOpaque);
Rect outBounds;
- mCanvas->drawRenderNode(mRootRenderNode.get(), outBounds);
+ // It there are multiple render nodes, they are as follows:
+ // #0 - backdrop
+ // #1 - content (with - and clipped to - bounds mContentOverdrawProtectionBounds)
+ // #2 - frame
+ // Usually the backdrop cannot be seen since it will be entirely covered by the content. While
+ // resizing however it might become partially visible. The following render loop will crop the
+ // backdrop against the content and draw the remaining part of it. It will then crop the content
+ // against the backdrop (since that indicates a shrinking of the window) and then the frame
+ // around everything.
+ // The bounds of the backdrop against which the content should be clipped.
+ Rect backdropBounds = mContentOverdrawProtectionBounds;
+ // If there is no content bounds we ignore the layering as stated above and start with 2.
+ int layer = mContentOverdrawProtectionBounds.isEmpty() ? 2 : 0;
+ // Draw all render nodes. Note that
+ for (const sp<RenderNode>& node : mRenderNodes) {
+ if (layer == 0) { // Backdrop.
+ // Draw the backdrop clipped to the inverse content bounds.
+ const RenderProperties& properties = node->properties();
+ Rect targetBounds(properties.getLeft(), properties.getTop(),
+ properties.getRight(), properties.getBottom());
+ // Remember the intersection of the target bounds and the intersection bounds against
+ // which we have to crop the content.
+ backdropBounds.intersect(targetBounds);
+ // Check if we have to draw something on the left side ...
+ if (targetBounds.left < mContentOverdrawProtectionBounds.left) {
+ mCanvas->save(SkCanvas::kClip_SaveFlag);
+ if (mCanvas->clipRect(targetBounds.left, targetBounds.top,
+ mContentOverdrawProtectionBounds.left, targetBounds.bottom,
+ SkRegion::kIntersect_Op)) {
+ mCanvas->drawRenderNode(node.get(), outBounds);
+ }
+ // Reduce the target area by the area we have just painted.
+ targetBounds.left = std::min(mContentOverdrawProtectionBounds.left,
+ targetBounds.right);
+ mCanvas->restore();
+ }
+ // ... or on the right side ...
+ if (targetBounds.right > mContentOverdrawProtectionBounds.right &&
+ !targetBounds.isEmpty()) {
+ mCanvas->save(SkCanvas::kClip_SaveFlag);
+ if (mCanvas->clipRect(mContentOverdrawProtectionBounds.right, targetBounds.top,
+ targetBounds.right, targetBounds.bottom,
+ SkRegion::kIntersect_Op)) {
+ mCanvas->drawRenderNode(node.get(), outBounds);
+ }
+ // Reduce the target area by the area we have just painted.
+ targetBounds.right = std::max(targetBounds.left,
+ mContentOverdrawProtectionBounds.right);
+ mCanvas->restore();
+ }
+ // ... or at the top ...
+ if (targetBounds.top < mContentOverdrawProtectionBounds.top &&
+ !targetBounds.isEmpty()) {
+ mCanvas->save(SkCanvas::kClip_SaveFlag);
+ if (mCanvas->clipRect(targetBounds.left, targetBounds.top, targetBounds.right,
+ mContentOverdrawProtectionBounds.top,
+ SkRegion::kIntersect_Op)) {
+ mCanvas->drawRenderNode(node.get(), outBounds);
+ }
+ // Reduce the target area by the area we have just painted.
+ targetBounds.top = std::min(mContentOverdrawProtectionBounds.top,
+ targetBounds.bottom);
+ mCanvas->restore();
+ }
+ // ... or at the bottom.
+ if (targetBounds.bottom > mContentOverdrawProtectionBounds.bottom &&
+ !targetBounds.isEmpty()) {
+ mCanvas->save(SkCanvas::kClip_SaveFlag);
+ if (mCanvas->clipRect(targetBounds.left,
+ mContentOverdrawProtectionBounds.bottom, targetBounds.right,
+ targetBounds.bottom, SkRegion::kIntersect_Op)) {
+ mCanvas->drawRenderNode(node.get(), outBounds);
+ }
+ mCanvas->restore();
+ }
+ } else if (layer == 1) { // Content
+ // It gets cropped against the bounds of the backdrop to stay inside.
+ mCanvas->save(SkCanvas::kClip_SaveFlag);
+ if (mCanvas->clipRect(backdropBounds.left, backdropBounds.top,
+ backdropBounds.right, backdropBounds.bottom,
+ SkRegion::kIntersect_Op)) {
+ mCanvas->drawRenderNode(node.get(), outBounds);
+ }
+ mCanvas->restore();
+ } else { // draw the rest on top at will!
+ mCanvas->drawRenderNode(node.get(), outBounds);
+ }
+ layer++;
+ }
profiler().draw(mCanvas);
@@ -343,7 +439,10 @@ void CanvasContext::doFrame() {
if (CC_UNLIKELY(!mCanvas || mEglSurface == EGL_NO_SURFACE)) {
return;
}
+ prepareAndDraw(nullptr);
+}
+void CanvasContext::prepareAndDraw(RenderNode* node) {
ATRACE_CALL();
int64_t frameInfo[UI_THREAD_FRAME_INFO_SIZE];
@@ -353,7 +452,7 @@ void CanvasContext::doFrame() {
mRenderThread.timeLord().latestVsync());
TreeInfo info(TreeInfo::MODE_RT_ONLY, mRenderThread.renderState());
- prepareTree(info, frameInfo, systemTime(CLOCK_MONOTONIC));
+ prepareTree(info, frameInfo, systemTime(CLOCK_MONOTONIC), node);
if (info.out.canDrawThisFrame) {
draw();
}
@@ -423,7 +522,9 @@ void CanvasContext::destroyHardwareResources() {
stopDrawing();
if (mEglManager.hasEglContext()) {
freePrefetechedLayers();
- mRootRenderNode->destroyHardwareResources();
+ for (const sp<RenderNode>& node : mRenderNodes) {
+ node->destroyHardwareResources();
+ }
Caches& caches = Caches::getInstance();
// Make sure to release all the textures we were owning as there won't
// be another draw
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 6a793203e290..1c3845cac504 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -34,6 +34,7 @@
#include <set>
#include <string>
+#include <vector>
namespace android {
namespace uirenderer {
@@ -77,12 +78,14 @@ public:
void setOpaque(bool opaque);
void makeCurrent();
void processLayerUpdate(DeferredLayerUpdater* layerUpdater);
- void prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued);
+ void prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
+ int64_t syncQueued, RenderNode* target);
void draw();
void destroy();
// IFrameCallback, Chroreographer-driven frame callback entry point
virtual void doFrame() override;
+ void prepareAndDraw(RenderNode* node);
void buildLayer(RenderNode* node);
bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
@@ -113,6 +116,20 @@ public:
void serializeDisplayListTree();
+ void addRenderNode(RenderNode* node, bool placeFront) {
+ int pos = placeFront ? 0 : static_cast<int>(mRenderNodes.size());
+ mRenderNodes.emplace( mRenderNodes.begin() + pos, node);
+ }
+
+ void removeRenderNode(RenderNode* node) {
+ mRenderNodes.erase(std::remove(mRenderNodes.begin(), mRenderNodes.end(), node),
+ mRenderNodes.end());
+ }
+
+ void setContentOverdrawProtectionBounds(int left, int top, int right, int bottom) {
+ mContentOverdrawProtectionBounds.set(left, top, right, bottom);
+ }
+
private:
friend class RegisterFrameCallbackTask;
// TODO: Replace with something better for layer & other GL object
@@ -138,7 +155,7 @@ private:
DamageAccumulator mDamageAccumulator;
std::unique_ptr<AnimationContext> mAnimationContext;
- const sp<RenderNode> mRootRenderNode;
+ std::vector< sp<RenderNode> > mRenderNodes;
FrameInfo* mCurrentFrameInfo = nullptr;
// Ring buffer large enough for 2 seconds worth of frames
@@ -148,6 +165,9 @@ private:
FrameInfoVisualizer mProfiler;
std::set<RenderNode*> mPrefetechedLayers;
+
+ // Stores the bounds of the main content.
+ Rect mContentOverdrawProtectionBounds;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 198906ca845e..a47c9ecf8b31 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -38,9 +38,11 @@ DrawFrameTask::DrawFrameTask()
DrawFrameTask::~DrawFrameTask() {
}
-void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context) {
+void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context,
+ RenderNode* targetNode) {
mRenderThread = thread;
mContext = context;
+ mTargetNode = targetNode;
}
void DrawFrameTask::pushLayerUpdate(DeferredLayerUpdater* layer) {
@@ -118,7 +120,7 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
mContext->processLayerUpdate(mLayers[i].get());
}
mLayers.clear();
- mContext->prepareTree(info, mFrameInfo, mSyncQueued);
+ mContext->prepareTree(info, mFrameInfo, mSyncQueued, mTargetNode);
// This is after the prepareTree so that any pending operations
// (RenderNode tree state, prefetched layers, etc...) will be flushed.
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index ebefcba9f6a5..68ee897e3b8e 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -57,7 +57,7 @@ public:
DrawFrameTask();
virtual ~DrawFrameTask();
- void setContext(RenderThread* thread, CanvasContext* context);
+ void setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode);
void pushLayerUpdate(DeferredLayerUpdater* layer);
void removeLayerUpdate(DeferredLayerUpdater* layer);
@@ -78,6 +78,7 @@ private:
RenderThread* mRenderThread;
CanvasContext* mContext;
+ RenderNode* mTargetNode = nullptr;
/*********************************************
* Single frame data
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index d2ce49f800fc..c9b9637dd52e 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -20,6 +20,7 @@
#include "Properties.h"
#include "RenderThread.h"
#include "renderstate/RenderState.h"
+#include "utils/StringUtils.h"
#include <cutils/log.h>
#include <cutils/properties.h>
@@ -133,12 +134,9 @@ void EglManager::initialize() {
}
void EglManager::initExtensions() {
- std::string extensions(eglQueryString(mEglDisplay, EGL_EXTENSIONS));
- auto has = [&](const char* ext) {
- return extensions.find(ext) != std::string::npos;
- };
- EglExtensions.bufferAge = has("EGL_EXT_buffer_age");
- EglExtensions.setDamage = has("EGL_KHR_partial_update");
+ StringCollection extensions(eglQueryString(mEglDisplay, EGL_EXTENSIONS));
+ EglExtensions.bufferAge = extensions.has("EGL_EXT_buffer_age");
+ EglExtensions.setDamage = extensions.has("EGL_KHR_partial_update");
}
bool EglManager::hasEglContext() {
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index b8388116ff80..f43a769890a4 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -74,7 +74,7 @@ RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextF
args->thread = &mRenderThread;
args->contextFactory = contextFactory;
mContext = (CanvasContext*) postAndWait(task);
- mDrawFrameTask.setContext(&mRenderThread, mContext);
+ mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode);
}
RenderProxy::~RenderProxy() {
@@ -91,7 +91,7 @@ void RenderProxy::destroyContext() {
SETUP_TASK(destroyContext);
args->context = mContext;
mContext = nullptr;
- mDrawFrameTask.setContext(nullptr, nullptr);
+ mDrawFrameTask.setContext(nullptr, nullptr, nullptr);
// This is also a fence as we need to be certain that there are no
// outstanding mDrawFrame tasks posted before it is destroyed
postAndWait(task);
@@ -461,7 +461,8 @@ void RenderProxy::dumpGraphicsMemory(int fd) {
staticPostAndWait(task);
}
-CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, size_t size) {
+CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map,
+ size_t size) {
CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size);
args->buffer->decStrong(nullptr);
return nullptr;
@@ -490,6 +491,61 @@ void RenderProxy::setProcessStatsBuffer(int fd) {
post(task);
}
+CREATE_BRIDGE3(addRenderNode, CanvasContext* context, RenderNode* node, bool placeFront) {
+ args->context->addRenderNode(args->node, args->placeFront);
+ return nullptr;
+}
+
+void RenderProxy::addRenderNode(RenderNode* node, bool placeFront) {
+ SETUP_TASK(addRenderNode);
+ args->context = mContext;
+ args->node = node;
+ args->placeFront = placeFront;
+ post(task);
+}
+
+CREATE_BRIDGE2(removeRenderNode, CanvasContext* context, RenderNode* node) {
+ args->context->removeRenderNode(args->node);
+ return nullptr;
+}
+
+void RenderProxy::removeRenderNode(RenderNode* node) {
+ SETUP_TASK(removeRenderNode);
+ args->context = mContext;
+ args->node = node;
+ post(task);
+}
+
+CREATE_BRIDGE2(drawRenderNode, CanvasContext* context, RenderNode* node) {
+ args->context->prepareAndDraw(args->node);
+ return nullptr;
+}
+
+void RenderProxy::drawRenderNode(RenderNode* node) {
+ SETUP_TASK(drawRenderNode);
+ args->context = mContext;
+ args->node = node;
+ // Be pseudo-thread-safe and don't use any member variables
+ staticPostAndWait(task);
+}
+
+CREATE_BRIDGE5(setContentOverdrawProtectionBounds, CanvasContext* context, int left, int top,
+ int right, int bottom) {
+ args->context->setContentOverdrawProtectionBounds(args->left, args->top, args->right,
+ args->bottom);
+ return nullptr;
+}
+
+void RenderProxy::setContentOverdrawProtectionBounds(int left, int top, int right, int bottom) {
+ SETUP_TASK(setContentOverdrawProtectionBounds);
+ args->context = mContext;
+ args->left = left;
+ args->top = top;
+ args->right = right;
+ args->bottom = bottom;
+ staticPostAndWait(task);
+}
+
CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) {
args->context->serializeDisplayListTree();
return nullptr;
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index e7356dbb0373..046f24ac3f81 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -106,6 +106,11 @@ public:
ANDROID_API void serializeDisplayListTree();
+ ANDROID_API void addRenderNode(RenderNode* node, bool placeFront);
+ ANDROID_API void removeRenderNode(RenderNode* node);
+ ANDROID_API void drawRenderNode(RenderNode* node);
+ ANDROID_API void setContentOverdrawProtectionBounds(int left, int top, int right, int bottom);
+
private:
RenderThread& mRenderThread;
CanvasContext* mContext;
diff --git a/libs/hwui/unit_tests/StringUtilsTests.cpp b/libs/hwui/unit_tests/StringUtilsTests.cpp
new file mode 100644
index 000000000000..5174ae99e71e
--- /dev/null
+++ b/libs/hwui/unit_tests/StringUtilsTests.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "utils/StringUtils.h"
+
+namespace android {
+namespace uirenderer {
+
+TEST(StringUtils, simpleBuildSet) {
+ StringCollection collection("a b c");
+
+ EXPECT_TRUE(collection.has("a"));
+ EXPECT_TRUE(collection.has("b"));
+ EXPECT_TRUE(collection.has("c"));
+ EXPECT_FALSE(collection.has("d"));
+}
+
+TEST(StringUtils, advancedBuildSet) {
+ StringCollection collection("GL_ext1 GL_ext2 GL_ext3");
+
+ EXPECT_TRUE(collection.has("GL_ext1"));
+ EXPECT_FALSE(collection.has("GL_ext")); // string present, but not in list
+}
+
+};
+};
diff --git a/libs/hwui/utils/StringUtils.cpp b/libs/hwui/utils/StringUtils.cpp
new file mode 100644
index 000000000000..a1df0e7966a9
--- /dev/null
+++ b/libs/hwui/utils/StringUtils.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "StringUtils.h"
+
+namespace android {
+namespace uirenderer {
+
+StringCollection::StringCollection(const char* spacedList) {
+ const char* current = spacedList;
+ const char* head = current;
+ do {
+ head = strchr(current, ' ');
+ std::string s(current, head ? head - current : strlen(current));
+ if (s.length()) {
+ mSet.insert(s);
+ }
+ current = head + 1;
+ } while (head);
+}
+
+bool StringCollection::has(const char* s) {
+ return mSet.find(std::string(s)) != mSet.end();
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/utils/StringUtils.h b/libs/hwui/utils/StringUtils.h
new file mode 100644
index 000000000000..ef2a6d5c031a
--- /dev/null
+++ b/libs/hwui/utils/StringUtils.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef STRING_UTILS_H
+#define STRING_UTILS_H
+
+#include <string>
+#include <unordered_set>
+
+namespace android {
+namespace uirenderer {
+
+class StringCollection {
+public:
+ StringCollection(const char* spacedList);
+ bool has(const char* string);
+private:
+ std::unordered_set<std::string> mSet;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* GLUTILS_H */
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index e72bdb446a65..266b0d97cb53 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -169,6 +169,13 @@ public final class MidiManager {
/**
* Registers a callback to receive notifications when MIDI devices are added and removed.
*
+ * The {@link DeviceCallback#onDeviceStatusChanged} method will be called immediately
+ * for any devices that have open ports. This allows applications to know which input
+ * ports are already in use and, therefore, unavailable.
+ *
+ * Applications should call {@link #getDevices} before registering the callback
+ * to get a list of devices already added.
+ *
* @param callback a {@link DeviceCallback} for MIDI device notifications
* @param handler The {@link android.os.Handler Handler} that will be used for delivering the
* device notifications. If handler is null, then the thread used for the
diff --git a/media/jni/android_media_AmrInputStream.cpp b/media/jni/android_media_AmrInputStream.cpp
index afb5d5cbba74..b56a3641ac9f 100644
--- a/media/jni/android_media_AmrInputStream.cpp
+++ b/media/jni/android_media_AmrInputStream.cpp
@@ -119,7 +119,7 @@ static void android_media_AmrInputStream_GsmAmrEncoderDelete
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"GsmAmrEncoderNew", "()J", (void*)android_media_AmrInputStream_GsmAmrEncoderNew},
{"GsmAmrEncoderInitialize", "(J)V", (void*)android_media_AmrInputStream_GsmAmrEncoderInitialize},
{"GsmAmrEncoderEncode", "(J[BI[BI)I", (void*)android_media_AmrInputStream_GsmAmrEncoderEncode},
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 0034b07762a8..3ffdb17f4ec0 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -1253,7 +1253,7 @@ static jint Image_getFormat(JNIEnv* env, jobject thiz, jint readerFormat)
// ----------------------------------------------------------------------------
-static JNINativeMethod gImageReaderMethods[] = {
+static const JNINativeMethod gImageReaderMethods[] = {
{"nativeClassInit", "()V", (void*)ImageReader_classInit },
{"nativeInit", "(Ljava/lang/Object;IIII)V", (void*)ImageReader_init },
{"nativeClose", "()V", (void*)ImageReader_close },
@@ -1263,7 +1263,7 @@ static JNINativeMethod gImageReaderMethods[] = {
{"nativeDetachImage", "(Landroid/media/Image;)I", (void*)ImageReader_detachImage },
};
-static JNINativeMethod gImageMethods[] = {
+static const JNINativeMethod gImageMethods[] = {
{"nativeImageGetBuffer", "(II)Ljava/nio/ByteBuffer;", (void*)Image_getByteBuffer },
{"nativeCreatePlane", "(II)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
(void*)Image_createSurfacePlane },
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 93a44261281b..e8f680f6a36c 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -1798,7 +1798,7 @@ static void android_media_MediaCodec_native_finalize(
android_media_MediaCodec_release(env, thiz);
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "native_release", "()V", (void *)android_media_MediaCodec_release },
{ "native_reset", "()V", (void *)android_media_MediaCodec_reset },
diff --git a/media/jni/android_media_MediaCodecList.cpp b/media/jni/android_media_MediaCodecList.cpp
index 82dd48dffeae..de9bf1f528af 100644
--- a/media/jni/android_media_MediaCodecList.cpp
+++ b/media/jni/android_media_MediaCodecList.cpp
@@ -286,7 +286,7 @@ static jobject android_media_MediaCodecList_getGlobalSettings(JNIEnv *env, jobje
static void android_media_MediaCodecList_native_init(JNIEnv* /* env */) {
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "native_getCodecCount", "()I", (void *)android_media_MediaCodecList_getCodecCount },
{ "getCodecName", "(I)Ljava/lang/String;",
(void *)android_media_MediaCodecList_getCodecName },
diff --git a/media/jni/android_media_MediaCrypto.cpp b/media/jni/android_media_MediaCrypto.cpp
index d7968d225ab2..e414f4838583 100644
--- a/media/jni/android_media_MediaCrypto.cpp
+++ b/media/jni/android_media_MediaCrypto.cpp
@@ -316,7 +316,7 @@ static void android_media_MediaCrypto_setMediaDrmSession(
}
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "release", "()V", (void *)android_media_MediaCrypto_release },
{ "native_init", "()V", (void *)android_media_MediaCrypto_native_init },
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 9ec0312d0f2a..275de1ad5ccb 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -1455,7 +1455,7 @@ static jbyteArray android_media_MediaDrm_signRSANative(
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "release", "()V", (void *)android_media_MediaDrm_release },
{ "native_init", "()V", (void *)android_media_MediaDrm_native_init },
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 4e9b72685223..96c12dd8665b 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -769,7 +769,7 @@ static void android_media_MediaExtractor_native_finalize(
android_media_MediaExtractor_release(env, thiz);
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "release", "()V", (void *)android_media_MediaExtractor_release },
{ "getTrackCount", "()I", (void *)android_media_MediaExtractor_getTrackCount },
diff --git a/media/jni/android_media_MediaHTTPConnection.cpp b/media/jni/android_media_MediaHTTPConnection.cpp
index 393003d98462..fa0b43fedcef 100644
--- a/media/jni/android_media_MediaHTTPConnection.cpp
+++ b/media/jni/android_media_MediaHTTPConnection.cpp
@@ -154,7 +154,7 @@ static jint android_media_MediaHTTPConnection_native_readAt(
return n;
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "native_getIMemory", "()Landroid/os/IBinder;",
(void *)android_media_MediaHTTPConnection_native_getIMemory },
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 59fb6d6f6859..f4e940d6cb21 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -467,7 +467,7 @@ static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobje
}
// JNI mapping between Java methods and native methods
-static JNINativeMethod nativeMethods[] = {
+static const JNINativeMethod nativeMethods[] = {
{
"_setDataSource",
"(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",
diff --git a/media/jni/android_media_MediaMuxer.cpp b/media/jni/android_media_MediaMuxer.cpp
index ecb2ac8a61e8..216624e96ad2 100644
--- a/media/jni/android_media_MediaMuxer.cpp
+++ b/media/jni/android_media_MediaMuxer.cpp
@@ -219,7 +219,7 @@ static void android_media_MediaMuxer_native_release(
}
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nativeAddTrack", "(J[Ljava/lang/String;[Ljava/lang/Object;)I",
(void *)android_media_MediaMuxer_addTrack },
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index d8041f4bff04..be3672968398 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1033,7 +1033,7 @@ android_media_MediaPlayer_setNextMediaPlayer(JNIEnv *env, jobject thiz, jobject
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{
"nativeSetDataSource",
"(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;"
diff --git a/media/jni/android_media_MediaProfiles.cpp b/media/jni/android_media_MediaProfiles.cpp
index ca9db91c5eed..580004304170 100644
--- a/media/jni/android_media_MediaProfiles.cpp
+++ b/media/jni/android_media_MediaProfiles.cpp
@@ -301,7 +301,7 @@ android_media_MediaProfiles_native_get_image_encoding_quality_level(JNIEnv *env,
}
return static_cast<jint>(levels[index]);
}
-static JNINativeMethod gMethodsForEncoderCapabilitiesClass[] = {
+static const JNINativeMethod gMethodsForEncoderCapabilitiesClass[] = {
{"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
{"native_get_num_file_formats", "()I", (void *)android_media_MediaProfiles_native_get_num_file_formats},
{"native_get_file_format", "(I)I", (void *)android_media_MediaProfiles_native_get_file_format},
@@ -315,7 +315,7 @@ static JNINativeMethod gMethodsForEncoderCapabilitiesClass[] = {
(void *)android_media_MediaProfiles_native_get_audio_encoder_cap},
};
-static JNINativeMethod gMethodsForCamcorderProfileClass[] = {
+static const JNINativeMethod gMethodsForCamcorderProfileClass[] = {
{"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
{"native_get_camcorder_profile", "(II)Landroid/media/CamcorderProfile;",
(void *)android_media_MediaProfiles_native_get_camcorder_profile},
@@ -323,7 +323,7 @@ static JNINativeMethod gMethodsForCamcorderProfileClass[] = {
(void *)android_media_MediaProfiles_native_has_camcorder_profile},
};
-static JNINativeMethod gMethodsForDecoderCapabilitiesClass[] = {
+static const JNINativeMethod gMethodsForDecoderCapabilitiesClass[] = {
{"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
{"native_get_num_video_decoders", "()I", (void *)android_media_MediaProfiles_native_get_num_video_decoders},
{"native_get_num_audio_decoders", "()I", (void *)android_media_MediaProfiles_native_get_num_audio_decoders},
@@ -331,7 +331,7 @@ static JNINativeMethod gMethodsForDecoderCapabilitiesClass[] = {
{"native_get_audio_decoder_type", "(I)I", (void *)android_media_MediaProfiles_native_get_audio_decoder_type},
};
-static JNINativeMethod gMethodsForCameraProfileClass[] = {
+static const JNINativeMethod gMethodsForCameraProfileClass[] = {
{"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
{"native_get_num_image_encoding_quality_levels",
"(I)I", (void *)android_media_MediaProfiles_native_get_num_image_encoding_quality_levels},
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index f60af63306ba..e05b3483aadc 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -510,7 +510,7 @@ void android_media_MediaRecorder_setInputSurface(
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"setCamera", "(Landroid/hardware/Camera;)V", (void *)android_media_MediaRecorder_setCamera},
{"setVideoSource", "(I)V", (void *)android_media_MediaRecorder_setVideoSource},
{"setAudioSource", "(I)V", (void *)android_media_MediaRecorder_setAudioSource},
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index 1a9384e6b2c8..0f3c61f53a2c 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -412,7 +412,7 @@ android_media_MediaScanner_native_finalize(JNIEnv *env, jobject thiz)
setNativeScanner_l(env, thiz, 0);
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{
"processDirectory",
"(Ljava/lang/String;Landroid/media/MediaScannerClient;)V",
diff --git a/media/jni/android_media_ResampleInputStream.cpp b/media/jni/android_media_ResampleInputStream.cpp
index 1549a301772a..d06baa57071d 100644
--- a/media/jni/android_media_ResampleInputStream.cpp
+++ b/media/jni/android_media_ResampleInputStream.cpp
@@ -107,7 +107,7 @@ static void android_media_ResampleInputStream_fir21(JNIEnv *env, jclass /* clazz
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"fir21", "([BI[BII)V", (void*)android_media_ResampleInputStream_fir21},
};
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 713f28ce5684..ec2f98a4c9b4 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -1173,12 +1173,12 @@ android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject /*thiz*/, jlo
// ----------------------------------------------------------------------------
-static JNINativeMethod gMtpDatabaseMethods[] = {
+static const JNINativeMethod gMtpDatabaseMethods[] = {
{"native_setup", "()V", (void *)android_mtp_MtpDatabase_setup},
{"native_finalize", "()V", (void *)android_mtp_MtpDatabase_finalize},
};
-static JNINativeMethod gMtpPropertyGroupMethods[] = {
+static const JNINativeMethod gMtpPropertyGroupMethods[] = {
{"format_date_time", "(J)Ljava/lang/String;",
(void *)android_mtp_MtpPropertyGroup_format_date_time},
};
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 2a46ee72e50c..f11329c7b258 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -490,7 +490,7 @@ android_mtp_MtpDevice_send_object_info(JNIEnv *env, jobject thiz, jobject info)
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"native_open", "(Ljava/lang/String;I)Z",
(void *)android_mtp_MtpDevice_open},
{"native_close", "()V", (void *)android_mtp_MtpDevice_close},
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index 2ce2a904e0f0..d13187c39846 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -179,7 +179,7 @@ android_mtp_MtpServer_remove_storage(JNIEnv *env, jobject thiz, jint storageId)
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"native_setup", "(Landroid/mtp/MtpDatabase;Z)V",
(void *)android_mtp_MtpServer_setup},
{"native_run", "()V", (void *)android_mtp_MtpServer_run},
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index aba4bbeb1e70..fa6913573add 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -879,7 +879,7 @@ android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz _
// ----------------------------------------------------------------------------
// Dalvik VM type signatures
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"native_init", "()V", (void *)android_media_AudioEffect_native_init},
{"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;II[I[Ljava/lang/Object;Ljava/lang/String;)I",
(void *)android_media_AudioEffect_native_setup},
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 05570195752b..3d3adba609c0 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -677,7 +677,7 @@ android_media_setPeriodicCapture(JNIEnv *env, jobject thiz, jint rate, jboolean
// ----------------------------------------------------------------------------
// Dalvik VM type signatures
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"native_init", "()V", (void *)android_media_visualizer_native_init},
{"native_setup", "(Ljava/lang/Object;I[ILjava/lang/String;)I",
(void *)android_media_visualizer_native_setup},
diff --git a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
index e6d59e4fb141..444705cfc79f 100644
--- a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
+++ b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
@@ -147,14 +147,22 @@ public final class BluetoothMidiDevice {
// switch to receiving notifications after initial characteristic read
mBluetoothGatt.setCharacteristicNotification(characteristic, true);
+ // Use writeType that requests acknowledgement.
+ // This improves compatibility with various BLE-MIDI devices.
+ int originalWriteType = characteristic.getWriteType();
+ characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
+
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
CLIENT_CHARACTERISTIC_CONFIG);
if (descriptor != null) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
- mBluetoothGatt.writeDescriptor(descriptor);
+ boolean result = mBluetoothGatt.writeDescriptor(descriptor);
+ Log.d(TAG, "writeDescriptor returned " + result);
} else {
Log.e(TAG, "No CLIENT_CHARACTERISTIC_CONFIG for device " + mBluetoothDevice);
}
+
+ characteristic.setWriteType(originalWriteType);
}
@Override
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 0fe5509b95ce..abb464eb3a67 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -76,8 +76,9 @@ public class CaptivePortalLoginActivity extends Activity {
String server = Settings.Global.getString(getContentResolver(), "captive_portal_server");
if (server == null) server = DEFAULT_SERVER;
mCm = ConnectivityManager.from(this);
+ String url = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL);
try {
- mURL = new URL("http", server, "/generate_204");
+ mURL = url != null ? new URL(url) : new URL("http", server, "/generate_204");
} catch (MalformedURLException e) {
// System misconfigured, bail out in a way that at least provides network access.
Log.e(TAG, "Invalid captive portal URL, server=" + server);
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 97bc8fd4d1f4..ac6f950a0a82 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -35,11 +35,6 @@
<action android:name="android.intent.action.OPEN_DOCUMENT_TREE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
- <intent-filter>
- <action android:name="android.provider.action.BROWSE_DOCUMENT_ROOT" />
- <category android:name="android.intent.category.DEFAULT" />
- <data android:mimeType="vnd.android.document/root" />
- </intent-filter>
</activity>
<activity
@@ -63,6 +58,11 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
+ <intent-filter>
+ <action android:name="android.provider.action.BROWSE_DOCUMENT_ROOT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.document/root" />
+ </intent-filter>
</activity>
<provider
diff --git a/packages/DocumentsUI/res/drawable/progress_indeterminate_horizontal_material_trimmed.xml b/packages/DocumentsUI/res/drawable/progress_indeterminate_horizontal_material_trimmed.xml
new file mode 100644
index 000000000000..070b9a10351c
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/progress_indeterminate_horizontal_material_trimmed.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Variant of progress_indeterminate_horizontal_material in frameworks/base/core/res, which
+ draws the whole height of the progress bar instead having blank space above and below the
+ bar. -->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/vector_drawable_progress_indeterminate_horizontal_trimmed" >
+ <target
+ android:name="rect2_grp"
+ android:animation="@*android:anim/progress_indeterminate_horizontal_rect2" />
+ <target
+ android:name="rect1_grp"
+ android:animation="@*android:anim/progress_indeterminate_horizontal_rect1" />
+</animated-vector>
diff --git a/packages/DocumentsUI/res/drawable/vector_drawable_progress_indeterminate_horizontal_trimmed.xml b/packages/DocumentsUI/res/drawable/vector_drawable_progress_indeterminate_horizontal_trimmed.xml
new file mode 100644
index 000000000000..39e3a3738e28
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/vector_drawable_progress_indeterminate_horizontal_trimmed.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Variant of vector_drawable_progress_indeterminate_horizontal in frameworks/base/core/res, which
+ draws the whole height of the progress bar instead having blank space above and below the
+ bar. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="10dp"
+ android:width="360dp"
+ android:viewportHeight="10"
+ android:viewportWidth="360" >
+ <group
+ android:name="progress_group"
+ android:translateX="180"
+ android:translateY="5" >
+ <path
+ android:name="background_track"
+ android:pathData="M -180.0,-5.0 l 360.0,0 l 0,10.0 l -360.0,0 Z"
+ android:fillColor="?android:attr/colorControlActivated"
+ android:fillAlpha="?android:attr/disabledAlpha"/>
+ <group
+ android:name="rect2_grp"
+ android:translateX="-197.60001"
+ android:scaleX="0.1" >
+ <path
+ android:name="rect2"
+ android:pathData="M -144.0,-5.0 l 288.0,0 l 0,10.0 l -288.0,0 Z"
+ android:fillColor="?android:attr/colorControlActivated" />
+ </group>
+ <group
+ android:name="rect1_grp"
+ android:translateX="-522.59998"
+ android:scaleX="0.1" >
+ <path
+ android:name="rect1"
+ android:pathData="M -144.0,-5.0 l 288.0,0 l 0,10.0 l -288.0,0 Z"
+ android:fillColor="?android:attr/colorControlActivated" />
+ </group>
+ </group>
+</vector>
diff --git a/packages/DocumentsUI/res/layout/fragment_directory.xml b/packages/DocumentsUI/res/layout/fragment_directory.xml
index f5c73d5269c2..b02349a693f6 100644
--- a/packages/DocumentsUI/res/layout/fragment_directory.xml
+++ b/packages/DocumentsUI/res/layout/fragment_directory.xml
@@ -28,12 +28,6 @@
android:visibility="gone"
style="@android:style/TextAppearance.Material.Subhead" />
- <!-- The 'list' view is still used for RecentsCreateFragment -->
- <ListView
- android:id="@+id/list"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
<LinearLayout
android:id="@+id/content"
android:layout_width="match_parent"
@@ -41,6 +35,14 @@
android:orientation="vertical"
android:animateLayoutChanges="true">
+ <ProgressBar
+ android:id="@+id/progressbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:indeterminate="true"
+ style="@style/TrimmedHorizontalProgressBar"
+ android:visibility="gone"/>
+
<FrameLayout
android:id="@+id/container_message_bar"
android:layout_width="match_parent"
@@ -48,12 +50,12 @@
android:elevation="8dp"
android:background="@color/material_grey_50"
android:visibility="gone"/>
-
+
<!-- This FrameLayout works around b/24189541 -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
-
+
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:scrollbars="vertical"
@@ -67,9 +69,9 @@
android:scrollbarStyle="outsideOverlay"
android:drawSelectorOnTop="true"
android:background="@color/directory_background" />
-
+
</FrameLayout>
-
+
</LinearLayout>
</com.android.documentsui.DirectoryView>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index 8301816edaea..c13f144d0717 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -77,14 +77,20 @@
<item name="android:colorPrimaryDark">@color/platform_blue_700</item>
<item name="android:colorPrimary">@color/platform_blue_500</item>
<item name="android:colorAccent">@color/platform_blue_700</item>
+ <item name="colorControlActivated">@color/platform_blue_a100</item>
<item name="android:actionModeStyle">@style/FilesActionModeStyle</item>
<item name="colorActionMode">@color/platform_blue_700</item>
-
<item name="android:alertDialogTheme">@style/AlertDialogTheme</item>
</style>
<style name="FilesActionModeStyle" parent="@android:style/Widget.Material.Light.ActionMode">
<item name="android:background">@color/platform_blue_100</item>
</style>
-
+
+ <style name="TrimmedHorizontalProgressBar" parent="android:Widget.Material.ProgressBar.Horizontal">
+ <item name="android:indeterminateDrawable">@drawable/progress_indeterminate_horizontal_material_trimmed</item>
+ <item name="android:minHeight">3dp</item>
+ <item name="android:maxHeight">3dp</item>
+ </style>
+
</resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 1e7a42fa7732..1585908e5639 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -16,13 +16,6 @@
package com.android.documentsui;
-import static com.android.documentsui.BaseActivity.State.ACTION_BROWSE;
-import static com.android.documentsui.BaseActivity.State.ACTION_CREATE;
-import static com.android.documentsui.BaseActivity.State.ACTION_GET_CONTENT;
-import static com.android.documentsui.BaseActivity.State.ACTION_MANAGE;
-import static com.android.documentsui.BaseActivity.State.ACTION_OPEN;
-import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_COPY_DESTINATION;
-import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_TREE;
import static com.android.documentsui.DirectoryFragment.ANIM_DOWN;
import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
import static com.android.documentsui.DirectoryFragment.ANIM_SIDE;
@@ -90,6 +83,7 @@ abstract class BaseActivity extends Activity {
@LayoutRes
private int mLayoutId;
private final String mTag;
+ private DirectoryContainerView mDirectoryContainer;
public abstract void onDocumentPicked(DocumentInfo doc, @Nullable DocumentContext siblings);
public abstract void onDocumentsPicked(List<DocumentInfo> docs);
@@ -116,6 +110,7 @@ abstract class BaseActivity extends Activity {
setContentView(mLayoutId);
mRoots = DocumentsApplication.getRootsCache(this);
+ mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
mSearchManager = new SearchManager();
// Base classes must update result in their onCreate.
@@ -123,22 +118,6 @@ abstract class BaseActivity extends Activity {
}
@Override
- public void onResume() {
- super.onResume();
-
- final State state = getDisplayState();
- final RootInfo root = getCurrentRoot();
-
- // If we're browsing a specific root, and that root went away, then we
- // have no reason to hang around
- if (state.action == State.ACTION_BROWSE && root != null) {
- if (mRoots.getRootBlocking(root.authority, root.rootId) == null) {
- finish();
- }
- }
- }
-
- @Override
public boolean onCreateOptionsMenu(Menu menu) {
boolean showMenu = super.onCreateOptionsMenu(menu);
@@ -176,8 +155,10 @@ abstract class BaseActivity extends Activity {
State state = getDisplayState();
sortSize.setVisible(state.showSize); // Only sort by size when visible
+ fileSize.setVisible(!state.showSize);
grid.setVisible(state.derivedMode != State.MODE_GRID);
list.setVisible(state.derivedMode != State.MODE_LIST);
+ advanced.setVisible(!mState.showAdvanced);
settings.setVisible((root.flags & Root.FLAG_HAS_SETTINGS) != 0);
return shown;
@@ -187,13 +168,17 @@ abstract class BaseActivity extends Activity {
State state = new State();
final Intent intent = getIntent();
- final String action = intent.getAction();
state.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
+
+ state.forceSize = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_FILESIZE, false);
+ state.showSize = state.forceSize || LocalPreferences.getDisplayFileSize(this);
+
state.forceAdvanced = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
- state.showAdvanced = state.forceAdvanced ||
- LocalPreferences.getDisplayAdvancedDevices(this);
+ state.showAdvanced = state.forceAdvanced
+ || LocalPreferences.getDisplayAdvancedDevices(this);
+ state.initAcceptMimes(intent);
state.excludedAuthorities = getExcludedAuthorities();
return state;
@@ -217,7 +202,7 @@ abstract class BaseActivity extends Activity {
if (mRoots.isRecentsRoot(root)) {
onCurrentDirectoryChanged(ANIM_SIDE);
} else {
- new PickRootTask(root).executeOnExecutor(getCurrentExecutor());
+ new PickRootTask(root).executeOnExecutor(getExecutorForCurrentDirectory());
}
}
@@ -316,6 +301,7 @@ abstract class BaseActivity extends Activity {
* @param anim
*/
final void onCurrentDirectoryChanged(int anim) {
+ mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN);
onDirectoryChanged(anim);
final RootsFragment roots = RootsFragment.get(getFragmentManager());
@@ -396,6 +382,7 @@ abstract class BaseActivity extends Activity {
public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME;
public boolean allowMultiple;
+ public boolean forceSize ;
public boolean showSize;
public boolean localOnly ;
public boolean forceAdvanced ;
@@ -426,7 +413,6 @@ abstract class BaseActivity extends Activity {
public static final int ACTION_OPEN_TREE = 4;
public static final int ACTION_MANAGE = 5;
public static final int ACTION_BROWSE = 6;
- public static final int ACTION_BROWSE_ALL = 7;
public static final int ACTION_OPEN_COPY_DESTINATION = 8;
public static final int MODE_UNKNOWN = 0;
@@ -438,6 +424,15 @@ abstract class BaseActivity extends Activity {
public static final int SORT_ORDER_LAST_MODIFIED = 2;
public static final int SORT_ORDER_SIZE = 3;
+ public void initAcceptMimes(Intent intent) {
+ if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
+ acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
+ } else {
+ String glob = intent.getType();
+ acceptMimes = new String[] { glob != null ? glob : "*/*" };
+ }
+ }
+
@Override
public int describeContents() {
return 0;
@@ -450,6 +445,7 @@ abstract class BaseActivity extends Activity {
out.writeStringArray(acceptMimes);
out.writeInt(userSortOrder);
out.writeInt(allowMultiple ? 1 : 0);
+ out.writeInt(forceSize ? 1 : 0);
out.writeInt(showSize ? 1 : 0);
out.writeInt(localOnly ? 1 : 0);
out.writeInt(forceAdvanced ? 1 : 0);
@@ -472,6 +468,7 @@ abstract class BaseActivity extends Activity {
state.acceptMimes = in.readStringArray();
state.userSortOrder = in.readInt();
state.allowMultiple = in.readInt() != 0;
+ state.forceSize = in.readInt() != 0;
state.showSize = in.readInt() != 0;
state.localOnly = in.readInt() != 0;
state.forceAdvanced = in.readInt() != 0;
@@ -559,7 +556,7 @@ abstract class BaseActivity extends Activity {
return getDisplayState().stack.peek();
}
- public Executor getCurrentExecutor() {
+ public Executor getExecutorForCurrentDirectory() {
final DocumentInfo cwd = getCurrentDirectory();
if (cwd != null && cwd.authority != null) {
return ProviderExecutor.forAuthority(cwd.authority);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index c2821e13d7c3..ea8ecf54f31c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -17,7 +17,6 @@
package com.android.documentsui;
import static com.android.documentsui.BaseActivity.State.ACTION_BROWSE;
-import static com.android.documentsui.BaseActivity.State.ACTION_BROWSE_ALL;
import static com.android.documentsui.BaseActivity.State.ACTION_CREATE;
import static com.android.documentsui.BaseActivity.State.ACTION_MANAGE;
import static com.android.documentsui.BaseActivity.State.MODE_GRID;
@@ -101,7 +100,7 @@ import com.android.documentsui.RecentsProvider.StateColumns;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.RootInfo;
-import com.android.internal.util.Preconditions;
+
import com.google.common.collect.Lists;
import java.util.ArrayList;
@@ -135,6 +134,7 @@ public class DirectoryFragment extends Fragment {
private static final String EXTRA_IGNORE_STATE = "ignoreState";
private Model mModel;
+ private Model.UpdateListener mModelUpdateListener = new ModelUpdateListener();
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -160,6 +160,7 @@ public class DirectoryFragment extends Fragment {
private int mColumnCount = 1; // This will get updated when layout changes.
private MessageBar mMessageBar;
+ private View mProgressBar;
public static void showNormal(FragmentManager fm, RootInfo root, DocumentInfo doc, int anim) {
show(fm, TYPE_NORMAL, root, doc, null, anim);
@@ -223,6 +224,7 @@ public class DirectoryFragment extends Fragment {
final View view = inflater.inflate(R.layout.fragment_directory, container, false);
mMessageBar = MessageBar.create(getChildFragmentManager());
+ mProgressBar = view.findViewById(R.id.progressbar);
mEmptyView = view.findViewById(android.R.id.empty);
@@ -311,9 +313,8 @@ public class DirectoryFragment extends Fragment {
: MultiSelectManager.MODE_SINGLE);
selMgr.addCallback(new SelectionModeListener());
- mModel = new Model(context, selMgr);
- mModel.setSelectionManager(selMgr);
- mModel.addUpdateListener(mAdapter);
+ mModel = new Model(context, selMgr, mAdapter);
+ mModel.addUpdateListener(mModelUpdateListener);
mType = getArguments().getInt(EXTRA_TYPE);
mStateKey = buildStateKey(root, doc);
@@ -897,8 +898,7 @@ public class DirectoryFragment extends Fragment {
}
}
- private final class DocumentsAdapter extends RecyclerView.Adapter<DocumentHolder>
- implements Model.UpdateListener {
+ private final class DocumentsAdapter extends RecyclerView.Adapter<DocumentHolder> {
private final Context mContext;
private final LayoutInflater mInflater;
@@ -909,30 +909,6 @@ public class DirectoryFragment extends Fragment {
}
@Override
- public void onModelUpdate(Model model) {
- if (model.info != null || model.error != null) {
- mMessageBar.setInfo(model.info);
- mMessageBar.setError(model.error);
- mMessageBar.show();
- }
-
- if (model.isEmpty()) {
- mEmptyView.setVisibility(View.VISIBLE);
- } else {
- mEmptyView.setVisibility(View.GONE);
- }
-
- notifyDataSetChanged();
- }
-
- @Override
- public void onModelUpdateFailed(Exception e) {
- // TODO: deal with catastrophic update failures
- String error = getString(R.string.query_error);
- notifyDataSetChanged();
- }
-
- @Override
public DocumentHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final State state = getDisplayState(DirectoryFragment.this);
final LayoutInflater inflater = LayoutInflater.from(getContext());
@@ -1576,9 +1552,9 @@ public class DirectoryFragment extends Fragment {
}
private FragmentTuner pickFragmentTuner(final State state) {
- return state.action == ACTION_BROWSE_ALL
+ return state.action == ACTION_BROWSE
? new FilesTuner()
- : new DefaultTuner(state);
+ : new DefaultTuner(state.action);
}
/**
@@ -1615,15 +1591,14 @@ public class DirectoryFragment extends Fragment {
*/
private static final class DefaultTuner implements FragmentTuner {
- private final State mState;
+ private final boolean mManaging;
- public DefaultTuner(State state) {
- mState = state;
+ public DefaultTuner(int action) {
+ mManaging = (action == ACTION_MANAGE);
}
@Override
public void updateActionMenu(Menu menu, int dirType, boolean canDelete) {
- Preconditions.checkState(mState.action != ACTION_BROWSE_ALL);
final MenuItem open = menu.findItem(R.id.menu_open);
final MenuItem share = menu.findItem(R.id.menu_share);
@@ -1632,14 +1607,11 @@ public class DirectoryFragment extends Fragment {
final MenuItem moveTo = menu.findItem(R.id.menu_move_to);
final MenuItem copyToClipboard = menu.findItem(R.id.menu_copy_to_clipboard);
- final boolean manageOrBrowse = (mState.action == ACTION_MANAGE
- || mState.action == ACTION_BROWSE);
-
- open.setVisible(!manageOrBrowse);
- share.setVisible(manageOrBrowse);
- delete.setVisible(manageOrBrowse && canDelete);
+ open.setVisible(!mManaging);
+ share.setVisible(mManaging);
+ delete.setVisible(mManaging && canDelete);
// Disable copying from the Recents view.
- copyTo.setVisible(manageOrBrowse && dirType != TYPE_RECENT_OPEN);
+ copyTo.setVisible(mManaging && dirType != TYPE_RECENT_OPEN);
moveTo.setVisible(SystemProperties.getBoolean("debug.documentsui.enable_move", false));
// Only shown in files mode.
@@ -1656,6 +1628,7 @@ public class DirectoryFragment extends Fragment {
private static final class FilesTuner implements FragmentTuner {
@Override
public void updateActionMenu(Menu menu, int dirType, boolean canDelete) {
+
menu.findItem(R.id.menu_share).setVisible(true);
menu.findItem(R.id.menu_delete).setVisible(canDelete);
menu.findItem(R.id.menu_copy_to_clipboard).setVisible(true);
@@ -1675,6 +1648,7 @@ public class DirectoryFragment extends Fragment {
@VisibleForTesting
public static final class Model implements DocumentContext {
private MultiSelectManager mSelectionManager;
+ private RecyclerView.Adapter<?> mViewAdapter;
private Context mContext;
private int mCursorCount;
private boolean mIsLoading;
@@ -1684,17 +1658,11 @@ public class DirectoryFragment extends Fragment {
@Nullable private String info;
@Nullable private String error;
- Model(Context context, MultiSelectManager selectionManager) {
+ Model(Context context, MultiSelectManager selectionManager,
+ RecyclerView.Adapter<?> viewAdapter) {
mContext = context;
mSelectionManager = selectionManager;
- }
-
- /**
- * Sets the selection manager used by the model.
- * TODO: the model should instantiate the selection manager. See onActivityCreated.
- */
- void setSelectionManager(MultiSelectManager mgr) {
- mSelectionManager = mgr;
+ mViewAdapter = viewAdapter;
}
/**
@@ -1859,7 +1827,7 @@ public class DirectoryFragment extends Fragment {
int position = selected.get(i);
if (DEBUG) Log.d(TAG, "Marked position " + position + " for deletion");
mMarkedForDeletion.append(position, true);
- mUpdateListener.notifyItemRemoved(position);
+ mViewAdapter.notifyItemRemoved(position);
}
}
@@ -1874,7 +1842,7 @@ public class DirectoryFragment extends Fragment {
for (int i = 0; i < size; ++i) {
final int position = mMarkedForDeletion.keyAt(i);
mMarkedForDeletion.put(position, false);
- mUpdateListener.notifyItemInserted(position);
+ mViewAdapter.notifyItemInserted(position);
}
// Then, clear the deletion list.
@@ -1957,26 +1925,46 @@ public class DirectoryFragment extends Fragment {
mUpdateListener = listener;
}
- interface UpdateListener {
+ static class UpdateListener {
/**
* Called when a successful update has occurred.
*/
- void onModelUpdate(Model model);
+ void onModelUpdate(Model model) {}
/**
* Called when an update has been attempted but failed.
*/
- void onModelUpdateFailed(Exception e);
+ void onModelUpdateFailed(Exception e) {}
+ }
+ }
- /**
- * Called when an item has been removed from the model.
- */
- void notifyItemRemoved(int position);
+ private class ModelUpdateListener extends Model.UpdateListener {
+ @Override
+ public void onModelUpdate(Model model) {
+ if (model.info != null || model.error != null) {
+ mMessageBar.setInfo(model.info);
+ mMessageBar.setError(model.error);
+ mMessageBar.show();
+ }
- /**
- * Called when an item has been added to the model.
- */
- void notifyItemInserted(int position);
+ mProgressBar.setVisibility(model.isLoading() ? View.VISIBLE : View.GONE);
+
+ if (model.isEmpty()) {
+ mEmptyView.setVisibility(View.VISIBLE);
+ mRecView.setVisibility(View.GONE);
+ } else {
+ mEmptyView.setVisibility(View.GONE);
+ mRecView.setVisibility(View.VISIBLE);
+ }
+
+ mAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public void onModelUpdateFailed(Exception e) {
+ // TODO: deal with catastrophic update failures
+ String error = getString(R.string.query_error);
+ mAdapter.notifyDataSetChanged();
}
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 1de1c6a57028..dbfcf407e6bd 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -16,7 +16,6 @@
package com.android.documentsui;
-import static com.android.documentsui.BaseActivity.State.ACTION_BROWSE;
import static com.android.documentsui.BaseActivity.State.ACTION_CREATE;
import static com.android.documentsui.BaseActivity.State.ACTION_GET_CONTENT;
import static com.android.documentsui.BaseActivity.State.ACTION_OPEN;
@@ -28,7 +27,6 @@ import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
-import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.ContentProviderClient;
@@ -44,7 +42,6 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.DocumentsContract;
-import android.provider.DocumentsContract.Root;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -75,8 +72,6 @@ public class DocumentsActivity extends BaseActivity {
private Toolbar mRootsToolbar;
- private DirectoryContainerView mDirectoryContainer;
-
private ItemSelectedListener mStackListener;
private BaseAdapter mStackAdapter;
@@ -89,7 +84,7 @@ public class DocumentsActivity extends BaseActivity {
super.onCreate(icicle);
final Resources res = getResources();
- mShowAsDialog = res.getBoolean(R.bool.show_as_dialog) && mState.action != ACTION_BROWSE;
+ mShowAsDialog = res.getBoolean(R.bool.show_as_dialog);
if (!mShowAsDialog) {
setTheme(R.style.DocumentsNonDialogTheme);
@@ -114,8 +109,6 @@ public class DocumentsActivity extends BaseActivity {
mDrawer = DrawerController.create(this);
}
- mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
-
mToolbar = (Toolbar) findViewById(R.id.toolbar);
mStackAdapter = new StackAdapter();
@@ -127,14 +120,6 @@ public class DocumentsActivity extends BaseActivity {
setActionBar(mToolbar);
- // Hide roots when we're managing a specific root
- if (mState.action == ACTION_BROWSE) {
- mDrawer.lockClosed();
- if (mShowAsDialog) {
- findViewById(R.id.container_roots).setVisibility(View.GONE);
- }
- }
-
if (mState.action == ACTION_CREATE) {
final String mimeType = getIntent().getType();
final String title = getIntent().getStringExtra(Intent.EXTRA_TITLE);
@@ -160,12 +145,7 @@ public class DocumentsActivity extends BaseActivity {
// In this case, we set the activity title in AsyncTask.onPostExecute(). To prevent
// talkback from reading aloud the default title, we clear it here.
setTitle("");
- if (mState.action == ACTION_BROWSE) {
- final Uri rootUri = getIntent().getData();
- new RestoreRootTask(rootUri).executeOnExecutor(getCurrentExecutor());
- } else {
- new RestoreStackTask().execute();
- }
+ new RestoreStackTask().execute();
} else {
onCurrentDirectoryChanged(ANIM_NONE);
}
@@ -185,8 +165,6 @@ public class DocumentsActivity extends BaseActivity {
state.action = ACTION_GET_CONTENT;
} else if (Intent.ACTION_OPEN_DOCUMENT_TREE.equals(action)) {
state.action = ACTION_OPEN_TREE;
- } else if (DocumentsContract.ACTION_BROWSE_DOCUMENT_ROOT.equals(action)) {
- state.action = ACTION_BROWSE;
} else if (DocumentsIntent.ACTION_OPEN_COPY_DESTINATION.equals(action)) {
state.action = ACTION_OPEN_COPY_DESTINATION;
}
@@ -196,20 +174,6 @@ public class DocumentsActivity extends BaseActivity {
Intent.EXTRA_ALLOW_MULTIPLE, false);
}
- if (state.action == ACTION_BROWSE) {
- state.acceptMimes = new String[] { "*/*" };
- state.allowMultiple = true;
- } else if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
- state.acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
- } else {
- state.acceptMimes = new String[] { intent.getType() };
- }
-
- if (state.action == ACTION_BROWSE) {
- state.showSize = true;
- } else {
- state.showSize = LocalPreferences.getDisplayFileSize(this);
- }
if (state.action == ACTION_OPEN_COPY_DESTINATION) {
state.directoryCopy = intent.getBooleanExtra(
BaseActivity.DocumentsIntent.EXTRA_DIRECTORY_COPY, false);
@@ -361,11 +325,7 @@ public class DocumentsActivity extends BaseActivity {
final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
final MenuItem settings = menu.findItem(R.id.menu_settings);
- // File size is locked visible for browse because that is the action triggered by Settings,
- // where the user is trying to find large files to clean up.
- // TODO: instead of setting this according to the action, use a local preference, but
- // provide a @hide extra to let callers like Settings force-enable size visibility.
- boolean fileSizeVisible = mState.action != ACTION_BROWSE;
+ boolean fileSizeVisible = mState.showSize && !mState.forceSize;
if (mState.action == ACTION_CREATE
|| mState.action == ACTION_OPEN_TREE
|| mState.action == ACTION_OPEN_COPY_DESTINATION) {
@@ -387,11 +347,9 @@ public class DocumentsActivity extends BaseActivity {
createDir.setVisible(false);
}
- advanced.setVisible(mState.action != ACTION_BROWSE && !mState.forceAdvanced);
+ advanced.setVisible(!mState.forceAdvanced);
fileSize.setVisible(fileSizeVisible);
-
- settings.setVisible(mState.action == ACTION_BROWSE
- && (root.flags & Root.FLAG_HAS_SETTINGS) != 0);
+ settings.setVisible(false);
return true;
}
@@ -407,8 +365,6 @@ public class DocumentsActivity extends BaseActivity {
final RootInfo root = getCurrentRoot();
final DocumentInfo cwd = getCurrentDirectory();
- mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN);
-
if (cwd == null) {
// No directory means recents
if (mState.action == ACTION_CREATE ||
@@ -452,11 +408,11 @@ public class DocumentsActivity extends BaseActivity {
}
void onSaveRequested(DocumentInfo replaceTarget) {
- new ExistingFinishTask(replaceTarget.derivedUri).executeOnExecutor(getCurrentExecutor());
+ new ExistingFinishTask(replaceTarget.derivedUri).executeOnExecutor(getExecutorForCurrentDirectory());
}
void onSaveRequested(String mimeType, String displayName) {
- new CreateFinishTask(mimeType, displayName).executeOnExecutor(getCurrentExecutor());
+ new CreateFinishTask(mimeType, displayName).executeOnExecutor(getExecutorForCurrentDirectory());
}
@Override
@@ -472,21 +428,10 @@ public class DocumentsActivity extends BaseActivity {
openDirectory(doc);
} else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
// Explicit file picked, return
- new ExistingFinishTask(doc.derivedUri).executeOnExecutor(getCurrentExecutor());
+ new ExistingFinishTask(doc.derivedUri).executeOnExecutor(getExecutorForCurrentDirectory());
} else if (mState.action == ACTION_CREATE) {
// Replace selected file
SaveFragment.get(fm).setReplaceTarget(doc);
- } else if (mState.action == ACTION_BROWSE) {
- // Go straight to viewing
- final Intent view = new Intent(Intent.ACTION_VIEW);
- view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- view.setData(doc.derivedUri);
-
- try {
- startActivity(view);
- } catch (ActivityNotFoundException ex) {
- Toast.makeText(this, R.string.toast_no_application, Toast.LENGTH_SHORT).show();
- }
}
}
@@ -498,7 +443,7 @@ public class DocumentsActivity extends BaseActivity {
for (int i = 0; i < size; i++) {
uris[i] = docs.get(i).derivedUri;
}
- new ExistingFinishTask(uris).executeOnExecutor(getCurrentExecutor());
+ new ExistingFinishTask(uris).executeOnExecutor(getExecutorForCurrentDirectory());
}
}
@@ -513,7 +458,7 @@ public class DocumentsActivity extends BaseActivity {
// Should not be reached.
throw new IllegalStateException("Invalid mState.action.");
}
- new PickFinishTask(result).executeOnExecutor(getCurrentExecutor());
+ new PickFinishTask(result).executeOnExecutor(getExecutorForCurrentDirectory());
}
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 450def799a1a..7e9531b777fa 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -16,8 +16,9 @@
package com.android.documentsui;
-import static com.android.documentsui.DirectoryFragment.ANIM_DOWN;
import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
+import static com.android.documentsui.Shared.DEBUG;
+import static com.android.internal.util.Preconditions.checkArgument;
import android.app.Activity;
import android.app.FragmentManager;
@@ -25,11 +26,9 @@ import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.ContentResolver;
import android.content.ContentValues;
-import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.provider.DocumentsContract;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.KeyEvent;
@@ -46,7 +45,6 @@ import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.DurableUtils;
import com.android.documentsui.model.RootInfo;
-import com.android.internal.util.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
@@ -58,11 +56,9 @@ import java.util.List;
public class FilesActivity extends BaseActivity {
public static final String TAG = "FilesActivity";
- static final boolean DEBUG = false;
private Toolbar mToolbar;
private Spinner mToolbarStack;
- private DirectoryContainerView mDirectoryContainer;
private ItemSelectedListener mStackListener;
private BaseAdapter mStackAdapter;
private DocumentClipper mClipper;
@@ -75,10 +71,6 @@ public class FilesActivity extends BaseActivity {
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- final Context context = this;
-
- mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
-
mToolbar = (Toolbar) findViewById(R.id.toolbar);
mStackAdapter = new StackAdapter();
@@ -93,7 +85,16 @@ public class FilesActivity extends BaseActivity {
RootsFragment.show(getFragmentManager(), null);
if (!mState.restored) {
- new RestoreStackTask().execute();
+ Uri rootUri = getIntent().getData();
+
+ // If we've got a specific root to display, restore that root using a dedicated
+ // authority. That way a misbehaving provider won't result in an ANR.
+ if (rootUri != null) {
+ new RestoreRootTask(rootUri).executeOnExecutor(
+ ProviderExecutor.forAuthority(rootUri.getAuthority()));
+ } else {
+ new RestoreStackTask().execute();
+ }
// Show a failure dialog if there was a failed operation.
final Intent intent = getIntent();
@@ -118,22 +119,16 @@ public class FilesActivity extends BaseActivity {
final Intent intent = getIntent();
- state.action = State.ACTION_BROWSE_ALL;
- state.acceptMimes = new String[] { intent.getType() };
+ state.action = State.ACTION_BROWSE;
state.allowMultiple = true;
- // These options are specific to the DocumentsActivity.
- Preconditions.checkArgument(
- !intent.hasExtra(Intent.EXTRA_LOCAL_ONLY));
- Preconditions.checkArgument(
- !intent.hasExtra(DocumentsContract.EXTRA_SHOW_ADVANCED));
-
- state.showAdvanced = LocalPreferences.getDisplayAdvancedDevices(this);
- state.showSize = LocalPreferences.getDisplayFileSize(this);
+ // Options specific to the DocumentsActivity.
+ checkArgument(!intent.hasExtra(Intent.EXTRA_LOCAL_ONLY));
final DocumentStack stack = intent.getParcelableExtra(CopyService.EXTRA_STACK);
- if (stack != null)
+ if (stack != null) {
state.stack = stack;
+ }
return state;
}
@@ -145,6 +140,21 @@ public class FilesActivity extends BaseActivity {
}
@Override
+ public void onResume() {
+ super.onResume();
+
+ final RootInfo root = getCurrentRoot();
+
+ // If we're browsing a specific root, and that root went away, then we
+ // have no reason to hang around.
+ // TODO: Rather than just disappearing, maybe we should inform
+ // the user what has happened, let them close us. Less surprising.
+ if (mRoots.getRootBlocking(root.authority, root.rootId) == null) {
+ finish();
+ }
+ }
+
+ @Override
public void updateActionBar() {
final RootInfo root = getCurrentRoot();
@@ -197,12 +207,8 @@ public class FilesActivity extends BaseActivity {
public boolean onPrepareOptionsMenu(Menu menu) {
boolean shown = super.onPrepareOptionsMenu(menu);
- menu.findItem(R.id.menu_file_size).setVisible(true);
- menu.findItem(R.id.menu_advanced).setVisible(true);
-
final MenuItem pasteFromCb = menu.findItem(R.id.menu_paste_from_clipboard);
final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
- final MenuItem settings = menu.findItem(R.id.menu_settings);
boolean canCreateDir = canCreateDirectory();
@@ -235,8 +241,6 @@ public class FilesActivity extends BaseActivity {
final RootInfo root = getCurrentRoot();
final DocumentInfo cwd = getCurrentDirectory();
- mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN);
-
if (cwd == null) {
DirectoryFragment.showRecentsOpen(fm, anim);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java b/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
index 740157829d3f..f5b1d8e67dd4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
@@ -56,8 +56,6 @@ public class ManageRootActivity extends BaseActivity {
private Toolbar mToolbar;
private Spinner mToolbarStack;
- private DirectoryContainerView mDirectoryContainer;
-
private ItemSelectedListener mStackListener;
private BaseAdapter mStackAdapter;
@@ -73,8 +71,6 @@ public class ManageRootActivity extends BaseActivity {
mDrawer = DrawerController.createDummy();
- mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
-
mToolbar = (Toolbar) findViewById(R.id.toolbar);
mToolbar.setTitleTextAppearance(context,
android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
@@ -91,7 +87,7 @@ public class ManageRootActivity extends BaseActivity {
// talkback from reading aloud the default title, we clear it here.
setTitle("");
final Uri rootUri = getIntent().getData();
- new RestoreRootTask(rootUri).executeOnExecutor(getCurrentExecutor());
+ new RestoreRootTask(rootUri).executeOnExecutor(getExecutorForCurrentDirectory());
} else {
onCurrentDirectoryChanged(ANIM_NONE);
}
@@ -157,7 +153,6 @@ public class ManageRootActivity extends BaseActivity {
// If started in manage roots mode, there has to be a cwd (i.e. the root dir of the managed
// root).
Preconditions.checkNotNull(cwd);
- mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN);
if (mState.currentSearch != null) {
// Ongoing search
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MessageBar.java b/packages/DocumentsUI/src/com/android/documentsui/MessageBar.java
index a48fd5c268b4..312d53b9dc1c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MessageBar.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MessageBar.java
@@ -69,7 +69,7 @@ public class MessageBar extends Fragment {
* message bar layout will be adjusted accordingly.
*/
public void setError(@Nullable String error) {
- View errorView = mView.findViewById(R.id.container_message_bar);
+ View errorView = mView.findViewById(R.id.container_error);
if (error != null) {
TextView errorText = (TextView) mView.findViewById(R.id.textview_error);
errorText.setText(error);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
index 5930056f111c..583994351a0c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
@@ -45,6 +45,8 @@ import android.view.View;
import com.android.documentsui.Events.InputEvent;
import com.android.documentsui.Events.MotionInputEvent;
+import com.google.android.collect.Lists;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -113,8 +115,11 @@ public final class MultiSelectManager {
}
};
- CompositeOnGestureListener<? extends Object> compositeListener =
- new CompositeOnGestureListener<>(listener, gestureDelegate);
+ CompositeOnGestureListener compositeListener =
+ new CompositeOnGestureListener(
+ Lists.<OnGestureListener>newArrayList(listener, gestureDelegate),
+ Lists.<OnDoubleTapListener>newArrayList(listener, gestureDelegate));
+
final GestureDetector detector =
new GestureDetector(recyclerView.getContext(), compositeListener);
@@ -1060,21 +1065,23 @@ public final class MultiSelectManager {
* @template A gestureDelegate that implements both {@link OnGestureListener}
* and {@link OnDoubleTapListener}
*/
- private static final class
- CompositeOnGestureListener<L extends OnGestureListener & OnDoubleTapListener>
+ private static final class CompositeOnGestureListener
implements OnGestureListener, OnDoubleTapListener {
- private L[] mListeners;
+ private List<OnGestureListener> mGestureListeners;
+ private List<OnDoubleTapListener> mTapListeners;
- @SafeVarargs
- public CompositeOnGestureListener(L... listeners) {
- mListeners = listeners;
+ public CompositeOnGestureListener(
+ List<OnGestureListener> gestureListeners,
+ List<OnDoubleTapListener> tapListeners) {
+ mGestureListeners = gestureListeners;
+ mTapListeners = tapListeners;
}
@Override
public boolean onDown(MotionEvent e) {
- for (int i = 0; i < mListeners.length; i++) {
- if (mListeners[i].onDown(e)) {
+ for (OnGestureListener l : mGestureListeners) {
+ if (l.onDown(e)) {
return true;
}
}
@@ -1083,15 +1090,15 @@ public final class MultiSelectManager {
@Override
public void onShowPress(MotionEvent e) {
- for (int i = 0; i < mListeners.length; i++) {
- mListeners[i].onShowPress(e);
+ for (OnGestureListener l : mGestureListeners) {
+ l.onShowPress(e);
}
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
- for (int i = 0; i < mListeners.length; i++) {
- if (mListeners[i].onSingleTapUp(e)) {
+ for (OnGestureListener l : mGestureListeners) {
+ if (l.onSingleTapUp(e)) {
return true;
}
}
@@ -1100,8 +1107,8 @@ public final class MultiSelectManager {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- for (int i = 0; i < mListeners.length; i++) {
- if (mListeners[i].onScroll(e1, e2, distanceX, distanceY)) {
+ for (OnGestureListener l : mGestureListeners) {
+ if (l.onScroll(e1, e2, distanceX, distanceY)) {
return true;
}
}
@@ -1110,15 +1117,15 @@ public final class MultiSelectManager {
@Override
public void onLongPress(MotionEvent e) {
- for (int i = 0; i < mListeners.length; i++) {
- mListeners[i].onLongPress(e);
+ for (OnGestureListener l : mGestureListeners) {
+ l.onLongPress(e);
}
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- for (int i = 0; i < mListeners.length; i++) {
- if (mListeners[i].onFling(e1, e2, velocityX, velocityY)) {
+ for (OnGestureListener l : mGestureListeners) {
+ if (l.onFling(e1, e2, velocityX, velocityY)) {
return true;
}
}
@@ -1127,8 +1134,8 @@ public final class MultiSelectManager {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
- for (int i = 0; i < mListeners.length; i++) {
- if (mListeners[i].onSingleTapConfirmed(e)) {
+ for (OnDoubleTapListener listener : mTapListeners) {
+ if (listener.onSingleTapConfirmed(e)) {
return true;
}
}
@@ -1137,8 +1144,8 @@ public final class MultiSelectManager {
@Override
public boolean onDoubleTap(MotionEvent e) {
- for (int i = 0; i < mListeners.length; i++) {
- if (mListeners[i].onDoubleTap(e)) {
+ for (OnDoubleTapListener listener : mTapListeners) {
+ if (listener.onDoubleTap(e)) {
return true;
}
}
@@ -1147,8 +1154,8 @@ public final class MultiSelectManager {
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
- for (int i = 0; i < mListeners.length; i++) {
- if (mListeners[i].onDoubleTapEvent(e)) {
+ for (OnDoubleTapListener listener : mTapListeners) {
+ if (listener.onDoubleTapEvent(e)) {
return true;
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
index 662822ee35d3..681133156dca 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
@@ -30,19 +30,19 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils.TruncateAt;
import android.text.style.ImageSpan;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.BaseAdapter;
import android.widget.ImageView;
-import android.widget.ListView;
import android.widget.TextView;
import com.android.documentsui.BaseActivity.State;
@@ -64,8 +64,7 @@ import java.util.List;
public class RecentsCreateFragment extends Fragment {
private View mEmptyView;
- private ListView mListView;
-
+ private RecyclerView mRecView;
private DocumentStackAdapter mAdapter;
private LoaderCallbacks<List<DocumentStack>> mCallbacks;
@@ -85,13 +84,14 @@ public class RecentsCreateFragment extends Fragment {
final View view = inflater.inflate(R.layout.fragment_directory, container, false);
- mEmptyView = view.findViewById(android.R.id.empty);
+ mRecView = (RecyclerView) view.findViewById(R.id.recyclerView);
+ mRecView.setLayoutManager(new LinearLayoutManager(getContext()));
+ mRecView.addOnItemTouchListener(mItemListener);
- mListView = (ListView) view.findViewById(R.id.list);
- mListView.setOnItemClickListener(mItemListener);
+ mEmptyView = view.findViewById(android.R.id.empty);
mAdapter = new DocumentStackAdapter();
- mListView.setAdapter(mAdapter);
+ mRecView.setAdapter(mAdapter);
final RootsCache roots = DocumentsApplication.getRootsCache(context);
final State state = ((BaseActivity) getActivity()).getDisplayState();
@@ -105,7 +105,7 @@ public class RecentsCreateFragment extends Fragment {
@Override
public void onLoadFinished(
Loader<List<DocumentStack>> loader, List<DocumentStack> data) {
- mAdapter.swapStacks(data);
+ mAdapter.update(data);
// When launched into empty recents, show drawer
if (mAdapter.isEmpty() && !state.stackTouched &&
@@ -116,7 +116,7 @@ public class RecentsCreateFragment extends Fragment {
@Override
public void onLoaderReset(Loader<List<DocumentStack>> loader) {
- mAdapter.swapStacks(null);
+ mAdapter.update(null);
}
};
@@ -135,13 +135,24 @@ public class RecentsCreateFragment extends Fragment {
getLoaderManager().destroyLoader(LOADER_RECENTS);
}
- private OnItemClickListener mItemListener = new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- final DocumentStack stack = mAdapter.getItem(position);
- ((BaseActivity) getActivity()).onStackPicked(stack);
- }
- };
+ private RecyclerView.OnItemTouchListener mItemListener =
+ new RecyclerView.OnItemTouchListener() {
+ @Override
+ public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
+ Events.MotionInputEvent event = new Events.MotionInputEvent(e, mRecView);
+ if (event.isOverItem() && event.isActionUp()) {
+ final DocumentStack stack = mAdapter.getItem(event.getItemPosition());
+ ((BaseActivity) getActivity()).onStackPicked(stack);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
+ };
public static class RecentsCreateLoader extends UriDerivativeLoader<Uri, List<DocumentStack>> {
private final RootsCache mRoots;
@@ -187,14 +198,32 @@ public class RecentsCreateFragment extends Fragment {
}
}
- private class DocumentStackAdapter extends BaseAdapter {
- private List<DocumentStack> mStacks;
+ private static final class StackHolder extends RecyclerView.ViewHolder {
+ public View view;
+ public StackHolder(View view) {
+ super(view);
+ this.view = view;
+ }
+ }
+
+ private class DocumentStackAdapter extends RecyclerView.Adapter<StackHolder> {
+ @Nullable private List<DocumentStack> mItems;
+
+ DocumentStack getItem(int position) {
+ return mItems.get(position);
+ }
+
+ @Override
+ public int getItemCount() {
+ return mItems == null ? 0 : mItems.size();
+ }
- public DocumentStackAdapter() {
+ boolean isEmpty() {
+ return mItems == null ? true : mItems.isEmpty();
}
- public void swapStacks(List<DocumentStack> stacks) {
- mStacks = stacks;
+ void update(@Nullable List<DocumentStack> items) {
+ mItems = items;
if (isEmpty()) {
mEmptyView.setVisibility(View.VISIBLE);
@@ -206,17 +235,22 @@ public class RecentsCreateFragment extends Fragment {
}
@Override
- public View getView(int position, View convertView, ViewGroup parent) {
- final Context context = parent.getContext();
+ public StackHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ final Context context = parent.getContext();
- if (convertView == null) {
- final LayoutInflater inflater = LayoutInflater.from(context);
- convertView = inflater.inflate(R.layout.item_doc_list, parent, false);
- }
+ final LayoutInflater inflater = LayoutInflater.from(context);
+ return new StackHolder(
+ (View) inflater.inflate(R.layout.item_doc_list, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(StackHolder holder, int position) {
+ Context context = getContext();
+ View view = holder.view;
- final ImageView iconMime = (ImageView) convertView.findViewById(R.id.icon_mime);
- final TextView title = (TextView) convertView.findViewById(android.R.id.title);
- final View line2 = convertView.findViewById(R.id.line2);
+ final ImageView iconMime = (ImageView) view.findViewById(R.id.icon_mime);
+ final TextView title = (TextView) view.findViewById(android.R.id.title);
+ final View line2 = view.findViewById(R.id.line2);
final DocumentStack stack = getItem(position);
iconMime.setImageDrawable(stack.root.loadIcon(context));
@@ -234,23 +268,6 @@ public class RecentsCreateFragment extends Fragment {
title.setEllipsize(TruncateAt.MIDDLE);
if (line2 != null) line2.setVisibility(View.GONE);
-
- return convertView;
- }
-
- @Override
- public int getCount() {
- return mStacks != null ? mStacks.size() : 0;
- }
-
- @Override
- public DocumentStack getItem(int position) {
- return mStacks.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return getItem(position).hashCode();
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index 05f7d8dd11e3..cb46bca741a1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -17,6 +17,7 @@
package com.android.documentsui;
import static com.android.documentsui.Shared.TAG;
+import static com.android.documentsui.Shared.DEBUG;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
@@ -58,8 +59,6 @@ import java.util.concurrent.TimeUnit;
* Cache of known storage backends and their roots.
*/
public class RootsCache {
- private static final boolean LOGD = false;
-
public static final Uri sNotificationUri = Uri.parse(
"content://com.android.documentsui.roots/");
@@ -91,7 +90,7 @@ public class RootsCache {
@Override
public void onChange(boolean selfChange, Uri uri) {
- if (LOGD) Log.d(TAG, "Updating roots due to change at " + uri);
+ if (DEBUG) Log.d(TAG, "Updating roots due to change at " + uri);
updateAuthorityAsync(uri.getAuthority());
}
}
@@ -148,7 +147,7 @@ public class RootsCache {
final ContentResolver resolver = mContext.getContentResolver();
synchronized (mLock) {
for (String authority : mStoppedAuthorities) {
- if (LOGD) Log.d(TAG, "Loading stopped authority " + authority);
+ if (DEBUG) Log.d(TAG, "Loading stopped authority " + authority);
mRoots.putAll(authority, loadRootsForAuthority(resolver, authority));
}
mStoppedAuthorities.clear();
@@ -199,7 +198,8 @@ public class RootsCache {
}
final long delta = SystemClock.elapsedRealtime() - start;
- Log.d(TAG, "Update found " + mTaskRoots.size() + " roots in " + delta + "ms");
+ if (DEBUG)
+ Log.d(TAG, "Update found " + mTaskRoots.size() + " roots in " + delta + "ms");
synchronized (mLock) {
mRoots = mTaskRoots;
mStoppedAuthorities = mTaskStoppedAuthorities;
@@ -213,7 +213,7 @@ public class RootsCache {
// Ignore stopped packages for now; we might query them
// later during UI interaction.
if ((info.applicationInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0) {
- if (LOGD) Log.d(TAG, "Ignoring stopped authority " + info.authority);
+ if (DEBUG) Log.d(TAG, "Ignoring stopped authority " + info.authority);
mTaskStoppedAuthorities.add(info.authority);
return;
}
@@ -223,7 +223,7 @@ public class RootsCache {
if (mFilterPackage != null && !mFilterPackage.equals(info.packageName)) {
synchronized (mLock) {
if (mTaskRoots.putAll(info.authority, mRoots.get(info.authority))) {
- if (LOGD) Log.d(TAG, "Used cached roots for " + info.authority);
+ if (DEBUG) Log.d(TAG, "Used cached roots for " + info.authority);
cacheHit = true;
}
}
@@ -241,7 +241,7 @@ public class RootsCache {
* Bring up requested provider and query for all active roots.
*/
private Collection<RootInfo> loadRootsForAuthority(ContentResolver resolver, String authority) {
- if (LOGD) Log.d(TAG, "Loading roots for " + authority);
+ if (DEBUG) Log.d(TAG, "Loading roots for " + authority);
synchronized (mObservedAuthorities) {
if (mObservedAuthorities.add(authority)) {
@@ -370,10 +370,15 @@ public class RootsCache {
// Exclude downloads roots that don't support directory creation
// TODO: Add flag to check the root supports directory creation or not.
if (state.directoryCopy && root.isDownloads()) continue;
- // Only show empty roots when creating
- if ((state.action != State.ACTION_CREATE ||
+
+ // Only show empty roots when creating, or in browse mode.
+ if (empty && (state.action != State.ACTION_BROWSE ||
+ state.action != State.ACTION_CREATE ||
state.action != State.ACTION_OPEN_TREE ||
- state.action != State.ACTION_OPEN_COPY_DESTINATION) && empty) continue;
+ state.action != State.ACTION_OPEN_COPY_DESTINATION)) {
+ if (DEBUG) Log.i(TAG, "Skipping empty root: " + root);
+ continue;
+ }
// Only include roots that serve requested content
final boolean overlap =
@@ -385,7 +390,7 @@ public class RootsCache {
// Exclude roots from the calling package.
if (state.excludedAuthorities.contains(root.authority)) {
- if (LOGD) Log.d(TAG, "Excluding root " + root.authority + " from calling package.");
+ if (DEBUG) Log.d(TAG, "Excluding root " + root.authority + " from calling package.");
continue;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 0c1ebc16f1df..9c884d4ef8c6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -22,7 +22,7 @@ import android.content.Context;
* @hide
*/
public final class Shared {
- public static final boolean DEBUG = false;
+ public static final boolean DEBUG = true;
public static final String TAG = "Documents";
/**
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java
index 5505f3546e5d..1895a6e66450 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java
@@ -22,9 +22,12 @@ import android.content.ContextWrapper;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.provider.DocumentsContract.Document;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.support.v7.widget.RecyclerView;
import android.test.AndroidTestCase;
import android.test.MoreAsserts;
import android.test.mock.MockContentResolver;
+import android.view.ViewGroup;
import com.android.documentsui.DirectoryFragment.Model;
import com.android.documentsui.MultiSelectManager.Selection;
@@ -57,7 +60,8 @@ public class DirectoryFragmentModelTest extends AndroidTestCase {
DirectoryResult r = new DirectoryResult();
r.cursor = cursor;
- model = new Model(mContext, null);
+ // Instantiate the model with a dummy view adapter and listener that (for now) do nothing.
+ model = new Model(mContext, null, new DummyAdapter());
model.addUpdateListener(new DummyListener());
model.update(r);
}
@@ -160,11 +164,16 @@ public class DirectoryFragmentModelTest extends AndroidTestCase {
return model.getDocuments(sel);
}
- private static class DummyListener implements Model.UpdateListener {
+ private static class DummyListener extends Model.UpdateListener {
public void onModelUpdate(Model model) {}
public void onModelUpdateFailed(Exception e) {}
- public void notifyItemRemoved(int position) {}
- public void notifyItemInserted(int position) {}
}
+ private static class DummyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+ public int getItemCount() { return 0; }
+ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {}
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ return null;
+ }
+ }
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
index aeac91215be6..2033159af720 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
@@ -23,6 +23,7 @@ import com.android.internal.telephony.PhoneConstants;
import android.content.Context;
import android.content.res.ColorStateList;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
@@ -96,6 +97,12 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
}
@Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ resetState();
+ }
+
+ @Override
protected int getPromtReasonStringRes(int reason) {
// No message on SIM Pin
return 0;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index e34286572cb6..57ee319f8ff3 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -121,7 +121,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private static final int MSG_DEVICE_PROVISIONED = 308;
private static final int MSG_DPM_STATE_CHANGED = 309;
private static final int MSG_USER_SWITCHING = 310;
- private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 311;
private static final int MSG_KEYGUARD_RESET = 312;
private static final int MSG_BOOT_COMPLETED = 313;
private static final int MSG_USER_SWITCH_COMPLETE = 314;
@@ -233,9 +232,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
case MSG_USER_SWITCH_COMPLETE:
handleUserSwitchComplete(msg.arg1);
break;
- case MSG_KEYGUARD_VISIBILITY_CHANGED:
- handleKeyguardVisibilityChanged(msg.arg1);
- break;
case MSG_KEYGUARD_RESET:
handleKeyguardReset();
break;
@@ -1344,19 +1340,20 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
/**
- * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
+ * Notifies that the visibility state of Keyguard has changed.
+ *
+ * <p>Needs to be called from the main thread.
*/
- private void handleKeyguardVisibilityChanged(int showing) {
- if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
- boolean isShowing = (showing == 1);
- mKeyguardIsVisible = isShowing;
+ public void onKeyguardVisibilityChanged(boolean showing) {
+ if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
+ mKeyguardIsVisible = showing;
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
- cb.onKeyguardVisibilityChangedRaw(isShowing);
+ cb.onKeyguardVisibilityChangedRaw(showing);
}
}
- if (!isShowing) {
+ if (!showing) {
mFingerprintAlreadyAuthenticated = false;
}
updateFingerprintListeningState();
@@ -1477,13 +1474,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
}
- public void sendKeyguardVisibilityChanged(boolean showing) {
- if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
- Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
- message.arg1 = showing ? 1 : 0;
- message.sendToTarget();
- }
-
public void sendKeyguardReset() {
mHandler.obtainMessage(MSG_KEYGUARD_RESET).sendToTarget();
}
diff --git a/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp b/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp
index b5d91385abe5..1530a02c22fe 100644
--- a/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp
+++ b/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp
@@ -166,7 +166,7 @@ static void writeBitmapPixels(JNIEnv* env, jclass /* clazz */, jobject jbitmap,
}
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
{"nativeReadBitmapPixels", "(Landroid/graphics/Bitmap;I)V", (void *) readBitmapPixels},
{"nativeWriteBitmapPixels", "(Landroid/graphics/Bitmap;I)V", (void *) writeBitmapPixels},
};
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 1d71346b575b..e12e3a571880 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -166,7 +166,7 @@ public class SettingsHelper {
.putExtra(Intent.EXTRA_SETTING_NAME, name)
.putExtra(Intent.EXTRA_SETTING_NEW_VALUE, value)
.putExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE, oldValue);
- context.sendBroadcastAsUser(intent, UserHandle.OWNER, null);
+ context.sendBroadcastAsUser(intent, UserHandle.SYSTEM, null);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
index dd93389880b0..1d0bfe7dc6f1 100644
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -20,10 +20,6 @@ import android.view.Display;
import android.view.View;
public interface RecentsComponent {
- public interface Callbacks {
- public void onVisibilityChanged(boolean visible);
- }
-
void showRecents(boolean triggeredFromAltTab, View statusBarView);
void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
void toggleRecents(Display display, int layoutDirection, View statusBarView);
@@ -31,5 +27,4 @@ public interface RecentsComponent {
void cancelPreloadingRecents();
void showNextAffiliatedTask();
void showPrevAffiliatedTask();
- void setCallback(Callbacks cb);
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 33bd726c8d4e..5bf251b57af1 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -22,7 +22,9 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
+import android.os.Process;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.util.Log;
import java.util.HashMap;
@@ -51,12 +53,20 @@ public class SystemUIApplication extends Application {
};
/**
+ * The classes of the stuff to start for each user. This is a subset of the services listed
+ * above.
+ */
+ private final Class<?>[] SERVICES_PER_USER = new Class[] {
+ com.android.systemui.recents.Recents.class
+ };
+
+ /**
* Hold a reference on the stuff we start.
*/
private final SystemUI[] mServices = new SystemUI[SERVICES.length];
private boolean mServicesStarted;
private boolean mBootCompleted;
- private final Map<Class<?>, Object> mComponents = new HashMap<Class<?>, Object>();
+ private final Map<Class<?>, Object> mComponents = new HashMap<>();
@Override
public void onCreate() {
@@ -66,24 +76,32 @@ public class SystemUIApplication extends Application {
// the theme set there.
setTheme(R.style.systemui_theme);
- IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
- filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (mBootCompleted) return;
-
- if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
- unregisterReceiver(this);
- mBootCompleted = true;
- if (mServicesStarted) {
- final int N = mServices.length;
- for (int i = 0; i < N; i++) {
- mServices[i].onBootCompleted();
+ if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
+ IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mBootCompleted) return;
+
+ if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
+ unregisterReceiver(this);
+ mBootCompleted = true;
+ if (mServicesStarted) {
+ final int N = mServices.length;
+ for (int i = 0; i < N; i++) {
+ mServices[i].onBootCompleted();
+ }
}
}
- }
- }, filter);
+ }, filter);
+ } else {
+ // For a secondary user, boot-completed will never be called because it has already
+ // been broadcasted on startup for the primary SystemUI process. Instead, for
+ // components which require the SystemUI component to be initialized per-user, we
+ // start those components now for the current non-system user.
+ startServicesIfNeeded(SERVICES_PER_USER);
+ }
}
/**
@@ -94,6 +112,10 @@ public class SystemUIApplication extends Application {
* <p>This method must only be called from the main thread.</p>
*/
public void startServicesIfNeeded() {
+ startServicesIfNeeded(SERVICES);
+ }
+
+ private void startServicesIfNeeded(Class<?>[] services) {
if (mServicesStarted) {
return;
}
@@ -107,13 +129,14 @@ public class SystemUIApplication extends Application {
}
}
- Log.v(TAG, "Starting SystemUI services.");
- final int N = SERVICES.length;
+ Log.v(TAG, "Starting SystemUI services for user " +
+ Process.myUserHandle().getIdentifier() + ".");
+ final int N = services.length;
for (int i=0; i<N; i++) {
- Class<?> cl = SERVICES[i];
+ Class<?> cl = services[i];
if (DEBUG) Log.d(TAG, "loading: " + cl);
try {
- mServices[i] = (SystemUI)cl.newInstance();
+ mServices[i] = (SystemUI) cl.newInstance();
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InstantiationException ex) {
@@ -136,7 +159,9 @@ public class SystemUIApplication extends Application {
if (mServicesStarted) {
int len = mServices.length;
for (int i = 0; i < len; i++) {
- mServices[i].onConfigurationChanged(newConfig);
+ if (mServices[i] != null) {
+ mServices[i].onConfigurationChanged(newConfig);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java
new file mode 100644
index 000000000000..86bea873b737
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+import android.view.MotionEvent;
+
+import java.util.HashMap;
+
+/**
+ * A classifier which looks at the speed and distance between successive points of a Stroke.
+ * It looks at two consecutive speeds between two points and calculates the ratio between them.
+ * The final result is the maximum of these values. It does the same for distances. If some speed
+ * or distance is equal to zero then the ratio between this and the next part is not calculated. To
+ * the duration of each part there is added one nanosecond so that it is always possible to
+ * calculate the speed of a part.
+ */
+public class AccelerationClassifier extends StrokeClassifier {
+ private final HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
+
+ public AccelerationClassifier(ClassifierData classifierData) {
+ mClassifierData = classifierData;
+ }
+
+ @Override
+ public void onTouchEvent(MotionEvent event) {
+ int action = event.getActionMasked();
+
+ if (action == MotionEvent.ACTION_DOWN) {
+ mStrokeMap.clear();
+ }
+
+ for (int i = 0; i < event.getPointerCount(); i++) {
+ Stroke stroke = mClassifierData.getStroke(event.getPointerId(i));
+ Point point = stroke.getPoints().get(stroke.getPoints().size() - 1);
+ if (mStrokeMap.get(stroke) == null) {
+ mStrokeMap.put(stroke, new Data(point));
+ } else {
+ mStrokeMap.get(stroke).addPoint(point);
+ }
+ }
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ Data data = mStrokeMap.get(stroke);
+ return SpeedRatioEvaluator.evaluate(data.maxSpeedRatio)
+ + DistanceRatioEvaluator.evaluate(data.maxDistanceRatio);
+ }
+
+ private static class Data {
+ public Point previousPoint;
+ public float previousSpeed;
+ public float previousDistance;
+ public float maxSpeedRatio;
+ public float maxDistanceRatio;
+
+ public Data(Point point) {
+ previousPoint = point;
+ previousSpeed = previousDistance = 0.0f;
+ maxDistanceRatio = maxSpeedRatio = 0.0f;
+ }
+
+ public void addPoint(Point point) {
+ float distance = previousPoint.dist(point);
+ float duration = (float) (point.timeOffsetNano - previousPoint.timeOffsetNano + 1);
+ float speed = distance / duration;
+ if (previousDistance != 0.0f) {
+ maxDistanceRatio = Math.max(maxDistanceRatio, distance / previousDistance);
+ }
+
+ if (previousSpeed != 0.0f) {
+ maxSpeedRatio = Math.max(maxSpeedRatio, speed / previousSpeed);
+ }
+
+ previousDistance = distance;
+ previousSpeed = speed;
+ previousPoint = point;
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java
index 5cd914f06828..c74339b9082b 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java
@@ -16,7 +16,6 @@
package com.android.systemui.classifier;
-import android.hardware.SensorEvent;
import android.view.MotionEvent;
import java.lang.Math;
@@ -27,27 +26,24 @@ import java.util.List;
/**
* A classifier which calculates the variance of differences between successive angles in a stroke.
- * For each stroke it keeps its last three points. If some successive points are the same, it ignores
- * the repetitions. If a new point is added, the classifier calculates the angle between the last
- * three points. After that it calculates the difference between this angle and the previously
- * calculated angle. The return value of the classifier is the variance of the differences
- * from a stroke. If there are multiple strokes created at once, the classifier sums up the
- * variances of all the strokes. Also the value is multiplied by HISTORY_FACTOR after each
- * INTERVAL milliseconds.
+ * For each stroke it keeps its last three points. If some successive points are the same, it
+ * ignores the repetitions. If a new point is added, the classifier calculates the angle between
+ * the last three points. After that, it calculates the difference between this angle and the
+ * previously calculated angle. Then it calculates the variance of the differences from a stroke.
+ * To the differences there is artificially added value 0.0 and the difference between the first
+ * angle and PI (angles are in radians). It helps with strokes which have few points and punishes
+ * more strokes which are not smooth. This classifier also tries to split the stroke into two parts
+ * int the place in which the biggest angle is. It calculates the angle variance of the two parts
+ * and sums them up. The reason the classifier is doing this, is because some human swipes at the
+ * beginning go for a moment in one direction and then they rapidly change direction for the rest
+ * of the stroke (like a tick). The final result is the minimum of angle variance of the whole
+ * stroke and the sum of angle variances of the two parts split up.
*/
-public class AnglesVarianceClassifier extends Classifier {
- private final float INTERVAL = 10.0f;
- private final float CLEAR_HISTORY = 500f;
- private final float HISTORY_FACTOR = 0.9f;
-
+public class AnglesVarianceClassifier extends StrokeClassifier {
private HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
- private float mValue;
- private long mLastUpdate;
public AnglesVarianceClassifier(ClassifierData classifierData) {
mClassifierData = classifierData;
- mValue = 0.0f;
- mLastUpdate = System.currentTimeMillis();
}
@Override
@@ -65,54 +61,33 @@ public class AnglesVarianceClassifier extends Classifier {
mStrokeMap.put(stroke, new Data());
}
mStrokeMap.get(stroke).addPoint(stroke.getPoints().get(stroke.getPoints().size() - 1));
-
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
- || (action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) {
- decayValue();
- mValue += mStrokeMap.get(stroke).getAnglesVariance();
- }
}
}
- /**
- * Decreases mValue through time
- */
- private void decayValue() {
- long currentTimeMillis = System.currentTimeMillis();
- if (currentTimeMillis - mLastUpdate > CLEAR_HISTORY) {
- mValue = 0.0f;
- } else {
- mValue *= Math.pow(HISTORY_FACTOR, (float) (currentTimeMillis - mLastUpdate) / INTERVAL);
- }
- mLastUpdate = currentTimeMillis;
- }
-
@Override
- public void onSensorChanged(SensorEvent event) {
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ return AnglesVarianceEvaluator.evaluate(mStrokeMap.get(stroke).getAnglesVariance());
}
- @Override
- public float getFalseTouchEvaluation(int type) {
- decayValue();
- float currentValue = 0.0f;
- for (Data data: mStrokeMap.values()) {
- currentValue += data.getAnglesVariance();
- }
- return (float) (mValue + currentValue);
- }
-
- private class Data {
+ private static class Data {
private List<Point> mLastThreePoints = new ArrayList<>();
+ private float mFirstAngleVariance;
private float mPreviousAngle;
+ private float mBiggestAngle;
private float mSumSquares;
+ private float mSecondSumSquares;
private float mSum;
+ private float mSecondSum;
private float mCount;
+ private float mSecondCount;
public Data() {
+ mFirstAngleVariance = 0.0f;
mPreviousAngle = (float) Math.PI;
- mSumSquares = 0.0f;
- mSum = 0.0f;
- mCount = 1.0f;
+ mBiggestAngle = 0.0f;
+ mSumSquares = mSecondSumSquares = 0.0f;
+ mSum = mSecondSum = 0.0f;
+ mCount = mSecondCount = 1.0f;
}
public void addPoint(Point point) {
@@ -124,10 +99,26 @@ public class AnglesVarianceClassifier extends Classifier {
if (mLastThreePoints.size() == 4) {
mLastThreePoints.remove(0);
- float angle = getAngle(mLastThreePoints.get(0), mLastThreePoints.get(1),
+ float angle = mLastThreePoints.get(1).getAngle(mLastThreePoints.get(0),
mLastThreePoints.get(2));
float difference = angle - mPreviousAngle;
+
+ // If this is the biggest angle of the stroke so then we save the value of
+ // the angle variance so far and start to count the values for the angle
+ // variance of the second part.
+ if (mBiggestAngle < angle) {
+ mBiggestAngle = angle;
+ mFirstAngleVariance = getAnglesVariance(mSumSquares, mSum, mCount);
+ mSecondSumSquares = 0.0f;
+ mSecondSum = 0.0f;
+ mSecondCount = 1.0f;
+ } else {
+ mSecondSum += difference;
+ mSecondSumSquares += difference * difference;
+ mSecondCount += 1.0;
+ }
+
mSum += difference;
mSumSquares += difference * difference;
mCount += 1.0;
@@ -136,21 +127,14 @@ public class AnglesVarianceClassifier extends Classifier {
}
}
- private float getAngle(Point a, Point b, Point c) {
- float dist1 = a.dist(b);
- float dist2 = b.dist(c);
- float crossProduct = b.crossProduct(a, c);
- float dotProduct = b.dotProduct(a, c);
- float cos = Math.min(1.0f, Math.max(-1.0f, dotProduct / dist1 / dist2));
- float angle = (float) Math.acos(cos);
- if (crossProduct < 0.0) {
- angle = 2.0f * (float) Math.PI - angle;
- }
- return angle;
+ public float getAnglesVariance(float sumSquares, float sum, float count) {
+ return sumSquares / count - (sum / count) * (sum / count);
}
public float getAnglesVariance() {
- return mSumSquares / mCount + (mSum / mCount) * (mSum / mCount);
+ return Math.min(getAnglesVariance(mSumSquares, mSum, mCount),
+ mFirstAngleVariance + getAnglesVariance(mSecondSumSquares, mSecondSum,
+ mSecondCount));
}
}
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java
new file mode 100644
index 000000000000..99cc1a6d14fe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+public class AnglesVarianceEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value > 0.05) evaluation++;
+ if (value > 0.10) evaluation++;
+ if (value > 0.20) evaluation++;
+ if (value > 0.40) evaluation++;
+ if (value > 0.80) evaluation++;
+ if (value > 1.50) evaluation++;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
index b76be1478bb4..89d20defc7db 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
@@ -20,7 +20,7 @@ import android.hardware.SensorEvent;
import android.view.MotionEvent;
/**
- * An interface for classifiers for touch and sensor events.
+ * An abstract class for classifiers for touch and sensor events.
*/
public abstract class Classifier {
public static final int QUICK_SETTINGS = 0;
@@ -30,6 +30,7 @@ public abstract class Classifier {
public static final int UNLOCK = 4;
public static final int LEFT_AFFORDANCE = 5;
public static final int RIGHT_AFFORDANCE = 6;
+ public static final int GENERIC = 7;
/**
* Contains all the information about touch events from which the classifier can query
@@ -47,11 +48,4 @@ public abstract class Classifier {
*/
public void onSensorChanged(SensorEvent event) {
}
-
- /**
- * @param type the type of action for which this method is called
- * @return a nonnegative value which is used to determine whether this a false touch. The
- * bigger the value the greater the chance that this a false touch.
- */
- public abstract float getFalseTouchEvaluation(int type);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java b/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java
index 77b81d2b68fa..649279dac285 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java
@@ -19,32 +19,47 @@ package com.android.systemui.classifier;
import android.util.SparseArray;
import android.view.MotionEvent;
+import java.util.ArrayList;
+
/**
* Contains data which is used to classify interaction sequences on the lockscreen. It does, for
* example, provide information on the current touch state.
*/
public class ClassifierData {
private SparseArray<Stroke> mCurrentStrokes = new SparseArray<>();
+ private ArrayList<Stroke> mEndingStrokes = new ArrayList<>();
+ private float mXdpi;
+ private float mYdpi;
- public ClassifierData() {
+ public ClassifierData(float xdpi, float ydpi) {
+ mXdpi = xdpi;
+ mYdpi = ydpi;
}
public void update(MotionEvent event) {
+ mEndingStrokes.clear();
int action = event.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
mCurrentStrokes.clear();
}
+
for (int i = 0; i < event.getPointerCount(); i++) {
int id = event.getPointerId(i);
if (mCurrentStrokes.get(id) == null) {
- mCurrentStrokes.put(id, new Stroke(event.getEventTimeNano()));
+ mCurrentStrokes.put(id, new Stroke(event.getEventTimeNano(), mXdpi, mYdpi));
}
mCurrentStrokes.get(id).addPoint(event.getX(i), event.getY(i),
event.getEventTimeNano());
+
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
+ || (action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) {
+ mEndingStrokes.add(getStroke(id));
+ }
}
}
public void cleanUp(MotionEvent event) {
+ mEndingStrokes.clear();
int action = event.getActionMasked();
for (int i = 0; i < event.getPointerCount(); i++) {
int id = event.getPointerId(i);
@@ -56,6 +71,13 @@ public class ClassifierData {
}
/**
+ * @return the list of Strokes which are ending in the recently added MotionEvent
+ */
+ public ArrayList<Stroke> getEndingStrokes() {
+ return mEndingStrokes;
+ }
+
+ /**
* @param id the id from MotionEvent
* @return the Stroke assigned to the id
*/
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DistanceRatioEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/DistanceRatioEvaluator.java
new file mode 100644
index 000000000000..8acb009a230f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DistanceRatioEvaluator.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+public class DistanceRatioEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value <= 1.0) evaluation++;
+ if (value <= 0.5) evaluation++;
+ if (value > 4.0) evaluation++;
+ if (value > 7.0) evaluation++;
+ if (value > 14.0) evaluation++;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java
new file mode 100644
index 000000000000..892469428f4a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+/**
+ * A classifier which looks at the ratio between the duration of the stroke and its number of
+ * points.
+ */
+public class DurationCountClassifier extends StrokeClassifier {
+ public DurationCountClassifier(ClassifierData classifierData) {
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ return DurationCountEvaluator.evaluate(stroke.getDurationSeconds() / stroke.getCount());
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DurationCountEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/DurationCountEvaluator.java
new file mode 100644
index 000000000000..5395983968f7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DurationCountEvaluator.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+
+public class DurationCountEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value < 0.0105) evaluation++;
+ if (value < 0.00909) evaluation++;
+ if (value < 0.00667) evaluation++;
+ if (value > 0.0333) evaluation++;
+ if (value > 0.0500) evaluation++;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java
new file mode 100644
index 000000000000..78bc0ddf1942
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+/**
+ * A classifier which looks at the distance between the first and the last point from the stroke.
+ */
+public class EndPointLengthClassifier extends StrokeClassifier {
+ public EndPointLengthClassifier(ClassifierData classifierData) {
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ return EndPointLengthEvaluator.evaluate(stroke.getEndPointLength());
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthEvaluator.java
new file mode 100644
index 000000000000..bb2f1c4e355d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthEvaluator.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+public class EndPointLengthEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value < 0.05) evaluation += 2.0;
+ if (value < 0.1) evaluation += 2.0;
+ if (value < 0.2) evaluation += 2.0;
+ if (value < 0.3) evaluation += 2.0;
+ if (value < 0.4) evaluation += 2.0;
+ if (value < 0.5) evaluation += 2.0;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
new file mode 100644
index 000000000000..c125e0093db5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+/**
+ * A classifier which looks at the ratio between the total length covered by the stroke and the
+ * distance between the first and last point from this stroke.
+ */
+public class EndPointRatioClassifier extends StrokeClassifier {
+ public EndPointRatioClassifier(ClassifierData classifierData) {
+ mClassifierData = classifierData;
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ if (stroke.getTotalLength() == 0.0f) {
+ return 1.0f;
+ }
+ return EndPointRatioEvaluator.evaluate(
+ stroke.getEndPointLength() / stroke.getTotalLength());
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioEvaluator.java
new file mode 100644
index 000000000000..529fcec2710e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioEvaluator.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+public class EndPointRatioEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value < 0.85) evaluation++;
+ if (value < 0.75) evaluation++;
+ if (value < 0.65) evaluation++;
+ if (value < 0.55) evaluation++;
+ if (value < 0.45) evaluation++;
+ if (value < 0.35) evaluation++;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 347273ac0f68..c68fff837c6f 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -126,11 +126,10 @@ public class FalsingManager implements SensorEventListener {
}
/**
- * @param type the type of action for which this method is called
* @return true if the classifier determined that this is not a human interacting with the phone
*/
- public boolean isFalseTouch(int type) {
- return mHumanInteractionClassifier.getFalseTouchEvaluation(type) > 0.5;
+ public boolean isFalseTouch() {
+ return mHumanInteractionClassifier.isFalseTouch();
}
@Override
@@ -189,6 +188,7 @@ public class FalsingManager implements SensorEventListener {
}
public void onQsDown() {
+ mHumanInteractionClassifier.setType(Classifier.QUICK_SETTINGS);
mDataCollector.onQsDown();
}
@@ -197,6 +197,7 @@ public class FalsingManager implements SensorEventListener {
}
public void onTrackingStarted() {
+ mHumanInteractionClassifier.setType(Classifier.UNLOCK);
mDataCollector.onTrackingStarted();
}
@@ -217,6 +218,7 @@ public class FalsingManager implements SensorEventListener {
}
public void onNotificatonStartDraggingDown() {
+ mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DRAG_DOWN);
mDataCollector.onNotificatonStartDraggingDown();
}
@@ -229,6 +231,7 @@ public class FalsingManager implements SensorEventListener {
}
public void onNotificatonStartDismissing() {
+ mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DISMISS);
mDataCollector.onNotificatonStartDismissing();
}
@@ -245,6 +248,11 @@ public class FalsingManager implements SensorEventListener {
}
public void onAffordanceSwipingStarted(boolean rightCorner) {
+ if (rightCorner) {
+ mHumanInteractionClassifier.setType(Classifier.RIGHT_AFFORDANCE);
+ } else {
+ mHumanInteractionClassifier.setType(Classifier.LEFT_AFFORDANCE);
+ }
mDataCollector.onAffordanceSwipingStarted(rightCorner);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java
new file mode 100644
index 000000000000..11388fc49594
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+/**
+ * An abstract class for classifiers which classify the whole gesture (all the strokes which
+ * occurred from DOWN event to UP/CANCEL event)
+ */
+public abstract class GestureClassifier extends Classifier {
+
+ /**
+ * @param type the type of action for which this method is called
+ * @return a non-negative value which is used to determine whether the most recent gesture is a
+ * false interaction; the bigger the value the greater the chance that this a false
+ * interaction.
+ */
+ public abstract float getFalseTouchEvaluation(int type);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java
new file mode 100644
index 000000000000..85a9bee8d977
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+import java.util.ArrayList;
+
+/**
+ * Holds the evaluations for ended strokes and gestures. These values are decreased through time.
+ */
+public class HistoryEvaluator {
+ private static final float INTERVAL = 50.0f;
+ private static final float HISTORY_FACTOR = 0.9f;
+ private static final float EPSILON = 1e-5f;
+
+ private final ArrayList<Data> mStrokes = new ArrayList<>();
+ private final ArrayList<Data> mGestureWeights = new ArrayList<>();
+ private long mLastUpdate;
+
+ public HistoryEvaluator() {
+ mLastUpdate = System.currentTimeMillis();
+ }
+
+ public void addStroke(float evaluation) {
+ decayValue();
+ mStrokes.add(new Data(evaluation));
+ }
+
+ public void addGesture(float evaluation) {
+ decayValue();
+ mGestureWeights.add(new Data(evaluation));
+ }
+
+ /**
+ * Calculates the weighted average of strokes and adds to it the weighted average of gestures
+ */
+ public float getEvaluation() {
+ return weightedAverage(mStrokes) + weightedAverage(mGestureWeights);
+ }
+
+ private float weightedAverage(ArrayList<Data> list) {
+ float sumValue = 0.0f;
+ float sumWeight = 0.0f;
+ int size = list.size();
+ for (int i = 0; i < size; i++) {
+ Data data = list.get(i);
+ sumValue += data.evaluation * data.weight;
+ sumWeight += data.weight;
+ }
+
+ if (sumWeight == 0.0f) {
+ return 0.0f;
+ }
+
+ return sumValue / sumWeight;
+ }
+
+ private void decayValue() {
+ long currentTimeMillis = System.currentTimeMillis();
+
+ // All weights are multiplied by HISTORY_FACTOR after each INTERVAL milliseconds.
+ float factor = (float) Math.pow(HISTORY_FACTOR,
+ (float) (currentTimeMillis - mLastUpdate) / INTERVAL);
+
+ decayValue(mStrokes, factor);
+ decayValue(mGestureWeights, factor);
+ mLastUpdate = currentTimeMillis;
+ }
+
+ private void decayValue(ArrayList<Data> list, float factor) {
+ int size = list.size();
+ for (int i = 0; i < size; i++) {
+ list.get(i).weight *= factor;
+ }
+
+ // Removing evaluations with such small weights that they do not matter anymore
+ while (!list.isEmpty() && isZero(list.get(0).weight)) {
+ list.remove(0);
+ }
+ }
+
+ private boolean isZero(float x) {
+ return x <= EPSILON && x >= -EPSILON;
+ }
+
+ /**
+ * For each stroke it holds its initial value and the current weight. Initially the
+ * weight is set to 1.0
+ */
+ private static class Data {
+ public float evaluation;
+ public float weight;
+
+ public Data(float evaluation) {
+ this.evaluation = evaluation;
+ weight = 1.0f;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index a5f6df858d2c..6ef805c569dd 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -25,6 +25,8 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.view.MotionEvent;
+import java.util.ArrayList;
+
/**
* An classifier trying to determine whether it is a human interacting with the phone or not.
*/
@@ -35,8 +37,14 @@ public class HumanInteractionClassifier extends Classifier {
private final Handler mHandler = new Handler();
private final Context mContext;
- private AnglesVarianceClassifier mAnglesVarianceClassifier;
+ private ArrayList<StrokeClassifier> mStrokeClassifiers = new ArrayList<>();
+ private ArrayList<GestureClassifier> mGestureClassifiers = new ArrayList<>();
+ private final int mStrokeClassifiersSize;
+ private final int mGestureClassifiersSize;
+
+ private HistoryEvaluator mHistoryEvaluator;
private boolean mEnableClassifier = false;
+ private int mCurrentType = Classifier.GENERIC;
protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@Override
@@ -47,8 +55,24 @@ public class HumanInteractionClassifier extends Classifier {
private HumanInteractionClassifier(Context context) {
mContext = context;
- mClassifierData = new ClassifierData();
- mAnglesVarianceClassifier = new AnglesVarianceClassifier(mClassifierData);
+ mClassifierData = new ClassifierData(mContext.getResources().getDisplayMetrics().xdpi,
+ mContext.getResources().getDisplayMetrics().ydpi);
+ mHistoryEvaluator = new HistoryEvaluator();
+
+ mStrokeClassifiers.add(new AnglesVarianceClassifier(mClassifierData));
+ mStrokeClassifiers.add(new SpeedClassifier(mClassifierData));
+ mStrokeClassifiers.add(new DurationCountClassifier(mClassifierData));
+ mStrokeClassifiers.add(new EndPointRatioClassifier(mClassifierData));
+ mStrokeClassifiers.add(new EndPointLengthClassifier(mClassifierData));
+ mStrokeClassifiers.add(new AccelerationClassifier(mClassifierData));
+ mStrokeClassifiers.add(new SpeedVarianceClassifier(mClassifierData));
+ mStrokeClassifiers.add(new LengthCountClassifier(mClassifierData));
+
+ mGestureClassifiers.add(new PointerCountClassifier(mClassifierData));
+ mGestureClassifiers.add(new ProximityClassifier(mClassifierData));
+
+ mStrokeClassifiersSize = mStrokeClassifiers.size();
+ mGestureClassifiersSize = mGestureClassifiers.size();
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(HIC_ENABLE), false,
@@ -71,25 +95,61 @@ public class HumanInteractionClassifier extends Classifier {
HIC_ENABLE, 0);
}
+ public void setType(int type) {
+ mCurrentType = type;
+ }
+
@Override
public void onTouchEvent(MotionEvent event) {
if (mEnableClassifier) {
mClassifierData.update(event);
- mAnglesVarianceClassifier.onTouchEvent(event);
+
+ for (int i = 0; i < mStrokeClassifiersSize; i++) {
+ mStrokeClassifiers.get(i).onTouchEvent(event);
+ }
+
+ for (int i = 0; i < mGestureClassifiersSize; i++) {
+ mGestureClassifiers.get(i).onTouchEvent(event);
+ }
+
+ int size = mClassifierData.getEndingStrokes().size();
+ for (int i = 0; i < size; i++) {
+ Stroke stroke = mClassifierData.getEndingStrokes().get(i);
+ float evaluation = 0.0f;
+ for (int j = 0; j < mStrokeClassifiersSize; j++) {
+ evaluation += mStrokeClassifiers.get(j).getFalseTouchEvaluation(
+ mCurrentType, stroke);
+ }
+ mHistoryEvaluator.addStroke(evaluation);
+ }
+
+ int action = event.getActionMasked();
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ float evaluation = 0.0f;
+ for (int i = 0; i < mGestureClassifiersSize; i++) {
+ evaluation += mGestureClassifiers.get(i).getFalseTouchEvaluation(mCurrentType);
+ }
+ mHistoryEvaluator.addGesture(evaluation);
+ setType(Classifier.GENERIC);
+ }
+
mClassifierData.cleanUp(event);
}
}
@Override
public void onSensorChanged(SensorEvent event) {
- }
+ for (int i = 0; i < mStrokeClassifiers.size(); i++) {
+ mStrokeClassifiers.get(i).onSensorChanged(event);
+ }
- @Override
- public float getFalseTouchEvaluation(int type) {
- if (mEnableClassifier) {
- return mAnglesVarianceClassifier.getFalseTouchEvaluation(type);
+ for (int i = 0; i < mGestureClassifiers.size(); i++) {
+ mGestureClassifiers.get(i).onSensorChanged(event);
}
- return 0.0f;
+ }
+
+ public boolean isFalseTouch() {
+ return mHistoryEvaluator.getEvaluation() >= 5.0f;
}
public boolean isEnabled() {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java
new file mode 100644
index 000000000000..1ea467bfb857
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+/**
+ * A classifier which looks at the ratio between the duration of the stroke and its number of
+ * points.
+ */
+public class LengthCountClassifier extends StrokeClassifier {
+ public LengthCountClassifier(ClassifierData classifierData) {
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ return LengthCountEvaluator.evaluate(stroke.getTotalLength() / stroke.getCount());
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java
new file mode 100644
index 000000000000..68f163d1916b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+/**
+ * A classifier which looks at the ratio between the length of the stroke and its number of
+ * points.
+ */
+public class LengthCountEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value < 0.07) evaluation++;
+ if (value < 0.05) evaluation++;
+ if (value < 0.02) evaluation++;
+ if (value > 0.6) evaluation++;
+ if (value > 1.2) evaluation++;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Point.java b/packages/SystemUI/src/com/android/systemui/classifier/Point.java
index e7dbae19eb31..f3dc2be4144b 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/Point.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/Point.java
@@ -56,4 +56,28 @@ public class Point {
public float dotProduct(Point a, Point b) {
return (a.x - x) * (b.x - x) + (a.y - y) * (b.y - y);
}
+
+ /**
+ * Calculates the angle in radians created by points (a, this, b). If any two of these points
+ * are the same, the method will return 0.0f
+ *
+ * @return the angle in radians
+ */
+ public float getAngle(Point a, Point b) {
+ float dist1 = dist(a);
+ float dist2 = dist(b);
+
+ if (dist1 == 0.0f || dist2 == 0.0f) {
+ return 0.0f;
+ }
+
+ float crossProduct = crossProduct(a, b);
+ float dotProduct = dotProduct(a, b);
+ float cos = Math.min(1.0f, Math.max(-1.0f, dotProduct / dist1 / dist2));
+ float angle = (float) Math.acos(cos);
+ if (crossProduct < 0.0) {
+ angle = 2.0f * (float) Math.PI - angle;
+ }
+ return angle;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java
new file mode 100644
index 000000000000..5097b635807e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+import android.view.MotionEvent;
+
+/**
+ * A classifier which looks at the total number of traces in the whole gesture.
+ */
+public class PointerCountClassifier extends GestureClassifier {
+ private int mCount;
+
+ public PointerCountClassifier(ClassifierData classifierData) {
+ mCount = 0;
+ }
+
+ @Override
+ public void onTouchEvent(MotionEvent event) {
+ int action = event.getActionMasked();
+
+ if (action == MotionEvent.ACTION_DOWN) {
+ mCount = 1;
+ }
+
+ if (action == MotionEvent.ACTION_POINTER_DOWN) {
+ ++mCount;
+ }
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type) {
+ return PointerCountEvaluator.evaluate(mCount);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountEvaluator.java
new file mode 100644
index 000000000000..d7a3af0360af
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountEvaluator.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+public class PointerCountEvaluator {
+ public static float evaluate(int value) {
+ return (value - 1) * (value - 1);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
new file mode 100644
index 000000000000..69950640337f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.view.MotionEvent;
+
+/**
+ * A classifier which looks at the proximity sensor during the gesture. It calculates the percentage
+ * the proximity sensor showing the near state during the whole gesture
+ */
+public class ProximityClassifier extends GestureClassifier {
+ private long mGestureStartTimeNano;
+ private long mNearStartTimeNano;
+ private long mNearDuration;
+ private boolean mNear;
+ private float mAverageNear;
+
+ public ProximityClassifier(ClassifierData classifierData) {
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) {
+ update(event.values[0] < event.sensor.getMaximumRange(), event.timestamp);
+ }
+ }
+
+ @Override
+ public void onTouchEvent(MotionEvent event) {
+ int action = event.getActionMasked();
+
+ if (action == MotionEvent.ACTION_DOWN) {
+ mGestureStartTimeNano = event.getEventTimeNano();
+ mNearStartTimeNano = event.getEventTimeNano();
+ mNearDuration = 0;
+ }
+
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ update(mNear, event.getEventTimeNano());
+ long duration = event.getEventTimeNano() - mGestureStartTimeNano;
+
+ if (duration == 0) {
+ mAverageNear = mNear ? 1.0f : 0.0f;
+ } else {
+ mAverageNear = (float) mNearDuration / (float) duration;
+ }
+ }
+ }
+
+
+ /**
+ * @param near is the sensor showing the near state right now
+ * @param timestampNano time of this event in nanoseconds
+ */
+ private void update(boolean near, long timestampNano) {
+ // This if is necessary because MotionEvents and SensorEvents do not come in
+ // chronological order
+ if (timestampNano > mNearStartTimeNano) {
+ // if the state before was near then add the difference of the current time and
+ // mNearStartTimeNano to mNearDuration.
+ if (mNear) {
+ mNearDuration += timestampNano - mNearStartTimeNano;
+ }
+
+ // if the new state is near, set mNearStartTimeNano equal to this moment.
+ if (near) {
+ mNearStartTimeNano = timestampNano;
+ }
+ }
+ mNear = near;
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type) {
+ return ProximityEvaluator.evaluate(mAverageNear, type);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityEvaluator.java
new file mode 100644
index 000000000000..91002bf1291c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityEvaluator.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+public class ProximityEvaluator {
+ public static float evaluate(float value, int type) {
+ float evaluation = 0.0f;
+ float threshold = 0.1f;
+ if (type == Classifier.QUICK_SETTINGS) {
+ threshold = 1.0f;
+ }
+ if (value >= threshold) evaluation += 2.0;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.java
new file mode 100644
index 000000000000..81b78c7ecdfe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+/**
+ * A classifier that looks at the speed of the stroke. It calculates the speed of a stroke in
+ * inches per second.
+ */
+public class SpeedClassifier extends StrokeClassifier {
+ private final float NANOS_TO_SECONDS = 1e9f;
+
+ public SpeedClassifier(ClassifierData classifierData) {
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ float duration = (float) stroke.getDurationNanos() / NANOS_TO_SECONDS;
+ if (duration == 0.0f) {
+ return SpeedEvaluator.evaluate(0.0f);
+ }
+ return SpeedEvaluator.evaluate(stroke.getTotalLength() / duration);
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java
new file mode 100644
index 000000000000..c0e4a2ddc89a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+public class SpeedEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value < 4.0 || value > 35.0) evaluation += 1.0;
+ if (value < 2.2) evaluation += 1.0;
+ if (value > 50.0) evaluation += 1.0;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
new file mode 100644
index 000000000000..349aa9ed49d6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+public class SpeedRatioEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value > 9.0) ++evaluation;
+ if (value > 18.0) ++evaluation;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceClassifier.java
new file mode 100644
index 000000000000..9a30fe1a425c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceClassifier.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+import android.view.MotionEvent;
+
+import java.lang.Math;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * A classifier which for each point from a stroke, it creates a point on plane with coordinates
+ * (timeOffsetNano, distanceCoveredUpToThisPoint) (scaled by DURATION_SCALE and LENGTH_SCALE)
+ * and then it calculates the angle variance of these points like the class
+ * {@link AnglesVarianceClassifier} (without splitting it into two parts). The classifier ignores
+ * the last point of a stroke because the UP event comes in with some delay and this ruins the
+ * smoothness of this curve
+ */
+public class SpeedVarianceClassifier extends StrokeClassifier {
+ private HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
+
+ public SpeedVarianceClassifier(ClassifierData classifierData) {
+ mClassifierData = classifierData;
+ }
+
+ @Override
+ public void onTouchEvent(MotionEvent event) {
+ int action = event.getActionMasked();
+
+ if (action == MotionEvent.ACTION_DOWN) {
+ mStrokeMap.clear();
+ }
+
+ for (int i = 0; i < event.getPointerCount(); i++) {
+ Stroke stroke = mClassifierData.getStroke(event.getPointerId(i));
+
+ if (mStrokeMap.get(stroke) == null) {
+ mStrokeMap.put(stroke, new Data());
+ }
+
+ if (action != MotionEvent.ACTION_UP && action != MotionEvent.ACTION_CANCEL
+ && !(action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) {
+ mStrokeMap.get(stroke).addPoint(
+ stroke.getPoints().get(stroke.getPoints().size() - 1));
+ }
+ }
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ return SpeedVarianceEvaluator.evaluate(mStrokeMap.get(stroke).getAnglesVariance());
+ }
+
+ private static class Data {
+ private final float DURATION_SCALE = 1e8f;
+ private final float LENGTH_SCALE = 1.0f;
+
+ private List<Point> mLastThreePoints = new ArrayList<>();
+ private Point mPreviousPoint;
+ private float mPreviousAngle;
+ private float mSumSquares;
+ private float mSum;
+ private float mCount;
+ private float mDist;
+
+ public Data() {
+ mPreviousPoint = null;
+ mPreviousAngle = (float) Math.PI;
+ mSumSquares = 0.0f;
+ mSum = 0.0f;
+ mCount = 1.0f;
+ mDist = 0.0f;
+ }
+
+ public void addPoint(Point point) {
+ if (mPreviousPoint != null) {
+ mDist += mPreviousPoint.dist(point);
+ }
+
+ mPreviousPoint = point;
+ Point speedPoint = new Point((float) point.timeOffsetNano / DURATION_SCALE,
+ mDist / LENGTH_SCALE);
+
+ // Checking if the added point is different than the previously added point
+ // Repetitions are being ignored so that proper angles are calculated.
+ if (mLastThreePoints.isEmpty()
+ || !mLastThreePoints.get(mLastThreePoints.size() - 1).equals(speedPoint)) {
+ mLastThreePoints.add(speedPoint);
+ if (mLastThreePoints.size() == 4) {
+ mLastThreePoints.remove(0);
+
+ float angle = mLastThreePoints.get(1).getAngle(mLastThreePoints.get(0),
+ mLastThreePoints.get(2));
+
+ float difference = angle - mPreviousAngle;
+ mSum += difference;
+ mSumSquares += difference * difference;
+ mCount += 1.0;
+ mPreviousAngle = angle;
+ }
+ }
+ }
+
+ public float getAnglesVariance() {
+ return mSumSquares / mCount - (mSum / mCount) * (mSum / mCount);
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java
new file mode 100644
index 000000000000..8f9a7e159638
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+public class SpeedVarianceEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value > 0.06) evaluation += 1.0;
+ if (value > 0.15) evaluation += 1.0;
+ if (value > 0.3) evaluation += 1.0;
+ if (value > 0.6) evaluation += 1.0;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java b/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java
index f386cbe458e6..49e6fb8b62c9 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java
@@ -19,20 +19,52 @@ package com.android.systemui.classifier;
import java.util.ArrayList;
/**
- * Contains data about movement traces (pointers)
+ * Contains data about a stroke (a single trace, all the events from a given id from the
+ * DOWN/POINTER_DOWN event till the UP/POINTER_UP/CANCEL event.)
*/
public class Stroke {
+ private final float NANOS_TO_SECONDS = 1e9f;
+
private ArrayList<Point> mPoints = new ArrayList<>();
private long mStartTimeNano;
private long mEndTimeNano;
+ private float mLength;
+ private float mXdpi;
+ private float mYdpi;
- public Stroke(long eventTimeNano) {
+ public Stroke(long eventTimeNano, float xdpi, float ydpi) {
+ mXdpi = xdpi;
+ mYdpi = ydpi;
mStartTimeNano = mEndTimeNano = eventTimeNano;
}
public void addPoint(float x, float y, long eventTimeNano) {
mEndTimeNano = eventTimeNano;
- mPoints.add(new Point(x, y, eventTimeNano - mStartTimeNano));
+ Point point = new Point(x / mXdpi, y / mYdpi, eventTimeNano - mStartTimeNano);
+ if (!mPoints.isEmpty()) {
+ mLength += mPoints.get(mPoints.size() - 1).dist(point);
+ }
+ mPoints.add(point);
+ }
+
+ public int getCount() {
+ return mPoints.size();
+ }
+
+ public float getTotalLength() {
+ return mLength;
+ }
+
+ public float getEndPointLength() {
+ return mPoints.get(0).dist(mPoints.get(mPoints.size() - 1));
+ }
+
+ public long getDurationNanos() {
+ return mEndTimeNano - mStartTimeNano;
+ }
+
+ public float getDurationSeconds() {
+ return (float) getDurationNanos() / NANOS_TO_SECONDS;
}
public ArrayList<Point> getPoints() {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java
new file mode 100644
index 000000000000..5da392f31d63
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+/**
+ * An abstract class for classifiers which classify each stroke separately.
+ */
+public abstract class StrokeClassifier extends Classifier {
+
+ /**
+ * @param type the type of action for which this method is called
+ * @param stroke the stroke for which the evaluation will be calculated
+ * @return a non-negative value which is used to determine whether this a false touch; the
+ * bigger the value the greater the chance that this a false touch
+ */
+ public abstract float getFalseTouchEvaluation(int type, Stroke stroke);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 3de500165185..2ea1e43b39a2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -921,9 +921,27 @@ public class KeyguardViewMediator extends SystemUI {
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
}
+ } else if (!isSecure()) {
+
+ // Keyguard is not secure, no need to do anything, and we don't need to reshow
+ // the Keyguard after the client releases the Keyguard lock.
+ mExternallyEnabled = true;
+ mNeedToReshowWhenReenabled = false;
+ updateInputRestricted();
+ try {
+ callback.onKeyguardExitResult(true);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ }
} else {
- mExitSecureCallback = callback;
- verifyUnlockLocked();
+
+ // Since we prevent apps from hiding the Keyguard if we are secure, this should be
+ // a no-op as well.
+ try {
+ callback.onKeyguardExitResult(false);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index 7f68e290f3a0..f39f3026f26b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -160,7 +160,7 @@ public class RingtonePlayer extends SystemUI {
throw new SecurityException("Async playback only available from system UID.");
}
if (UserHandle.ALL.equals(user)) {
- user = UserHandle.OWNER;
+ user = UserHandle.SYSTEM;
}
mAsyncPlayer.play(getContextForUser(user), uri, looping, aa);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QWifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QWifiTile.java
index 87194fb840d1..b1572754fb6b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QWifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QWifiTile.java
@@ -17,6 +17,7 @@
package com.android.systemui.qs.tiles;
import com.android.systemui.qs.QSTileView;
+import com.android.systemui.statusbar.policy.WifiIcons;
/** Quick settings tile: Wifi **/
public class QWifiTile extends WifiTile {
@@ -29,4 +30,23 @@ public class QWifiTile extends WifiTile {
public int getTileType() {
return QSTileView.QS_TYPE_QUICK;
}
+
+ @Override
+ protected void handleUpdateState(SignalState state, Object arg) {
+ super.handleUpdateState(state, arg);
+
+ CallbackInfo cb = (CallbackInfo) arg;
+ if (cb == null) {
+ cb = mSignalCallback.mInfo;
+ }
+ boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null);
+
+ if (state.enabled && wifiConnected) {
+ // Only show full signal here.
+ state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_SIGNAL_STRENGTH[1][4]);
+ }
+ // No activity in the quick toggle.
+ state.activityIn = false;
+ state.activityOut = false;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 3295e14e0ae5..91e02183818f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -48,7 +48,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
private final WifiDetailAdapter mDetailAdapter;
private final QSTile.SignalState mStateBeforeClick = newTileState();
- private final WifiSignalCallback mSignalCallback = new WifiSignalCallback();
+ protected final WifiSignalCallback mSignalCallback = new WifiSignalCallback();
private final boolean mAlwaysDetail;
@@ -200,7 +200,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
return string;
}
- private static final class CallbackInfo {
+ protected static final class CallbackInfo {
boolean enabled;
boolean connected;
int wifiSignalIconId;
@@ -223,7 +223,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
}
}
- private final class WifiSignalCallback extends SignalCallbackAdapter {
+ protected final class WifiSignalCallback extends SignalCallbackAdapter {
final CallbackInfo mInfo = new CallbackInfo();
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 308e7cc9e012..cbccaf887d69 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -151,7 +151,8 @@ public class Recents extends SystemUI
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case ACTION_PROXY_NOTIFY_RECENTS_VISIBLITY_TO_OWNER:
- visibilityChanged(intent.getBooleanExtra(EXTRA_RECENTS_VISIBILITY, false));
+ visibilityChanged(context,
+ intent.getBooleanExtra(EXTRA_RECENTS_VISIBILITY, false));
break;
case ACTION_PROXY_SCREEN_PINNING_REQUEST_TO_OWNER:
onStartScreenPinning(context);
@@ -160,7 +161,6 @@ public class Recents extends SystemUI
}
}
- static RecentsComponent.Callbacks sRecentsComponentCallbacks;
static RecentsTaskLoadPlan sInstanceLoadPlan;
static Recents sInstance;
@@ -834,18 +834,12 @@ public class Recents extends SystemUI
mCanReuseTaskStackViews = true;
}
- /** Sets the RecentsComponent callbacks. */
- @Override
- public void setCallback(RecentsComponent.Callbacks cb) {
- sRecentsComponentCallbacks = cb;
- }
-
/** Notifies the callbacks that the visibility of Recents has changed. */
@ProxyFromAnyToSystemUser
public static void notifyVisibilityChanged(Context context, SystemServicesProxy ssp,
boolean visible) {
if (ssp.isForegroundUserSystem()) {
- visibilityChanged(visible);
+ visibilityChanged(context, visible);
} else {
Intent intent = createLocalBroadcastIntent(context,
ACTION_PROXY_NOTIFY_RECENTS_VISIBLITY_TO_OWNER);
@@ -853,9 +847,13 @@ public class Recents extends SystemUI
context.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
}
}
- static void visibilityChanged(boolean visible) {
- if (sRecentsComponentCallbacks != null) {
- sRecentsComponentCallbacks.onVisibilityChanged(visible);
+ static void visibilityChanged(Context context, boolean visible) {
+ // For the primary user, the context for the SystemUI component is the SystemUIApplication
+ SystemUIApplication app = (SystemUIApplication)
+ getInstanceAndStartIfNeeded(context.getApplicationContext()).mContext;
+ PhoneStatusBar statusBar = app.getComponent(PhoneStatusBar.class);
+ if (statusBar != null) {
+ statusBar.updateRecentsVisibility(visible);
}
}
@@ -873,7 +871,7 @@ public class Recents extends SystemUI
static void onStartScreenPinning(Context context) {
// For the primary user, the context for the SystemUI component is the SystemUIApplication
SystemUIApplication app = (SystemUIApplication)
- getInstanceAndStartIfNeeded(context).mContext;
+ getInstanceAndStartIfNeeded(context.getApplicationContext()).mContext;
PhoneStatusBar statusBar = app.getComponent(PhoneStatusBar.class);
if (statusBar != null) {
statusBar.showScreenPinningRequest(false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 2c964be44cac..e7a3c8a3fe72 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -115,8 +115,7 @@ import static com.android.keyguard.KeyguardHostView.OnDismissAction;
public abstract class BaseStatusBar extends SystemUI implements
CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
- RecentsComponent.Callbacks, ExpandableNotificationRow.ExpansionLogger,
- NotificationData.Environment {
+ ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment {
public static final String TAG = "StatusBar";
public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
public static final boolean MULTIUSER_DEBUG = false;
@@ -577,7 +576,6 @@ public abstract class BaseStatusBar extends SystemUI implements
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mRecents = getComponent(Recents.class);
- mRecents.setCallback(this);
final Configuration currentConfig = mContext.getResources().getConfiguration();
mLocale = currentConfig.locale;
@@ -1174,11 +1172,6 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
- @Override
- public void onVisibilityChanged(boolean visible) {
- // Do nothing
- }
-
/**
* If there is an active heads-up notification and it has a fullscreen intent, fire it now.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 5a2fa3bad127..1d890d0dde6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -33,7 +33,7 @@ public class DozeParameters {
private static final String TAG = "DozeParameters";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final int MAX_DURATION = 10 * 1000;
+ private static final int MAX_DURATION = 60 * 1000;
private final Context mContext;
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 13d0e1e0fbc3..3feead8f36ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -610,7 +610,7 @@ public abstract class PanelView extends FrameLayout {
if (!mStatusBar.isFalsingThresholdNeeded()) {
return false;
}
- if (mFalsingManager.isFalseTouch(Classifier.UNLOCK)) {
+ if (mFalsingManager.isFalseTouch()) {
return true;
}
if (!mTouchAboveFalsingThreshold) {
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 7f4be65c946f..151fa3c5a033 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -4106,8 +4106,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
super.toggleRecents();
}
- @Override
- public void onVisibilityChanged(boolean visible) {
+ public void updateRecentsVisibility(boolean visible) {
// Update the recents visibility flag
if (visible) {
mSystemUiVisibility |= View.RECENT_APPS_VISIBLE;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 394ff3f8245c..05f6e57d9199 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -466,7 +466,7 @@ public class StatusBarKeyguardViewManager {
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
if ((showing && !occluded) != (mLastShowing && !mLastOccluded) || mFirstUpdate) {
- updateMonitor.sendKeyguardVisibilityChanged(showing && !occluded);
+ updateMonitor.onKeyguardVisibilityChanged(showing && !occluded);
}
if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
updateMonitor.sendKeyguardBouncerChanged(bouncerShowing);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
index c56646fc7740..374408d3ec7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
@@ -18,7 +18,7 @@ package com.android.systemui.statusbar.policy;
import com.android.systemui.R;
-class WifiIcons {
+public class WifiIcons {
static final int[][] WIFI_SIGNAL_STRENGTH = {
{ R.drawable.stat_sys_wifi_signal_0,
R.drawable.stat_sys_wifi_signal_1,
@@ -32,7 +32,7 @@ class WifiIcons {
R.drawable.stat_sys_wifi_signal_4_fully }
};
- static final int[][] QS_WIFI_SIGNAL_STRENGTH = {
+ public static final int[][] QS_WIFI_SIGNAL_STRENGTH = {
{ R.drawable.ic_qs_wifi_0,
R.drawable.ic_qs_wifi_1,
R.drawable.ic_qs_wifi_2,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index b2f527e3bbb4..da19b06d2f40 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -89,7 +89,6 @@ public class VolumeDialog {
private static final long USER_ATTEMPT_GRACE_PERIOD = 1000;
private static final int WAIT_FOR_RIPPLE = 200;
- private static final int UPDATE_ANIMATION_DURATION = 80;
private final Context mContext;
private final H mHandler = new H();
@@ -353,14 +352,6 @@ public class VolumeDialog {
writer.println(mAccessibility.mFeedbackEnabled);
}
- private static int getImpliedLevel(SeekBar seekBar, int progress) {
- final int m = seekBar.getMax();
- final int n = m / 100 - 1;
- final int level = progress == 0 ? 0
- : progress == m ? (m / 100) : (1 + (int)((progress / (float) m) * n));
- return level;
- }
-
@SuppressLint("InflateParams")
private VolumeRow initRow(final int stream, int iconRes, int iconMuteRes, boolean important) {
final VolumeRow row = new VolumeRow();
@@ -690,7 +681,7 @@ public class VolumeDialog {
: false;
// update slider max
- final int max = ss.levelMax * 100;
+ final int max = ss.levelMax;
if (max != row.slider.getMax()) {
row.slider.setMax(max);
}
@@ -777,8 +768,7 @@ public class VolumeDialog {
if (row.tracking) {
return; // don't update if user is sliding
}
- final int progress = row.slider.getProgress();
- final int level = getImpliedLevel(row.slider, progress);
+ final int level = row.slider.getProgress();
final boolean rowVisible = row.view.getVisibility() == View.VISIBLE;
final boolean inGracePeriod = (SystemClock.uptimeMillis() - row.userAttempt)
< USER_ATTEMPT_GRACE_PERIOD;
@@ -794,33 +784,7 @@ public class VolumeDialog {
return; // don't clamp if visible
}
}
- final int newProgress = vlevel * 100;
- if (progress != newProgress) {
- if (mShowing && rowVisible) {
- // animate!
- if (row.anim != null && row.anim.isRunning()
- && row.animTargetProgress == newProgress) {
- return; // already animating to the target progress
- }
- // start/update animation
- if (row.anim == null) {
- row.anim = ObjectAnimator.ofInt(row.slider, "progress", progress, newProgress);
- row.anim.setInterpolator(new DecelerateInterpolator());
- } else {
- row.anim.cancel();
- row.anim.setIntValues(progress, newProgress);
- }
- row.animTargetProgress = newProgress;
- row.anim.setDuration(UPDATE_ANIMATION_DURATION);
- row.anim.start();
- } else {
- // update slider directly to clamped value
- if (row.anim != null) {
- row.anim.cancel();
- }
- row.slider.setProgress(newProgress);
- }
- }
+ row.slider.setProgress(vlevel, true);
}
private void recheckH(VolumeRow row) {
@@ -1025,20 +989,19 @@ public class VolumeDialog {
+ " onProgressChanged " + progress + " fromUser=" + fromUser);
if (!fromUser) return;
if (mRow.ss.levelMin > 0) {
- final int minProgress = mRow.ss.levelMin * 100;
+ final int minProgress = mRow.ss.levelMin;
if (progress < minProgress) {
seekBar.setProgress(minProgress);
progress = minProgress;
}
}
- final int userLevel = getImpliedLevel(seekBar, progress);
- if (mRow.ss.level != userLevel || mRow.ss.muted && userLevel > 0) {
+ if (mRow.ss.level != progress || mRow.ss.muted && progress > 0) {
mRow.userAttempt = SystemClock.uptimeMillis();
- if (mRow.requestedLevel != userLevel) {
- mController.setStreamVolume(mRow.stream, userLevel);
- mRow.requestedLevel = userLevel;
+ if (mRow.requestedLevel != progress) {
+ mController.setStreamVolume(mRow.stream, progress);
+ mRow.requestedLevel = progress;
Events.writeEvent(mContext, Events.EVENT_TOUCH_LEVEL_CHANGED, mRow.stream,
- userLevel);
+ progress);
}
}
}
@@ -1055,7 +1018,7 @@ public class VolumeDialog {
if (D.BUG) Log.d(TAG, "onStopTrackingTouch"+ " " + mRow.stream);
mRow.tracking = false;
mRow.userAttempt = SystemClock.uptimeMillis();
- int userLevel = getImpliedLevel(seekBar, seekBar.getProgress());
+ final int userLevel = seekBar.getProgress();
Events.writeEvent(mContext, Events.EVENT_TOUCH_LEVEL_DONE, mRow.stream, userLevel);
if (mRow.ss.level != userLevel) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(H.RECHECK, mRow),
@@ -1137,8 +1100,6 @@ public class VolumeDialog {
private int iconState; // from Events
private boolean cachedShowHeaders = VolumePrefs.DEFAULT_SHOW_HEADERS;
private int cachedExpandButtonRes;
- private ObjectAnimator anim; // slider progress animation for non-touch-related updates
- private int animTargetProgress;
private int lastAudibleLevel = 1;
}
diff --git a/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp b/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp
index 272733893280..990d7707cdfb 100644
--- a/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp
+++ b/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp
@@ -130,7 +130,7 @@ static jstring com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked(J
return jret;
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "createV8ParserNativeLocked", "()Z",
(void*)com_android_pacprocessor_PacNative_createV8ParserNativeLocked},
{ "destroyV8ParserNativeLocked", "()Z",
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 0419d33c686c..8c830e8d9257 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -2494,7 +2494,7 @@ nSystemGetPointerSize(JNIEnv *_env, jobject _this) {
static const char *classPathName = "android/renderscript/RenderScript";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nInit", "()V", (void*)_nInit },
{"nDeviceCreate", "()J", (void*)nDeviceCreate },
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 91c3d48d1274..ff2a2ee3ca26 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -967,8 +967,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser(
new Intent(AccessibilityService.SERVICE_INTERFACE),
- PackageManager.GET_SERVICES
- | PackageManager.GET_META_DATA
+ PackageManager.GET_SERVICES
+ | PackageManager.GET_META_DATA
| PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
mCurrentUserId);
@@ -3217,7 +3217,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
- case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY: {
+ case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
+ case WindowManager.LayoutParams.TYPE_DOCK_DIVIDER: {
return AccessibilityWindowInfo.TYPE_SYSTEM;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AutoclickController.java b/services/accessibility/java/com/android/server/accessibility/AutoclickController.java
index 2e6136fc111b..8989625f979a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AutoclickController.java
+++ b/services/accessibility/java/com/android/server/accessibility/AutoclickController.java
@@ -16,9 +16,16 @@
package com.android.server.accessibility;
+import android.annotation.NonNull;
+import android.content.ContentResolver;
import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
import android.os.Handler;
import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -46,16 +53,17 @@ import android.view.accessibility.AccessibilityEvent;
* the class should handle cases where multiple mouse devices are present.
*/
public class AutoclickController implements EventStreamTransformation {
- private static final String LOG_TAG = AutoclickController.class.getSimpleName();
- // TODO: Control click delay via settings.
- private static final int CLICK_DELAY_MS = 600;
+ public static final int DEFAULT_CLICK_DELAY_MS = 600;
+
+ private static final String LOG_TAG = AutoclickController.class.getSimpleName();
private EventStreamTransformation mNext;
- private Context mContext;
+ private final Context mContext;
// Lazily created on the first mouse motion event.
private ClickScheduler mClickScheduler;
+ private ClickDelayObserver mClickDelayObserver;
public AutoclickController(Context context) {
mContext = context;
@@ -66,7 +74,9 @@ public class AutoclickController implements EventStreamTransformation {
if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
if (mClickScheduler == null) {
Handler handler = new Handler(mContext.getMainLooper());
- mClickScheduler = new ClickScheduler(handler, CLICK_DELAY_MS);
+ mClickScheduler = new ClickScheduler(handler, DEFAULT_CLICK_DELAY_MS);
+ mClickDelayObserver = new ClickDelayObserver(handler);
+ mClickDelayObserver.start(mContext.getContentResolver(), mClickScheduler);
}
handleMouseMotion(event, policyFlags);
@@ -119,8 +129,13 @@ public class AutoclickController implements EventStreamTransformation {
@Override
public void onDestroy() {
+ if (mClickDelayObserver != null) {
+ mClickDelayObserver.stop();
+ mClickDelayObserver = null;
+ }
if (mClickScheduler != null) {
mClickScheduler.cancel();
+ mClickScheduler = null;
}
}
@@ -143,6 +158,80 @@ public class AutoclickController implements EventStreamTransformation {
}
/**
+ * Observes setting value for autoclick delay, and updates ClickScheduler delay whenever the
+ * setting value changes.
+ */
+ final private static class ClickDelayObserver extends ContentObserver {
+ /** URI used to identify the autoclick delay setting with content resolver. */
+ private final Uri mAutoclickDelaySettingUri = Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY);
+
+ private ContentResolver mContentResolver;
+ private ClickScheduler mClickScheduler;
+
+ public ClickDelayObserver(Handler handler) {
+ super(handler);
+ }
+
+ /**
+ * Starts the observer. And makes sure up-to-date autoclick delay is propagated to
+ * |clickScheduler|.
+ *
+ * @param contentResolver Content resolver that should be observed for setting's value
+ * changes.
+ * @param clickScheduler ClickScheduler that should be updated when click delay changes.
+ * @throws IllegalStateException If internal state is already setup when the method is
+ * called.
+ * @throws NullPointerException If any of the arguments is a null pointer.
+ */
+ public void start(@NonNull ContentResolver contentResolver,
+ @NonNull ClickScheduler clickScheduler) {
+ if (mContentResolver != null || mClickScheduler != null) {
+ throw new IllegalStateException("Observer already started.");
+ }
+ if (contentResolver == null) {
+ throw new NullPointerException("contentResolver not set.");
+ }
+ if (clickScheduler == null) {
+ throw new NullPointerException("clickScheduler not set.");
+ }
+
+ mContentResolver = contentResolver;
+ mClickScheduler = clickScheduler;
+ mContentResolver.registerContentObserver(mAutoclickDelaySettingUri, false, this,
+ UserHandle.USER_ALL);
+
+ // Initialize mClickScheduler's initial delay value.
+ onChange(true, mAutoclickDelaySettingUri);
+ }
+
+ /**
+ * Stops the the observer. Should only be called if the observer has been started.
+ *
+ * @throws IllegalStateException If internal state hasn't yet been initialized by calling
+ * {@link #start}.
+ */
+ public void stop() {
+ if (mContentResolver == null || mClickScheduler == null) {
+ throw new IllegalStateException("ClickDelayObserver not started.");
+ }
+
+ mContentResolver.unregisterContentObserver(this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (mAutoclickDelaySettingUri.equals(uri)) {
+ // TODO: Plumb current user id down to here and use getIntForUser.
+ int delay = Settings.Secure.getInt(
+ mContentResolver, Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
+ DEFAULT_CLICK_DELAY_MS);
+ mClickScheduler.updateDelay(delay);
+ }
+ }
+ }
+
+ /**
* Schedules and performs click event sequence that should be initiated when mouse pointer stops
* moving. The click is first scheduled when a mouse movement is detected, and then further
* delayed on every sufficient mouse movement.
@@ -242,6 +331,15 @@ public class AutoclickController implements EventStreamTransformation {
}
/**
+ * Updates delay that should be used when scheduling clicks. The delay will be used only for
+ * clicks scheduled after this point (pending click tasks are not affected).
+ * @param delay New delay value.
+ */
+ public void updateDelay(int delay) {
+ mDelay = delay;
+ }
+
+ /**
* Updates the time at which click sequence should occur.
*
* @param delay Delay (from now) after which click should occur.
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 2f4ad3ff0e29..0c6eb40f5b08 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -1523,13 +1523,13 @@ public class DeviceIdleController extends SystemService
private void reportPowerSaveWhitelistChangedLocked() {
Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
+ getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
}
private void reportTempWhitelistChangedLocked() {
Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
+ getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
}
void readConfigFileLocked() {
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index b9db89ecae64..245448748766 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -170,7 +170,7 @@ public final class DropBoxManagerService extends SystemService {
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_SEND_BROADCAST) {
- getContext().sendBroadcastAsUser((Intent)msg.obj, UserHandle.OWNER,
+ getContext().sendBroadcastAsUser((Intent)msg.obj, UserHandle.SYSTEM,
android.Manifest.permission.READ_LOGS);
}
}
@@ -488,7 +488,7 @@ public final class DropBoxManagerService extends SystemService {
///////////////////////////////////////////////////////////////////////////
- /** Chronologically sorted list of {@link #EntryFile} */
+ /** Chronologically sorted list of {@link EntryFile} */
private static final class FileList implements Comparable<FileList> {
public int blocks = 0;
public final TreeSet<EntryFile> contents = new TreeSet<EntryFile>();
@@ -613,7 +613,7 @@ public final class DropBoxManagerService extends SystemService {
/**
* Creates a EntryFile object with only a timestamp for comparison purposes.
- * @param timestampMillis to compare with.
+ * @param millis to compare with.
*/
public EntryFile(long millis) {
this.tag = null;
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index b826cfda0952..9bf2aaad597e 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -29,6 +29,9 @@ option java_package com.android.server
# This is logged when the partial wake lock (keeping the device awake
# regardless of whether the screen is off) is acquired or released.
2729 power_partial_wake_state (releasedorAcquired|1|5),(tag|3)
+# The device is being asked to go into a soft sleep (typically by the ungaze gesture).
+# It logs the time remaining before the device would've normally gone to sleep without the request.
+2731 power_soft_sleep_requested (savedwaketimems|2)
#
# Leave IDs through 2739 for more power logs (2730 used by battery_discharge above)
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index bd7d4b27e02c..7c85001c9175 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -101,8 +101,7 @@ public class GestureLauncherService extends SystemService {
* Whether camera double tap power button gesture is currently enabled;
*/
private boolean mCameraDoubleTapPowerEnabled;
- private long mLastPowerDownWhileNonInteractive;
- private long mLastPowerDownWhileInteractive;
+ private long mLastPowerDown;
public GestureLauncherService(Context context) {
super(context);
@@ -252,35 +251,32 @@ public class GestureLauncherService extends SystemService {
public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive) {
boolean launched = false;
boolean intercept = false;
+ long doubleTapInterval;
synchronized (this) {
- if (!mCameraDoubleTapPowerEnabled) {
- mLastPowerDownWhileNonInteractive = 0;
- mLastPowerDownWhileInteractive = 0;
- return false;
- }
- if (event.getEventTime() - mLastPowerDownWhileNonInteractive
- < CAMERA_POWER_DOUBLE_TAP_TIME_MS) {
- launched = true;
- intercept = true;
- } else if (event.getEventTime() - mLastPowerDownWhileInteractive
- < CAMERA_POWER_DOUBLE_TAP_TIME_MS) {
+ doubleTapInterval = event.getEventTime() - mLastPowerDown;
+ if (mCameraDoubleTapPowerEnabled
+ && doubleTapInterval < CAMERA_POWER_DOUBLE_TAP_TIME_MS) {
launched = true;
+ intercept = interactive;
}
- mLastPowerDownWhileNonInteractive = interactive ? 0 : event.getEventTime();
- mLastPowerDownWhileInteractive = interactive ? event.getEventTime() : 0;
+ mLastPowerDown = event.getEventTime();
}
if (launched) {
Slog.i(TAG, "Power button double tap gesture detected, launching camera.");
- launched = handleCameraLaunchGesture(false /* useWakelock */,
- MetricsLogger.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE);
+ launched = handleCameraLaunchGesture(false /* useWakelock */);
+ if (launched) {
+ MetricsLogger.action(mContext, MetricsLogger.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE,
+ (int) doubleTapInterval);
+ }
}
+ MetricsLogger.histogram(mContext, "power_double_tap_interval", (int) doubleTapInterval);
return intercept && launched;
}
/**
* @return true if camera was launched, false otherwise.
*/
- private boolean handleCameraLaunchGesture(boolean useWakelock, int logCategory) {
+ private boolean handleCameraLaunchGesture(boolean useWakelock) {
boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
if (!userSetupComplete) {
@@ -300,7 +296,6 @@ public class GestureLauncherService extends SystemService {
StatusBarManagerInternal service = LocalServices.getService(
StatusBarManagerInternal.class);
service.onCameraLaunchGestureDetected();
- MetricsLogger.action(mContext, logCategory);
return true;
}
@@ -339,8 +334,8 @@ public class GestureLauncherService extends SystemService {
Slog.d(TAG, String.format("Received a camera launch event: " +
"values=[%.4f, %.4f, %.4f].", values[0], values[1], values[2]));
}
- if (handleCameraLaunchGesture(true /* useWakelock */,
- MetricsLogger.ACTION_WIGGLE_CAMERA_GESTURE)) {
+ if (handleCameraLaunchGesture(true /* useWakelock */)) {
+ MetricsLogger.action(mContext, MetricsLogger.ACTION_WIGGLE_CAMERA_GESTURE);
trackCameraLaunchEvent(event);
}
return;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 885c765f3f4b..087ddd6fd882 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -211,8 +211,8 @@ public class LocationManagerService extends ILocationManager.Stub {
new ArrayList<LocationProviderProxy>();
// current active user on the device - other users are denied location data
- private int mCurrentUserId = UserHandle.USER_OWNER;
- private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_OWNER };
+ private int mCurrentUserId = UserHandle.USER_SYSTEM;
+ private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_SYSTEM };
public LocationManagerService(Context context) {
super();
@@ -1832,7 +1832,8 @@ public class LocationManagerService extends ILocationManager.Stub {
// geo-fence manager uses the public location API, need to clear identity
int uid = Binder.getCallingUid();
- if (UserHandle.getUserId(uid) != UserHandle.USER_OWNER) {
+ // TODO: http://b/23822629
+ if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
// temporary measure until geofences work for secondary users
Log.w(TAG, "proximity alerts are currently available only to the primary user");
return;
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 540f8cb8557c..c3d32c2a870b 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -2981,7 +2981,7 @@ class MountService extends IMountService.Stub
Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
if (mContext.bindServiceAsUser(service, mDefContainerConn, Context.BIND_AUTO_CREATE,
- UserHandle.OWNER)) {
+ UserHandle.SYSTEM)) {
mBound = true;
return true;
}
@@ -3014,7 +3014,6 @@ class MountService extends IMountService.Stub
Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
handleError();
- return;
} else {
handleExecute();
if (DEBUG_OBB)
@@ -3176,8 +3175,6 @@ class MountService extends IMountService.Stub
waitForReady();
warnOnNotMounted();
- final ObbInfo obbInfo = getObbInfo();
-
final ObbState existingState;
synchronized (mObbMounts) {
existingState = mObbPathToStateMap.get(mObbState.rawPath);
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index b05a6908aee5..b984e1938758 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -133,8 +133,8 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
filter.addDataSchemeSpecificPart(scorer.mPackageName,
PatternMatcher.PATTERN_LITERAL);
mReceiver = new ScorerChangedReceiver(scorer.mPackageName);
- // TODO: Need to update when we support per-user scorers.
- mContext.registerReceiverAsUser(mReceiver, UserHandle.OWNER, filter, null, null);
+ // TODO: Need to update when we support per-user scorers. http://b/23422763
+ mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter, null, null);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Registered receiver for " + scorer.mPackageName);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 372a5fad14c2..07a7af46e265 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -33,6 +33,7 @@ import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
import static com.android.server.am.ActivityManagerDebugConfig.*;
import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
+import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
@@ -2020,7 +2021,7 @@ public final class ActivityManagerService extends ActivityManagerNative
intent, PendingIntent.FLAG_CANCEL_CURRENT, null,
new UserHandle(userId)))
.setDeleteIntent(PendingIntent.getBroadcastAsUser(mContext, 0,
- deleteIntent, 0, UserHandle.OWNER))
+ deleteIntent, 0, UserHandle.SYSTEM))
.build();
try {
@@ -2378,8 +2379,8 @@ public final class ActivityManagerService extends ActivityManagerNative
mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));
// User 0 is the first and only user that runs at boot.
- mStartedUsers.put(UserHandle.USER_OWNER, new UserState(UserHandle.OWNER, true));
- mUserLru.add(UserHandle.USER_OWNER);
+ mStartedUsers.put(UserHandle.USER_SYSTEM, new UserState(UserHandle.SYSTEM, true));
+ mUserLru.add(UserHandle.USER_SYSTEM);
updateStartedUserArrayLocked();
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
@@ -4626,7 +4627,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// is hosted by the process... then make sure all visible
// activities are running, taking care of restarting this
// process.
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
}
@@ -5646,7 +5647,7 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
// Entire package setting changed
enabled = pm.getApplicationEnabledSetting(packageName,
- (userId != UserHandle.USER_ALL) ? userId : UserHandle.USER_OWNER);
+ (userId != UserHandle.USER_ALL) ? userId : UserHandle.USER_SYSTEM);
} catch (Exception e) {
// No such package/component; probably racing with uninstall. In any
// event it means we have nothing further to do here.
@@ -5664,7 +5665,7 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
enabled = pm.getComponentEnabledSetting(
new ComponentName(packageName, changedClass),
- (userId != UserHandle.USER_ALL) ? userId : UserHandle.USER_OWNER);
+ (userId != UserHandle.USER_ALL) ? userId : UserHandle.USER_SYSTEM);
} catch (Exception e) {
// As above, probably racing with uninstall.
return;
@@ -8664,14 +8665,14 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (task.mResizeable != resizeable) {
task.mResizeable = resizeable;
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mStackSupervisor.resumeTopActivitiesLocked();
}
}
}
@Override
- public void resizeTask(int taskId, Rect bounds, boolean resizedByUser) {
+ public void resizeTask(int taskId, Rect bounds, int resizeMode) {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
"resizeTask()");
long ident = Binder.clearCallingIdentity();
@@ -8682,7 +8683,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, "resizeTask: taskId=" + taskId + " not found");
return;
}
- mStackSupervisor.resizeTaskLocked(task, bounds, resizedByUser);
+ mStackSupervisor.resizeTaskLocked(task, bounds, resizeMode);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -9108,7 +9109,7 @@ public final class ActivityManagerService extends ActivityManagerNative
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
- mStackSupervisor.resizeStackLocked(stackId, bounds);
+ mStackSupervisor.resizeStackLocked(stackId, bounds, !PRESERVE_WINDOWS);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -9391,7 +9392,7 @@ public final class ActivityManagerService extends ActivityManagerNative
(ProviderInfo)providers.get(i);
boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,
cpi.name, cpi.flags);
- if (singleton && UserHandle.getUserId(app.uid) != UserHandle.USER_OWNER) {
+ if (singleton && UserHandle.getUserId(app.uid) != UserHandle.USER_SYSTEM) {
// This is a singleton provider, but a user besides the
// default user is asking to initialize a process it runs
// in... well, no, it doesn't actually run in this process,
@@ -9613,7 +9614,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- private final ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
+ private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
String name, IBinder token, boolean stable, int userId) {
ContentProviderRecord cpr;
ContentProviderConnection conn = null;
@@ -9641,14 +9642,14 @@ public final class ActivityManagerService extends ActivityManagerNative
cpr = mProviderMap.getProviderByName(name, userId);
// If that didn't work, check if it exists for user 0 and then
// verify that it's a singleton provider before using it.
- if (cpr == null && userId != UserHandle.USER_OWNER) {
- cpr = mProviderMap.getProviderByName(name, UserHandle.USER_OWNER);
+ if (cpr == null && userId != UserHandle.USER_SYSTEM) {
+ cpr = mProviderMap.getProviderByName(name, UserHandle.USER_SYSTEM);
if (cpr != null) {
cpi = cpr.info;
if (isSingleton(cpi.processName, cpi.applicationInfo,
cpi.name, cpi.flags)
&& isValidSingletonCall(r.uid, cpi.applicationInfo.uid)) {
- userId = UserHandle.USER_OWNER;
+ userId = UserHandle.USER_SYSTEM;
checkCrossUser = false;
} else {
cpr = null;
@@ -9741,7 +9742,6 @@ public final class ActivityManagerService extends ActivityManagerNative
Binder.restoreCallingIdentity(origId);
}
- boolean singleton;
if (!providerRunning) {
try {
checkTime(startTime, "getContentProviderImpl: before resolveContentProvider");
@@ -9758,11 +9758,11 @@ public final class ActivityManagerService extends ActivityManagerNative
// (it's a call within the same user || the provider is a
// privileged app)
// Then allow connecting to the singleton provider
- singleton = isSingleton(cpi.processName, cpi.applicationInfo,
+ boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,
cpi.name, cpi.flags)
&& isValidSingletonCall(r.uid, cpi.applicationInfo.uid);
if (singleton) {
- userId = UserHandle.USER_OWNER;
+ userId = UserHandle.USER_SYSTEM;
}
cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);
checkTime(startTime, "getContentProviderImpl: got app info for user");
@@ -10365,7 +10365,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
final ProcessRecord r = new ProcessRecord(stats, info, proc, uid);
if (!mBooted && !mBooting
- && userId == UserHandle.USER_OWNER
+ && userId == UserHandle.USER_SYSTEM
&& (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
r.persistent = true;
}
@@ -11188,7 +11188,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final boolean translucentChanged = r.changeWindowTranslucency(true);
if (translucentChanged) {
r.task.stack.releaseBackgroundResources(r);
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
mWindowManager.setAppFullscreen(token, true);
return translucentChanged;
@@ -11216,7 +11216,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (translucentChanged) {
r.task.stack.convertActivityToTranslucent(r);
}
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mWindowManager.setAppFullscreen(token, false);
return translucentChanged;
}
@@ -11822,12 +11822,12 @@ public final class ActivityManagerService extends ActivityManagerNative
}
private boolean deliverPreBootCompleted(final Runnable onFinishCallback,
- ArrayList<ComponentName> doneReceivers, int userId) {
+ ArrayList<ComponentName> doneReceivers) {
Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
List<ResolveInfo> ris = null;
try {
ris = AppGlobals.getPackageManager().queryIntentReceivers(
- intent, null, 0, userId);
+ intent, null, 0, UserHandle.USER_SYSTEM);
} catch (RemoteException e) {
}
if (ris == null) {
@@ -11841,22 +11841,18 @@ public final class ActivityManagerService extends ActivityManagerNative
}
intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
- // For User 0, load the version number. When delivering to a new user, deliver
- // to all receivers.
- if (userId == UserHandle.USER_OWNER) {
- ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
- for (int i=0; i<ris.size(); i++) {
- ActivityInfo ai = ris.get(i).activityInfo;
- ComponentName comp = new ComponentName(ai.packageName, ai.name);
- if (lastDoneReceivers.contains(comp)) {
- // We already did the pre boot receiver for this app with the current
- // platform version, so don't do it again...
- ris.remove(i);
- i--;
- // ...however, do keep it as one that has been done, so we don't
- // forget about it when rewriting the file of last done receivers.
- doneReceivers.add(comp);
- }
+ ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
+ for (int i=0; i<ris.size(); i++) {
+ ActivityInfo ai = ris.get(i).activityInfo;
+ ComponentName comp = new ComponentName(ai.packageName, ai.name);
+ if (lastDoneReceivers.contains(comp)) {
+ // We already did the pre boot receiver for this app with the current
+ // platform version, so don't do it again...
+ ris.remove(i);
+ i--;
+ // ...however, do keep it as one that has been done, so we don't
+ // forget about it when rewriting the file of last done receivers.
+ doneReceivers.add(comp);
}
}
@@ -11864,9 +11860,8 @@ public final class ActivityManagerService extends ActivityManagerNative
return false;
}
- // If primary user, send broadcast to all available users, else just to userId
- final int[] users = userId == UserHandle.USER_OWNER ? getUsersLocked()
- : new int[] { userId };
+ // TODO: can we still do this with per user encryption?
+ final int[] users = getUsersLocked();
if (users.length <= 0) {
return false;
}
@@ -11917,7 +11912,7 @@ public final class ActivityManagerService extends ActivityManagerNative
writeLastDonePreBootReceivers(doneReceivers);
systemReady(goingCallback);
}
- }, doneReceivers, UserHandle.USER_OWNER);
+ }, doneReceivers);
if (mWaitingUpdate) {
return;
@@ -17699,7 +17694,8 @@ public final class ActivityManagerService extends ActivityManagerNative
kept = mainStack.ensureActivityConfigurationLocked(starting, changes, false);
// And we need to make sure at this point that all other activities
// are made visible with the correct configuration.
- mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes);
+ mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes,
+ !PRESERVE_WINDOWS);
}
}
@@ -20170,7 +20166,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if ((userInfo.flags&UserInfo.FLAG_INITIALIZED) == 0) {
- if (userId != UserHandle.USER_OWNER) {
+ if (userId != UserHandle.USER_SYSTEM) {
Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
broadcastIntentLocked(null, null, intent, null,
@@ -20408,7 +20404,7 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int i = 0; i < num; i++) {
Integer oldUserId = mUserLru.get(i);
UserState oldUss = mStartedUsers.get(oldUserId);
- if (oldUserId == UserHandle.USER_OWNER || oldUserId == mCurrentUserId
+ if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId
|| oldUss.mState == UserState.STATE_STOPPING
|| oldUss.mState == UserState.STATE_SHUTDOWN) {
continue;
@@ -20493,8 +20489,12 @@ public final class ActivityManagerService extends ActivityManagerNative
i++;
continue;
}
- if (oldUserId == UserHandle.USER_OWNER || oldUserId == mCurrentUserId) {
- // Owner and current can't be stopped, but count as running.
+ if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId) {
+ // Owner/System user and current user can't be stopped. We count it as running
+ // when it is not a pure system user.
+ if (UserInfo.isSystemOnly(oldUserId)) {
+ num--;
+ }
i++;
continue;
}
@@ -20517,8 +20517,8 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
- if (userId < 0 || userId == UserHandle.USER_OWNER) {
- throw new IllegalArgumentException("Can't stop primary user " + userId);
+ if (userId < 0 || userId == UserHandle.USER_SYSTEM) {
+ throw new IllegalArgumentException("Can't stop system user " + userId);
}
enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId);
synchronized (this) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 3fcffd78d049..9809c2e4906c 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -30,6 +30,7 @@ import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStackSupervisor.MOVING;
+import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import android.graphics.Rect;
import android.util.ArraySet;
@@ -528,21 +529,15 @@ final class ActivityStack {
* */
void moveToFront(String reason, TaskRecord task) {
if (isAttached()) {
- final boolean homeStack = isHomeStack()
- || (mActivityContainer.mParentActivity != null
- && mActivityContainer.mParentActivity.isHomeActivity());
- ActivityStack lastFocusStack = null;
- if (!homeStack) {
- // Need to move this stack to the front before calling
- // {@link ActivityStackSupervisor#moveHomeStack} below.
- lastFocusStack = mStacks.get(mStacks.size() - 1);
- mStacks.remove(this);
- mStacks.add(this);
- }
- // TODO(multi-display): Focus stack currently adjusted in call to move home stack.
- // Needs to also work if focus is moving to the non-home display.
+ final ActivityStack lastFocusStack = mStacks.get(mStacks.size() - 1);
+ // Need to move this stack to the front before calling
+ // {@link ActivityStackSupervisor#setFocusStack} below.
+ mStacks.remove(this);
+ mStacks.add(this);
+
+ // TODO(multi-display): Needs to also work if focus is moving to the non-home display.
if (isOnHomeDisplay()) {
- mStackSupervisor.moveHomeStack(homeStack, reason, lastFocusStack);
+ mStackSupervisor.setFocusStack(reason, lastFocusStack);
}
if (task != null) {
insertTaskAtTop(task, null);
@@ -815,7 +810,7 @@ final class ActivityStack {
}
void goToSleep() {
- ensureActivitiesVisibleLocked(null, 0);
+ ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
// Make sure any stopped but visible activities are now sleeping.
// This ensures that the activity's onStop() is called.
@@ -1335,17 +1330,28 @@ final class ActivityStack {
return topHomeActivity == null || !topHomeActivity.isHomeActivity();
}
- if (focusedStackId == DOCKED_STACK_ID
- && stackIndex == (mStacks.indexOf(focusedStack) - 1)) {
+ final int belowFocusedIndex = mStacks.indexOf(focusedStack) - 1;
+ if (focusedStackId == DOCKED_STACK_ID && stackIndex == belowFocusedIndex) {
// Stacks directly behind the docked stack are always visible.
return true;
}
- if (mStackId == HOME_STACK_ID && focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
- // Home stack is always visible behind the fullscreen stack with a translucent activity.
- // This is done so that the home stack can act as a background to the translucent
- // activity.
- return hasTranslucentActivity(focusedStack);
+ if (focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
+ && hasTranslucentActivity(focusedStack)) {
+ // Stacks behind the fullscreen stack with a translucent activity are always
+ // visible so they can act as a backdrop to the translucent activity.
+ // For example, dialog activities
+ if (stackIndex == belowFocusedIndex) {
+ return true;
+ }
+ if (belowFocusedIndex >= 0) {
+ final ActivityStack stack = mStacks.get(belowFocusedIndex);
+ if (stack.mStackId == DOCKED_STACK_ID && stackIndex == (belowFocusedIndex - 1)) {
+ // The stack behind the docked stack is also visible so we can have a complete
+ // backdrop to the translucent activity when the docked stack is up.
+ return true;
+ }
+ }
}
if (mStackId >= FIRST_STATIC_STACK_ID && mStackId <= LAST_STATIC_STACK_ID) {
@@ -1379,7 +1385,8 @@ final class ActivityStack {
* Make sure that all activities that need to be visible (that is, they
* currently can be seen by the user) actually are.
*/
- final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
+ final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+ boolean preserveWindows) {
ActivityRecord top = topRunningActivityLocked(null);
if (top == null) {
return;
@@ -1428,7 +1435,7 @@ final class ActivityStack {
// First: if this is not the current activity being started, make
// sure it matches the current configuration.
if (r != starting) {
- ensureActivityConfigurationLocked(r, 0, false);
+ ensureActivityConfigurationLocked(r, 0, preserveWindows);
}
if (r.app == null || r.app.thread == null) {
@@ -2342,7 +2349,7 @@ final class ActivityStack {
// Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
// tell WindowManager that r is visible even though it is at the back of the stack.
mWindowManager.setAppVisibility(r.appToken, true);
- ensureActivitiesVisibleLocked(null, 0);
+ ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
} else if (SHOW_APP_STARTING_PREVIEW && doShow) {
// Figure out if we are transitioning from another activity that is
// "has the same starting icon" as the next one. This allows the
@@ -4024,6 +4031,11 @@ final class ActivityStack {
return true;
}
+ if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+ "Configuration changes for " + r + " ; taskChanges="
+ + Configuration.configurationDiffToString(taskChanges) + ", allChanges="
+ + Configuration.configurationDiffToString(changes));
+
// If the activity isn't currently running, just leave the new
// configuration and it will pick that up next time it starts.
if (r.app == null || r.app.thread == null) {
@@ -4536,18 +4548,17 @@ final class ActivityStack {
if (mTaskHistory.isEmpty()) {
if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this);
- final boolean notHomeStack = !isHomeStack();
if (isOnHomeDisplay()) {
String myReason = reason + " leftTaskHistoryEmpty";
if (mFullscreen || !adjustFocusToNextVisibleStackLocked(null, myReason)) {
- mStackSupervisor.moveHomeStack(notHomeStack, myReason);
+ mStackSupervisor.moveHomeStackToFront(myReason);
}
}
if (mStacks != null) {
mStacks.remove(this);
mStacks.add(0, this);
}
- if (notHomeStack) {
+ if (!isHomeStack()) {
mActivityContainer.onTaskListEmptyLocked();
}
}
@@ -4564,6 +4575,8 @@ final class ActivityStack {
addTask(task, toTop, false);
if (mTaskPositioner != null) {
mTaskPositioner.updateDefaultBounds(task, mTaskHistory, info.initialLayout);
+ } else if (mBounds != null && task.mResizeable) {
+ task.updateOverrideConfiguration(mBounds);
}
return task;
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index d3cea8de1442..17a44720deaf 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -175,6 +175,9 @@ public final class ActivityStackSupervisor implements DisplayListener {
// should be created if it doesn't exist already.
private static final boolean CREATE_IF_NEEDED = true;
+ // Used to indicate that windows of activities should be preserved during the resize.
+ static final boolean PRESERVE_WINDOWS = true;
+
// Used to indicate if an object (e.g. task) should be moved/created
// at the top of its container (e.g. stack).
static final boolean ON_TOP = true;
@@ -189,6 +192,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
// Activity actions an app cannot start if it uses a permission which is not granted.
private static final ArrayMap<String, String> ACTION_TO_RUNTIME_PERMISSION =
new ArrayMap<>();
+
static {
ACTION_TO_RUNTIME_PERMISSION.put(MediaStore.ACTION_IMAGE_CAPTURE,
Manifest.permission.CAMERA);
@@ -464,35 +468,22 @@ public final class ActivityStackSupervisor implements DisplayListener {
return stack == mFocusedStack;
}
- void moveHomeStack(boolean toFront, String reason) {
- moveHomeStack(toFront, reason, null);
- }
-
- void moveHomeStack(boolean toFront, String reason, ActivityStack lastFocusedStack) {
+ void setFocusStack(String reason, ActivityStack lastFocusedStack) {
ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
final int topNdx = stacks.size() - 1;
if (topNdx <= 0) {
return;
}
- // The home stack should either be at the top or bottom of the stack list.
- if ((toFront && (stacks.get(topNdx) != mHomeStack))
- || (!toFront && (stacks.get(0) != mHomeStack))) {
- if (DEBUG_STACK) Slog.d(TAG_STACK, "moveHomeTask: topStack old="
- + ((lastFocusedStack != null) ? lastFocusedStack : stacks.get(topNdx))
- + " new=" + mFocusedStack);
- stacks.remove(mHomeStack);
- stacks.add(toFront ? topNdx : 0, mHomeStack);
- }
-
+ final ActivityStack topStack = stacks.get(topNdx);
+ mFocusedStack = topStack;
if (lastFocusedStack != null) {
mLastFocusedStack = lastFocusedStack;
}
- mFocusedStack = stacks.get(topNdx);
- EventLog.writeEvent(EventLogTags.AM_HOME_STACK_MOVED,
- mCurrentUser, toFront ? 1 : 0, stacks.get(topNdx).getStackId(),
- mFocusedStack == null ? -1 : mFocusedStack.getStackId(), reason);
+ EventLogTags.writeAmFocusedStack(
+ mCurrentUser, mFocusedStack == null ? -1 : mFocusedStack.getStackId(),
+ mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(), reason);
if (mService.mBooting || !mService.mBooted) {
final ActivityRecord r = topRunningActivityLocked();
@@ -502,6 +493,10 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
}
+ void moveHomeStackToFront(String reason) {
+ mHomeStack.moveToFront(reason);
+ }
+
/** Returns true if the focus activity was adjusted to the home stack top activity. */
boolean moveHomeStackTaskToTop(int homeStackTaskType, String reason) {
if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
@@ -660,7 +655,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
}
if (!didSomething) {
- ensureActivitiesVisibleLocked(null, 0);
+ ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
return didSomething;
}
@@ -1803,8 +1798,11 @@ public final class ActivityStackSupervisor implements DisplayListener {
return container.mStack;
}
- if (mFocusedStack != mHomeStack && (!newTask ||
- mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
+ // The fullscreen stack is the only stack that can contain any task regardless of if
+ // the task is resizeable or not. So, we let the task go in the fullscreen task if it
+ // is the focus stack.
+ if (mFocusedStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID
+ && (!newTask || mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Have a focused stack=" + mFocusedStack);
return mFocusedStack;
@@ -1823,7 +1821,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
// If there is no suitable dynamic stack then we figure out which static stack to use.
- int stackId = task != null ? task.getLaunchStackId() :
+ final int stackId = task != null ? task.getLaunchStackId() :
bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
FULLSCREEN_WORKSPACE_STACK_ID;
stack = getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
@@ -2629,7 +2627,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
mLaunchingActivity.release();
}
- ensureActivitiesVisibleLocked(null, 0);
+ ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
// Atomically retrieve all of the other things to do.
@@ -2859,7 +2857,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
if (opts.hasBounds()) {
Rect bounds = opts.getBounds();
task.updateOverrideConfiguration(bounds);
- mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig, false);
+ mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig,
+ false /*relayout*/, false /*forced*/);
stackId = task.getLaunchStackId();
}
}
@@ -2962,7 +2961,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
}
- void resizeStackLocked(int stackId, Rect bounds) {
+ void resizeStackLocked(int stackId, Rect bounds, boolean preserveWindows) {
final ActivityStack stack = getStack(stackId);
if (stack == null) {
Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
@@ -2970,31 +2969,29 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
ActivityRecord r = stack.topRunningActivityLocked(null);
- final boolean resizeTasks = r != null && r.task.mResizeable;
mTmpBounds.clear();
mTmpConfigs.clear();
- if (resizeTasks) {
- ArrayList<TaskRecord> tasks = stack.getAllTasks();
- for (int i = tasks.size() - 1; i >= 0; i--) {
- TaskRecord task = tasks.get(i);
+ ArrayList<TaskRecord> tasks = stack.getAllTasks();
+ for (int i = tasks.size() - 1; i >= 0; i--) {
+ TaskRecord task = tasks.get(i);
+ if (task.mResizeable) {
if (stack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
- // For freeform stack we don't adjust the size of the tasks to match that of
- // the stack, but we do try to make sure the tasks are still contained with the
- // bounds of the stack.
+ // For freeform stack we don't adjust the size of the tasks to match that
+ // of the stack, but we do try to make sure the tasks are still contained
+ // with the bounds of the stack.
tempRect2.set(task.mBounds);
fitWithinBounds(tempRect2, bounds);
task.updateOverrideConfiguration(tempRect2);
} else {
task.updateOverrideConfiguration(bounds);
}
-
- mTmpConfigs.put(task.taskId, task.mOverrideConfig);
- mTmpBounds.put(task.taskId, task.mBounds);
}
+
+ mTmpConfigs.put(task.taskId, task.mOverrideConfig);
+ mTmpBounds.put(task.taskId, task.mBounds);
}
- stack.mFullscreen = mWindowManager.resizeStack(stackId, bounds, resizeTasks, mTmpConfigs,
- mTmpBounds);
+ stack.mFullscreen = mWindowManager.resizeStack(stackId, bounds, mTmpConfigs, mTmpBounds);
if (stack.mStackId == DOCKED_STACK_ID) {
// Dock stack funness...Yay!
if (stack.mFullscreen) {
@@ -3003,11 +3000,10 @@ public final class ActivityStackSupervisor implements DisplayListener {
// docked stack tasks to the fullscreen stack.
for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
if (i != DOCKED_STACK_ID) {
- resizeStackLocked(i, null);
+ resizeStackLocked(i, null, preserveWindows);
}
}
- final ArrayList<TaskRecord> tasks = stack.getAllTasks();
final int count = tasks.size();
for (int i = 0; i < count; i++) {
moveTaskToStackLocked(tasks.get(i).taskId,
@@ -3035,33 +3031,38 @@ public final class ActivityStackSupervisor implements DisplayListener {
tempRect.right -= leftChange;
tempRect.top -= bottomChange;
tempRect.bottom -= topChange;
- resizeStackLocked(i, tempRect);
+ resizeStackLocked(i, tempRect, PRESERVE_WINDOWS);
}
}
}
-
}
+ // Since we are resizing the stack, all other operations should strive to preserve
+ // windows.
+ preserveWindows = true;
}
stack.setBounds(bounds);
if (r != null) {
- final boolean updated = stack.ensureActivityConfigurationLocked(r, 0, false);
+ final boolean updated = stack.ensureActivityConfigurationLocked(r, 0, preserveWindows);
// And we need to make sure at this point that all other activities
// are made visible with the correct configuration.
- ensureActivitiesVisibleLocked(r, 0);
+ ensureActivitiesVisibleLocked(r, 0, preserveWindows);
if (!updated) {
resumeTopActivitiesLocked(stack, null, null);
}
}
}
- void resizeTaskLocked(TaskRecord task, Rect bounds, boolean resizedByUser) {
+ void resizeTaskLocked(TaskRecord task, Rect bounds, int resizeMode) {
if (!task.mResizeable) {
Slog.w(TAG, "resizeTask: task " + task + " not resizeable.");
return;
}
- if (task.mBounds != null && task.mBounds.equals(bounds)) {
+ // If this is a forced resize, let it go through even if the bounds is not changing,
+ // as we might need a relayout due to surface size change (to/from fullscreen).
+ final boolean forced = (resizeMode == RESIZE_MODE_FORCED);
+ if (task.mBounds != null && task.mBounds.equals(bounds) && !forced) {
// Nothing to do here...
return;
}
@@ -3102,10 +3103,11 @@ public final class ActivityStackSupervisor implements DisplayListener {
ActivityRecord r = task.topRunningActivityLocked(null);
if (r != null) {
final ActivityStack stack = task.stack;
+ final boolean resizedByUser = resizeMode == RESIZE_MODE_USER;
final boolean preserveWindow = resizedByUser && !changedStacks;
kept = stack.ensureActivityConfigurationLocked(r, 0, preserveWindow);
// All other activities must be made visible with their correct configuration.
- ensureActivitiesVisibleLocked(r, 0);
+ ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS);
if (!kept) {
resumeTopActivitiesLocked(stack, null, null);
if (changedStacks && stackId == FULLSCREEN_WORKSPACE_STACK_ID) {
@@ -3121,7 +3123,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
}
}
- mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig, kept);
+ mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig, kept, forced);
}
ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) {
@@ -3208,7 +3210,13 @@ public final class ActivityStackSupervisor implements DisplayListener {
final boolean wasFocused = isFrontStack(task.stack) && (topRunningActivityLocked() == r);
final boolean wasResumed = wasFocused && (task.stack.mResumedActivity == r);
+ final boolean resizeable = task.mResizeable;
+ // Temporarily disable resizeablility of task we are moving. We don't want it to be resized
+ // if a docked stack is created below which will lead to the stack we are moving from and
+ // its resizeable tasks being resized.
+ task.mResizeable = false;
final ActivityStack stack = getStack(stackId, CREATE_IF_NEEDED, toTop);
+ task.mResizeable = resizeable;
mWindowManager.moveTaskToStack(task.taskId, stack.mStackId, toTop);
if (task.stack != null) {
task.stack.removeTask(task, reason, MOVING);
@@ -3243,17 +3251,17 @@ public final class ActivityStackSupervisor implements DisplayListener {
// Make sure the task has the appropriate bounds/size for the stack it is in.
if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
- resizeTaskLocked(task, stack.mBounds, false);
+ resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM);
} else if (stackId == FREEFORM_WORKSPACE_STACK_ID
&& task.mBounds == null && task.mLastNonFullscreenBounds != null) {
- resizeTaskLocked(task, task.mLastNonFullscreenBounds, false);
+ resizeTaskLocked(task, task.mLastNonFullscreenBounds, RESIZE_MODE_SYSTEM);
} else if (stackId == DOCKED_STACK_ID) {
- resizeTaskLocked(task, stack.mBounds, false);
+ resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM);
}
// The task might have already been running and its visibility needs to be synchronized with
// the visibility of the stack / windows.
- ensureActivitiesVisibleLocked(null, 0);
+ ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
resumeTopActivitiesLocked();
}
@@ -3273,7 +3281,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
stack.positionTask(task, position, stackChanged);
// The task might have already been running and its visibility needs to be synchronized with
// the visibility of the stack / windows.
- stack.ensureActivitiesVisibleLocked(null, 0);
+ stack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
resumeTopActivitiesLocked();
}
@@ -3448,7 +3456,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
mService.updateUsageStats(r, true);
}
if (allResumedActivitiesComplete()) {
- ensureActivitiesVisibleLocked(null, 0);
+ ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
return true;
}
@@ -3534,14 +3542,15 @@ public final class ActivityStackSupervisor implements DisplayListener {
mHandler.obtainMessage(LAUNCH_TASK_BEHIND_COMPLETE, token).sendToTarget();
}
- void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
+ void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+ boolean preserveWindows) {
// First the front stacks. In case any are not fullscreen and are in front of home.
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
final int topStackNdx = stacks.size() - 1;
for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
- stack.ensureActivitiesVisibleLocked(starting, configChanges);
+ stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows);
}
}
}
@@ -3648,11 +3657,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
final boolean homeInFront = stack.isHomeStack();
if (stack.isOnHomeDisplay()) {
- moveHomeStack(homeInFront, "switchUserOnHomeDisplay");
- TaskRecord task = stack.topTask();
- if (task != null) {
- mWindowManager.moveTaskToTop(task.taskId);
- }
+ stack.moveToFront("switchUserOnHomeDisplay");
} else {
// Stack was moved to another display while user was swapped out.
resumeHomeStackTask(HOME_ACTIVITY_TYPE, null, "switchUserOnOtherDisplay");
diff --git a/services/core/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java
index 424ceb1a457c..c36fd06f633b 100644
--- a/services/core/java/com/android/server/am/CompatModePackages.java
+++ b/services/core/java/com/android/server/am/CompatModePackages.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import static com.android.server.am.ActivityManagerDebugConfig.*;
+import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import java.io.File;
import java.io.FileInputStream;
@@ -347,7 +348,7 @@ public final class CompatModePackages {
stack.ensureActivityConfigurationLocked(starting, 0, false);
// And we need to make sure at this point that all other activities
// are made visible with the correct configuration.
- stack.ensureActivitiesVisibleLocked(starting, 0);
+ stack.ensureActivitiesVisibleLocked(starting, 0, !PRESERVE_WINDOWS);
}
}
}
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 9a645dfc6985..78b5f3333b2c 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -93,8 +93,8 @@ option java_package com.android.server.am
# Activity focused
30043 am_focused_activity (User|1|5),(Component Name|3)
-# Home Stack brought to front or rear
-30044 am_home_stack_moved (User|1|5),(To Front|1|5),(Top Stack Id|1|5),(Focused Stack Id|1|5),(Reason|3)
+# Stack focus
+30044 am_focused_stack (User|1|5),(Focused Stack Id|1|5),(Last Focused Stack Id|1|5),(Reason|3)
# Running pre boot receiver
30045 am_pre_boot (User|1|5),(Package|3)
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 8f10f083c0ff..43f5baab793f 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -1235,7 +1235,7 @@ final class TaskRecord {
if (stack == null
|| stack.mStackId == HOME_STACK_ID
|| stack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
- return null;
+ return (mResizeable && stack != null) ? stack.mBounds : null;
} else if (stack.mStackId == DOCKED_STACK_ID) {
return stack.mBounds;
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 452378ff1e45..533f425e33f7 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -837,6 +837,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mPendingScreenOff && target != Display.STATE_OFF) {
setScreenState(Display.STATE_OFF);
mPendingScreenOff = false;
+ mPowerState.dismissColorFade();
}
if (target == Display.STATE_ON) {
@@ -910,6 +911,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// A black surface is already hiding the contents of the screen.
setScreenState(Display.STATE_OFF);
mPendingScreenOff = false;
+ mPowerState.dismissColorFade();
} else if (performScreenOffTransition
&& mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ?
diff --git a/services/core/java/com/android/server/location/GeofenceProxy.java b/services/core/java/com/android/server/location/GeofenceProxy.java
index d1bb8db221f4..b3a001022556 100644
--- a/services/core/java/com/android/server/location/GeofenceProxy.java
+++ b/services/core/java/com/android/server/location/GeofenceProxy.java
@@ -94,7 +94,7 @@ public final class GeofenceProxy {
private void bindHardwareGeofence() {
mContext.bindServiceAsUser(new Intent(mContext, GeofenceHardwareService.class),
- mServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.OWNER);
+ mServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index b59b4b2586ee..f292c9c4c3d8 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -77,24 +77,37 @@ public final class Installer extends SystemService {
public int dexopt(String apkPath, int uid, boolean isPublic,
String instructionSet, int dexoptNeeded) {
+ return dexopt(apkPath, uid, isPublic, instructionSet, dexoptNeeded, true);
+ }
+
+ public int dexopt(String apkPath, int uid, boolean isPublic,
+ String instructionSet, int dexoptNeeded, boolean bootComplete) {
if (!isValidInstructionSet(instructionSet)) {
Slog.e(TAG, "Invalid instruction set: " + instructionSet);
return -1;
}
- return mInstaller.dexopt(apkPath, uid, isPublic, instructionSet, dexoptNeeded);
+ return mInstaller.dexopt(apkPath, uid, isPublic, instructionSet, dexoptNeeded,
+ bootComplete);
}
public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName,
String instructionSet, int dexoptNeeded, boolean vmSafeMode,
boolean debuggable, @Nullable String outputPath) {
+ return dexopt(apkPath, uid, isPublic, pkgName, instructionSet, dexoptNeeded, vmSafeMode,
+ debuggable, outputPath, true);
+ }
+
+ public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName,
+ String instructionSet, int dexoptNeeded, boolean vmSafeMode,
+ boolean debuggable, @Nullable String outputPath, boolean bootComplete) {
if (!isValidInstructionSet(instructionSet)) {
Slog.e(TAG, "Invalid instruction set: " + instructionSet);
return -1;
}
return mInstaller.dexopt(apkPath, uid, isPublic, pkgName,
instructionSet, dexoptNeeded, vmSafeMode,
- debuggable, outputPath);
+ debuggable, outputPath, bootComplete);
}
public int idmap(String targetApkPath, String overlayApkPath, int uid) {
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 8c23648f0f0f..b692def44153 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -71,7 +71,7 @@ final class PackageDexOptimizer {
* {@link PackageManagerService#mInstallLock}.
*/
int performDexOpt(PackageParser.Package pkg, String[] instructionSets,
- boolean forceDex, boolean defer, boolean inclDependencies) {
+ boolean forceDex, boolean defer, boolean inclDependencies, boolean bootComplete) {
ArraySet<String> done;
if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) {
done = new ArraySet<String>();
@@ -86,7 +86,7 @@ final class PackageDexOptimizer {
mDexoptWakeLock.acquire();
}
try {
- return performDexOptLI(pkg, instructionSets, forceDex, defer, done);
+ return performDexOptLI(pkg, instructionSets, forceDex, defer, bootComplete, done);
} finally {
if (useLock) {
mDexoptWakeLock.release();
@@ -96,18 +96,19 @@ final class PackageDexOptimizer {
}
private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets,
- boolean forceDex, boolean defer, ArraySet<String> done) {
+ boolean forceDex, boolean defer, boolean bootComplete, ArraySet<String> done) {
final String[] instructionSets = targetInstructionSets != null ?
targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
if (done != null) {
done.add(pkg.packageName);
if (pkg.usesLibraries != null) {
- performDexOptLibsLI(pkg.usesLibraries, instructionSets, forceDex, defer, done);
+ performDexOptLibsLI(pkg.usesLibraries, instructionSets, forceDex, defer,
+ bootComplete, done);
}
if (pkg.usesOptionalLibraries != null) {
performDexOptLibsLI(pkg.usesOptionalLibraries, instructionSets, forceDex, defer,
- done);
+ bootComplete, done);
}
}
@@ -174,11 +175,11 @@ final class PackageDexOptimizer {
Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg="
+ pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
+ " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
- + " oatDir = " + oatDir);
+ + " oatDir = " + oatDir + " bootComplete=" + bootComplete);
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
final int ret = mPackageManagerService.mInstaller.dexopt(path, sharedGid,
!pkg.isForwardLocked(), pkg.packageName, dexCodeInstructionSet,
- dexoptNeeded, vmSafeMode, debuggable, oatDir);
+ dexoptNeeded, vmSafeMode, debuggable, oatDir, bootComplete);
// Dex2oat might fail due to compiler / verifier errors. We soldier on
// regardless, and attempt to interpret the app as a safety net.
@@ -235,12 +236,12 @@ final class PackageDexOptimizer {
}
private void performDexOptLibsLI(ArrayList<String> libs, String[] instructionSets,
- boolean forceDex, boolean defer, ArraySet<String> done) {
+ boolean forceDex, boolean defer, boolean bootComplete, ArraySet<String> done) {
for (String libName : libs) {
PackageParser.Package libPkg = mPackageManagerService.findSharedNonSystemLibrary(
libName);
if (libPkg != null && !done.contains(libName)) {
- performDexOptLI(libPkg, instructionSets, forceDex, defer, done);
+ performDexOptLI(libPkg, instructionSets, forceDex, defer, bootComplete, done);
}
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e385ac5d32cb..17a3f56a1bf6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2015,7 +2015,7 @@ public class PackageManagerService extends IPackageManager.Stub {
int dexoptNeeded = DexFile.getDexOptNeeded(lib, null, dexCodeInstructionSet, false);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
alreadyDexOpted.add(lib);
- mInstaller.dexopt(lib, Process.SYSTEM_UID, true, dexCodeInstructionSet, dexoptNeeded);
+ mInstaller.dexopt(lib, Process.SYSTEM_UID, true, dexCodeInstructionSet, dexoptNeeded, false);
}
} catch (FileNotFoundException e) {
Slog.w(TAG, "Library not found: " + lib);
@@ -2063,7 +2063,7 @@ public class PackageManagerService extends IPackageManager.Stub {
try {
int dexoptNeeded = DexFile.getDexOptNeeded(path, null, dexCodeInstructionSet, false);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- mInstaller.dexopt(path, Process.SYSTEM_UID, true, dexCodeInstructionSet, dexoptNeeded);
+ mInstaller.dexopt(path, Process.SYSTEM_UID, true, dexCodeInstructionSet, dexoptNeeded, false);
}
} catch (FileNotFoundException e) {
Slog.w(TAG, "Jar not found: " + path);
@@ -2292,7 +2292,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// the rest of the commands above) because there's precious little we
// can do about it. A settings error is reported, though.
adjustCpuAbisForSharedUserLPw(setting.packages, null /* scanned package */,
- false /* force dexopt */, false /* defer dexopt */);
+ false /* force dexopt */, false /* defer dexopt */,
+ false /* boot complete */);
}
// Now that we know all the packages we are keeping,
@@ -6155,41 +6156,6 @@ public class PackageManagerService extends IPackageManager.Stub {
it.remove();
}
}
- // Give priority to system apps.
- for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
- PackageParser.Package pkg = it.next();
- if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp()) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Adding system app " + sortedPkgs.size() + ": " + pkg.packageName);
- }
- sortedPkgs.add(pkg);
- it.remove();
- }
- }
- // Give priority to updated system apps.
- for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
- PackageParser.Package pkg = it.next();
- if (pkg.isUpdatedSystemApp()) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Adding updated system app " + sortedPkgs.size() + ": " + pkg.packageName);
- }
- sortedPkgs.add(pkg);
- it.remove();
- }
- }
- // Give priority to apps that listen for boot complete.
- intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
- pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM);
- for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
- PackageParser.Package pkg = it.next();
- if (pkgNames.contains(pkg.packageName)) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Adding boot app " + sortedPkgs.size() + ": " + pkg.packageName);
- }
- sortedPkgs.add(pkg);
- it.remove();
- }
- }
// Filter out packages that aren't recently used.
filterRecentlyUsedApps(pkgs);
// Add all remaining apps.
@@ -6281,7 +6247,8 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageParser.Package p = pkg;
synchronized (mInstallLock) {
mPackageDexOptimizer.performDexOpt(p, null /* instruction sets */,
- false /* force dex */, false /* defer */, true /* include dependencies */);
+ false /* force dex */, false /* defer */, true /* include dependencies */,
+ false /* boot complete */);
}
}
@@ -6340,7 +6307,8 @@ public class PackageManagerService extends IPackageManager.Stub {
synchronized (mInstallLock) {
final String[] instructionSets = new String[] { targetInstructionSet };
int result = mPackageDexOptimizer.performDexOpt(p, instructionSets,
- false /* forceDex */, false /* defer */, true /* inclDependencies */);
+ false /* forceDex */, false /* defer */, true /* inclDependencies */,
+ true /* boot complete */);
return result == PackageDexOptimizer.DEX_OPT_PERFORMED;
}
} finally {
@@ -6390,7 +6358,8 @@ public class PackageManagerService extends IPackageManager.Stub {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
final int res = mPackageDexOptimizer.performDexOpt(pkg, instructionSets,
- true /*forceDex*/, false /* defer */, true /* inclDependencies */);
+ true /*forceDex*/, false /* defer */, true /* inclDependencies */,
+ true /* boot complete */);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) {
@@ -7199,14 +7168,15 @@ public class PackageManagerService extends IPackageManager.Stub {
// we can avoid redundant dexopts, and also to make sure we've got the
// code and package path correct.
adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
- pkg, forceDex, (scanFlags & SCAN_DEFER_DEX) != 0);
+ pkg, forceDex, (scanFlags & SCAN_DEFER_DEX) != 0, true /* boot complete */);
}
if ((scanFlags & SCAN_NO_DEX) == 0) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instruction sets */,
- forceDex, (scanFlags & SCAN_DEFER_DEX) != 0, false /* inclDependencies */);
+ forceDex, (scanFlags & SCAN_DEFER_DEX) != 0, false /* inclDependencies */,
+ (scanFlags & SCAN_BOOTING) == 0);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
@@ -7286,7 +7256,8 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageParser.Package clientPkg = clientLibPkgs.get(i);
int result = mPackageDexOptimizer.performDexOpt(clientPkg,
null /* instruction sets */, forceDex,
- (scanFlags & SCAN_DEFER_DEX) != 0, false);
+ (scanFlags & SCAN_DEFER_DEX) != 0, false,
+ (scanFlags & SCAN_BOOTING) == 0);
if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
throw new PackageManagerException(INSTALL_FAILED_DEXOPT,
"scanPackageLI failed to dexopt clientLibPkgs");
@@ -7842,7 +7813,8 @@ public class PackageManagerService extends IPackageManager.Stub {
* adds unnecessary complexity.
*/
private void adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser,
- PackageParser.Package scannedPackage, boolean forceDexOpt, boolean deferDexOpt) {
+ PackageParser.Package scannedPackage, boolean forceDexOpt, boolean deferDexOpt,
+ boolean bootComplete) {
String requiredInstructionSet = null;
if (scannedPackage != null && scannedPackage.applicationInfo.primaryCpuAbi != null) {
requiredInstructionSet = VMRuntime.getInstructionSet(
@@ -7908,7 +7880,8 @@ public class PackageManagerService extends IPackageManager.Stub {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
int result = mPackageDexOptimizer.performDexOpt(ps.pkg,
- null /* instruction sets */, forceDexOpt, deferDexOpt, true);
+ null /* instruction sets */, forceDexOpt, deferDexOpt, true,
+ bootComplete);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
@@ -12598,7 +12571,8 @@ public class PackageManagerService extends IPackageManager.Stub {
int result = mPackageDexOptimizer
.performDexOpt(pkg, null /* instruction sets */, false /* forceDex */,
- false /* defer */, false /* inclDependencies */);
+ false /* defer */, false /* inclDependencies */,
+ true /* boot complete */);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
@@ -15902,14 +15876,28 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- private void loadPrivatePackages(VolumeInfo vol) {
+ private void loadPrivatePackages(final VolumeInfo vol) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ loadPrivatePackagesInner(vol);
+ }
+ });
+ }
+
+ private void loadPrivatePackagesInner(VolumeInfo vol) {
final ArrayList<ApplicationInfo> loaded = new ArrayList<>();
final int parseFlags = mDefParseFlags | PackageParser.PARSE_EXTERNAL_STORAGE;
- synchronized (mInstallLock) {
+
+ final VersionInfo ver;
+ final List<PackageSetting> packages;
synchronized (mPackages) {
- final VersionInfo ver = mSettings.findOrCreateVersion(vol.fsUuid);
- final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(vol.fsUuid);
- for (PackageSetting ps : packages) {
+ ver = mSettings.findOrCreateVersion(vol.fsUuid);
+ packages = mSettings.getVolumePackagesLPr(vol.fsUuid);
+ }
+
+ for (PackageSetting ps : packages) {
+ synchronized (mInstallLock) {
final PackageParser.Package pkg;
try {
pkg = scanPackageTracedLI(ps.codePath, parseFlags, SCAN_INITIAL, 0L, null);
@@ -15922,7 +15910,9 @@ public class PackageManagerService extends IPackageManager.Stub {
deleteCodeCacheDirsLI(ps.volumeUuid, ps.name);
}
}
+ }
+ synchronized (mPackages) {
int updateFlags = UPDATE_PERMISSIONS_ALL;
if (ver.sdkVersion != mSdkVersion) {
logCriticalInfo(Log.INFO, "Platform changed from " + ver.sdkVersion + " to "
@@ -15936,13 +15926,21 @@ public class PackageManagerService extends IPackageManager.Stub {
mSettings.writeLPr();
}
- }
if (DEBUG_INSTALL) Slog.d(TAG, "Loaded packages " + loaded);
sendResourcesChangedBroadcast(true, false, loaded, null);
}
- private void unloadPrivatePackages(VolumeInfo vol) {
+ private void unloadPrivatePackages(final VolumeInfo vol) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ unloadPrivatePackagesInner(vol);
+ }
+ });
+ }
+
+ private void unloadPrivatePackagesInner(VolumeInfo vol) {
final ArrayList<ApplicationInfo> unloaded = new ArrayList<>();
synchronized (mInstallLock) {
synchronized (mPackages) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 33ecd0944f25..dbc3970cf4cf 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2003,6 +2003,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case TYPE_SYSTEM_DIALOG:
case TYPE_VOLUME_OVERLAY:
case TYPE_PRIVATE_PRESENTATION:
+ case TYPE_DOCK_DIVIDER:
break;
}
@@ -2134,54 +2135,56 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case TYPE_INPUT_METHOD_DIALOG:
// on-screen keyboards and other such input method user interfaces go here.
return 13;
+ case TYPE_DOCK_DIVIDER:
+ return 14;
case TYPE_KEYGUARD_SCRIM:
// the safety window that shows behind keyguard while keyguard is starting
- return 14;
- case TYPE_STATUS_BAR_SUB_PANEL:
return 15;
- case TYPE_STATUS_BAR:
+ case TYPE_STATUS_BAR_SUB_PANEL:
return 16;
- case TYPE_STATUS_BAR_PANEL:
+ case TYPE_STATUS_BAR:
return 17;
- case TYPE_KEYGUARD_DIALOG:
+ case TYPE_STATUS_BAR_PANEL:
return 18;
+ case TYPE_KEYGUARD_DIALOG:
+ return 19;
case TYPE_VOLUME_OVERLAY:
// the on-screen volume indicator and controller shown when the user
// changes the device volume
- return 19;
+ return 20;
case TYPE_SYSTEM_OVERLAY:
// the on-screen volume indicator and controller shown when the user
// changes the device volume
- return 20;
+ return 21;
case TYPE_NAVIGATION_BAR:
// the navigation bar, if available, shows atop most things
- return 21;
+ return 22;
case TYPE_NAVIGATION_BAR_PANEL:
// some panels (e.g. search) need to show on top of the navigation bar
- return 22;
+ return 23;
case TYPE_SYSTEM_ERROR:
// system-level error dialogs
- return 23;
+ return 24;
case TYPE_MAGNIFICATION_OVERLAY:
// used to highlight the magnified portion of a display
- return 24;
+ return 25;
case TYPE_DISPLAY_OVERLAY:
// used to simulate secondary display devices
- return 25;
+ return 26;
case TYPE_DRAG:
// the drag layer: input for drag-and-drop is associated with this window,
// which sits above all other focusable windows
- return 26;
+ return 27;
case TYPE_ACCESSIBILITY_OVERLAY:
// overlay put by accessibility services to intercept user interaction
- return 27;
- case TYPE_SECURE_SYSTEM_OVERLAY:
return 28;
- case TYPE_BOOT_PROGRESS:
+ case TYPE_SECURE_SYSTEM_OVERLAY:
return 29;
+ case TYPE_BOOT_PROGRESS:
+ return 30;
case TYPE_POINTER:
// the (mouse) pointer layer
- return 30;
+ return 31;
}
Log.e(TAG, "Unknown window type: " + type);
return 2;
@@ -2271,6 +2274,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case TYPE_WALLPAPER:
case TYPE_DREAM:
case TYPE_KEYGUARD_SCRIM:
+ case TYPE_DOCK_DIVIDER:
return false;
default:
// Hide only windows below the keyguard host window.
@@ -3577,7 +3581,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final Rect of = mTmpOverscanFrame;
final Rect vf = mTmpVisibleFrame;
final Rect dcf = mTmpDecorFrame;
- final Rect osf = mTmpOutsetFrame;
pf.left = df.left = of.left = vf.left = mDockLeft;
pf.top = df.top = of.top = vf.top = mDockTop;
pf.right = df.right = of.right = vf.right = mDockRight;
@@ -3619,150 +3622,163 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// then take that into account.
navVisible |= !canHideNavigationBar();
- boolean updateSysUiVisibility = false;
- if (mNavigationBar != null) {
- boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
- // Force the navigation bar to its appropriate place and
- // size. We need to do this directly, instead of relying on
- // it to bubble up from the nav bar, because this needs to
- // change atomically with screen rotations.
- mNavigationBarOnBottom = (!mNavigationBarCanMove || displayWidth < displayHeight);
- if (mNavigationBarOnBottom) {
- // It's a system nav bar or a portrait screen; nav bar goes on bottom.
- int top = displayHeight - overscanBottom
- - mNavigationBarHeightForRotation[displayRotation];
- mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
- mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
- if (transientNavBarShowing) {
- mNavigationBarController.setBarShowingLw(true);
- } else if (navVisible) {
- mNavigationBarController.setBarShowingLw(true);
- mDockBottom = mTmpNavigationFrame.top;
- mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
- mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
- } else {
- // We currently want to hide the navigation UI.
- mNavigationBarController.setBarShowingLw(false);
- }
- if (navVisible && !navTranslucent && !navAllowedHidden
- && !mNavigationBar.isAnimatingLw()
- && !mNavigationBarController.wasRecentlyTranslucent()) {
- // If the opaque nav bar is currently requested to be visible,
- // and not in the process of animating on or off, then
- // we can tell the app that it is covered by it.
- mSystemBottom = mTmpNavigationFrame.top;
- }
- } else {
- // Landscape screen; nav bar goes to the right.
- int left = displayWidth - overscanRight
- - mNavigationBarWidthForRotation[displayRotation];
- mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
- mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
- if (transientNavBarShowing) {
- mNavigationBarController.setBarShowingLw(true);
- } else if (navVisible) {
- mNavigationBarController.setBarShowingLw(true);
- mDockRight = mTmpNavigationFrame.left;
- mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
- mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
- } else {
- // We currently want to hide the navigation UI.
- mNavigationBarController.setBarShowingLw(false);
- }
- if (navVisible && !navTranslucent && !navAllowedHidden
- && !mNavigationBar.isAnimatingLw()
- && !mNavigationBarController.wasRecentlyTranslucent()) {
- // If the nav bar is currently requested to be visible,
- // and not in the process of animating on or off, then
- // we can tell the app that it is covered by it.
- mSystemRight = mTmpNavigationFrame.left;
- }
- }
- // Make sure the content and current rectangles are updated to
- // account for the restrictions from the navigation bar.
- mContentTop = mVoiceContentTop = mCurTop = mDockTop;
- mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
- mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
- mContentRight = mVoiceContentRight = mCurRight = mDockRight;
- mStatusBarLayer = mNavigationBar.getSurfaceLayer();
- // And compute the final frame.
- mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
- mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
- mTmpNavigationFrame, mTmpNavigationFrame);
- if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
- if (mNavigationBarController.checkHiddenLw()) {
- updateSysUiVisibility = true;
- }
- }
+ boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
+ displayRotation, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
+ navAllowedHidden);
if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
mDockLeft, mDockTop, mDockRight, mDockBottom));
+ updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
+ if (updateSysUiVisibility) {
+ updateSystemUiVisibilityLw();
+ }
+ }
+ }
- // decide where the status bar goes ahead of time
- if (mStatusBar != null) {
- // apply any navigation bar insets
- pf.left = df.left = of.left = mUnrestrictedScreenLeft;
- pf.top = df.top = of.top = mUnrestrictedScreenTop;
- pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
- pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
- + mUnrestrictedScreenTop;
- vf.left = mStableLeft;
- vf.top = mStableTop;
- vf.right = mStableRight;
- vf.bottom = mStableBottom;
-
- mStatusBarLayer = mStatusBar.getSurfaceLayer();
-
- // Let the status bar determine its size.
- mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
- vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
- dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
-
- // For layout, the status bar is always at the top with our fixed height.
- mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
-
- boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
- boolean statusBarTranslucent = (sysui
- & (View.STATUS_BAR_TRANSLUCENT | View.SYSTEM_UI_TRANSPARENT)) != 0;
- if (!isKeyguardShowing) {
- statusBarTranslucent &= areTranslucentBarsAllowed();
- }
+ private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
+ boolean isKeyguardShowing) {
+ // decide where the status bar goes ahead of time
+ if (mStatusBar != null) {
+ // apply any navigation bar insets
+ pf.left = df.left = of.left = mUnrestrictedScreenLeft;
+ pf.top = df.top = of.top = mUnrestrictedScreenTop;
+ pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
+ pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
+ + mUnrestrictedScreenTop;
+ vf.left = mStableLeft;
+ vf.top = mStableTop;
+ vf.right = mStableRight;
+ vf.bottom = mStableBottom;
+
+ mStatusBarLayer = mStatusBar.getSurfaceLayer();
+
+ // Let the status bar determine its size.
+ mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
+ vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
+ dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
- // If the status bar is hidden, we don't want to cause
- // windows behind it to scroll.
- if (mStatusBar.isVisibleLw() && !statusBarTransient) {
- // Status bar may go away, so the screen area it occupies
- // is available to apps but just covering them when the
- // status bar is visible.
- mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
+ // For layout, the status bar is always at the top with our fixed height.
+ mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
+
+ boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
+ boolean statusBarTranslucent = (sysui
+ & (View.STATUS_BAR_TRANSLUCENT | View.SYSTEM_UI_TRANSPARENT)) != 0;
+ if (!isKeyguardShowing) {
+ statusBarTranslucent &= areTranslucentBarsAllowed();
+ }
- mContentTop = mVoiceContentTop = mCurTop = mDockTop;
- mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
- mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
- mContentRight = mVoiceContentRight = mCurRight = mDockRight;
+ // If the status bar is hidden, we don't want to cause
+ // windows behind it to scroll.
+ if (mStatusBar.isVisibleLw() && !statusBarTransient) {
+ // Status bar may go away, so the screen area it occupies
+ // is available to apps but just covering them when the
+ // status bar is visible.
+ mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
+
+ mContentTop = mVoiceContentTop = mCurTop = mDockTop;
+ mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
+ mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
+ mContentRight = mVoiceContentRight = mCurRight = mDockRight;
- if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
+ if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
String.format(
- "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
- mDockLeft, mDockTop, mDockRight, mDockBottom,
- mContentLeft, mContentTop, mContentRight, mContentBottom,
- mCurLeft, mCurTop, mCurRight, mCurBottom));
+ "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
+ mDockLeft, mDockTop, mDockRight, mDockBottom,
+ mContentLeft, mContentTop, mContentRight, mContentBottom,
+ mCurLeft, mCurTop, mCurRight, mCurBottom));
+ }
+ if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
+ && !statusBarTransient && !statusBarTranslucent
+ && !mStatusBarController.wasRecentlyTranslucent()) {
+ // If the opaque status bar is currently requested to be visible,
+ // and not in the process of animating on or off, then
+ // we can tell the app that it is covered by it.
+ mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
+ }
+ if (mStatusBarController.checkHiddenLw()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
+ int overscanRight, int overscanBottom, Rect dcf, boolean navVisible,
+ boolean navTranslucent, boolean navAllowedHidden) {
+ if (mNavigationBar != null) {
+ boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
+ // Force the navigation bar to its appropriate place and
+ // size. We need to do this directly, instead of relying on
+ // it to bubble up from the nav bar, because this needs to
+ // change atomically with screen rotations.
+ mNavigationBarOnBottom = (!mNavigationBarCanMove || displayWidth < displayHeight);
+ if (mNavigationBarOnBottom) {
+ // It's a system nav bar or a portrait screen; nav bar goes on bottom.
+ int top = displayHeight - overscanBottom
+ - mNavigationBarHeightForRotation[displayRotation];
+ mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
+ mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
+ if (transientNavBarShowing) {
+ mNavigationBarController.setBarShowingLw(true);
+ } else if (navVisible) {
+ mNavigationBarController.setBarShowingLw(true);
+ mDockBottom = mTmpNavigationFrame.top;
+ mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
+ mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
+ } else {
+ // We currently want to hide the navigation UI.
+ mNavigationBarController.setBarShowingLw(false);
}
- if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
- && !statusBarTransient && !statusBarTranslucent
- && !mStatusBarController.wasRecentlyTranslucent()) {
- // If the opaque status bar is currently requested to be visible,
+ if (navVisible && !navTranslucent && !navAllowedHidden
+ && !mNavigationBar.isAnimatingLw()
+ && !mNavigationBarController.wasRecentlyTranslucent()) {
+ // If the opaque nav bar is currently requested to be visible,
// and not in the process of animating on or off, then
// we can tell the app that it is covered by it.
- mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
+ mSystemBottom = mTmpNavigationFrame.top;
+ }
+ } else {
+ // Landscape screen; nav bar goes to the right.
+ int left = displayWidth - overscanRight
+ - mNavigationBarWidthForRotation[displayRotation];
+ mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
+ mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
+ if (transientNavBarShowing) {
+ mNavigationBarController.setBarShowingLw(true);
+ } else if (navVisible) {
+ mNavigationBarController.setBarShowingLw(true);
+ mDockRight = mTmpNavigationFrame.left;
+ mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
+ mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
+ } else {
+ // We currently want to hide the navigation UI.
+ mNavigationBarController.setBarShowingLw(false);
}
- if (mStatusBarController.checkHiddenLw()) {
- updateSysUiVisibility = true;
+ if (navVisible && !navTranslucent && !navAllowedHidden
+ && !mNavigationBar.isAnimatingLw()
+ && !mNavigationBarController.wasRecentlyTranslucent()) {
+ // If the nav bar is currently requested to be visible,
+ // and not in the process of animating on or off, then
+ // we can tell the app that it is covered by it.
+ mSystemRight = mTmpNavigationFrame.left;
}
}
- if (updateSysUiVisibility) {
- updateSystemUiVisibilityLw();
+ // Make sure the content and current rectangles are updated to
+ // account for the restrictions from the navigation bar.
+ mContentTop = mVoiceContentTop = mCurTop = mDockTop;
+ mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
+ mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
+ mContentRight = mVoiceContentRight = mCurRight = mDockRight;
+ mStatusBarLayer = mNavigationBar.getSurfaceLayer();
+ // And compute the final frame.
+ mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
+ mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
+ mTmpNavigationFrame, mTmpNavigationFrame);
+ if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
+ if (mNavigationBarController.checkHiddenLw()) {
+ return true;
}
}
+ return false;
}
/** {@inheritDoc} */
@@ -4416,6 +4432,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (attrs.type == TYPE_STATUS_BAR) {
if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
mForceStatusBarFromKeyguard = true;
+ mShowingLockscreen = true;
}
if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
mForceStatusBarTransparent = true;
@@ -4436,9 +4453,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mForceStatusBar = true;
}
}
- if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
- mShowingLockscreen = true;
- }
if (attrs.type == TYPE_DREAM) {
// If the lockscreen was showing when the dream started then wait
// for the dream to draw before hiding the lockscreen.
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 7ae3c79e0fe5..c0dfbcbb01ab 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -129,7 +129,7 @@ public class KeyguardServiceDelegate {
intent.setComponent(keyguardComponent);
if (!context.bindServiceAsUser(intent, mKeyguardConnection,
- Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
+ Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
Log.v(TAG, "*** Keyguard: can't bind to " + keyguardComponent);
mKeyguardState.showing = false;
mKeyguardState.showingAndNotOccluded = false;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 513fd4e55d39..a0a31c0d8a0c 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -1577,6 +1577,13 @@ public final class PowerManagerService extends SystemService
}
if (mUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM && userInactiveOverride) {
+ if ((mUserActivitySummary &
+ (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0) {
+ // Device is being kept awake by recent user activity
+ long savedWakeTimeMs = now - nextTimeout;
+ EventLog.writeEvent(
+ EventLogTags.POWER_SOFT_SLEEP_REQUESTED, savedWakeTimeMs);
+ }
mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
nextTimeout = -1;
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 87dc6c4c3e72..11a16394a502 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -305,9 +305,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
throw new SecurityException("invalid status bar icon slot: " + slot);
}
- StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.OWNER, iconId,
- iconLevel, 0,
- contentDescription);
+ StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.SYSTEM, iconId,
+ iconLevel, 0, contentDescription);
//Slog.d(TAG, "setIcon slot=" + slot + " index=" + index + " icon=" + icon);
mIcons.setIcon(index, icon);
diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
index f4bd61fa39cd..6c5452a3cb2e 100644
--- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java
+++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
@@ -188,7 +188,7 @@ public class TelecomLoaderService extends SystemService {
| Context.BIND_AUTO_CREATE;
// Bind to Telecom and register the service
- if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.OWNER)) {
+ if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.SYSTEM)) {
mServiceConnection = serviceConnection;
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b503554ce15e..4392ab43579c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityManager.DOCKED_STACK_ID;
import static android.app.ActivityManager.HOME_STACK_ID;
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
@@ -100,7 +101,8 @@ class DisplayContent {
Region mTouchExcludeRegion = new Region();
/** Save allocating when calculating rects */
- Rect mTmpRect = new Rect();
+ private Rect mTmpRect = new Rect();
+ private Rect mTmpRect2 = new Rect();
/** For gathering Task objects in order. */
final ArrayList<Task> mTmpTaskHistory = new ArrayList<Task>();
@@ -110,6 +112,8 @@ class DisplayContent {
/** Remove this display when animation on it has completed. */
boolean mDeferredRemoval;
+ final DockedStackDividerController mDividerControllerLocked;
+
/**
* @param display May not be null.
* @param service You know.
@@ -121,6 +125,7 @@ class DisplayContent {
display.getMetrics(mDisplayMetrics);
isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
mService = service;
+ mDividerControllerLocked = new DockedStackDividerController(service.mContext, this);
}
int getDisplayId() {
@@ -442,6 +447,35 @@ class DisplayContent {
}
}
+ void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
+ final int rotationDelta = DisplayContent.deltaRotation(oldRotation, newRotation);
+ getLogicalDisplayRect(mTmpRect);
+ switch (rotationDelta) {
+ case Surface.ROTATION_0:
+ mTmpRect2.set(bounds);
+ break;
+ case Surface.ROTATION_90:
+ mTmpRect2.top = mTmpRect.bottom - bounds.right;
+ mTmpRect2.left = bounds.top;
+ mTmpRect2.right = mTmpRect2.left + bounds.height();
+ mTmpRect2.bottom = mTmpRect2.top + bounds.width();
+ break;
+ case Surface.ROTATION_180:
+ mTmpRect2.top = mTmpRect.bottom - bounds.bottom;
+ mTmpRect2.left = mTmpRect.right - bounds.right;
+ mTmpRect2.right = mTmpRect2.left + bounds.width();
+ mTmpRect2.bottom = mTmpRect2.top + bounds.height();
+ break;
+ case Surface.ROTATION_270:
+ mTmpRect2.top = bounds.left;
+ mTmpRect2.left = mTmpRect.right - bounds.bottom;
+ mTmpRect2.right = mTmpRect2.left + bounds.height();
+ mTmpRect2.bottom = mTmpRect2.top + bounds.width();
+ break;
+ }
+ bounds.set(mTmpRect2);
+ }
+
static int deltaRotation(int oldRotation, int newRotation) {
int delta = newRotation - oldRotation;
if (delta < 0) delta += 4;
@@ -522,4 +556,14 @@ class DisplayContent {
public String toString() {
return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mStacks;
}
+
+ TaskStack getDockedStack() {
+ for (int i = mStacks.size() - 1; i >= 0; i--) {
+ TaskStack stack = mStacks.get(i);
+ if (stack.mStackId == DOCKED_STACK_ID) {
+ return stack;
+ }
+ }
+ return null;
+ }
}
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
new file mode 100644
index 000000000000..ad207d4b8939
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -0,0 +1,117 @@
+/*
+ * 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.wm;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING;
+import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+
+/**
+ * Controls showing and hiding of a docked stack divider on the display.
+ */
+public class DockedStackDividerController {
+ private static final String TAG = "DockedStackDivider";
+ private final Context mContext;
+ private final int mDividerWidth;
+ private final DisplayContent mDisplayContent;
+ private View mView;
+ private Rect mTmpRect = new Rect();
+
+ DockedStackDividerController(Context context, DisplayContent displayContent) {
+ mContext = context;
+ mDisplayContent = displayContent;
+ mDividerWidth = context.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_divider_thickness);
+ }
+
+ private void addDivider() {
+ View view = LayoutInflater.from(mContext).inflate(
+ com.android.internal.R.layout.docked_stack_divider, null);
+ WindowManagerGlobal manager = WindowManagerGlobal.getInstance();
+ WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+ mDividerWidth, MATCH_PARENT, TYPE_DOCK_DIVIDER,
+ FLAG_TOUCHABLE_WHEN_WAKING | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL
+ | FLAG_WATCH_OUTSIDE_TOUCH | FLAG_SPLIT_TOUCH,
+ PixelFormat.OPAQUE);
+ params.setTitle(TAG);
+ manager.addView(view, params, mDisplayContent.getDisplay(), null);
+ mView = view;
+ }
+
+ private void removeDivider() {
+ WindowManagerGlobal manager = WindowManagerGlobal.getInstance();
+ manager.removeView(mView, true /* immediate */);
+ mView = null;
+ }
+
+ boolean hasDivider() {
+ return mView != null;
+ }
+
+ void update() {
+ TaskStack stack = mDisplayContent.getDockedStack();
+ if (stack != null && mView == null) {
+ addDivider();
+ } else if (stack == null && mView != null) {
+ removeDivider();
+ }
+ }
+
+ int getWidth() {
+ return mDividerWidth;
+ }
+
+
+ void positionDockedStackedDivider(Rect frame) {
+ TaskStack stack = mDisplayContent.getDockedStack();
+ if (stack == null) {
+ // Unfortunately we might end up with still having a divider, even though the underlying
+ // stack was already removed. This is because we are on AM thread and the removal of the
+ // divider was deferred to WM thread and hasn't happened yet.
+ return;
+ }
+ final @TaskStack.DockSide int side = stack.getDockSide();
+ stack.getBounds(mTmpRect);
+ switch (side) {
+ case TaskStack.DOCKED_LEFT:
+ frame.set(mTmpRect.right, frame.top, mTmpRect.right + frame.width(), frame.bottom);
+ break;
+ case TaskStack.DOCKED_TOP:
+ frame.set(frame.left, mTmpRect.bottom, mTmpRect.right,
+ mTmpRect.bottom + frame.height());
+ break;
+ case TaskStack.DOCKED_RIGHT:
+ frame.set(mTmpRect.left - frame.width(), frame.top, mTmpRect.left, frame.bottom);
+ break;
+ case TaskStack.DOCKED_BOTTOM:
+ frame.set(frame.left, mTmpRect.top - frame.height(), frame.right, mTmpRect.top);
+ break;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index cc9efdbe90af..6ebff4212b16 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityManager.DOCKED_STACK_ID;
import static com.android.server.wm.WindowManagerService.TAG;
import static com.android.server.wm.WindowManagerService.DEBUG_RESIZE;
import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
@@ -72,6 +73,9 @@ class Task implements DimLayer.DimLayerUser {
// For handling display rotations.
private Rect mTmpRect2 = new Rect();
+ // Whether the task is currently being drag-resized
+ private boolean mDragResizing;
+
// The particular window with FLAG_DIM_BEHIND set. If null, hide mDimLayer.
WindowStateAnimator mDimWinAnimator;
// Used to support {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND}
@@ -227,10 +231,32 @@ class Task implements DimLayer.DimLayerUser {
return boundsChange;
}
+ boolean resizeLocked(Rect bounds, Configuration configuration, boolean forced) {
+ int boundsChanged = setBounds(bounds, configuration);
+ if (forced) {
+ boundsChanged |= BOUNDS_CHANGE_SIZE;
+ }
+ if (boundsChanged == BOUNDS_CHANGE_NONE) {
+ return false;
+ }
+ if ((boundsChanged & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
+ resizeWindows();
+ }
+ return true;
+ }
+
void getBounds(Rect out) {
out.set(mBounds);
}
+ void setDragResizing(boolean dragResizing) {
+ mDragResizing = dragResizing;
+ }
+
+ boolean isDragResizing() {
+ return mDragResizing;
+ }
+
void updateDisplayInfo(final DisplayContent displayContent) {
if (displayContent == null) {
return;
@@ -246,31 +272,8 @@ class Task implements DimLayer.DimLayerUser {
// Device rotation changed. We don't want the task to move around on the screen when
// this happens, so update the task bounds so it stays in the same place.
- final int rotationDelta = DisplayContent.deltaRotation(mRotation, newRotation);
- displayContent.getLogicalDisplayRect(mTmpRect);
- switch (rotationDelta) {
- case Surface.ROTATION_0:
- mTmpRect2.set(mBounds);
- break;
- case Surface.ROTATION_90:
- mTmpRect2.top = mTmpRect.bottom - mBounds.right;
- mTmpRect2.left = mBounds.top;
- mTmpRect2.right = mTmpRect2.left + mBounds.height();
- mTmpRect2.bottom = mTmpRect2.top + mBounds.width();
- break;
- case Surface.ROTATION_180:
- mTmpRect2.top = mTmpRect.bottom - mBounds.bottom;
- mTmpRect2.left = mTmpRect.right - mBounds.right;
- mTmpRect2.right = mTmpRect2.left + mBounds.width();
- mTmpRect2.bottom = mTmpRect2.top + mBounds.height();
- break;
- case Surface.ROTATION_270:
- mTmpRect2.top = mBounds.left;
- mTmpRect2.left = mTmpRect.right - mBounds.bottom;
- mTmpRect2.right = mTmpRect2.left + mBounds.height();
- mTmpRect2.bottom = mTmpRect2.top + mBounds.width();
- break;
- }
+ mTmpRect2.set(mBounds);
+ displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
setBounds(mTmpRect2, mOverrideConfig);
}
@@ -430,6 +433,10 @@ class Task implements DimLayer.DimLayerUser {
return mStack != null && mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
}
+ boolean inDockedWorkspace() {
+ return mStack != null && mStack.mStackId == DOCKED_STACK_ID;
+ }
+
@Override
public boolean isFullscreen() {
return mFullscreen;
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 17b56ba2ada2..9557d121830d 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -19,6 +19,8 @@ package com.android.server.wm;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.RESIZE_MODE_FORCED;
+import static android.app.ActivityManager.RESIZE_MODE_USER;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static com.android.server.wm.WindowManagerService.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerService.SHOW_TRANSACTIONS;
@@ -86,8 +88,7 @@ class TaskPositioner implements DimLayer.DimLayerUser {
private int mMinVisibleWidth;
private int mMinVisibleHeight;
- private int mTaskId;
- private TaskStack mStack;
+ private Task mTask;
private boolean mResizing;
private final Rect mWindowOriginalBounds = new Rect();
private final Rect mWindowDragBounds = new Rect();
@@ -95,6 +96,7 @@ class TaskPositioner implements DimLayer.DimLayerUser {
private float mStartDragY;
@CtrlType
private int mCtrlType = CTRL_NONE;
+ private boolean mDragEnded = false;
InputChannel mServerChannel;
InputChannel mClientChannel;
@@ -116,7 +118,14 @@ class TaskPositioner implements DimLayer.DimLayerUser {
boolean handled = false;
try {
- boolean endDrag = false;
+ if (mDragEnded) {
+ // The drag has ended but the clean-up message has not been processed by
+ // window manager. Drop events that occur after this until window manager
+ // has a chance to clean-up the input handle.
+ handled = true;
+ return;
+ }
+
final float newX = motionEvent.getRawX();
final float newY = motionEvent.getRawY();
@@ -132,11 +141,11 @@ class TaskPositioner implements DimLayer.DimLayerUser {
Slog.w(TAG, "ACTION_MOVE @ {" + newX + ", " + newY + "}");
}
synchronized (mService.mWindowMap) {
- endDrag = notifyMoveLocked(newX, newY);
+ mDragEnded = notifyMoveLocked(newX, newY);
}
try {
mService.mActivityManager.resizeTask(
- mTaskId, mWindowDragBounds, true /* resizedByUser */);
+ mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER);
} catch(RemoteException e) {}
} break;
@@ -144,33 +153,41 @@ class TaskPositioner implements DimLayer.DimLayerUser {
if (DEBUG_TASK_POSITIONING) {
Slog.w(TAG, "ACTION_UP @ {" + newX + ", " + newY + "}");
}
- endDrag = true;
+ mDragEnded = true;
} break;
case MotionEvent.ACTION_CANCEL: {
if (DEBUG_TASK_POSITIONING) {
Slog.w(TAG, "ACTION_CANCEL @ {" + newX + ", " + newY + "}");
}
- endDrag = true;
+ mDragEnded = true;
} break;
}
- if (endDrag) {
- mResizing = false;
+ if (mDragEnded) {
+ synchronized (mService.mWindowMap) {
+ endDragLocked();
+ }
try {
- mService.mActivityManager.resizeTask(
- mTaskId, mWindowDragBounds, true /* resizedByUser */);
+ if (mResizing) {
+ // We were using fullscreen surface during resizing. Request
+ // resizeTask() one last time to restore surface to window size.
+ mService.mActivityManager.resizeTask(
+ mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_FORCED);
+ }
+
+ if (mCurrentDimSide != CTRL_NONE) {
+ final int createMode = mCurrentDimSide == CTRL_LEFT
+ ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
+ : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
+ mService.mActivityManager.moveTaskToDockedStack(
+ mTask.mTaskId, createMode, true /*toTop*/);
+ }
} catch(RemoteException e) {}
+
// Post back to WM to handle clean-ups. We still need the input
// event handler for the last finishInputEvent()!
mService.mH.sendEmptyMessage(H.FINISH_TASK_POSITIONING);
- if (mCurrentDimSide != CTRL_NONE) {
- final int createMode = mCurrentDimSide == CTRL_LEFT
- ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
- : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
- mService.mActivityManager.moveTaskToDockedStack(
- mTaskId, createMode, true /*toTop*/);
- }
}
handled = true;
} catch (Exception e) {
@@ -253,6 +270,8 @@ class TaskPositioner implements DimLayer.DimLayerUser {
mSideMargin = mService.dipToPixel(SIDE_MARGIN_DIP, mDisplayMetrics);
mMinVisibleWidth = mService.dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics);
mMinVisibleHeight = mService.dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics);
+
+ mDragEnded = false;
}
void unregister() {
@@ -283,6 +302,7 @@ class TaskPositioner implements DimLayer.DimLayerUser {
mDimLayer = null;
}
mCurrentDimSide = CTRL_NONE;
+ mDragEnded = true;
// Resume rotations after a drag.
if (WindowManagerService.DEBUG_ORIENTATION) {
@@ -291,10 +311,6 @@ class TaskPositioner implements DimLayer.DimLayerUser {
mService.resumeRotationLocked();
}
- boolean isTaskResizing(final Task task) {
- return mResizing && task != null && mTaskId == task.mTaskId;
- }
-
void startDragLocked(WindowState win, boolean resize, float startX, float startY) {
if (DEBUG_TASK_POSITIONING) {
Slog.d(TAG, "startDragLocked: win=" + win + ", resize=" + resize
@@ -318,13 +334,16 @@ class TaskPositioner implements DimLayer.DimLayerUser {
mResizing = true;
}
- final Task task = win.getTask();
- mTaskId = task.mTaskId;
- mStack = task.mStack;
+ mTask = win.getTask();
mStartDragX = startX;
mStartDragY = startY;
- mService.getTaskBounds(mTaskId, mWindowOriginalBounds);
+ mService.getTaskBounds(mTask.mTaskId, mWindowOriginalBounds);
+ }
+
+ private void endDragLocked() {
+ mResizing = false;
+ mTask.setDragResizing(false);
}
/** Returns true if the move operation should be ended. */
@@ -354,11 +373,12 @@ class TaskPositioner implements DimLayer.DimLayerUser {
bottom = Math.max(top + mMinVisibleHeight, bottom + deltaY);
}
mWindowDragBounds.set(left, top, right, bottom);
+ mTask.setDragResizing(true);
return false;
}
// This is a moving operation.
- mStack.getBounds(mTmpRect);
+ mTask.mStack.getBounds(mTmpRect);
mTmpRect.inset(mMinVisibleWidth, mMinVisibleHeight);
if (!mTmpRect.contains((int) x, (int) y)) {
// We end the moving operation if position is outside the stack bounds.
@@ -397,13 +417,13 @@ class TaskPositioner implements DimLayer.DimLayerUser {
* shouldn't be shown.
*/
private int getDimSide(int x) {
- if (mStack.mStackId != FREEFORM_WORKSPACE_STACK_ID
- || !mStack.isFullscreen()
+ if (mTask.mStack.mStackId != FREEFORM_WORKSPACE_STACK_ID
+ || !mTask.mStack.isFullscreen()
|| mService.mCurConfiguration.orientation != ORIENTATION_LANDSCAPE) {
return CTRL_NONE;
}
- mStack.getBounds(mTmpRect);
+ mTask.mStack.getBounds(mTmpRect);
if (x - mSideMargin <= mTmpRect.left) {
return CTRL_LEFT;
}
@@ -415,7 +435,7 @@ class TaskPositioner implements DimLayer.DimLayerUser {
}
private void showDimLayer() {
- mStack.getBounds(mTmpRect);
+ mTask.mStack.getBounds(mTmpRect);
if (mCurrentDimSide == CTRL_LEFT) {
mTmpRect.right = mTmpRect.centerX();
} else if (mCurrentDimSide == CTRL_RIGHT) {
@@ -433,7 +453,7 @@ class TaskPositioner implements DimLayer.DimLayerUser {
@Override /** {@link DimLayer.DimLayerUser} */
public DisplayInfo getDisplayInfo() {
- return mStack.getDisplayInfo();
+ return mTask.mStack.getDisplayInfo();
}
private int getDragLayerLocked() {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 571540fade62..96fcf93b5981 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -30,6 +30,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.view.DisplayInfo;
+import android.view.Surface;
import com.android.server.EventLogTags;
import java.io.PrintWriter;
@@ -57,6 +58,7 @@ public class TaskStack implements DimLayer.DimLayerUser {
/** For comparison with DisplayContent bounds. */
private Rect mTmpRect = new Rect();
+ private Rect TmpRect2 = new Rect();
/** Content limits relative to the DisplayContent this sits in. */
private Rect mBounds = new Rect();
@@ -64,6 +66,9 @@ public class TaskStack implements DimLayer.DimLayerUser {
/** Whether mBounds is fullscreen */
private boolean mFullscreen = true;
+ // Device rotation as of the last time {@link #mBounds} was set.
+ int mRotation;
+
/** Support for non-zero {@link android.view.animation.Animation#getBackgroundColor()} */
DimLayer mAnimationBackgroundSurface;
@@ -118,30 +123,22 @@ public class TaskStack implements DimLayer.DimLayerUser {
/**
* Set the bounds of the stack and its containing tasks.
* @param stackBounds New stack bounds. Passing in null sets the bounds to fullscreen.
- * @param resizeTasks If true, the tasks within the stack will also be resized.
* @param configs Configuration for individual tasks, keyed by task id.
* @param taskBounds Bounds for individual tasks, keyed by task id.
* @return True if the stack bounds was changed.
* */
- boolean setBounds(Rect stackBounds, boolean resizeTasks, SparseArray<Configuration> configs,
- SparseArray<Rect> taskBounds) {
+ boolean setBounds(
+ Rect stackBounds, SparseArray<Configuration> configs, SparseArray<Rect> taskBounds) {
if (!setBounds(stackBounds)) {
return false;
}
- if (!resizeTasks) {
- return true;
- }
-
// Update bounds of containing tasks.
for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
final Task task = mTasks.get(taskNdx);
Configuration config = configs.get(task.mTaskId);
if (config != null) {
Rect bounds = taskBounds.get(task.mTaskId);
- if (bounds == null) {
- bounds = stackBounds;
- }
task.setBounds(bounds, config);
} else {
Slog.wtf(TAG, "No config for task: " + task + ", is there a mismatch with AM?");
@@ -152,8 +149,10 @@ public class TaskStack implements DimLayer.DimLayerUser {
private boolean setBounds(Rect bounds) {
boolean oldFullscreen = mFullscreen;
+ int rotation = Surface.ROTATION_0;
if (mDisplayContent != null) {
mDisplayContent.getLogicalDisplayRect(mTmpRect);
+ rotation = mDisplayContent.getDisplayInfo().rotation;
if (bounds == null) {
bounds = mTmpRect;
mFullscreen = true;
@@ -171,12 +170,13 @@ public class TaskStack implements DimLayer.DimLayerUser {
// Can't set to fullscreen if we don't have a display to get bounds from...
return false;
}
- if (mBounds.equals(bounds) && oldFullscreen == mFullscreen) {
+ if (mBounds.equals(bounds) && oldFullscreen == mFullscreen && mRotation == rotation) {
return false;
}
mAnimationBackgroundSurface.setBounds(bounds);
mBounds.set(bounds);
+ mRotation = rotation;
return true;
}
@@ -188,8 +188,13 @@ public class TaskStack implements DimLayer.DimLayerUser {
if (mDisplayContent != null) {
if (bounds != null) {
setBounds(bounds);
+ } else if (mFullscreen) {
+ setBounds(null);
} else {
- setBounds(mFullscreen ? null : mBounds);
+ TmpRect2.set(mBounds);
+ mDisplayContent.rotateBounds(
+ mRotation, mDisplayContent.getDisplayInfo().rotation, TmpRect2);
+ setBounds(TmpRect2);
}
for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
mTasks.get(taskNdx).updateDisplayInfo(mDisplayContent);
@@ -347,7 +352,8 @@ public class TaskStack implements DimLayer.DimLayerUser {
// the docked stack occupies a dedicated region on screen.
bounds = new Rect();
displayContent.getLogicalDisplayRect(mTmpRect);
- getInitialDockedStackBounds(mTmpRect, bounds, mStackId);
+ getInitialDockedStackBounds(mTmpRect, bounds, mStackId,
+ mDisplayContent.mDividerControllerLocked.getWidth() / 2);
}
updateDisplayInfo(bounds);
@@ -366,27 +372,29 @@ public class TaskStack implements DimLayer.DimLayerUser {
* @param displayRect The bounds of the display the docked stack is on.
* @param outBounds Output bounds that should be used for the stack.
* @param stackId Id of stack we are calculating the bounds for.
+ * @param adjustment
*/
- private static void getInitialDockedStackBounds(
- Rect displayRect, Rect outBounds, int stackId) {
+ private static void getInitialDockedStackBounds(Rect displayRect, Rect outBounds, int stackId,
+ int adjustment) {
// Docked stack start off occupying half the screen space.
+ final boolean dockedStack = stackId == DOCKED_STACK_ID;
final boolean splitHorizontally = displayRect.width() > displayRect.height();
final boolean topOrLeftCreateMode =
WindowManagerService.sDockedStackCreateMode == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
- final boolean placeTopOrLeft = (stackId == DOCKED_STACK_ID && topOrLeftCreateMode)
- || (stackId != DOCKED_STACK_ID && !topOrLeftCreateMode);
+ final boolean placeTopOrLeft = (dockedStack && topOrLeftCreateMode)
+ || (!dockedStack && !topOrLeftCreateMode);
outBounds.set(displayRect);
if (placeTopOrLeft) {
if (splitHorizontally) {
- outBounds.right = displayRect.centerX();
+ outBounds.right = displayRect.centerX() - adjustment;
} else {
- outBounds.bottom = displayRect.centerY();
+ outBounds.bottom = displayRect.centerY() - adjustment;
}
} else {
if (splitHorizontally) {
- outBounds.left = displayRect.centerX();
+ outBounds.left = displayRect.centerX() + adjustment;
} else {
- outBounds.top = displayRect.centerY();
+ outBounds.top = displayRect.centerY() + adjustment;
}
}
}
@@ -399,7 +407,8 @@ public class TaskStack implements DimLayer.DimLayerUser {
private void resizeNonDockedStacks(boolean fullscreen) {
mDisplayContent.getLogicalDisplayRect(mTmpRect);
if (!fullscreen) {
- getInitialDockedStackBounds(mTmpRect, mTmpRect, FULLSCREEN_WORKSPACE_STACK_ID);
+ getInitialDockedStackBounds(mTmpRect, mTmpRect, FULLSCREEN_WORKSPACE_STACK_ID,
+ mDisplayContent.mDividerControllerLocked.getWidth());
}
final int count = mService.mStackIdToStack.size();
@@ -541,14 +550,14 @@ public class TaskStack implements DimLayer.DimLayerUser {
final int orientation = mService.mCurConfiguration.orientation;
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
// Portrait mode, docked either at the top or the bottom.
- if (mTmpRect.top - mBounds.top < mTmpRect.bottom - mBounds.bottom) {
+ if (mBounds.top - mTmpRect.top < mTmpRect.bottom - mBounds.bottom) {
return DOCKED_TOP;
} else {
return DOCKED_BOTTOM;
}
} else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
// Landscape mode, docked either on the left or on the right.
- if (mTmpRect.left - mBounds.left < mTmpRect.right - mBounds.right) {
+ if (mBounds.left - mTmpRect.left < mTmpRect.right - mBounds.right) {
return DOCKED_LEFT;
} else {
return DOCKED_RIGHT;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 22a6f62abad5..d510c4a4f7f0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+import static android.app.ActivityManager.DOCKED_STACK_ID;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
@@ -33,6 +34,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
@@ -921,6 +923,7 @@ public class WindowManagerService extends IWindowManager.Stub
mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
+
LocalServices.addService(WindowManagerInternal.class, new LocalService());
initPolicy();
@@ -1854,6 +1857,11 @@ public class WindowManagerService extends IWindowManager.Stub
+ attrs.token + ". Aborting.");
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
+ } else if (type == TYPE_DOCK_DIVIDER) {
+ if (displayContent.mDividerControllerLocked.hasDivider()) {
+ Slog.w(TAG, "Attempted to add docked stack divider twice. Aborting.");
+ return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
+ }
} else if (token.appWindowToken != null) {
Slog.w(TAG, "Non-null appWindowToken for system window of type=" + type);
// It is not valid to use an app token with other system types; we will
@@ -2589,9 +2597,13 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- dragResizing = win.isDragResizing();
- if (win.mDragResizing != dragResizing) {
- win.mDragResizing = dragResizing;
+ // If we're starting a drag-resize, we'll be changing the surface size as well as
+ // notifying the client to render to with an offset from the surface's top-left.
+ // Do a screen freeze, and keep the old surface until the the first frame drawn to
+ // the new surface comes back, so that we avoid a flash due to mismatching surface
+ // setups on window manager side and client side.
+ if (win.isDragResizeChanged()) {
+ win.setDragResizing();
if (win.mHasSurface) {
winAnimator.mDestroyPendingSurfaceUponRedraw = true;
winAnimator.mSurfaceDestroyDeferred = true;
@@ -2600,6 +2612,7 @@ public class WindowManagerService extends IWindowManager.Stub
toBeDisplayed = true;
}
}
+ dragResizing = win.isDragResizing();
try {
if (!win.mHasSurface) {
surfaceChanged = true;
@@ -4516,7 +4529,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
stack.attachDisplayContent(displayContent);
displayContent.attachStack(stack, onTop);
-
+ if (stack.mStackId == DOCKED_STACK_ID) {
+ mH.obtainMessage(H.UPDATE_DOCKED_STACK_DIVIDER,
+ displayContent).sendToTarget();
+ }
moveStackWindowsLocked(displayContent);
final WindowList windows = displayContent.getWindowList();
for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
@@ -4539,6 +4555,11 @@ public class WindowManagerService extends IWindowManager.Stub
void detachStackLocked(DisplayContent displayContent, TaskStack stack) {
displayContent.detachStack(stack);
stack.detachDisplay();
+ // We can't directly remove the divider, because only the WM thread can do these operations
+ // and we can be on AM thread.
+ if (stack.mStackId == DOCKED_STACK_ID) {
+ mH.obtainMessage(H.UPDATE_DOCKED_STACK_DIVIDER, displayContent).sendToTarget();
+ }
}
public void detachStack(int stackId) {
@@ -4627,12 +4648,11 @@ public class WindowManagerService extends IWindowManager.Stub
* Re-sizes a stack and its containing tasks.
* @param stackId Id of stack to resize.
* @param bounds New stack bounds. Passing in null sets the bounds to fullscreen.
- * @param resizeTasks If true, the tasks within the stack will also be resized.
* @param configs Configurations for tasks in the resized stack, keyed by task id.
* @param taskBounds Bounds for tasks in the resized stack, keyed by task id.
* @return True if the stack is now fullscreen.
* */
- public boolean resizeStack(int stackId, Rect bounds, boolean resizeTasks,
+ public boolean resizeStack(int stackId, Rect bounds,
SparseArray<Configuration> configs, SparseArray<Rect> taskBounds) {
synchronized (mWindowMap) {
final TaskStack stack = mStackIdToStack.get(stackId);
@@ -4640,7 +4660,7 @@ public class WindowManagerService extends IWindowManager.Stub
throw new IllegalArgumentException("resizeStack: stackId " + stackId
+ " not found.");
}
- if (stack.setBounds(bounds, resizeTasks, configs, taskBounds)) {
+ if (stack.setBounds(bounds, configs, taskBounds)) {
stack.resizeWindows();
stack.getDisplayContent().layoutNeeded = true;
mWindowPlacerLocked.performSurfacePlacement();
@@ -4677,23 +4697,18 @@ public class WindowManagerService extends IWindowManager.Stub
* Returns a {@link Configuration} object that contains configurations settings
* that should be overridden due to the operation.
*/
- public void resizeTask(int taskId, Rect bounds, Configuration configuration, boolean relayout) {
+ public void resizeTask(int taskId, Rect bounds, Configuration configuration,
+ boolean relayout, boolean forced) {
synchronized (mWindowMap) {
Task task = mTaskIdToTask.get(taskId);
if (task == null) {
throw new IllegalArgumentException("resizeTask: taskId " + taskId
+ " not found.");
}
- final int boundsChanged = task.setBounds(bounds, configuration);
- if (boundsChanged != Task.BOUNDS_CHANGE_NONE) {
- if ((boundsChanged & Task.BOUNDS_CHANGE_SIZE) == Task.BOUNDS_CHANGE_SIZE) {
- task.resizeWindows();
- }
- if (relayout) {
- task.getDisplayContent().layoutNeeded = true;
- mWindowPlacerLocked.performSurfacePlacement();
- }
+ if (task.resizeLocked(bounds, configuration, forced) && relayout) {
+ task.getDisplayContent().layoutNeeded = true;
+ mWindowPlacerLocked.performSurfacePlacement();
}
}
}
@@ -7221,6 +7236,8 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int TAP_DOWN_OUTSIDE_TASK = 40;
public static final int FINISH_TASK_POSITIONING = 41;
+ public static final int UPDATE_DOCKED_STACK_DIVIDER = 42;
+
@Override
public void handleMessage(Message msg) {
if (DEBUG_WINDOW_TRACE) {
@@ -7760,6 +7777,13 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
break;
+ case UPDATE_DOCKED_STACK_DIVIDER: {
+ DisplayContent content = (DisplayContent) msg.obj;
+ synchronized (mWindowMap) {
+ content.mDividerControllerLocked.update();
+ }
+ }
+ break;
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG, "handleMessage: exit");
@@ -8476,7 +8500,7 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.v(TAG, "Win " + w + " config changed: "
+ mCurConfiguration);
}
- final boolean dragResizingChanged = w.mDragResizing != w.isDragResizing();
+ final boolean dragResizingChanged = w.isDragResizeChanged();
if (localLOGV) Slog.v(TAG, "Resizing " + w
+ ": configChanged=" + configChanged
+ " dragResizingChanged=" + dragResizingChanged
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 16347f560e64..64440d389910 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -23,6 +23,7 @@ import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
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;
@@ -128,6 +129,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
boolean mAttachedHidden; // is our parent window hidden?
boolean mWallpaperVisible; // for wallpaper, what was last vis report?
boolean mDragResizing;
+ boolean mDragResizeChanging;
RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks;
@@ -706,6 +708,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mContentFrame.set(mFrame);
mVisibleFrame.set(mContentFrame);
mStableFrame.set(mContentFrame);
+ } else if (mAttrs.type == TYPE_DOCK_DIVIDER) {
+ mDisplayContent.mDividerControllerLocked.positionDockedStackedDivider(mFrame);
} else {
mContentFrame.set(Math.max(mContentFrame.left, mFrame.left),
Math.max(mContentFrame.top, mFrame.top),
@@ -1701,9 +1705,18 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return task != null && task.inFreeformWorkspace();
}
- boolean isDragResizing() {
+ boolean isDragResizeChanged() {
+ final Task task = getTask();
+ return task != null && mDragResizing != task.isDragResizing();
+ }
+
+ void setDragResizing() {
final Task task = getTask();
- return mService.mTaskPositioner != null && mService.mTaskPositioner.isTaskResizing(task);
+ mDragResizing = task != null && task.isDragResizing();
+ }
+
+ boolean isDragResizing() {
+ return mDragResizing;
}
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index e6fef2f0d22f..07e1fce4c741 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -818,7 +818,7 @@ class WindowStateAnimator {
// so that we don't need to reallocate during the process. This also prevents
// buffer drops due to size mismatch.
final DisplayInfo displayInfo = w.getDisplayInfo();
- if (displayInfo != null && w.mDragResizing) {
+ if (displayInfo != null && w.isDragResizing()) {
left = 0;
top = 0;
width = displayInfo.logicalWidth;
@@ -1211,6 +1211,13 @@ class WindowStateAnimator {
return;
} else if (mIsWallpaper && mService.mWindowPlacerLocked.mWallpaperActionPending) {
return;
+ } else if (mWin.isDragResizeChanged()) {
+ // This window is awaiting a relayout because user just started (or ended)
+ // drag-resizing. The shown frame (which affects surface size and pos)
+ // should not be updated until we get next finished draw with the new surface.
+ // Otherwise one or two frames rendered with old settings would be displayed
+ // with new geometry.
+ return;
}
if (WindowManagerService.localLOGV) Slog.v(
@@ -1333,7 +1340,7 @@ class WindowStateAnimator {
final boolean fullscreen = w.isFullscreen(displayInfo.appWidth, displayInfo.appHeight);
final Rect clipRect = mTmpClipRect;
- if (w.mDragResizing) {
+ if (w.isDragResizing()) {
// When we're doing a drag-resizing, the surface is set up to cover full screen.
// Set the clip rect to be the same size so that we don't get any scaling.
clipRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
@@ -1423,7 +1430,7 @@ class WindowStateAnimator {
// so that we don't need to reallocate during the process. This also prevents
// buffer drops due to size mismatch.
final DisplayInfo displayInfo = w.getDisplayInfo();
- if (displayInfo != null && w.mDragResizing) {
+ if (displayInfo != null && w.isDragResizing()) {
left = 0;
top = 0;
width = displayInfo.logicalWidth;
diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
index 3fd0f84f5957..5cbb277a2f12 100644
--- a/services/core/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/core/jni/com_android_server_AlarmManagerService.cpp
@@ -460,7 +460,7 @@ static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv*, jobject, jl
return result;
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"init", "()J", (void*)android_server_AlarmManagerService_init},
{"close", "(J)V", (void*)android_server_AlarmManagerService_close},
diff --git a/services/core/jni/com_android_server_AssetAtlasService.cpp b/services/core/jni/com_android_server_AssetAtlasService.cpp
index 8f4fb51093d9..ed79ceb3a9d3 100644
--- a/services/core/jni/com_android_server_AssetAtlasService.cpp
+++ b/services/core/jni/com_android_server_AssetAtlasService.cpp
@@ -204,7 +204,7 @@ static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject
const char* const kClassPathName = "com/android/server/AssetAtlasService";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nUploadAtlas", "(Landroid/view/GraphicBuffer;Landroid/graphics/Bitmap;)Z",
(void*) com_android_server_AssetAtlasService_upload },
};
diff --git a/services/core/jni/com_android_server_ConsumerIrService.cpp b/services/core/jni/com_android_server_ConsumerIrService.cpp
index f5121cdf5580..7104870349b5 100644
--- a/services/core/jni/com_android_server_ConsumerIrService.cpp
+++ b/services/core/jni/com_android_server_ConsumerIrService.cpp
@@ -100,7 +100,7 @@ static jintArray halGetCarrierFrequencies(JNIEnv *env, jobject /* obj */,
return freqsOut.getJavaArray();
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "halOpen", "()J", (void *)halOpen },
{ "halTransmit", "(JI[I)I", (void *)halTransmit },
{ "halGetCarrierFrequencies", "(J)[I", (void *)halGetCarrierFrequencies},
diff --git a/services/core/jni/com_android_server_PersistentDataBlockService.cpp b/services/core/jni/com_android_server_PersistentDataBlockService.cpp
index 4ccfa56cd30c..06de592d7533 100644
--- a/services/core/jni/com_android_server_PersistentDataBlockService.cpp
+++ b/services/core/jni/com_android_server_PersistentDataBlockService.cpp
@@ -97,7 +97,7 @@ namespace android {
return wipe_block_device(fd);
}
- static JNINativeMethod sMethods[] = {
+ static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"nativeGetBlockDeviceSize", "(Ljava/lang/String;)J", (void*)com_android_server_PersistentDataBlockService_getBlockDeviceSize},
{"nativeWipe", "(Ljava/lang/String;)I", (void*)com_android_server_PersistentDataBlockService_wipe},
diff --git a/services/core/jni/com_android_server_SerialService.cpp b/services/core/jni/com_android_server_SerialService.cpp
index d48d159b1178..1bd7a599ed60 100644
--- a/services/core/jni/com_android_server_SerialService.cpp
+++ b/services/core/jni/com_android_server_SerialService.cpp
@@ -55,7 +55,7 @@ static jobject android_server_SerialService_open(JNIEnv *env, jobject /* thiz */
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "native_open", "(Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;",
(void*)android_server_SerialService_open },
};
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index 64514a9f72e8..c7d6b95083d2 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -37,7 +37,7 @@ static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jo
/*
* JNI registration.
*/
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "startSensorService", "()V", (void*) android_server_SystemServer_startSensorService },
};
diff --git a/services/core/jni/com_android_server_UsbDeviceManager.cpp b/services/core/jni/com_android_server_UsbDeviceManager.cpp
index a1bff9d850bf..3733a55e7504 100644
--- a/services/core/jni/com_android_server_UsbDeviceManager.cpp
+++ b/services/core/jni/com_android_server_UsbDeviceManager.cpp
@@ -118,7 +118,7 @@ static jint android_server_UsbDeviceManager_getAudioMode(JNIEnv* /* env */, jobj
return result;
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "nativeGetAccessoryStrings", "()[Ljava/lang/String;",
(void*)android_server_UsbDeviceManager_getAccessoryStrings },
{ "nativeOpenAccessory", "()Landroid/os/ParcelFileDescriptor;",
diff --git a/services/core/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp
index d8c172fd51cc..795f6aa6018a 100644
--- a/services/core/jni/com_android_server_UsbHostManager.cpp
+++ b/services/core/jni/com_android_server_UsbHostManager.cpp
@@ -186,7 +186,7 @@ static jobject android_server_UsbHostManager_openDevice(JNIEnv *env, jobject /*
gParcelFileDescriptorOffsets.mConstructor, fileDescriptor);
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "monitorUsbHostBus", "()V", (void*)android_server_UsbHostManager_monitorUsbHostBus },
{ "nativeOpenDevice", "(Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;",
(void*)android_server_UsbHostManager_openDevice },
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index fb1166b41d41..64278ed4499b 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -46,7 +46,7 @@ static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */)
vibrator_off();
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "vibratorExists", "()Z", (void*)vibratorExists },
{ "vibratorOn", "(J)V", (void*)vibratorOn },
{ "vibratorOff", "()V", (void*)vibratorOff }
diff --git a/services/core/jni/com_android_server_am_ActivityManagerService.cpp b/services/core/jni/com_android_server_am_ActivityManagerService.cpp
index 52217b955852..50e4502a9a3a 100644
--- a/services/core/jni/com_android_server_am_ActivityManagerService.cpp
+++ b/services/core/jni/com_android_server_am_ActivityManagerService.cpp
@@ -110,7 +110,6 @@ namespace android
return 0;
}
char buf[17];
- char *curBuf = buf;
while (fgets(buf, 16, boost_cpuset_file)) {
//ALOGE("Appending FD %s to fg", buf);
int i = 0;
diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
index dfc5ef6ec366..5c4365979644 100644
--- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp
+++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
@@ -170,7 +170,7 @@ static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobject outBuf)
return mergedreasonpos - mergedreason;
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "nativeWaitWakeup", "(Ljava/nio/ByteBuffer;)I", (void*)nativeWaitWakeup },
};
diff --git a/services/core/jni/com_android_server_connectivity_Vpn.cpp b/services/core/jni/com_android_server_connectivity_Vpn.cpp
index 7faeb49d7b56..2d0dfd2f7f26 100644
--- a/services/core/jni/com_android_server_connectivity_Vpn.cpp
+++ b/services/core/jni/com_android_server_connectivity_Vpn.cpp
@@ -350,7 +350,7 @@ static bool delAddress(JNIEnv *env, jobject thiz, jstring jName, jstring jAddres
//------------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"jniCreate", "(I)I", (void *)create},
{"jniGetName", "(I)Ljava/lang/String;", (void *)getName},
{"jniSetAddresses", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setAddresses},
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
index f2d0f060c66c..b72cf4dc94d0 100644
--- a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
@@ -384,7 +384,7 @@ static jboolean nativeIsConnected(JNIEnv* env, jclass clazz, jlong controllerPtr
return controller->isConnected(port) ? JNI_TRUE : JNI_FALSE ;
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit",
"(Lcom/android/server/hdmi/HdmiCecController;Landroid/os/MessageQueue;)J",
diff --git a/services/core/jni/com_android_server_input_InputApplicationHandle.cpp b/services/core/jni/com_android_server_input_InputApplicationHandle.cpp
index 11388d80a9d2..bdc109d086f6 100644
--- a/services/core/jni/com_android_server_input_InputApplicationHandle.cpp
+++ b/services/core/jni/com_android_server_input_InputApplicationHandle.cpp
@@ -120,7 +120,7 @@ static void android_server_InputApplicationHandle_nativeDispose(JNIEnv* env, job
}
-static JNINativeMethod gInputApplicationHandleMethods[] = {
+static const JNINativeMethod gInputApplicationHandleMethods[] = {
/* name, signature, funcPtr */
{ "nativeDispose", "()V",
(void*) android_server_InputApplicationHandle_nativeDispose },
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index e29d0a94610c..1d4f047ff605 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -1369,7 +1369,7 @@ static void nativeMonitor(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) {
// ----------------------------------------------------------------------------
-static JNINativeMethod gInputManagerMethods[] = {
+static const JNINativeMethod gInputManagerMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit",
"(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)J",
diff --git a/services/core/jni/com_android_server_input_InputWindowHandle.cpp b/services/core/jni/com_android_server_input_InputWindowHandle.cpp
index 01c51cf6cfe0..92ef7f1ae096 100644
--- a/services/core/jni/com_android_server_input_InputWindowHandle.cpp
+++ b/services/core/jni/com_android_server_input_InputWindowHandle.cpp
@@ -210,7 +210,7 @@ static void android_server_InputWindowHandle_nativeDispose(JNIEnv* env, jobject
}
-static JNINativeMethod gInputWindowHandleMethods[] = {
+static const JNINativeMethod gInputWindowHandleMethods[] = {
/* name, signature, funcPtr */
{ "nativeDispose", "()V",
(void*) android_server_InputWindowHandle_nativeDispose },
diff --git a/services/core/jni/com_android_server_lights_LightsService.cpp b/services/core/jni/com_android_server_lights_LightsService.cpp
index b2b27835274d..3f074f52f443 100644
--- a/services/core/jni/com_android_server_lights_LightsService.cpp
+++ b/services/core/jni/com_android_server_lights_LightsService.cpp
@@ -126,7 +126,7 @@ static void setLight_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr,
}
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "init_native", "()J", (void*)init_native },
{ "finalize_native", "(J)V", (void*)finalize_native },
{ "setLight_native", "(JIIIIII)V", (void*)setLight_native },
diff --git a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
index c0a0c9cddba5..774577d43d69 100644
--- a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
+++ b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
@@ -1023,7 +1023,7 @@ static void RemoveGeofences(
env->ReleaseIntArrayElements(geofenceIdsArray, geofenceIds, 0 /*mode*/);
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
//{"name", "signature", functionPointer }
{"nativeClassInit", "()V", reinterpret_cast<void*>(ClassInit)},
{"nativeInit", "()V", reinterpret_cast<void*>(Init)},
diff --git a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
index 5c27b1f65f17..b8d4196dad16 100644
--- a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -1434,7 +1434,7 @@ static void android_location_GpsLocationProvider_configuration_update(JNIEnv* en
env->ReleaseStringUTFChars(config_content, data);
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
{"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported},
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 1662755511f4..2fdb8e2469cd 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -166,7 +166,7 @@ static void nativeSetFeature(JNIEnv *env, jclass clazz, jint featureId, jint dat
// ----------------------------------------------------------------------------
-static JNINativeMethod gPowerManagerServiceMethods[] = {
+static const JNINativeMethod gPowerManagerServiceMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit", "()V",
(void*) nativeInit },
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index 507bc9cb5269..89b2a47d73c6 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -662,7 +662,7 @@ static void nativeClose(JNIEnv* env, jclass clazz, jlong ptr) {
delete tvInputHal;
}
-static JNINativeMethod gTvInputHalMethods[] = {
+static const JNINativeMethod gTvInputHalMethods[] = {
/* name, signature, funcPtr */
{ "nativeOpen", "(Landroid/os/MessageQueue;)J",
(void*) nativeOpen },
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 67e57034cf91..3f70e0c7ccae 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -73,8 +73,10 @@ import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.PersistableBundle;
import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
import android.os.PowerManagerInternal;
import android.os.Process;
import android.os.RecoverySystem;
@@ -111,6 +113,7 @@ import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
@@ -266,16 +269,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
| DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
final Context mContext;
+ final PackageManager mPackageManager;
final UserManager mUserManager;
- final PowerManager.WakeLock mWakeLock;
final LocalService mLocalService;
- final PowerManager mPowerManager;
final PowerManagerInternal mPowerManagerInternal;
- IWindowManager mIWindowManager;
- NotificationManager mNotificationManager;
+ final IWindowManager mIWindowManager;
+ final NotificationManager mNotificationManager;
// Stores and loads state on device and profile owners.
private final Owners mOwners;
@@ -346,7 +348,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final SparseArray<DevicePolicyData> mUserData = new SparseArray<>();
- Handler mHandler = new Handler();
+ final Handler mHandler;
BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
@@ -992,7 +994,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
boolean removed = false;
if (DBG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
DevicePolicyData policy = getUserData(userHandle);
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
synchronized (this) {
for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
ActiveAdmin aa = policy.mAdminList.get(i);
@@ -1036,19 +1038,148 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
+ /** Unit test will override it to inject a mock. */
+ @VisibleForTesting
+ Owners newOwners() {
+ return new Owners(mContext);
+ }
+
+ /** Unit test will override it to inject a mock. */
+ @VisibleForTesting
+ UserManager getUserManager() {
+ return UserManager.get(mContext);
+ }
+
+ /** Unit test will override it to inject a mock. */
+ @VisibleForTesting
+ PackageManager getPackageManager() {
+ return mContext.getPackageManager();
+ }
+
+ /** Unit test will override it to inject a mock. */
+ @VisibleForTesting
+ NotificationManager getNotificationManager() {
+ return mContext.getSystemService(NotificationManager.class);
+ }
+
+ /** Unit test will override it to inject a mock. */
+ @VisibleForTesting
+ PowerManagerInternal getPowerManagerInternal() {
+ return LocalServices.getService(PowerManagerInternal.class);
+ }
+
+ /** Unit test will override it to inject a mock. */
+ @VisibleForTesting
+ IWindowManager getIWindowManager() {
+ return IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
+ }
+
+ /** Unit test will override it to inject a mock. */
+ @VisibleForTesting
+ IActivityManager getIActivityManager() {
+ return ActivityManagerNative.getDefault();
+ }
+
+ /** Unit test will override it to inject a mock. */
+ @VisibleForTesting
+ IPackageManager getIPackageManager() {
+ return AppGlobals.getPackageManager();
+ }
+
+ /** Unit test will override it to inject a mock. */
+ @VisibleForTesting
+ LockPatternUtils newLockPatternUtils(Context context) {
+ return new LockPatternUtils(context);
+ }
+
+ /** Unit test will override it to inject. */
+ @VisibleForTesting
+ Looper getMyLooper() {
+ return Looper.myLooper();
+ }
+
+ @VisibleForTesting
+ long binderClearCallingIdentity() {
+ return Binder.clearCallingIdentity();
+ }
+
+ @VisibleForTesting
+ void binderRestoreCallingIdentity(long token) {
+ Binder.restoreCallingIdentity(token);
+ }
+
+ @VisibleForTesting
+ int binderGetCallingUid() {
+ return Binder.getCallingUid();
+ }
+
+ @VisibleForTesting
+ int binderGetCallingPid() {
+ return Binder.getCallingPid();
+ }
+
+ @VisibleForTesting
+ UserHandle binderGetCallingUserHandle() {
+ return Binder.getCallingUserHandle();
+ }
+
+ @VisibleForTesting
+ boolean binderIsCallingUidMyUid() {
+ return getCallingUid() == Process.myUid();
+ }
+
+ @VisibleForTesting
+ File environmentGetUserSystemDirectory(int userId) {
+ return Environment.getUserSystemDirectory(userId);
+ }
+
+ @VisibleForTesting
+ void powerManagerGoToSleep(long time, int reason, int flags) {
+ mContext.getSystemService(PowerManager.class).goToSleep(time, reason, flags);
+ }
+
+ @VisibleForTesting
+ boolean systemPropertiesGetBoolean(String key, boolean def) {
+ return SystemProperties.getBoolean(key, def);
+ }
+
+ @VisibleForTesting
+ long systemPropertiesGetLong(String key, long def) {
+ return SystemProperties.getLong(key, def);
+ }
+
+ @VisibleForTesting
+ String systemPropertiesGet(String key, String def) {
+ return SystemProperties.get(key, def);
+ }
+
+ @VisibleForTesting
+ String systemPropertiesGet(String key) {
+ return SystemProperties.get(key);
+ }
+
+ @VisibleForTesting
+ void systemPropertiesSet(String key, String value) {
+ SystemProperties.set(key, value);
+ }
+
/**
* Instantiates the service.
*/
public DevicePolicyManagerService(Context context) {
mContext = context;
- mOwners = new Owners(mContext);
- mUserManager = UserManager.get(mContext);
- mHasFeature = context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_DEVICE_ADMIN);
- mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
- mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
- mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM");
+ mHandler = new Handler(getMyLooper());
+ mOwners = newOwners();
+
+ mUserManager = Preconditions.checkNotNull(getUserManager());
+ mPackageManager = Preconditions.checkNotNull(getPackageManager());
+ mPowerManagerInternal = Preconditions.checkNotNull(getPowerManagerInternal());
+ mIWindowManager = Preconditions.checkNotNull(getIWindowManager());
+ mNotificationManager = Preconditions.checkNotNull(getNotificationManager());
+
mLocalService = new LocalService();
+
+ mHasFeature = mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
if (!mHasFeature) {
// Skip the rest of the initialization
return;
@@ -1076,6 +1207,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
/**
+ * We need it for testing to allow accessing context from the test-only subclass while this
+ * class's constructor is still running.
+ */
+ @VisibleForTesting
+ Context getContext() {
+ return mContext;
+ }
+
+ /**
* Creates and loads the policy data from xml.
* @param userHandle the user for whom to load the policy data
* @return
@@ -1103,17 +1243,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* @return
*/
DevicePolicyData getUserDataUnchecked(int userHandle) {
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
return getUserData(userHandle);
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
void removeUserData(int userHandle) {
synchronized (this) {
- if (userHandle == UserHandle.USER_OWNER) {
+ if (userHandle == UserHandle.USER_SYSTEM) {
Slog.w(LOG_TAG, "Tried to remove device policy file for user 0! Ignoring.");
return;
}
@@ -1124,7 +1264,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (policy != null) {
mUserData.remove(userHandle);
}
- File policyFile = new File(Environment.getUserSystemDirectory(userHandle),
+ File policyFile = new File(environmentGetUserSystemDirectory(userHandle),
DEVICE_POLICIES_XML);
policyFile.delete();
Slog.i(LOG_TAG, "Removed device policy file " + policyFile.getAbsolutePath());
@@ -1164,7 +1304,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
alarmTime = now + alarmInterval;
}
- long token = Binder.clearCallingIdentity();
+ long token = binderClearCallingIdentity();
try {
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getBroadcastAsUser(context, REQUEST_EXPIRE_PASSWORD,
@@ -1176,24 +1316,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
am.set(AlarmManager.RTC, alarmTime, pi);
}
} finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- private IWindowManager getWindowManager() {
- if (mIWindowManager == null) {
- IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE);
- mIWindowManager = IWindowManager.Stub.asInterface(b);
- }
- return mIWindowManager;
- }
-
- private NotificationManager getNotificationManager() {
- if (mNotificationManager == null) {
- mNotificationManager =
- (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ binderRestoreCallingIdentity(token);
}
- return mNotificationManager;
}
ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle) {
@@ -1208,7 +1332,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
throws SecurityException {
- final int callingUid = Binder.getCallingUid();
+ final int callingUid = binderGetCallingUid();
ActiveAdmin result = getActiveAdminWithPolicyForUidLocked(who, reqPolicy, callingUid);
if (result != null) {
@@ -1232,7 +1356,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
+ admin.info.getTagForPolicy(reqPolicy));
} else {
throw new SecurityException("No active admin owned by uid "
- + Binder.getCallingUid() + " for policy #" + reqPolicy);
+ + binderGetCallingUid() + " for policy #" + reqPolicy);
}
}
@@ -1248,7 +1372,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
if (admin.getUid() != uid) {
throw new SecurityException("Admin " + who + " is not owned by uid "
- + Binder.getCallingUid());
+ + binderGetCallingUid());
}
if (isActiveAdminWithPolicyForUserLocked(admin, reqPolicy, userId)) {
return admin;
@@ -1275,12 +1399,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
&& !hasUserSetupCompleted(userId);
if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
- if ((userId == UserHandle.USER_OWNER && (ownsDevice || ownsInitialization))
+ if ((userId == UserHandle.USER_SYSTEM && (ownsDevice || ownsInitialization))
|| (ownsDevice && ownsProfile)) {
return true;
}
} else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
- if ((userId == UserHandle.USER_OWNER && ownsDevice) || ownsProfile
+ if ((userId == UserHandle.USER_SYSTEM && ownsDevice) || ownsProfile
|| ownsInitialization) {
return true;
}
@@ -1410,14 +1534,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- private static JournaledFile makeJournaledFile(int userHandle) {
- final String base = userHandle == 0
- ? "/data/system/" + DEVICE_POLICIES_XML
- : new File(Environment.getUserSystemDirectory(userHandle), DEVICE_POLICIES_XML)
+ private JournaledFile makeJournaledFile(int userHandle) {
+ final String base = userHandle == UserHandle.USER_SYSTEM
+ ? getDevicePolicyFilePathForSystemUser() + DEVICE_POLICIES_XML
+ : new File(environmentGetUserSystemDirectory(userHandle), DEVICE_POLICIES_XML)
.getAbsolutePath();
return new JournaledFile(new File(base), new File(base + ".tmp"));
}
+ @VisibleForTesting
+ String getDevicePolicyFilePathForSystemUser() {
+ return "/data/system/";
+ }
+
private void saveSettingsLocked(int userHandle) {
DevicePolicyData policy = getUserData(userHandle);
JournaledFile journal = makeJournaledFile(userHandle);
@@ -1513,6 +1642,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
journal.commit();
sendChangedNotification(userHandle);
} catch (IOException e) {
+ Slog.w(LOG_TAG, "failed writing file", e);
try {
if (stream != null) {
stream.close();
@@ -1527,11 +1657,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private void sendChangedNotification(int userHandle) {
Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle));
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
@@ -1663,9 +1793,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// sufficiently what is currently set. Note that this is only
// a sanity check in case the two get out of sync; this should
// never normally happen.
- final long identity = Binder.clearCallingIdentity();
+ final long identity = binderClearCallingIdentity();
try {
- LockPatternUtils utils = new LockPatternUtils(mContext);
+ LockPatternUtils utils = newLockPatternUtils(mContext);
if (utils.getActivePasswordQuality(userHandle) < policy.mActivePasswordQuality) {
Slog.w(LOG_TAG, "Active password quality 0x"
+ Integer.toHexString(policy.mActivePasswordQuality)
@@ -1681,7 +1811,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
policy.mActivePasswordNonLetter = 0;
}
} finally {
- Binder.restoreCallingIdentity(identity);
+ binderRestoreCallingIdentity(identity);
}
validatePasswordOwnerLocked(policy);
@@ -1695,26 +1825,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private void updateLockTaskPackagesLocked(List<String> packages, int userId) {
- IActivityManager am = ActivityManagerNative.getDefault();
- long ident = Binder.clearCallingIdentity();
+ IActivityManager am = getIActivityManager();
+ long ident = binderClearCallingIdentity();
try {
am.updateLockTaskPackages(userId, packages.toArray(new String[packages.size()]));
} catch (RemoteException e) {
// Not gonna happen.
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
private void updateDeviceOwnerLocked() {
- IActivityManager am = ActivityManagerNative.getDefault();
- long ident = Binder.clearCallingIdentity();
+ IActivityManager am = getIActivityManager();
+ long ident = binderClearCallingIdentity();
try {
am.updateDeviceOwner(getDeviceOwner());
} catch (RemoteException e) {
// Not gonna happen.
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
@@ -1759,17 +1889,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Ensure the status of the camera is synced down to the system. Interested native services
// should monitor this value and act accordingly.
String cameraPropertyForUser = SYSTEM_PROP_DISABLE_CAMERA_PREFIX + policy.mUserHandle;
- boolean systemState = SystemProperties.getBoolean(cameraPropertyForUser, false);
+ boolean systemState = systemPropertiesGetBoolean(cameraPropertyForUser, false);
boolean cameraDisabled = getCameraDisabled(null, policy.mUserHandle);
if (cameraDisabled != systemState) {
- long token = Binder.clearCallingIdentity();
+ long token = binderClearCallingIdentity();
try {
String value = cameraDisabled ? "1" : "0";
if (DBG) Slog.v(LOG_TAG, "Change in camera state ["
+ cameraPropertyForUser + "] = " + value);
- SystemProperties.set(cameraPropertyForUser, value);
+ systemPropertiesSet(cameraPropertyForUser, value);
} finally {
- Binder.restoreCallingIdentity(token);
+ binderRestoreCallingIdentity(token);
}
}
}
@@ -1789,7 +1919,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private void onLockSettingsReady() {
- getUserData(UserHandle.USER_OWNER);
+ getUserData(UserHandle.USER_SYSTEM);
loadOwners();
cleanUpOldUsers();
// Register an observer for watching for user setup complete.
@@ -1809,7 +1939,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private void ensureDeviceOwnerUserStarted() {
if (mOwners.hasDeviceOwner()) {
- final IActivityManager am = ActivityManagerNative.getDefault();
+ final IActivityManager am = getIActivityManager();
final int userId = mOwners.getDeviceOwnerUserId();
if (VERBOSE_LOG) {
Log.v(LOG_TAG, "Starting non-system DO user: " + userId);
@@ -1917,7 +2047,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Log.e(LOG_TAG, "Could not connect to KeyChain service", e);
}
if (!hasCert) {
- getNotificationManager().cancelAsUser(
+ mNotificationManager.cancelAsUser(
null, MONITORING_CERT_NOTIFICATION_ID, userHandle);
return;
}
@@ -1962,7 +2092,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
com.android.internal.R.color.system_notification_accent_color))
.build();
- getNotificationManager().notifyAsUser(
+ mNotificationManager.notifyAsUser(
null, MONITORING_CERT_NOTIFICATION_ID, noti, userHandle);
}
}
@@ -1991,7 +2121,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
throw new IllegalArgumentException("Bad admin: " + adminReceiver);
}
synchronized (this) {
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
if (!refreshing
&& getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null) {
@@ -2018,7 +2148,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
onEnableData, null);
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
}
@@ -2112,7 +2242,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (admin == null) {
return;
}
- if (admin.getUid() != Binder.getCallingUid()) {
+ if (admin.getUid() != binderGetCallingUid()) {
// Active device owners must remain active admins.
if (isDeviceOwner(adminReceiver.getPackageName())) {
return;
@@ -2120,11 +2250,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.MANAGE_DEVICE_ADMINS, null);
}
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
removeActiveAdminLocked(adminReceiver, userHandle);
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
}
@@ -2394,7 +2524,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|| activeAdmin.crossProfileWidgetProviders.isEmpty()) {
return null;
}
- if (Binder.getCallingUid() == Process.myUid()) {
+ if (binderIsCallingUidMyUid()) {
return new ArrayList<>(activeAdmin.crossProfileWidgetProviders);
} else {
return activeAdmin.crossProfileWidgetProviders;
@@ -2959,7 +3089,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- int callingUid = Binder.getCallingUid();
+ int callingUid = binderGetCallingUid();
DevicePolicyData policy = getUserData(userHandle);
if (policy.mPasswordOwner >= 0 && policy.mPasswordOwner != callingUid) {
Slog.w(LOG_TAG, "resetPassword: already set by another uid and not entered by user");
@@ -2975,7 +3105,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Don't do this with the lock held, because it is going to call
// back in to the service.
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
LockPatternUtils utils = new LockPatternUtils(mContext);
if (!TextUtils.isEmpty(password)) {
@@ -2996,7 +3126,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
return true;
@@ -3004,10 +3134,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private void setDoNotAskCredentialsOnBoot() {
synchronized (this) {
- DevicePolicyData policyData = getUserData(UserHandle.USER_OWNER);
+ DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
if (!policyData.doNotAskCredentialsOnBoot) {
policyData.doNotAskCredentialsOnBoot = true;
- saveSettingsLocked(UserHandle.USER_OWNER);
+ saveSettingsLocked(UserHandle.USER_SYSTEM);
}
}
}
@@ -3017,7 +3147,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT, null);
synchronized (this) {
- DevicePolicyData policyData = getUserData(UserHandle.USER_OWNER);
+ DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
return policyData.doNotAskCredentialsOnBoot;
}
}
@@ -3046,7 +3176,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return;
}
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
if (timeMs <= 0) {
timeMs = Integer.MAX_VALUE;
@@ -3060,7 +3190,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
policy.mLastMaximumTimeToLock = timeMs;
mPowerManagerInternal.setMaximumScreenOffTimeoutFromDeviceAdmin((int)timeMs);
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
@@ -3112,23 +3242,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private void lockNowUnchecked() {
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
// Power off the display
- mPowerManager.goToSleep(SystemClock.uptimeMillis(),
+ powerManagerGoToSleep(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN, 0);
// Ensure the device is locked
new LockPatternUtils(mContext).requireStrongAuth(
STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW, UserHandle.USER_ALL);
- getWindowManager().lockNow(null);
+ mIWindowManager.lockNow(null);
} catch (RemoteException e) {
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
private boolean isExtStorageEncrypted() {
- String state = SystemProperties.get("vold.decrypt");
+ String state = systemPropertiesGet("vold.decrypt");
return !"".equals(state);
}
@@ -3146,7 +3276,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private boolean isCallerDelegatedCertInstaller() {
- final int callingUid = Binder.getCallingUid();
+ final int callingUid = binderGetCallingUid();
final int userHandle = UserHandle.getUserId(callingUid);
synchronized (this) {
final DevicePolicyData policy = getUserData(userHandle);
@@ -3181,7 +3311,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
- final long id = Binder.clearCallingIdentity();
+ final long id = binderClearCallingIdentity();
try {
final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle);
try {
@@ -3196,7 +3326,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Log.w(LOG_TAG, "installCaCertsToKeyChain(): ", e1);
Thread.currentThread().interrupt();
} finally {
- Binder.restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
return false;
}
@@ -3212,7 +3342,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
enforceCanManageCaCerts(admin);
final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
- final long id = Binder.clearCallingIdentity();
+ final long id = binderClearCallingIdentity();
try {
final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle);
try {
@@ -3228,7 +3358,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Log.w(LOG_TAG, "CaCertUninstaller: ", ie);
Thread.currentThread().interrupt();
} finally {
- Binder.restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
@@ -3244,7 +3374,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
- final long id = Binder.clearCallingIdentity();
+ final long id = binderClearCallingIdentity();
try {
final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle);
try {
@@ -3259,7 +3389,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Log.w(LOG_TAG, "Interrupted while installing certificate", e);
Thread.currentThread().interrupt();
} finally {
- Binder.restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
return false;
}
@@ -3268,11 +3398,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
public void choosePrivateKeyAlias(final int uid, final Uri uri, final String alias,
final IBinder response) {
// Caller UID needs to be trusted, so we restrict this method to SYSTEM_UID callers.
- if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) {
+ if (UserHandle.getAppId(binderGetCallingUid()) != Process.SYSTEM_UID) {
return;
}
- final UserHandle caller = Binder.getCallingUserHandle();
+ final UserHandle caller = binderGetCallingUserHandle();
// If there is a profile owner, redirect to that; otherwise query the device owner.
ComponentName aliasChooser = getProfileOwner(caller.getIdentifier());
if (aliasChooser == null && caller.isOwner()) {
@@ -3293,7 +3423,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
intent.putExtra(DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_ALIAS, alias);
intent.putExtra(DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_RESPONSE, response);
- final long id = Binder.clearCallingIdentity();
+ final long id = binderClearCallingIdentity();
try {
mContext.sendOrderedBroadcastAsUser(intent, caller, null, new BroadcastReceiver() {
@Override
@@ -3303,7 +3433,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}, null, Activity.RESULT_OK, null, null);
} finally {
- Binder.restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
@@ -3372,20 +3502,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final ActiveAdmin admin = getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_WIPE_DATA);
- final String source;
- final ComponentName cname = admin.info.getComponent();
- if (cname != null) {
- source = cname.flattenToShortString();
- } else {
- source = admin.info.getPackageName();
- }
+ final String source = admin.info.getComponent().flattenToShortString();
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) {
boolean ownsInitialization = isDeviceInitializer(admin.info.getPackageName())
&& !hasUserSetupCompleted(userHandle);
- if (userHandle != UserHandle.USER_OWNER
+ if (userHandle != UserHandle.USER_SYSTEM
|| !(isDeviceOwner(admin.info.getPackageName())
|| ownsInitialization)) {
throw new SecurityException(
@@ -3401,22 +3525,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
wipeDeviceOrUserLocked(wipeExtRequested, userHandle,
"DevicePolicyManager.wipeData() from " + source);
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
}
private void wipeDeviceOrUserLocked(boolean wipeExtRequested, final int userHandle, String reason) {
- if (userHandle == UserHandle.USER_OWNER) {
+ if (userHandle == UserHandle.USER_SYSTEM) {
wipeDataLocked(wipeExtRequested, reason);
} else {
mHandler.post(new Runnable() {
@Override
public void run() {
try {
- IActivityManager am = ActivityManagerNative.getDefault();
+ IActivityManager am = getIActivityManager();
if (am.getCurrentUser().id == userHandle) {
- am.switchUser(UserHandle.USER_OWNER);
+ am.switchUser(UserHandle.USER_SYSTEM);
}
boolean isManagedProfile = isManagedProfile(userHandle);
@@ -3442,11 +3566,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
.setColor(mContext.getColor(R.color.system_notification_accent_color))
.setStyle(new Notification.BigTextStyle().bigText(contentText))
.build();
- getNotificationManager().notify(PROFILE_WIPED_NOTIFICATION_ID, notification);
+ mNotificationManager.notify(PROFILE_WIPED_NOTIFICATION_ID, notification);
}
private void clearWipeProfileNotification() {
- getNotificationManager().cancel(PROFILE_WIPED_NOTIFICATION_ID);
+ mNotificationManager.cancel(PROFILE_WIPED_NOTIFICATION_ID);
}
@Override
@@ -3506,7 +3630,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|| p.mActivePasswordNumeric != numbers
|| p.mActivePasswordSymbols != symbols
|| p.mActivePasswordNonLetter != nonletter) {
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
p.mActivePasswordQuality = quality;
p.mActivePasswordLength = length;
@@ -3524,7 +3648,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userHandle);
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
}
@@ -3560,7 +3684,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
boolean wipeData = false;
int identifier = 0;
@@ -3591,7 +3715,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
"reportFailedPasswordAttempt()");
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
@@ -3604,7 +3728,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
DevicePolicyData policy = getUserData(userHandle);
if (policy.mFailedPasswordAttempts != 0 || policy.mPasswordOwner >= 0) {
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
policy.mFailedPasswordAttempts = 0;
policy.mPasswordOwner = -1;
@@ -3615,7 +3739,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
}
@@ -3630,8 +3754,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized(this) {
Preconditions.checkNotNull(who, "ComponentName is null");
- // Only check if owner has set global proxy. We don't allow other users to set it.
- DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
+ // Only check if system user has set global proxy. We don't allow other users to set it.
+ DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
@@ -3647,8 +3771,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- // If the user is not the owner, don't set the global proxy. Fail silently.
- if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
+ // If the user is not system, don't set the global proxy. Fail silently.
+ if (UserHandle.getCallingUserId() != UserHandle.USER_SYSTEM) {
Slog.w(LOG_TAG, "Only the owner is allowed to set the global proxy. User "
+ UserHandle.getCallingUserId() + " is not permitted.");
return null;
@@ -3666,11 +3790,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Reset the global proxy accordingly
// Do this using system permissions, as apps cannot write to secure settings
- long origId = Binder.clearCallingIdentity();
+ long origId = binderClearCallingIdentity();
try {
resetGlobalProxyLocked(policy);
} finally {
- Binder.restoreCallingIdentity(origId);
+ binderRestoreCallingIdentity(origId);
}
return null;
}
@@ -3683,7 +3807,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
enforceCrossUserPermission(userHandle);
synchronized(this) {
- DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
+ DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
// Scan through active admins and find if anyone has already
// set the global proxy.
final int N = policy.mAdminList.size();
@@ -3705,13 +3829,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
- long token = Binder.clearCallingIdentity();
+ long token = binderClearCallingIdentity();
try {
ConnectivityManager connectivityManager = (ConnectivityManager)
mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
connectivityManager.setGlobalProxy(proxyInfo);
} finally {
- Binder.restoreCallingIdentity(token);
+ binderRestoreCallingIdentity(token);
}
}
@@ -3771,10 +3895,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
// Check for permissions
- // Only owner can set storage encryption
- if (userHandle != UserHandle.USER_OWNER
- || UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
- Slog.w(LOG_TAG, "Only owner is allowed to set storage encryption. User "
+ // Only system user can set storage encryption
+ if (userHandle != UserHandle.USER_SYSTEM) {
+ Slog.w(LOG_TAG, "Only owner/system user is allowed to set storage encryption. User "
+ UserHandle.getCallingUserId() + " is not permitted.");
return 0;
}
@@ -3793,7 +3916,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
saveSettingsLocked(userHandle);
}
- DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
+ DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
// (2) Compute "max" for all admins
boolean newRequested = false;
final int N = policy.mAdminList.size();
@@ -3873,15 +3996,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE}.
*/
private int getEncryptionStatus() {
- String status = SystemProperties.get("ro.crypto.state", "unsupported");
+ String status = systemPropertiesGet("ro.crypto.state", "unsupported");
if ("encrypted".equalsIgnoreCase(status)) {
- final long token = Binder.clearCallingIdentity();
+ final long token = binderClearCallingIdentity();
try {
return LockPatternUtils.isDeviceEncrypted()
? DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE
: DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY;
} finally {
- Binder.restoreCallingIdentity(token);
+ binderRestoreCallingIdentity(token);
}
} else if ("unencrypted".equalsIgnoreCase(status)) {
return DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
@@ -3946,13 +4069,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private void updateScreenCaptureDisabledInWindowManager(int userHandle, boolean disabled) {
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
- getWindowManager().setScreenCaptureDisabled(userHandle, disabled);
+ mIWindowManager.setScreenCaptureDisabled(userHandle, disabled);
} catch (RemoteException e) {
Log.w(LOG_TAG, "Unable to notify WindowManager.", e);
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
@@ -3977,12 +4100,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Turn AUTO_TIME on in settings if it is required
if (required) {
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.AUTO_TIME, 1 /* AUTO_TIME on */);
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
}
@@ -4091,7 +4214,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return 0;
}
enforceCrossUserPermission(userHandle);
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
synchronized (this) {
if (who != null) {
@@ -4134,7 +4257,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return which;
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
@@ -4152,15 +4275,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
enforceCanSetDeviceOwner(userId);
// Shutting down backup manager service permanently.
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
IBackupManager ibm = IBackupManager.Stub.asInterface(
ServiceManager.getService(Context.BACKUP_SERVICE));
- ibm.setBackupServiceActive(UserHandle.USER_OWNER, false);
+ ibm.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
} catch (RemoteException e) {
throw new IllegalStateException("Failed deactivating backup service.", e);
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
mOwners.setDeviceOwner(packageName, ownerName, userId);
@@ -4168,12 +4291,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
updateDeviceOwnerLocked();
Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED);
- ident = Binder.clearCallingIdentity();
+ ident = binderClearCallingIdentity();
try {
// TODO Send to system too?
mContext.sendBroadcastAsUser(intent, new UserHandle(userId));
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
return true;
}
@@ -4211,7 +4334,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return null;
}
String deviceOwnerPackage = mOwners.getDeviceOwnerPackageName();
- return getApplicationLabel(deviceOwnerPackage, UserHandle.USER_OWNER);
+ return getApplicationLabel(deviceOwnerPackage, UserHandle.USER_SYSTEM);
}
}
@@ -4222,7 +4345,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return null;
}
- DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
+ DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
final int n = policy.mAdminList.size();
for (int i = 0; i < n; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -4238,7 +4361,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Preconditions.checkNotNull(packageName, "packageName is null");
try {
int uid = mContext.getPackageManager().getPackageUid(packageName, 0);
- if (uid != Binder.getCallingUid()) {
+ if (uid != binderGetCallingUid()) {
throw new SecurityException("Invalid packageName");
}
} catch (NameNotFoundException e) {
@@ -4248,21 +4371,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
throw new SecurityException("clearDeviceOwner can only be called by the device owner");
}
synchronized (this) {
- clearUserPoliciesLocked(new UserHandle(UserHandle.USER_OWNER));
+ clearUserPoliciesLocked(new UserHandle(UserHandle.USER_SYSTEM));
mOwners.clearDeviceOwner();
mOwners.writeDeviceOwner();
updateDeviceOwnerLocked();
// Reactivate backup service.
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
IBackupManager ibm = IBackupManager.Stub.asInterface(
ServiceManager.getService(Context.BACKUP_SERVICE));
- ibm.setBackupServiceActive(UserHandle.USER_OWNER, true);
+ ibm.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
} catch (RemoteException e) {
throw new IllegalStateException("Failed reactivating backup service.", e);
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
}
@@ -4281,8 +4404,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
boolean isInitializerSystemApp;
try {
- isInitializerSystemApp = isSystemApp(AppGlobals.getPackageManager(),
- initializer.getPackageName(), Binder.getCallingUserHandle().getIdentifier());
+ isInitializerSystemApp = isSystemApp(getIPackageManager(),
+ initializer.getPackageName(), binderGetCallingUserHandle().getIdentifier());
} catch (RemoteException | IllegalArgumentException e) {
isInitializerSystemApp = false;
Slog.e(LOG_TAG, "Fail to check if device initialzer is system app.", e);
@@ -4365,9 +4488,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, UserHandle.getCallingUserId());
- if (admin.getUid() != Binder.getCallingUid()) {
+ if (admin.getUid() != binderGetCallingUid()) {
throw new SecurityException("Admin " + who + " is not owned by uid "
- + Binder.getCallingUid());
+ + binderGetCallingUid());
}
if (!isDeviceInitializer(admin.info.getPackageName())
@@ -4376,12 +4499,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
"clearDeviceInitializer can only be called by the device initializer/owner");
}
synchronized (this) {
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
mOwners.clearDeviceInitializer();
mOwners.writeDeviceOwner();
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
}
@@ -4409,7 +4532,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (!mHasFeature) {
return;
}
- UserHandle callingUser = Binder.getCallingUserHandle();
+ UserHandle callingUser = binderGetCallingUserHandle();
// Check if this is the profile owner who is calling
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
synchronized (this) {
@@ -4429,15 +4552,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
policy.mStatusBarDisabled = false;
saveSettingsLocked(userId);
- final long ident = Binder.clearCallingIdentity();
+ final long ident = binderClearCallingIdentity();
try {
clearUserRestrictions(userHandle);
- AppGlobals.getPackageManager().updatePermissionFlagsForAllApps(
+ getIPackageManager().updatePermissionFlagsForAllApps(
PackageManager.FLAG_PERMISSION_POLICY_FIXED,
0 /* flagValues */, userHandle.getIdentifier());
} catch (RemoteException re) {
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
@@ -4497,10 +4620,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
"This method can only be called by device initializers");
}
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
if (!isDeviceOwner(activeAdmin.info.getPackageName())) {
- IPackageManager ipm = AppGlobals.getPackageManager();
+ IPackageManager ipm = getIPackageManager();
ipm.setComponentEnabledSetting(who,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP, userId);
@@ -4508,7 +4631,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
removeActiveAdmin(who, userId);
}
- if (userId == UserHandle.USER_OWNER) {
+ if (userId == UserHandle.USER_SYSTEM) {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1);
}
@@ -4518,7 +4641,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Log.i(LOG_TAG, "Can't talk to package manager", e);
return false;
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
return true;
}
@@ -4536,7 +4659,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
int userId = UserHandle.getCallingUserId();
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
mUserManager.setUserEnabled(userId);
UserInfo parent = mUserManager.getProfileParent(userId);
@@ -4546,7 +4669,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcastAsUser(intent, new UserHandle(parent.id));
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -4558,11 +4681,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Check if this is the profile owner (includes device owner).
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
mUserManager.setUserName(userId, profileName);
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
@@ -4612,7 +4735,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* Canonical name for a given package.
*/
private String getApplicationLabel(String packageName, int userHandle) {
- long token = Binder.clearCallingIdentity();
+ long token = binderClearCallingIdentity();
try {
final Context userContext;
try {
@@ -4630,7 +4753,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
return result != null ? result.toString() : null;
} finally {
- Binder.restoreCallingIdentity(token);
+ binderRestoreCallingIdentity(token);
}
}
@@ -4656,7 +4779,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
throw new IllegalStateException("Trying to set the profile owner, but profile owner "
+ "is already set.");
}
- int callingUid = Binder.getCallingUid();
+ int callingUid = binderGetCallingUid();
if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID) {
if (hasUserSetupCompleted(userHandle) &&
AccountManager.get(mContext).getAccountsAsUser(userHandle).length > 0) {
@@ -4689,9 +4812,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
throw new IllegalStateException("User not running: " + userId);
}
- int callingUid = Binder.getCallingUid();
+ int callingUid = binderGetCallingUid();
if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID) {
- if (!hasUserSetupCompleted(UserHandle.USER_OWNER)) {
+ if (!hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
return;
}
// STOPSHIP Do proper check in split user mode
@@ -4715,7 +4838,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
// STOPSHIP Do proper check in split user mode
if (!UserManager.isSplitSystemUser()) {
- if (hasUserSetupCompleted(UserHandle.USER_OWNER)) {
+ if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
throw new IllegalStateException("Cannot set the device owner if the device is "
+ "already set-up");
}
@@ -4726,7 +4849,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (userHandle < 0) {
throw new IllegalArgumentException("Invalid userId " + userHandle);
}
- final int callingUid = Binder.getCallingUid();
+ final int callingUid = binderGetCallingUid();
if (userHandle == UserHandle.getUserId(callingUid)) return;
if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
mContext.enforceCallingOrSelfPermission(
@@ -4742,26 +4865,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private UserInfo getProfileParent(int userHandle) {
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
return mUserManager.getProfileParent(userHandle);
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
private boolean isManagedProfile(int userHandle) {
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
return mUserManager.getUserInfo(userHandle).isManagedProfile();
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
private void enableIfNecessary(String packageName, int userId) {
try {
- IPackageManager ipm = AppGlobals.getPackageManager();
+ IPackageManager ipm = getIPackageManager();
ApplicationInfo ai = ipm.getApplicationInfo(packageName,
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
userId);
@@ -4781,8 +4904,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission Denial: can't dump DevicePolicyManagerService from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
+ + binderGetCallingPid()
+ + ", uid=" + binderGetCallingUid());
return;
}
@@ -4823,14 +4946,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- IPackageManager pm = AppGlobals.getPackageManager();
- long id = Binder.clearCallingIdentity();
+ IPackageManager pm = getIPackageManager();
+ long id = binderClearCallingIdentity();
try {
pm.addPersistentPreferredActivity(filter, activity, userHandle);
} catch (RemoteException re) {
// Shouldn't happen
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -4842,14 +4965,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- IPackageManager pm = AppGlobals.getPackageManager();
- long id = Binder.clearCallingIdentity();
+ IPackageManager pm = getIPackageManager();
+ long id = binderClearCallingIdentity();
try {
pm.clearPackagePersistentPreferredActivities(packageName, userHandle);
} catch (RemoteException re) {
// Shouldn't happen
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -4861,11 +4984,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
mUserManager.setApplicationRestrictions(packageName, settings, userHandle);
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -4963,7 +5086,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public ComponentName getRestrictionsProvider(int userHandle) {
synchronized (this) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ if (binderGetCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Only the system can query the permission provider");
}
DevicePolicyData userData = getUserData(userHandle);
@@ -4978,8 +5101,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- IPackageManager pm = AppGlobals.getPackageManager();
- long id = Binder.clearCallingIdentity();
+ IPackageManager pm = getIPackageManager();
+ long id = binderClearCallingIdentity();
try {
UserInfo parent = mUserManager.getProfileParent(callingUserId);
if (parent == null) {
@@ -4998,7 +5121,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} catch (RemoteException re) {
// Shouldn't happen
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -5009,8 +5132,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int callingUserId = UserHandle.getCallingUserId();
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- IPackageManager pm = AppGlobals.getPackageManager();
- long id = Binder.clearCallingIdentity();
+ IPackageManager pm = getIPackageManager();
+ long id = binderClearCallingIdentity();
try {
UserInfo parent = mUserManager.getProfileParent(callingUserId);
if (parent == null) {
@@ -5027,7 +5150,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} catch (RemoteException re) {
// Shouldn't happen
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -5039,7 +5162,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private boolean checkPackagesInPermittedListOrSystem(List<String> enabledPackages,
List<String> permittedList) {
int userIdToCheck = UserHandle.getCallingUserId();
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
// If we have an enabled packages list for a managed profile the packages
// we should check are installed for the parent user.
@@ -5048,7 +5171,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
userIdToCheck = user.profileGroupId;
}
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
for (String enabledPackage : enabledPackages) {
boolean systemService = false;
try {
@@ -5063,7 +5186,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
return true;
}
@@ -5088,7 +5211,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (packageList != null) {
int userId = UserHandle.getCallingUserId();
List<AccessibilityServiceInfo> enabledServices = null;
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
UserInfo user = mUserManager.getUserInfo(userId);
if (user.isManagedProfile()) {
@@ -5098,7 +5221,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
enabledServices = accessibilityManager.getEnabledAccessibilityServiceList(
AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
if (enabledServices != null) {
@@ -5169,7 +5292,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// If we have a permitted list add all system accessibility services.
if (result != null) {
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
UserInfo user = mUserManager.getUserInfo(userId);
if (user.isManagedProfile()) {
@@ -5180,7 +5303,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
List<AccessibilityServiceInfo> installedServices =
accessibilityManager.getInstalledAccessibilityServiceList();
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
if (installedServices != null) {
for (AccessibilityServiceInfo service : installedServices) {
ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo;
@@ -5191,7 +5314,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
@@ -5201,12 +5324,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private boolean checkCallerIsCurrentUserOrProfile() {
int callingUserId = UserHandle.getCallingUserId();
- long token = Binder.clearCallingIdentity();
+ long token = binderClearCallingIdentity();
try {
UserInfo currentUser;
UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
try {
- currentUser = ActivityManagerNative.getDefault().getCurrentUser();
+ currentUser = getIActivityManager().getCurrentUser();
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Failed to talk to activity managed.", e);
return false;
@@ -5223,7 +5346,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return false;
}
} finally {
- Binder.restoreCallingIdentity(token);
+ binderRestoreCallingIdentity(token);
}
return true;
}
@@ -5289,7 +5412,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
public List getPermittedInputMethodsForCurrentUser() {
UserInfo currentUser;
try {
- currentUser = ActivityManagerNative.getDefault().getCurrentUser();
+ currentUser = getIActivityManager().getCurrentUser();
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Failed to make remote calls to get current user", e);
// Activity managed is dead, just allow all IMEs
@@ -5327,9 +5450,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
InputMethodManager inputMethodManager = (InputMethodManager) mContext
.getSystemService(Context.INPUT_METHOD_SERVICE);
List<InputMethodInfo> imes = inputMethodManager.getInputMethodList();
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
if (imes != null) {
for (InputMethodInfo ime : imes) {
ServiceInfo serviceInfo = ime.getServiceInfo();
@@ -5340,7 +5463,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
return result;
@@ -5353,7 +5476,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
UserInfo userInfo = mUserManager.createUser(name, 0 /* flags */);
if (userInfo != null) {
@@ -5361,7 +5484,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
return null;
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -5373,11 +5496,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (user == null) {
return null;
}
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
String profileOwnerPkg = profileOwnerComponent.getPackageName();
- final IPackageManager ipm = AppGlobals.getPackageManager();
- IActivityManager activityManager = ActivityManagerNative.getDefault();
+ final IPackageManager ipm = getIPackageManager();
+ IActivityManager activityManager = getIActivityManager();
final int userHandle = user.getIdentifier();
try {
@@ -5396,7 +5519,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
setProfileOwner(profileOwnerComponent, ownerName, userHandle);
return user;
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
@@ -5406,11 +5529,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
return mUserManager.removeUser(userHandle.getIdentifier());
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -5421,18 +5544,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
- int userId = UserHandle.USER_OWNER;
+ int userId = UserHandle.USER_SYSTEM;
if (userHandle != null) {
userId = userHandle.getIdentifier();
}
- return ActivityManagerNative.getDefault().switchUser(userId);
+ return getIActivityManager().switchUser(userId);
} catch (RemoteException e) {
Log.e(LOG_TAG, "Couldn't switch user", e);
return false;
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -5445,14 +5568,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
Bundle bundle = mUserManager.getApplicationRestrictions(packageName, userHandle);
// if no restrictions were saved, mUserManager.getApplicationRestrictions
// returns null, but DPM method should return an empty Bundle as per JavaDoc
return bundle != null ? bundle : Bundle.EMPTY;
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -5460,13 +5583,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public void setUserRestriction(ComponentName who, String key, boolean enabled) {
Preconditions.checkNotNull(who, "ComponentName is null");
- final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
- final int userHandle = user.getIdentifier();
+ final int userHandle = UserHandle.getCallingUserId();
+ final UserHandle user = new UserHandle(userHandle);
synchronized (this) {
ActiveAdmin activeAdmin =
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
boolean isDeviceOwner = isDeviceOwner(activeAdmin.info.getPackageName());
- if (!isDeviceOwner && userHandle != UserHandle.USER_OWNER
+ if (!isDeviceOwner && userHandle != UserHandle.USER_SYSTEM
&& DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) {
throw new SecurityException("Profile owners cannot set user restriction " + key);
}
@@ -5482,7 +5605,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ServiceManager.getService(Context.AUDIO_SERVICE));
}
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
if (enabled && !alreadyRestricted) {
if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
@@ -5491,8 +5614,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
iAudioService.setMasterMute(true, 0, mContext.getPackageName(),
userHandle);
- }
- if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) {
+ } else if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0,
userHandle);
@@ -5504,8 +5626,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "",
userHandle);
} else if (UserManager.DISALLOW_DEBUGGING_FEATURES.equals(key)) {
- // Only disable adb if changing for primary user, since it is global
- if (userHandle == UserHandle.USER_OWNER) {
+ // Only disable adb if changing for system user, since it is global
+ // TODO: should this be admin user?
+ if (userHandle == UserHandle.USER_SYSTEM) {
Settings.Global.putStringForUser(mContext.getContentResolver(),
Settings.Global.ADB_ENABLED, "0", userHandle);
}
@@ -5528,8 +5651,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Send out notifications however as some clients may want to reread the
// value which actually changed due to a restriction having been applied.
final String property = Settings.Secure.SYS_PROP_SETTING_VERSION;
- long version = SystemProperties.getLong(property, 0) + 1;
- SystemProperties.set(property, Long.toString(version));
+ long version = systemPropertiesGetLong(property, 0) + 1;
+ systemPropertiesSet(property, Long.toString(version));
final String name = Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
Uri url = Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
@@ -5548,7 +5671,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Failed to talk to AudioService.", re);
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
sendChangedNotification(userHandle);
}
@@ -5562,15 +5685,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
return pm.setApplicationHiddenSettingAsUser(packageName, hidden, callingUserId);
} catch (RemoteException re) {
// shouldn't happen
Slog.e(LOG_TAG, "Failed to setApplicationHiddenSetting", re);
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
return false;
}
@@ -5583,15 +5706,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
return pm.getApplicationHiddenSettingAsUser(packageName, callingUserId);
} catch (RemoteException re) {
// shouldn't happen
Slog.e(LOG_TAG, "Failed to getApplicationHiddenSettingAsUser", re);
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
return false;
}
@@ -5606,7 +5729,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
int userId = UserHandle.getCallingUserId();
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
if (DBG) {
@@ -5622,7 +5745,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
primaryUser = um.getUserInfo(userId);
}
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
if (!isSystemApp(pm, packageName, primaryUser.id)) {
throw new IllegalArgumentException("Only system apps can be enabled this way.");
}
@@ -5634,7 +5757,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// shouldn't happen
Slog.wtf(LOG_TAG, "Failed to install " + packageName, re);
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -5648,7 +5771,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
int userId = UserHandle.getCallingUserId();
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
UserManager um = UserManager.get(mContext);
@@ -5659,7 +5782,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
primaryUser = um.getUserInfo(userId);
}
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
List<ResolveInfo> activitiesToEnable = pm.queryIntentActivities(intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
0, // no flags
@@ -5687,7 +5810,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Slog.wtf(LOG_TAG, "Failed to resolve intent for: " + intent);
return 0;
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -5753,15 +5876,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
pm.setBlockUninstallForUser(packageName, uninstallBlocked, userId);
} catch (RemoteException re) {
// Shouldn't happen.
Slog.e(LOG_TAG, "Failed to setBlockUninstallForUser", re);
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -5778,15 +5901,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
}
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
return pm.getBlockUninstallForUser(packageName, userId);
} catch (RemoteException re) {
// Shouldn't happen.
Slog.e(LOG_TAG, "Failed to getBlockUninstallForUser", re);
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
return false;
@@ -5838,7 +5961,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
actualLookupKey, actualContactId, originalIntent);
final int callingUserId = UserHandle.getCallingUserId();
- final long ident = Binder.clearCallingIdentity();
+ final long ident = binderClearCallingIdentity();
try {
synchronized (this) {
final int managedUserId = getManagedUserId(callingUserId);
@@ -5856,7 +5979,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mContext, intent, new UserHandle(managedUserId));
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
@@ -5937,7 +6060,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
- int userHandle = Binder.getCallingUserHandle().getIdentifier();
+ int userHandle = binderGetCallingUserHandle().getIdentifier();
setLockTaskPackagesLocked(userHandle, new ArrayList<>(Arrays.asList(packages)));
}
}
@@ -5959,7 +6082,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
- int userHandle = Binder.getCallingUserHandle().getIdentifier();
+ int userHandle = binderGetCallingUserHandle().getIdentifier();
final List<String> packages = getLockTaskPackagesLocked(userHandle);
return packages.toArray(new String[packages.size()]);
}
@@ -5978,7 +6101,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public boolean isLockTaskPermitted(String pkg) {
// Get current user's devicepolicy
- int uid = Binder.getCallingUid();
+ int uid = binderGetCallingUid();
int userHandle = UserHandle.getUserId(uid);
DevicePolicyData policy = getUserData(userHandle);
synchronized (this) {
@@ -5997,7 +6120,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userHandle) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ if (binderGetCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("notifyLockTaskModeChanged can only be called by system");
}
synchronized (this) {
@@ -6048,11 +6171,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
Settings.Global.putString(contentResolver, setting, value);
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -6077,11 +6200,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
"Permission denial: Profile owners cannot update %1$s", setting));
}
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
Settings.Secure.putStringForUser(contentResolver, setting, value, callingUserId);
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -6092,7 +6215,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
int userId = UserHandle.getCallingUserId();
- long identity = Binder.clearCallingIdentity();
+ long identity = binderClearCallingIdentity();
try {
IAudioService iAudioService = IAudioService.Stub.asInterface(
ServiceManager.getService(Context.AUDIO_SERVICE));
@@ -6100,7 +6223,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Failed to setMasterMute", re);
} finally {
- Binder.restoreCallingIdentity(identity);
+ binderRestoreCallingIdentity(identity);
}
}
}
@@ -6124,11 +6247,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
int userId = UserHandle.getCallingUserId();
- long id = Binder.clearCallingIdentity();
+ long id = binderClearCallingIdentity();
try {
mUserManager.setUserIcon(userId, icon);
} finally {
- restoreCallingIdentity(id);
+ binderRestoreCallingIdentity(id);
}
}
}
@@ -6142,7 +6265,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final int userId = UserHandle.getCallingUserId();
LockPatternUtils utils = new LockPatternUtils(mContext);
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
// disallow disabling the keyguard if a password is currently set
if (disabled && utils.isSecure(userId)) {
@@ -6150,7 +6273,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
utils.setLockScreenDisabled(disabled, userId);
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
return true;
}
@@ -6173,7 +6296,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private boolean setStatusBarDisabledInternal(boolean disabled, int userId) {
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
IStatusBarService statusBarService = IStatusBarService.Stub.asInterface(
ServiceManager.checkService(Context.STATUS_BAR_SERVICE));
@@ -6187,7 +6310,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Failed to disable the status bar", e);
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
return false;
}
@@ -6394,8 +6517,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mContext.enforceCallingOrSelfPermission(permission.NOTIFY_PENDING_SYSTEM_UPDATE,
"Only the system update service can broadcast update information");
- if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
- Slog.w(LOG_TAG, "Only the system update service in the primary user " +
+ if (UserHandle.getCallingUserId() != UserHandle.USER_SYSTEM) {
+ Slog.w(LOG_TAG, "Only the system update service in the system user " +
"can broadcast update information.");
return;
}
@@ -6418,7 +6541,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Log.e(LOG_TAG, "Cannot find device owner package", e);
}
if (receivers != null) {
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
for (int i = 0; i < receivers.length; i++) {
if (permission.BIND_DEVICE_ADMIN.equals(receivers[i].permission)) {
@@ -6428,7 +6551,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
}
@@ -6459,12 +6582,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public boolean setPermissionGrantState(ComponentName admin, String packageName,
String permission, int grantState) throws RemoteException {
- UserHandle user = Binder.getCallingUserHandle();
+ UserHandle user = binderGetCallingUserHandle();
synchronized (this) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
- final ApplicationInfo ai = AppGlobals.getPackageManager()
+ final ApplicationInfo ai = getIPackageManager()
.getApplicationInfo(packageName, 0, user.getIdentifier());
final int targetSdkVersion = ai == null ? 0 : ai.targetSdkVersion;
if (targetSdkVersion < android.os.Build.VERSION_CODES.M) {
@@ -6496,7 +6619,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} catch (SecurityException se) {
return false;
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
}
@@ -6506,12 +6629,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
String permission) throws RemoteException {
PackageManager packageManager = mContext.getPackageManager();
- UserHandle user = Binder.getCallingUserHandle();
+ UserHandle user = binderGetCallingUserHandle();
synchronized (this) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- long ident = Binder.clearCallingIdentity();
+ long ident = binderClearCallingIdentity();
try {
- int granted = AppGlobals.getPackageManager().checkPermission(permission,
+ int granted = getIPackageManager().checkPermission(permission,
packageName, user.getIdentifier());
int permFlags = packageManager.getPermissionFlags(permission, packageName, user);
if ((permFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED)
@@ -6525,7 +6648,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
: DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ binderRestoreCallingIdentity(ident);
}
}
}
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index f6de12dbf6cb..c6d5a7e268b7 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -588,6 +588,8 @@ public class MidiService extends IMidiManager.Stub {
Client client = getClient(token);
if (client == null) return;
client.addListener(listener);
+ // Let listener know whether any ports are already busy.
+ updateStickyDeviceStatus(client.mUid, listener);
}
@Override
@@ -597,6 +599,25 @@ public class MidiService extends IMidiManager.Stub {
client.removeListener(listener);
}
+ // Inform listener of the status of all known devices.
+ private void updateStickyDeviceStatus(int uid, IMidiDeviceListener listener) {
+ synchronized (mDevicesByInfo) {
+ for (Device device : mDevicesByInfo.values()) {
+ // ignore private devices that our client cannot access
+ if (device.isUidAllowed(uid)) {
+ try {
+ MidiDeviceStatus status = device.getDeviceStatus();
+ if (status != null) {
+ listener.onDeviceStatusChanged(status);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "remote exception", e);
+ }
+ }
+ }
+ }
+ }
+
private static final MidiDeviceInfo[] EMPTY_DEVICE_INFO_ARRAY = new MidiDeviceInfo[0];
public MidiDeviceInfo[] getDevices() {
diff --git a/core/java/android/net/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index 2283004c7759..3acd56560f4a 100644
--- a/core/java/android/net/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.net;
+package android.net.ip;
import com.android.internal.annotations.GuardedBy;
diff --git a/core/java/android/net/netlink/NetlinkConstants.java b/services/net/java/android/net/netlink/NetlinkConstants.java
index e331701efbce..e331701efbce 100644
--- a/core/java/android/net/netlink/NetlinkConstants.java
+++ b/services/net/java/android/net/netlink/NetlinkConstants.java
diff --git a/core/java/android/net/netlink/NetlinkErrorMessage.java b/services/net/java/android/net/netlink/NetlinkErrorMessage.java
index e2755740453a..e2755740453a 100644
--- a/core/java/android/net/netlink/NetlinkErrorMessage.java
+++ b/services/net/java/android/net/netlink/NetlinkErrorMessage.java
diff --git a/core/java/android/net/netlink/NetlinkMessage.java b/services/net/java/android/net/netlink/NetlinkMessage.java
index 3bf75cabea17..3bf75cabea17 100644
--- a/core/java/android/net/netlink/NetlinkMessage.java
+++ b/services/net/java/android/net/netlink/NetlinkMessage.java
diff --git a/core/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java
index 657d48c15250..657d48c15250 100644
--- a/core/java/android/net/netlink/NetlinkSocket.java
+++ b/services/net/java/android/net/netlink/NetlinkSocket.java
diff --git a/core/java/android/net/netlink/RtNetlinkNeighborMessage.java b/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java
index 02df1313c43f..02df1313c43f 100644
--- a/core/java/android/net/netlink/RtNetlinkNeighborMessage.java
+++ b/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java
diff --git a/core/java/android/net/netlink/StructNdMsg.java b/services/net/java/android/net/netlink/StructNdMsg.java
index b68ec0bc6226..b68ec0bc6226 100644
--- a/core/java/android/net/netlink/StructNdMsg.java
+++ b/services/net/java/android/net/netlink/StructNdMsg.java
diff --git a/core/java/android/net/netlink/StructNdaCacheInfo.java b/services/net/java/android/net/netlink/StructNdaCacheInfo.java
index 16cf56385eb8..16cf56385eb8 100644
--- a/core/java/android/net/netlink/StructNdaCacheInfo.java
+++ b/services/net/java/android/net/netlink/StructNdaCacheInfo.java
diff --git a/core/java/android/net/netlink/StructNlAttr.java b/services/net/java/android/net/netlink/StructNlAttr.java
index 597a6aa1c9eb..597a6aa1c9eb 100644
--- a/core/java/android/net/netlink/StructNlAttr.java
+++ b/services/net/java/android/net/netlink/StructNlAttr.java
diff --git a/core/java/android/net/netlink/StructNlMsgErr.java b/services/net/java/android/net/netlink/StructNlMsgErr.java
index f095af43c743..f095af43c743 100644
--- a/core/java/android/net/netlink/StructNlMsgErr.java
+++ b/services/net/java/android/net/netlink/StructNlMsgErr.java
diff --git a/core/java/android/net/netlink/StructNlMsgHdr.java b/services/net/java/android/net/netlink/StructNlMsgHdr.java
index 98ab5e719d69..98ab5e719d69 100644
--- a/core/java/android/net/netlink/StructNlMsgHdr.java
+++ b/services/net/java/android/net/netlink/StructNlMsgHdr.java
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 7d1282bceac9..c147bccc19b5 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -67,6 +67,33 @@
</intent-filter>
</receiver>
+ <receiver android:name="com.android.server.devicepolicy.DummyDeviceAdmins$Admin1"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_admin_sample" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.devicepolicy.DummyDeviceAdmins$Admin2"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_admin_sample" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.devicepolicy.DummyDeviceAdmins$Admin3"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_admin_sample" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+
</application>
<instrumentation
diff --git a/core/tests/coretests/src/android/net/netlink/NetlinkErrorMessageTest.java b/services/tests/servicestests/src/android/net/netlink/NetlinkErrorMessageTest.java
index e677475f5907..e677475f5907 100644
--- a/core/tests/coretests/src/android/net/netlink/NetlinkErrorMessageTest.java
+++ b/services/tests/servicestests/src/android/net/netlink/NetlinkErrorMessageTest.java
diff --git a/core/tests/coretests/src/android/net/netlink/NetlinkSocketTest.java b/services/tests/servicestests/src/android/net/netlink/NetlinkSocketTest.java
index c599fe3e5b76..c599fe3e5b76 100644
--- a/core/tests/coretests/src/android/net/netlink/NetlinkSocketTest.java
+++ b/services/tests/servicestests/src/android/net/netlink/NetlinkSocketTest.java
diff --git a/core/tests/coretests/src/android/net/netlink/RtNetlinkNeighborMessageTest.java b/services/tests/servicestests/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
index 19ee00036b61..19ee00036b61 100644
--- a/core/tests/coretests/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
+++ b/services/tests/servicestests/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
new file mode 100644
index 000000000000..7e730f6b5289
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.devicepolicy;
+
+import com.android.internal.widget.LockPatternUtils;
+
+import android.app.IActivityManager;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.os.Looper;
+import android.os.PowerManager.WakeLock;
+import android.os.PowerManagerInternal;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.view.IWindowManager;
+
+import java.io.File;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+/**
+ * Overrides {@link #DevicePolicyManagerService} for dependency injection.
+ */
+public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerService {
+ /**
+ * Overrides {@link #Owners} for dependency injection.
+ */
+ public static class OwnersTestable extends Owners {
+ public static final String LEGACY_FILE = "legacy.xml";
+ public static final String DEVICE_OWNER_FILE = "device_owner2.xml";
+ public static final String PROFILE_OWNER_FILE_BASE = "profile_owner.xml";
+
+ private final File mLegacyFile;
+ private final File mDeviceOwnerFile;
+ private final File mProfileOwnerBase;
+
+ public OwnersTestable(Context context, File dataDir) {
+ super(context);
+ mLegacyFile = new File(dataDir, LEGACY_FILE);
+ mDeviceOwnerFile = new File(dataDir, DEVICE_OWNER_FILE);
+ mProfileOwnerBase = new File(dataDir, PROFILE_OWNER_FILE_BASE);
+ }
+
+ @Override
+ File getLegacyConfigFileWithTestOverride() {
+ return mLegacyFile;
+ }
+
+ @Override
+ File getDeviceOwnerFileWithTestOverride() {
+ return mDeviceOwnerFile;
+ }
+
+ @Override
+ File getProfileOwnerFileWithTestOverride(int userId) {
+ return new File(mDeviceOwnerFile.getAbsoluteFile() + "-" + userId);
+ }
+ }
+
+ public final File dataDir;
+ public final File systemUserDataDir;
+ public final File secondUserDataDir;
+
+ public DevicePolicyManagerServiceTestable(DpmMockContext context, File dataDir) {
+ super(context);
+ this.dataDir = dataDir;
+
+ systemUserDataDir = new File(dataDir, "user0");
+ DpmTestUtils.clearDir(dataDir);
+
+ secondUserDataDir = new File(dataDir, "user" + DpmMockContext.CALLER_USER_HANDLE);
+ DpmTestUtils.clearDir(secondUserDataDir);
+
+ when(getContext().environment.getUserSystemDirectory(
+ eq(DpmMockContext.CALLER_USER_HANDLE))).thenReturn(secondUserDataDir);
+ }
+
+ @Override
+ DpmMockContext getContext() {
+ return (DpmMockContext) super.getContext();
+ }
+
+ @Override
+ Owners newOwners() {
+ return new OwnersTestable(getContext(), dataDir);
+ }
+
+ @Override
+ UserManager getUserManager() {
+ return getContext().userManager;
+ }
+
+ @Override
+ PackageManager getPackageManager() {
+ return getContext().packageManager;
+ }
+
+ @Override
+ PowerManagerInternal getPowerManagerInternal() {
+ return getContext().powerManagerInternal;
+ }
+
+ @Override
+ NotificationManager getNotificationManager() {
+ return getContext().notificationManager;
+ }
+
+ @Override
+ IWindowManager getIWindowManager() {
+ return getContext().iwindowManager;
+ }
+
+ @Override
+ IActivityManager getIActivityManager() {
+ return getContext().iactivityManager;
+ }
+
+ @Override
+ IPackageManager getIPackageManager() {
+ return getContext().ipackageManager;
+ }
+
+ @Override
+ LockPatternUtils newLockPatternUtils(Context context) {
+ return getContext().lockPatternUtils;
+ }
+
+ @Override
+ Looper getMyLooper() {
+ return Looper.getMainLooper();
+ }
+
+ @Override
+ String getDevicePolicyFilePathForSystemUser() {
+ return systemUserDataDir.getAbsolutePath();
+ }
+
+ @Override
+ long binderClearCallingIdentity() {
+ return getContext().binder.clearCallingIdentity();
+ }
+
+ @Override
+ void binderRestoreCallingIdentity(long token) {
+ getContext().binder.restoreCallingIdentity(token);
+ }
+
+ @Override
+ int binderGetCallingUid() {
+ return getContext().binder.getCallingUid();
+ }
+
+ @Override
+ int binderGetCallingPid() {
+ return getContext().binder.getCallingPid();
+ }
+
+ @Override
+ UserHandle binderGetCallingUserHandle() {
+ return getContext().binder.getCallingUserHandle();
+ }
+
+ @Override
+ boolean binderIsCallingUidMyUid() {
+ return getContext().binder.isCallerUidMyUid();
+ }
+
+ @Override
+ File environmentGetUserSystemDirectory(int userId) {
+ return getContext().environment.getUserSystemDirectory(userId);
+ }
+
+ @Override
+ void powerManagerGoToSleep(long time, int reason, int flags) {
+ getContext().powerManager.goToSleep(time, reason, flags);
+ }
+
+ @Override
+ boolean systemPropertiesGetBoolean(String key, boolean def) {
+ return getContext().systemProperties.getBoolean(key, def);
+ }
+
+ @Override
+ long systemPropertiesGetLong(String key, long def) {
+ return getContext().systemProperties.getLong(key, def);
+ }
+
+ @Override
+ String systemPropertiesGet(String key, String def) {
+ return getContext().systemProperties.get(key, def);
+ }
+
+ @Override
+ String systemPropertiesGet(String key) {
+ return getContext().systemProperties.get(key);
+ }
+
+ @Override
+ void systemPropertiesSet(String key, String value) {
+ getContext().systemProperties.set(key, value);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
new file mode 100644
index 000000000000..0da459dab0d6
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.devicepolicy;
+
+import com.android.server.LocalServices;
+
+import android.Manifest.permission;
+import android.app.Activity;
+import android.app.admin.DeviceAdminReceiver;
+import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyManagerInternal;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+
+import org.mockito.ArgumentCaptor;
+
+import java.util.List;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for DevicePolicyManager( and DevicePolicyManagerService).
+ *
+ m FrameworksServicesTests &&
+ adb install \
+ -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
+ adb shell am instrument -e class com.android.server.devicepolicy.DevicePolicyManagerTest \
+ -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+
+ (mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
+ */
+public class DevicePolicyManagerTest extends DpmTestBase {
+
+
+ private DpmMockContext mContext;
+ public DevicePolicyManager dpm;
+ public DevicePolicyManagerServiceTestable dpms;
+ public ComponentName admin1;
+ public ComponentName admin2;
+ public ComponentName admin3;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mContext = getContext();
+
+ when(mContext.packageManager.hasSystemFeature(eq(PackageManager.FEATURE_DEVICE_ADMIN)))
+ .thenReturn(true);
+
+ LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
+ dpms = new DevicePolicyManagerServiceTestable(mContext, dataDir);
+ dpm = new DevicePolicyManagerTestable(mContext, dpms);
+
+ admin1 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin1.class);
+ admin2 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin2.class);
+ admin3 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin3.class);
+
+ setUpPackageManagerForAdmin(admin1);
+ setUpPackageManagerForAdmin(admin2);
+ setUpPackageManagerForAdmin(admin3);
+
+ setUpApplicationInfo(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
+ }
+
+ /**
+ * Set up a mock result for {@link PackageManager#queryBroadcastReceivers}. We'll return
+ * the actual ResolveInfo for the admin component, but we need to mock PM so it'll return
+ * it for user {@link DpmMockContext#CALLER_USER_HANDLE}.
+ */
+ private void setUpPackageManagerForAdmin(ComponentName admin) {
+ final Intent resolveIntent = new Intent();
+ resolveIntent.setComponent(admin);
+ final List<ResolveInfo> realResolveInfo =
+ mRealTestContext.getPackageManager().queryBroadcastReceivers(
+ resolveIntent,
+ PackageManager.GET_META_DATA);
+ assertNotNull(realResolveInfo);
+ assertEquals(1, realResolveInfo.size());
+
+ // We need to rewrite the UID in the activity info.
+ realResolveInfo.get(0).activityInfo.applicationInfo.uid = DpmMockContext.CALLER_UID;
+
+ doReturn(realResolveInfo).when(mContext.packageManager).queryBroadcastReceivers(
+ MockUtils.checkIntentComponent(admin),
+ eq(PackageManager.GET_META_DATA
+ | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
+ eq(DpmMockContext.CALLER_USER_HANDLE)
+ );
+ }
+
+ /**
+ * Set up a mock result for {@link IPackageManager#getApplicationInfo} for user
+ * {@link DpmMockContext#CALLER_USER_HANDLE}.
+ */
+ private void setUpApplicationInfo(int enabledSetting) throws Exception {
+ final ApplicationInfo ai = mRealTestContext.getPackageManager().getApplicationInfo(
+ admin1.getPackageName(),
+ PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
+
+ ai.enabledSetting = enabledSetting;
+
+ doReturn(ai).when(mContext.ipackageManager).getApplicationInfo(
+ eq(admin1.getPackageName()),
+ eq(PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
+ eq(DpmMockContext.CALLER_USER_HANDLE));
+ }
+
+ public void testHasNoFeature() {
+ when(mContext.packageManager.hasSystemFeature(eq(PackageManager.FEATURE_DEVICE_ADMIN)))
+ .thenReturn(false);
+
+ LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
+ new DevicePolicyManagerServiceTestable(mContext, dataDir);
+
+ // If the device has no DPMS feature, it shouldn't register the local service.
+ assertNull(LocalServices.getService(DevicePolicyManagerInternal.class));
+ }
+
+ /**
+ * Caller doesn't have proper permissions.
+ */
+ public void testSetActiveAdmin_SecurityException() {
+ // 1. Failure cases.
+
+ // Caller doesn't have MANAGE_DEVICE_ADMINS.
+ try {
+ dpm.setActiveAdmin(admin1, false);
+ fail("Didn't throw SecurityException");
+ } catch (SecurityException expected) {
+ }
+
+ // Caller has MANAGE_DEVICE_ADMINS, but for different user.
+ mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+ try {
+ dpm.setActiveAdmin(admin1, false, DpmMockContext.CALLER_USER_HANDLE + 1);
+ fail("Didn't throw SecurityException");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ /**
+ * Test for:
+ * {@link DevicePolicyManager#setActiveAdmin}
+ * with replace=false and replace=true
+ * {@link DevicePolicyManager#isAdminActive}
+ * {@link DevicePolicyManager#isAdminActiveAsUser}
+ * {@link DevicePolicyManager#getActiveAdmins}
+ * {@link DevicePolicyManager#getActiveAdminsAsUser}
+ */
+ public void testSetActiveAdmin() throws Exception {
+ // 1. Make sure the caller has proper permissions.
+ mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+ // 2. Call the API.
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+
+ // 3. Verify internal calls.
+
+ // Check if the boradcast is sent.
+ verify(mContext.spiedContext).sendBroadcastAsUser(
+ MockUtils.checkIntentAction(
+ DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
+ MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
+ verify(mContext.spiedContext).sendBroadcastAsUser(
+ MockUtils.checkIntentAction(
+ DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED),
+ MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
+
+ verify(mContext.ipackageManager, times(1)).setApplicationEnabledSetting(
+ eq(admin1.getPackageName()),
+ eq(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT),
+ eq(PackageManager.DONT_KILL_APP),
+ eq(DpmMockContext.CALLER_USER_HANDLE),
+ anyString());
+
+ // TODO Verify other calls too.
+
+ // Make sure it's active admin1.
+ assertTrue(dpm.isAdminActive(admin1));
+ assertFalse(dpm.isAdminActive(admin2));
+ assertFalse(dpm.isAdminActive(admin3));
+
+ // But not admin1 for a different user.
+
+ // For this to work, caller needs android.permission.INTERACT_ACROSS_USERS_FULL.
+ // (Because we're checking a different user's status from CALLER_USER_HANDLE.)
+ mContext.callerPermissions.add("android.permission.INTERACT_ACROSS_USERS_FULL");
+
+ assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE + 1));
+ assertFalse(dpm.isAdminActiveAsUser(admin2, DpmMockContext.CALLER_USER_HANDLE + 1));
+
+ mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
+
+ // Next, add one more admin.
+ // Before doing so, update the application info, now it's enabled.
+ setUpApplicationInfo(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+
+ dpm.setActiveAdmin(admin2, /* replace =*/ false);
+
+ // Now we have two admins.
+ assertTrue(dpm.isAdminActive(admin1));
+ assertTrue(dpm.isAdminActive(admin2));
+ assertFalse(dpm.isAdminActive(admin3));
+
+ // Admin2 was already enabled, so setApplicationEnabledSetting() shouldn't have called
+ // again. (times(1) because it was previously called for admin1)
+ verify(mContext.ipackageManager, times(1)).setApplicationEnabledSetting(
+ eq(admin1.getPackageName()),
+ eq(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT),
+ eq(PackageManager.DONT_KILL_APP),
+ eq(DpmMockContext.CALLER_USER_HANDLE),
+ anyString());
+
+ // 4. Add the same admin1 again without replace, which should throw.
+ try {
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+ fail("Didn't throw");
+ } catch (IllegalArgumentException expected) {
+ }
+
+ // 5. Add the same admin1 again with replace, which should succeed.
+ dpm.setActiveAdmin(admin1, /* replace =*/ true);
+
+ // TODO make sure it's replaced.
+
+ // 6. Test getActiveAdmins()
+ List<ComponentName> admins = dpm.getActiveAdmins();
+ assertEquals(2, admins.size());
+ assertEquals(admin1, admins.get(0));
+ assertEquals(admin2, admins.get(1));
+
+ // Another user has no admins.
+ mContext.callerPermissions.add("android.permission.INTERACT_ACROSS_USERS_FULL");
+
+ assertEquals(0, DpmTestUtils.getListSizeAllowingNull(
+ dpm.getActiveAdminsAsUser(DpmMockContext.CALLER_USER_HANDLE + 1)));
+
+ mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
+ }
+
+ /**
+ * Test for:
+ * {@link DevicePolicyManager#setActiveAdmin}
+ * with replace=false
+ */
+ public void testSetActiveAdmin_twiceWithoutReplace() throws Exception {
+ // 1. Make sure the caller has proper permissions.
+ mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+ assertTrue(dpm.isAdminActive(admin1));
+
+ // Add the same admin1 again without replace, which should throw.
+ try {
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+ fail("Didn't throw");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ /**
+ * Test for:
+ * {@link DevicePolicyManager#removeActiveAdmin}
+ */
+ public void testRemoveActiveAdmin_SecurityException() {
+ mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+ // Add admin.
+
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+
+ assertTrue(dpm.isAdminActive(admin1));
+
+ assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+ // Directly call the DPMS method with a different userid, which should fail.
+ try {
+ dpms.removeActiveAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE + 1);
+ fail("Didn't throw SecurityException");
+ } catch (SecurityException expected) {
+ }
+
+ // Try to remove active admin with a different caller userid should fail too, without
+ // having MANAGE_DEVICE_ADMINS.
+ mContext.callerPermissions.clear();
+
+ mContext.binder.callingUid = 1234567;
+ try {
+ dpm.removeActiveAdmin(admin1);
+ fail("Didn't throw SecurityException");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ /**
+ * Test for:
+ * {@link DevicePolicyManager#removeActiveAdmin}
+ */
+ public void testRemoveActiveAdmin_fromDifferentUserWithMINTERACT_ACROSS_USERS_FULL() {
+ mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+ // Add admin1.
+
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+
+ assertTrue(dpm.isAdminActive(admin1));
+ assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+ // Different user, but should work, because caller has proper permissions.
+ mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
+ mContext.binder.callingUid = 1234567;
+ dpm.removeActiveAdmin(admin1);
+
+ assertTrue(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+ // TODO DO Still can't be removed in this case.
+ }
+
+ /**
+ * Test for:
+ * {@link DevicePolicyManager#removeActiveAdmin}
+ */
+ public void testRemoveActiveAdmin_sameUserNoMANAGE_DEVICE_ADMINS() {
+ // Need MANAGE_DEVICE_ADMINS for setActiveAdmin. We'll remove it later.
+ mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+ // Add admin1.
+
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+
+ assertTrue(dpm.isAdminActive(admin1));
+ assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+ // Broadcast from saveSettingsLocked().
+ verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
+ MockUtils.checkIntentAction(
+ DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
+ MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
+
+ // Remove. No permissions, but same user, so it'll work.
+ mContext.callerPermissions.clear();
+ dpm.removeActiveAdmin(admin1);
+
+ final ArgumentCaptor<BroadcastReceiver> brCap =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+
+ // Is removing now, but not removed yet.
+ assertTrue(dpm.isAdminActive(admin1));
+ assertTrue(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+ verify(mContext.spiedContext).sendOrderedBroadcastAsUser(
+ MockUtils.checkIntentAction(
+ DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED),
+ MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE),
+ isNull(String.class),
+ brCap.capture(),
+ eq(dpms.mHandler),
+ eq(Activity.RESULT_OK),
+ isNull(String.class),
+ isNull(Bundle.class));
+
+ brCap.getValue().onReceive(mContext, null);
+
+ assertFalse(dpm.isAdminActive(admin1));
+ assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+ // Again broadcast from saveSettingsLocked().
+ verify(mContext.spiedContext, times(2)).sendBroadcastAsUser(
+ MockUtils.checkIntentAction(
+ DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
+ MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
+
+ // TODO Check other internal calls.
+ }
+}
+
+
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTestable.java
new file mode 100644
index 000000000000..325bf9ff0225
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTestable.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.devicepolicy;
+
+import android.app.admin.DevicePolicyManager;
+
+/**
+ * Overrides {@link #DevicePolicyManager} for dependency injection.
+ */
+public class DevicePolicyManagerTestable extends DevicePolicyManager {
+ public final DevicePolicyManagerServiceTestable dpms;
+
+ public DevicePolicyManagerTestable(DpmMockContext context,
+ DevicePolicyManagerServiceTestable dpms) {
+ super(context, dpms);
+ this.dpms = dpms;
+ }
+
+ @Override
+ public int myUserId() {
+ return DpmMockContext.CALLER_USER_HANDLE;
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index c2b89819501b..6bb9833a883c 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -16,31 +16,356 @@
package com.android.server.devicepolicy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.widget.LockPatternUtils;
+
+import android.app.IActivityManager;
+import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.PowerManager.WakeLock;
+import android.os.PowerManagerInternal;
+import android.os.SystemProperties;
+import android.os.UserHandle;
import android.os.UserManager;
+import android.test.mock.MockContext;
+import android.view.IWindowManager;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
-public class DpmMockContext extends ContextWrapper {
- private final UserManager mMockUserManager;
+/**
+ * Context used throughout DPMS tests.
+ */
+public class DpmMockContext extends MockContext {
+ /**
+ * User-id of a non-system user we use throughout unit tests.
+ */
+ public static final int CALLER_USER_HANDLE = 20;
+ /**
+ * UID of the caller.
+ */
+ public static final int CALLER_UID = UserHandle.PER_USER_RANGE * CALLER_USER_HANDLE + 123;
- public DpmMockContext(Context context) {
- super(context);
- mMockUserManager = mock(UserManager.class);
+ /**
+ * PID of the caller.
+ */
+ public static final int CALLER_PID = 22222;
+
+ /**
+ * UID of the system server.
+ */
+ public static final int SYSTEM_UID = android.os.Process.SYSTEM_UID;
+
+ /**
+ * PID of the system server.
+ */
+ public static final int SYSTEM_PID = 11111;
+
+ public static class MockBinder {
+ public int callingUid = CALLER_UID;
+ public int callingPid = CALLER_PID;
+
+ public long clearCallingIdentity() {
+ final long token = (((long) callingUid) << 32) | (callingPid);
+ callingUid = SYSTEM_UID;
+ callingPid = SYSTEM_PID;
+ return token;
+ }
+
+ public void restoreCallingIdentity(long token) {
+ callingUid = (int) (token >> 32);
+ callingPid = (int) token;
+ }
+
+ public int getCallingUid() {
+ return callingUid;
+ }
+
+ public int getCallingPid() {
+ return callingPid;
+ }
+
+ public UserHandle getCallingUserHandle() {
+ return new UserHandle(UserHandle.getUserId(getCallingUid()));
+ }
+
+ public boolean isCallerUidMyUid() {
+ return callingUid == SYSTEM_UID;
+ }
+ }
+
+ public static class EnvironmentForMock {
+ public File getUserSystemDirectory(int userId) {
+ return null;
+ }
}
- public UserManager getMockUserManager() {
- return mMockUserManager;
+ public static class PowerManagerForMock {
+ public WakeLock newWakeLock(int levelAndFlags, String tag) {
+ return null;
+ }
+
+ public void goToSleep(long time, int reason, int flags) {
+ }
+ }
+
+ public static class SystemPropertiesForMock {
+ public boolean getBoolean(String key, boolean def) {
+ return false;
+ }
+
+ public long getLong(String key, long def) {
+ return 0;
+ }
+
+ public String get(String key, String def) {
+ return null;
+ }
+
+ public String get(String key) {
+ return null;
+ }
+
+ public void set(String key, String value) {
+ }
+ }
+
+ public final Context realTestContext;
+
+ /**
+ * Use this instance to verify unimplemented methods such as {@link #sendBroadcast}.
+ * (Spying on {@code this} instance will confuse mockito somehow and I got weired "wrong number
+ * of arguments" exceptions.)
+ */
+ public final Context spiedContext;
+
+ public final MockBinder binder;
+ public final EnvironmentForMock environment;
+ public final SystemPropertiesForMock systemProperties;
+ public final UserManager userManager;
+ public final PowerManagerForMock powerManager;
+ public final PowerManagerInternal powerManagerInternal;
+ public final NotificationManager notificationManager;
+ public final IWindowManager iwindowManager;
+ public final IActivityManager iactivityManager;
+ public final IPackageManager ipackageManager;
+ public final LockPatternUtils lockPatternUtils;
+
+ /** Note this is a partial mock, not a real mock. */
+ public final PackageManager packageManager;
+
+ public final List<String> callerPermissions = new ArrayList<>();
+
+ public DpmMockContext(Context context) {
+ realTestContext = context;
+ binder = new MockBinder();
+ environment = mock(EnvironmentForMock.class);
+ systemProperties= mock(SystemPropertiesForMock.class);
+ userManager = mock(UserManager.class);
+ powerManager = mock(PowerManagerForMock.class);
+ powerManagerInternal = mock(PowerManagerInternal.class);
+ notificationManager = mock(NotificationManager.class);
+ iwindowManager = mock(IWindowManager.class);
+ iactivityManager = mock(IActivityManager.class);
+ ipackageManager = mock(IPackageManager.class);
+ lockPatternUtils = mock(LockPatternUtils.class);
+
+ // Package manager is huge, so we use a partial mock instead.
+ packageManager = spy(context.getPackageManager());
+
+ spiedContext = mock(Context.class);
}
@Override
public Object getSystemService(String name) {
switch (name) {
case Context.USER_SERVICE:
- return mMockUserManager;
+ return userManager;
+ case Context.POWER_SERVICE:
+ return powerManager;
+ }
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return packageManager;
+ }
+
+ @Override
+ public void enforceCallingOrSelfPermission(String permission, String message) {
+ if (binder.getCallingUid() == SYSTEM_UID) {
+ return; // Assume system has all permissions.
}
- return super.getSystemService(name);
+ if (!callerPermissions.contains(permission)) {
+ throw new SecurityException("Caller doesn't have " + permission + " : " + message);
+ }
+ }
+
+ @Override
+ public void sendBroadcast(Intent intent) {
+ spiedContext.sendBroadcast(intent);
+ }
+
+ @Override
+ public void sendBroadcast(Intent intent, String receiverPermission) {
+ spiedContext.sendBroadcast(intent, receiverPermission);
+ }
+
+ @Override
+ public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
+ spiedContext.sendBroadcastMultiplePermissions(intent, receiverPermissions);
+ }
+
+ @Override
+ public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
+ spiedContext.sendBroadcast(intent, receiverPermission, options);
+ }
+
+ @Override
+ public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
+ spiedContext.sendBroadcast(intent, receiverPermission, appOp);
+ }
+
+ @Override
+ public void sendOrderedBroadcast(Intent intent, String receiverPermission) {
+ spiedContext.sendOrderedBroadcast(intent, receiverPermission);
+ }
+
+ @Override
+ public void sendOrderedBroadcast(Intent intent, String receiverPermission,
+ BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
+ String initialData, Bundle initialExtras) {
+ spiedContext.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler,
+ initialCode, initialData, initialExtras);
+ }
+
+ @Override
+ public void sendOrderedBroadcast(Intent intent, String receiverPermission, Bundle options,
+ BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
+ String initialData, Bundle initialExtras) {
+ spiedContext.sendOrderedBroadcast(intent, receiverPermission, options, resultReceiver,
+ scheduler,
+ initialCode, initialData, initialExtras);
+ }
+
+ @Override
+ public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp,
+ BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
+ String initialData, Bundle initialExtras) {
+ spiedContext.sendOrderedBroadcast(intent, receiverPermission, appOp, resultReceiver,
+ scheduler,
+ initialCode, initialData, initialExtras);
+ }
+
+ @Override
+ public void sendBroadcastAsUser(Intent intent, UserHandle user) {
+ spiedContext.sendBroadcastAsUser(intent, user);
+ }
+
+ @Override
+ public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission) {
+ spiedContext.sendBroadcastAsUser(intent, user, receiverPermission);
+ }
+
+ @Override
+ public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission,
+ int appOp) {
+ spiedContext.sendBroadcastAsUser(intent, user, receiverPermission, appOp);
+ }
+
+ @Override
+ public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+ String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
+ int initialCode, String initialData, Bundle initialExtras) {
+ spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, resultReceiver,
+ scheduler, initialCode, initialData, initialExtras);
+ }
+
+ @Override
+ public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+ String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
+ Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
+ spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp,
+ resultReceiver,
+ scheduler, initialCode, initialData, initialExtras);
+ }
+
+ @Override
+ public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+ String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
+ Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
+ spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, options,
+ resultReceiver, scheduler, initialCode, initialData, initialExtras);
+ }
+
+ @Override
+ public void sendStickyBroadcast(Intent intent) {
+ spiedContext.sendStickyBroadcast(intent);
+ }
+
+ @Override
+ public void sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver,
+ Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
+ spiedContext.sendStickyOrderedBroadcast(intent, resultReceiver, scheduler, initialCode,
+ initialData, initialExtras);
+ }
+
+ @Override
+ public void removeStickyBroadcast(Intent intent) {
+ spiedContext.removeStickyBroadcast(intent);
+ }
+
+ @Override
+ public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
+ spiedContext.sendStickyBroadcastAsUser(intent, user);
+ }
+
+ @Override
+ public void sendStickyOrderedBroadcastAsUser(Intent intent, UserHandle user,
+ BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
+ String initialData, Bundle initialExtras) {
+ spiedContext.sendStickyOrderedBroadcastAsUser(intent, user, resultReceiver, scheduler, initialCode,
+ initialData, initialExtras);
+ }
+
+ @Override
+ public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
+ spiedContext.removeStickyBroadcastAsUser(intent, user);
+ }
+
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+ return spiedContext.registerReceiver(receiver, filter);
+ }
+
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
+ String broadcastPermission, Handler scheduler) {
+ return spiedContext.registerReceiver(receiver, filter, broadcastPermission, scheduler);
+ }
+
+ @Override
+ public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+ IntentFilter filter, String broadcastPermission, Handler scheduler) {
+ return spiedContext.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
+ scheduler);
+ }
+
+ @Override
+ public void unregisterReceiver(BroadcastReceiver receiver) {
+ spiedContext.unregisterReceiver(receiver);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
index 445260b9da6c..77270c8cec55 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
@@ -19,14 +19,25 @@ package com.android.server.devicepolicy;
import android.content.Context;
import android.test.AndroidTestCase;
+import java.io.File;
+
public class DpmTestBase extends AndroidTestCase {
- private DpmMockContext mMockContext;
+ public static final String TAG = "DpmTest";
+
+ protected Context mRealTestContext;
+ protected DpmMockContext mMockContext;
+
+ public File dataDir;
@Override
protected void setUp() throws Exception {
super.setUp();
+ mRealTestContext = super.getContext();
mMockContext = new DpmMockContext(super.getContext());
+
+ dataDir = new File(mRealTestContext.getCacheDir(), "test-data");
+ DpmTestUtils.clearDir(dataDir);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java
new file mode 100644
index 000000000000..44a851abe476
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.devicepolicy;
+
+import android.os.FileUtils;
+import android.util.Log;
+import android.util.Printer;
+
+import org.junit.Assert;
+
+import java.io.File;
+import java.util.List;
+
+public class DpmTestUtils {
+ private DpmTestUtils() {
+ }
+
+ public static void clearDir(File dir) {
+ if (dir.exists()) {
+ Assert.assertTrue("failed to delete dir", FileUtils.deleteContents(dir));
+ }
+ dir.mkdirs();
+ Log.i(DpmTestBase.TAG, "Created " + dir);
+ }
+
+ public static int getListSizeAllowingNull(List<?> list) {
+ return list == null ? 0 : list.size();
+ }
+
+ public static Printer LOG_PRINTER = new Printer() {
+ @Override
+ public void println(String x) {
+ Log.i(DpmTestBase.TAG, x);
+ }
+ };
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmins.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmins.java
new file mode 100644
index 000000000000..5cd15557a80d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmins.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.devicepolicy;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class DummyDeviceAdmins {
+ public static class Admin1 extends DeviceAdminReceiver {
+ }
+ public static class Admin2 extends DeviceAdminReceiver {
+ }
+ public static class Admin3 extends DeviceAdminReceiver {
+ }
+} \ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
new file mode 100644
index 000000000000..5008fbfa3b10
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.devicepolicy;
+
+import com.google.common.base.Objects;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.UserHandle;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.mockito.Mockito;
+
+public class MockUtils {
+ private MockUtils() {
+ }
+
+ public static UserHandle checkUserHandle(final int userId) {
+ final Matcher<UserHandle> m = new BaseMatcher<UserHandle>() {
+ @Override
+ public boolean matches(Object item) {
+ if (item == null) return false;
+ return Objects.equal(((UserHandle) item).getIdentifier(), userId);
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("UserHandle: user-id= \"" + userId + "\"");
+ }
+ };
+ return Mockito.argThat(m);
+ }
+
+ public static Intent checkIntentComponent(final ComponentName component) {
+ final Matcher<Intent> m = new BaseMatcher<Intent>() {
+ @Override
+ public boolean matches(Object item) {
+ if (item == null) return false;
+ return Objects.equal(((Intent) item).getComponent(), component);
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Intent: component=\"" + component + "\"");
+ }
+ };
+ return Mockito.argThat(m);
+ }
+
+ public static Intent checkIntentAction(final String action) {
+ final Matcher<Intent> m = new BaseMatcher<Intent>() {
+ @Override
+ public boolean matches(Object item) {
+ if (item == null) return false;
+ return Objects.equal(((Intent) item).getAction(), action);
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Intent: action=\"" + action + "\"");
+ }
+ };
+ return Mockito.argThat(m);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
index 3b88fb165775..a07d61520fa4 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
@@ -16,12 +16,11 @@
package com.android.server.devicepolicy;
+import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable;
+
import android.content.ComponentName;
-import android.content.Context;
import android.content.pm.UserInfo;
-import android.os.FileUtils;
import android.os.UserHandle;
-import android.test.AndroidTestCase;
import android.util.Log;
import java.io.BufferedReader;
@@ -31,8 +30,6 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
-import junit.framework.Assert;
-
import static org.mockito.Mockito.when;
/**
@@ -47,58 +44,11 @@ import static org.mockito.Mockito.when;
(mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
*/
public class OwnersTest extends DpmTestBase {
- private static final String TAG = "DeviceOwnerTest";
-
- private static final String LEGACY_FILE = "legacy.xml";
- private static final String DEVICE_OWNER_FILE = "device_owner2.xml";
- private static final String PROFILE_OWNER_FILE_BASE = "profile_owner.xml";
-
- private File mDataDir;
-
- private class OwnersSub extends Owners {
- final File mLegacyFile;
- final File mDeviceOwnerFile;
- final File mProfileOwnerBase;
-
- public OwnersSub() {
- super(getContext());
- mLegacyFile = new File(mDataDir, LEGACY_FILE);
- mDeviceOwnerFile = new File(mDataDir, DEVICE_OWNER_FILE);
- mProfileOwnerBase = new File(mDataDir, PROFILE_OWNER_FILE_BASE);
- }
-
- @Override
- File getLegacyConfigFileWithTestOverride() {
- return mLegacyFile;
- }
-
- @Override
- File getDeviceOwnerFileWithTestOverride() {
- return mDeviceOwnerFile;
- }
-
- @Override
- File getProfileOwnerFileWithTestOverride(int userId) {
- return new File(mDeviceOwnerFile.getAbsoluteFile() + "-" + userId);
- }
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- mDataDir = new File(getContext().getCacheDir(), "OwnersTest");
- if (mDataDir.exists()) {
- assertTrue("failed to delete dir", FileUtils.deleteContents(mDataDir));
- }
- mDataDir.mkdirs();
- Log.i(TAG, "Created " + mDataDir);
- }
-
private String readAsset(String assetPath) throws IOException {
final StringBuilder sb = new StringBuilder();
try (BufferedReader br = new BufferedReader(
- new InputStreamReader((getContext().getResources().getAssets().open(assetPath))))) {
+ new InputStreamReader(
+ mRealTestContext.getResources().getAssets().open(assetPath)))) {
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
@@ -126,7 +76,7 @@ public class OwnersTest extends DpmTestBase {
ui.id = userId;
userInfos.add(ui);
}
- when(getContext().getMockUserManager().getUsers()).thenReturn(userInfos);
+ when(getContext().userManager.getUsers()).thenReturn(userInfos);
}
public void testUpgrade01() throws Exception {
@@ -134,9 +84,10 @@ public class OwnersTest extends DpmTestBase {
// First, migrate.
{
- final OwnersSub owners = new OwnersSub();
+ final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
- createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test01/input.xml"));
+ createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
+ readAsset("OwnersTest/test01/input.xml"));
owners.load();
@@ -160,7 +111,7 @@ public class OwnersTest extends DpmTestBase {
// Then re-read and check.
{
- final OwnersSub owners = new OwnersSub();
+ final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
owners.load();
assertFalse(owners.hasDeviceOwner());
@@ -176,9 +127,10 @@ public class OwnersTest extends DpmTestBase {
// First, migrate.
{
- final OwnersSub owners = new OwnersSub();
+ final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
- createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test02/input.xml"));
+ createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
+ readAsset("OwnersTest/test02/input.xml"));
owners.load();
@@ -204,7 +156,7 @@ public class OwnersTest extends DpmTestBase {
// Then re-read and check.
{
- final OwnersSub owners = new OwnersSub();
+ final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
owners.load();
assertTrue(owners.hasDeviceOwner());
@@ -223,9 +175,10 @@ public class OwnersTest extends DpmTestBase {
// First, migrate.
{
- final OwnersSub owners = new OwnersSub();
+ final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
- createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test03/input.xml"));
+ createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
+ readAsset("OwnersTest/test03/input.xml"));
owners.load();
@@ -259,7 +212,7 @@ public class OwnersTest extends DpmTestBase {
// Then re-read and check.
{
- final OwnersSub owners = new OwnersSub();
+ final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
owners.load();
assertFalse(owners.hasDeviceOwner());
@@ -286,9 +239,10 @@ public class OwnersTest extends DpmTestBase {
// First, migrate.
{
- final OwnersSub owners = new OwnersSub();
+ final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
- createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test04/input.xml"));
+ createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
+ readAsset("OwnersTest/test04/input.xml"));
owners.load();
@@ -327,7 +281,7 @@ public class OwnersTest extends DpmTestBase {
// Then re-read and check.
{
- final OwnersSub owners = new OwnersSub();
+ final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
owners.load();
assertTrue(owners.hasDeviceOwner());
@@ -359,9 +313,10 @@ public class OwnersTest extends DpmTestBase {
// First, migrate.
{
- final OwnersSub owners = new OwnersSub();
+ final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
- createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test05/input.xml"));
+ createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
+ readAsset("OwnersTest/test05/input.xml"));
owners.load();
@@ -386,7 +341,7 @@ public class OwnersTest extends DpmTestBase {
// Then re-read and check.
{
- final OwnersSub owners = new OwnersSub();
+ final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
owners.load();
assertFalse(owners.hasDeviceOwner());
@@ -405,9 +360,10 @@ public class OwnersTest extends DpmTestBase {
// First, migrate.
{
- final OwnersSub owners = new OwnersSub();
+ final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
- createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test06/input.xml"));
+ createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
+ readAsset("OwnersTest/test06/input.xml"));
owners.load();
@@ -431,7 +387,7 @@ public class OwnersTest extends DpmTestBase {
// Then re-read and check.
{
- final OwnersSub owners = new OwnersSub();
+ final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
owners.load();
assertFalse(owners.hasDeviceOwner());
@@ -447,10 +403,11 @@ public class OwnersTest extends DpmTestBase {
public void testRemoveExistingFiles() throws Exception {
addUsersToUserManager(10, 11, 20, 21);
- final OwnersSub owners = new OwnersSub();
+ final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
// First, migrate to create new-style config files.
- createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test04/input.xml"));
+ createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
+ readAsset("OwnersTest/test04/input.xml"));
owners.load();
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index 2cf42f09111d..154cbd30d836 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -517,7 +517,7 @@ class UsbSettingsManager {
com.android.internal.R.bool.config_disableUsbPermissionDialogs);
synchronized (mLock) {
- if (UserHandle.OWNER.equals(user)) {
+ if (UserHandle.SYSTEM.equals(user)) {
upgradeSingleUserLocked();
}
readSettingsLocked();
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 5fbfe8ace7e1..ceb3993e1705 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -57,6 +57,7 @@ import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.util.Log;
+
public class ActivityTestMain extends Activity {
static final String TAG = "ActivityTest";
@@ -315,7 +316,7 @@ public class ActivityTestMain extends Activity {
Log.i(TAG, "Service disconnected " + name);
}
};
- if (bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
+ if (bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
mConnections.add(conn);
} else {
Toast.makeText(ActivityTestMain.this, "Failed to bind",
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 10cf5c1b2f8b..b028ce61f821 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -944,5 +944,14 @@
</intent-filter>
</activity>
+ <activity
+ android:name="MultiProducerActivity"
+ android:label="Threads/Multiple Producers">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.test.hwui.TEST" />
+ </intent-filter>
+ </activity>
+
</application>
</manifest>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java
new file mode 100644
index 000000000000..b458d9b14096
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.view.DisplayListCanvas;
+import android.view.HardwareRenderer;
+import android.view.RenderNode;
+import android.view.ThreadedRenderer;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.AbsoluteLayout;
+import android.widget.AbsoluteLayout.LayoutParams;
+
+public class MultiProducerActivity extends Activity implements OnClickListener {
+ private static final int DURATION = 800;
+ private View mBackgroundTarget = null;
+ private View mFrameTarget = null;
+ private View mContent = null;
+ // The width & height of our "output drawing".
+ private final int WIDTH = 900;
+ private final int HEIGHT = 600;
+ // A border width around the drawing.
+ private static final int BORDER_WIDTH = 20;
+ // The Gap between the content and the frame which should get filled on the right and bottom
+ // side by the backdrop.
+ final int CONTENT_GAP = 100;
+
+ // For debug purposes - disable drawing of frame / background.
+ private final boolean USE_FRAME = true;
+ private final boolean USE_BACK = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // To make things simple - we do a quick and dirty absolute layout.
+ final AbsoluteLayout layout = new AbsoluteLayout(this);
+
+ // Create the outer frame
+ if (USE_FRAME) {
+ mFrameTarget = new View(this);
+ LayoutParams frameLP = new LayoutParams(WIDTH, HEIGHT, 0, 0);
+ layout.addView(mFrameTarget, frameLP);
+ }
+
+ // Create the background which fills the gap between content and frame.
+ if (USE_BACK) {
+ mBackgroundTarget = new View(this);
+ LayoutParams backgroundLP = new LayoutParams(
+ WIDTH - 2 * BORDER_WIDTH, HEIGHT - 2 * BORDER_WIDTH,
+ BORDER_WIDTH, BORDER_WIDTH);
+ layout.addView(mBackgroundTarget, backgroundLP);
+ }
+
+ // Create the content
+ // Note: We reduce the size by CONTENT_GAP pixels on right and bottom, so that they get
+ // drawn by the backdrop.
+ mContent = new View(this);
+ mContent.setBackground(new ColorPulse(0xFFF44336, 0xFF9C27B0, null));
+ mContent.setOnClickListener(this);
+ LayoutParams contentLP = new LayoutParams(WIDTH - 2 * BORDER_WIDTH - CONTENT_GAP,
+ HEIGHT - 2 * BORDER_WIDTH - CONTENT_GAP, BORDER_WIDTH, BORDER_WIDTH);
+ layout.addView(mContent, contentLP);
+
+ setContentView(layout);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ View view = mBackgroundTarget != null ? mBackgroundTarget : mFrameTarget;
+ if (view != null) {
+ view.post(mSetup);
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ View view = mBackgroundTarget != null ? mBackgroundTarget : mFrameTarget;
+ if (view != null) {
+ view.removeCallbacks(mSetup);
+ }
+ if (mBgRenderer != null) {
+ mBgRenderer.destroy();
+ mBgRenderer = null;
+ }
+ }
+
+ @Override
+ public void onClick(View view) {
+ sBlockThread.run();
+ }
+
+ private Runnable mSetup = new Runnable() {
+ @Override
+ public void run() {
+ View view = mBackgroundTarget != null ? mBackgroundTarget : mFrameTarget;
+ if (view == null) {
+ view.postDelayed(mSetup, 50);
+ }
+ HardwareRenderer renderer = view.getHardwareRenderer();
+ if (renderer == null || view.getWidth() == 0) {
+ view.postDelayed(mSetup, 50);
+ }
+ ThreadedRenderer threaded = (ThreadedRenderer) renderer;
+
+ mBgRenderer = new FakeFrame(threaded,mFrameTarget, mBackgroundTarget);
+ mBgRenderer.start();
+ }
+ };
+
+ private FakeFrame mBgRenderer;
+ private class FakeFrame extends Thread {
+ ThreadedRenderer mRenderer;
+ volatile boolean mRunning = true;
+ View mTargetFrame;
+ View mTargetBack;
+ Drawable mFrameContent;
+ Drawable mBackContent;
+ // The Z value where to place this.
+ int mZFrame;
+ int mZBack;
+ String mRenderNodeName;
+
+ FakeFrame(ThreadedRenderer renderer, View targetFrame, View targetBack) {
+ mRenderer = renderer;
+ mTargetFrame = targetFrame;
+
+ mTargetBack = targetBack;
+ mFrameContent = new ColorPulse(0xFF101010, 0xFF707070, new Rect(0, 0, WIDTH, HEIGHT));
+ mBackContent = new ColorPulse(0xFF909090, 0xFFe0e0e0, null);
+ }
+
+ @Override
+ public void run() {
+ Rect currentFrameBounds = new Rect();
+ Rect currentBackBounds = new Rect();
+ Rect newBounds = new Rect();
+ int[] surfaceOrigin = new int[2];
+ RenderNode nodeFrame = null;
+ RenderNode nodeBack = null;
+
+ // Since we are overriding the window painting logic we need to at least fill the
+ // surface with some window content (otherwise the world will go black).
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException e) {
+ }
+
+ if (mTargetBack != null) {
+ nodeBack = RenderNode.create("FakeBackdrop", null);
+ nodeBack.setClipToBounds(true);
+ mRenderer.addRenderNode(nodeBack, true);
+ }
+
+ if (mTargetFrame != null) {
+ nodeFrame = RenderNode.create("FakeFrame", null);
+ nodeFrame.setClipToBounds(true);
+ mRenderer.addRenderNode(nodeFrame, false);
+ }
+
+ while (mRunning) {
+ // Get the surface position to draw to within our surface.
+ surfaceOrigin[0] = 0;
+ surfaceOrigin[1] = 0;
+ // This call should be done while the rendernode's displaylist is produced.
+ // For simplicity of this test we do this before we kick off the draw.
+ mContent.getLocationInSurface(surfaceOrigin);
+ mRenderer.setContentOverdrawProtectionBounds(surfaceOrigin[0], surfaceOrigin[1],
+ surfaceOrigin[0] + mContent.getWidth(),
+ surfaceOrigin[1] + mContent.getHeight());
+ // Determine new position for frame.
+ if (nodeFrame != null) {
+ surfaceOrigin[0] = 0;
+ surfaceOrigin[1] = 0;
+ mTargetFrame.getLocationInSurface(surfaceOrigin);
+ newBounds.set(surfaceOrigin[0], surfaceOrigin[1],
+ surfaceOrigin[0] + mTargetFrame.getWidth(),
+ surfaceOrigin[1] + mTargetFrame.getHeight());
+ if (!currentFrameBounds.equals(newBounds)) {
+ currentFrameBounds.set(newBounds);
+ nodeFrame.setLeftTopRightBottom(currentFrameBounds.left,
+ currentFrameBounds.top,
+ currentFrameBounds.right, currentFrameBounds.bottom);
+ }
+
+ // Draw frame
+ DisplayListCanvas canvas = nodeFrame.start(currentFrameBounds.width(),
+ currentFrameBounds.height());
+ mFrameContent.draw(canvas);
+ nodeFrame.end(canvas);
+ }
+
+ // Determine new position for backdrop
+ if (nodeBack != null) {
+ surfaceOrigin[0] = 0;
+ surfaceOrigin[1] = 0;
+ mTargetBack.getLocationInSurface(surfaceOrigin);
+ newBounds.set(surfaceOrigin[0], surfaceOrigin[1],
+ surfaceOrigin[0] + mTargetBack.getWidth(),
+ surfaceOrigin[1] + mTargetBack.getHeight());
+ if (!currentBackBounds.equals(newBounds)) {
+ currentBackBounds.set(newBounds);
+ nodeBack.setLeftTopRightBottom(currentBackBounds.left,
+ currentBackBounds.top,
+ currentBackBounds.right, currentBackBounds.bottom);
+ }
+
+ // Draw Backdrop
+ DisplayListCanvas canvas = nodeBack.start(currentBackBounds.width(),
+ currentBackBounds.height());
+ mBackContent.draw(canvas);
+ nodeBack.end(canvas);
+ }
+
+ // we need to only render one guy - the rest will happen automatically (I think).
+ if (nodeFrame != null) {
+ mRenderer.drawRenderNode(nodeFrame);
+ }
+ if (nodeBack != null) {
+ mRenderer.drawRenderNode(nodeBack);
+ }
+ try {
+ Thread.sleep(5);
+ } catch (InterruptedException e) {}
+ }
+ if (nodeFrame != null) {
+ mRenderer.removeRenderNode(nodeFrame);
+ }
+ if (nodeBack != null) {
+ mRenderer.removeRenderNode(nodeBack);
+ }
+ }
+
+ public void destroy() {
+ mRunning = false;
+ try {
+ join();
+ } catch (InterruptedException e) {}
+ }
+ }
+
+ private final static Runnable sBlockThread = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(DURATION);
+ } catch (InterruptedException e) {
+ }
+ }
+ };
+
+ static class ColorPulse extends Drawable {
+
+ private int mColorStart;
+ private int mColorEnd;
+ private int mStep;
+ private Rect mRect;
+ private Paint mPaint = new Paint();
+
+ public ColorPulse(int color1, int color2, Rect rect) {
+ mColorStart = color1;
+ mColorEnd = color2;
+ if (rect != null) {
+ mRect = new Rect(rect.left + BORDER_WIDTH / 2, rect.top + BORDER_WIDTH / 2,
+ rect.right - BORDER_WIDTH / 2, rect.bottom - BORDER_WIDTH / 2);
+ }
+ }
+
+ static int evaluate(float fraction, int startInt, int endInt) {
+ int startA = (startInt >> 24) & 0xff;
+ int startR = (startInt >> 16) & 0xff;
+ int startG = (startInt >> 8) & 0xff;
+ int startB = startInt & 0xff;
+
+ int endA = (endInt >> 24) & 0xff;
+ int endR = (endInt >> 16) & 0xff;
+ int endG = (endInt >> 8) & 0xff;
+ int endB = endInt & 0xff;
+
+ return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
+ (int)((startR + (int)(fraction * (endR - startR))) << 16) |
+ (int)((startG + (int)(fraction * (endG - startG))) << 8) |
+ (int)((startB + (int)(fraction * (endB - startB))));
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ float frac = mStep / 50.0f;
+ int color = evaluate(frac, mColorStart, mColorEnd);
+ if (mRect != null && !mRect.isEmpty()) {
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setStrokeWidth(BORDER_WIDTH);
+ mPaint.setColor(color);
+ canvas.drawRect(mRect, mPaint);
+ } else {
+ canvas.drawColor(color);
+ }
+
+ mStep++;
+ if (mStep >= 50) {
+ mStep = 0;
+ int tmp = mColorStart;
+ mColorStart = mColorEnd;
+ mColorEnd = tmp;
+ }
+ invalidateSelf();
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ }
+
+ @Override
+ public int getOpacity() {
+ return mRect == null || mRect.isEmpty() ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
+ }
+
+ }
+}
+
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
index 705cc34ff62b..2be99bed4bfb 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
@@ -21,10 +21,14 @@
<group>
<path
+ android:name="box0"
+ android:pathData="m0,0l480,0l0,480l-480,0l0-480z"
+ android:fillColor="@android:color/white" />
+ <path
android:name="box1"
android:pathData="m20,200l100,90l180-180l-35-35l-145,145l-60-60l-40,40z"
- android:fillColor="?android:attr/colorControlActivated"
- android:strokeColor="?android:attr/colorControlActivated"
+ android:fillColor="?android:attr/colorControlNormal"
+ android:strokeColor="?android:attr/colorControlNormal"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
</group>
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
index a23d81933749..85fc452add3e 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
@@ -18,7 +18,12 @@ import android.graphics.drawable.VectorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.GridLayout;
@SuppressWarnings({"UnusedDeclaration"})
@@ -55,6 +60,23 @@ public class VectorDrawable01 extends Activity {
container.setBackgroundColor(0xFF888888);
final Button []bArray = new Button[icon.length];
+ CheckBox toggle = new CheckBox(this);
+ toggle.setText("Toggle");
+ toggle.setChecked(true);
+ toggle.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ ViewGroup vg = (ViewGroup) buttonView.getParent();
+ for (int i = 0, count = vg.getChildCount(); i < count; i++) {
+ View child = vg.getChildAt(i);
+ if (child != buttonView) {
+ child.setEnabled(isChecked);
+ }
+ }
+ }
+ });
+ container.addView(toggle);
+
for (int i = 0; i < icon.length; i++) {
Button button = new Button(this);
bArray[i] = button;
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
index 163fbcb7f900..3b7bf8549181 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
@@ -48,9 +48,6 @@ import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Iterator;
-/**
- *
- */
public final class BridgeResources extends Resources {
private BridgeContext mContext;
@@ -278,7 +275,7 @@ public final class BridgeResources extends Resources {
* always Strings. The ideal signature for the method should be &lt;T super String&gt;, but java
* generics don't support it.
*/
- private <T extends CharSequence> T[] fillValues(ArrayResourceValue resValue, T[] values) {
+ <T extends CharSequence> T[] fillValues(ArrayResourceValue resValue, T[] values) {
int i = 0;
for (Iterator<String> iterator = resValue.iterator(); iterator.hasNext(); i++) {
@SuppressWarnings("unchecked")
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 6a6109047573..31dd3d943769 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -16,6 +16,7 @@
package android.content.res;
+import com.android.ide.common.rendering.api.ArrayResourceValue;
import com.android.ide.common.rendering.api.AttrResourceValue;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.RenderResources;
@@ -33,6 +34,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.annotation.Nullable;
+import android.content.res.Resources.NotFoundException;
import android.content.res.Resources.Theme;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
@@ -740,12 +742,20 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public CharSequence[] getTextArray(int index) {
- String value = getString(index);
- if (value != null) {
- return new CharSequence[] { value };
+ if (!hasValue(index)) {
+ return null;
}
-
- return null;
+ ResourceValue resVal = mResourceData[index];
+ if (resVal instanceof ArrayResourceValue) {
+ ArrayResourceValue array = (ArrayResourceValue) resVal;
+ int count = array.getElementCount();
+ return count >= 0 ? mBridgeResources.fillValues(array, new CharSequence[count]) : null;
+ }
+ int id = getResourceId(index, 0);
+ String resIdMessage = id > 0 ? " (resource id 0x" + Integer.toHexString(id) + ')' : "";
+ throw new NotFoundException(
+ String.format("%1$s in %2$s%3$s is not a valid array resource.",
+ resVal.getValue(), mNames[index], resIdMessage));
}
@Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 24e1ce7db7ec..2a4f58381aee 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -1050,11 +1050,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
}
if (scrollPos != 0) {
view.scrollBy(0, scrollPos);
- } else {
- view.scrollBy(0, scrollPos);
}
- } else {
- view.scrollBy(0, scrollPos);
}
if (!(view instanceof ViewGroup)) {
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 0d95b38feb46..23be8e076174 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -23,6 +23,7 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.ScanSettings;
import android.net.wifi.WifiChannel;
import android.net.wifi.ScanResult;
+import android.net.wifi.ScanInfo;
import android.net.wifi.WifiConnectionStatistics;
import android.net.wifi.WifiActivityEnergyInfo;
import android.net.Network;
@@ -70,6 +71,10 @@ interface IWifiManager
void disconnect();
+ List<ScanInfo> getScanInfos(String callingPackage);
+
+ void setOsuSelection(int osuID);
+
void reconnect();
void reassociate();
diff --git a/wifi/java/android/net/wifi/ScanInfo.aidl b/wifi/java/android/net/wifi/ScanInfo.aidl
new file mode 100644
index 000000000000..18ae5088146f
--- /dev/null
+++ b/wifi/java/android/net/wifi/ScanInfo.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+parcelable ScanInfo;
diff --git a/wifi/java/android/net/wifi/ScanInfo.java b/wifi/java/android/net/wifi/ScanInfo.java
new file mode 100644
index 000000000000..39186fa7a38a
--- /dev/null
+++ b/wifi/java/android/net/wifi/ScanInfo.java
@@ -0,0 +1,189 @@
+package android.net.wifi;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class ScanInfo implements Parcelable {
+ private final ScanResult mScanResult;
+
+ private final long mBSSID; // The BSSID of the best AP with an SSID matching the OSU
+ private final int mRSSI; // RSSI of the AP with BSSID
+ private final String mSSID; // The SSID to connect to for an OSU connection.
+ private final String mName;
+ private final String mServiceDescription;
+ private final String mIconType;
+ private final byte[] mIconData;
+ private final int mOSUIdentity;
+
+ public ScanInfo(ScanResult scanResult) {
+ mScanResult = scanResult;
+
+ mBSSID = -1;
+ mRSSI = -1;
+ mSSID = null;
+ mName = null;
+ mServiceDescription = null;
+ mIconType = null;
+ mIconData = null;
+ mOSUIdentity = -1;
+ }
+
+ public ScanInfo(long BSSID, int rssi, String SSID, String name, String serviceDescription,
+ String iconType, byte[] iconData, int OSUIdentity) {
+ mBSSID = BSSID;
+ mRSSI = rssi;
+ mSSID = SSID;
+ mName = name;
+ mServiceDescription = serviceDescription;
+ mIconType = iconType;
+ mIconData = iconData;
+ mOSUIdentity = OSUIdentity;
+
+ mScanResult = null;
+ }
+
+ /**
+ * Get the scan result of this ScanInfo.
+ * @return The ScanResult, if this ScanInfo contains a one. If the ScanInfo contains
+ * OSU information getScanResult will return null.
+ */
+ public ScanResult getScanResult() {
+ return mScanResult;
+ }
+
+ /**
+ * OSU only: The BSSID of the AP who advertises the OSU SSID. This value is not guaranteed to
+ * be correct; In the somewhat unlikely case that multiple APs advertise OSU SSIDs that matches
+ * an OSU information element returned through ANQP and one of those is not related to an OSU
+ * there is a (slight) risk that the BSSID is for a "spoof" OSU.
+ * The matching algorithm that produces the ScanInfo objects makes a best effort to get the
+ * matching right though and since it is (a) fair to assume that the OSU SSID resides on the
+ * same AP as the one advertising the OSU information, and (b) BSSIDs for multi-SSID APs are
+ * typically adjacent to each other, matching will prefer the BSSID closest to the advertising
+ * APs BSSID if multiple SSIDs match.
+ * @return The BSSID.
+ */
+ public long getBssid() {
+ return mBSSID;
+ }
+
+ /**
+ * OSU only.
+ * @return The signal level of the AP associated with the BSSID from getBSSID.
+ */
+ public int getRssi() {
+ return mRSSI;
+ }
+
+ /**
+ * OSU only.
+ * @return The SSID of the AP to which to associate to establish an OSU connection.
+ */
+ public String getSsid() {
+ return mSSID;
+ }
+
+ /**
+ * OSU only.
+ * @return The name of the Service Provider of the OSU.
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * OSU only.
+ * @return The service description of the OSU.
+ */
+ public String getServiceDescription() {
+ return mServiceDescription;
+ }
+
+ /**
+ * OSU only.
+ * Get the type of icon that icon data represents, e.g. JPG, PNG etc. This field is formatted
+ * using standard MIME encodings per RFC-4288 and IANA MIME media types.
+ * @return The icon type in icon data.
+ */
+ public String getIconType() {
+ return mIconType;
+ }
+
+ /**
+ * OSU only.
+ * @return The binary data of the icon.
+ */
+ public byte[] getIconData() {
+ return mIconData;
+ }
+
+ /**
+ * OSU only.
+ * @return a unique identity for the OSU. This value is generated by the framework and should
+ * be used to uniquely identify a specific OSU. Please note that values may be reused after
+ * a very long time-span (in any normal scenario, likely years) and implementations should make
+ * sure to not rely on any long term persisted values.
+ */
+ public int getOsuIdentity() {
+ return mOSUIdentity;
+ }
+
+ private static final int ScanResultMarker = 0;
+ private static final int OSUMarker = 1;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Creator<ScanInfo> CREATOR =
+ new Creator<ScanInfo>() {
+ @Override
+ public ScanInfo createFromParcel(Parcel source) {
+ int marker = source.readInt();
+ if (marker == ScanResultMarker) {
+ return new ScanInfo(ScanResult.CREATOR.createFromParcel(source));
+ }
+ else if (marker == OSUMarker) {
+ return new ScanInfo(
+ source.readLong(),
+ source.readInt(),
+ source.readString(),
+ source.readString(),
+ source.readString(),
+ source.readString(),
+ source.createByteArray(),
+ source.readInt()
+ );
+ }
+ else {
+ throw new RuntimeException("Bad ScanInfo data");
+ }
+ }
+
+ @Override
+ public ScanInfo[] newArray(int size) {
+ return new ScanInfo[0];
+ }
+ };
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (mScanResult != null) {
+ dest.writeInt(ScanResultMarker);
+ mScanResult.writeToParcel(dest, flags);
+ return;
+ }
+
+ dest.writeInt(OSUMarker);
+ dest.writeLong(mBSSID);
+ dest.writeInt(mRSSI);
+ dest.writeString(mSSID);
+ dest.writeString(mName);
+ dest.writeString(mServiceDescription);
+ dest.writeString(mIconType);
+ dest.writeByteArray(mIconData);
+ dest.writeInt(mOSUIdentity);
+ }
+}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index cf88df42f8d3..ff8d6d4d09aa 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1315,6 +1315,30 @@ public class WifiManager {
}
/**
+ * An augmented version of getScanResults that returns ScanResults as well as OSU information
+ * wrapped in ScanInfo objects.
+ * @return
+ */
+ public List<ScanInfo> getScanInfos() {
+ try {
+ return mService.getScanInfos(mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Notify the OSU framework about the currently selected OSU.
+ * @param osuID The OSU ID from ScanInfo.getOsuIdentity()
+ */
+ public void setOsuSelection(int osuID) {
+ try {
+ mService.setOsuSelection(osuID);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Check if scanning is always available.
*
* If this return {@code true}, apps can issue {@link #startScan} and fetch scan results