diff options
| -rw-r--r-- | Android.mk | 3 | ||||
| -rw-r--r-- | CleanSpec.mk | 2 | ||||
| -rw-r--r-- | api/current.txt | 18 | ||||
| -rw-r--r-- | cmds/am/src/com/android/commands/am/Am.java | 96 | ||||
| -rw-r--r-- | core/java/android/app/ActivityManager.java | 101 | ||||
| -rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 160 | ||||
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 16 | ||||
| -rw-r--r-- | core/java/android/app/ActivityView.java | 281 | ||||
| -rw-r--r-- | core/java/android/app/IActivityContainer.aidl | 35 | ||||
| -rw-r--r-- | core/java/android/app/IActivityContainerCallback.aidl | 24 | ||||
| -rw-r--r-- | core/java/android/app/IActivityManager.java | 27 | ||||
| -rw-r--r-- | core/java/android/app/IWallpaperManager.aidl | 10 | ||||
| -rw-r--r-- | core/java/android/app/Notification.java | 21 | ||||
| -rw-r--r-- | core/java/android/bluetooth/BluetoothAdapter.java | 210 | ||||
| -rw-r--r-- | core/java/android/bluetooth/BluetoothAdvScanData.java | 147 | ||||
| -rw-r--r-- | core/java/android/bluetooth/BluetoothGatt.java | 73 | ||||
| -rw-r--r-- | core/java/android/bluetooth/BluetoothGattServer.java | 2 | ||||
| -rw-r--r-- | core/java/android/bluetooth/BluetoothGattService.java | 23 | ||||
| -rw-r--r-- | core/java/android/bluetooth/BluetoothInputDevice.java | 12 | ||||
| -rw-r--r-- | core/java/android/bluetooth/BluetoothSocket.java | 27 | ||||
| -rw-r--r-- | core/java/android/bluetooth/BluetoothUuid.java | 16 | ||||
| -rw-r--r-- | core/java/android/bluetooth/IBluetoothGatt.aidl | 15 | ||||
| -rw-r--r-- | core/java/android/bluetooth/IBluetoothGattCallback.aidl | 1 | ||||
| -rw-r--r-- | core/java/android/content/Intent.java | 5 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageManager.java | 23 | ||||
| -rw-r--r-- | core/java/android/database/sqlite/SQLiteDatabase.java | 10 | ||||
| -rw-r--r-- | core/java/android/hardware/display/DisplayManager.java | 21 | ||||
| -rw-r--r-- | core/java/android/hardware/display/DisplayManagerInternal.java | 109 | ||||
| -rw-r--r-- | core/java/android/hardware/display/DisplayViewport.java (renamed from services/java/com/android/server/display/DisplayViewport.java) | 4 | ||||
| -rw-r--r-- | core/java/android/hardware/input/InputManagerInternal.java | 36 | ||||
| -rw-r--r-- | core/java/android/net/ConnectivityManager.java | 12 | ||||
| -rw-r--r-- | core/java/android/net/ProxyDataTracker.java | 204 | ||||
| -rw-r--r-- | core/java/android/os/FactoryTest.java | 14 | ||||
| -rw-r--r-- | core/java/android/os/PowerManager.java | 13 | ||||
| -rw-r--r-- | core/java/android/os/PowerManagerInternal.java | 60 | ||||
| -rw-r--r-- | core/java/android/os/Process.java | 13 | ||||
| -rw-r--r-- | core/java/android/service/dreams/DozeHardware.java | 77 | ||||
| -rw-r--r-- | core/java/android/service/dreams/DreamManagerInternal.java | 39 | ||||
| -rw-r--r-- | core/java/android/service/dreams/DreamService.java | 294 | ||||
| -rw-r--r-- | core/java/android/service/dreams/IDozeHardware.aidl (renamed from services/java/com/android/server/display/DisplayTransactionListener.java) | 12 | ||||
| -rw-r--r-- | core/java/android/service/dreams/IDreamManager.aidl | 6 | ||||
| -rw-r--r-- | core/java/android/service/dreams/IDreamService.aidl | 2 | ||||
| -rw-r--r-- | core/java/android/service/notification/NotificationListenerService.java | 11 | ||||
| -rw-r--r-- | core/java/android/util/TypedValue.java | 16 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceControl.java | 72 | ||||
| -rw-r--r-- | core/java/android/view/WindowManagerInternal.java | 33 | ||||
| -rw-r--r-- | core/java/android/view/WindowManagerPolicy.java | 22 | ||||
| -rw-r--r-- | core/java/android/view/accessibility/AccessibilityManager.java | 40 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/BatteryStatsImpl.java | 9 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/BinderInternal.java | 7 | ||||
| -rw-r--r-- | core/java/com/android/internal/view/menu/ActionMenuPresenter.java | 36 | ||||
| -rw-r--r-- | core/java/com/android/server/LocalServices.java | 60 | ||||
| -rw-r--r-- | core/java/com/android/server/SystemService.java | 218 | ||||
| -rw-r--r-- | core/java/com/android/server/SystemServiceManager.java | 164 | ||||
| -rw-r--r-- | core/jni/android_opengl_EGL14.cpp | 2 | ||||
| -rw-r--r-- | core/jni/android_util_Process.cpp | 18 | ||||
| -rw-r--r-- | core/res/AndroidManifest.xml | 8 | ||||
| -rw-r--r-- | core/res/res/values/config.xml | 79 | ||||
| -rw-r--r-- | core/res/res/values/styles_micro.xml | 22 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 8 | ||||
| -rw-r--r-- | core/res/res/values/themes_micro.xml | 27 | ||||
| -rw-r--r-- | libs/common_time/Android.mk (renamed from services/common_time/Android.mk) | 0 | ||||
| -rw-r--r-- | libs/common_time/clock_recovery.cpp (renamed from services/common_time/clock_recovery.cpp) | 0 | ||||
| -rw-r--r-- | libs/common_time/clock_recovery.h (renamed from services/common_time/clock_recovery.h) | 0 | ||||
| -rw-r--r-- | libs/common_time/common_clock.cpp (renamed from services/common_time/common_clock.cpp) | 0 | ||||
| -rw-r--r-- | libs/common_time/common_clock.h (renamed from services/common_time/common_clock.h) | 0 | ||||
| -rw-r--r-- | libs/common_time/common_clock_service.cpp (renamed from services/common_time/common_clock_service.cpp) | 0 | ||||
| -rw-r--r-- | libs/common_time/common_clock_service.h (renamed from services/common_time/common_clock_service.h) | 0 | ||||
| -rw-r--r-- | libs/common_time/common_time_config_service.cpp (renamed from services/common_time/common_time_config_service.cpp) | 0 | ||||
| -rw-r--r-- | libs/common_time/common_time_config_service.h (renamed from services/common_time/common_time_config_service.h) | 0 | ||||
| -rw-r--r-- | libs/common_time/common_time_server.cpp (renamed from services/common_time/common_time_server.cpp) | 0 | ||||
| -rw-r--r-- | libs/common_time/common_time_server.h (renamed from services/common_time/common_time_server.h) | 0 | ||||
| -rw-r--r-- | libs/common_time/common_time_server_api.cpp (renamed from services/common_time/common_time_server_api.cpp) | 0 | ||||
| -rw-r--r-- | libs/common_time/common_time_server_packets.cpp (renamed from services/common_time/common_time_server_packets.cpp) | 0 | ||||
| -rw-r--r-- | libs/common_time/common_time_server_packets.h (renamed from services/common_time/common_time_server_packets.h) | 0 | ||||
| -rw-r--r-- | libs/common_time/diag_thread.cpp (renamed from services/common_time/diag_thread.cpp) | 0 | ||||
| -rw-r--r-- | libs/common_time/diag_thread.h (renamed from services/common_time/diag_thread.h) | 0 | ||||
| -rw-r--r-- | libs/common_time/main.cpp (renamed from services/common_time/main.cpp) | 0 | ||||
| -rw-r--r-- | libs/common_time/utils.cpp (renamed from services/common_time/utils.cpp) | 0 | ||||
| -rw-r--r-- | libs/common_time/utils.h (renamed from services/common_time/utils.h) | 0 | ||||
| -rw-r--r-- | libs/input/Android.mk (renamed from services/input/Android.mk) | 0 | ||||
| -rw-r--r-- | libs/input/EventHub.cpp (renamed from services/input/EventHub.cpp) | 0 | ||||
| -rw-r--r-- | libs/input/EventHub.h (renamed from services/input/EventHub.h) | 0 | ||||
| -rw-r--r-- | libs/input/InputApplication.cpp (renamed from services/input/InputApplication.cpp) | 0 | ||||
| -rw-r--r-- | libs/input/InputApplication.h (renamed from services/input/InputApplication.h) | 0 | ||||
| -rw-r--r-- | libs/input/InputDispatcher.cpp (renamed from services/input/InputDispatcher.cpp) | 190 | ||||
| -rw-r--r-- | libs/input/InputDispatcher.h (renamed from services/input/InputDispatcher.h) | 9 | ||||
| -rw-r--r-- | libs/input/InputListener.cpp (renamed from services/input/InputListener.cpp) | 0 | ||||
| -rw-r--r-- | libs/input/InputListener.h (renamed from services/input/InputListener.h) | 0 | ||||
| -rw-r--r-- | libs/input/InputManager.cpp (renamed from services/input/InputManager.cpp) | 0 | ||||
| -rw-r--r-- | libs/input/InputManager.h (renamed from services/input/InputManager.h) | 0 | ||||
| -rw-r--r-- | libs/input/InputReader.cpp (renamed from services/input/InputReader.cpp) | 0 | ||||
| -rw-r--r-- | libs/input/InputReader.h (renamed from services/input/InputReader.h) | 0 | ||||
| -rw-r--r-- | libs/input/InputWindow.cpp (renamed from services/input/InputWindow.cpp) | 0 | ||||
| -rw-r--r-- | libs/input/InputWindow.h (renamed from services/input/InputWindow.h) | 0 | ||||
| -rw-r--r-- | libs/input/PointerController.cpp (renamed from services/input/PointerController.cpp) | 0 | ||||
| -rw-r--r-- | libs/input/PointerController.h (renamed from services/input/PointerController.h) | 0 | ||||
| -rw-r--r-- | libs/input/SpriteController.cpp (renamed from services/input/SpriteController.cpp) | 0 | ||||
| -rw-r--r-- | libs/input/SpriteController.h (renamed from services/input/SpriteController.h) | 0 | ||||
| -rw-r--r-- | libs/input/tests/Android.mk (renamed from services/input/tests/Android.mk) | 0 | ||||
| -rw-r--r-- | libs/input/tests/InputDispatcher_test.cpp (renamed from services/input/tests/InputDispatcher_test.cpp) | 39 | ||||
| -rw-r--r-- | libs/input/tests/InputReader_test.cpp (renamed from services/input/tests/InputReader_test.cpp) | 0 | ||||
| -rw-r--r-- | packages/Keyguard/Android.mk | 2 | ||||
| -rw-r--r-- | policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java | 3 | ||||
| -rw-r--r-- | policy/src/com/android/internal/policy/impl/PhoneWindowManager.java | 43 | ||||
| -rw-r--r-- | policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java | 3 | ||||
| -rw-r--r-- | services/Android.mk | 64 | ||||
| -rw-r--r-- | services/accessibility/Android.mk | 10 | ||||
| -rw-r--r-- | services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java (renamed from services/java/com/android/server/accessibility/AccessibilityInputFilter.java) | 0 | ||||
| -rw-r--r-- | services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java (renamed from services/java/com/android/server/accessibility/AccessibilityManagerService.java) | 0 | ||||
| -rw-r--r-- | services/accessibility/java/com/android/server/accessibility/EventStreamTransformation.java (renamed from services/java/com/android/server/accessibility/EventStreamTransformation.java) | 0 | ||||
| -rw-r--r-- | services/accessibility/java/com/android/server/accessibility/GestureUtils.java (renamed from services/java/com/android/server/accessibility/GestureUtils.java) | 0 | ||||
| -rw-r--r-- | services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java (renamed from services/java/com/android/server/accessibility/ScreenMagnifier.java) | 0 | ||||
| -rw-r--r-- | services/accessibility/java/com/android/server/accessibility/TouchExplorer.java (renamed from services/java/com/android/server/accessibility/TouchExplorer.java) | 0 | ||||
| -rw-r--r-- | services/appwidget/Android.mk | 10 | ||||
| -rw-r--r-- | services/appwidget/java/com/android/server/appwidget/AppWidgetService.java | 384 | ||||
| -rw-r--r-- | services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java (renamed from services/java/com/android/server/AppWidgetServiceImpl.java) | 2 | ||||
| -rw-r--r-- | services/backup/Android.mk | 12 | ||||
| -rw-r--r-- | services/backup/java/com/android/server/backup/BackupManagerService.java (renamed from services/java/com/android/server/BackupManagerService.java) | 31 | ||||
| -rw-r--r-- | services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java (renamed from services/java/com/android/server/PackageManagerBackupAgent.java) | 2 | ||||
| -rw-r--r-- | services/backup/java/com/android/server/backup/SystemBackupAgent.java (renamed from services/java/com/android/server/SystemBackupAgent.java) | 48 | ||||
| -rw-r--r-- | services/core/Android.mk | 14 | ||||
| -rw-r--r-- | services/core/java/com/android/server/AlarmManagerService.java (renamed from services/java/com/android/server/AlarmManagerService.java) | 579 | ||||
| -rw-r--r-- | services/core/java/com/android/server/AppOpsService.java (renamed from services/java/com/android/server/AppOpsService.java) | 4 | ||||
| -rw-r--r-- | services/core/java/com/android/server/AssetAtlasService.java (renamed from services/java/com/android/server/AssetAtlasService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/AttributeCache.java (renamed from services/java/com/android/server/AttributeCache.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/BatteryService.java (renamed from services/java/com/android/server/BatteryService.java) | 33 | ||||
| -rw-r--r-- | services/core/java/com/android/server/BluetoothManagerService.java (renamed from services/java/com/android/server/BluetoothManagerService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/BootReceiver.java (renamed from services/java/com/android/server/BootReceiver.java) | 7 | ||||
| -rw-r--r-- | services/core/java/com/android/server/BrickReceiver.java (renamed from services/java/com/android/server/BrickReceiver.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/CertBlacklister.java (renamed from services/java/com/android/server/CertBlacklister.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/CommonTimeManagementService.java (renamed from services/java/com/android/server/CommonTimeManagementService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/ConnectivityService.java (renamed from services/java/com/android/server/ConnectivityService.java) | 4 | ||||
| -rw-r--r-- | services/core/java/com/android/server/ConsumerIrService.java (renamed from services/java/com/android/server/ConsumerIrService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/CountryDetectorService.java (renamed from services/java/com/android/server/CountryDetectorService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/DiskStatsService.java (renamed from services/java/com/android/server/DiskStatsService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/DisplayThread.java | 56 | ||||
| -rw-r--r-- | services/core/java/com/android/server/DockObserver.java (renamed from services/java/com/android/server/DockObserver.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/DropBoxManagerService.java (renamed from services/java/com/android/server/DropBoxManagerService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/EntropyMixer.java (renamed from services/java/com/android/server/EntropyMixer.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/EventLogTags.logtags (renamed from services/java/com/android/server/EventLogTags.logtags) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/FgThread.java (renamed from services/java/com/android/server/FgThread.java) | 11 | ||||
| -rw-r--r-- | services/core/java/com/android/server/INativeDaemonConnectorCallbacks.java (renamed from services/java/com/android/server/INativeDaemonConnectorCallbacks.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/IdleMaintenanceService.java (renamed from services/java/com/android/server/IdleMaintenanceService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/InputMethodManagerService.java (renamed from services/java/com/android/server/InputMethodManagerService.java) | 2 | ||||
| -rw-r--r-- | services/core/java/com/android/server/IntentResolver.java (renamed from services/java/com/android/server/IntentResolver.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/IoThread.java (renamed from services/java/com/android/server/IoThread.java) | 11 | ||||
| -rw-r--r-- | services/core/java/com/android/server/LocationManagerService.java (renamed from services/java/com/android/server/LocationManagerService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/LockSettingsService.java (renamed from services/java/com/android/server/LockSettingsService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/MasterClearReceiver.java (renamed from services/java/com/android/server/MasterClearReceiver.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/MountService.java (renamed from services/java/com/android/server/MountService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/NativeDaemonConnector.java (renamed from services/java/com/android/server/NativeDaemonConnector.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/NativeDaemonConnectorException.java (renamed from services/java/com/android/server/NativeDaemonConnectorException.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/NativeDaemonEvent.java (renamed from services/java/com/android/server/NativeDaemonEvent.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/NetworkManagementService.java (renamed from services/java/com/android/server/NetworkManagementService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/NetworkTimeUpdateService.java (renamed from services/java/com/android/server/NetworkTimeUpdateService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/NsdService.java (renamed from services/java/com/android/server/NsdService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/RandomBlock.java (renamed from services/java/com/android/server/RandomBlock.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/RecognitionManagerService.java (renamed from services/java/com/android/server/RecognitionManagerService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/SamplingProfilerService.java (renamed from services/java/com/android/server/SamplingProfilerService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/SerialService.java (renamed from services/java/com/android/server/SerialService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/ServiceThread.java | 48 | ||||
| -rw-r--r-- | services/core/java/com/android/server/ServiceWatcher.java (renamed from services/java/com/android/server/ServiceWatcher.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/ShutdownActivity.java (renamed from services/java/com/android/server/ShutdownActivity.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/TelephonyRegistry.java (renamed from services/java/com/android/server/TelephonyRegistry.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/TextServicesManagerService.java (renamed from services/java/com/android/server/TextServicesManagerService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/TwilightCalculator.java (renamed from services/java/com/android/server/TwilightCalculator.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/UiModeManagerService.java (renamed from services/java/com/android/server/UiModeManagerService.java) | 290 | ||||
| -rw-r--r-- | services/core/java/com/android/server/UiThread.java (renamed from services/java/com/android/server/UiThread.java) | 20 | ||||
| -rw-r--r-- | services/core/java/com/android/server/UpdateLockService.java (renamed from services/java/com/android/server/UpdateLockService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/VibratorService.java (renamed from services/java/com/android/server/VibratorService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/Watchdog.java (renamed from services/java/com/android/server/Watchdog.java) | 33 | ||||
| -rw-r--r-- | services/core/java/com/android/server/WiredAccessoryManager.java (renamed from services/java/com/android/server/WiredAccessoryManager.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/accounts/AccountAuthenticatorCache.java (renamed from services/java/com/android/server/accounts/AccountAuthenticatorCache.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/accounts/AccountManagerService.java (renamed from services/java/com/android/server/accounts/AccountManagerService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/accounts/IAccountAuthenticatorCache.java (renamed from services/java/com/android/server/accounts/IAccountAuthenticatorCache.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActiveServices.java (renamed from services/java/com/android/server/am/ActiveServices.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java (renamed from services/java/com/android/server/am/ActivityManagerService.java) | 451 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityRecord.java (renamed from services/java/com/android/server/am/ActivityRecord.java) | 9 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityResult.java (renamed from services/java/com/android/server/am/ActivityResult.java) | 0 | ||||
| -rwxr-xr-x | services/core/java/com/android/server/am/ActivityStack.java (renamed from services/java/com/android/server/am/ActivityStack.java) | 193 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityStackSupervisor.java (renamed from services/java/com/android/server/am/ActivityStackSupervisor.java) | 1256 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/AppBindRecord.java (renamed from services/java/com/android/server/am/AppBindRecord.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/AppErrorDialog.java (renamed from services/java/com/android/server/am/AppErrorDialog.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/AppErrorResult.java (renamed from services/java/com/android/server/am/AppErrorResult.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/AppNotRespondingDialog.java (renamed from services/java/com/android/server/am/AppNotRespondingDialog.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java (renamed from services/java/com/android/server/am/AppWaitingForDebuggerDialog.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/BackupRecord.java (renamed from services/java/com/android/server/am/BackupRecord.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/BaseErrorDialog.java (renamed from services/java/com/android/server/am/BaseErrorDialog.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/BatteryStatsService.java (renamed from services/java/com/android/server/am/BatteryStatsService.java) | 5 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/BroadcastFilter.java (renamed from services/java/com/android/server/am/BroadcastFilter.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/BroadcastQueue.java (renamed from services/java/com/android/server/am/BroadcastQueue.java) | 15 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/BroadcastRecord.java (renamed from services/java/com/android/server/am/BroadcastRecord.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/CompatModeDialog.java (renamed from services/java/com/android/server/am/CompatModeDialog.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/CompatModePackages.java (renamed from services/java/com/android/server/am/CompatModePackages.java) | 34 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ConnectionRecord.java (renamed from services/java/com/android/server/am/ConnectionRecord.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ContentProviderConnection.java (renamed from services/java/com/android/server/am/ContentProviderConnection.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ContentProviderRecord.java (renamed from services/java/com/android/server/am/ContentProviderRecord.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/CoreSettingsObserver.java (renamed from services/java/com/android/server/am/CoreSettingsObserver.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/EventLogTags.logtags (renamed from services/java/com/android/server/am/EventLogTags.logtags) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/FactoryErrorDialog.java (renamed from services/java/com/android/server/am/FactoryErrorDialog.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/IntentBindRecord.java (renamed from services/java/com/android/server/am/IntentBindRecord.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/LaunchWarningWindow.java (renamed from services/java/com/android/server/am/LaunchWarningWindow.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/NativeCrashListener.java (renamed from services/java/com/android/server/am/NativeCrashListener.java) | 4 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/PendingIntentRecord.java (renamed from services/java/com/android/server/am/PendingIntentRecord.java) | 10 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/PendingThumbnailsRecord.java (renamed from services/java/com/android/server/am/PendingThumbnailsRecord.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ProcessList.java (renamed from services/java/com/android/server/am/ProcessList.java) | 135 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ProcessMemInfo.java (renamed from services/java/com/android/server/am/ProcessMemInfo.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ProcessRecord.java (renamed from services/java/com/android/server/am/ProcessRecord.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ProcessStatsService.java (renamed from services/java/com/android/server/am/ProcessStatsService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ProviderMap.java (renamed from services/java/com/android/server/am/ProviderMap.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ReceiverList.java (renamed from services/java/com/android/server/am/ReceiverList.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ServiceRecord.java (renamed from services/java/com/android/server/am/ServiceRecord.java) | 9 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/StrictModeViolationDialog.java (renamed from services/java/com/android/server/am/StrictModeViolationDialog.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/TaskAccessInfo.java (renamed from services/java/com/android/server/am/TaskAccessInfo.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/TaskRecord.java (renamed from services/java/com/android/server/am/TaskRecord.java) | 26 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ThumbnailHolder.java (renamed from services/java/com/android/server/am/ThumbnailHolder.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/UriPermission.java (renamed from services/java/com/android/server/am/UriPermission.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/UriPermissionOwner.java (renamed from services/java/com/android/server/am/UriPermissionOwner.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/UsageStatsService.java (renamed from services/java/com/android/server/am/UsageStatsService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/UserStartedState.java (renamed from services/java/com/android/server/am/UserStartedState.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/package.html (renamed from services/java/com/android/server/am/package.html) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/clipboard/ClipboardService.java (renamed from services/java/com/android/server/ClipboardService.java) | 2 | ||||
| -rw-r--r-- | services/core/java/com/android/server/connectivity/DataConnectionStats.java (renamed from services/java/com/android/server/connectivity/DataConnectionStats.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/connectivity/Nat464Xlat.java (renamed from services/java/com/android/server/connectivity/Nat464Xlat.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/connectivity/PacManager.java (renamed from services/java/com/android/server/connectivity/PacManager.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/connectivity/Tethering.java (renamed from services/java/com/android/server/connectivity/Tethering.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/connectivity/Vpn.java (renamed from services/java/com/android/server/connectivity/Vpn.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/content/ContentService.java (renamed from services/java/com/android/server/content/ContentService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/content/SyncManager.java (renamed from services/java/com/android/server/content/SyncManager.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/content/SyncOperation.java (renamed from services/java/com/android/server/content/SyncOperation.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/content/SyncQueue.java (renamed from services/java/com/android/server/content/SyncQueue.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/content/SyncStorageEngine.java (renamed from services/java/com/android/server/content/SyncStorageEngine.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/display/DisplayAdapter.java (renamed from services/java/com/android/server/display/DisplayAdapter.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/display/DisplayDevice.java (renamed from services/java/com/android/server/display/DisplayDevice.java) | 1 | ||||
| -rw-r--r-- | services/core/java/com/android/server/display/DisplayDeviceInfo.java (renamed from services/java/com/android/server/display/DisplayDeviceInfo.java) | 11 | ||||
| -rw-r--r-- | services/core/java/com/android/server/display/DisplayManagerService.java (renamed from services/java/com/android/server/display/DisplayManagerService.java) | 933 | ||||
| -rw-r--r-- | services/core/java/com/android/server/display/LocalDisplayAdapter.java (renamed from services/java/com/android/server/display/LocalDisplayAdapter.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/display/LogicalDisplay.java (renamed from services/java/com/android/server/display/LogicalDisplay.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/display/OverlayDisplayAdapter.java (renamed from services/java/com/android/server/display/OverlayDisplayAdapter.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/display/OverlayDisplayWindow.java (renamed from services/java/com/android/server/display/OverlayDisplayWindow.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/display/PersistentDataStore.java (renamed from services/java/com/android/server/display/PersistentDataStore.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/display/VirtualDisplayAdapter.java (renamed from services/java/com/android/server/display/VirtualDisplayAdapter.java) | 7 | ||||
| -rw-r--r-- | services/core/java/com/android/server/display/WifiDisplayAdapter.java (renamed from services/java/com/android/server/display/WifiDisplayAdapter.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/display/WifiDisplayController.java (renamed from services/java/com/android/server/display/WifiDisplayController.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/dreams/DreamController.java (renamed from services/java/com/android/server/dreams/DreamController.java) | 19 | ||||
| -rw-r--r-- | services/core/java/com/android/server/dreams/DreamManagerService.java | 655 | ||||
| -rw-r--r-- | services/core/java/com/android/server/dreams/McuHal.java | 46 | ||||
| -rw-r--r-- | services/core/java/com/android/server/firewall/AndFilter.java (renamed from services/java/com/android/server/firewall/AndFilter.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/firewall/CategoryFilter.java (renamed from services/java/com/android/server/firewall/CategoryFilter.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/firewall/Filter.java (renamed from services/java/com/android/server/firewall/Filter.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/firewall/FilterFactory.java (renamed from services/java/com/android/server/firewall/FilterFactory.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/firewall/FilterList.java (renamed from services/java/com/android/server/firewall/FilterList.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/firewall/IntentFirewall.java (renamed from services/java/com/android/server/firewall/IntentFirewall.java) | 12 | ||||
| -rw-r--r-- | services/core/java/com/android/server/firewall/NotFilter.java (renamed from services/java/com/android/server/firewall/NotFilter.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/firewall/OrFilter.java (renamed from services/java/com/android/server/firewall/OrFilter.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/firewall/PortFilter.java (renamed from services/java/com/android/server/firewall/PortFilter.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/firewall/SenderFilter.java (renamed from services/java/com/android/server/firewall/SenderFilter.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/firewall/SenderPermissionFilter.java (renamed from services/java/com/android/server/firewall/SenderPermissionFilter.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/firewall/StringFilter.java (renamed from services/java/com/android/server/firewall/StringFilter.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/input/InputApplicationHandle.java (renamed from services/java/com/android/server/input/InputApplicationHandle.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/input/InputManagerService.java (renamed from services/java/com/android/server/input/InputManagerService.java) | 48 | ||||
| -rw-r--r-- | services/core/java/com/android/server/input/InputWindowHandle.java (renamed from services/java/com/android/server/input/InputWindowHandle.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/input/PersistentDataStore.java (renamed from services/java/com/android/server/input/PersistentDataStore.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/lights/Light.java | 41 | ||||
| -rw-r--r-- | services/core/java/com/android/server/lights/LightsManager.java | 31 | ||||
| -rw-r--r-- | services/core/java/com/android/server/lights/LightsService.java (renamed from services/java/com/android/server/LightsService.java) | 92 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/ComprehensiveCountryDetector.java (renamed from services/java/com/android/server/location/ComprehensiveCountryDetector.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/CountryDetectorBase.java (renamed from services/java/com/android/server/location/CountryDetectorBase.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/FlpHardwareProvider.java (renamed from services/java/com/android/server/location/FlpHardwareProvider.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/FusedLocationHardwareSecure.java (renamed from services/java/com/android/server/location/FusedLocationHardwareSecure.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/FusedProxy.java (renamed from services/java/com/android/server/location/FusedProxy.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/GeocoderProxy.java (renamed from services/java/com/android/server/location/GeocoderProxy.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/GeofenceManager.java (renamed from services/java/com/android/server/location/GeofenceManager.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/GeofenceProxy.java (renamed from services/java/com/android/server/location/GeofenceProxy.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/GeofenceState.java (renamed from services/java/com/android/server/location/GeofenceState.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/GpsLocationProvider.java (renamed from services/java/com/android/server/location/GpsLocationProvider.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/GpsXtraDownloader.java (renamed from services/java/com/android/server/location/GpsXtraDownloader.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/LocationBasedCountryDetector.java (renamed from services/java/com/android/server/location/LocationBasedCountryDetector.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/LocationBlacklist.java (renamed from services/java/com/android/server/location/LocationBlacklist.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/LocationFudger.java (renamed from services/java/com/android/server/location/LocationFudger.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/LocationProviderInterface.java (renamed from services/java/com/android/server/location/LocationProviderInterface.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/LocationProviderProxy.java (renamed from services/java/com/android/server/location/LocationProviderProxy.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/MockProvider.java (renamed from services/java/com/android/server/location/MockProvider.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/PassiveProvider.java (renamed from services/java/com/android/server/location/PassiveProvider.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/media/MediaRouterService.java (renamed from services/java/com/android/server/media/MediaRouterService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/media/RemoteDisplayProviderProxy.java (renamed from services/java/com/android/server/media/RemoteDisplayProviderProxy.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/media/RemoteDisplayProviderWatcher.java (renamed from services/java/com/android/server/media/RemoteDisplayProviderWatcher.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/net/LockdownVpnTracker.java (renamed from services/java/com/android/server/net/LockdownVpnTracker.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/net/NetworkIdentitySet.java (renamed from services/java/com/android/server/net/NetworkIdentitySet.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/net/NetworkPolicyManagerService.java (renamed from services/java/com/android/server/net/NetworkPolicyManagerService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/net/NetworkStatsCollection.java (renamed from services/java/com/android/server/net/NetworkStatsCollection.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/net/NetworkStatsRecorder.java (renamed from services/java/com/android/server/net/NetworkStatsRecorder.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/net/NetworkStatsService.java (renamed from services/java/com/android/server/net/NetworkStatsService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/notification/NotificationDelegate.java | 27 | ||||
| -rw-r--r-- | services/core/java/com/android/server/notification/NotificationManagerInternal.java | 24 | ||||
| -rw-r--r-- | services/core/java/com/android/server/notification/NotificationManagerService.java (renamed from services/java/com/android/server/NotificationManagerService.java) | 1244 | ||||
| -rw-r--r-- | services/core/java/com/android/server/os/SchedulingPolicyService.java (renamed from services/java/com/android/server/os/SchedulingPolicyService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/BasePermission.java (renamed from services/java/com/android/server/pm/BasePermission.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/GrantedPermissions.java (renamed from services/java/com/android/server/pm/GrantedPermissions.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/Installer.java (renamed from services/java/com/android/server/pm/Installer.java) | 18 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/KeySetManager.java (renamed from services/java/com/android/server/pm/KeySetManager.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageKeySetData.java (renamed from services/java/com/android/server/pm/PackageKeySetData.java) | 0 | ||||
| -rwxr-xr-x | services/core/java/com/android/server/pm/PackageManagerService.java (renamed from services/java/com/android/server/pm/PackageManagerService.java) | 90 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageSetting.java (renamed from services/java/com/android/server/pm/PackageSetting.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageSettingBase.java (renamed from services/java/com/android/server/pm/PackageSettingBase.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageSignatures.java (renamed from services/java/com/android/server/pm/PackageSignatures.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageVerificationResponse.java (renamed from services/java/com/android/server/pm/PackageVerificationResponse.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageVerificationState.java (renamed from services/java/com/android/server/pm/PackageVerificationState.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PendingPackage.java (renamed from services/java/com/android/server/pm/PendingPackage.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PreferredActivity.java (renamed from services/java/com/android/server/pm/PreferredActivity.java) | 1 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PreferredComponent.java (renamed from services/java/com/android/server/PreferredComponent.java) | 2 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PreferredIntentResolver.java (renamed from services/java/com/android/server/pm/PreferredIntentResolver.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/SELinuxMMAC.java (renamed from services/java/com/android/server/pm/SELinuxMMAC.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/Settings.java (renamed from services/java/com/android/server/pm/Settings.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/SharedUserSetting.java (renamed from services/java/com/android/server/pm/SharedUserSetting.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/UserManagerService.java (renamed from services/java/com/android/server/pm/UserManagerService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/DisplayBlanker.java (renamed from services/java/com/android/server/power/DisplayBlanker.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/DisplayPowerController.java (renamed from services/java/com/android/server/power/DisplayPowerController.java) | 64 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/DisplayPowerRequest.java (renamed from services/java/com/android/server/power/DisplayPowerRequest.java) | 24 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/DisplayPowerState.java (renamed from services/java/com/android/server/power/DisplayPowerState.java) | 6 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/ElectronBeam.java (renamed from services/java/com/android/server/power/ElectronBeam.java) | 29 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/Notifier.java (renamed from services/java/com/android/server/power/Notifier.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/PowerManagerService.java (renamed from services/java/com/android/server/power/PowerManagerService.java) | 1343 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/RampAnimator.java (renamed from services/java/com/android/server/power/RampAnimator.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/ScreenOnBlocker.java (renamed from services/java/com/android/server/power/ScreenOnBlocker.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/ShutdownThread.java (renamed from services/java/com/android/server/power/ShutdownThread.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/SuspendBlocker.java (renamed from services/java/com/android/server/power/SuspendBlocker.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/WirelessChargerDetector.java (renamed from services/java/com/android/server/power/WirelessChargerDetector.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/search/SearchManagerService.java (renamed from services/java/com/android/server/search/SearchManagerService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/search/Searchables.java (renamed from services/java/com/android/server/search/Searchables.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java | 29 | ||||
| -rw-r--r-- | services/core/java/com/android/server/statusbar/StatusBarManagerService.java (renamed from services/java/com/android/server/StatusBarManagerService.java) | 236 | ||||
| -rw-r--r-- | services/core/java/com/android/server/storage/DeviceStorageMonitorInternal.java | 24 | ||||
| -rw-r--r-- | services/core/java/com/android/server/storage/DeviceStorageMonitorService.java (renamed from services/java/com/android/server/DeviceStorageMonitorService.java) | 250 | ||||
| -rw-r--r-- | services/core/java/com/android/server/twilight/TwilightListener.java | 21 | ||||
| -rw-r--r-- | services/core/java/com/android/server/twilight/TwilightManager.java | 24 | ||||
| -rw-r--r-- | services/core/java/com/android/server/twilight/TwilightService.java (renamed from services/java/com/android/server/TwilightService.java) | 251 | ||||
| -rw-r--r-- | services/core/java/com/android/server/twilight/TwilightState.java | 112 | ||||
| -rw-r--r-- | services/core/java/com/android/server/updates/CarrierProvisioningUrlsInstallReceiver.java (renamed from services/java/com/android/server/updates/CarrierProvisioningUrlsInstallReceiver.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/updates/CertPinInstallReceiver.java (renamed from services/java/com/android/server/updates/CertPinInstallReceiver.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java (renamed from services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/updates/IntentFirewallInstallReceiver.java (renamed from services/java/com/android/server/updates/IntentFirewallInstallReceiver.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java (renamed from services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/updates/SmsShortCodesInstallReceiver.java (renamed from services/java/com/android/server/updates/SmsShortCodesInstallReceiver.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/updates/TZInfoInstallReceiver.java (renamed from services/java/com/android/server/updates/TZInfoInstallReceiver.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wallpaper/WallpaperManagerService.java (renamed from services/java/com/android/server/WallpaperManagerService.java) | 20 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wifi/README.txt (renamed from services/java/com/android/server/wifi/README.txt) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wifi/WifiController.java (renamed from services/java/com/android/server/wifi/WifiController.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wifi/WifiNotificationController.java (renamed from services/java/com/android/server/wifi/WifiNotificationController.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wifi/WifiService.java (renamed from services/java/com/android/server/wifi/WifiService.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wifi/WifiSettingsStore.java (renamed from services/java/com/android/server/wifi/WifiSettingsStore.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wifi/WifiTrafficPoller.java (renamed from services/java/com/android/server/wifi/WifiTrafficPoller.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/AppTransition.java (renamed from services/java/com/android/server/wm/AppTransition.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/AppWindowAnimator.java (renamed from services/java/com/android/server/wm/AppWindowAnimator.java) | 16 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/AppWindowToken.java (renamed from services/java/com/android/server/wm/AppWindowToken.java) | 2 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/BlackFrame.java (renamed from services/java/com/android/server/wm/BlackFrame.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/DimLayer.java (renamed from services/java/com/android/server/wm/DimLayer.java) | 95 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/DisplayContent.java | 372 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/DisplayMagnifier.java (renamed from services/java/com/android/server/wm/DisplayMagnifier.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/DisplaySettings.java (renamed from services/java/com/android/server/wm/DisplaySettings.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/DragState.java (renamed from services/java/com/android/server/wm/DragState.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/FakeWindowImpl.java (renamed from services/java/com/android/server/wm/FakeWindowImpl.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/FocusedStackFrame.java (renamed from services/java/com/android/server/wm/FocusedStackFrame.java) | 8 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/InputMonitor.java (renamed from services/java/com/android/server/wm/InputMonitor.java) | 9 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/KeyguardDisableHandler.java (renamed from services/java/com/android/server/wm/KeyguardDisableHandler.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/PointerEventDispatcher.java (renamed from services/java/com/android/server/wm/PointerEventDispatcher.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/ScreenRotationAnimation.java (renamed from services/java/com/android/server/wm/ScreenRotationAnimation.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/Session.java (renamed from services/java/com/android/server/wm/Session.java) | 6 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/StackTapPointerEventListener.java (renamed from services/java/com/android/server/wm/StackTapPointerEventListener.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/StartingData.java (renamed from services/java/com/android/server/wm/StartingData.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/StrictModeFlash.java (renamed from services/java/com/android/server/wm/StrictModeFlash.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/Task.java (renamed from services/java/com/android/server/wm/Task.java) | 20 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/TaskGroup.java (renamed from services/java/com/android/server/wm/TaskGroup.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/TaskStack.java (renamed from services/java/com/android/server/wm/TaskStack.java) | 214 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/ViewServer.java (renamed from services/java/com/android/server/wm/ViewServer.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/Watermark.java (renamed from services/java/com/android/server/wm/Watermark.java) | 0 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowAnimator.java (renamed from services/java/com/android/server/wm/WindowAnimator.java) | 98 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java (renamed from services/java/com/android/server/wm/WindowManagerService.java) | 730 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowState.java (renamed from services/java/com/android/server/wm/WindowState.java) | 125 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowStateAnimator.java (renamed from services/java/com/android/server/wm/WindowStateAnimator.java) | 97 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowToken.java (renamed from services/java/com/android/server/wm/WindowToken.java) | 0 | ||||
| -rw-r--r-- | services/core/jni/Android.mk | 57 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_AlarmManagerService.cpp (renamed from services/jni/com_android_server_AlarmManagerService.cpp) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_AssetAtlasService.cpp (renamed from services/jni/com_android_server_AssetAtlasService.cpp) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_ConsumerIrService.cpp (renamed from services/jni/com_android_server_ConsumerIrService.cpp) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_SerialService.cpp (renamed from services/jni/com_android_server_SerialService.cpp) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_SystemServer.cpp (renamed from services/jni/com_android_server_SystemServer.cpp) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_UsbDeviceManager.cpp (renamed from services/jni/com_android_server_UsbDeviceManager.cpp) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_UsbHostManager.cpp (renamed from services/jni/com_android_server_UsbHostManager.cpp) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_VibratorService.cpp (renamed from services/jni/com_android_server_VibratorService.cpp) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_connectivity_Vpn.cpp (renamed from services/jni/com_android_server_connectivity_Vpn.cpp) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_dreams_McuHal.cpp | 100 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_input_InputApplicationHandle.cpp (renamed from services/jni/com_android_server_input_InputApplicationHandle.cpp) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_input_InputApplicationHandle.h (renamed from services/jni/com_android_server_input_InputApplicationHandle.h) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_input_InputManagerService.cpp (renamed from services/jni/com_android_server_input_InputManagerService.cpp) | 28 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_input_InputWindowHandle.cpp (renamed from services/jni/com_android_server_input_InputWindowHandle.cpp) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_input_InputWindowHandle.h (renamed from services/jni/com_android_server_input_InputWindowHandle.h) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_lights_LightsService.cpp (renamed from services/jni/com_android_server_LightsService.cpp) | 2 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_location_FlpHardwareProvider.cpp (renamed from services/jni/com_android_server_location_FlpHardwareProvider.cpp) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_location_GpsLocationProvider.cpp (renamed from services/jni/com_android_server_location_GpsLocationProvider.cpp) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_power_PowerManagerService.cpp (renamed from services/jni/com_android_server_power_PowerManagerService.cpp) | 0 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_power_PowerManagerService.h (renamed from services/jni/com_android_server_power_PowerManagerService.h) | 0 | ||||
| -rw-r--r-- | services/core/jni/onload.cpp (renamed from services/jni/onload.cpp) | 3 | ||||
| -rw-r--r-- | services/devicepolicy/Android.mk | 12 | ||||
| -rw-r--r-- | services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java (renamed from services/java/com/android/server/DevicePolicyManagerService.java) | 352 | ||||
| -rw-r--r-- | services/java/Android.mk | 18 | ||||
| -rw-r--r-- | services/java/com/android/server/AppWidgetService.java | 363 | ||||
| -rw-r--r-- | services/java/com/android/server/SystemServer.java | 617 | ||||
| -rw-r--r-- | services/java/com/android/server/display/HeadlessDisplayAdapter.java | 73 | ||||
| -rw-r--r-- | services/java/com/android/server/dreams/DreamManagerService.java | 425 | ||||
| -rw-r--r-- | services/java/com/android/server/print/PrintManagerService.java | 656 | ||||
| -rw-r--r-- | services/java/com/android/server/wm/DisplayContent.java | 523 | ||||
| -rw-r--r-- | services/java/com/android/server/wm/StackBox.java | 414 | ||||
| -rw-r--r-- | services/jni/Android.mk | 63 | ||||
| -rw-r--r-- | services/print/Android.mk | 10 | ||||
| -rw-r--r-- | services/print/java/com/android/server/print/PrintManagerService.java | 689 | ||||
| -rw-r--r-- | services/print/java/com/android/server/print/RemotePrintService.java (renamed from services/java/com/android/server/print/RemotePrintService.java) | 0 | ||||
| -rw-r--r-- | services/print/java/com/android/server/print/RemotePrintSpooler.java (renamed from services/java/com/android/server/print/RemotePrintSpooler.java) | 0 | ||||
| -rw-r--r-- | services/print/java/com/android/server/print/UserState.java (renamed from services/java/com/android/server/print/UserState.java) | 0 | ||||
| -rw-r--r-- | services/tests/Android.mk | 3 | ||||
| -rw-r--r-- | services/usb/Android.mk | 12 | ||||
| -rw-r--r-- | services/usb/java/com/android/server/usb/UsbDebuggingManager.java (renamed from services/java/com/android/server/usb/UsbDebuggingManager.java) | 0 | ||||
| -rw-r--r-- | services/usb/java/com/android/server/usb/UsbDeviceManager.java (renamed from services/java/com/android/server/usb/UsbDeviceManager.java) | 2 | ||||
| -rw-r--r-- | services/usb/java/com/android/server/usb/UsbHostManager.java (renamed from services/java/com/android/server/usb/UsbHostManager.java) | 0 | ||||
| -rw-r--r-- | services/usb/java/com/android/server/usb/UsbService.java (renamed from services/java/com/android/server/usb/UsbService.java) | 23 | ||||
| -rw-r--r-- | services/usb/java/com/android/server/usb/UsbSettingsManager.java (renamed from services/java/com/android/server/usb/UsbSettingsManager.java) | 0 | ||||
| -rw-r--r-- | tests/DozeTest/Android.mk | 14 | ||||
| -rw-r--r-- | tests/DozeTest/AndroidManifest.xml | 35 | ||||
| -rwxr-xr-x | tests/DozeTest/res/drawable-hdpi/ic_app.png | bin | 0 -> 3608 bytes | |||
| -rw-r--r-- | tests/DozeTest/res/drawable-mdpi/ic_app.png | bin | 0 -> 5198 bytes | |||
| -rw-r--r-- | tests/DozeTest/res/layout/dream.xml | 41 | ||||
| -rw-r--r-- | tests/DozeTest/res/values/strings.xml | 25 | ||||
| -rw-r--r-- | tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java | 165 | ||||
| -rw-r--r-- | tools/aapt/AaptAssets.cpp | 45 | ||||
| -rw-r--r-- | tools/aapt/AaptAssets.h | 8 | ||||
| -rw-r--r-- | tools/aapt/Bundle.h | 6 | ||||
| -rw-r--r-- | tools/aapt/Command.cpp | 2 | ||||
| -rw-r--r-- | tools/aapt/Main.cpp | 2 |
439 files changed, 11848 insertions, 7706 deletions
diff --git a/Android.mk b/Android.mk index efa1870c23e8..7cbc3396186c 100644 --- a/Android.mk +++ b/Android.mk @@ -59,6 +59,8 @@ LOCAL_SRC_FILES += \ core/java/android/accounts/IAccountManagerResponse.aidl \ core/java/android/accounts/IAccountAuthenticator.aidl \ core/java/android/accounts/IAccountAuthenticatorResponse.aidl \ + core/java/android/app/IActivityContainer.aidl \ + core/java/android/app/IActivityContainerCallback.aidl \ core/java/android/app/IActivityController.aidl \ core/java/android/app/IActivityPendingResult.aidl \ core/java/android/app/IAlarmManager.aidl \ @@ -174,6 +176,7 @@ LOCAL_SRC_FILES += \ core/java/android/print/IWriteResultCallback.aidl \ core/java/android/printservice/IPrintService.aidl \ core/java/android/printservice/IPrintServiceClient.aidl \ + core/java/android/service/dreams/IDozeHardware.aidl \ core/java/android/service/dreams/IDreamManager.aidl \ core/java/android/service/dreams/IDreamService.aidl \ core/java/android/service/wallpaper/IWallpaperConnection.aidl \ diff --git a/CleanSpec.mk b/CleanSpec.mk index cfa8be9a13c7..ef3f4aea190a 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -184,7 +184,7 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/effects/) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/framework-res_intermediates) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/IPrintClient.*) - +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates) # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ diff --git a/api/current.txt b/api/current.txt index 50337c0cb8f6..046775e40224 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3080,6 +3080,17 @@ package android.app { method public void update(android.app.ActivityOptions); } + public class ActivityView extends android.view.ViewGroup { + ctor public ActivityView(android.content.Context); + ctor public ActivityView(android.content.Context, android.util.AttributeSet); + ctor public ActivityView(android.content.Context, android.util.AttributeSet, int); + method public boolean isAttachedToDisplay(); + method protected void onLayout(boolean, int, int, int, int); + method public void startActivity(android.content.Intent); + method public void startActivity(android.content.IntentSender); + method public void startActivity(android.app.PendingIntent); + } + public class AlarmManager { method public void cancel(android.app.PendingIntent); method public void set(int, long, android.app.PendingIntent); @@ -3941,6 +3952,7 @@ package android.app { field public static final int FLAG_FOREGROUND_SERVICE = 64; // 0x40 field public static final deprecated int FLAG_HIGH_PRIORITY = 128; // 0x80 field public static final int FLAG_INSISTENT = 4; // 0x4 + field public static final int FLAG_LOCAL_ONLY = 256; // 0x100 field public static final int FLAG_NO_CLEAR = 32; // 0x20 field public static final int FLAG_ONGOING_EVENT = 2; // 0x2 field public static final int FLAG_ONLY_ALERT_ONCE = 8; // 0x8 @@ -4021,6 +4033,7 @@ package android.app { method public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean); method public android.app.Notification.Builder setLargeIcon(android.graphics.Bitmap); method public android.app.Notification.Builder setLights(int, int, int); + method public android.app.Notification.Builder setLocalOnly(boolean); method public android.app.Notification.Builder setNumber(int); method public android.app.Notification.Builder setOngoing(boolean); method public android.app.Notification.Builder setOnlyAlertOnce(boolean); @@ -7277,6 +7290,7 @@ package android.content.pm { field public static final java.lang.String EXTRA_VERIFICATION_RESULT = "android.content.pm.extra.VERIFICATION_RESULT"; field public static final java.lang.String FEATURE_APP_WIDGETS = "android.software.app_widgets"; field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency"; + field public static final java.lang.String FEATURE_BACKUP = "android.software.backup"; field public static final java.lang.String FEATURE_BLUETOOTH = "android.hardware.bluetooth"; field public static final java.lang.String FEATURE_BLUETOOTH_LE = "android.hardware.bluetooth_le"; field public static final java.lang.String FEATURE_CAMERA = "android.hardware.camera"; @@ -7298,6 +7312,7 @@ package android.content.pm { field public static final java.lang.String FEATURE_MICROPHONE = "android.hardware.microphone"; field public static final java.lang.String FEATURE_NFC = "android.hardware.nfc"; field public static final java.lang.String FEATURE_NFC_HOST_CARD_EMULATION = "android.hardware.nfc.hce"; + field public static final java.lang.String FEATURE_PRINTING = "android.software.print"; field public static final java.lang.String FEATURE_SCREEN_LANDSCAPE = "android.hardware.screen.landscape"; field public static final java.lang.String FEATURE_SCREEN_PORTRAIT = "android.hardware.screen.portrait"; field public static final java.lang.String FEATURE_SENSOR_ACCELEROMETER = "android.hardware.sensor.accelerometer"; @@ -7320,6 +7335,7 @@ package android.content.pm { field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH_JAZZHAND = "android.hardware.touchscreen.multitouch.jazzhand"; field public static final java.lang.String FEATURE_USB_ACCESSORY = "android.hardware.usb.accessory"; field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host"; + field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch"; field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi"; field public static final java.lang.String FEATURE_WIFI_DIRECT = "android.hardware.wifi.direct"; field public static final int GET_ACTIVITIES = 1; // 0x1 @@ -10870,6 +10886,7 @@ package android.hardware.display { method public void registerDisplayListener(android.hardware.display.DisplayManager.DisplayListener, android.os.Handler); method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener); field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION"; + field public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 8; // 0x8 field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2 field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1 field public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 4; // 0x4 @@ -26175,7 +26192,6 @@ package android.util { method public final java.lang.CharSequence coerceToString(); method public static final java.lang.String coerceToString(int, int); method public static float complexToDimension(int, android.util.DisplayMetrics); - method public static float complexToDimensionNoisy(int, android.util.DisplayMetrics); method public static int complexToDimensionPixelOffset(int, android.util.DisplayMetrics); method public static int complexToDimensionPixelSize(int, android.util.DisplayMetrics); method public static float complexToFloat(int); diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 0344d261fd35..89e15d25dd62 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -19,8 +19,9 @@ package com.android.commands.am; import android.app.ActivityManager; -import android.app.ActivityManager.StackBoxInfo; +import android.app.ActivityManager.StackInfo; import android.app.ActivityManagerNative; +import android.app.IActivityContainer; import android.app.IActivityController; import android.app.IActivityManager; import android.app.IInstrumentationWatcher; @@ -31,9 +32,11 @@ import android.content.IIntentReceiver; import android.content.Intent; import android.content.pm.IPackageManager; import android.content.pm.ResolveInfo; +import android.graphics.Rect; import android.net.Uri; import android.os.Binder; import android.os.Bundle; +import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceManager; @@ -106,11 +109,11 @@ public class Am extends BaseCommand { " am to-intent-uri [INTENT]\n" + " am switch-user <USER_ID>\n" + " am stop-user <USER_ID>\n" + - " am stack create <TASK_ID> <RELATIVE_STACK_BOX_ID> <POSITION> <WEIGHT>\n" + + " am stack start <DISPLAY_ID> <INTENT>\n" + " am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" + - " am stack resize <STACK_ID> <WEIGHT>\n" + - " am stack boxes\n" + - " am stack box <STACK_BOX_ID>\n" + + " am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" + + " am stack list\n" + + " am stack info <STACK_ID>\n" + "\n" + "am start: start an Activity. Options are:\n" + " -D: enable debugging\n" + @@ -204,24 +207,16 @@ public class Am extends BaseCommand { "am stop-user: stop execution of USER_ID, not allowing it to run any\n" + " code until a later explicit switch to it.\n" + "\n" + - "am stack create: create a new stack relative to an existing one.\n" + - " <TASK_ID>: the task to populate the new stack with. Must exist.\n" + - " <RELATIVE_STACK_BOX_ID>: existing stack box's id.\n" + - " <POSITION>: 0: before <RELATIVE_STACK_BOX_ID>, per RTL/LTR configuration,\n" + - " 1: after <RELATIVE_STACK_BOX_ID>, per RTL/LTR configuration,\n" + - " 2: to left of <RELATIVE_STACK_BOX_ID>,\n" + - " 3: to right of <RELATIVE_STACK_BOX_ID>," + - " 4: above <RELATIVE_STACK_BOX_ID>, 5: below <RELATIVE_STACK_BOX_ID>\n" + - " <WEIGHT>: float between 0.2 and 0.8 inclusive.\n" + + "am stack start: start a new activity on <DISPLAY_ID> using <INTENT>.\n" + "\n" + "am stack movetask: move <TASK_ID> from its current stack to the top (true) or" + " bottom (false) of <STACK_ID>.\n" + "\n" + - "am stack resize: change <STACK_ID> relative size to new <WEIGHT>.\n" + + "am stack resize: change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>.\n" + "\n" + - "am stack boxes: list the hierarchy of stack boxes and their contents.\n" + + "am stack list: list all of the activity stacks and their sizes.\n" + "\n" + - "am stack box: list the hierarchy of stack boxes rooted at <STACK_BOX_ID>.\n" + + "am stack info: display the information about activity stack <STACK_ID>.\n" + "\n" + "<INTENT> specifications include these flags and arguments:\n" + " [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" + @@ -1546,35 +1541,32 @@ public class Am extends BaseCommand { private void runStack() throws Exception { String op = nextArgRequired(); - if (op.equals("create")) { - runStackCreate(); + if (op.equals("start")) { + runStackStart(); } else if (op.equals("movetask")) { runStackMoveTask(); } else if (op.equals("resize")) { - runStackBoxResize(); - } else if (op.equals("boxes")) { - runStackBoxes(); - } else if (op.equals("box")) { - runStackBoxInfo(); + runStackResize(); + } else if (op.equals("list")) { + runStackList(); + } else if (op.equals("info")) { + runStackInfo(); } else { showError("Error: unknown command '" + op + "'"); return; } } - private void runStackCreate() throws Exception { - String taskIdStr = nextArgRequired(); - int taskId = Integer.valueOf(taskIdStr); - String relativeToStr = nextArgRequired(); - int relativeTo = Integer.valueOf(relativeToStr); - String positionStr = nextArgRequired(); - int position = Integer.valueOf(positionStr); - String weightStr = nextArgRequired(); - float weight = Float.valueOf(weightStr); + private void runStackStart() throws Exception { + String displayIdStr = nextArgRequired(); + int displayId = Integer.valueOf(displayIdStr); + Intent intent = makeIntent(UserHandle.USER_CURRENT); try { - int stackId = mAm.createStack(taskId, relativeTo, position, weight); - System.out.println("createStack returned new stackId=" + stackId + "\n\n"); + IBinder homeActivityToken = mAm.getHomeActivityToken(); + IActivityContainer container = mAm.createActivityContainer(homeActivityToken, null); + container.attachToDisplay(displayId); + container.startActivity(intent); } catch (RemoteException e) { } } @@ -1601,34 +1593,40 @@ public class Am extends BaseCommand { } } - private void runStackBoxResize() throws Exception { - String stackBoxIdStr = nextArgRequired(); - int stackBoxId = Integer.valueOf(stackBoxIdStr); - String weightStr = nextArgRequired(); - float weight = Float.valueOf(weightStr); + private void runStackResize() throws Exception { + String stackIdStr = nextArgRequired(); + int stackId = Integer.valueOf(stackIdStr); + String leftStr = nextArgRequired(); + int left = Integer.valueOf(leftStr); + String topStr = nextArgRequired(); + int top = Integer.valueOf(topStr); + String rightStr = nextArgRequired(); + int right = Integer.valueOf(rightStr); + String bottomStr = nextArgRequired(); + int bottom = Integer.valueOf(bottomStr); try { - mAm.resizeStackBox(stackBoxId, weight); + mAm.resizeStack(stackId, new Rect(left, top, right, bottom)); } catch (RemoteException e) { } } - private void runStackBoxes() throws Exception { + private void runStackList() throws Exception { try { - List<StackBoxInfo> stackBoxes = mAm.getStackBoxes(); - for (StackBoxInfo info : stackBoxes) { + List<StackInfo> stacks = mAm.getAllStackInfos(); + for (StackInfo info : stacks) { System.out.println(info); } } catch (RemoteException e) { } } - private void runStackBoxInfo() throws Exception { + private void runStackInfo() throws Exception { try { - String stackBoxIdStr = nextArgRequired(); - int stackBoxId = Integer.valueOf(stackBoxIdStr); - StackBoxInfo stackBoxInfo = mAm.getStackBoxInfo(stackBoxId); - System.out.println(stackBoxInfo); + String stackIdStr = nextArgRequired(); + int stackId = Integer.valueOf(stackIdStr); + StackInfo info = mAm.getStackInfo(stackId); + System.out.println(info); } catch (RemoteException e) { } } diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 7ca345993c23..c877cd3ac264 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1289,106 +1289,15 @@ public class ActivityManager { } /** - * Information you can retrieve about the WindowManager StackBox hierarchy. - * @hide - */ - public static class StackBoxInfo implements Parcelable { - public int stackBoxId; - public float weight; - public boolean vertical; - public Rect bounds; - public StackBoxInfo[] children; - public int stackId; - public StackInfo stack; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(stackBoxId); - dest.writeFloat(weight); - dest.writeInt(vertical ? 1 : 0); - bounds.writeToParcel(dest, flags); - dest.writeInt(stackId); - if (children != null) { - children[0].writeToParcel(dest, flags); - children[1].writeToParcel(dest, flags); - } else { - stack.writeToParcel(dest, flags); - } - } - - public void readFromParcel(Parcel source) { - stackBoxId = source.readInt(); - weight = source.readFloat(); - vertical = source.readInt() == 1; - bounds = Rect.CREATOR.createFromParcel(source); - stackId = source.readInt(); - if (stackId == -1) { - children = new StackBoxInfo[2]; - children[0] = StackBoxInfo.CREATOR.createFromParcel(source); - children[1] = StackBoxInfo.CREATOR.createFromParcel(source); - } else { - stack = StackInfo.CREATOR.createFromParcel(source); - } - } - - public static final Creator<StackBoxInfo> CREATOR = - new Creator<ActivityManager.StackBoxInfo>() { - - @Override - public StackBoxInfo createFromParcel(Parcel source) { - return new StackBoxInfo(source); - } - - @Override - public StackBoxInfo[] newArray(int size) { - return new StackBoxInfo[size]; - } - }; - - public StackBoxInfo() { - } - - public StackBoxInfo(Parcel source) { - readFromParcel(source); - } - - public String toString(String prefix) { - StringBuilder sb = new StringBuilder(256); - sb.append(prefix); sb.append("Box id=" + stackBoxId); sb.append(" weight=" + weight); - sb.append(" vertical=" + vertical); sb.append(" bounds=" + bounds.toShortString()); - sb.append("\n"); - if (children != null) { - sb.append(prefix); sb.append("First child=\n"); - sb.append(children[0].toString(prefix + " ")); - sb.append(prefix); sb.append("Second child=\n"); - sb.append(children[1].toString(prefix + " ")); - } else { - sb.append(prefix); sb.append("Stack=\n"); - sb.append(stack.toString(prefix + " ")); - } - return sb.toString(); - } - - @Override - public String toString() { - return toString(""); - } - } - - /** * Information you can retrieve about an ActivityStack in the system. * @hide */ public static class StackInfo implements Parcelable { public int stackId; - public Rect bounds; + public Rect bounds = new Rect(); public int[] taskIds; public String[] taskNames; + public int displayId; @Override public int describeContents() { @@ -1404,6 +1313,7 @@ public class ActivityManager { dest.writeInt(bounds.bottom); dest.writeIntArray(taskIds); dest.writeStringArray(taskNames); + dest.writeInt(displayId); } public void readFromParcel(Parcel source) { @@ -1412,6 +1322,7 @@ public class ActivityManager { source.readInt(), source.readInt(), source.readInt(), source.readInt()); taskIds = source.createIntArray(); taskNames = source.createStringArray(); + displayId = source.readInt(); } public static final Creator<StackInfo> CREATOR = new Creator<StackInfo>() { @@ -1435,7 +1346,9 @@ public class ActivityManager { public String toString(String prefix) { StringBuilder sb = new StringBuilder(256); sb.append(prefix); sb.append("Stack id="); sb.append(stackId); - sb.append(" bounds="); sb.append(bounds.toShortString()); sb.append("\n"); + sb.append(" bounds="); sb.append(bounds.toShortString()); + sb.append(" displayId="); sb.append(displayId); + sb.append("\n"); prefix = prefix + " "; for (int i = 0; i < taskIds.length; ++i) { sb.append(prefix); sb.append("taskId="); sb.append(taskIds[i]); diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 74266ccf58a2..7b81713c0fcc 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -16,7 +16,7 @@ package android.app; -import android.app.ActivityManager.StackBoxInfo; +import android.app.ActivityManager.StackInfo; import android.content.ComponentName; import android.content.IIntentReceiver; import android.content.IIntentSender; @@ -31,6 +31,7 @@ import android.content.pm.ParceledListSlice; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.graphics.Rect; import android.net.Uri; import android.os.Binder; import android.os.Bundle; @@ -611,18 +612,6 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } - case CREATE_STACK_TRANSACTION: { - data.enforceInterface(IActivityManager.descriptor); - int taskId = data.readInt(); - int relativeStackId = data.readInt(); - int position = data.readInt(); - float weight = data.readFloat(); - int res = createStack(taskId, relativeStackId, position, weight); - reply.writeNoException(); - reply.writeInt(res); - return true; - } - case MOVE_TASK_TO_STACK_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); int taskId = data.readInt(); @@ -635,25 +624,26 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case RESIZE_STACK_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); - int stackBoxId = data.readInt(); + int stackId = data.readInt(); float weight = data.readFloat(); - resizeStackBox(stackBoxId, weight); + Rect r = Rect.CREATOR.createFromParcel(data); + resizeStack(stackId, r); reply.writeNoException(); return true; } - case GET_STACK_BOXES_TRANSACTION: { + case GET_ALL_STACK_INFOS_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); - List<StackBoxInfo> list = getStackBoxes(); + List<StackInfo> list = getAllStackInfos(); reply.writeNoException(); reply.writeTypedList(list); return true; } - case GET_STACK_BOX_INFO_TRANSACTION: { + case GET_STACK_INFO_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); - int stackBoxId = data.readInt(); - StackBoxInfo info = getStackBoxInfo(stackBoxId); + int stackId = data.readInt(); + StackInfo info = getStackInfo(stackId); reply.writeNoException(); if (info != null) { reply.writeInt(1); @@ -2028,6 +2018,45 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeNoException(); return true; } + + case CREATE_ACTIVITY_CONTAINER_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder parentActivityToken = data.readStrongBinder(); + IActivityContainerCallback callback = + (IActivityContainerCallback) data.readStrongBinder(); + IActivityContainer activityContainer = + createActivityContainer(parentActivityToken, callback); + reply.writeNoException(); + if (activityContainer != null) { + reply.writeInt(1); + reply.writeStrongBinder(activityContainer.asBinder()); + } else { + reply.writeInt(0); + } + return true; + } + + case GET_ACTIVITY_CONTAINER_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder activityToken = data.readStrongBinder(); + IActivityContainer activityContainer = getEnclosingActivityContainer(activityToken); + reply.writeNoException(); + if (activityContainer != null) { + reply.writeInt(1); + reply.writeStrongBinder(activityContainer.asBinder()); + } else { + reply.writeInt(0); + } + return true; + } + + case GET_HOME_ACTIVITY_TOKEN_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder homeActivityToken = getHomeActivityToken(); + reply.writeNoException(); + reply.writeStrongBinder(homeActivityToken); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -2715,24 +2744,6 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } @Override - public int createStack(int taskId, int relativeStackBoxId, int position, float weight) - throws RemoteException - { - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - data.writeInterfaceToken(IActivityManager.descriptor); - data.writeInt(taskId); - data.writeInt(relativeStackBoxId); - data.writeInt(position); - data.writeFloat(weight); - mRemote.transact(CREATE_STACK_TRANSACTION, data, reply, 0); - reply.readException(); - int res = reply.readInt(); - data.recycle(); - reply.recycle(); - return res; - } - @Override public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException { Parcel data = Parcel.obtain(); @@ -2747,44 +2758,44 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } @Override - public void resizeStackBox(int stackBoxId, float weight) throws RemoteException + public void resizeStack(int stackBoxId, Rect r) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeInt(stackBoxId); - data.writeFloat(weight); + r.writeToParcel(data, 0); mRemote.transact(RESIZE_STACK_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY); reply.readException(); data.recycle(); reply.recycle(); } @Override - public List<StackBoxInfo> getStackBoxes() throws RemoteException + public List<StackInfo> getAllStackInfos() throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); - mRemote.transact(GET_STACK_BOXES_TRANSACTION, data, reply, 0); + mRemote.transact(GET_ALL_STACK_INFOS_TRANSACTION, data, reply, 0); reply.readException(); - ArrayList<StackBoxInfo> list = reply.createTypedArrayList(StackBoxInfo.CREATOR); + ArrayList<StackInfo> list = reply.createTypedArrayList(StackInfo.CREATOR); data.recycle(); reply.recycle(); return list; } @Override - public StackBoxInfo getStackBoxInfo(int stackBoxId) throws RemoteException + public StackInfo getStackInfo(int stackId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); - data.writeInt(stackBoxId); - mRemote.transact(GET_STACK_BOX_INFO_TRANSACTION, data, reply, 0); + data.writeInt(stackId); + mRemote.transact(GET_STACK_INFO_TRANSACTION, data, reply, 0); reply.readException(); int res = reply.readInt(); - StackBoxInfo info = null; + StackInfo info = null; if (res != 0) { - info = StackBoxInfo.CREATOR.createFromParcel(reply); + info = StackInfo.CREATOR.createFromParcel(reply); } data.recycle(); reply.recycle(); @@ -4660,5 +4671,58 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } + public IActivityContainer createActivityContainer(IBinder parentActivityToken, + IActivityContainerCallback callback) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(parentActivityToken); + data.writeStrongBinder((IBinder)callback); + mRemote.transact(CREATE_ACTIVITY_CONTAINER_TRANSACTION, data, reply, 0); + reply.readException(); + final int result = reply.readInt(); + final IActivityContainer res; + if (result == 1) { + res = IActivityContainer.Stub.asInterface(reply.readStrongBinder()); + } else { + res = null; + } + data.recycle(); + reply.recycle(); + return res; + } + + public IActivityContainer getEnclosingActivityContainer(IBinder activityToken) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(activityToken); + mRemote.transact(GET_ACTIVITY_CONTAINER_TRANSACTION, data, reply, 0); + reply.readException(); + final int result = reply.readInt(); + final IActivityContainer res; + if (result == 1) { + res = IActivityContainer.Stub.asInterface(reply.readStrongBinder()); + } else { + res = null; + } + data.recycle(); + reply.recycle(); + return res; + } + + public IBinder getHomeActivityToken() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(GET_HOME_ACTIVITY_TOKEN_TRANSACTION, data, reply, 0); + reply.readException(); + IBinder res = reply.readStrongBinder(); + data.recycle(); + reply.recycle(); + return res; + } + private IBinder mRemote; } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 97baf9a90417..9f21a3603fe9 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2219,15 +2219,27 @@ public final class ActivityThread { ContextImpl appContext = new ContextImpl(); appContext.init(r.packageInfo, r.token, this); appContext.setOuterContext(activity); + Context baseContext = appContext; + + final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance(); + try { + IActivityContainer container = + ActivityManagerNative.getDefault().getEnclosingActivityContainer(r.token); + final int displayId = + container == null ? Display.DEFAULT_DISPLAY : container.getDisplayId(); + if (displayId > Display.DEFAULT_DISPLAY) { + Display display = dm.getRealDisplay(displayId, r.token); + baseContext = appContext.createDisplayContext(display); + } + } catch (RemoteException e) { + } // For debugging purposes, if the activity's package name contains the value of // the "debug.use-second-display" system property as a substring, then show // its content on a secondary display if there is one. - Context baseContext = appContext; String pkgName = SystemProperties.get("debug.second-display.pkg"); if (pkgName != null && !pkgName.isEmpty() && r.packageInfo.mPackageName.contains(pkgName)) { - DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance(); for (int displayId : dm.getDisplayIds()) { if (displayId != Display.DEFAULT_DISPLAY) { Display display = dm.getRealDisplay(displayId, r.token); diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java new file mode 100644 index 000000000000..14f08298e404 --- /dev/null +++ b/core/java/android/app/ActivityView.java @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.content.Context; +import android.content.ContextWrapper; +import android.content.IIntentSender; +import android.content.Intent; +import android.content.IntentSender; +import android.graphics.SurfaceTexture; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.InputDevice; +import android.view.InputEvent; +import android.view.MotionEvent; +import android.view.Surface; +import android.view.TextureView; +import android.view.TextureView.SurfaceTextureListener; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; + +public class ActivityView extends ViewGroup { + private final String TAG = "ActivityView"; + private final boolean DEBUG = false; + + private final TextureView mTextureView; + private IActivityContainer mActivityContainer; + private Activity mActivity; + private int mWidth; + private int mHeight; + private Surface mSurface; + + // Only one IIntentSender or Intent may be queued at a time. Most recent one wins. + IIntentSender mQueuedPendingIntent; + Intent mQueuedIntent; + + public ActivityView(Context context) { + this(context, null); + } + + public ActivityView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public ActivityView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + while (context instanceof ContextWrapper) { + if (context instanceof Activity) { + mActivity = (Activity)context; + break; + } + context = ((ContextWrapper)context).getBaseContext(); + } + if (mActivity == null) { + throw new IllegalStateException("The ActivityView's Context is not an Activity."); + } + + mTextureView = new TextureView(context); + mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener()); + addView(mTextureView); + if (DEBUG) Log.v(TAG, "ctor()"); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mTextureView.layout(0, 0, r - l, b - t); + } + + @Override + protected void onAttachedToWindow() { + if (DEBUG) Log.v(TAG, "onAttachedToWindow()"); + super.onAttachedToWindow(); + try { + final IBinder token = mActivity.getActivityToken(); + mActivityContainer = + ActivityManagerNative.getDefault().createActivityContainer(token, null); + } catch (RemoteException e) { + throw new IllegalStateException("ActivityView: Unable to create ActivityContainer. " + + e); + } + + attachToSurfaceWhenReady(); + } + + @Override + protected void onDetachedFromWindow() { + if (DEBUG) Log.v(TAG, "onDetachedFromWindow(): mActivityContainer=" + mActivityContainer); + super.onDetachedFromWindow(); + if (mActivityContainer != null) { + detach(); + mActivityContainer = null; + } + } + + @Override + protected void onWindowVisibilityChanged(int visibility) { + if (DEBUG) Log.v(TAG, "onWindowVisibilityChanged(): visibility=" + visibility); + super.onWindowVisibilityChanged(visibility); + switch (visibility) { + case View.VISIBLE: + attachToSurfaceWhenReady(); + break; + case View.INVISIBLE: + break; + case View.GONE: + detach(); + break; + } + } + + private boolean injectInputEvent(InputEvent event) { + try { + return mActivityContainer != null && mActivityContainer.injectEvent(event); + } catch (RemoteException e) { + return false; + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + return injectInputEvent(event) || super.onTouchEvent(event); + } + + @Override + public boolean onGenericMotionEvent(MotionEvent event) { + if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { + if (injectInputEvent(event)) { + return true; + } + } + return super.onGenericMotionEvent(event); + } + + public boolean isAttachedToDisplay() { + return mSurface != null; + } + + public void startActivity(Intent intent) { + if (DEBUG) Log.v(TAG, "startActivity(): intent=" + intent + " " + + (isAttachedToDisplay() ? "" : "not") + " attached"); + if (mSurface != null) { + try { + mActivityContainer.startActivity(intent); + } catch (RemoteException e) { + throw new IllegalStateException("ActivityView: Unable to startActivity. " + e); + } + } else { + mQueuedIntent = intent; + mQueuedPendingIntent = null; + } + } + + private void startActivityIntentSender(IIntentSender iIntentSender) { + try { + mActivityContainer.startActivityIntentSender(iIntentSender); + } catch (RemoteException e) { + throw new IllegalStateException( + "ActivityView: Unable to startActivity from IntentSender. " + e); + } + } + + public void startActivity(IntentSender intentSender) { + if (DEBUG) Log.v(TAG, "startActivityIntentSender(): intentSender=" + intentSender + " " + + (isAttachedToDisplay() ? "" : "not") + " attached"); + final IIntentSender iIntentSender = intentSender.getTarget(); + if (mSurface != null) { + startActivityIntentSender(iIntentSender); + } else { + mQueuedPendingIntent = iIntentSender; + mQueuedIntent = null; + } + } + + public void startActivity(PendingIntent pendingIntent) { + if (DEBUG) Log.v(TAG, "startActivityPendingIntent(): PendingIntent=" + pendingIntent + " " + + (isAttachedToDisplay() ? "" : "not") + " attached"); + final IIntentSender iIntentSender = pendingIntent.getTarget(); + if (mSurface != null) { + startActivityIntentSender(iIntentSender); + } else { + mQueuedPendingIntent = iIntentSender; + mQueuedIntent = null; + } + } + + private void attachToSurfaceWhenReady() { + final SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture(); + if (mActivityContainer == null || surfaceTexture == null || mSurface != null) { + // Either not ready to attach, or already attached. + return; + } + + WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE); + DisplayMetrics metrics = new DisplayMetrics(); + wm.getDefaultDisplay().getMetrics(metrics); + + mSurface = new Surface(surfaceTexture); + try { + mActivityContainer.attachToSurface(mSurface, mWidth, mHeight, metrics.densityDpi); + } catch (RemoteException e) { + mSurface.release(); + mSurface = null; + throw new IllegalStateException( + "ActivityView: Unable to create ActivityContainer. " + e); + } + + if (DEBUG) Log.v(TAG, "attachToSurfaceWhenReady: " + (mQueuedIntent != null || + mQueuedPendingIntent != null ? "" : "no") + " queued intent"); + if (mQueuedIntent != null) { + startActivity(mQueuedIntent); + mQueuedIntent = null; + } else if (mQueuedPendingIntent != null) { + startActivityIntentSender(mQueuedPendingIntent); + mQueuedPendingIntent = null; + } + } + + private void detach() { + if (DEBUG) Log.d(TAG, "detach: attached=" + isAttachedToDisplay()); + if (mSurface != null) { + try { + mActivityContainer.detachFromDisplay(); + } catch (RemoteException e) { + } + mSurface.release(); + mSurface = null; + } + } + + private class ActivityViewSurfaceTextureListener implements SurfaceTextureListener { + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, + int height) { + if (DEBUG) Log.d(TAG, "onSurfaceTextureAvailable: width=" + width + " height=" + + height); + mWidth = width; + mHeight = height; + if (mActivityContainer != null) { + attachToSurfaceWhenReady(); + } + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, + int height) { + if (DEBUG) Log.d(TAG, "onSurfaceTextureSizeChanged: w=" + width + " h=" + height); + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { + if (DEBUG) Log.d(TAG, "onSurfaceTextureDestroyed"); + detach(); + return true; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { +// Log.d(TAG, "onSurfaceTextureUpdated"); + } + + } +} diff --git a/core/java/android/app/IActivityContainer.aidl b/core/java/android/app/IActivityContainer.aidl new file mode 100644 index 000000000000..5b80e06e1611 --- /dev/null +++ b/core/java/android/app/IActivityContainer.aidl @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2013, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.app.IActivityContainerCallback; +import android.content.Intent; +import android.content.IIntentSender; +import android.os.IBinder; +import android.view.InputEvent; +import android.view.Surface; + +/** @hide */ +interface IActivityContainer { + void attachToDisplay(int displayId); + void attachToSurface(in Surface surface, int width, int height, int density); + void detachFromDisplay(); + int startActivity(in Intent intent); + int startActivityIntentSender(in IIntentSender intentSender); + int getDisplayId(); + boolean injectEvent(in InputEvent event); +} diff --git a/core/java/android/app/IActivityContainerCallback.aidl b/core/java/android/app/IActivityContainerCallback.aidl new file mode 100644 index 000000000000..55c2001e90ef --- /dev/null +++ b/core/java/android/app/IActivityContainerCallback.aidl @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2013, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.os.IBinder; + +/** @hide */ +interface IActivityContainerCallback { + oneway void onLastActivityRemoved(IBinder container); +} diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 77c2ea0c1694..3ed3f7bdf20e 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -18,7 +18,7 @@ package android.app; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManager.RunningServiceInfo; -import android.app.ActivityManager.StackBoxInfo; +import android.app.ActivityManager.StackInfo; import android.content.ComponentName; import android.content.ContentProviderNative; import android.content.IContentProvider; @@ -36,6 +36,7 @@ import android.content.pm.ProviderInfo; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; import android.os.Debug; @@ -117,12 +118,10 @@ public interface IActivityManager extends IInterface { public void moveTaskToBack(int task) throws RemoteException; public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException; public void moveTaskBackwards(int task) throws RemoteException; - public int createStack(int taskId, int relativeStackBoxId, int position, float weight) - throws RemoteException; public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException; - public void resizeStackBox(int stackBoxId, float weight) throws RemoteException; - public List<StackBoxInfo> getStackBoxes() throws RemoteException; - public StackBoxInfo getStackBoxInfo(int stackBoxId) throws RemoteException; + public void resizeStack(int stackId, Rect bounds) throws RemoteException; + public List<StackInfo> getAllStackInfos() throws RemoteException; + public StackInfo getStackInfo(int stackId) throws RemoteException; public void setFocusedStack(int stackId) throws RemoteException; public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException; /* oneway */ @@ -408,6 +407,14 @@ public interface IActivityManager extends IInterface { public void performIdleMaintenance() throws RemoteException; + public IActivityContainer createActivityContainer(IBinder parentActivityToken, + IActivityContainerCallback callback) throws RemoteException; + + public IActivityContainer getEnclosingActivityContainer(IBinder activityToken) + throws RemoteException; + + public IBinder getHomeActivityToken() throws RemoteException; + /* * Private non-Binder interfaces */ @@ -678,12 +685,12 @@ public interface IActivityManager extends IInterface { int KILL_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+164; int SET_USER_IS_MONKEY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+165; int HANG_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+166; - int CREATE_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+167; + int CREATE_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+167; int MOVE_TASK_TO_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+168; int RESIZE_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+169; - int GET_STACK_BOXES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+170; + int GET_ALL_STACK_INFOS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+170; int SET_FOCUSED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+171; - int GET_STACK_BOX_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+172; + int GET_STACK_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+172; int CONVERT_FROM_TRANSLUCENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+173; int CONVERT_TO_TRANSLUCENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+174; int NOTIFY_ACTIVITY_DRAWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+175; @@ -694,4 +701,6 @@ public interface IActivityManager extends IInterface { int RELEASE_PERSISTABLE_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+180; int GET_PERSISTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+181; int APP_NOT_RESPONDING_VIA_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+182; + int GET_HOME_ACTIVITY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+183; + int GET_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+184; } diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl index 3efd3c0ede8b..181eb63bce69 100644 --- a/core/java/android/app/IWallpaperManager.aidl +++ b/core/java/android/app/IWallpaperManager.aidl @@ -71,4 +71,14 @@ interface IWallpaperManager { * Returns the desired minimum height for the wallpaper. */ int getHeightHint(); + + /** + * Returns the name of the wallpaper. Private API. + */ + String getName(); + + /** + * Informs the service that wallpaper settings have been restored. Private API. + */ + void settingsRestored(); } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index c63e586a7127..1e96ebf3d1c5 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -348,6 +348,13 @@ public class Notification implements Parcelable */ public static final int FLAG_HIGH_PRIORITY = 0x00000080; + /** + * Bit to be bitswise-ored into the {@link #flags} field that should be + * set if this notification is relevant to the current device only + * and it is not recommended that it bridge to other devices. + */ + public static final int FLAG_LOCAL_ONLY = 0x00000100; + public int flags; /** @@ -1532,6 +1539,17 @@ public class Notification implements Parcelable } /** + * Set whether or not this notification should not bridge to other devices. + * + * <p>Some notifications can be bridged to other devices for remote display. + * This hint can be set to recommend this notification not be bridged. + */ + public Builder setLocalOnly(boolean localOnly) { + setFlag(FLAG_LOCAL_ONLY, localOnly); + return this; + } + + /** * Set which notification properties will be inherited from system defaults. * <p> * The value should be one or more of the following fields combined with @@ -1900,8 +1918,7 @@ public class Notification implements Parcelable * An object that can apply a rich notification style to a {@link Notification.Builder} * object. */ - public static abstract class Style - { + public static abstract class Style { private CharSequence mBigContentTitle; private CharSequence mSummaryText = null; private boolean mSummaryTextSet = false; diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index e2bc80aad66d..d1f1f2af44c9 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -27,14 +27,14 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import android.util.Pair; + import java.io.IOException; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; import java.util.HashMap; -import java.util.LinkedList; +import java.util.HashSet; import java.util.Locale; import java.util.Map; import java.util.Random; @@ -183,6 +183,43 @@ public final class BluetoothAdapter { "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION"; /** + * Activity Action: Show a system activity to request BLE advertising.<br> + * If the device is not doing BLE advertising, this activity will start BLE advertising for the + * device, otherwise it will continue BLE advertising using the current + * {@link BluetoothAdvScanData}. <br> + * Note this activity will also request the user to turn on Bluetooth if it's not currently + * enabled. + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_START_ADVERTISING = + "android.bluetooth.adapter.action.START_ADVERTISING"; + + /** + * Activity Action: Stop the current BLE advertising. + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_STOP_ADVERTISING = + "android.bluetooth.adapter.action.STOP_ADVERTISING"; + + /** + * Broadcast Action: Indicate BLE Advertising is started. + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_BLUETOOTH_ADVERTISING_STARTED = + "android.bluetooth.adapter.action.ADVERTISING_STARTED"; + + /** + * Broadcast Action: Indicated BLE Advertising is stopped. + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_BLUETOOTH_ADVERTISING_STOPPED = + "android.bluetooth.adapter.action.ADVERTISING_STOPPED"; + + /** * Activity Action: Show a system activity that allows the user to turn on * Bluetooth. * <p>This system activity will return once Bluetooth has completed turning @@ -251,7 +288,6 @@ public final class BluetoothAdapter { */ public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23; - /** * Broadcast Action: The local Bluetooth adapter has started the remote * device discovery process. @@ -365,6 +401,8 @@ public final class BluetoothAdapter { private IBluetooth mService; private final Map<LeScanCallback, GattCallbackWrapper> mLeScanClients; + private BluetoothAdvScanData mBluetoothAdvScanData = null; + private GattCallbackWrapper mAdvertisingCallback; /** * Get a handle to the default local Bluetooth adapter. @@ -438,6 +476,97 @@ public final class BluetoothAdapter { } /** + * Returns a {@link BluetoothAdvScanData} object representing advertising data. + * @hide + */ + public BluetoothAdvScanData getAdvScanData() { + try { + IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); + if (iGatt == null) { + // BLE is not supported + Log.e(TAG, "failed to start, iGatt null"); + return null; + } + if (mBluetoothAdvScanData == null) { + mBluetoothAdvScanData = new BluetoothAdvScanData(iGatt, BluetoothAdvScanData.AD); + } + return mBluetoothAdvScanData; + } catch (RemoteException e) { + Log.e(TAG, "failed to get advScanData, error: " + e); + return null; + } + } + + + /** + * Start BLE advertising using current {@link BluetoothAdvScanData}. + * An app should start advertising by requesting + * {@link BluetoothAdapter#ACTION_START_ADVERTISING} instead of calling this method directly. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} + * + * @return true if BLE avertising succeeds, false otherwise. + * @hide + */ + public boolean startAdvertising() { + if (getState() != STATE_ON) return false; + + try { + IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); + if (iGatt == null) { + // BLE is not supported. + return false; + } + // Restart/reset advertising packets if advertising is in progress. + if (isAdvertising()) { + // Invalid advertising callback. + if (mAdvertisingCallback == null || mAdvertisingCallback.mLeHandle == -1) { + Log.e(TAG, "failed to restart advertising, invalid callback"); + return false; + } + iGatt.startAdvertising(mAdvertisingCallback.mLeHandle); + return true; + } + UUID uuid = UUID.randomUUID(); + GattCallbackWrapper wrapper = + new GattCallbackWrapper(this, null, null, GattCallbackWrapper.CALLBACK_TYPE_ADV); + iGatt.registerClient(new ParcelUuid(uuid), wrapper); + mAdvertisingCallback = wrapper; + return true; + } catch (RemoteException e) { + Log.e(TAG, "", e); + return false; + } + } + + /** + * Stop BLE advertising. + * An app should stop advertising by requesting + * {@link BluetoothAdapter#ACTION_STOP_ADVERTISING} instead of calling this method directly. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} + * @return true if BLE advertising stops, false otherwise. + * @hide + */ + public boolean stopAdvertisting() { + try { + IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); + if (iGatt == null) { + // BLE is not supported + return false; + } + if (mAdvertisingCallback == null) { + // no callback. + return false; + } + mAdvertisingCallback.stopAdvertising(); + mAdvertisingCallback = null; + return true; + } catch (RemoteException e) { + Log.e(TAG, "", e); + return false; + } + } + + /** * Return true if Bluetooth is currently enabled and ready for use. * <p>Equivalent to: * <code>getBluetoothState() == STATE_ON</code> @@ -849,6 +978,23 @@ public final class BluetoothAdapter { } /** + * Returns whether BLE is currently advertising. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. + * + * @hide + */ + public boolean isAdvertising() { + if (getState() != STATE_ON) return false; + try { + IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); + return iGatt.isAdvertising(); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + return false; + } + + /** * Return the set of {@link BluetoothDevice} objects that are bonded * (paired) to the local adapter. * <p>If Bluetooth state is not {@link #STATE_ON}, this API @@ -1546,8 +1692,12 @@ public final class BluetoothAdapter { private static class GattCallbackWrapper extends IBluetoothGattCallback.Stub { private static final int LE_CALLBACK_REG_TIMEOUT = 2000; private static final int LE_CALLBACK_REG_WAIT_COUNT = 5; + private static final int CALLBACK_TYPE_SCAN = 0; + private static final int CALLBACK_TYPE_ADV = 1; private final LeScanCallback mLeScanCb; + private int mCallbackType; + // mLeHandle 0: not registered // -1: scan stopped // >0: registered and scan started @@ -1561,6 +1711,16 @@ public final class BluetoothAdapter { mLeScanCb = leScanCb; mScanFilter = uuid; mLeHandle = 0; + mCallbackType = CALLBACK_TYPE_SCAN; + } + + public GattCallbackWrapper(BluetoothAdapter bluetoothAdapter, LeScanCallback leScanCb, + UUID[] uuid, int type) { + mBluetoothAdapter = new WeakReference<BluetoothAdapter>(bluetoothAdapter); + mLeScanCb = leScanCb; + mScanFilter = uuid; + mLeHandle = 0; + mCallbackType = type; } public boolean scanStarted() { @@ -1583,6 +1743,30 @@ public final class BluetoothAdapter { return started; } + public void stopAdvertising() { + synchronized (this) { + if (mLeHandle <= 0) { + Log.e(TAG, "Error state, mLeHandle: " + mLeHandle); + return; + } + BluetoothAdapter adapter = mBluetoothAdapter.get(); + if (adapter != null) { + try { + IBluetoothGatt iGatt = adapter.getBluetoothManager().getBluetoothGatt(); + iGatt.stopAdvertising(); + Log.d(TAG, "unregeistering client " + mLeHandle); + iGatt.unregisterClient(mLeHandle); + } catch (RemoteException e) { + Log.e(TAG, "Failed to stop advertising and unregister" + e); + } + } else { + Log.e(TAG, "stopAdvertising, BluetoothAdapter is null"); + } + mLeHandle = -1; + notifyAll(); + } + } + public void stopLeScan() { synchronized(this) { if (mLeHandle <= 0) { @@ -1624,14 +1808,18 @@ public final class BluetoothAdapter { BluetoothAdapter adapter = mBluetoothAdapter.get(); if (adapter != null) { iGatt = adapter.getBluetoothManager().getBluetoothGatt(); - if (mScanFilter == null) { - iGatt.startScan(mLeHandle, false); + if (mCallbackType == CALLBACK_TYPE_ADV) { + iGatt.startAdvertising(mLeHandle); } else { - ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length]; - for(int i = 0; i != uuids.length; ++i) { - uuids[i] = new ParcelUuid(mScanFilter[i]); - } - iGatt.startScanWithUuids(mLeHandle, false, uuids); + if (mScanFilter == null) { + iGatt.startScan(mLeHandle, false); + } else { + ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length]; + for(int i = 0; i != uuids.length; ++i) { + uuids[i] = new ParcelUuid(mScanFilter[i]); + } + iGatt.startScanWithUuids(mLeHandle, false, uuids); + } } } else { Log.e(TAG, "onClientRegistered, BluetoothAdapter null"); @@ -1642,7 +1830,7 @@ public final class BluetoothAdapter { mLeHandle = -1; } if (mLeHandle == -1) { - // registration succeeded but start scan failed + // registration succeeded but start scan or advertise failed if (iGatt != null) { try { iGatt.unregisterClient(mLeHandle); diff --git a/core/java/android/bluetooth/BluetoothAdvScanData.java b/core/java/android/bluetooth/BluetoothAdvScanData.java new file mode 100644 index 000000000000..a97b0a806e38 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothAdvScanData.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; +import android.os.ParcelUuid; +import android.os.RemoteException; +import android.util.Log; + +import java.util.Collections; +import java.util.List; + + +/** + * This class provides the public APIs to set advertising and scan response data when BLE device + * operates in peripheral mode. <br> + * The exact format is defined in Bluetooth 4.0 specification, Volume 3, Part C, Section 11 + * @hide + */ +public final class BluetoothAdvScanData { + + /** + * Available data types of {@link BluetoothAdvScanData}. + */ + public static final int AD = 0; // Advertising Data + public static final int SCAN_RESPONSE = 1; // Scan Response + public static final int EIR = 2; // Extended Inquiry Response + + private static final String TAG = "BluetoothAdvScanData"; + + /** + * Data type of BluetoothAdvScanData. + */ + private final int mDataType; + /** + * Bluetooth Gatt Service. + */ + private IBluetoothGatt mBluetoothGatt; + + /** + * @param mBluetoothGatt + * @param dataType + */ + public BluetoothAdvScanData(IBluetoothGatt mBluetoothGatt, int dataType) { + this.mBluetoothGatt = mBluetoothGatt; + this.mDataType = dataType; + } + + /** + * @return advertising data type. + */ + public int getDataType() { + return mDataType; + } + + /** + * Set manufactureCode and manufactureData. + * Returns true if manufacturer data is set, false if there is no enough room to set + * manufacturer data or the data is already set. + * @param manufacturerCode - unique identifier for the manufacturer + * @param manufacturerData - data associated with the specific manufacturer. + */ + public boolean setManufacturerData(int manufacturerCode, byte[] manufacturerData) { + if (mDataType != AD) return false; + try { + return mBluetoothGatt.setAdvManufacturerCodeAndData(manufacturerCode, manufacturerData); + } catch (RemoteException e) { + return false; + } + } + + /** + * Set service data. Note the service data can only be set when the data type is {@code AD}; + * @param serviceData + */ + public boolean setServiceData(byte[] serviceData) { + + if (mDataType != AD) return false; + if (serviceData == null) return false; + try { + return mBluetoothGatt.setAdvServiceData(serviceData); + } catch (RemoteException e) { + return false; + } + } + + /** + * Returns an immutable list of service uuids that will be advertised. + */ + public List<ParcelUuid> getServiceUuids() { + try { + return Collections.unmodifiableList(mBluetoothGatt.getAdvServiceUuids()); + } catch (RemoteException e) { + return null; + } + } + + /** + * Returns manufacturer data. + */ + public byte[] getManufacturerData() { + if (mBluetoothGatt == null) return null; + try { + return mBluetoothGatt.getAdvManufacturerData(); + } catch (RemoteException e) { + return null; + } + } + + /** + * Returns service data. + */ + public byte[] getServiceData() { + if (mBluetoothGatt == null) return null; + try { + return mBluetoothGatt.getAdvServiceData(); + } catch (RemoteException e) { + return null; + } + } + + /** + * Remove manufacturer data based on given manufacturer code. + * @param manufacturerCode + */ + public void removeManufacturerCodeAndData(int manufacturerCode) { + if (mBluetoothGatt != null) { + try { + mBluetoothGatt.removeAdvManufacturerCodeAndData(manufacturerCode); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } + } +} diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index a2bb78c4c158..cd093c5a4419 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -553,14 +553,6 @@ public final class BluetoothGatt implements BluetoothProfile { Log.w(TAG, "Unhandled exception in callback", ex); } } - - /** - * Listen command status callback - * @hide - */ - public void onListen(int status) { - if (DBG) Log.d(TAG, "onListen() - status=" + status); - } }; /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device) { @@ -693,71 +685,6 @@ public final class BluetoothGatt implements BluetoothProfile { return true; } - /** - * Starts or stops sending of advertisement packages to listen for connection - * requests from a central devices. - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. - * - * @param start Start or stop advertising - */ - /*package*/ void listen(boolean start) { - if (mContext == null || !mContext.getResources(). - getBoolean(com.android.internal.R.bool.config_bluetooth_le_peripheral_mode_supported)) { - throw new UnsupportedOperationException("BluetoothGatt#listen is blocked"); - } - if (DBG) Log.d(TAG, "listen() - start: " + start); - if (mService == null || mClientIf == 0) return; - - try { - mService.clientListen(mClientIf, start); - } catch (RemoteException e) { - Log.e(TAG,"",e); - } - } - - /** - * Sets the advertising data contained in the adv. response packet. - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. - * - * @param advData true to set adv. data, false to set scan response - * @param includeName Inlucde the name in the adv. response - * @param includeTxPower Include TX power value - * @param minInterval Minimum desired scan interval (optional) - * @param maxInterval Maximum desired scan interval (optional) - * @param appearance The appearance flags for the device (optional) - * @param manufacturerData Manufacturer specific data including company ID (optional) - */ - /*package*/ void setAdvData(boolean advData, boolean includeName, boolean includeTxPower, - Integer minInterval, Integer maxInterval, - Integer appearance, Byte[] manufacturerData) { - if (mContext == null || !mContext.getResources(). - getBoolean(com.android.internal.R.bool.config_bluetooth_le_peripheral_mode_supported)) { - throw new UnsupportedOperationException("BluetoothGatt#setAdvData is blocked"); - } - if (DBG) Log.d(TAG, "setAdvData()"); - if (mService == null || mClientIf == 0) return; - - byte[] data = new byte[0]; - if (manufacturerData != null) { - data = new byte[manufacturerData.length]; - for(int i = 0; i != manufacturerData.length; ++i) { - data[i] = manufacturerData[i]; - } - } - - try { - mService.setAdvData(mClientIf, !advData, - includeName, includeTxPower, - minInterval != null ? minInterval : 0, - maxInterval != null ? maxInterval : 0, - appearance != null ? appearance : 0, data); - } catch (RemoteException e) { - Log.e(TAG,"",e); - } - } - /** * Disconnects an established connection, or cancels a connection attempt * currently in progress. diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java index 58ee54fdb100..153215cb5256 100644 --- a/core/java/android/bluetooth/BluetoothGattServer.java +++ b/core/java/android/bluetooth/BluetoothGattServer.java @@ -537,7 +537,7 @@ public final class BluetoothGattServer implements BluetoothProfile { try { mService.beginServiceDeclaration(mServerIf, service.getType(), service.getInstanceId(), service.getHandles(), - new ParcelUuid(service.getUuid())); + new ParcelUuid(service.getUuid()), service.isAdvertisePreferred()); List<BluetoothGattService> includedServices = service.getIncludedServices(); for (BluetoothGattService includedService : includedServices) { diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java index 1e6636960105..52bc0f796cb5 100644 --- a/core/java/android/bluetooth/BluetoothGattService.java +++ b/core/java/android/bluetooth/BluetoothGattService.java @@ -15,8 +15,6 @@ */ package android.bluetooth; -import android.bluetooth.BluetoothDevice; - import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -82,6 +80,11 @@ public class BluetoothGattService { protected List<BluetoothGattService> mIncludedServices; /** + * Whether the service uuid should be advertised. + */ + private boolean mAdvertisePreferred; + + /** * Create a new BluetoothGattService. * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * @@ -263,4 +266,20 @@ public class BluetoothGattService { } return null; } + + /** + * Returns whether the uuid of the service should be advertised. + * @hide + */ + public boolean isAdvertisePreferred() { + return mAdvertisePreferred; + } + + /** + * Set whether the service uuid should be advertised. + * @hide + */ + public void setAdvertisePreferred(boolean advertisePreferred) { + this.mAdvertisePreferred = advertisePreferred; + } } diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java index 844f432ca32f..33232edf58cc 100644 --- a/core/java/android/bluetooth/BluetoothInputDevice.java +++ b/core/java/android/bluetooth/BluetoothInputDevice.java @@ -76,6 +76,12 @@ public final class BluetoothInputDevice implements BluetoothProfile { public static final String ACTION_PROTOCOL_MODE_CHANGED = "android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED"; + /** + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_REPORT = + "android.bluetooth.input.profile.action.REPORT"; /** * @hide @@ -130,17 +136,17 @@ public final class BluetoothInputDevice implements BluetoothProfile { /** * @hide */ - public static final byte REPORT_TYPE_INPUT = 0; + public static final byte REPORT_TYPE_INPUT = 1; /** * @hide */ - public static final byte REPORT_TYPE_OUTPUT = 1; + public static final byte REPORT_TYPE_OUTPUT = 2; /** * @hide */ - public static final byte REPORT_TYPE_FEATURE = 2; + public static final byte REPORT_TYPE_FEATURE = 3; /** * @hide diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java index d10eaea2fba1..1e75fc2a1c01 100644 --- a/core/java/android/bluetooth/BluetoothSocket.java +++ b/core/java/android/bluetooth/BluetoothSocket.java @@ -417,27 +417,28 @@ public final class BluetoothSocket implements Closeable { * if an i/o error occurs. */ /*package*/ void flush() throws IOException { + if (mSocketOS == null) throw new IOException("flush is called on null OutputStream"); if (VDBG) Log.d(TAG, "flush: " + mSocketOS); mSocketOS.flush(); } /*package*/ int read(byte[] b, int offset, int length) throws IOException { - - if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); - int ret = mSocketIS.read(b, offset, length); - if(ret < 0) - throw new IOException("bt socket closed, read return: " + ret); - if (VDBG) Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret); - return ret; + if (mSocketIS == null) throw new IOException("read is called on null InputStream"); + if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); + int ret = mSocketIS.read(b, offset, length); + if(ret < 0) + throw new IOException("bt socket closed, read return: " + ret); + if (VDBG) Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret); + return ret; } /*package*/ int write(byte[] b, int offset, int length) throws IOException { - - if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length); - mSocketOS.write(b, offset, length); - // There is no good way to confirm since the entire process is asynchronous anyway - if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length); - return length; + if (mSocketOS == null) throw new IOException("write is called on null OutputStream"); + if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length); + mSocketOS.write(b, offset, length); + // There is no good way to confirm since the entire process is asynchronous anyway + if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length); + return length; } @Override diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java index abdf949ebcfd..4b28516e15a2 100644 --- a/core/java/android/bluetooth/BluetoothUuid.java +++ b/core/java/android/bluetooth/BluetoothUuid.java @@ -73,6 +73,9 @@ public final class BluetoothUuid { public static final ParcelUuid MAS = ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB"); + public static final ParcelUuid BASE_UUID = + ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB"); + public static final ParcelUuid[] RESERVED_UUIDS = { AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget, @@ -211,4 +214,17 @@ public final class BluetoothUuid { long value = (uuid.getMostSignificantBits() & 0x0000FFFF00000000L) >>> 32; return (int)value; } + + /** + * Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid. + * @param parcelUuid + * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise. + */ + public static boolean isShortUuid(ParcelUuid parcelUuid) { + UUID uuid = parcelUuid.getUuid(); + if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { + return false; + } + return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L); + } } diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl index df393dbb2899..784cdcc5318c 100644 --- a/core/java/android/bluetooth/IBluetoothGatt.aidl +++ b/core/java/android/bluetooth/IBluetoothGatt.aidl @@ -37,10 +37,15 @@ interface IBluetoothGatt { void unregisterClient(in int clientIf); void clientConnect(in int clientIf, in String address, in boolean isDirect); void clientDisconnect(in int clientIf, in String address); - void clientListen(in int clientIf, in boolean start); - void setAdvData(in int clientIf, in boolean setScanRsp, in boolean inclName, - in boolean inclTxPower, in int minInterval, in int maxInterval, - in int appearance, in byte[] manufacturerData); + void startAdvertising(in int appIf); + void stopAdvertising(); + boolean setAdvServiceData(in byte[] serviceData); + byte[] getAdvServiceData(); + boolean setAdvManufacturerCodeAndData(int manufactureCode, in byte[] manufacturerData); + byte[] getAdvManufacturerData(); + List<ParcelUuid> getAdvServiceUuids(); + void removeAdvManufacturerCodeAndData(int manufacturerCode); + boolean isAdvertising(); void refreshDevice(in int clientIf, in String address); void discoverServices(in int clientIf, in String address); void readCharacteristic(in int clientIf, in String address, in int srvcType, @@ -75,7 +80,7 @@ interface IBluetoothGatt { void serverDisconnect(in int serverIf, in String address); void beginServiceDeclaration(in int serverIf, in int srvcType, in int srvcInstanceId, in int minHandles, - in ParcelUuid srvcId); + in ParcelUuid srvcId, boolean advertisePreferred); void addIncludedService(in int serverIf, in int srvcType, in int srvcInstanceId, in ParcelUuid srvcId); void addCharacteristic(in int serverIf, in ParcelUuid charId, diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl index 60c297b59798..e3563fcc3a77 100644 --- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl +++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl @@ -63,5 +63,4 @@ interface IBluetoothGattCallback { in int charInstId, in ParcelUuid charUuid, in byte[] value); void onReadRemoteRssi(in String address, in int rssi, in int status); - void onListen(in int status); } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 3c66b6871f74..11ac15fbe0a4 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -3538,6 +3538,11 @@ public class Intent implements Parcelable, Cloneable { * it will be finished so that the user does not return to them, but * instead returns to whatever activity preceeded it. * + * <p>When this flag is assigned to the root activity all activities up + * to, but not including the root activity, will be cleared. This prevents + * this flag from being used to finish all activities in a task and thereby + * ending the task. + * * <p>This is useful for cases where you have a logical break in your * application. For example, an e-mail application may have a command * to view an attachment, which launches an image view activity to diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index c97c2b89304d..ddf0ed6259b2 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1249,6 +1249,29 @@ public abstract class PackageManager { public static final String FEATURE_TELEVISION = "android.hardware.type.television"; /** + * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature}: This is a device dedicated to showing UI + * on a watch. A watch here is defined to be a device worn on the body, perhaps on + * the wrist. The user is very close when interacting with the device. + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_WATCH = "android.hardware.type.watch"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: + * The device supports printing. + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_PRINTING = "android.software.print"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: + * The device can perform backup and restore operations on installed applications. + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_BACKUP = "android.software.backup"; + + /** * Action to external storage service to clean out removed apps. * @hide */ diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index 60ccc6180eb6..433d5d1c713e 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -738,14 +738,16 @@ public final class SQLiteDatabase extends SQLiteClosable { File dir = file.getParentFile(); if (dir != null) { final String prefix = file.getName() + "-mj"; - final FileFilter filter = new FileFilter() { + File[] files = dir.listFiles(new FileFilter() { @Override public boolean accept(File candidate) { return candidate.getName().startsWith(prefix); } - }; - for (File masterJournal : dir.listFiles(filter)) { - deleted |= masterJournal.delete(); + }); + if (files != null) { + for (File masterJournal : files) { + deleted |= masterJournal.delete(); + } } } return deleted; diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 093e0e9270ff..a517bc5d71c6 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -115,6 +115,7 @@ public final class DisplayManager { * </p> * * @see #createVirtualDisplay + * @see #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY */ public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1 << 0; @@ -171,6 +172,22 @@ public final class DisplayManager { */ public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 1 << 2; + /** + * Virtual display flag: Only show this display's own content; do not mirror + * the content of another display. + * + * <p> + * This flag is used in conjunction with {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}. + * Ordinarily public virtual displays will automatically mirror the content of the + * default display if they have no windows of their own. When this flag is + * specified, the virtual display will only ever show its own content and + * will be blanked instead if it has no windows. + * </p> + * + * @see #createVirtualDisplay + */ + public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 1 << 3; + /** @hide */ public DisplayManager(Context context) { mContext = context; @@ -429,8 +446,8 @@ public final class DisplayManager { * @param surface The surface to which the content of the virtual display should * be rendered, must be non-null. * @param flags A combination of virtual display flags: - * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION} - * or {@link #VIRTUAL_DISPLAY_FLAG_SECURE}. + * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION}, + * {@link #VIRTUAL_DISPLAY_FLAG_SECURE}, or {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}. * @return The newly created virtual display, or null if the application could * not create the virtual display. * diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java new file mode 100644 index 000000000000..8430973c79d3 --- /dev/null +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.display; + +import android.view.DisplayInfo; + +/** + * Display manager local system service interface. + * + * @hide Only for use within the system server. + */ +public abstract class DisplayManagerInternal { + /** + * Called by the power manager to blank all displays. + */ + public abstract void blankAllDisplaysFromPowerManager(); + + /** + * Called by the power manager to unblank all displays. + */ + public abstract void unblankAllDisplaysFromPowerManager(); + + /** + * Returns information about the specified logical display. + * + * @param displayId The logical display id. + * @return The logical display info, or null if the display does not exist. The + * returned object must be treated as immutable. + */ + public abstract DisplayInfo getDisplayInfo(int displayId); + + /** + * Registers a display transaction listener to provide the client a chance to + * update its surfaces within the same transaction as any display layout updates. + * + * @param listener The listener to register. + */ + public abstract void registerDisplayTransactionListener(DisplayTransactionListener listener); + + /** + * Unregisters a display transaction listener to provide the client a chance to + * update its surfaces within the same transaction as any display layout updates. + * + * @param listener The listener to unregister. + */ + public abstract void unregisterDisplayTransactionListener(DisplayTransactionListener listener); + + /** + * Overrides the display information of a particular logical display. + * This is used by the window manager to control the size and characteristics + * of the default display. It is expected to apply the requested change + * to the display information synchronously so that applications will immediately + * observe the new state. + * + * NOTE: This method must be the only entry point by which the window manager + * influences the logical configuration of displays. + * + * @param displayId The logical display id. + * @param info The new data to be stored. + */ + public abstract void setDisplayInfoOverrideFromWindowManager( + int displayId, DisplayInfo info); + + /** + * Called by the window manager to perform traversals while holding a + * surface flinger transaction. + */ + public abstract void performTraversalInTransactionFromWindowManager(); + + /** + * Tells the display manager whether there is interesting unique content on the + * specified logical display. This is used to control automatic mirroring. + * <p> + * If the display has unique content, then the display manager arranges for it + * to be presented on a physical display if appropriate. Otherwise, the display manager + * may choose to make the physical display mirror some other logical display. + * </p> + * + * @param displayId The logical display id to update. + * @param hasContent True if the logical display has content. + * @param inTraversal True if called from WindowManagerService during a window traversal + * prior to call to performTraversalInTransactionFromWindowManager. + */ + public abstract void setDisplayHasContent(int displayId, boolean hasContent, + boolean inTraversal); + + /** + * Called within a Surface transaction whenever the size or orientation of a + * display may have changed. Provides an opportunity for the client to + * update the position of its surfaces as part of the same transaction. + */ + public interface DisplayTransactionListener { + void onDisplayTransaction(); + } +} diff --git a/services/java/com/android/server/display/DisplayViewport.java b/core/java/android/hardware/display/DisplayViewport.java index 5080556a54a3..c2d498b7fe68 100644 --- a/services/java/com/android/server/display/DisplayViewport.java +++ b/core/java/android/hardware/display/DisplayViewport.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.display; +package android.hardware.display; import android.graphics.Rect; @@ -25,6 +25,8 @@ import android.graphics.Rect; * This information is used by the input system to translate touch input from * physical display coordinates into logical display coordinates. * </p> + * + * @hide Only for use within the system server. */ public final class DisplayViewport { // True if this viewport is valid. diff --git a/core/java/android/hardware/input/InputManagerInternal.java b/core/java/android/hardware/input/InputManagerInternal.java new file mode 100644 index 000000000000..8be94d0f7e85 --- /dev/null +++ b/core/java/android/hardware/input/InputManagerInternal.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.input; + +import android.hardware.display.DisplayViewport; +import android.view.InputEvent; + +/** + * Input manager local system service interface. + * + * @hide Only for use within the system server. + */ +public abstract class InputManagerInternal { + /** + * Sets information about the displays as needed by the input system. + * The input system should copy this information if required. + */ + public abstract void setDisplayViewports(DisplayViewport defaultViewport, + DisplayViewport externalTouchViewport); + + public abstract boolean injectInputEvent(InputEvent event, int displayId, int mode); +} diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index c78a973ceeb0..9ae4fa2f9da5 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -361,11 +361,17 @@ public class ConnectivityManager { */ public static final int TYPE_MOBILE_IA = 14; + /** + * The network that uses proxy to achieve connectivity. + * {@hide} + */ + public static final int TYPE_PROXY = 16; + /** {@hide} */ - public static final int MAX_RADIO_TYPE = TYPE_MOBILE_IA; + public static final int MAX_RADIO_TYPE = TYPE_PROXY; /** {@hide} */ - public static final int MAX_NETWORK_TYPE = TYPE_MOBILE_IA; + public static final int MAX_NETWORK_TYPE = TYPE_PROXY; /** * If you want to set the default network preference,you can directly @@ -444,6 +450,8 @@ public class ConnectivityManager { return "WIFI_P2P"; case TYPE_MOBILE_IA: return "MOBILE_IA"; + case TYPE_PROXY: + return "PROXY"; default: return Integer.toString(type); } diff --git a/core/java/android/net/ProxyDataTracker.java b/core/java/android/net/ProxyDataTracker.java new file mode 100644 index 000000000000..461e8b80212a --- /dev/null +++ b/core/java/android/net/ProxyDataTracker.java @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.os.UserHandle; +import android.util.Log; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * A data tracker responsible for bringing up and tearing down the system proxy server. + * + * {@hide} + */ +public class ProxyDataTracker extends BaseNetworkStateTracker { + private static final String TAG = "ProxyDataTracker"; + private static final String NETWORK_TYPE = "PROXY"; + + // TODO: investigate how to get these DNS addresses from the system. + private static final String DNS1 = "8.8.8.8"; + private static final String DNS2 = "8.8.4.4"; + private static final String REASON_ENABLED = "enabled"; + private static final String REASON_DISABLED = "disabled"; + private static final String REASON_PROXY_DOWN = "proxy_down"; + + private static final int MSG_TEAR_DOWN_REQUEST = 1; + private static final int MSG_SETUP_REQUEST = 2; + + private static final String PERMISSION_PROXY_STATUS_SENDER = + "android.permission.ACCESS_NETWORK_CONDITIONS"; + private static final String ACTION_PROXY_STATUS_CHANGE = + "com.android.net.PROXY_STATUS_CHANGE"; + private static final String KEY_IS_PROXY_AVAILABLE = "is_proxy_available"; + private static final String KEY_REPLY_TO_MESSENGER_BINDER = "reply_to_messenger_binder"; + private static final String KEY_REPLY_TO_MESSENGER_BINDER_BUNDLE = + "reply_to_messenger_binder_bundle"; + + private Handler mTarget; + private Messenger mProxyStatusService; + private AtomicBoolean mReconnectRequested = new AtomicBoolean(false); + private AtomicBoolean mIsProxyAvailable = new AtomicBoolean(false); + private final AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0); + + private final BroadcastReceiver mProxyStatusServiceListener = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(ACTION_PROXY_STATUS_CHANGE)) { + mIsProxyAvailable.set(intent.getBooleanExtra(KEY_IS_PROXY_AVAILABLE, false)); + if (mIsProxyAvailable.get()) { + Bundle bundle = intent.getBundleExtra(KEY_REPLY_TO_MESSENGER_BINDER_BUNDLE); + if (bundle == null || bundle.getBinder(KEY_REPLY_TO_MESSENGER_BINDER) == null) { + Log.e(TAG, "no messenger binder in the intent to send future requests"); + mIsProxyAvailable.set(false); + return; + } + mProxyStatusService = + new Messenger(bundle.getBinder(KEY_REPLY_TO_MESSENGER_BINDER)); + // If there is a pending reconnect request, do it now. + if (mReconnectRequested.get()) { + reconnect(); + } + } else { + setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, + REASON_PROXY_DOWN, null); + } + } else { + Log.d(TAG, "Unrecognized broadcast intent"); + } + } + }; + + /** + * Create a new ProxyDataTracker + */ + public ProxyDataTracker() { + mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_PROXY, 0, NETWORK_TYPE, ""); + mLinkProperties = new LinkProperties(); + mLinkCapabilities = new LinkCapabilities(); + mNetworkInfo.setIsAvailable(true); + try { + mLinkProperties.addDns(InetAddress.getByName(DNS1)); + mLinkProperties.addDns(InetAddress.getByName(DNS2)); + } catch (UnknownHostException e) { + Log.e(TAG, "Could not add DNS address", e); + } + } + + public Object Clone() throws CloneNotSupportedException { + throw new CloneNotSupportedException(); + } + + @Override + public void startMonitoring(Context context, Handler target) { + mContext = context; + mTarget = target; + mContext.registerReceiver(mProxyStatusServiceListener, + new IntentFilter(ACTION_PROXY_STATUS_CHANGE), + PERMISSION_PROXY_STATUS_SENDER, + null); + } + + /** + * Disable connectivity to the network. + */ + public boolean teardown() { + setTeardownRequested(true); + mReconnectRequested.set(false); + try { + if (mIsProxyAvailable.get() && mProxyStatusService != null) { + mProxyStatusService.send(Message.obtain(null, MSG_TEAR_DOWN_REQUEST)); + } + } catch (RemoteException e) { + Log.e(TAG, "Unable to connect to proxy status service", e); + return false; + } + setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, REASON_DISABLED, null); + return true; + } + + /** + * Re-enable proxy data connectivity after a {@link #teardown()}. + */ + public boolean reconnect() { + mReconnectRequested.set(true); + setTeardownRequested(false); + if (!mIsProxyAvailable.get()) { + Log.w(TAG, "Reconnect requested even though proxy service is not up. Bailing."); + return false; + } + setDetailedState(NetworkInfo.DetailedState.CONNECTING, REASON_ENABLED, null); + + try { + mProxyStatusService.send(Message.obtain(null, MSG_SETUP_REQUEST)); + } catch (RemoteException e) { + Log.e(TAG, "Unable to connect to proxy status service", e); + setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, REASON_PROXY_DOWN, null); + return false; + } + // We'll assume proxy is set up successfully. If not, a status change broadcast will be + // received afterwards to indicate any failure. + setDetailedState(NetworkInfo.DetailedState.CONNECTED, REASON_ENABLED, null); + return true; + } + + /** + * Fetch default gateway address for the network + */ + public int getDefaultGatewayAddr() { + return mDefaultGatewayAddr.get(); + } + + /** + * Return the system properties name associated with the tcp buffer sizes + * for this network. + */ + public String getTcpBufferSizesPropName() { + return "net.tcp.buffersize.wifi"; + } + + /** + * Record the detailed state of a network, and if it is a + * change from the previous state, send a notification to + * any listeners. + * @param state the new @{code DetailedState} + * @param reason a {@code String} indicating a reason for the state change, + * if one was supplied. May be {@code null}. + * @param extraInfo optional {@code String} providing extra information about the state change + */ + private void setDetailedState(NetworkInfo.DetailedState state, String reason, + String extraInfo) { + mNetworkInfo.setDetailedState(state, reason, extraInfo); + Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo); + msg.sendToTarget(); + } +} diff --git a/core/java/android/os/FactoryTest.java b/core/java/android/os/FactoryTest.java index ec996973fdb0..7a252f933446 100644 --- a/core/java/android/os/FactoryTest.java +++ b/core/java/android/os/FactoryTest.java @@ -25,6 +25,20 @@ package android.os; * {@hide} */ public final class FactoryTest { + public static final int FACTORY_TEST_OFF = 0; + public static final int FACTORY_TEST_LOW_LEVEL = 1; + public static final int FACTORY_TEST_HIGH_LEVEL = 2; + + /** + * Gets the current factory test mode. + * + * @return One of: {@link #FACTORY_TEST_OFF}, {@link #FACTORY_TEST_LOW_LEVEL}, + * or {@link #FACTORY_TEST_HIGH_LEVEL}. + */ + public static int getMode() { + return SystemProperties.getInt("ro.factorytest", FACTORY_TEST_OFF); + } + /** * When true, long-press on power should immediately cause the device to * shut down, without prompting the user. diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 5e0d48949c22..86ef4796d75e 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -191,6 +191,18 @@ public final class PowerManager { public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020; /** + * Wake lock level: Put the screen in a low power state and allow the CPU to suspend + * if no other wake locks are held. + * <p> + * This is used by the dream manager to implement doze mode. It currently + * has no effect unless the power manager is in the dozing state. + * </p> + * + * {@hide} + */ + public static final int DOZE_WAKE_LOCK = 0x00000040; + + /** * Mask for the wake lock level component of a combined wake lock level and flags integer. * * @hide @@ -418,6 +430,7 @@ public final class PowerManager { case SCREEN_BRIGHT_WAKE_LOCK: case FULL_WAKE_LOCK: case PROXIMITY_SCREEN_OFF_WAKE_LOCK: + case DOZE_WAKE_LOCK: break; default: throw new IllegalArgumentException("Must specify a valid wake lock level."); diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java new file mode 100644 index 000000000000..cb3d52819825 --- /dev/null +++ b/core/java/android/os/PowerManagerInternal.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +import android.view.WindowManagerPolicy; + +/** + * Power manager local system service interface. + * + * @hide Only for use within the system server. + */ +public abstract class PowerManagerInternal { + /** + * Used by the window manager to override the screen brightness based on the + * current foreground activity. + * + * This method must only be called by the window manager. + * + * @param brightness The overridden brightness, or -1 to disable the override. + */ + public abstract void setScreenBrightnessOverrideFromWindowManager(int brightness); + + /** + * Used by the window manager to override the button brightness based on the + * current foreground activity. + * + * This method must only be called by the window manager. + * + * @param brightness The overridden brightness, or -1 to disable the override. + */ + public abstract void setButtonBrightnessOverrideFromWindowManager(int brightness); + + /** + * Used by the window manager to override the user activity timeout based on the + * current foreground activity. It can only be used to make the timeout shorter + * than usual, not longer. + * + * This method must only be called by the window manager. + * + * @param timeoutMillis The overridden timeout, or -1 to disable the override. + */ + public abstract void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis); + + // TODO: Remove this and retrieve as a local service instead. + public abstract void setPolicy(WindowManagerPolicy policy); +} diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 631edd67957b..057f516af17b 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -892,19 +892,6 @@ public class Process { } /** - * Set the out-of-memory badness adjustment for a process. - * - * @param pid The process identifier to set. - * @param amt Adjustment value -- linux allows -16 to +15. - * - * @return Returns true if the underlying system supports this - * feature, else false. - * - * {@hide} - */ - public static final native boolean setOomAdj(int pid, int amt); - - /** * Adjust the swappiness level for a process. * * @param pid The process identifier to set. diff --git a/core/java/android/service/dreams/DozeHardware.java b/core/java/android/service/dreams/DozeHardware.java new file mode 100644 index 000000000000..b5e7f436cd25 --- /dev/null +++ b/core/java/android/service/dreams/DozeHardware.java @@ -0,0 +1,77 @@ +/** + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.service.dreams; + +import android.os.RemoteException; +import android.util.Log; + +/** + * Provides access to low-level hardware features that a dream may use to provide + * a richer user experience while dozing. + * <p> + * This class contains functions that should be called by the dream to configure + * hardware before starting to doze and allowing the application processor to suspend. + * For example, the dream may provide the hardware with enough information to render + * some content on its own without any further assistance from the application processor. + * </p><p> + * This object is obtained by calling {@link DreamService#getDozeHardware()}. + * </p> + * + * @hide experimental + */ +public final class DozeHardware { + private static final String TAG = "DozeHardware"; + + public static final String MSG_ENABLE_MCU = "enable_mcu"; + + public static final byte[] VALUE_ON = "on".getBytes(); + public static final byte[] VALUE_OFF = "off".getBytes(); + + private final IDozeHardware mHardware; + + DozeHardware(IDozeHardware hardware) { + mHardware = hardware; + } + + /** + * Sets whether to enable the microcontroller. + * + * @param enable If true, enables the MCU otherwise disables it. + */ + public void setEnableMcu(boolean enable) { + sendMessage(MSG_ENABLE_MCU, enable ? VALUE_ON : VALUE_OFF); + } + + /** + * Sends a message to the doze hardware module. + * + * @param msg The name of the message to send. + * @param arg An optional argument data blob, may be null. + * @return A result data blob, may be null. + */ + public byte[] sendMessage(String msg, byte[] arg) { + if (msg == null) { + throw new IllegalArgumentException("msg must not be null"); + } + + try { + return mHardware.sendMessage(msg, arg); + } catch (RemoteException ex) { + Log.e(TAG, "Failed to send message to doze hardware module.", ex); + return null; + } + } +} diff --git a/core/java/android/service/dreams/DreamManagerInternal.java b/core/java/android/service/dreams/DreamManagerInternal.java new file mode 100644 index 000000000000..9f7ddbac571b --- /dev/null +++ b/core/java/android/service/dreams/DreamManagerInternal.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.dreams; + +/** + * Dream manager local system service interface. + * + * @hide Only for use within the system server. + */ +public abstract class DreamManagerInternal { + /** + * Called by the power manager to start a dream. + */ + public abstract void startDream(boolean doze); + + /** + * Called by the power manager to stop a dream. + */ + public abstract void stopDream(); + + /** + * Called by the power manager to determine whether a dream is running. + */ + public abstract boolean isDreaming(); +} diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index f6b6c89cbd48..1abb1d72a98b 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -20,12 +20,14 @@ import java.io.PrintWriter; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.app.AlarmManager; import android.app.Service; import android.content.Intent; import android.graphics.PixelFormat; import android.graphics.drawable.ColorDrawable; import android.os.Handler; import android.os.IBinder; +import android.os.RemoteException; import android.os.ServiceManager; import android.util.Slog; import android.view.ActionMode; @@ -42,6 +44,8 @@ import android.view.WindowManager.LayoutParams; import android.view.accessibility.AccessibilityEvent; import com.android.internal.policy.PolicyManager; +import com.android.internal.util.DumpUtils; +import com.android.internal.util.DumpUtils.Dump; /** * Extend this class to implement a custom dream (available to the user as a "Daydream"). @@ -145,19 +149,26 @@ public class DreamService extends Service implements Window.Callback { */ public static final String DREAM_META_DATA = "android.service.dream"; + private final IDreamManager mSandman; private final Handler mHandler = new Handler(); private IBinder mWindowToken; private Window mWindow; private WindowManager mWindowManager; - private IDreamManager mSandman; private boolean mInteractive = false; private boolean mLowProfile = true; private boolean mFullscreen = false; private boolean mScreenBright = true; private boolean mFinished; + private boolean mCanDoze; + private boolean mDozing; + private DozeHardware mDozeHardware; private boolean mDebug = false; + public DreamService() { + mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE)); + } + /** * @hide */ @@ -444,9 +455,11 @@ public class DreamService extends Service implements Window.Callback { * correct interactions with it (seeing when it is cleared etc). */ public void setLowProfile(boolean lowProfile) { - mLowProfile = lowProfile; - int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE; - applySystemUiVisibilityFlags(mLowProfile ? flag : 0, flag); + if (mLowProfile != lowProfile) { + mLowProfile = lowProfile; + int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE; + applySystemUiVisibilityFlags(mLowProfile ? flag : 0, flag); + } } /** @@ -467,9 +480,11 @@ public class DreamService extends Service implements Window.Callback { * will be cleared. */ public void setFullscreen(boolean fullscreen) { - mFullscreen = fullscreen; - int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN; - applyWindowFlags(mFullscreen ? flag : 0, flag); + if (mFullscreen != fullscreen) { + mFullscreen = fullscreen; + int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN; + applyWindowFlags(mFullscreen ? flag : 0, flag); + } } /** @@ -487,14 +502,16 @@ public class DreamService extends Service implements Window.Callback { * @param screenBright True to keep the screen bright while dreaming. */ public void setScreenBright(boolean screenBright) { - mScreenBright = screenBright; - int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; - applyWindowFlags(mScreenBright ? flag : 0, flag); + if (mScreenBright != screenBright) { + mScreenBright = screenBright; + int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; + applyWindowFlags(mScreenBright ? flag : 0, flag); + } } /** - * Returns whether or not this dream keeps the screen bright while dreaming. Defaults to false, - * allowing the screen to dim if necessary. + * Returns whether or not this dream keeps the screen bright while dreaming. + * Defaults to false, allowing the screen to dim if necessary. * * @see #setScreenBright(boolean) */ @@ -503,6 +520,119 @@ public class DreamService extends Service implements Window.Callback { } /** + * Returns true if this dream is allowed to doze. + * <p> + * The value returned by this method is only meaningful when the dream has started. + * </p> + * + * @return True if this dream can doze. + * @see #startDozing + * @hide experimental + */ + public boolean canDoze() { + return mCanDoze; + } + + /** + * Starts dozing, entering a deep dreamy sleep. + * <p> + * Dozing enables the system to conserve power while the user is not actively interacting + * with the device. While dozing, the display will remain on in a low-power state + * and will continue to show its previous contents but the application processor and + * other system components will be allowed to suspend when possible. + * </p><p> + * While the application processor is suspended, the dream may stop executing code + * for long periods of time. Prior to being suspended, the dream may schedule periodic + * wake-ups to render new content by scheduling an alarm with the {@link AlarmManager}. + * The dream may also keep the CPU awake by acquiring a + * {@link android.os.PowerManager#PARTIAL_WAKE_LOCK partial wake lock} when necessary. + * Note that since the purpose of doze mode is to conserve power (especially when + * running on battery), the dream should not wake the CPU very often or keep it + * awake for very long. + * </p><p> + * It is a good idea to call this method some time after the dream's entry animation + * has completed and the dream is ready to doze. It is important to completely + * finish all of the work needed before dozing since the application processor may + * be suspended at any moment once this method is called unless other wake locks + * are being held. + * </p><p> + * Call {@link #stopDozing} or {@link #finish} to stop dozing. + * </p> + * + * @see #stopDozing + * @hide experimental + */ + public void startDozing() { + if (mCanDoze && !mDozing) { + mDozing = true; + try { + mSandman.startDozing(mWindowToken); + } catch (RemoteException ex) { + // system server died + } + } + } + + /** + * Stops dozing, returns to active dreaming. + * <p> + * This method reverses the effect of {@link #startDozing}. From this moment onward, + * the application processor will be kept awake as long as the dream is running + * or until the dream starts dozing again. + * </p> + * + * @see #startDozing + * @hide experimental + */ + public void stopDozing() { + if (mDozing) { + mDozing = false; + try { + mSandman.stopDozing(mWindowToken); + } catch (RemoteException ex) { + // system server died + } + } + } + + /** + * Returns true if the dream will allow the system to enter a low-power state while + * it is running without actually turning off the screen. Defaults to false, + * keeping the application processor awake while the dream is running. + * + * @return True if the dream is dozing. + * + * @see #setDozing(boolean) + * @hide experimental + */ + public boolean isDozing() { + return mDozing; + } + + /** + * Gets an object that may be used to access low-level hardware features that a + * dream may use to provide a richer user experience while dozing. + * + * @return An instance of {@link DozeHardware} or null if this device does not offer + * hardware support for dozing. + * + * @hide experimental + */ + public DozeHardware getDozeHardware() { + if (mCanDoze && mDozeHardware == null) { + try { + IDozeHardware hardware = mSandman.getDozeHardware(mWindowToken); + if (hardware != null) { + mDozeHardware = new DozeHardware(hardware); + } + } catch (RemoteException ex) { + // system server died + } + } + return mDozeHardware; + } + + /** * Called when this Dream is constructed. */ @Override @@ -536,7 +666,11 @@ public class DreamService extends Service implements Window.Callback { } /** - * Stops the dream, detaches from the window, and wakes up. + * Stops the dream and detaches from the window. + * <p> + * When the dream ends, the system will be allowed to go to sleep fully unless there + * is a reason for it to be awake such as recent user activity or wake locks being held. + * </p> */ public final void finish() { if (mDebug) Slog.v(TAG, "finish()"); @@ -557,10 +691,6 @@ public class DreamService extends Service implements Window.Callback { // end public api - private void loadSandman() { - mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE)); - } - /** * Called by DreamController.stopDream() when the Dream is about to be unbound and destroyed. * @@ -572,23 +702,16 @@ public class DreamService extends Service implements Window.Callback { return; } - try { - onDreamingStopped(); - } catch (Throwable t) { - Slog.w(TAG, "Crashed in onDreamingStopped()", t); - // we were going to stop anyway - } + if (mDebug) Slog.v(TAG, "detach(): Calling onDreamingStopped()"); + onDreamingStopped(); if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager"); - try { - // force our window to be removed synchronously - mWindowManager.removeViewImmediate(mWindow.getDecorView()); - // the following will print a log message if it finds any other leaked windows - WindowManagerGlobal.getInstance().closeAll(mWindowToken, - this.getClass().getName(), "Dream"); - } catch (Throwable t) { - Slog.w(TAG, "Crashed removing window view", t); - } + + // force our window to be removed synchronously + mWindowManager.removeViewImmediate(mWindow.getDecorView()); + // the following will print a log message if it finds any other leaked windows + WindowManagerGlobal.getInstance().closeAll(mWindowToken, + this.getClass().getName(), "Dream"); mWindow = null; mWindowToken = null; @@ -601,23 +724,30 @@ public class DreamService extends Service implements Window.Callback { * * @param windowToken A window token that will allow a window to be created in the correct layer. */ - private final void attach(IBinder windowToken) { + private final void attach(IBinder windowToken, boolean canDoze) { if (mWindowToken != null) { Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken); return; } + if (mFinished) { + Slog.w(TAG, "attach() called after dream already finished"); + try { + mSandman.finishSelf(windowToken); + } catch (RemoteException ex) { + // system server died + } + return; + } if (mDebug) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId()); - if (mSandman == null) { - loadSandman(); - } mWindowToken = windowToken; mWindow = PolicyManager.makeNewWindow(this); mWindow.setCallback(this); mWindow.requestFeature(Window.FEATURE_NO_TITLE); mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000)); mWindow.setFormat(PixelFormat.OPAQUE); + mCanDoze = canDoze; if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s", windowToken, WindowManager.LayoutParams.TYPE_DREAM)); @@ -642,40 +772,25 @@ public class DreamService extends Service implements Window.Callback { mWindowManager = mWindow.getWindowManager(); if (mDebug) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId()); - try { - applySystemUiVisibilityFlags( - (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0), - View.SYSTEM_UI_FLAG_LOW_PROFILE); - getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes()); - } catch (Throwable t) { - Slog.w(TAG, "Crashed adding window view", t); - safelyFinish(); - return; - } + applySystemUiVisibilityFlags( + (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0), + View.SYSTEM_UI_FLAG_LOW_PROFILE); + getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes()); // start it up mHandler.post(new Runnable() { @Override public void run() { - try { - onDreamingStarted(); - } catch (Throwable t) { - Slog.w(TAG, "Crashed in onDreamingStarted()", t); - safelyFinish(); - } + if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()"); + onDreamingStarted(); } }); } private void safelyFinish() { if (mDebug) Slog.v(TAG, "safelyFinish()"); - try { - finish(); - } catch (Throwable t) { - Slog.w(TAG, "Crashed in safelyFinish()", t); - finishInternal(); - return; - } + + finish(); if (!mFinished) { Slog.w(TAG, "Bad dream, did not call super.finish()"); @@ -685,19 +800,21 @@ public class DreamService extends Service implements Window.Callback { private void finishInternal() { if (mDebug) Slog.v(TAG, "finishInternal() mFinished = " + mFinished); - if (mFinished) return; - try { + + if (!mFinished) { mFinished = true; - if (mSandman != null) { - mSandman.finishSelf(mWindowToken); + if (mWindowToken == null) { + Slog.w(TAG, "Finish was called before the dream was attached."); } else { - Slog.w(TAG, "No dream manager found"); + try { + mSandman.finishSelf(mWindowToken); + } catch (RemoteException ex) { + // system server died + } } - stopSelf(); // if launched via any other means - } catch (Throwable t) { - Slog.w(TAG, "Crashed in finishInternal()", t); + stopSelf(); // if launched via any other means } } @@ -732,32 +849,39 @@ public class DreamService extends Service implements Window.Callback { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - super.dump(fd, pw, args); - - pw.print(TAG + ": "); - if (mWindowToken == null) { - pw.println("stopped"); - } else { - pw.println("running (token=" + mWindowToken + ")"); - } - pw.println(" window: " + mWindow); - pw.print(" flags:"); - if (isInteractive()) pw.print(" interactive"); - if (isLowProfile()) pw.print(" lowprofile"); - if (isFullscreen()) pw.print(" fullscreen"); - if (isScreenBright()) pw.print(" bright"); - pw.println(); + DumpUtils.dumpAsync(mHandler, new Dump() { + @Override + public void dump(PrintWriter pw) { + pw.print(TAG + ": "); + if (mWindowToken == null) { + pw.println("stopped"); + } else { + pw.println("running (token=" + mWindowToken + ")"); + } + pw.println(" window: " + mWindow); + pw.print(" flags:"); + if (isInteractive()) pw.print(" interactive"); + if (isLowProfile()) pw.print(" lowprofile"); + if (isFullscreen()) pw.print(" fullscreen"); + if (isScreenBright()) pw.print(" bright"); + if (isDozing()) pw.print(" dozing"); + pw.println(); + } + }, pw, 1000); } - private class DreamServiceWrapper extends IDreamService.Stub { - public void attach(final IBinder windowToken) { + private final class DreamServiceWrapper extends IDreamService.Stub { + @Override + public void attach(final IBinder windowToken, final boolean canDoze) { mHandler.post(new Runnable() { @Override public void run() { - DreamService.this.attach(windowToken); + DreamService.this.attach(windowToken, canDoze); } }); } + + @Override public void detach() { mHandler.post(new Runnable() { @Override diff --git a/services/java/com/android/server/display/DisplayTransactionListener.java b/core/java/android/service/dreams/IDozeHardware.aidl index 34eb8f930e9d..f5a657b098c4 100644 --- a/services/java/com/android/server/display/DisplayTransactionListener.java +++ b/core/java/android/service/dreams/IDozeHardware.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Android Open Source Project + * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,11 @@ * limitations under the License. */ -package com.android.server.display; +package android.service.dreams; /** - * Called within a Surface transaction whenever the size or orientation of a - * display may have changed. Provides an opportunity for the client to - * update the position of its surfaces as part of the same transaction. + * @hide */ -public interface DisplayTransactionListener { - void onDisplayTransaction(); +interface IDozeHardware { + byte[] sendMessage(String msg, in byte[] arg); } diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl index 1c1b39094776..2718e3166f18 100644 --- a/core/java/android/service/dreams/IDreamManager.aidl +++ b/core/java/android/service/dreams/IDreamManager.aidl @@ -16,10 +16,11 @@ package android.service.dreams; +import android.content.ComponentName; import android.os.Bundle; import android.os.ParcelFileDescriptor; -import android.content.ComponentName; import android.os.IBinder; +import android.service.dreams.IDozeHardware; /** @hide */ interface IDreamManager { @@ -31,4 +32,7 @@ interface IDreamManager { void testDream(in ComponentName componentName); boolean isDreaming(); void finishSelf(in IBinder token); + void startDozing(in IBinder token); + void stopDozing(in IBinder token); + IDozeHardware getDozeHardware(in IBinder token); }
\ No newline at end of file diff --git a/core/java/android/service/dreams/IDreamService.aidl b/core/java/android/service/dreams/IDreamService.aidl index 99dc0b77d208..bd58f1d905da 100644 --- a/core/java/android/service/dreams/IDreamService.aidl +++ b/core/java/android/service/dreams/IDreamService.aidl @@ -20,6 +20,6 @@ package android.service.dreams; * @hide */ oneway interface IDreamService { - void attach(IBinder windowToken); + void attach(IBinder windowToken, boolean canDoze); void detach(); } diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index 2e0e59bc91c9..cf862b872aa3 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -112,6 +112,7 @@ public abstract class NotificationListenerService extends Service { * {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}. */ public final void cancelNotification(String pkg, String tag, int id) { + if (!isBound()) return; try { getNotificationInterface().cancelNotificationFromListener(mWrapper, pkg, tag, id); } catch (android.os.RemoteException ex) { @@ -131,6 +132,7 @@ public abstract class NotificationListenerService extends Service { * {@see #cancelNotification(String, String, int)} */ public final void cancelAllNotifications() { + if (!isBound()) return; try { getNotificationInterface().cancelAllNotificationsFromListener(mWrapper); } catch (android.os.RemoteException ex) { @@ -145,6 +147,7 @@ public abstract class NotificationListenerService extends Service { * @return An array of active notifications. */ public StatusBarNotification[] getActiveNotifications() { + if (!isBound()) return null; try { return getNotificationInterface().getActiveNotificationsFromListener(mWrapper); } catch (android.os.RemoteException ex) { @@ -161,6 +164,14 @@ public abstract class NotificationListenerService extends Service { return mWrapper; } + private boolean isBound() { + if (mWrapper == null) { + Log.w(TAG, "Notification listener service not yet bound."); + return false; + } + return true; + } + private class INotificationListenerWrapper extends INotificationListener.Stub { @Override public void onNotificationPosted(StatusBarNotification sbn) { diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java index ed4529851d8f..931fb8114716 100644 --- a/core/java/android/util/TypedValue.java +++ b/core/java/android/util/TypedValue.java @@ -290,18 +290,14 @@ public class TypedValue { return -1; } + /** + * @hide Was accidentally exposed in API level 1 for debugging purposes. + * Kept for compatibility just in case although the debugging code has been removed. + */ + @Deprecated public static float complexToDimensionNoisy(int data, DisplayMetrics metrics) { - float res = complexToDimension(data, metrics); - System.out.println( - "Dimension (0x" + ((data>>TypedValue.COMPLEX_MANTISSA_SHIFT) - & TypedValue.COMPLEX_MANTISSA_MASK) - + "*" + (RADIX_MULTS[(data>>TypedValue.COMPLEX_RADIX_SHIFT) - & TypedValue.COMPLEX_RADIX_MASK] / MANTISSA_MULT) - + ")" + DIMENSION_UNIT_STRS[(data>>COMPLEX_UNIT_SHIFT) - & COMPLEX_UNIT_MASK] - + " = " + res); - return res; + return complexToDimension(data, metrics); } /** diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 62afa60d594b..eea58843a7f6 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -79,9 +79,6 @@ public class SurfaceControl { private final String mName; long mNativeObject; // package visibility only for Surface.java access - private static final boolean HEADLESS = "1".equals( - SystemProperties.get("ro.config.headless", "0")); - /* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */ /** @@ -106,18 +103,18 @@ public class SurfaceControl { * surfaces are pre-multiplied, which means that each color component is * already multiplied by its alpha value. In this case the blending * equation used is: - * - * DEST = SRC + DEST * (1-SRC_ALPHA) - * + * <p> + * <code>DEST = SRC + DEST * (1-SRC_ALPHA)</code> + * <p> * By contrast, non pre-multiplied surfaces use the following equation: - * - * DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA) - * + * <p> + * <code>DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA)</code> + * <p> * pre-multiplied surfaces must always be used if transparent pixels are * composited on top of each-other into the surface. A pre-multiplied * surface can never lower the value of the alpha component of a given * pixel. - * + * <p> * In some rare situations, a non pre-multiplied surface is preferable. * */ @@ -128,7 +125,17 @@ public class SurfaceControl { * even if its pixel format is set to translucent. This can be useful if an * application needs full RGBA 8888 support for instance but will * still draw every pixel opaque. - * + * <p> + * This flag is ignored if setAlpha() is used to make the surface non-opaque. + * Combined effects are (assuming a buffer format with an alpha channel): + * <ul> + * <li>OPAQUE + alpha(1.0) == opaque composition + * <li>OPAQUE + alpha(0.x) == blended composition + * <li>!OPAQUE + alpha(1.0) == blended composition + * <li>!OPAQUE + alpha(0.x) == blended composition + * </ul> + * If the underlying buffer lacks an alpha channel, the OPAQUE flag is effectively + * set automatically. */ public static final int OPAQUE = 0x00000400; @@ -169,9 +176,16 @@ public class SurfaceControl { /** * Surface flag: Hide the surface. * Equivalent to calling hide(). + * Updates the value set during Surface creation (see {@link #HIDDEN}). */ public static final int SURFACE_HIDDEN = 0x01; + /** + * Surface flag: composite without blending when possible. + * Updates the value set during Surface creation (see {@link #OPAQUE}). + */ + public static final int SURFACE_OPAQUE = 0x02; + /* built-in physical display ids (keep in sync with ISurfaceComposer.h) * these are different from the logical display ids used elsewhere in the framework */ @@ -192,14 +206,14 @@ public class SurfaceControl { /** * Create a surface with a name. - * + * <p> * The surface creation flags specify what kind of surface to create and * certain options such as whether the surface can be assumed to be opaque * and whether it should be initially hidden. Surfaces should always be * created with the {@link #HIDDEN} flag set to ensure that they are not * made visible prematurely before all of the surface's properties have been * configured. - * + * <p> * Good practice is to first create the surface with the {@link #HIDDEN} flag * specified, open a transaction, set the surface layer, layer stack, alpha, * and position, call {@link #show} if appropriate, and close the transaction. @@ -232,8 +246,6 @@ public class SurfaceControl { new Throwable()); } - checkHeadless(); - mName = name; mNativeObject = nativeCreate(session, name, w, h, format, flags); if (mNativeObject == 0) { @@ -344,6 +356,10 @@ public class SurfaceControl { nativeSetTransparentRegionHint(mNativeObject, region); } + /** + * Sets an alpha value for the entire Surface. This value is combined with the + * per-pixel alpha. It may be used with opaque Surfaces. + */ public void setAlpha(float alpha) { checkNotReleased(); nativeSetAlpha(mNativeObject, alpha); @@ -354,6 +370,13 @@ public class SurfaceControl { nativeSetMatrix(mNativeObject, dsdx, dtdx, dsdy, dtdy); } + /** + * Sets and clears flags, such as {@link #SURFACE_HIDDEN}. The new value will be: + * <p> + * <code>newFlags = (oldFlags & ~mask) | (flags & mask)</code> + * <p> + * Note this does not take the same set of flags as the constructor. + */ public void setFlags(int flags, int mask) { checkNotReleased(); nativeSetFlags(mNativeObject, flags, mask); @@ -374,6 +397,19 @@ public class SurfaceControl { nativeSetLayerStack(mNativeObject, layerStack); } + /** + * Sets the opacity of the surface. Setting the flag is equivalent to creating the + * Surface with the {@link #OPAQUE} flag. + */ + public void setOpaque(boolean isOpaque) { + checkNotReleased(); + if (isOpaque) { + nativeSetFlags(mNativeObject, SURFACE_OPAQUE, SURFACE_OPAQUE); + } else { + nativeSetFlags(mNativeObject, 0, SURFACE_OPAQUE); + } + } + /* * set display parameters. * needs to be inside open/closeTransaction block @@ -619,10 +655,4 @@ public class SurfaceControl { } nativeScreenshot(display, consumer, width, height, minLayer, maxLayer, allLayers); } - - private static void checkHeadless() { - if (HEADLESS) { - throw new UnsupportedOperationException("Device is headless"); - } - } } diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java new file mode 100644 index 000000000000..a1bd4bd1f7ca --- /dev/null +++ b/core/java/android/view/WindowManagerInternal.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view; + +import android.hardware.display.DisplayManagerInternal; + +/** + * Window manager local system service interface. + * + * @hide Only for use within the system server. + */ +public abstract class WindowManagerInternal { + /** + * Request that the window manager call + * {@link DisplayManagerInternal#performTraversalInTransactionFromWindowManager} + * within a surface transaction at a later time. + */ + public abstract void requestTraversalFromDisplayManager(); +}
\ No newline at end of file diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index c5a1b86c0635..74dda7767095 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -115,20 +115,6 @@ public interface WindowManagerPolicy { public final static int ACTION_PASS_TO_USER = 0x00000001; /** - * This key event should wake the device. - * To be returned from {@link #interceptKeyBeforeQueueing}. - * Do not return this and {@link #ACTION_GO_TO_SLEEP} or {@link #ACTION_PASS_TO_USER}. - */ - public final static int ACTION_WAKE_UP = 0x00000002; - - /** - * This key event should put the device to sleep (and engage keyguard if necessary) - * To be returned from {@link #interceptKeyBeforeQueueing}. - * Do not return this and {@link #ACTION_WAKE_UP} or {@link #ACTION_PASS_TO_USER}. - */ - public final static int ACTION_GO_TO_SLEEP = 0x00000004; - - /** * Interface to the Window Manager state associated with a particular * window. You can hold on to an instance of this interface from the call * to prepareAddWindow() until removeWindow(). @@ -751,8 +737,7 @@ public interface WindowManagerPolicy { * @param policyFlags The policy flags associated with the key. * @param isScreenOn True if the screen is already on * - * @return The bitwise or of the {@link #ACTION_PASS_TO_USER}, - * {@link #ACTION_WAKE_UP} and {@link #ACTION_GO_TO_SLEEP} flags. + * @return Actions flags: may be {@link #ACTION_PASS_TO_USER}. */ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn); @@ -765,10 +750,9 @@ public interface WindowManagerPolicy { * because it's the most fragile. * @param policyFlags The policy flags associated with the motion. * - * @return The bitwise or of the {@link #ACTION_PASS_TO_USER}, - * {@link #ACTION_WAKE_UP} and {@link #ACTION_GO_TO_SLEEP} flags. + * @return Actions flags: may be {@link #ACTION_PASS_TO_USER}. */ - public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags); + public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags); /** * Called from the input dispatcher thread before a key is dispatched to a window. diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index 00f4adb911bc..879e58f494c0 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -177,7 +177,8 @@ public final class AccessibilityManager { userId = UserHandle.myUserId(); } IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE); - IAccessibilityManager service = IAccessibilityManager.Stub.asInterface(iBinder); + IAccessibilityManager service = iBinder == null + ? null : IAccessibilityManager.Stub.asInterface(iBinder); sInstance = new AccessibilityManager(context, service, userId); } } @@ -197,10 +198,14 @@ public final class AccessibilityManager { mHandler = new MyHandler(context.getMainLooper()); mService = service; mUserId = userId; - + if (mService == null) { + mIsEnabled = false; + } try { - final int stateFlags = mService.addClient(mClient, userId); - setState(stateFlags); + if (mService != null) { + final int stateFlags = mService.addClient(mClient, userId); + setState(stateFlags); + } } catch (RemoteException re) { Log.e(LOG_TAG, "AccessibilityManagerService is dead", re); } @@ -322,14 +327,16 @@ public final class AccessibilityManager { public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() { List<AccessibilityServiceInfo> services = null; try { - services = mService.getInstalledAccessibilityServiceList(mUserId); - if (DEBUG) { - Log.i(LOG_TAG, "Installed AccessibilityServices " + services); + if (mService != null) { + services = mService.getInstalledAccessibilityServiceList(mUserId); + if (DEBUG) { + Log.i(LOG_TAG, "Installed AccessibilityServices " + services); + } } } catch (RemoteException re) { Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re); } - return Collections.unmodifiableList(services); + return services != null ? Collections.unmodifiableList(services) : Collections.EMPTY_LIST; } /** @@ -349,14 +356,16 @@ public final class AccessibilityManager { int feedbackTypeFlags) { List<AccessibilityServiceInfo> services = null; try { - services = mService.getEnabledAccessibilityServiceList(feedbackTypeFlags, mUserId); - if (DEBUG) { - Log.i(LOG_TAG, "Installed AccessibilityServices " + services); + if (mService != null) { + services = mService.getEnabledAccessibilityServiceList(feedbackTypeFlags, mUserId); + if (DEBUG) { + Log.i(LOG_TAG, "Installed AccessibilityServices " + services); + } } } catch (RemoteException re) { Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re); } - return Collections.unmodifiableList(services); + return services != null ? Collections.unmodifiableList(services) : Collections.EMPTY_LIST; } /** @@ -466,6 +475,9 @@ public final class AccessibilityManager { */ public int addAccessibilityInteractionConnection(IWindow windowToken, IAccessibilityInteractionConnection connection) { + if (mService == null) { + return View.NO_ID; + } try { return mService.addAccessibilityInteractionConnection(windowToken, connection, mUserId); } catch (RemoteException re) { @@ -482,7 +494,9 @@ public final class AccessibilityManager { */ public void removeAccessibilityInteractionConnection(IWindow windowToken) { try { - mService.removeAccessibilityInteractionConnection(windowToken); + if (mService != null) { + mService.removeAccessibilityInteractionConnection(windowToken); + } } catch (RemoteException re) { Log.e(LOG_TAG, "Error while removing an accessibility interaction connection. ", re); } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 2e5fcecbf26c..872861024cdd 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -26,6 +26,7 @@ import android.os.BatteryManager; import android.os.BatteryStats; import android.os.FileUtils; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.ParcelFormatException; @@ -113,6 +114,10 @@ public final class BatteryStatsImpl extends BatteryStats { } final class MyHandler extends Handler { + public MyHandler(Looper looper) { + super(looper, null, true); + } + @Override public void handleMessage(Message msg) { BatteryCallback cb = mCallback; @@ -4487,9 +4492,9 @@ public final class BatteryStatsImpl extends BatteryStats { } } - public BatteryStatsImpl(String filename) { + public BatteryStatsImpl(String filename, Handler handler) { mFile = new JournaledFile(new File(filename), new File(filename + ".tmp")); - mHandler = new MyHandler(); + mHandler = new MyHandler(handler.getLooper()); mStartCount++; mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables); for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java index f54a3e9ce9c3..3b0f0f4777dd 100644 --- a/core/java/com/android/internal/os/BinderInternal.java +++ b/core/java/com/android/internal/os/BinderInternal.java @@ -16,18 +16,11 @@ package com.android.internal.os; -import android.os.Binder; import android.os.IBinder; import android.os.SystemClock; import android.util.EventLog; -import android.util.Log; -import java.io.FileDescriptor; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintWriter; import java.lang.ref.WeakReference; -import java.lang.reflect.Modifier; /** * Private and debugging Binder APIs. diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java index 46541785f468..fe1cf72cb884 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java @@ -164,8 +164,24 @@ public class ActionMenuPresenter extends BaseMenuPresenter } actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE); + final ActionMenuView menuParent = (ActionMenuView) parent; + final ViewGroup.LayoutParams lp = actionView.getLayoutParams(); + if (!menuParent.checkLayoutParams(lp)) { + actionView.setLayoutParams(menuParent.generateLayoutParams(lp)); + } + return actionView; + } + + @Override + public void bindItemView(final MenuItemImpl item, MenuView.ItemView itemView) { + itemView.initialize(item, 0); + + final ActionMenuView menuView = (ActionMenuView) mMenuView; + final ActionMenuItemView actionItemView = (ActionMenuItemView) itemView; + actionItemView.setItemInvoker(menuView); + if (item.hasSubMenu()) { - actionView.setOnTouchListener(new ForwardingListener(actionView) { + actionItemView.setOnTouchListener(new ForwardingListener(actionItemView) { @Override public ListPopupWindow getPopup() { return mActionButtonPopup != null ? mActionButtonPopup.getPopup() : null; @@ -182,24 +198,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter } }); } else { - actionView.setOnTouchListener(null); + actionItemView.setOnTouchListener(null); } - - final ActionMenuView menuParent = (ActionMenuView) parent; - final ViewGroup.LayoutParams lp = actionView.getLayoutParams(); - if (!menuParent.checkLayoutParams(lp)) { - actionView.setLayoutParams(menuParent.generateLayoutParams(lp)); - } - return actionView; - } - - @Override - public void bindItemView(MenuItemImpl item, MenuView.ItemView itemView) { - itemView.initialize(item, 0); - - final ActionMenuView menuView = (ActionMenuView) mMenuView; - ActionMenuItemView actionItemView = (ActionMenuItemView) itemView; - actionItemView.setItemInvoker(menuView); } @Override diff --git a/core/java/com/android/server/LocalServices.java b/core/java/com/android/server/LocalServices.java new file mode 100644 index 000000000000..25dcb308b55a --- /dev/null +++ b/core/java/com/android/server/LocalServices.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.util.ArrayMap; + +/** + * This class is used in a similar way as ServiceManager, except the services registered here + * are not Binder objects and are only available in the same process. + * + * Once all services are converted to the SystemService interface, this class can be absorbed + * into SystemServiceManager. + * + * {@hide} + */ +public final class LocalServices { + private LocalServices() {} + + private static final ArrayMap<Class<?>, Object> sLocalServiceObjects = + new ArrayMap<Class<?>, Object>(); + + /** + * Returns a local service instance that implements the specified interface. + * + * @param type The type of service. + * @return The service object. + */ + @SuppressWarnings("unchecked") + public static <T> T getService(Class<T> type) { + synchronized (sLocalServiceObjects) { + return (T) sLocalServiceObjects.get(type); + } + } + + /** + * Adds a service instance of the specified interface to the global registry of local services. + */ + public static <T> void addService(Class<T> type, T service) { + synchronized (sLocalServiceObjects) { + if (sLocalServiceObjects.containsKey(type)) { + throw new IllegalStateException("Overriding service registration"); + } + sLocalServiceObjects.put(type, service); + } + } +} diff --git a/core/java/com/android/server/SystemService.java b/core/java/com/android/server/SystemService.java new file mode 100644 index 000000000000..e37456364530 --- /dev/null +++ b/core/java/com/android/server/SystemService.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.content.Context; +import android.os.IBinder; +import android.os.ServiceManager; + +/** + * The base class for services running in the system process. Override and implement + * the lifecycle event callback methods as needed. + * <p> + * The lifecycle of a SystemService: + * </p><ul> + * <li>The constructor is called and provided with the system {@link Context} + * to initialize the system service. + * <li>{@link #onStart()} is called to get the service running. The service should + * publish its binder interface at this point using + * {@link #publishBinderService(String, IBinder)}. It may also publish additional + * local interfaces that other services within the system server may use to access + * privileged internal functions. + * <li>Then {@link #onBootPhase(int)} is called as many times as there are boot phases + * until {@link #PHASE_BOOT_COMPLETE} is sent, which is the last boot phase. Each phase + * is an opportunity to do special work, like acquiring optional service dependencies, + * waiting to see if SafeMode is enabled, or registering with a service that gets + * started after this one. + * </ul><p> + * NOTE: All lifecycle methods are called from the system server's main looper thread. + * </p> + * + * {@hide} + */ +public abstract class SystemService { + /* + * Boot Phases + */ + public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; // maybe should be a dependency? + + /** + * After receiving this boot phase, services can obtain lock settings data. + */ + public static final int PHASE_LOCK_SETTINGS_READY = 480; + + /** + * After receiving this boot phase, services can safely call into core system services + * such as the PowerManager or PackageManager. + */ + public static final int PHASE_SYSTEM_SERVICES_READY = 500; + + /** + * After receiving this boot phase, services can broadcast Intents. + */ + public static final int PHASE_ACTIVITY_MANAGER_READY = 550; + + /** + * After receiving this boot phase, services can start/bind to third party apps. + * Apps will be able to make Binder calls into services at this point. + */ + public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600; + + /** + * After receiving this boot phase, services must have finished all boot-related work. + */ + public static final int PHASE_BOOT_COMPLETE = 1000; + + private final Context mContext; + + /** + * Initializes the system service. + * <p> + * Subclasses must define a single argument constructor that accepts the context + * and passes it to super. + * </p> + * + * @param context The system server context. + */ + public SystemService(Context context) { + mContext = context; + } + + /** + * Gets the system context. + */ + public final Context getContext() { + return mContext; + } + + /** + * Returns true if the system is running in safe mode. + * TODO: we should define in which phase this becomes valid + */ + public final boolean isSafeMode() { + return getManager().isSafeMode(); + } + + /** + * Called when the dependencies listed in the @Service class-annotation are available + * and after the chosen start phase. + * When this method returns, the service should be published. + */ + public abstract void onStart(); + + /** + * Called on each phase of the boot process. Phases before the service's start phase + * (as defined in the @Service annotation) are never received. + * + * @param phase The current boot phase. + */ + public void onBootPhase(int phase) {} + + /** + * Publish the service so it is accessible to other services and apps. + */ + protected final void publishBinderService(String name, IBinder service) { + publishBinderService(name, service, false); + } + + /** + * Publish the service so it is accessible to other services and apps. + */ + protected final void publishBinderService(String name, IBinder service, + boolean allowIsolated) { + ServiceManager.addService(name, service, allowIsolated); + } + + /** + * Get a binder service by its name. + */ + protected final IBinder getBinderService(String name) { + return ServiceManager.getService(name); + } + + /** + * Publish the service so it is only accessible to the system process. + */ + protected final <T> void publishLocalService(Class<T> type, T service) { + LocalServices.addService(type, service); + } + + /** + * Get a local service by interface. + */ + protected final <T> T getLocalService(Class<T> type) { + return LocalServices.getService(type); + } + + private SystemServiceManager getManager() { + return LocalServices.getService(SystemServiceManager.class); + } + +// /** +// * Called when a new user has been created. If your service deals with multiple users, this +// * method should be overridden. +// * +// * @param userHandle The user that was created. +// */ +// public void onUserCreated(int userHandle) { +// } +// +// /** +// * Called when an existing user has started a new session. If your service deals with multiple +// * users, this method should be overridden. +// * +// * @param userHandle The user who started a new session. +// */ +// public void onUserStarted(int userHandle) { +// } +// +// /** +// * Called when a background user session has entered the foreground. If your service deals with +// * multiple users, this method should be overridden. +// * +// * @param userHandle The user who's session entered the foreground. +// */ +// public void onUserForeground(int userHandle) { +// } +// +// /** +// * Called when a foreground user session has entered the background. If your service deals with +// * multiple users, this method should be overridden; +// * +// * @param userHandle The user who's session entered the background. +// */ +// public void onUserBackground(int userHandle) { +// } +// +// /** +// * Called when a user's active session has stopped. If your service deals with multiple users, +// * this method should be overridden. +// * +// * @param userHandle The user who's session has stopped. +// */ +// public void onUserStopped(int userHandle) { +// } +// +// /** +// * Called when a user has been removed from the system. If your service deals with multiple +// * users, this method should be overridden. +// * +// * @param userHandle The user who has been removed. +// */ +// public void onUserRemoved(int userHandle) { +// } +} diff --git a/core/java/com/android/server/SystemServiceManager.java b/core/java/com/android/server/SystemServiceManager.java new file mode 100644 index 000000000000..eb8df0e3ad17 --- /dev/null +++ b/core/java/com/android/server/SystemServiceManager.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.content.Context; +import android.util.Slog; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; + +/** + * Manages creating, starting, and other lifecycle events of + * {@link com.android.server.SystemService system services}. + * + * {@hide} + */ +public class SystemServiceManager { + private static final String TAG = "SystemServiceManager"; + + private final Context mContext; + private boolean mSafeMode; + + // Services that should receive lifecycle events. + private final ArrayList<SystemService> mServices = new ArrayList<SystemService>(); + + private int mCurrentPhase = -1; + + public SystemServiceManager(Context context) { + mContext = context; + } + + /** + * Starts a service by class name. + * + * @return The service instance. + */ + @SuppressWarnings("unchecked") + public SystemService startService(String className) throws ClassNotFoundException { + return startService((Class<SystemService>) Class.forName(className)); + } + + /** + * Creates and starts a system service. The class must be a subclass of + * {@link com.android.server.SystemService}. + * + * @param serviceClass A Java class that implements the SystemService interface. + * @return The service instance, never null. + * @throws RuntimeException if the service fails to start. + */ + @SuppressWarnings("unchecked") + public <T extends SystemService> T startService(Class<T> serviceClass) { + final String name = serviceClass.getName(); + Slog.i(TAG, "Starting " + name); + + // Create the service. + if (!SystemService.class.isAssignableFrom(serviceClass)) { + throw new RuntimeException("Failed to create " + name + + ": service must extend " + SystemService.class.getName()); + } + final T service; + try { + Constructor<T> constructor = serviceClass.getConstructor(Context.class); + service = constructor.newInstance(mContext); + } catch (InstantiationException ex) { + throw new RuntimeException("Failed to create service " + name + + ": service could not be instantiated", ex); + } catch (IllegalAccessException ex) { + throw new RuntimeException("Failed to create service " + name + + ": service must have a public constructor with a Context argument", ex); + } catch (NoSuchMethodException ex) { + throw new RuntimeException("Failed to create service " + name + + ": service must have a public constructor with a Context argument", ex); + } catch (InvocationTargetException ex) { + throw new RuntimeException("Failed to create service " + name + + ": service constructor threw an exception", ex); + } + + // Register it. + mServices.add(service); + + // Start it. + try { + service.onStart(); + } catch (RuntimeException ex) { + throw new RuntimeException("Failed to start service " + name + + ": onStart threw an exception", ex); + } + return service; + } + + /** + * Starts the specified boot phase for all system services that have been started up to + * this point. + * + * @param phase The boot phase to start. + */ + public void startBootPhase(final int phase) { + if (phase <= mCurrentPhase) { + throw new IllegalArgumentException("Next phase must be larger than previous"); + } + mCurrentPhase = phase; + + Slog.i(TAG, "Starting phase " + mCurrentPhase); + + final int serviceLen = mServices.size(); + for (int i = 0; i < serviceLen; i++) { + final SystemService service = mServices.get(i); + try { + service.onBootPhase(mCurrentPhase); + } catch (Exception ex) { + throw new RuntimeException("Failed to boot service " + + service.getClass().getName() + + ": onBootPhase threw an exception during phase " + + mCurrentPhase, ex); + } + } + } + + /** Sets the safe mode flag for services to query. */ + public void setSafeMode(boolean safeMode) { + mSafeMode = safeMode; + } + + /** + * Returns whether we are booting into safe mode. + * @return safe mode flag + */ + public boolean isSafeMode() { + return mSafeMode; + } + + /** + * Outputs the state of this manager to the System log. + */ + public void dump() { + StringBuilder builder = new StringBuilder(); + builder.append("Current phase: ").append(mCurrentPhase).append("\n"); + builder.append("Services:\n"); + final int startedLen = mServices.size(); + for (int i = 0; i < startedLen; i++) { + final SystemService service = mServices.get(i); + builder.append("\t") + .append(service.getClass().getSimpleName()) + .append("\n"); + } + + Slog.e(TAG, builder.toString()); + } +} diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp index 1fe4b08d9721..5b0a4b2e4039 100644 --- a/core/jni/android_opengl_EGL14.cpp +++ b/core/jni/android_opengl_EGL14.cpp @@ -630,7 +630,7 @@ not_valid_surface: if (producer == NULL) goto not_valid_surface; - window = new android::Surface(producer); + window = new android::Surface(producer, true); if (window == NULL) goto not_valid_surface; diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 601975af01b9..cbed99f9acad 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -344,23 +344,6 @@ jint android_os_Process_getThreadPriority(JNIEnv* env, jobject clazz, return pri; } -jboolean android_os_Process_setOomAdj(JNIEnv* env, jobject clazz, - jint pid, jint adj) -{ -#ifdef HAVE_OOM_ADJ - char text[64]; - sprintf(text, "/proc/%d/oom_adj", pid); - int fd = open(text, O_WRONLY); - if (fd >= 0) { - sprintf(text, "%d", adj); - write(fd, text, strlen(text)); - close(fd); - } - return true; -#endif - return false; -} - jboolean android_os_Process_setSwappiness(JNIEnv *env, jobject clazz, jint pid, jboolean is_increased) { @@ -1023,7 +1006,6 @@ static const JNINativeMethod methods[] = { {"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup}, {"setProcessGroup", "(II)V", (void*)android_os_Process_setProcessGroup}, {"getProcessGroup", "(I)I", (void*)android_os_Process_getProcessGroup}, - {"setOomAdj", "(II)Z", (void*)android_os_Process_setOomAdj}, {"setSwappiness", "(IZ)Z", (void*)android_os_Process_setSwappiness}, {"setArgV0", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0}, {"setUid", "(I)I", (void*)android_os_Process_setUid}, diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index b198937df18d..e7db535650a9 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1288,7 +1288,7 @@ <!-- @hide Allows an application to create/manage/remove stacks --> <permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" android:permissionGroup="android.permission-group.APP_INFO" - android:protectionLevel="signature" + android:protectionLevel="signature|system" android:label="@string/permlab_manageActivityStacks" android:description="@string/permdesc_manageActivityStacks" /> @@ -2356,13 +2356,13 @@ @hide --> <permission android:name="android.permission.READ_DREAM_STATE" android:permissionGroup="android.permission-group.SYSTEM_TOOLS" - android:protectionLevel="signature" /> + android:protectionLevel="signature|system" /> <!-- Allows applications to write dream settings, and start or stop dreaming. @hide --> <permission android:name="android.permission.WRITE_DREAM_STATE" android:permissionGroup="android.permission-group.SYSTEM_TOOLS" - android:protectionLevel="signature" /> + android:protectionLevel="signature|system" /> <!-- Allow an application to read and write the cache partition. @hide --> @@ -2522,7 +2522,7 @@ android:hasCode="false" android:label="@string/android_system_label" android:allowClearUserData="false" - android:backupAgent="com.android.server.SystemBackupAgent" + android:backupAgent="com.android.server.backup.SystemBackupAgent" android:killAfterRestore="false" android:icon="@drawable/ic_launcher_android" android:supportsRtl="true"> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index b34c792f5de0..96a920df65a5 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -652,6 +652,11 @@ Must be in the range specified by minimum and maximum. --> <integer name="config_screenBrightnessSettingDefault">102</integer> + <!-- Screen brightness used to dim the screen while dozing in a very low power state. + May be less than the minimum allowed brightness setting + that can be set by the user. --> + <integer name="config_screenBrightnessDoze">1</integer> + <!-- Screen brightness used to dim the screen when the user activity timeout expires. May be less than the minimum allowed brightness setting that can be set by the user. --> @@ -1072,8 +1077,16 @@ <!-- Name of the wimax state tracker clas --> <string name="config_wimaxStateTrackerClassname" translatable="false"></string> - <!-- Is the dreams feature supported? --> + <!-- Specifies whether the dreams feature should be supported. + When true, the system will allow the user to configure dreams (screensavers) + to launch when a user activity timeout occurs or the system is told to nap. + When false, the dreams feature will be disabled (this does not affect dozing). + + Consider setting this resource to false or disabling dreams by default when a + doze component is specified below since dreaming will supercede dozing and + will prevent the system from entering a low power state until the dream ends. --> <bool name="config_dreamsSupported">true</bool> + <!-- If supported, are dreams enabled? (by default) --> <bool name="config_dreamsEnabledByDefault">true</bool> <!-- If supported and enabled, are dreams activated when docked? (by default) --> @@ -1083,6 +1096,70 @@ <!-- ComponentName of the default dream (Settings.Secure.SCREENSAVER_COMPONENT) --> <string name="config_dreamsDefaultComponent">com.google.android.deskclock/com.android.deskclock.Screensaver</string> + <!-- Are we allowed to dream while not plugged in? --> + <bool name="config_dreamsEnabledOnBattery">false</bool> + <!-- Minimum battery level to allow dreaming when powered. + Use -1 to disable this safety feature. --> + <integer name="config_dreamsBatteryLevelMinimumWhenPowered">-1</integer> + <!-- Minimum battery level to allow dreaming when not powered. + Use -1 to disable this safety feature. --> + <integer name="config_dreamsBatteryLevelMinimumWhenNotPowered">15</integer> + <!-- If the battery level drops by this percentage and the user activity timeout + has expired, then assume the device is receiving insufficient current to charge + effectively and terminate the dream. Use -1 to disable this safety feature. --> + <integer name="config_dreamsBatteryLevelDrainCutoff">5</integer> + + <!-- ComponentName of a dream to show whenever the system would otherwise have + gone to sleep. When the PowerManager is asked to go to sleep, it will instead + try to start this dream if possible. The dream should typically call startDozing() + to put the display into a low power state and allow the application processor + to be suspended. When the dream ends, the system will go to sleep as usual. + Specify the component name (Settings.Secure.SCREENSAVER_COMPONENT) or an + empty string if none. + + Note that doze dreams are not subject to the same start conditions as ordinary dreams. + Doze dreams will run whenever the power manager is in a dozing state. --> + <string name="config_dozeComponent"></string> + + <!-- Power Management: Specifies whether to decouple the auto-suspend state of the + device from the display on/off state. + + When false, autosuspend_disable() will be called before the display is turned on + and autosuspend_enable() will be called after the display is turned off. + This mode provides best compatibility for devices using legacy power management + features such as early suspend / late resume. + + When true, autosuspend_display() and autosuspend_enable() will be called + independently of whether the display is being turned on or off. This mode + enables the power manager to suspend the application processor while the + display is on. + + This resource should be set to "true" when a doze component has been specified + to maximize power savings but not all devices support it. + + Refer to autosuspend.h for details. + --> + <bool name="config_powerDecoupleAutoSuspendModeFromDisplay">false</bool> + + <!-- Power Management: Specifies whether to decouple the interactive state of the + device from the display on/off state. + + When false, setInteractive(..., true) will be called before the display is turned on + and setInteractive(..., false) will be called after the display is turned off. + This mode provides best compatibility for devices that expect the interactive + state to be tied to the display state. + + When true, setInteractive(...) will be called independently of whether the display + is being turned on or off. This mode enables the power manager to reduce + clocks and disable the touch controller while the display is on. + + This resource should be set to "true" when a doze component has been specified + to maximize power savings but not all devices support it. + + Refer to power.h for details. + --> + <bool name="config_powerDecoupleInteractiveModeFromDisplay">false</bool> + <!-- Base "touch slop" value used by ViewConfiguration as a movement threshold where scrolling should begin. --> <dimen name="config_viewConfigurationTouchSlop">8dp</dimen> diff --git a/core/res/res/values/styles_micro.xml b/core/res/res/values/styles_micro.xml new file mode 100644 index 000000000000..2fd283eb780d --- /dev/null +++ b/core/res/res/values/styles_micro.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<resources> + <style name="Widget.Micro" parent="Widget.Holo" /> + + <style name="Widget.Micro.TextView"> + <item name="android:fontFamily">sans-serif-condensed</item> + </style> +</resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 6d90973c44f2..c38e753ff94e 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1504,6 +1504,7 @@ <java-symbol type="integer" name="config_screenBrightnessSettingMaximum" /> <java-symbol type="integer" name="config_screenBrightnessSettingDefault" /> <java-symbol type="integer" name="config_screenBrightnessDim" /> + <java-symbol type="integer" name="config_screenBrightnessDoze" /> <java-symbol type="integer" name="config_shutdownBatteryTemperature" /> <java-symbol type="integer" name="config_undockedHdmiRotation" /> <java-symbol type="integer" name="config_virtualKeyQuietTimeMillis" /> @@ -1608,11 +1609,18 @@ <java-symbol type="xml" name="storage_list" /> <java-symbol type="bool" name="config_dreamsSupported" /> <java-symbol type="bool" name="config_dreamsEnabledByDefault" /> + <java-symbol type="bool" name="config_dreamsEnabledOnBattery" /> <java-symbol type="bool" name="config_dreamsActivatedOnDockByDefault" /> <java-symbol type="bool" name="config_dreamsActivatedOnSleepByDefault" /> + <java-symbol type="integer" name="config_dreamsBatteryLevelMinimumWhenPowered" /> + <java-symbol type="integer" name="config_dreamsBatteryLevelMinimumWhenNotPowered" /> + <java-symbol type="integer" name="config_dreamsBatteryLevelDrainCutoff" /> <java-symbol type="string" name="config_dreamsDefaultComponent" /> + <java-symbol type="string" name="config_dozeComponent" /> <java-symbol type="string" name="enable_explore_by_touch_warning_title" /> <java-symbol type="string" name="enable_explore_by_touch_warning_message" /> + <java-symbol type="bool" name="config_powerDecoupleAutoSuspendModeFromDisplay" /> + <java-symbol type="bool" name="config_powerDecoupleInteractiveModeFromDisplay" /> <java-symbol type="layout" name="resolver_list" /> <java-symbol type="id" name="resolver_list" /> diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml new file mode 100644 index 000000000000..be5fa99d0271 --- /dev/null +++ b/core/res/res/values/themes_micro.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<resources> + <style name="Theme.Micro" parent="Theme.Holo" /> + + <style name="Theme.Micro.Light" parent="Theme.Holo.Light"/> + <style name="Theme.Micro.Light.NoActionBar" parent="Theme.Holo.Light.NoActionBar"> + <item name="textViewStyle">@android:style/Widget.Micro.TextView</item> + </style> + <style name="Theme.Micro.Light.DarkActionBar" parent="Theme.Holo.Light.DarkActionBar"> + <item name="textViewStyle">@android:style/Widget.Micro.TextView</item> + </style> + +</resources> diff --git a/services/common_time/Android.mk b/libs/common_time/Android.mk index 75eb5281f692..75eb5281f692 100644 --- a/services/common_time/Android.mk +++ b/libs/common_time/Android.mk diff --git a/services/common_time/clock_recovery.cpp b/libs/common_time/clock_recovery.cpp index 3a7c70c3e17d..3a7c70c3e17d 100644 --- a/services/common_time/clock_recovery.cpp +++ b/libs/common_time/clock_recovery.cpp diff --git a/services/common_time/clock_recovery.h b/libs/common_time/clock_recovery.h index b6c87ffaf37e..b6c87ffaf37e 100644 --- a/services/common_time/clock_recovery.h +++ b/libs/common_time/clock_recovery.h diff --git a/services/common_time/common_clock.cpp b/libs/common_time/common_clock.cpp index c9eb3884440d..c9eb3884440d 100644 --- a/services/common_time/common_clock.cpp +++ b/libs/common_time/common_clock.cpp diff --git a/services/common_time/common_clock.h b/libs/common_time/common_clock.h index b786fdceba5f..b786fdceba5f 100644 --- a/services/common_time/common_clock.h +++ b/libs/common_time/common_clock.h diff --git a/services/common_time/common_clock_service.cpp b/libs/common_time/common_clock_service.cpp index 9ca6f3523084..9ca6f3523084 100644 --- a/services/common_time/common_clock_service.cpp +++ b/libs/common_time/common_clock_service.cpp diff --git a/services/common_time/common_clock_service.h b/libs/common_time/common_clock_service.h index bd663f06d43a..bd663f06d43a 100644 --- a/services/common_time/common_clock_service.h +++ b/libs/common_time/common_clock_service.h diff --git a/services/common_time/common_time_config_service.cpp b/libs/common_time/common_time_config_service.cpp index 958561818423..958561818423 100644 --- a/services/common_time/common_time_config_service.cpp +++ b/libs/common_time/common_time_config_service.cpp diff --git a/services/common_time/common_time_config_service.h b/libs/common_time/common_time_config_service.h index 89806dd87e29..89806dd87e29 100644 --- a/services/common_time/common_time_config_service.h +++ b/libs/common_time/common_time_config_service.h diff --git a/services/common_time/common_time_server.cpp b/libs/common_time/common_time_server.cpp index 21e706fa0722..21e706fa0722 100644 --- a/services/common_time/common_time_server.cpp +++ b/libs/common_time/common_time_server.cpp diff --git a/services/common_time/common_time_server.h b/libs/common_time/common_time_server.h index 6e1805086978..6e1805086978 100644 --- a/services/common_time/common_time_server.h +++ b/libs/common_time/common_time_server.h diff --git a/services/common_time/common_time_server_api.cpp b/libs/common_time/common_time_server_api.cpp index e15707181bca..e15707181bca 100644 --- a/services/common_time/common_time_server_api.cpp +++ b/libs/common_time/common_time_server_api.cpp diff --git a/services/common_time/common_time_server_packets.cpp b/libs/common_time/common_time_server_packets.cpp index 9833c37f2519..9833c37f2519 100644 --- a/services/common_time/common_time_server_packets.cpp +++ b/libs/common_time/common_time_server_packets.cpp diff --git a/services/common_time/common_time_server_packets.h b/libs/common_time/common_time_server_packets.h index 57ba8a256308..57ba8a256308 100644 --- a/services/common_time/common_time_server_packets.h +++ b/libs/common_time/common_time_server_packets.h diff --git a/services/common_time/diag_thread.cpp b/libs/common_time/diag_thread.cpp index 4cb955131099..4cb955131099 100644 --- a/services/common_time/diag_thread.cpp +++ b/libs/common_time/diag_thread.cpp diff --git a/services/common_time/diag_thread.h b/libs/common_time/diag_thread.h index c630e0d9b525..c630e0d9b525 100644 --- a/services/common_time/diag_thread.h +++ b/libs/common_time/diag_thread.h diff --git a/services/common_time/main.cpp b/libs/common_time/main.cpp index 49eb30abab66..49eb30abab66 100644 --- a/services/common_time/main.cpp +++ b/libs/common_time/main.cpp diff --git a/services/common_time/utils.cpp b/libs/common_time/utils.cpp index ed2c77ddb3a5..ed2c77ddb3a5 100644 --- a/services/common_time/utils.cpp +++ b/libs/common_time/utils.cpp diff --git a/services/common_time/utils.h b/libs/common_time/utils.h index c28cf0ac33d7..c28cf0ac33d7 100644 --- a/services/common_time/utils.h +++ b/libs/common_time/utils.h diff --git a/services/input/Android.mk b/libs/input/Android.mk index 6e944ef5cc96..6e944ef5cc96 100644 --- a/services/input/Android.mk +++ b/libs/input/Android.mk diff --git a/services/input/EventHub.cpp b/libs/input/EventHub.cpp index fc64656b1745..fc64656b1745 100644 --- a/services/input/EventHub.cpp +++ b/libs/input/EventHub.cpp diff --git a/services/input/EventHub.h b/libs/input/EventHub.h index ae28f016f726..ae28f016f726 100644 --- a/services/input/EventHub.h +++ b/libs/input/EventHub.h diff --git a/services/input/InputApplication.cpp b/libs/input/InputApplication.cpp index a99e637fdf43..a99e637fdf43 100644 --- a/services/input/InputApplication.cpp +++ b/libs/input/InputApplication.cpp diff --git a/services/input/InputApplication.h b/libs/input/InputApplication.h index 1f5504c2d234..1f5504c2d234 100644 --- a/services/input/InputApplication.h +++ b/libs/input/InputApplication.h diff --git a/services/input/InputDispatcher.cpp b/libs/input/InputDispatcher.cpp index 10a639e7aaad..4d447878da4b 100644 --- a/services/input/InputDispatcher.cpp +++ b/libs/input/InputDispatcher.cpp @@ -1020,7 +1020,14 @@ void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout sp<InputWindowHandle> windowHandle = connection->inputWindowHandle; if (windowHandle != NULL) { - mTouchState.removeWindow(windowHandle); + const InputWindowInfo* info = windowHandle->getInfo(); + if (info) { + ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(info->displayId); + if (stateIndex >= 0) { + mTouchStatesByDisplay.editValueAt(stateIndex).removeWindow( + windowHandle); + } + } } if (connection->status == Connection::STATUS_NORMAL) { @@ -1161,11 +1168,21 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN; sp<InputWindowHandle> newHoverWindowHandle; - bool isSplit = mTouchState.split; - bool switchedDevice = mTouchState.deviceId >= 0 && mTouchState.displayId >= 0 - && (mTouchState.deviceId != entry->deviceId - || mTouchState.source != entry->source - || mTouchState.displayId != displayId); + // Copy current touch state into mTempTouchState. + // This state is always reset at the end of this function, so if we don't find state + // for the specified display then our initial state will be empty. + const TouchState* oldState = NULL; + ssize_t oldStateIndex = mTouchStatesByDisplay.indexOfKey(displayId); + if (oldStateIndex >= 0) { + oldState = &mTouchStatesByDisplay.valueAt(oldStateIndex); + mTempTouchState.copyFrom(*oldState); + } + + bool isSplit = mTempTouchState.split; + bool switchedDevice = mTempTouchState.deviceId >= 0 && mTempTouchState.displayId >= 0 + && (mTempTouchState.deviceId != entry->deviceId + || mTempTouchState.source != entry->source + || mTempTouchState.displayId != displayId); bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE || maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER || maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT); @@ -1175,11 +1192,10 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, bool wrongDevice = false; if (newGesture) { bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN; - if (switchedDevice && mTouchState.down && !down) { + if (switchedDevice && mTempTouchState.down && !down) { #if DEBUG_FOCUS ALOGD("Dropping event because a pointer for a different device is already down."); #endif - mTempTouchState.copyFrom(mTouchState); injectionResult = INPUT_EVENT_INJECTION_FAILED; switchedDevice = false; wrongDevice = true; @@ -1191,8 +1207,6 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, mTempTouchState.source = entry->source; mTempTouchState.displayId = displayId; isSplit = false; - } else { - mTempTouchState.copyFrom(mTouchState); } if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) { @@ -1515,32 +1529,31 @@ Failed: if (isHoverAction) { // Started hovering, therefore no longer down. - if (mTouchState.down) { + if (oldState && oldState->down) { #if DEBUG_FOCUS ALOGD("Conflicting pointer actions: Hover received while pointer was down."); #endif *outConflictingPointerActions = true; } - mTouchState.reset(); + mTempTouchState.reset(); if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) { - mTouchState.deviceId = entry->deviceId; - mTouchState.source = entry->source; - mTouchState.displayId = displayId; + mTempTouchState.deviceId = entry->deviceId; + mTempTouchState.source = entry->source; + mTempTouchState.displayId = displayId; } } else if (maskedAction == AMOTION_EVENT_ACTION_UP || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { // All pointers up or canceled. - mTouchState.reset(); + mTempTouchState.reset(); } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { // First pointer went down. - if (mTouchState.down) { + if (oldState && oldState->down) { #if DEBUG_FOCUS ALOGD("Conflicting pointer actions: Down received while already down."); #endif *outConflictingPointerActions = true; } - mTouchState.copyFrom(mTempTouchState); } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) { // One pointer went up. if (isSplit) { @@ -1559,12 +1572,20 @@ Failed: i += 1; } } - mTouchState.copyFrom(mTempTouchState); - } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) { - // Discard temporary touch state since it was only valid for this action. - } else { - // Save changes to touch state as-is for all other actions. - mTouchState.copyFrom(mTempTouchState); + } + + // Save changes unless the action was scroll in which case the temporary touch + // state was only valid for this one action. + if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) { + if (mTempTouchState.displayId >= 0) { + if (oldStateIndex >= 0) { + mTouchStatesByDisplay.editValueAt(oldStateIndex).copyFrom(mTempTouchState); + } else { + mTouchStatesByDisplay.add(displayId, mTempTouchState); + } + } else if (oldStateIndex >= 0) { + mTouchStatesByDisplay.removeItemsAt(oldStateIndex); + } } // Update hover state. @@ -2316,7 +2337,7 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet originalMotionEntry->yPrecision, originalMotionEntry->downTime, originalMotionEntry->displayId, - splitPointerCount, splitPointerProperties, splitPointerCoords); + splitPointerCount, splitPointerProperties, splitPointerCoords, 0, 0); if (originalMotionEntry->injectionState) { splitMotionEntry->injectionState = originalMotionEntry->injectionState; @@ -2488,7 +2509,7 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { args->action, args->flags, args->metaState, args->buttonState, args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime, args->displayId, - args->pointerCount, args->pointerProperties, args->pointerCoords); + args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0); needWake = enqueueInboundEventLocked(newEntry); mLock.unlock(); @@ -2536,7 +2557,7 @@ void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) { } } -int32_t InputDispatcher::injectInputEvent(const InputEvent* event, +int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t displayId, int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, uint32_t policyFlags) { #if DEBUG_INBOUND_EVENT_DETAILS @@ -2587,7 +2608,6 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, case AINPUT_EVENT_TYPE_MOTION: { const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event); - int32_t displayId = ADISPLAY_ID_DEFAULT; int32_t action = motionEvent->getAction(); size_t pointerCount = motionEvent->getPointerCount(); const PointerProperties* pointerProperties = motionEvent->getPointerProperties(); @@ -2610,7 +2630,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, motionEvent->getEdgeFlags(), motionEvent->getXPrecision(), motionEvent->getYPrecision(), motionEvent->getDownTime(), displayId, - uint32_t(pointerCount), pointerProperties, samplePointerCoords); + uint32_t(pointerCount), pointerProperties, samplePointerCoords, + motionEvent->getXOffset(), motionEvent->getYOffset()); lastInjectedEntry = firstInjectedEntry; for (size_t i = motionEvent->getHistorySize(); i > 0; i--) { sampleEventTimes += 1; @@ -2622,7 +2643,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, motionEvent->getEdgeFlags(), motionEvent->getXPrecision(), motionEvent->getYPrecision(), motionEvent->getDownTime(), displayId, - uint32_t(pointerCount), pointerProperties, samplePointerCoords); + uint32_t(pointerCount), pointerProperties, samplePointerCoords, + motionEvent->getXOffset(), motionEvent->getYOffset()); lastInjectedEntry->next = nextInjectedEntry; lastInjectedEntry = nextInjectedEntry; } @@ -2847,22 +2869,25 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inpu mFocusedWindowHandle = newFocusedWindowHandle; } - for (size_t i = 0; i < mTouchState.windows.size(); i++) { - TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i); - if (!hasWindowHandleLocked(touchedWindow.windowHandle)) { + for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) { + TouchState& state = mTouchStatesByDisplay.editValueAt(d); + for (size_t i = 0; i < state.windows.size(); i++) { + TouchedWindow& touchedWindow = state.windows.editItemAt(i); + if (!hasWindowHandleLocked(touchedWindow.windowHandle)) { #if DEBUG_FOCUS - ALOGD("Touched window was removed: %s", - touchedWindow.windowHandle->getName().string()); + ALOGD("Touched window was removed: %s", + touchedWindow.windowHandle->getName().string()); #endif - sp<InputChannel> touchedInputChannel = - touchedWindow.windowHandle->getInputChannel(); - if (touchedInputChannel != NULL) { - CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, - "touched window was removed"); - synthesizeCancelationEventsForInputChannelLocked( - touchedInputChannel, options); + sp<InputChannel> touchedInputChannel = + touchedWindow.windowHandle->getInputChannel(); + if (touchedInputChannel != NULL) { + CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, + "touched window was removed"); + synthesizeCancelationEventsForInputChannelLocked( + touchedInputChannel, options); + } + state.windows.removeAt(i--); } - mTouchState.windows.removeAt(i--); } } @@ -3003,23 +3028,27 @@ bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel, } bool found = false; - for (size_t i = 0; i < mTouchState.windows.size(); i++) { - const TouchedWindow& touchedWindow = mTouchState.windows[i]; - if (touchedWindow.windowHandle == fromWindowHandle) { - int32_t oldTargetFlags = touchedWindow.targetFlags; - BitSet32 pointerIds = touchedWindow.pointerIds; - - mTouchState.windows.removeAt(i); - - int32_t newTargetFlags = oldTargetFlags - & (InputTarget::FLAG_FOREGROUND - | InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS); - mTouchState.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds); - - found = true; - break; + for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) { + TouchState& state = mTouchStatesByDisplay.editValueAt(d); + for (size_t i = 0; i < state.windows.size(); i++) { + const TouchedWindow& touchedWindow = state.windows[i]; + if (touchedWindow.windowHandle == fromWindowHandle) { + int32_t oldTargetFlags = touchedWindow.targetFlags; + BitSet32 pointerIds = touchedWindow.pointerIds; + + state.windows.removeAt(i); + + int32_t newTargetFlags = oldTargetFlags + & (InputTarget::FLAG_FOREGROUND + | InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS); + state.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds); + + found = true; + goto Found; + } } } +Found: if (! found) { #if DEBUG_FOCUS @@ -3063,7 +3092,7 @@ void InputDispatcher::resetAndDropEverythingLocked(const char* reason) { drainInboundQueueLocked(); resetANRTimeoutsLocked(); - mTouchState.reset(); + mTouchStatesByDisplay.clear(); mLastHoverWindowHandle.clear(); } @@ -3098,22 +3127,28 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) { dump.appendFormat(INDENT "FocusedWindow: name='%s'\n", mFocusedWindowHandle != NULL ? mFocusedWindowHandle->getName().string() : "<null>"); - dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down)); - dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split)); - dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId); - dump.appendFormat(INDENT "TouchSource: 0x%08x\n", mTouchState.source); - dump.appendFormat(INDENT "TouchDisplayId: %d\n", mTouchState.displayId); - if (!mTouchState.windows.isEmpty()) { - dump.append(INDENT "TouchedWindows:\n"); - for (size_t i = 0; i < mTouchState.windows.size(); i++) { - const TouchedWindow& touchedWindow = mTouchState.windows[i]; - dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n", - i, touchedWindow.windowHandle->getName().string(), - touchedWindow.pointerIds.value, - touchedWindow.targetFlags); + if (!mTouchStatesByDisplay.isEmpty()) { + dump.appendFormat(INDENT "TouchStatesByDisplay:\n"); + for (size_t i = 0; i < mTouchStatesByDisplay.size(); i++) { + const TouchState& state = mTouchStatesByDisplay.valueAt(i); + dump.appendFormat(INDENT2 "%d: down=%s, split=%s, deviceId=%d, source=0x%08x\n", + state.displayId, toString(state.down), toString(state.split), + state.deviceId, state.source); + if (!state.windows.isEmpty()) { + dump.append(INDENT3 "Windows:\n"); + for (size_t i = 0; i < state.windows.size(); i++) { + const TouchedWindow& touchedWindow = state.windows[i]; + dump.appendFormat(INDENT4 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n", + i, touchedWindow.windowHandle->getName().string(), + touchedWindow.pointerIds.value, + touchedWindow.targetFlags); + } + } else { + dump.append(INDENT3 "Windows: <none>\n"); + } } } else { - dump.append(INDENT "TouchedWindows: <none>\n"); + dump.append(INDENT "TouchStates: <no displays touched>\n"); } if (!mWindowHandles.isEmpty()) { @@ -3898,7 +3933,8 @@ InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime, int32_t metaState, int32_t buttonState, int32_t edgeFlags, float xPrecision, float yPrecision, nsecs_t downTime, int32_t displayId, uint32_t pointerCount, - const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) : + const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, + float xOffset, float yOffset) : EventEntry(TYPE_MOTION, eventTime, policyFlags), eventTime(eventTime), deviceId(deviceId), source(source), action(action), flags(flags), @@ -3908,6 +3944,9 @@ InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime, for (uint32_t i = 0; i < pointerCount; i++) { this->pointerProperties[i].copyFrom(pointerProperties[i]); this->pointerCoords[i].copyFrom(pointerCoords[i]); + if (xOffset || yOffset) { + this->pointerCoords[i].applyOffset(xOffset, yOffset); + } } } @@ -4201,7 +4240,8 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim memento.flags, 0, 0, 0, memento.xPrecision, memento.yPrecision, memento.downTime, memento.displayId, - memento.pointerCount, memento.pointerProperties, memento.pointerCoords)); + memento.pointerCount, memento.pointerProperties, memento.pointerCoords, + 0, 0)); } } } diff --git a/services/input/InputDispatcher.h b/libs/input/InputDispatcher.h index 190e7b221058..29854b2d56e4 100644 --- a/services/input/InputDispatcher.h +++ b/libs/input/InputDispatcher.h @@ -297,7 +297,7 @@ public: * * This method may be called on any thread (usually by the input manager). */ - virtual int32_t injectInputEvent(const InputEvent* event, + virtual int32_t injectInputEvent(const InputEvent* event, int32_t displayId, int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, uint32_t policyFlags) = 0; @@ -381,7 +381,7 @@ public: virtual void notifySwitch(const NotifySwitchArgs* args); virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args); - virtual int32_t injectInputEvent(const InputEvent* event, + virtual int32_t injectInputEvent(const InputEvent* event, int32_t displayId, int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, uint32_t policyFlags); @@ -525,7 +525,8 @@ private: int32_t metaState, int32_t buttonState, int32_t edgeFlags, float xPrecision, float yPrecision, nsecs_t downTime, int32_t displayId, uint32_t pointerCount, - const PointerProperties* pointerProperties, const PointerCoords* pointerCoords); + const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, + float xOffset, float yOffset); virtual void appendDescription(String8& msg) const; protected: @@ -959,7 +960,7 @@ private: bool isSlippery() const; }; - TouchState mTouchState; + KeyedVector<int32_t, TouchState> mTouchStatesByDisplay; TouchState mTempTouchState; // Focused application. diff --git a/services/input/InputListener.cpp b/libs/input/InputListener.cpp index 85bb0ed5242e..85bb0ed5242e 100644 --- a/services/input/InputListener.cpp +++ b/libs/input/InputListener.cpp diff --git a/services/input/InputListener.h b/libs/input/InputListener.h index 78ae10f70dfb..78ae10f70dfb 100644 --- a/services/input/InputListener.h +++ b/libs/input/InputListener.h diff --git a/services/input/InputManager.cpp b/libs/input/InputManager.cpp index 6a6547bdf03c..6a6547bdf03c 100644 --- a/services/input/InputManager.cpp +++ b/libs/input/InputManager.cpp diff --git a/services/input/InputManager.h b/libs/input/InputManager.h index a213b2dfaa51..a213b2dfaa51 100644 --- a/services/input/InputManager.h +++ b/libs/input/InputManager.h diff --git a/services/input/InputReader.cpp b/libs/input/InputReader.cpp index 03852a5ffcff..03852a5ffcff 100644 --- a/services/input/InputReader.cpp +++ b/libs/input/InputReader.cpp diff --git a/services/input/InputReader.h b/libs/input/InputReader.h index a8bb63671b60..a8bb63671b60 100644 --- a/services/input/InputReader.h +++ b/libs/input/InputReader.h diff --git a/services/input/InputWindow.cpp b/libs/input/InputWindow.cpp index fe61918e1d86..fe61918e1d86 100644 --- a/services/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp diff --git a/services/input/InputWindow.h b/libs/input/InputWindow.h index 28fa7ab42d44..28fa7ab42d44 100644 --- a/services/input/InputWindow.h +++ b/libs/input/InputWindow.h diff --git a/services/input/PointerController.cpp b/libs/input/PointerController.cpp index 9af521b7aba2..9af521b7aba2 100644 --- a/services/input/PointerController.cpp +++ b/libs/input/PointerController.cpp diff --git a/services/input/PointerController.h b/libs/input/PointerController.h index 790c0bbd5ca9..790c0bbd5ca9 100644 --- a/services/input/PointerController.h +++ b/libs/input/PointerController.h diff --git a/services/input/SpriteController.cpp b/libs/input/SpriteController.cpp index fd9c66ba04cf..fd9c66ba04cf 100644 --- a/services/input/SpriteController.cpp +++ b/libs/input/SpriteController.cpp diff --git a/services/input/SpriteController.h b/libs/input/SpriteController.h index 75e4843d38dc..75e4843d38dc 100644 --- a/services/input/SpriteController.h +++ b/libs/input/SpriteController.h diff --git a/services/input/tests/Android.mk b/libs/input/tests/Android.mk index 9278f413c3a0..9278f413c3a0 100644 --- a/services/input/tests/Android.mk +++ b/libs/input/tests/Android.mk diff --git a/services/input/tests/InputDispatcher_test.cpp b/libs/input/tests/InputDispatcher_test.cpp index 26b4fab794d8..fc89a9b18905 100644 --- a/services/input/tests/InputDispatcher_test.cpp +++ b/libs/input/tests/InputDispatcher_test.cpp @@ -27,6 +27,9 @@ static const nsecs_t ARBITRARY_TIME = 1234; // An arbitrary device id. static const int32_t DEVICE_ID = 1; +// An arbitrary display id. +static const int32_t DISPLAY_ID = 0; + // An arbitrary injector pid / uid pair that has permission to inject events. static const int32_t INJECTOR_PID = 999; static const int32_t INJECTOR_UID = 1001; @@ -126,7 +129,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) { event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( + &event, DISPLAY_ID, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject key events with undefined action."; @@ -134,7 +138,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) { event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( + &event, DISPLAY_ID, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject key events with ACTION_MULTIPLE."; } @@ -154,7 +159,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( + &event, DISPLAY_ID, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with undefined action."; @@ -164,7 +170,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( + &event, DISPLAY_ID, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with pointer down index too large."; @@ -173,7 +180,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( + &event, DISPLAY_ID, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with pointer down index too small."; @@ -183,7 +191,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( + &event, DISPLAY_ID, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with pointer up index too large."; @@ -192,7 +201,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( + &event, DISPLAY_ID, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with pointer up index too small."; @@ -201,7 +211,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 0, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( + &event, DISPLAY_ID, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with 0 pointers."; @@ -209,7 +220,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( + &event, DISPLAY_ID, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with more than MAX_POINTERS pointers."; @@ -219,7 +231,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( + &event, DISPLAY_ID, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with pointer ids less than 0."; @@ -228,7 +241,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( + &event, DISPLAY_ID, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with pointer ids greater than MAX_POINTER_ID."; @@ -239,7 +253,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 2, pointerProperties, pointerCoords); - ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, + ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( + &event, DISPLAY_ID, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with duplicate pointer ids."; } diff --git a/services/input/tests/InputReader_test.cpp b/libs/input/tests/InputReader_test.cpp index f0687324d242..f0687324d242 100644 --- a/services/input/tests/InputReader_test.cpp +++ b/libs/input/tests/InputReader_test.cpp diff --git a/packages/Keyguard/Android.mk b/packages/Keyguard/Android.mk index f6f441d002fb..1f2b5fb51372 100644 --- a/packages/Keyguard/Android.mk +++ b/packages/Keyguard/Android.mk @@ -18,8 +18,6 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-subdir-Iaidl-files) -LOCAL_JAVA_LIBRARIES := services - LOCAL_PACKAGE_NAME := Keyguard LOCAL_CERTIFICATE := platform diff --git a/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java b/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java index 6bf4beb0ea57..968976b93a90 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java +++ b/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java @@ -26,7 +26,8 @@ import android.view.LayoutInflater; public class PhoneLayoutInflater extends LayoutInflater { private static final String[] sClassPrefixList = { "android.widget.", - "android.webkit." + "android.webkit.", + "android.app." }; /** diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index c33bd3546aba..e38db586d5c4 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -231,7 +231,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */ boolean mEnableShiftMenuBugReports = false; - boolean mHeadless; boolean mSafeMode; WindowState mStatusBar = null; int mStatusBarHeight; @@ -855,7 +854,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mContext = context; mWindowManager = windowManager; mWindowManagerFuncs = windowManagerFuncs; - mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0")); mHandler = new PolicyHandler(); mOrientationListener = new MyOrientationListener(mContext, mHandler); try { @@ -1674,7 +1672,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { return view.getParent() != null ? view : null; } catch (WindowManager.BadTokenException e) { // ignore - Log.w(TAG, appToken + " already running, starting window not displayed"); + Log.w(TAG, appToken + " already running, starting window not displayed. " + + e.getMessage()); } catch (RuntimeException e) { // don't crash if something else bad happens, for example a // failure loading resources because we are loading from an app @@ -3602,9 +3601,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { - // do nothing if headless - if (mHeadless) return; - // lid changed state final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED; if (newLidState == mLidState) { @@ -3813,14 +3809,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (keyCode == KeyEvent.KEYCODE_POWER) { policyFlags |= WindowManagerPolicy.FLAG_WAKE; } - final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE - | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; if (DEBUG_INPUT) { Log.d(TAG, "interceptKeyTq keycode=" + keyCode + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive - + " policyFlags=" + Integer.toHexString(policyFlags) - + " isWakeKey=" + isWakeKey); + + " policyFlags=" + Integer.toHexString(policyFlags)); } if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0 @@ -3837,15 +3830,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { // the device some other way (which is why we have an exemption here for injected // events). int result; - if ((isScreenOn && !mHeadless) || (isInjected && !isWakeKey)) { + boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE + | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; + if (isScreenOn || (isInjected && !isWakeKey)) { // When the screen is on or if the key is injected pass the key to the application. result = ACTION_PASS_TO_USER; } else { // When the screen is off and the key is not injected, determine whether // to wake the device but don't pass the key to the application. result = 0; - if (down && isWakeKey && isWakeKeyWhenScreenOff(keyCode)) { - result |= ACTION_WAKE_UP; + if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) { + isWakeKey = false; } } @@ -3955,7 +3950,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } if ((mEndcallBehavior & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { - result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP; + mPowerManager.goToSleep(event.getEventTime()); + isWakeKey = false; } } } @@ -3999,7 +3995,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { mPowerKeyTriggered = false; cancelPendingScreenshotChordAction(); if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) { - result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP; + mPowerManager.goToSleep(event.getEventTime()); + isWakeKey = false; } mPendingPowerKeyUpCanceled = false; } @@ -4069,6 +4066,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; } } + + if (isWakeKey) { + mPowerManager.wakeUp(event.getEventTime()); + } return result; } @@ -4109,13 +4110,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override - public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) { + public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags) { int result = 0; final boolean isWakeMotion = (policyFlags & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; if (isWakeMotion) { - result |= ACTION_WAKE_UP; + mPowerManager.wakeUp(whenNanos / 1000000); } return result; } @@ -4663,10 +4664,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override public void systemReady() { - if (!mHeadless) { - mKeyguardDelegate = new KeyguardServiceDelegate(mContext, null); - mKeyguardDelegate.onSystemReady(); - } + mKeyguardDelegate = new KeyguardServiceDelegate(mContext, null); + mKeyguardDelegate.onSystemReady(); + synchronized (mLock) { updateOrientationListenerLp(); mSystemReady = true; @@ -4693,7 +4693,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ public void showBootMessage(final CharSequence msg, final boolean always) { - if (mHeadless) return; mHandler.post(new Runnable() { @Override public void run() { if (mBootMsgDialog == null) { diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java index 13574624ae26..e5af716e4f71 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java @@ -109,6 +109,9 @@ public class KeyguardServiceDelegate { if (!context.bindServiceAsUser(intent, mKeyguardConnection, Context.BIND_AUTO_CREATE, UserHandle.OWNER)) { if (DEBUG) Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS); + mKeyguardState.showing = false; + mKeyguardState.showingAndNotHidden = false; + mKeyguardState.secure = false; } else { if (DEBUG) Log.v(TAG, "*** Keyguard started"); } diff --git a/services/Android.mk b/services/Android.mk new file mode 100644 index 000000000000..5260540bb44b --- /dev/null +++ b/services/Android.mk @@ -0,0 +1,64 @@ +LOCAL_PATH:= $(call my-dir) + +# merge all required services into one jar +# ============================================================ +include $(CLEAR_VARS) + +LOCAL_MODULE := services + +LOCAL_SRC_FILES := $(call all-java-files-under,java) + +# Uncomment to enable output of certain warnings (deprecated, unchecked) +# LOCAL_JAVACFLAGS := -Xlint + +# Services that will be built as part of services.jar +# These should map to directory names relative to this +# Android.mk. +services := \ + core \ + accessibility \ + appwidget \ + backup \ + devicepolicy \ + print \ + usb + +# The convention is to name each service module 'services.$(module_name)' +LOCAL_STATIC_JAVA_LIBRARIES := $(addprefix services.,$(services)) + +include $(BUILD_JAVA_LIBRARY) + +# native library +# ============================================================= + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := +LOCAL_SHARED_LIBRARIES := + +# include all the jni subdirs to collect their sources +include $(wildcard $(LOCAL_PATH)/*/jni/Android.mk) + +LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES + +ifeq ($(WITH_MALLOC_LEAK_CHECK),true) + LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK +endif + +LOCAL_MODULE:= libandroid_servers + +include $(BUILD_SHARED_LIBRARY) + +# ============================================================= + +ifeq (,$(ONE_SHOT_MAKEFILE)) +# A full make is happening, so make everything. +include $(call all-makefiles-under,$(LOCAL_PATH)) +else +# If we ran an mm[m] command, we still want to build the individual +# services that we depend on. This differs from the above condition +# by only including service makefiles and not any tests or other +# modules. +include $(patsubst %,$(LOCAL_PATH)/%/Android.mk,$(services)) +endif + diff --git a/services/accessibility/Android.mk b/services/accessibility/Android.mk new file mode 100644 index 000000000000..d98fc281dfb7 --- /dev/null +++ b/services/accessibility/Android.mk @@ -0,0 +1,10 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := services.accessibility + +LOCAL_SRC_FILES += \ + $(call all-java-files-under,java) + +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java index 9e893da02c70..9e893da02c70 100644 --- a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index ccac0d32ea7b..ccac0d32ea7b 100644 --- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java diff --git a/services/java/com/android/server/accessibility/EventStreamTransformation.java b/services/accessibility/java/com/android/server/accessibility/EventStreamTransformation.java index 8c93e7b4440d..8c93e7b4440d 100644 --- a/services/java/com/android/server/accessibility/EventStreamTransformation.java +++ b/services/accessibility/java/com/android/server/accessibility/EventStreamTransformation.java diff --git a/services/java/com/android/server/accessibility/GestureUtils.java b/services/accessibility/java/com/android/server/accessibility/GestureUtils.java index b68b09f8d0a0..b68b09f8d0a0 100644 --- a/services/java/com/android/server/accessibility/GestureUtils.java +++ b/services/accessibility/java/com/android/server/accessibility/GestureUtils.java diff --git a/services/java/com/android/server/accessibility/ScreenMagnifier.java b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java index 5f12cf41c1b5..5f12cf41c1b5 100644 --- a/services/java/com/android/server/accessibility/ScreenMagnifier.java +++ b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java index 43f12ebedde1..43f12ebedde1 100644 --- a/services/java/com/android/server/accessibility/TouchExplorer.java +++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java diff --git a/services/appwidget/Android.mk b/services/appwidget/Android.mk new file mode 100644 index 000000000000..ca38f2f6449d --- /dev/null +++ b/services/appwidget/Android.mk @@ -0,0 +1,10 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := services.appwidget + +LOCAL_SRC_FILES += \ + $(call all-java-files-under,java) + +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java new file mode 100644 index 000000000000..e20867762daa --- /dev/null +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java @@ -0,0 +1,384 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.appwidget; + +import android.app.ActivityManager; +import android.appwidget.AppWidgetProviderInfo; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.os.Binder; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.UserHandle; +import android.util.Slog; +import android.util.SparseArray; +import android.widget.RemoteViews; + +import com.android.internal.appwidget.IAppWidgetHost; +import com.android.internal.appwidget.IAppWidgetService; +import com.android.internal.os.BackgroundThread; +import com.android.internal.util.IndentingPrintWriter; +import com.android.server.SystemService; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.List; +import java.util.Locale; + + +/** + * SystemService that publishes an IAppWidgetService. + */ +public class AppWidgetService extends SystemService { + + static final String TAG = "AppWidgetService"; + + final Context mContext; + final Handler mSaveStateHandler; + + final SparseArray<AppWidgetServiceImpl> mAppWidgetServices; + + public AppWidgetService(Context context) { + super(context); + mContext = context; + + mSaveStateHandler = BackgroundThread.getHandler(); + + mAppWidgetServices = new SparseArray<AppWidgetServiceImpl>(5); + AppWidgetServiceImpl primary = new AppWidgetServiceImpl(context, 0, mSaveStateHandler); + mAppWidgetServices.append(0, primary); + } + + @Override + public void onStart() { + publishBinderService(Context.APPWIDGET_SERVICE, mServiceImpl); + } + + @Override + public void onBootPhase(int phase) { + if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { + mServiceImpl.systemRunning(isSafeMode()); + } + } + + private final AppWidgetServiceStub mServiceImpl = new AppWidgetServiceStub(); + + private class AppWidgetServiceStub extends IAppWidgetService.Stub { + + private boolean mSafeMode; + private Locale mLocale; + private PackageManager mPackageManager; + + public void systemRunning(boolean safeMode) { + mSafeMode = safeMode; + + mAppWidgetServices.get(0).systemReady(safeMode); + + // Register for the boot completed broadcast, so we can send the + // ENABLE broacasts. If we try to send them now, they time out, + // because the system isn't ready to handle them yet. + mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, + new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null); + + // Register for configuration changes so we can update the names + // of the widgets when the locale changes. + mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, + new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED), null, null); + + // Register for broadcasts about package install, etc., so we can + // update the provider list. + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_PACKAGE_ADDED); + filter.addAction(Intent.ACTION_PACKAGE_CHANGED); + filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addDataScheme("package"); + mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, + filter, null, null); + // Register for events related to sdcard installation. + IntentFilter sdFilter = new IntentFilter(); + sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); + sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); + mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, + sdFilter, null, null); + + IntentFilter userFilter = new IntentFilter(); + userFilter.addAction(Intent.ACTION_USER_REMOVED); + userFilter.addAction(Intent.ACTION_USER_STOPPING); + mContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) { + onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, + UserHandle.USER_NULL)); + } else if (Intent.ACTION_USER_STOPPING.equals(intent.getAction())) { + onUserStopping(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, + UserHandle.USER_NULL)); + } + } + }, userFilter); + } + + @Override + public int allocateAppWidgetId(String packageName, int hostId, int userId) + throws RemoteException { + return getImplForUser(userId).allocateAppWidgetId(packageName, hostId); + } + + @Override + public int[] getAppWidgetIdsForHost(int hostId, int userId) throws RemoteException { + return getImplForUser(userId).getAppWidgetIdsForHost(hostId); + } + + @Override + public void deleteAppWidgetId(int appWidgetId, int userId) throws RemoteException { + getImplForUser(userId).deleteAppWidgetId(appWidgetId); + } + + @Override + public void deleteHost(int hostId, int userId) throws RemoteException { + getImplForUser(userId).deleteHost(hostId); + } + + @Override + public void deleteAllHosts(int userId) throws RemoteException { + getImplForUser(userId).deleteAllHosts(); + } + + @Override + public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options, + int userId) throws RemoteException { + getImplForUser(userId).bindAppWidgetId(appWidgetId, provider, options); + } + + @Override + public boolean bindAppWidgetIdIfAllowed( + String packageName, int appWidgetId, ComponentName provider, Bundle options, + int userId) throws RemoteException { + return getImplForUser(userId).bindAppWidgetIdIfAllowed( + packageName, appWidgetId, provider, options); + } + + @Override + public boolean hasBindAppWidgetPermission(String packageName, int userId) + throws RemoteException { + return getImplForUser(userId).hasBindAppWidgetPermission(packageName); + } + + @Override + public void setBindAppWidgetPermission(String packageName, boolean permission, int userId) + throws RemoteException { + getImplForUser(userId).setBindAppWidgetPermission(packageName, permission); + } + + @Override + public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection, + int userId) throws RemoteException { + getImplForUser(userId).bindRemoteViewsService(appWidgetId, intent, connection); + } + + @Override + public int[] startListening(IAppWidgetHost host, String packageName, int hostId, + List<RemoteViews> updatedViews, int userId) throws RemoteException { + return getImplForUser(userId).startListening(host, packageName, hostId, updatedViews); + } + + public void onUserRemoved(int userId) { + if (userId < 1) return; + synchronized (mAppWidgetServices) { + AppWidgetServiceImpl impl = mAppWidgetServices.get(userId); + mAppWidgetServices.remove(userId); + + if (impl == null) { + AppWidgetServiceImpl.getSettingsFile(userId).delete(); + } else { + impl.onUserRemoved(); + } + } + } + + public void onUserStopping(int userId) { + if (userId < 1) return; + synchronized (mAppWidgetServices) { + AppWidgetServiceImpl impl = mAppWidgetServices.get(userId); + if (impl != null) { + mAppWidgetServices.remove(userId); + impl.onUserStopping(); + } + } + } + + private void checkPermission(int userId) { + int realUserId = ActivityManager.handleIncomingUser( + Binder.getCallingPid(), + Binder.getCallingUid(), + userId, + false, /* allowAll */ + true, /* requireFull */ + this.getClass().getSimpleName(), + this.getClass().getPackage().getName()); + } + + private AppWidgetServiceImpl getImplForUser(int userId) { + checkPermission(userId); + boolean sendInitial = false; + AppWidgetServiceImpl service; + synchronized (mAppWidgetServices) { + service = mAppWidgetServices.get(userId); + if (service == null) { + Slog.i(TAG, "Unable to find AppWidgetServiceImpl for user " + userId + + ", adding"); + // TODO: Verify that it's a valid user + service = new AppWidgetServiceImpl(mContext, userId, mSaveStateHandler); + service.systemReady(mSafeMode); + // Assume that BOOT_COMPLETED was received, as this is a non-primary user. + mAppWidgetServices.append(userId, service); + sendInitial = true; + } + } + if (sendInitial) { + service.sendInitialBroadcasts(); + } + return service; + } + + @Override + public int[] getAppWidgetIds(ComponentName provider, int userId) throws RemoteException { + return getImplForUser(userId).getAppWidgetIds(provider); + } + + @Override + public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId, int userId) + throws RemoteException { + return getImplForUser(userId).getAppWidgetInfo(appWidgetId); + } + + @Override + public RemoteViews getAppWidgetViews(int appWidgetId, int userId) throws RemoteException { + return getImplForUser(userId).getAppWidgetViews(appWidgetId); + } + + @Override + public void updateAppWidgetOptions(int appWidgetId, Bundle options, int userId) { + getImplForUser(userId).updateAppWidgetOptions(appWidgetId, options); + } + + @Override + public Bundle getAppWidgetOptions(int appWidgetId, int userId) { + return getImplForUser(userId).getAppWidgetOptions(appWidgetId); + } + + @Override + public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter, int userId) + throws RemoteException { + return getImplForUser(userId).getInstalledProviders(categoryFilter); + } + + @Override + public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId, int userId) + throws RemoteException { + getImplForUser(userId).notifyAppWidgetViewDataChanged( + appWidgetIds, viewId); + } + + @Override + public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId) + throws RemoteException { + getImplForUser(userId).partiallyUpdateAppWidgetIds( + appWidgetIds, views); + } + + @Override + public void stopListening(int hostId, int userId) throws RemoteException { + getImplForUser(userId).stopListening(hostId); + } + + @Override + public void unbindRemoteViewsService(int appWidgetId, Intent intent, int userId) + throws RemoteException { + getImplForUser(userId).unbindRemoteViewsService( + appWidgetId, intent); + } + + @Override + public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId) + throws RemoteException { + getImplForUser(userId).updateAppWidgetIds(appWidgetIds, views); + } + + @Override + public void updateAppWidgetProvider(ComponentName provider, RemoteViews views, int userId) + throws RemoteException { + getImplForUser(userId).updateAppWidgetProvider(provider, views); + } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); + + // Dump the state of all the app widget providers + synchronized (mAppWidgetServices) { + IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); + for (int i = 0; i < mAppWidgetServices.size(); i++) { + pw.println("User: " + mAppWidgetServices.keyAt(i)); + ipw.increaseIndent(); + AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); + service.dump(fd, ipw, args); + ipw.decreaseIndent(); + } + } + } + + BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + // Slog.d(TAG, "received " + action); + if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { + int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); + if (userId >= 0) { + getImplForUser(userId).sendInitialBroadcasts(); + } else { + Slog.w(TAG, "Incorrect user handle supplied in " + intent); + } + } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) { + for (int i = 0; i < mAppWidgetServices.size(); i++) { + AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); + service.onConfigurationChanged(); + } + } else { + int sendingUser = getSendingUserId(); + if (sendingUser == UserHandle.USER_ALL) { + for (int i = 0; i < mAppWidgetServices.size(); i++) { + AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); + service.onBroadcastReceived(intent); + } + } else { + AppWidgetServiceImpl service = mAppWidgetServices.get(sendingUser); + if (service != null) { + service.onBroadcastReceived(intent); + } + } + } + } + }; + } +} diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index 69ae846597f7..98dead312469 100644 --- a/services/java/com/android/server/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.appwidget; import android.app.AlarmManager; import android.app.AppGlobals; diff --git a/services/backup/Android.mk b/services/backup/Android.mk new file mode 100644 index 000000000000..3e686d122668 --- /dev/null +++ b/services/backup/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := services.backup + +LOCAL_SRC_FILES += \ + $(call all-java-files-under,java) + +LOCAL_JAVA_LIBRARIES := services.core + +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/services/java/com/android/server/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 00bfee78bfbb..ca2f7b1c46e6 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.backup; import android.app.ActivityManagerNative; import android.app.AlarmManager; @@ -83,7 +83,9 @@ import com.android.internal.backup.BackupConstants; import com.android.internal.backup.IBackupTransport; import com.android.internal.backup.IObbBackupService; import com.android.internal.backup.LocalTransport; -import com.android.server.PackageManagerBackupAgent.Metadata; +import com.android.server.EventLogTags; +import com.android.server.SystemService; +import com.android.server.backup.PackageManagerBackupAgent.Metadata; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -135,7 +137,8 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; -class BackupManagerService extends IBackupManager.Stub { +public class BackupManagerService extends IBackupManager.Stub { + private static final String TAG = "BackupManagerService"; private static final boolean DEBUG = true; private static final boolean MORE_DEBUG = false; @@ -271,6 +274,20 @@ class BackupManagerService extends IBackupManager.Stub { // Watch the device provisioning operation during setup ContentObserver mProvisionedObserver; + public static final class Lifecycle extends SystemService { + private final BackupManagerService mService; + + public Lifecycle(Context context) { + super(context); + mService = new BackupManagerService(context); + } + + @Override + public void onStart() { + publishBinderService(Context.BACKUP_SERVICE, mService); + } + } + class ProvisionedObserver extends ContentObserver { public ProvisionedObserver(Handler handler) { super(handler); @@ -1178,7 +1195,8 @@ class BackupManagerService extends IBackupManager.Stub { // First, on an encrypted device we require matching the device pw final boolean isEncrypted; try { - isEncrypted = (mMountService.getEncryptionState() != MountService.ENCRYPTION_STATE_NONE); + isEncrypted = (mMountService.getEncryptionState() != + IMountService.ENCRYPTION_STATE_NONE); if (isEncrypted) { if (DEBUG) { Slog.i(TAG, "Device encrypted; verifying against device data pw"); @@ -5437,7 +5455,8 @@ class BackupManagerService extends IBackupManager.Stub { boolean isEncrypted; try { - isEncrypted = (mMountService.getEncryptionState() != MountService.ENCRYPTION_STATE_NONE); + isEncrypted = (mMountService.getEncryptionState() != + IMountService.ENCRYPTION_STATE_NONE); if (isEncrypted) Slog.w(TAG, "Device is encrypted; forcing enc password"); } catch (RemoteException e) { // couldn't contact the mount service; fail "safe" and assume encryption @@ -6086,7 +6105,7 @@ class BackupManagerService extends IBackupManager.Stub { } } - // clean up the BackupManagerService side of the bookkeeping + // clean up the BackupManagerImpl side of the bookkeeping // and cancel any pending timeout message mBackupManager.clearRestoreSession(mSession); } diff --git a/services/java/com/android/server/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java index 77bddb0717ec..495da886fa65 100644 --- a/services/java/com/android/server/PackageManagerBackupAgent.java +++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.backup; import android.app.backup.BackupAgent; import android.app.backup.BackupDataInput; diff --git a/services/java/com/android/server/SystemBackupAgent.java b/services/backup/java/com/android/server/backup/SystemBackupAgent.java index 8cf273dee8cc..26e2e2ac356c 100644 --- a/services/java/com/android/server/SystemBackupAgent.java +++ b/services/backup/java/com/android/server/backup/SystemBackupAgent.java @@ -14,9 +14,10 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.backup; +import android.app.IWallpaperManager; import android.app.backup.BackupDataInput; import android.app.backup.BackupDataOutput; import android.app.backup.BackupAgentHelper; @@ -26,11 +27,11 @@ import android.app.backup.WallpaperBackupHelper; import android.content.Context; import android.os.Environment; import android.os.ParcelFileDescriptor; +import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.util.Slog; - import java.io.File; import java.io.IOException; @@ -63,16 +64,23 @@ public class SystemBackupAgent extends BackupAgentHelper { public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException { // We only back up the data under the current "wallpaper" schema with metadata - WallpaperManagerService wallpaper = (WallpaperManagerService)ServiceManager.getService( + IWallpaperManager wallpaper = (IWallpaperManager)ServiceManager.getService( Context.WALLPAPER_SERVICE); String[] files = new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO }; String[] keys = new String[] { WALLPAPER_IMAGE_KEY, WALLPAPER_INFO_KEY }; - if (wallpaper != null && wallpaper.getName() != null && wallpaper.getName().length() > 0) { - // When the wallpaper has a name, back up the info by itself. - // TODO: Don't rely on the innards of the service object like this! - // TODO: Send a delete for any stored wallpaper image in this case? - files = new String[] { WALLPAPER_INFO }; - keys = new String[] { WALLPAPER_INFO_KEY }; + if (wallpaper != null) { + try { + final String wallpaperName = wallpaper.getName(); + if (wallpaperName != null && wallpaperName.length() > 0) { + // When the wallpaper has a name, back up the info by itself. + // TODO: Don't rely on the innards of the service object like this! + // TODO: Send a delete for any stored wallpaper image in this case? + files = new String[] { WALLPAPER_INFO }; + keys = new String[] { WALLPAPER_INFO_KEY }; + } + } catch (RemoteException re) { + Slog.e(TAG, "Couldn't get wallpaper name\n" + re); + } } addHelper("wallpaper", new WallpaperBackupHelper(SystemBackupAgent.this, files, keys)); super.onBackup(oldState, data, newState); @@ -109,9 +117,15 @@ public class SystemBackupAgent extends BackupAgentHelper { try { super.onRestore(data, appVersionCode, newState); - WallpaperManagerService wallpaper = (WallpaperManagerService)ServiceManager.getService( + IWallpaperManager wallpaper = (IWallpaperManager) ServiceManager.getService( Context.WALLPAPER_SERVICE); - wallpaper.settingsRestored(); + if (wallpaper != null) { + try { + wallpaper.settingsRestored(); + } catch (RemoteException re) { + Slog.e(TAG, "Couldn't restore settings\n" + re); + } + } } catch (IOException ex) { // If there was a failure, delete everything for the wallpaper, this is too aggressive, // but this is hopefully a rare failure. @@ -149,10 +163,16 @@ public class SystemBackupAgent extends BackupAgentHelper { FullBackup.restoreFile(data, size, type, mode, mtime, outFile); if (restoredWallpaper) { - WallpaperManagerService wallpaper = - (WallpaperManagerService)ServiceManager.getService( + IWallpaperManager wallpaper = + (IWallpaperManager)ServiceManager.getService( Context.WALLPAPER_SERVICE); - wallpaper.settingsRestored(); + if (wallpaper != null) { + try { + wallpaper.settingsRestored(); + } catch (RemoteException re) { + Slog.e(TAG, "Couldn't restore settings\n" + re); + } + } } } catch (IOException e) { if (restoredWallpaper) { diff --git a/services/core/Android.mk b/services/core/Android.mk new file mode 100644 index 000000000000..5c4520170fd8 --- /dev/null +++ b/services/core/Android.mk @@ -0,0 +1,14 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := services.core + +LOCAL_SRC_FILES += \ + $(call all-java-files-under,java) \ + java/com/android/server/EventLogTags.logtags \ + java/com/android/server/am/EventLogTags.logtags + +LOCAL_JAVA_LIBRARIES := android.policy telephony-common + +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 2e1b0af7b099..96063d577526 100644 --- a/services/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -31,6 +31,7 @@ import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; import android.os.Message; import android.os.PowerManager; import android.os.SystemClock; @@ -64,54 +65,51 @@ import static android.app.AlarmManager.ELAPSED_REALTIME; import com.android.internal.util.LocalLog; -class AlarmManagerService extends IAlarmManager.Stub { +class AlarmManagerService extends SystemService { // The threshold for how long an alarm can be late before we print a // warning message. The time duration is in milliseconds. private static final long LATE_ALARM_THRESHOLD = 10 * 1000; private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP; private static final int RTC_MASK = 1 << RTC; - private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP; + private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP; private static final int ELAPSED_REALTIME_MASK = 1 << ELAPSED_REALTIME; - private static final int TIME_CHANGED_MASK = 1 << 16; - private static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK; + static final int TIME_CHANGED_MASK = 1 << 16; + static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK; // Mask for testing whether a given alarm type is wakeup vs non-wakeup - private static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup - - private static final String TAG = "AlarmManager"; - private static final String ClockReceiver_TAG = "ClockReceiver"; - private static final boolean localLOGV = false; - private static final boolean DEBUG_BATCH = localLOGV || false; - private static final boolean DEBUG_VALIDATE = localLOGV || false; - private static final int ALARM_EVENT = 1; - private static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; + static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup + + static final String TAG = "AlarmManager"; + static final String ClockReceiver_TAG = "ClockReceiver"; + static final boolean localLOGV = false; + static final boolean DEBUG_BATCH = localLOGV || false; + static final boolean DEBUG_VALIDATE = localLOGV || false; + static final int ALARM_EVENT = 1; + static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; - private static final Intent mBackgroundIntent + static final Intent mBackgroundIntent = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND); - private static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder(); + static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder(); - private static final boolean WAKEUP_STATS = false; + static final boolean WAKEUP_STATS = false; - private final Context mContext; + final LocalLog mLog = new LocalLog(TAG); - private final LocalLog mLog = new LocalLog(TAG); + final Object mLock = new Object(); - private Object mLock = new Object(); - - private long mNativeData; + long mNativeData; private long mNextWakeup; private long mNextNonWakeup; - private int mBroadcastRefCount = 0; - private PowerManager.WakeLock mWakeLock; - private ArrayList<InFlight> mInFlight = new ArrayList<InFlight>(); - private final AlarmThread mWaitThread = new AlarmThread(); - private final AlarmHandler mHandler = new AlarmHandler(); - private ClockReceiver mClockReceiver; + int mBroadcastRefCount = 0; + PowerManager.WakeLock mWakeLock; + ArrayList<InFlight> mInFlight = new ArrayList<InFlight>(); + final AlarmHandler mHandler = new AlarmHandler(); + ClockReceiver mClockReceiver; private UninstallReceiver mUninstallReceiver; - private final ResultReceiver mResultReceiver = new ResultReceiver(); - private final PendingIntent mTimeTickSender; - private final PendingIntent mDateChangeSender; + final ResultReceiver mResultReceiver = new ResultReceiver(); + PendingIntent mTimeTickSender; + PendingIntent mDateChangeSender; class WakeupEvent { public long when; @@ -125,8 +123,8 @@ class AlarmManagerService extends IAlarmManager.Stub { } } - private final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>(); - private final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day + final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>(); + final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day static final class Batch { long start; // These endpoints are always in ELAPSED @@ -317,9 +315,13 @@ class AlarmManagerService extends IAlarmManager.Stub { } // minimum recurrence period or alarm futurity for us to be able to fuzz it - private static final long MIN_FUZZABLE_INTERVAL = 10000; - private static final BatchTimeOrder sBatchOrder = new BatchTimeOrder(); - private final ArrayList<Batch> mAlarmBatches = new ArrayList<Batch>(); + static final long MIN_FUZZABLE_INTERVAL = 10000; + static final BatchTimeOrder sBatchOrder = new BatchTimeOrder(); + final ArrayList<Batch> mAlarmBatches = new ArrayList<Batch>(); + + public AlarmManagerService(Context context) { + super(context); + } static long convertToElapsed(long when, int type) { final boolean isRtc = (type == RTC || type == RTC_WAKEUP); @@ -403,7 +405,7 @@ class AlarmManagerService extends IAlarmManager.Stub { } } - private static final class InFlight extends Intent { + static final class InFlight extends Intent { final PendingIntent mPendingIntent; final WorkSource mWorkSource; final Pair<String, ComponentName> mTarget; @@ -427,7 +429,7 @@ class AlarmManagerService extends IAlarmManager.Stub { } } - private static final class FilterStats { + static final class FilterStats { final BroadcastStats mBroadcastStats; final Pair<String, ComponentName> mTarget; @@ -443,7 +445,7 @@ class AlarmManagerService extends IAlarmManager.Stub { } } - private static final class BroadcastStats { + static final class BroadcastStats { final String mPackageName; long aggregateTime; @@ -459,47 +461,48 @@ class AlarmManagerService extends IAlarmManager.Stub { } } - private final HashMap<String, BroadcastStats> mBroadcastStats + final HashMap<String, BroadcastStats> mBroadcastStats = new HashMap<String, BroadcastStats>(); - public AlarmManagerService(Context context) { - mContext = context; + @Override + public void onStart() { mNativeData = init(); mNextWakeup = mNextNonWakeup = 0; // We have to set current TimeZone info to kernel // because kernel doesn't keep this after reboot - String tz = SystemProperties.get(TIMEZONE_PROPERTY); - if (tz != null) { - setTimeZone(tz); - } + setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY)); - PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); + PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - mTimeTickSender = PendingIntent.getBroadcastAsUser(context, 0, + mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0, new Intent(Intent.ACTION_TIME_TICK).addFlags( Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND), 0, UserHandle.ALL); Intent intent = new Intent(Intent.ACTION_DATE_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); - mDateChangeSender = PendingIntent.getBroadcastAsUser(context, 0, intent, + mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent, Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL); // now that we have initied the driver schedule the alarm - mClockReceiver= new ClockReceiver(); + mClockReceiver = new ClockReceiver(); mClockReceiver.scheduleTimeTickEvent(); mClockReceiver.scheduleDateChangedEvent(); mUninstallReceiver = new UninstallReceiver(); if (mNativeData != 0) { - mWaitThread.start(); + AlarmThread waitThread = new AlarmThread(); + waitThread.start(); } else { Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler."); } + + publishBinderService(Context.ALARM_SERVICE, mService); } - + + @Override protected void finalize() throws Throwable { try { close(mNativeData); @@ -508,19 +511,51 @@ class AlarmManagerService extends IAlarmManager.Stub { } } - @Override - public void set(int type, long triggerAtTime, long windowLength, long interval, - PendingIntent operation, WorkSource workSource) { - if (workSource != null) { - mContext.enforceCallingPermission( - android.Manifest.permission.UPDATE_DEVICE_STATS, - "AlarmManager.set"); + void setTimeZoneImpl(String tz) { + if (TextUtils.isEmpty(tz)) { + return; } - set(type, triggerAtTime, windowLength, interval, operation, false, workSource); + TimeZone zone = TimeZone.getTimeZone(tz); + // Prevent reentrant calls from stepping on each other when writing + // the time zone property + boolean timeZoneWasChanged = false; + synchronized (this) { + String current = SystemProperties.get(TIMEZONE_PROPERTY); + if (current == null || !current.equals(zone.getID())) { + if (localLOGV) { + Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID()); + } + timeZoneWasChanged = true; + SystemProperties.set(TIMEZONE_PROPERTY, zone.getID()); + } + + // Update the kernel timezone information + // Kernel tracks time offsets as 'minutes west of GMT' + int gmtOffset = zone.getOffset(System.currentTimeMillis()); + setKernelTimezone(mNativeData, -(gmtOffset / 60000)); + } + + TimeZone.setDefault(null); + + if (timeZoneWasChanged) { + Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED); + intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); + intent.putExtra("time-zone", zone.getID()); + getContext().sendBroadcastAsUser(intent, UserHandle.ALL); + } } - public void set(int type, long triggerAtTime, long windowLength, long interval, + void removeImpl(PendingIntent operation) { + if (operation == null) { + return; + } + synchronized (mLock) { + removeLocked(operation); + } + } + + void setImpl(int type, long triggerAtTime, long windowLength, long interval, PendingIntent operation, boolean isStandalone, WorkSource workSource) { if (operation == null) { Slog.w(TAG, "set/setRepeating ignored because there is no intent"); @@ -606,231 +641,64 @@ class AlarmManagerService extends IAlarmManager.Stub { rescheduleKernelAlarmsLocked(); } - private void logBatchesLocked() { - ByteArrayOutputStream bs = new ByteArrayOutputStream(2048); - PrintWriter pw = new PrintWriter(bs); - final long nowRTC = System.currentTimeMillis(); - final long nowELAPSED = SystemClock.elapsedRealtime(); - final int NZ = mAlarmBatches.size(); - for (int iz = 0; iz < NZ; iz++) { - Batch bz = mAlarmBatches.get(iz); - pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz); - dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC); - pw.flush(); - Slog.v(TAG, bs.toString()); - bs.reset(); - } - } - - private boolean validateConsistencyLocked() { - if (DEBUG_VALIDATE) { - long lastTime = Long.MIN_VALUE; - final int N = mAlarmBatches.size(); - for (int i = 0; i < N; i++) { - Batch b = mAlarmBatches.get(i); - if (b.start >= lastTime) { - // duplicate start times are okay because of standalone batches - lastTime = b.start; - } else { - Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order"); - logBatchesLocked(); - return false; - } - } - } - return true; - } - - private Batch findFirstWakeupBatchLocked() { - final int N = mAlarmBatches.size(); - for (int i = 0; i < N; i++) { - Batch b = mAlarmBatches.get(i); - if (b.hasWakeups()) { - return b; + private final IBinder mService = new IAlarmManager.Stub() { + @Override + public void set(int type, long triggerAtTime, long windowLength, long interval, + PendingIntent operation, WorkSource workSource) { + if (workSource != null) { + getContext().enforceCallingPermission( + android.Manifest.permission.UPDATE_DEVICE_STATS, + "AlarmManager.set"); } - } - return null; - } - private void rescheduleKernelAlarmsLocked() { - // Schedule the next upcoming wakeup alarm. If there is a deliverable batch - // prior to that which contains no wakeups, we schedule that as well. - if (mAlarmBatches.size() > 0) { - final Batch firstWakeup = findFirstWakeupBatchLocked(); - final Batch firstBatch = mAlarmBatches.get(0); - if (firstWakeup != null && mNextWakeup != firstWakeup.start) { - mNextWakeup = firstWakeup.start; - setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start); - } - if (firstBatch != firstWakeup && mNextNonWakeup != firstBatch.start) { - mNextNonWakeup = firstBatch.start; - setLocked(ELAPSED_REALTIME, firstBatch.start); - } + setImpl(type, triggerAtTime, windowLength, interval, operation, + false, workSource); } - } - - public void setTime(long millis) { - mContext.enforceCallingOrSelfPermission( - "android.permission.SET_TIME", - "setTime"); - - SystemClock.setCurrentTimeMillis(millis); - } - - public void setTimeZone(String tz) { - mContext.enforceCallingOrSelfPermission( - "android.permission.SET_TIME_ZONE", - "setTimeZone"); - - long oldId = Binder.clearCallingIdentity(); - try { - if (TextUtils.isEmpty(tz)) return; - TimeZone zone = TimeZone.getTimeZone(tz); - // Prevent reentrant calls from stepping on each other when writing - // the time zone property - boolean timeZoneWasChanged = false; - synchronized (this) { - String current = SystemProperties.get(TIMEZONE_PROPERTY); - if (current == null || !current.equals(zone.getID())) { - if (localLOGV) { - Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID()); - } - timeZoneWasChanged = true; - SystemProperties.set(TIMEZONE_PROPERTY, zone.getID()); - } - - // Update the kernel timezone information - // Kernel tracks time offsets as 'minutes west of GMT' - int gmtOffset = zone.getOffset(System.currentTimeMillis()); - setKernelTimezone(mNativeData, -(gmtOffset / 60000)); - } - - TimeZone.setDefault(null); - if (timeZoneWasChanged) { - Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED); - intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); - intent.putExtra("time-zone", zone.getID()); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } - } finally { - Binder.restoreCallingIdentity(oldId); - } - } - - public void remove(PendingIntent operation) { - if (operation == null) { - return; - } - synchronized (mLock) { - removeLocked(operation); - } - } - - public void removeLocked(PendingIntent operation) { - boolean didRemove = false; - for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { - Batch b = mAlarmBatches.get(i); - didRemove |= b.remove(operation); - if (b.size() == 0) { - mAlarmBatches.remove(i); - } - } + @Override + public void setTime(long millis) { + getContext().enforceCallingOrSelfPermission( + "android.permission.SET_TIME", + "setTime"); - if (didRemove) { - if (DEBUG_BATCH) { - Slog.v(TAG, "remove(operation) changed bounds; rebatching"); - } - rebatchAllAlarmsLocked(true); - rescheduleKernelAlarmsLocked(); + SystemClock.setCurrentTimeMillis(millis); } - } - public void removeLocked(String packageName) { - boolean didRemove = false; - for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { - Batch b = mAlarmBatches.get(i); - didRemove |= b.remove(packageName); - if (b.size() == 0) { - mAlarmBatches.remove(i); + @Override + public void setTimeZone(String tz) { + getContext().enforceCallingOrSelfPermission( + "android.permission.SET_TIME_ZONE", + "setTimeZone"); + + final long oldId = Binder.clearCallingIdentity(); + try { + setTimeZoneImpl(tz); + } finally { + Binder.restoreCallingIdentity(oldId); } } - if (didRemove) { - if (DEBUG_BATCH) { - Slog.v(TAG, "remove(package) changed bounds; rebatching"); - } - rebatchAllAlarmsLocked(true); - rescheduleKernelAlarmsLocked(); - } - } + @Override + public void remove(PendingIntent operation) { + removeImpl(operation); - public void removeUserLocked(int userHandle) { - boolean didRemove = false; - for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { - Batch b = mAlarmBatches.get(i); - didRemove |= b.remove(userHandle); - if (b.size() == 0) { - mAlarmBatches.remove(i); - } } - if (didRemove) { - if (DEBUG_BATCH) { - Slog.v(TAG, "remove(user) changed bounds; rebatching"); + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump AlarmManager from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; } - rebatchAllAlarmsLocked(true); - rescheduleKernelAlarmsLocked(); - } - } - public boolean lookForPackageLocked(String packageName) { - for (int i = 0; i < mAlarmBatches.size(); i++) { - Batch b = mAlarmBatches.get(i); - if (b.hasPackage(packageName)) { - return true; - } + dumpImpl(pw); } - return false; - } + }; - private void setLocked(int type, long when) - { - if (mNativeData != 0) - { - // The kernel never triggers alarms with negative wakeup times - // so we ensure they are positive. - long alarmSeconds, alarmNanoseconds; - if (when < 0) { - alarmSeconds = 0; - alarmNanoseconds = 0; - } else { - alarmSeconds = when / 1000; - alarmNanoseconds = (when % 1000) * 1000 * 1000; - } - - set(mNativeData, type, alarmSeconds, alarmNanoseconds); - } - else - { - Message msg = Message.obtain(); - msg.what = ALARM_EVENT; - - mHandler.removeMessages(ALARM_EVENT); - mHandler.sendMessageAtTime(msg, when); - } - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump AlarmManager from from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return; - } - + void dumpImpl(PrintWriter pw) { synchronized (mLock) { pw.println("Current Alarm Manager state:"); final long nowRTC = System.currentTimeMillis(); @@ -980,6 +848,159 @@ class AlarmManagerService extends IAlarmManager.Stub { } } + private void logBatchesLocked() { + ByteArrayOutputStream bs = new ByteArrayOutputStream(2048); + PrintWriter pw = new PrintWriter(bs); + final long nowRTC = System.currentTimeMillis(); + final long nowELAPSED = SystemClock.elapsedRealtime(); + final int NZ = mAlarmBatches.size(); + for (int iz = 0; iz < NZ; iz++) { + Batch bz = mAlarmBatches.get(iz); + pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz); + dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC); + pw.flush(); + Slog.v(TAG, bs.toString()); + bs.reset(); + } + } + + private boolean validateConsistencyLocked() { + if (DEBUG_VALIDATE) { + long lastTime = Long.MIN_VALUE; + final int N = mAlarmBatches.size(); + for (int i = 0; i < N; i++) { + Batch b = mAlarmBatches.get(i); + if (b.start >= lastTime) { + // duplicate start times are okay because of standalone batches + lastTime = b.start; + } else { + Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order"); + logBatchesLocked(); + return false; + } + } + } + return true; + } + + private Batch findFirstWakeupBatchLocked() { + final int N = mAlarmBatches.size(); + for (int i = 0; i < N; i++) { + Batch b = mAlarmBatches.get(i); + if (b.hasWakeups()) { + return b; + } + } + return null; + } + + void rescheduleKernelAlarmsLocked() { + // Schedule the next upcoming wakeup alarm. If there is a deliverable batch + // prior to that which contains no wakeups, we schedule that as well. + if (mAlarmBatches.size() > 0) { + final Batch firstWakeup = findFirstWakeupBatchLocked(); + final Batch firstBatch = mAlarmBatches.get(0); + if (firstWakeup != null && mNextWakeup != firstWakeup.start) { + mNextWakeup = firstWakeup.start; + setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start); + } + if (firstBatch != firstWakeup && mNextNonWakeup != firstBatch.start) { + mNextNonWakeup = firstBatch.start; + setLocked(ELAPSED_REALTIME, firstBatch.start); + } + } + } + + private void removeLocked(PendingIntent operation) { + boolean didRemove = false; + for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { + Batch b = mAlarmBatches.get(i); + didRemove |= b.remove(operation); + if (b.size() == 0) { + mAlarmBatches.remove(i); + } + } + + if (didRemove) { + if (DEBUG_BATCH) { + Slog.v(TAG, "remove(operation) changed bounds; rebatching"); + } + rebatchAllAlarmsLocked(true); + rescheduleKernelAlarmsLocked(); + } + } + + void removeLocked(String packageName) { + boolean didRemove = false; + for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { + Batch b = mAlarmBatches.get(i); + didRemove |= b.remove(packageName); + if (b.size() == 0) { + mAlarmBatches.remove(i); + } + } + + if (didRemove) { + if (DEBUG_BATCH) { + Slog.v(TAG, "remove(package) changed bounds; rebatching"); + } + rebatchAllAlarmsLocked(true); + rescheduleKernelAlarmsLocked(); + } + } + + void removeUserLocked(int userHandle) { + boolean didRemove = false; + for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { + Batch b = mAlarmBatches.get(i); + didRemove |= b.remove(userHandle); + if (b.size() == 0) { + mAlarmBatches.remove(i); + } + } + + if (didRemove) { + if (DEBUG_BATCH) { + Slog.v(TAG, "remove(user) changed bounds; rebatching"); + } + rebatchAllAlarmsLocked(true); + rescheduleKernelAlarmsLocked(); + } + } + + boolean lookForPackageLocked(String packageName) { + for (int i = 0; i < mAlarmBatches.size(); i++) { + Batch b = mAlarmBatches.get(i); + if (b.hasPackage(packageName)) { + return true; + } + } + return false; + } + + private void setLocked(int type, long when) { + if (mNativeData != 0) { + // The kernel never triggers alarms with negative wakeup times + // so we ensure they are positive. + long alarmSeconds, alarmNanoseconds; + if (when < 0) { + alarmSeconds = 0; + alarmNanoseconds = 0; + } else { + alarmSeconds = when / 1000; + alarmNanoseconds = (when % 1000) * 1000 * 1000; + } + + set(mNativeData, type, alarmSeconds, alarmNanoseconds); + } else { + Message msg = Message.obtain(); + msg.what = ALARM_EVENT; + + mHandler.removeMessages(ALARM_EVENT); + mHandler.sendMessageAtTime(msg, when); + } + } + private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list, String prefix, String label, long now) { for (int i=list.size()-1; i>=0; i--) { @@ -1020,7 +1041,7 @@ class AlarmManagerService extends IAlarmManager.Stub { private native int waitForAlarm(long nativeData); private native int setKernelTimezone(long nativeData, int minuteswest); - private void triggerAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED, long nowRTC) { + void triggerAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED, long nowRTC) { // batches are temporally sorted, so we need only pull from the // start of the list until we either empty it or hit a batch // that is not yet deliverable @@ -1166,13 +1187,13 @@ class AlarmManagerService extends IAlarmManager.Stub { if (DEBUG_BATCH) { Slog.v(TAG, "Time changed notification from kernel; rebatching"); } - remove(mTimeTickSender); + removeImpl(mTimeTickSender); rebatchAllAlarms(); mClockReceiver.scheduleTimeTickEvent(); Intent intent = new Intent(Intent.ACTION_TIME_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + getContext().sendBroadcastAsUser(intent, UserHandle.ALL); } synchronized (mLock) { @@ -1206,7 +1227,7 @@ class AlarmManagerService extends IAlarmManager.Stub { Alarm alarm = triggerList.get(i); try { if (localLOGV) Slog.v(TAG, "sending alarm " + alarm); - alarm.operation.send(mContext, 0, + alarm.operation.send(getContext(), 0, mBackgroundIntent.putExtra( Intent.EXTRA_ALARM_COUNT, alarm.count), mResultReceiver, mHandler); @@ -1248,7 +1269,7 @@ class AlarmManagerService extends IAlarmManager.Stub { if (alarm.repeatInterval > 0) { // This IntentSender is no longer valid, but this // is a repeating alarm, so toss the hoser. - remove(alarm.operation); + removeImpl(alarm.operation); } } catch (RuntimeException e) { Slog.w(TAG, "Failure sending alarm.", e); @@ -1310,7 +1331,7 @@ class AlarmManagerService extends IAlarmManager.Stub { if (alarm.repeatInterval > 0) { // This IntentSender is no longer valid, but this // is a repeating alarm, so toss the hoser. - remove(alarm.operation); + removeImpl(alarm.operation); } } } @@ -1323,7 +1344,7 @@ class AlarmManagerService extends IAlarmManager.Stub { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_TIME_TICK); filter.addAction(Intent.ACTION_DATE_CHANGED); - mContext.registerReceiver(this, filter); + getContext().registerReceiver(this, filter); } @Override @@ -1354,7 +1375,7 @@ class AlarmManagerService extends IAlarmManager.Stub { final long tickEventDelay = nextTime - currentTime; final WorkSource workSource = null; // Let system take blame for time tick events. - set(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0, + setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0, 0, mTimeTickSender, true, workSource); } @@ -1368,7 +1389,7 @@ class AlarmManagerService extends IAlarmManager.Stub { calendar.add(Calendar.DAY_OF_MONTH, 1); final WorkSource workSource = null; // Let system take blame for date change events. - set(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, true, workSource); + setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, true, workSource); } } @@ -1379,12 +1400,12 @@ class AlarmManagerService extends IAlarmManager.Stub { filter.addAction(Intent.ACTION_PACKAGE_RESTARTED); filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); filter.addDataScheme("package"); - mContext.registerReceiver(this, filter); + getContext().registerReceiver(this, filter); // Register for events related to sdcard installation. IntentFilter sdFilter = new IntentFilter(); sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); sdFilter.addAction(Intent.ACTION_USER_STOPPED); - mContext.registerReceiver(this, sdFilter); + getContext().registerReceiver(this, sdFilter); } @Override diff --git a/services/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java index a1a0d47cb019..e5615c0441a2 100644 --- a/services/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -186,9 +186,9 @@ public class AppOpsService extends IAppOpsService.Stub { } } - public AppOpsService(File storagePath) { + public AppOpsService(File storagePath, Handler handler) { mFile = new AtomicFile(storagePath); - mHandler = new Handler(); + mHandler = handler; readState(); } diff --git a/services/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java index 3fb006b8486d..3fb006b8486d 100644 --- a/services/java/com/android/server/AssetAtlasService.java +++ b/services/core/java/com/android/server/AssetAtlasService.java diff --git a/services/java/com/android/server/AttributeCache.java b/services/core/java/com/android/server/AttributeCache.java index 427dbc091ced..427dbc091ced 100644 --- a/services/java/com/android/server/AttributeCache.java +++ b/services/core/java/com/android/server/AttributeCache.java diff --git a/services/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index 5f3f894ca68e..cc9055dd480e 100644 --- a/services/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -19,6 +19,8 @@ package com.android.server; import android.os.BatteryStats; import com.android.internal.app.IBatteryStats; import com.android.server.am.BatteryStatsService; +import com.android.server.lights.Light; +import com.android.server.lights.LightsManager; import android.app.ActivityManagerNative; import android.content.ContentResolver; @@ -134,13 +136,10 @@ public final class BatteryService extends Binder { private boolean mSentLowBatteryBroadcast = false; - private BatteryListener mBatteryPropertiesListener; - private IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar; - - public BatteryService(Context context, LightsService lights) { + public BatteryService(Context context, LightsManager lightsManager) { mContext = context; mHandler = new Handler(true /*async*/); - mLed = new Led(context, lights); + mLed = new Led(context, lightsManager); mBatteryStats = BatteryStatsService.getService(); mCriticalBatteryLevel = mContext.getResources().getInteger( @@ -158,13 +157,11 @@ public final class BatteryService extends Binder { "DEVPATH=/devices/virtual/switch/invalid_charger"); } - mBatteryPropertiesListener = new BatteryListener(); - IBinder b = ServiceManager.getService("batterypropreg"); - mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(b); - + final IBatteryPropertiesRegistrar batteryPropertiesRegistrar = + IBatteryPropertiesRegistrar.Stub.asInterface(b); try { - mBatteryPropertiesRegistrar.registerListener(mBatteryPropertiesListener); + batteryPropertiesRegistrar.registerListener(new BatteryListener()); } catch (RemoteException e) { // Should never happen. } @@ -688,7 +685,7 @@ public final class BatteryService extends Binder { }; private final class Led { - private final LightsService.Light mBatteryLight; + private final Light mBatteryLight; private final int mBatteryLowARGB; private final int mBatteryMediumARGB; @@ -696,8 +693,8 @@ public final class BatteryService extends Binder { private final int mBatteryLedOn; private final int mBatteryLedOff; - public Led(Context context, LightsService lights) { - mBatteryLight = lights.getLight(LightsService.LIGHT_ID_BATTERY); + public Led(Context context, LightsManager lights) { + mBatteryLight = lights.getLight(LightsManager.LIGHT_ID_BATTERY); mBatteryLowARGB = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryLowARGB); @@ -723,7 +720,7 @@ public final class BatteryService extends Binder { mBatteryLight.setColor(mBatteryLowARGB); } else { // Flash red when battery is low and not charging - mBatteryLight.setFlashing(mBatteryLowARGB, LightsService.LIGHT_FLASH_TIMED, + mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED, mBatteryLedOn, mBatteryLedOff); } } else if (status == BatteryManager.BATTERY_STATUS_CHARGING @@ -743,8 +740,14 @@ public final class BatteryService extends Binder { } private final class BatteryListener extends IBatteryPropertiesListener.Stub { + @Override public void batteryPropertiesChanged(BatteryProperties props) { - BatteryService.this.update(props); + final long identity = Binder.clearCallingIdentity(); + try { + BatteryService.this.update(props); + } finally { + Binder.restoreCallingIdentity(identity); + } } } } diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 546324a73e05..546324a73e05 100644 --- a/services/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java diff --git a/services/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java index da1b2548238f..bce85cee338b 100644 --- a/services/java/com/android/server/BootReceiver.java +++ b/services/core/java/com/android/server/BootReceiver.java @@ -120,6 +120,8 @@ public class BootReceiver extends BroadcastReceiver { // Negative sizes mean to take the *tail* of the file (see FileUtils.readTextFile()) addFileToDropBox(db, prefs, headers, "/proc/last_kmsg", -LOG_SIZE, "SYSTEM_LAST_KMSG"); + addFileToDropBox(db, prefs, headers, "/sys/fs/pstore/console-ramoops", + -LOG_SIZE, "SYSTEM_LAST_KMSG"); addFileToDropBox(db, prefs, headers, "/cache/recovery/log", -LOG_SIZE, "SYSTEM_RECOVERY_LOG"); addFileToDropBox(db, prefs, headers, "/data/dontpanic/apanic_console", @@ -184,6 +186,11 @@ public class BootReceiver extends BroadcastReceiver { File file = new File("/proc/last_kmsg"); long fileTime = file.lastModified(); + if (fileTime <= 0) { + file = new File("/sys/fs/pstore/console-ramoops"); + fileTime = file.lastModified(); + } + if (fileTime <= 0) return; // File does not exist if (prefs != null) { diff --git a/services/java/com/android/server/BrickReceiver.java b/services/core/java/com/android/server/BrickReceiver.java index cff3805b68d2..cff3805b68d2 100644 --- a/services/java/com/android/server/BrickReceiver.java +++ b/services/core/java/com/android/server/BrickReceiver.java diff --git a/services/java/com/android/server/CertBlacklister.java b/services/core/java/com/android/server/CertBlacklister.java index 8b167d7b0c90..8b167d7b0c90 100644 --- a/services/java/com/android/server/CertBlacklister.java +++ b/services/core/java/com/android/server/CertBlacklister.java diff --git a/services/java/com/android/server/CommonTimeManagementService.java b/services/core/java/com/android/server/CommonTimeManagementService.java index 710fb9d34596..710fb9d34596 100644 --- a/services/java/com/android/server/CommonTimeManagementService.java +++ b/services/core/java/com/android/server/CommonTimeManagementService.java diff --git a/services/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index d42ae3a945db..8d158cfd8f6b 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -26,6 +26,7 @@ import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIMAX; +import static android.net.ConnectivityManager.TYPE_PROXY; import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.isNetworkTypeValid; import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; @@ -69,6 +70,7 @@ import android.net.NetworkState; import android.net.NetworkStateTracker; import android.net.NetworkUtils; import android.net.Proxy; +import android.net.ProxyDataTracker; import android.net.ProxyProperties; import android.net.RouteInfo; import android.net.SamplingDataTracker; @@ -729,6 +731,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { return makeWimaxStateTracker(mContext, mTrackerHandler); case TYPE_ETHERNET: return EthernetDataTracker.getInstance(); + case TYPE_PROXY: + return new ProxyDataTracker(); default: throw new IllegalArgumentException( "Trying to create a NetworkStateTracker for an unknown radio type: " diff --git a/services/java/com/android/server/ConsumerIrService.java b/services/core/java/com/android/server/ConsumerIrService.java index 783dff111443..783dff111443 100644 --- a/services/java/com/android/server/ConsumerIrService.java +++ b/services/core/java/com/android/server/ConsumerIrService.java diff --git a/services/java/com/android/server/CountryDetectorService.java b/services/core/java/com/android/server/CountryDetectorService.java index a478b2f47637..a478b2f47637 100644 --- a/services/java/com/android/server/CountryDetectorService.java +++ b/services/core/java/com/android/server/CountryDetectorService.java diff --git a/services/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java index ac25dc58861d..ac25dc58861d 100644 --- a/services/java/com/android/server/DiskStatsService.java +++ b/services/core/java/com/android/server/DiskStatsService.java diff --git a/services/core/java/com/android/server/DisplayThread.java b/services/core/java/com/android/server/DisplayThread.java new file mode 100644 index 000000000000..528ba0a90a0b --- /dev/null +++ b/services/core/java/com/android/server/DisplayThread.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.os.Handler; + +/** + * Shared singleton foreground thread for the system. This is a thread for + * operations that affect what's on the display, which needs to have a minimum + * of latency. This thread should pretty much only be used by the WindowManager, + * DisplayManager, and InputManager to perform quick operations in real time. + */ +public final class DisplayThread extends ServiceThread { + private static DisplayThread sInstance; + private static Handler sHandler; + + private DisplayThread() { + super("android.display", android.os.Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/); + } + + private static void ensureThreadLocked() { + if (sInstance == null) { + sInstance = new DisplayThread(); + sInstance.start(); + sHandler = new Handler(sInstance.getLooper()); + } + } + + public static DisplayThread get() { + synchronized (UiThread.class) { + ensureThreadLocked(); + return sInstance; + } + } + + public static Handler getHandler() { + synchronized (UiThread.class) { + ensureThreadLocked(); + return sHandler; + } + } +} diff --git a/services/java/com/android/server/DockObserver.java b/services/core/java/com/android/server/DockObserver.java index 4a8bf720aae1..4a8bf720aae1 100644 --- a/services/java/com/android/server/DockObserver.java +++ b/services/core/java/com/android/server/DockObserver.java diff --git a/services/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java index 29b04da9c564..29b04da9c564 100644 --- a/services/java/com/android/server/DropBoxManagerService.java +++ b/services/core/java/com/android/server/DropBoxManagerService.java diff --git a/services/java/com/android/server/EntropyMixer.java b/services/core/java/com/android/server/EntropyMixer.java index cfdbf7d530cd..cfdbf7d530cd 100644 --- a/services/java/com/android/server/EntropyMixer.java +++ b/services/core/java/com/android/server/EntropyMixer.java diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags index 399e7d183658..399e7d183658 100644 --- a/services/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags diff --git a/services/java/com/android/server/FgThread.java b/services/core/java/com/android/server/FgThread.java index 3b655f2cee93..03765db35bae 100644 --- a/services/java/com/android/server/FgThread.java +++ b/services/core/java/com/android/server/FgThread.java @@ -17,7 +17,6 @@ package com.android.server; import android.os.Handler; -import android.os.HandlerThread; /** * Shared singleton foreground thread for the system. This is a thread for regular @@ -27,12 +26,12 @@ import android.os.HandlerThread; * simply being a background priority), which can cause operations scheduled on it * to be delayed for a user-noticeable amount of time. */ -public final class FgThread extends HandlerThread { +public final class FgThread extends ServiceThread { private static FgThread sInstance; private static Handler sHandler; private FgThread() { - super("android.fg", android.os.Process.THREAD_PRIORITY_DEFAULT); + super("android.fg", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/); } private static void ensureThreadLocked() { @@ -40,12 +39,6 @@ public final class FgThread extends HandlerThread { sInstance = new FgThread(); sInstance.start(); sHandler = new Handler(sInstance.getLooper()); - sHandler.post(new Runnable() { - @Override - public void run() { - android.os.Process.setCanSelfBackground(false); - } - }); } } diff --git a/services/java/com/android/server/INativeDaemonConnectorCallbacks.java b/services/core/java/com/android/server/INativeDaemonConnectorCallbacks.java index 6fbf713d3f7a..6fbf713d3f7a 100644 --- a/services/java/com/android/server/INativeDaemonConnectorCallbacks.java +++ b/services/core/java/com/android/server/INativeDaemonConnectorCallbacks.java diff --git a/services/java/com/android/server/IdleMaintenanceService.java b/services/core/java/com/android/server/IdleMaintenanceService.java index b0a1aca37d7c..b0a1aca37d7c 100644 --- a/services/java/com/android/server/IdleMaintenanceService.java +++ b/services/core/java/com/android/server/IdleMaintenanceService.java diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index a996dbda5cf5..26424a58061f 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -28,7 +28,7 @@ import com.android.internal.view.IInputMethodClient; import com.android.internal.view.IInputMethodManager; import com.android.internal.view.IInputMethodSession; import com.android.internal.view.InputBindResult; -import com.android.server.EventLogTags; +import com.android.server.statusbar.StatusBarManagerService; import com.android.server.wm.WindowManagerService; import org.xmlpull.v1.XmlPullParser; diff --git a/services/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java index 64b0487fa320..64b0487fa320 100644 --- a/services/java/com/android/server/IntentResolver.java +++ b/services/core/java/com/android/server/IntentResolver.java diff --git a/services/java/com/android/server/IoThread.java b/services/core/java/com/android/server/IoThread.java index 09f2af79c83d..0f29857db345 100644 --- a/services/java/com/android/server/IoThread.java +++ b/services/core/java/com/android/server/IoThread.java @@ -17,19 +17,18 @@ package com.android.server; import android.os.Handler; -import android.os.HandlerThread; /** * Shared singleton I/O thread for the system. This is a thread for non-background * service operations that can potential block briefly on network IO operations * (not waiting for data itself, but communicating with network daemons). */ -public final class IoThread extends HandlerThread { +public final class IoThread extends ServiceThread { private static IoThread sInstance; private static Handler sHandler; private IoThread() { - super("android.io", android.os.Process.THREAD_PRIORITY_DEFAULT); + super("android.io", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/); } private static void ensureThreadLocked() { @@ -37,12 +36,6 @@ public final class IoThread extends HandlerThread { sInstance = new IoThread(); sInstance.start(); sHandler = new Handler(sInstance.getLooper()); - sHandler.post(new Runnable() { - @Override - public void run() { - android.os.Process.setCanSelfBackground(false); - } - }); } } diff --git a/services/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index eebd1c5e9642..eebd1c5e9642 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java diff --git a/services/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index 35e7afad301c..35e7afad301c 100644 --- a/services/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java diff --git a/services/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java index 86f57d124868..86f57d124868 100644 --- a/services/java/com/android/server/MasterClearReceiver.java +++ b/services/core/java/com/android/server/MasterClearReceiver.java diff --git a/services/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 816ae6967cfd..816ae6967cfd 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java index 417d6d81cdf6..417d6d81cdf6 100644 --- a/services/java/com/android/server/NativeDaemonConnector.java +++ b/services/core/java/com/android/server/NativeDaemonConnector.java diff --git a/services/java/com/android/server/NativeDaemonConnectorException.java b/services/core/java/com/android/server/NativeDaemonConnectorException.java index 590bbccdbc5d..590bbccdbc5d 100644 --- a/services/java/com/android/server/NativeDaemonConnectorException.java +++ b/services/core/java/com/android/server/NativeDaemonConnectorException.java diff --git a/services/java/com/android/server/NativeDaemonEvent.java b/services/core/java/com/android/server/NativeDaemonEvent.java index 209515279bf8..209515279bf8 100644 --- a/services/java/com/android/server/NativeDaemonEvent.java +++ b/services/core/java/com/android/server/NativeDaemonEvent.java diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index ad7ec99775a3..ad7ec99775a3 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java diff --git a/services/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java index fddb54e138e2..fddb54e138e2 100644 --- a/services/java/com/android/server/NetworkTimeUpdateService.java +++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java diff --git a/services/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index 16d2468e7c9d..16d2468e7c9d 100644 --- a/services/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java diff --git a/services/java/com/android/server/RandomBlock.java b/services/core/java/com/android/server/RandomBlock.java index 6d6d9010a8d9..6d6d9010a8d9 100644 --- a/services/java/com/android/server/RandomBlock.java +++ b/services/core/java/com/android/server/RandomBlock.java diff --git a/services/java/com/android/server/RecognitionManagerService.java b/services/core/java/com/android/server/RecognitionManagerService.java index c2e749d3382a..c2e749d3382a 100644 --- a/services/java/com/android/server/RecognitionManagerService.java +++ b/services/core/java/com/android/server/RecognitionManagerService.java diff --git a/services/java/com/android/server/SamplingProfilerService.java b/services/core/java/com/android/server/SamplingProfilerService.java index fbf1aa4b8db0..fbf1aa4b8db0 100644 --- a/services/java/com/android/server/SamplingProfilerService.java +++ b/services/core/java/com/android/server/SamplingProfilerService.java diff --git a/services/java/com/android/server/SerialService.java b/services/core/java/com/android/server/SerialService.java index 1abe4588261a..1abe4588261a 100644 --- a/services/java/com/android/server/SerialService.java +++ b/services/core/java/com/android/server/SerialService.java diff --git a/services/core/java/com/android/server/ServiceThread.java b/services/core/java/com/android/server/ServiceThread.java new file mode 100644 index 000000000000..bce64afd0c5e --- /dev/null +++ b/services/core/java/com/android/server/ServiceThread.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.os.HandlerThread; +import android.os.Process; +import android.os.StrictMode; +import android.util.Slog; + +/** + * Special handler thread that we create for system services that require their own loopers. + */ +public class ServiceThread extends HandlerThread { + private static final String TAG = "ServiceThread"; + + private final boolean mAllowIo; + + public ServiceThread(String name, int priority, boolean allowIo) { + super(name, priority); + mAllowIo = allowIo; + } + + @Override + public void run() { + Process.setCanSelfBackground(false); + + // For debug builds, log event loop stalls to dropbox for analysis. + if (!mAllowIo && StrictMode.conditionallyEnableDebugLogging()) { + Slog.i(TAG, "Enabled StrictMode logging for " + getName() + " looper."); + } + + super.run(); + } +}
\ No newline at end of file diff --git a/services/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java index 5c7bfab7ec20..5c7bfab7ec20 100644 --- a/services/java/com/android/server/ServiceWatcher.java +++ b/services/core/java/com/android/server/ServiceWatcher.java diff --git a/services/java/com/android/server/ShutdownActivity.java b/services/core/java/com/android/server/ShutdownActivity.java index be651417150f..be651417150f 100644 --- a/services/java/com/android/server/ShutdownActivity.java +++ b/services/core/java/com/android/server/ShutdownActivity.java diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 699d79eb0953..699d79eb0953 100644 --- a/services/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java index 09647674e07f..09647674e07f 100644 --- a/services/java/com/android/server/TextServicesManagerService.java +++ b/services/core/java/com/android/server/TextServicesManagerService.java diff --git a/services/java/com/android/server/TwilightCalculator.java b/services/core/java/com/android/server/TwilightCalculator.java index a5c93b5173d4..a5c93b5173d4 100644 --- a/services/java/com/android/server/TwilightCalculator.java +++ b/services/core/java/com/android/server/TwilightCalculator.java diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index 062be01ab26a..ad693d00248d 100644 --- a/services/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -34,9 +34,9 @@ import android.content.res.Configuration; import android.os.BatteryManager; import android.os.Binder; import android.os.Handler; +import android.os.IBinder; import android.os.PowerManager; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.UserHandle; import android.provider.Settings; import android.service.dreams.Sandman; @@ -47,9 +47,11 @@ import java.io.PrintWriter; import com.android.internal.R; import com.android.internal.app.DisableCarModeActivity; -import com.android.server.TwilightService.TwilightState; +import com.android.server.twilight.TwilightListener; +import com.android.server.twilight.TwilightManager; +import com.android.server.twilight.TwilightState; -final class UiModeManagerService extends IUiModeManager.Stub { +final class UiModeManagerService extends SystemService { private static final String TAG = UiModeManager.class.getSimpleName(); private static final boolean LOG = false; @@ -57,40 +59,40 @@ final class UiModeManagerService extends IUiModeManager.Stub { private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true; private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true; - private final Context mContext; - private final TwilightService mTwilightService; - private final Handler mHandler = new Handler(); - final Object mLock = new Object(); - private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED; + private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED; + int mNightMode = UiModeManager.MODE_NIGHT_NO; - private int mNightMode = UiModeManager.MODE_NIGHT_NO; private boolean mCarModeEnabled = false; private boolean mCharging = false; - private final int mDefaultUiModeType; - private final boolean mCarModeKeepsScreenOn; - private final boolean mDeskModeKeepsScreenOn; - private final boolean mTelevision; - + private int mDefaultUiModeType; + private boolean mCarModeKeepsScreenOn; + private boolean mDeskModeKeepsScreenOn; + private boolean mTelevision; private boolean mComputedNightMode; - private int mCurUiMode = 0; - private int mSetUiMode = 0; + int mCurUiMode = 0; + private int mSetUiMode = 0; private boolean mHoldingConfiguration = false; + private Configuration mConfiguration = new Configuration(); + boolean mSystemReady; - private boolean mSystemReady; + private final Handler mHandler = new Handler(); + private TwilightManager mTwilightManager; private NotificationManager mNotificationManager; - private StatusBarManager mStatusBarManager; - private final PowerManager mPowerManager; - private final PowerManager.WakeLock mWakeLock; + private PowerManager.WakeLock mWakeLock; + + public UiModeManagerService(Context context) { + super(context); + } - static Intent buildHomeIntent(String category) { + private static Intent buildHomeIntent(String category) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(category); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK @@ -142,28 +144,26 @@ final class UiModeManagerService extends IUiModeManager.Stub { } }; - private final TwilightService.TwilightListener mTwilightListener = - new TwilightService.TwilightListener() { + private final TwilightListener mTwilightListener = new TwilightListener() { @Override public void onTwilightStateChanged() { updateTwilight(); } }; - public UiModeManagerService(Context context, TwilightService twilight) { - mContext = context; - mTwilightService = twilight; - - ServiceManager.addService(Context.UI_MODE_SERVICE, this); - - mContext.registerReceiver(mDockModeReceiver, + @Override + public void onStart() { + final Context context = getContext(); + mTwilightManager = getLocalService(TwilightManager.class); + final PowerManager powerManager = + (PowerManager) context.getSystemService(Context.POWER_SERVICE); + mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG); + + context.registerReceiver(mDockModeReceiver, new IntentFilter(Intent.ACTION_DOCK_EVENT)); - mContext.registerReceiver(mBatteryReceiver, + context.registerReceiver(mBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); - mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); - mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG); - mConfiguration.setToDefaults(); mDefaultUiModeType = context.getResources().getInteger( @@ -175,101 +175,139 @@ final class UiModeManagerService extends IUiModeManager.Stub { mTelevision = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_TELEVISION); - mNightMode = Settings.Secure.getInt(mContext.getContentResolver(), + mNightMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO); - mTwilightService.registerListener(mTwilightListener, mHandler); + mTwilightManager.registerListener(mTwilightListener, mHandler); + + publishBinderService(Context.UI_MODE_SERVICE, mService); } - @Override // Binder call - public void disableCarMode(int flags) { - final long ident = Binder.clearCallingIdentity(); - try { - synchronized (mLock) { - setCarModeLocked(false); - if (mSystemReady) { - updateLocked(0, flags); + private final IBinder mService = new IUiModeManager.Stub() { + @Override + public void enableCarMode(int flags) { + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + setCarModeLocked(true); + if (mSystemReady) { + updateLocked(flags, 0); + } } + } finally { + Binder.restoreCallingIdentity(ident); } - } finally { - Binder.restoreCallingIdentity(ident); } - } - @Override // Binder call - public void enableCarMode(int flags) { - final long ident = Binder.clearCallingIdentity(); - try { - synchronized (mLock) { - setCarModeLocked(true); - if (mSystemReady) { - updateLocked(flags, 0); + @Override + public void disableCarMode(int flags) { + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + setCarModeLocked(false); + if (mSystemReady) { + updateLocked(0, flags); + } } + } finally { + Binder.restoreCallingIdentity(ident); } - } finally { - Binder.restoreCallingIdentity(ident); } - } - @Override // Binder call - public int getCurrentModeType() { - final long ident = Binder.clearCallingIdentity(); - try { - synchronized (mLock) { - return mCurUiMode & Configuration.UI_MODE_TYPE_MASK; + @Override + public int getCurrentModeType() { + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + return mCurUiMode & Configuration.UI_MODE_TYPE_MASK; + } + } finally { + Binder.restoreCallingIdentity(ident); } - } finally { - Binder.restoreCallingIdentity(ident); } - } - @Override // Binder call - public void setNightMode(int mode) { - switch (mode) { - case UiModeManager.MODE_NIGHT_NO: - case UiModeManager.MODE_NIGHT_YES: - case UiModeManager.MODE_NIGHT_AUTO: - break; - default: - throw new IllegalArgumentException("Unknown mode: " + mode); + @Override + public void setNightMode(int mode) { + switch (mode) { + case UiModeManager.MODE_NIGHT_NO: + case UiModeManager.MODE_NIGHT_YES: + case UiModeManager.MODE_NIGHT_AUTO: + break; + default: + throw new IllegalArgumentException("Unknown mode: " + mode); + } + + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + if (isDoingNightModeLocked() && mNightMode != mode) { + Settings.Secure.putInt(getContext().getContentResolver(), + Settings.Secure.UI_NIGHT_MODE, mode); + mNightMode = mode; + updateLocked(0, 0); + } + } + } finally { + Binder.restoreCallingIdentity(ident); + } } - final long ident = Binder.clearCallingIdentity(); - try { + @Override + public int getNightMode() { synchronized (mLock) { - if (isDoingNightModeLocked() && mNightMode != mode) { - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.UI_NIGHT_MODE, mode); - mNightMode = mode; - updateLocked(0, 0); - } + return mNightMode; } - } finally { - Binder.restoreCallingIdentity(ident); } - } - @Override // Binder call - public int getNightMode() { + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + + pw.println("Permission Denial: can't dump uimode service from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + dumpImpl(pw); + } + }; + + void dumpImpl(PrintWriter pw) { synchronized (mLock) { - return mNightMode; + pw.println("Current UI Mode Service state:"); + pw.print(" mDockState="); pw.print(mDockState); + pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState); + pw.print(" mNightMode="); pw.print(mNightMode); + pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled); + pw.print(" mComputedNightMode="); pw.println(mComputedNightMode); + pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode)); + pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode)); + pw.print(" mHoldingConfiguration="); pw.print(mHoldingConfiguration); + pw.print(" mSystemReady="); pw.println(mSystemReady); + pw.print(" mTwilightService.getCurrentState()="); + pw.println(mTwilightManager.getCurrentState()); } } - void systemReady() { - synchronized (mLock) { - mSystemReady = true; - mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR; - updateComputedNightModeLocked(); - updateLocked(0, 0); + @Override + public void onBootPhase(int phase) { + if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { + synchronized (mLock) { + mSystemReady = true; + mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR; + updateComputedNightModeLocked(); + updateLocked(0, 0); + } } } - private boolean isDoingNightModeLocked() { + boolean isDoingNightModeLocked() { return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED; } - private void setCarModeLocked(boolean enabled) { + void setCarModeLocked(boolean enabled) { if (mCarModeEnabled != enabled) { mCarModeEnabled = enabled; } @@ -344,7 +382,7 @@ final class UiModeManagerService extends IUiModeManager.Stub { } } - private void updateLocked(int enableFlags, int disableFlags) { + void updateLocked(int enableFlags, int disableFlags) { String action = null; String oldAction = null; if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_CAR) { @@ -359,7 +397,7 @@ final class UiModeManagerService extends IUiModeManager.Stub { adjustStatusBarCarModeLocked(); if (oldAction != null) { - mContext.sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL); + getContext().sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL); } mLastBroadcastState = Intent.EXTRA_DOCK_STATE_CAR; action = UiModeManager.ACTION_ENTER_CAR_MODE; @@ -367,7 +405,7 @@ final class UiModeManagerService extends IUiModeManager.Stub { } else if (isDeskDockState(mDockState)) { if (!isDeskDockState(mLastBroadcastState)) { if (oldAction != null) { - mContext.sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL); + getContext().sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL); } mLastBroadcastState = mDockState; action = UiModeManager.ACTION_ENTER_DESK_MODE; @@ -393,7 +431,7 @@ final class UiModeManagerService extends IUiModeManager.Stub { Intent intent = new Intent(action); intent.putExtra("enableFlags", enableFlags); intent.putExtra("disableFlags", disableFlags); - mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null, + getContext().sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null, mResultReceiver, null, Activity.RESULT_OK, null, null); // Attempting to make this transition a little more clean, we are going @@ -491,7 +529,7 @@ final class UiModeManagerService extends IUiModeManager.Stub { // activity manager take care of both the start and config // change. Intent homeIntent = buildHomeIntent(category); - if (Sandman.shouldStartDockApp(mContext, homeIntent)) { + if (Sandman.shouldStartDockApp(getContext(), homeIntent)) { try { int result = ActivityManagerNative.getDefault().startActivityWithConfig( null, null, homeIntent, null, null, null, 0, 0, @@ -513,14 +551,15 @@ final class UiModeManagerService extends IUiModeManager.Stub { // If we did not start a dock app, then start dreaming if supported. if (category != null && !dockAppStarted) { - Sandman.startDreamWhenDockedIfAppropriate(mContext); + Sandman.startDreamWhenDockedIfAppropriate(getContext()); } } private void adjustStatusBarCarModeLocked() { + final Context context = getContext(); if (mStatusBarManager == null) { mStatusBarManager = (StatusBarManager) - mContext.getSystemService(Context.STATUS_BAR_SERVICE); + context.getSystemService(Context.STATUS_BAR_SERVICE); } // Fear not: StatusBarManagerService manages a list of requests to disable @@ -536,12 +575,12 @@ final class UiModeManagerService extends IUiModeManager.Stub { if (mNotificationManager == null) { mNotificationManager = (NotificationManager) - mContext.getSystemService(Context.NOTIFICATION_SERVICE); + context.getSystemService(Context.NOTIFICATION_SERVICE); } if (mNotificationManager != null) { if (mCarModeEnabled) { - Intent carModeOffIntent = new Intent(mContext, DisableCarModeActivity.class); + Intent carModeOffIntent = new Intent(context, DisableCarModeActivity.class); Notification n = new Notification(); n.icon = R.drawable.stat_notify_car_mode; @@ -549,10 +588,10 @@ final class UiModeManagerService extends IUiModeManager.Stub { n.flags = Notification.FLAG_ONGOING_EVENT; n.when = 0; n.setLatestEventInfo( - mContext, - mContext.getString(R.string.car_mode_disable_notification_title), - mContext.getString(R.string.car_mode_disable_notification_message), - PendingIntent.getActivityAsUser(mContext, 0, carModeOffIntent, 0, + context, + context.getString(R.string.car_mode_disable_notification_title), + context.getString(R.string.car_mode_disable_notification_message), + PendingIntent.getActivityAsUser(context, 0, carModeOffIntent, 0, null, UserHandle.CURRENT)); mNotificationManager.notifyAsUser(null, R.string.car_mode_disable_notification_title, n, UserHandle.ALL); @@ -563,7 +602,7 @@ final class UiModeManagerService extends IUiModeManager.Stub { } } - private void updateTwilight() { + void updateTwilight() { synchronized (mLock) { if (isDoingNightModeLocked() && mNightMode == UiModeManager.MODE_NIGHT_AUTO) { updateComputedNightModeLocked(); @@ -573,36 +612,11 @@ final class UiModeManagerService extends IUiModeManager.Stub { } private void updateComputedNightModeLocked() { - TwilightState state = mTwilightService.getCurrentState(); + TwilightState state = mTwilightManager.getCurrentState(); if (state != null) { mComputedNightMode = state.isNight(); } } - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump uimode service from from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return; - } - - synchronized (mLock) { - pw.println("Current UI Mode Service state:"); - pw.print(" mDockState="); pw.print(mDockState); - pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState); - pw.print(" mNightMode="); pw.print(mNightMode); - pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled); - pw.print(" mComputedNightMode="); pw.println(mComputedNightMode); - pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode)); - pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode)); - pw.print(" mHoldingConfiguration="); pw.print(mHoldingConfiguration); - pw.print(" mSystemReady="); pw.println(mSystemReady); - pw.print(" mTwilightService.getCurrentState()="); - pw.println(mTwilightService.getCurrentState()); - } - } } diff --git a/services/java/com/android/server/UiThread.java b/services/core/java/com/android/server/UiThread.java index 60d73aa6cacb..0beb77fb4b92 100644 --- a/services/java/com/android/server/UiThread.java +++ b/services/core/java/com/android/server/UiThread.java @@ -17,21 +17,18 @@ package com.android.server; import android.os.Handler; -import android.os.HandlerThread; -import android.os.StrictMode; -import android.util.Slog; /** * Shared singleton thread for showing UI. This is a foreground thread, and in * additional should not have operations that can take more than a few ms scheduled * on it to avoid UI jank. */ -public final class UiThread extends HandlerThread { +public final class UiThread extends ServiceThread { private static UiThread sInstance; private static Handler sHandler; private UiThread() { - super("android.ui", android.os.Process.THREAD_PRIORITY_FOREGROUND); + super("android.ui", android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/); } private static void ensureThreadLocked() { @@ -39,19 +36,6 @@ public final class UiThread extends HandlerThread { sInstance = new UiThread(); sInstance.start(); sHandler = new Handler(sInstance.getLooper()); - sHandler.post(new Runnable() { - @Override - public void run() { - //Looper.myLooper().setMessageLogging(new LogPrinter( - // Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM)); - android.os.Process.setCanSelfBackground(false); - - // For debug builds, log event loop stalls to dropbox for analysis. - if (StrictMode.conditionallyEnableDebugLogging()) { - Slog.i("UiThread", "Enabled StrictMode logging for UI thread"); - } - } - }); } } diff --git a/services/java/com/android/server/UpdateLockService.java b/services/core/java/com/android/server/UpdateLockService.java index 0f778cd17f8a..0f778cd17f8a 100644 --- a/services/java/com/android/server/UpdateLockService.java +++ b/services/core/java/com/android/server/UpdateLockService.java diff --git a/services/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index 28eb948d4169..28eb948d4169 100644 --- a/services/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java diff --git a/services/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index e17f42d9f415..1ce073a7a836 100644 --- a/services/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -20,18 +20,15 @@ import android.app.IActivityController; import android.os.Binder; import android.os.RemoteException; import com.android.server.am.ActivityManagerService; -import com.android.server.power.PowerManagerService; -import android.app.AlarmManager; -import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.os.BatteryManager; import android.os.Debug; import android.os.Handler; +import android.os.IPowerManager; import android.os.Looper; import android.os.Process; import android.os.ServiceManager; @@ -45,7 +42,6 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; -import java.util.Calendar; /** This class calls its monitor every minute. Killing this process if they don't return **/ public class Watchdog extends Thread { @@ -80,9 +76,6 @@ public class Watchdog extends Thread { final ArrayList<HandlerChecker> mHandlerCheckers = new ArrayList<HandlerChecker>(); final HandlerChecker mMonitorChecker; ContentResolver mResolver; - BatteryService mBattery; - PowerManagerService mPower; - AlarmManagerService mAlarm; ActivityManagerService mActivity; int mPhonePid; @@ -232,15 +225,13 @@ public class Watchdog extends Thread { // And also check IO thread. mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(), "i/o thread", DEFAULT_TIMEOUT)); + // And the display thread. + mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(), + "display thread", DEFAULT_TIMEOUT)); } - public void init(Context context, BatteryService battery, - PowerManagerService power, AlarmManagerService alarm, - ActivityManagerService activity) { + public void init(Context context, ActivityManagerService activity) { mResolver = context.getContentResolver(); - mBattery = battery; - mPower = power; - mAlarm = alarm; mActivity = activity; context.registerReceiver(new RebootRequestReceiver(), @@ -277,15 +268,16 @@ public class Watchdog extends Thread { } } - public void addThread(Handler thread, String name) { - addThread(thread, name, DEFAULT_TIMEOUT); + public void addThread(Handler thread) { + addThread(thread, DEFAULT_TIMEOUT); } - public void addThread(Handler thread, String name, long timeoutMillis) { + public void addThread(Handler thread, long timeoutMillis) { synchronized (this) { if (isAlive()) { throw new RuntimeException("Threads can't be added once the Watchdog is running"); } + final String name = thread.getLooper().getThread().getName(); mHandlerCheckers.add(new HandlerChecker(thread, name, timeoutMillis)); } } @@ -295,8 +287,11 @@ public class Watchdog extends Thread { */ void rebootSystem(String reason) { Slog.i(TAG, "Rebooting system because: " + reason); - PowerManagerService pms = (PowerManagerService) ServiceManager.getService("power"); - pms.reboot(false, reason, false); + IPowerManager pms = (IPowerManager)ServiceManager.getService(Context.POWER_SERVICE); + try { + pms.reboot(false, reason, false); + } catch (RemoteException ex) { + } } private int evaluateCheckerCompletionLocked() { diff --git a/services/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java index 415fcc126aae..415fcc126aae 100644 --- a/services/java/com/android/server/WiredAccessoryManager.java +++ b/services/core/java/com/android/server/WiredAccessoryManager.java diff --git a/services/java/com/android/server/accounts/AccountAuthenticatorCache.java b/services/core/java/com/android/server/accounts/AccountAuthenticatorCache.java index 75523680d335..75523680d335 100644 --- a/services/java/com/android/server/accounts/AccountAuthenticatorCache.java +++ b/services/core/java/com/android/server/accounts/AccountAuthenticatorCache.java diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index aa9849ef5641..aa9849ef5641 100644 --- a/services/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java diff --git a/services/java/com/android/server/accounts/IAccountAuthenticatorCache.java b/services/core/java/com/android/server/accounts/IAccountAuthenticatorCache.java index bb09687720cc..bb09687720cc 100644 --- a/services/java/com/android/server/accounts/IAccountAuthenticatorCache.java +++ b/services/core/java/com/android/server/accounts/IAccountAuthenticatorCache.java diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 17bb3e0f525b..17bb3e0f525b 100644 --- a/services/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index fc66e45c0cee..46891f5920a4 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -28,11 +28,15 @@ import static org.xmlpull.v1.XmlPullParser.START_TAG; import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; import android.app.AppOpsManager; +import android.app.IActivityContainer; +import android.app.IActivityContainerCallback; import android.appwidget.AppWidgetManager; +import android.graphics.Rect; import android.util.ArrayMap; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IAppOpsService; +import com.android.internal.app.ProcessMap; import com.android.internal.app.ProcessStats; import com.android.internal.os.BackgroundThread; import com.android.internal.os.BatteryStatsImpl; @@ -45,14 +49,13 @@ import com.android.internal.util.Preconditions; import com.android.server.AppOpsService; import com.android.server.AttributeCache; import com.android.server.IntentResolver; -import com.android.internal.app.ProcessMap; -import com.android.server.SystemServer; +import com.android.server.ServiceThread; +import com.android.server.SystemService; import com.android.server.Watchdog; import com.android.server.am.ActivityStack.ActivityState; import com.android.server.firewall.IntentFirewall; import com.android.server.pm.UserManagerService; import com.android.server.wm.AppTransition; -import com.android.server.wm.StackBox; import com.android.server.wm.WindowManagerService; import com.google.android.collect.Lists; import com.google.android.collect.Maps; @@ -68,7 +71,6 @@ import org.xmlpull.v1.XmlSerializer; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; -import android.app.ActivityManager.StackBoxInfo; import android.app.ActivityManager.StackInfo; import android.app.ActivityManagerNative; import android.app.ActivityOptions; @@ -134,6 +136,7 @@ import android.os.Bundle; import android.os.Debug; import android.os.DropBoxManager; import android.os.Environment; +import android.os.FactoryTest; import android.os.FileObserver; import android.os.FileUtils; import android.os.Handler; @@ -331,8 +334,6 @@ public final class ActivityManagerService extends ActivityManagerNative public IntentFirewall mIntentFirewall; - private final boolean mHeadless; - // Whether we should show our dialogs (ANR, crash, etc) or just perform their // default actuion automatically. Important for devices without direct input // devices. @@ -747,7 +748,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>(); + private static final ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>(); /** * All information we have collected about the runtime performance of @@ -996,8 +997,7 @@ public final class ActivityManagerService extends ActivityManagerNative WindowManagerService mWindowManager; - static ActivityManagerService mSelf; - static ActivityThread mSystemThread; + final ActivityThread mSystemThread; int mCurrentUserId = 0; private UserManagerService mUserManager; @@ -1074,10 +1074,13 @@ public final class ActivityManagerService extends ActivityManagerNative */ private boolean mUserIsMonkey; - final Handler mHandler = new Handler() { - //public Handler() { - // if (localLOGV) Slog.v(TAG, "Handler started!"); - //} + final ServiceThread mHandlerThread; + final MainHandler mHandler; + + final class MainHandler extends Handler { + public MainHandler(Looper looper) { + super(looper, null, true); + } @Override public void handleMessage(Message msg) { @@ -1730,38 +1733,34 @@ public final class ActivityManagerService extends ActivityManagerNative } }; - public static void setSystemProcess() { + public void setSystemProcess() { try { - ActivityManagerService m = mSelf; - - ServiceManager.addService(Context.ACTIVITY_SERVICE, m, true); - ServiceManager.addService(ProcessStats.SERVICE_NAME, m.mProcessStats); - ServiceManager.addService("meminfo", new MemBinder(m)); - ServiceManager.addService("gfxinfo", new GraphicsBinder(m)); - ServiceManager.addService("dbinfo", new DbBinder(m)); + ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true); + ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats); + ServiceManager.addService("meminfo", new MemBinder(this)); + ServiceManager.addService("gfxinfo", new GraphicsBinder(this)); + ServiceManager.addService("dbinfo", new DbBinder(this)); if (MONITOR_CPU_USAGE) { - ServiceManager.addService("cpuinfo", new CpuBinder(m)); + ServiceManager.addService("cpuinfo", new CpuBinder(this)); } - ServiceManager.addService("permission", new PermissionController(m)); + ServiceManager.addService("permission", new PermissionController(this)); - ApplicationInfo info = - mSelf.mContext.getPackageManager().getApplicationInfo( - "android", STOCK_PM_FLAGS); + ApplicationInfo info = mContext.getPackageManager().getApplicationInfo( + "android", STOCK_PM_FLAGS); mSystemThread.installSystemApplicationInfo(info); - synchronized (mSelf) { - ProcessRecord app = mSelf.newProcessRecordLocked(info, - info.processName, false); + synchronized (this) { + ProcessRecord app = newProcessRecordLocked(info, info.processName, false); app.persistent = true; app.pid = MY_PID; app.maxAdj = ProcessList.SYSTEM_ADJ; - app.makeActive(mSystemThread.getApplicationThread(), mSelf.mProcessStats); - mSelf.mProcessNames.put(app.processName, app.uid, app); - synchronized (mSelf.mPidsSelfLocked) { - mSelf.mPidsSelfLocked.put(app.pid, app); + app.makeActive(mSystemThread.getApplicationThread(), mProcessStats); + mProcessNames.put(app.processName, app.uid, app); + synchronized (mPidsSelfLocked) { + mPidsSelfLocked.put(app.pid, app); } - mSelf.updateLruProcessLocked(app, false, null); - mSelf.updateOomAdjLocked(); + updateLruProcessLocked(app, false, null); + updateOomAdjLocked(); } } catch (PackageManager.NameNotFoundException e) { throw new RuntimeException( @@ -1772,105 +1771,17 @@ public final class ActivityManagerService extends ActivityManagerNative public void setWindowManager(WindowManagerService wm) { mWindowManager = wm; mStackSupervisor.setWindowManager(wm); - wm.createStack(HOME_STACK_ID, -1, StackBox.TASK_STACK_GOES_OVER, 1.0f); } public void startObservingNativeCrashes() { - final NativeCrashListener ncl = new NativeCrashListener(); + final NativeCrashListener ncl = new NativeCrashListener(this); ncl.start(); } - public static final Context main(int factoryTest) { - AThread thr = new AThread(); - thr.start(); - - synchronized (thr) { - while (thr.mService == null) { - try { - thr.wait(); - } catch (InterruptedException e) { - } - } - } - - ActivityManagerService m = thr.mService; - mSelf = m; - ActivityThread at = ActivityThread.systemMain(); - mSystemThread = at; - Context context = at.getSystemContext(); - context.setTheme(android.R.style.Theme_Holo); - m.mContext = context; - m.mFactoryTest = factoryTest; - m.mIntentFirewall = new IntentFirewall(m.new IntentFirewallInterface()); - - m.mStackSupervisor = new ActivityStackSupervisor(m, context, thr.mLooper); - - m.mBatteryStatsService.publish(context); - m.mUsageStatsService.publish(context); - m.mAppOpsService.publish(context); - - synchronized (thr) { - thr.mReady = true; - thr.notifyAll(); - } - - m.startRunning(null, null, null, null); - - return context; - } - - public static ActivityManagerService self() { - return mSelf; - } - public IAppOpsService getAppOpsService() { return mAppOpsService; } - static class AThread extends Thread { - ActivityManagerService mService; - Looper mLooper; - boolean mReady = false; - - public AThread() { - super("ActivityManager"); - } - - @Override - public void run() { - Looper.prepare(); - - android.os.Process.setThreadPriority( - android.os.Process.THREAD_PRIORITY_FOREGROUND); - android.os.Process.setCanSelfBackground(false); - - ActivityManagerService m = new ActivityManagerService(); - - synchronized (this) { - mService = m; - mLooper = Looper.myLooper(); - Watchdog.getInstance().addThread(new Handler(mLooper), getName()); - notifyAll(); - } - - synchronized (this) { - while (!mReady) { - try { - wait(); - } catch (InterruptedException e) { - } - } - } - - // For debug builds, log event loop stalls to dropbox for analysis. - if (StrictMode.conditionallyEnableDebugLogging()) { - Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper"); - } - - Looper.loop(); - } - } - static class MemBinder extends Binder { ActivityManagerService mActivityManagerService; MemBinder(ActivityManagerService activityManagerService) { @@ -1955,22 +1866,54 @@ public final class ActivityManagerService extends ActivityManagerNative } } - private ActivityManagerService() { + public static final class Lifecycle extends SystemService { + private final ActivityManagerService mService; + + public Lifecycle(Context context) { + super(context); + mService = new ActivityManagerService(context); + } + + @Override + public void onStart() { + mService.start(); + } + + public ActivityManagerService getService() { + return mService; + } + } + + // Note: This method is invoked on the main thread but may need to attach various + // handlers to other threads. So take care to be explicit about the looper. + public ActivityManagerService(Context systemContext) { + mContext = systemContext; + mFactoryTest = FactoryTest.getMode(); + mSystemThread = ActivityThread.currentActivityThread(); + Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass()); - mFgBroadcastQueue = new BroadcastQueue(this, "foreground", BROADCAST_FG_TIMEOUT, false); - mBgBroadcastQueue = new BroadcastQueue(this, "background", BROADCAST_BG_TIMEOUT, true); + mHandlerThread = new ServiceThread(TAG, + android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/); + mHandlerThread.start(); + mHandler = new MainHandler(mHandlerThread.getLooper()); + + mFgBroadcastQueue = new BroadcastQueue(this, mHandler, + "foreground", BROADCAST_FG_TIMEOUT, false); + mBgBroadcastQueue = new BroadcastQueue(this, mHandler, + "background", BROADCAST_BG_TIMEOUT, true); mBroadcastQueues[0] = mFgBroadcastQueue; mBroadcastQueues[1] = mBgBroadcastQueue; mServices = new ActiveServices(this); mProviderMap = new ProviderMap(this); + // TODO: Move creation of battery stats service outside of activity manager service. File dataDir = Environment.getDataDirectory(); File systemDir = new File(dataDir, "system"); systemDir.mkdirs(); mBatteryStatsService = new BatteryStatsService(new File( - systemDir, "batterystats.bin").toString()); + systemDir, "batterystats.bin").toString(), mHandler); mBatteryStatsService.getActiveStatistics().readLocked(); mBatteryStatsService.getActiveStatistics().writeAsyncLocked(); mOnBattery = DEBUG_POWER ? true @@ -1980,12 +1923,10 @@ public final class ActivityManagerService extends ActivityManagerNative mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats")); mUsageStatsService = new UsageStatsService(new File(systemDir, "usagestats").toString()); - mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml")); + mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler); mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml")); - mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0")); - // User 0 is the first and only user that runs at boot. mStartedUsers.put(0, new UserStartedState(new UserHandle(0), true)); mUserLru.add(Integer.valueOf(0)); @@ -2000,10 +1941,9 @@ public final class ActivityManagerService extends ActivityManagerNative mConfigurationSeq = mConfiguration.seq = 1; mProcessCpuTracker.init(); - mCompatModePackages = new CompatModePackages(this, systemDir); - - // Add ourself to the Watchdog monitors. - Watchdog.getInstance().addMonitor(this); + mCompatModePackages = new CompatModePackages(this, systemDir, mHandler); + mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler); + mStackSupervisor = new ActivityStackSupervisor(this); mProcessCpuThread = new Thread("CpuTracker") { @Override @@ -2034,7 +1974,18 @@ public final class ActivityManagerService extends ActivityManagerNative } } }; + + Watchdog.getInstance().addMonitor(this); + Watchdog.getInstance().addThread(mHandler); + } + + private void start() { mProcessCpuThread.start(); + + mBatteryStatsService.publish(mContext); + mUsageStatsService.publish(mContext); + mAppOpsService.publish(mContext); + startRunning(null, null, null, null); } @Override @@ -2730,13 +2681,13 @@ public final class ActivityManagerService extends ActivityManagerNative } gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid)); } - if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) { - if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL + if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) { + if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL && mTopComponent != null && app.processName.equals(mTopComponent.getPackageName())) { uid = 0; } - if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL + if (mFactoryTest == FactoryTest.FACTORY_TEST_HIGH_LEVEL && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) { uid = 0; } @@ -2846,21 +2797,14 @@ public final class ActivityManagerService extends ActivityManagerNative Intent getHomeIntent() { Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null); intent.setComponent(mTopComponent); - if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { + if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) { intent.addCategory(Intent.CATEGORY_HOME); } return intent; } boolean startHomeActivityLocked(int userId) { - if (mHeadless) { - // Added because none of the other calls to ensureBootCompleted seem to fire - // when running headless. - ensureBootCompleted(); - return false; - } - - if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL + if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL && mTopAction == null) { // We are running in factory test mode, but unable to find // the factory test app, so just sit around displaying the @@ -2924,14 +2868,14 @@ public final class ActivityManagerService extends ActivityManagerNative // version than the last one shown, and we are not running in // low-level factory test mode. final ContentResolver resolver = mContext.getContentResolver(); - if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL && + if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL && Settings.Global.getInt(resolver, Settings.Global.DEVICE_PROVISIONED, 0) != 0) { mCheckedForSetup = true; // See if we should be showing the platform update setup UI. Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP); - List<ResolveInfo> ris = mSelf.mContext.getPackageManager() + List<ResolveInfo> ris = mContext.getPackageManager() .queryIntentActivities(intent, PackageManager.GET_META_DATA); // We don't allow third party apps to replace this. @@ -2959,7 +2903,7 @@ public final class ActivityManagerService extends ActivityManagerNative intent.setComponent(new ComponentName( ri.activityInfo.packageName, ri.activityInfo.name)); mStackSupervisor.startActivityLocked(null, intent, null, ri.activityInfo, - null, null, 0, 0, 0, null, 0, null, false, null); + null, null, 0, 0, 0, null, 0, null, false, null, null); } } } @@ -3117,7 +3061,7 @@ public final class ActivityManagerService extends ActivityManagerNative // TODO: Switch to user app stacks here. return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profileFile, profileFd, - null, null, options, userId); + null, null, options, userId, null); } @Override @@ -3132,7 +3076,7 @@ public final class ActivityManagerService extends ActivityManagerNative // TODO: Switch to user app stacks here. mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profileFile, profileFd, - res, null, options, UserHandle.getCallingUserId()); + res, null, options, UserHandle.getCallingUserId(), null); return res; } @@ -3147,7 +3091,7 @@ public final class ActivityManagerService extends ActivityManagerNative // TODO: Switch to user app stacks here. int ret = mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, - null, null, null, config, options, userId); + null, null, null, config, options, userId, null); return ret; } @@ -3179,7 +3123,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } int ret = pir.sendInner(0, fillInIntent, resolvedType, null, null, - resultTo, resultWho, requestCode, flagsMask, flagsValues, options); + resultTo, resultWho, requestCode, flagsMask, flagsValues, options, null); return ret; } @@ -3278,7 +3222,7 @@ public final class ActivityManagerService extends ActivityManagerNative int res = mStackSupervisor.startActivityLocked(r.app.thread, intent, r.resolvedType, aInfo, resultTo != null ? resultTo.appToken : null, resultWho, requestCode, -1, r.launchedFromUid, r.launchedFromPackage, 0, - options, false, null); + options, false, null, null); Binder.restoreCallingIdentity(origId); r.finishing = wasFinishing; @@ -3291,7 +3235,8 @@ public final class ActivityManagerService extends ActivityManagerNative final int startActivityInPackage(int uid, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, - String resultWho, int requestCode, int startFlags, Bundle options, int userId) { + String resultWho, int requestCode, int startFlags, Bundle options, int userId, + IActivityContainer container) { userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, true, "startActivityInPackage", null); @@ -3299,7 +3244,7 @@ public final class ActivityManagerService extends ActivityManagerNative // TODO: Switch to user app stacks here. int ret = mStackSupervisor.startActivityMayWait(null, uid, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, - null, null, null, null, options, userId); + null, null, null, null, options, userId, container); return ret; } @@ -3603,9 +3548,13 @@ public final class ActivityManagerService extends ActivityManagerNative */ private final void handleAppDiedLocked(ProcessRecord app, boolean restarting, boolean allowRestart) { + int pid = app.pid; cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1); if (!restarting) { removeLruProcessLocked(app); + if (pid > 0) { + ProcessList.remove(pid); + } } if (mProfileProc == app) { @@ -5000,7 +4949,7 @@ public final class ActivityManagerService extends ActivityManagerNative // See if the top visible activity is waiting to run in this process... if (normalMode) { try { - if (mStackSupervisor.attachApplicationLocked(app, mHeadless)) { + if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } catch (Exception e) { @@ -5157,7 +5106,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { + if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) { // Start looking for apps that are abusing wake locks. Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG); mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY); @@ -7107,23 +7056,40 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public int createStack(int taskId, int relativeStackBoxId, int position, float weight) { + public IBinder getHomeActivityToken() throws RemoteException { enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, - "createStack()"); - if (DEBUG_STACK) Slog.d(TAG, "createStack: taskId=" + taskId + " relStackBoxId=" + - relativeStackBoxId + " position=" + position + " weight=" + weight); + "getHomeActivityToken()"); synchronized (this) { - long ident = Binder.clearCallingIdentity(); - try { - int stackId = mStackSupervisor.createStack(); - mWindowManager.createStack(stackId, relativeStackBoxId, position, weight); - if (taskId > 0) { - moveTaskToStack(taskId, stackId, true); - } - return stackId; - } finally { - Binder.restoreCallingIdentity(ident); + return mStackSupervisor.getHomeActivityToken(); + } + } + + @Override + public IActivityContainer createActivityContainer(IBinder parentActivityToken, + IActivityContainerCallback callback) throws RemoteException { + enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, + "createActivityContainer()"); + synchronized (this) { + if (parentActivityToken == null) { + throw new IllegalArgumentException("parent token must not be null"); } + ActivityRecord r = ActivityRecord.forToken(parentActivityToken); + if (r == null) { + return null; + } + return mStackSupervisor.createActivityContainer(r, callback); + } + } + + @Override + public IActivityContainer getEnclosingActivityContainer(IBinder activityToken) + throws RemoteException { + synchronized (this) { + ActivityStack stack = ActivityRecord.getStackLocked(activityToken); + if (stack != null) { + return stack.mActivityContainer; + } + return null; } } @@ -7148,99 +7114,40 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public void resizeStackBox(int stackBoxId, float weight) { + public void resizeStack(int stackBoxId, Rect bounds) { enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, "resizeStackBox()"); long ident = Binder.clearCallingIdentity(); try { - mWindowManager.resizeStackBox(stackBoxId, weight); + mWindowManager.resizeStack(stackBoxId, bounds); } finally { Binder.restoreCallingIdentity(ident); } } - private ArrayList<StackInfo> getStacks() { - synchronized (this) { - ArrayList<ActivityManager.StackInfo> list = new ArrayList<ActivityManager.StackInfo>(); - ArrayList<ActivityStack> stacks = mStackSupervisor.getStacks(); - for (ActivityStack stack : stacks) { - ActivityManager.StackInfo stackInfo = new ActivityManager.StackInfo(); - int stackId = stack.mStackId; - stackInfo.stackId = stackId; - stackInfo.bounds = mWindowManager.getStackBounds(stackId); - ArrayList<TaskRecord> tasks = stack.getAllTasks(); - final int numTasks = tasks.size(); - int[] taskIds = new int[numTasks]; - String[] taskNames = new String[numTasks]; - for (int i = 0; i < numTasks; ++i) { - final TaskRecord task = tasks.get(i); - taskIds[i] = task.taskId; - taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString() - : task.realActivity != null ? task.realActivity.flattenToString() - : task.getTopActivity() != null ? task.getTopActivity().packageName - : "unknown"; - } - stackInfo.taskIds = taskIds; - stackInfo.taskNames = taskNames; - list.add(stackInfo); - } - return list; - } - } - - private void addStackInfoToStackBoxInfo(StackBoxInfo stackBoxInfo, List<StackInfo> stackInfos) { - final int stackId = stackBoxInfo.stackId; - if (stackId >= 0) { - for (StackInfo stackInfo : stackInfos) { - if (stackId == stackInfo.stackId) { - stackBoxInfo.stack = stackInfo; - stackInfos.remove(stackInfo); - return; - } - } - } else { - addStackInfoToStackBoxInfo(stackBoxInfo.children[0], stackInfos); - addStackInfoToStackBoxInfo(stackBoxInfo.children[1], stackInfos); - } - } - @Override - public List<StackBoxInfo> getStackBoxes() { + public List<StackInfo> getAllStackInfos() { enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, - "getStackBoxes()"); + "getAllStackInfos()"); long ident = Binder.clearCallingIdentity(); try { - List<StackBoxInfo> stackBoxInfos = mWindowManager.getStackBoxInfos(); synchronized (this) { - List<StackInfo> stackInfos = getStacks(); - for (StackBoxInfo stackBoxInfo : stackBoxInfos) { - addStackInfoToStackBoxInfo(stackBoxInfo, stackInfos); - } + return mStackSupervisor.getAllStackInfosLocked(); } - return stackBoxInfos; } finally { Binder.restoreCallingIdentity(ident); } } @Override - public StackBoxInfo getStackBoxInfo(int stackBoxId) { + public StackInfo getStackInfo(int stackId) { enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, - "getStackBoxInfo()"); + "getStackInfo()"); long ident = Binder.clearCallingIdentity(); try { - List<StackBoxInfo> stackBoxInfos = mWindowManager.getStackBoxInfos(); - StackBoxInfo info = null; synchronized (this) { - List<StackInfo> stackInfos = getStacks(); - for (StackBoxInfo stackBoxInfo : stackBoxInfos) { - addStackInfoToStackBoxInfo(stackBoxInfo, stackInfos); - if (stackBoxInfo.stackBoxId == stackBoxId) { - info = stackBoxInfo; - } - } + return mStackSupervisor.getStackInfoLocked(stackId); } - return info; } finally { Binder.restoreCallingIdentity(ident); } @@ -8061,11 +7968,11 @@ public final class ActivityManagerService extends ActivityManagerNative } } - public static final void installSystemProviders() { + public final void installSystemProviders() { List<ProviderInfo> providers; - synchronized (mSelf) { - ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID); - providers = mSelf.generateApplicationProvidersLocked(app); + synchronized (this) { + ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID); + providers = generateApplicationProvidersLocked(app); if (providers != null) { for (int i=providers.size()-1; i>=0; i--) { ProviderInfo pi = (ProviderInfo)providers.get(i); @@ -8081,9 +7988,9 @@ public final class ActivityManagerService extends ActivityManagerNative mSystemThread.installSystemProviders(providers); } - mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf); + mCoreSettingsObserver = new CoreSettingsObserver(this); - mSelf.mUsageStatsService.monitorPackages(); + mUsageStatsService.monitorPackages(); } /** @@ -9321,7 +9228,7 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized(this) { // Make sure we have no pre-ready processes sitting around. - if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) { + if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) { ResolveInfo ri = mContext.getPackageManager() .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST), STOCK_PM_FLAGS); @@ -9363,7 +9270,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (goingCallback != null) goingCallback.run(); synchronized (this) { - if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { + if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) { try { List apps = AppGlobals.getPackageManager(). getPersistentApplications(STOCK_PM_FLAGS); @@ -9496,10 +9403,6 @@ public final class ActivityManagerService extends ActivityManagerNative private boolean handleAppCrashLocked(ProcessRecord app, String shortMsg, String longMsg, String stackTrace) { - if (mHeadless) { - Log.e(TAG, "handleAppCrashLocked: " + app.processName); - return false; - } long now = SystemClock.uptimeMillis(); Long crashTime; @@ -12388,6 +12291,7 @@ public final class ActivityManagerService extends ActivityManagerNative boolean restarting, boolean allowRestart, int index) { if (index >= 0) { removeLruProcessLocked(app); + ProcessList.remove(app.pid); } mProcessesToGc.remove(app); @@ -14042,9 +13946,6 @@ public final class ActivityManagerService extends ActivityManagerNative */ boolean updateConfigurationLocked(Configuration values, ActivityRecord starting, boolean persistent, boolean initLocale) { - // do nothing if we are headless - if (mHeadless) return true; - int changes = 0; if (values != null) { @@ -14127,18 +14028,21 @@ public final class ActivityManagerService extends ActivityManagerNative boolean kept = true; final ActivityStack mainStack = mStackSupervisor.getFocusedStack(); - if (changes != 0 && starting == null) { - // If the configuration changed, and the caller is not already - // in the process of starting an activity, then find the top - // activity to check if its configuration needs to change. - starting = mainStack.topRunningActivityLocked(null); - } + // mainStack is null during startup. + if (mainStack != null) { + if (changes != 0 && starting == null) { + // If the configuration changed, and the caller is not already + // in the process of starting an activity, then find the top + // activity to check if its configuration needs to change. + starting = mainStack.topRunningActivityLocked(null); + } - if (starting != null) { - kept = mainStack.ensureActivityConfigurationLocked(starting, changes); - // And we need to make sure at this point that all other activities - // are made visible with the correct configuration. - mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes); + if (starting != null) { + kept = mainStack.ensureActivityConfigurationLocked(starting, changes); + // And we need to make sure at this point that all other activities + // are made visible with the correct configuration. + mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes); + } } if (values != null && mWindowManager != null) { @@ -15250,16 +15154,13 @@ public final class ActivityManagerService extends ActivityManagerNative } if (app.curAdj != app.setAdj) { - if (Process.setOomAdj(app.pid, app.curAdj)) { - if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v( - TAG, "Set " + app.pid + " " + app.processName + - " adj " + app.curAdj + ": " + app.adjType); - app.setAdj = app.curAdj; - } else { - success = false; - Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj); - } + ProcessList.setOomAdj(app.pid, app.curAdj); + if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v( + TAG, "Set " + app.pid + " " + app.processName + + " adj " + app.curAdj + ": " + app.adjType); + app.setAdj = app.curAdj; } + if (app.setSchedGroup != app.curSchedGroup) { app.setSchedGroup = app.curSchedGroup; if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG, diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 49f29fe6c372..a27288ab08c7 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -21,6 +21,7 @@ import com.android.internal.R.styleable; import com.android.internal.app.ResolverActivity; import com.android.server.AttributeCache; import com.android.server.am.ActivityStack.ActivityState; +import com.android.server.am.ActivityStackSupervisor.ActivityContainer; import android.app.ActivityOptions; import android.app.ResultInfo; @@ -138,11 +139,13 @@ final class ActivityRecord { boolean forceNewConfig; // force re-create with new config next time int launchCount; // count of launches since last state long lastLaunchTime; // time of last lauch of this activity + ArrayList<ActivityStack> mChildContainers = new ArrayList<ActivityStack>(); String stringName; // for caching of toString(). private boolean inHistory; // are we in the history stack? final ActivityStackSupervisor mStackSupervisor; + ActivityContainer mInitialActivityContainer; void dump(PrintWriter pw, String prefix) { final long now = SystemClock.uptimeMillis(); @@ -347,7 +350,8 @@ final class ActivityRecord { int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType, ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo, String _resultWho, int _reqCode, - boolean _componentSpecified, ActivityStackSupervisor supervisor) { + boolean _componentSpecified, ActivityStackSupervisor supervisor, + ActivityContainer container) { service = _service; appToken = new Token(this); info = aInfo; @@ -378,6 +382,7 @@ final class ActivityRecord { idle = false; hasBeenLaunched = false; mStackSupervisor = supervisor; + mInitialActivityContainer = container; // This starts out true, since the initial state of an activity // is that we have everything, and we shouldn't never consider it @@ -481,7 +486,7 @@ final class ActivityRecord { void setTask(TaskRecord newTask, ThumbnailHolder newThumbHolder, boolean isRoot) { if (task != null && task.removeActivity(this)) { if (task != newTask) { - mStackSupervisor.removeTask(task); + task.stack.removeTask(task); } else { Slog.d(TAG, "!!! REMOVE THIS LOG !!! setTask: nearly removed stack=" + (newTask == null ? null : newTask.stack)); diff --git a/services/java/com/android/server/am/ActivityResult.java b/services/core/java/com/android/server/am/ActivityResult.java index 6d5bdebe4e36..6d5bdebe4e36 100644 --- a/services/java/com/android/server/am/ActivityResult.java +++ b/services/core/java/com/android/server/am/ActivityResult.java diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index d651a6217c49..68ef815b7d53 100755 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -39,6 +39,7 @@ import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; import com.android.internal.os.BatteryStatsImpl; import com.android.server.Watchdog; import com.android.server.am.ActivityManagerService.ItemMatcher; +import com.android.server.am.ActivityStackSupervisor.ActivityContainer; import com.android.server.wm.AppTransition; import com.android.server.wm.TaskGroup; import com.android.server.wm.WindowManagerService; @@ -52,7 +53,6 @@ import android.app.IThumbnailReceiver; import android.app.ResultInfo; import android.app.ActivityManager.RunningTaskInfo; import android.content.ComponentName; -import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; @@ -139,8 +139,6 @@ final class ActivityStack { final ActivityManagerService mService; final WindowManagerService mWindowManager; - final Context mContext; - /** * The back history of all previous (and possibly still * running) activities. It contains #TaskRecord objects. @@ -229,6 +227,11 @@ final class ActivityStack { int mCurrentUser; final int mStackId; + final ActivityContainer mActivityContainer; + /** The other stacks, in order, on the attached display. Updated at attach/detach time. */ + ArrayList<ActivityStack> mStacks; + /** The attached Display's unique identifier, or -1 if detached */ + int mDisplayId; /** Run all ActivityStacks through this */ final ActivityStackSupervisor mStackSupervisor; @@ -319,7 +322,7 @@ final class ActivityStack { } } - private int numActivities() { + int numActivities() { int count = 0; for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { count += mTaskHistory.get(taskNdx).mActivities.size(); @@ -327,14 +330,14 @@ final class ActivityStack { return count; } - ActivityStack(ActivityManagerService service, Context context, Looper looper, int stackId) { - mHandler = new ActivityStackHandler(looper); - mService = service; - mWindowManager = service.mWindowManager; - mStackSupervisor = service.mStackSupervisor; - mContext = context; - mStackId = stackId; - mCurrentUser = service.mCurrentUserId; + ActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer) { + mActivityContainer = activityContainer; + mStackSupervisor = activityContainer.getOuter(); + mService = mStackSupervisor.mService; + mHandler = new ActivityStackHandler(mService.mHandler.getLooper()); + mWindowManager = mService.mWindowManager; + mStackId = activityContainer.mStackId; + mCurrentUser = mService.mCurrentUserId; } boolean okToShow(ActivityRecord r) { @@ -436,25 +439,6 @@ final class ActivityStack { return null; } - boolean containsApp(ProcessRecord app) { - if (app == null) { - return false; - } - for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { - final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; - for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { - final ActivityRecord r = activities.get(activityNdx); - if (r.finishing) { - continue; - } - if (r.app == app) { - return true; - } - } - } - return false; - } - final boolean updateLRUListLocked(ActivityRecord r) { final boolean hadit = mLRUActivities.remove(r); mLRUActivities.add(r); @@ -465,6 +449,25 @@ final class ActivityStack { return mStackId == HOME_STACK_ID; } + final boolean isOnHomeDisplay() { + return isAttached() && + mActivityContainer.mActivityDisplay.mDisplayId == Display.DEFAULT_DISPLAY; + } + + final void moveToFront() { + if (isAttached()) { + if (isOnHomeDisplay()) { + mStackSupervisor.moveHomeStack(isHomeStack()); + } + mStacks.remove(this); + mStacks.add(this); + } + } + + final boolean isAttached() { + return mStacks != null; + } + /** * Returns the top activity in any existing task matching the given * Intent. Returns null if no such task is found. @@ -733,6 +736,12 @@ final class ActivityStack { mStackSupervisor.resumeTopActivitiesLocked(); return; } + + if (mActivityContainer.mParentActivity == null) { + // Top level stack, not a child. Look for child stacks. + mStackSupervisor.pauseChildStacks(prev, userLeaving, uiSleeping); + } + if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev); else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev); mResumedActivity = null; @@ -1224,12 +1233,14 @@ final class ActivityStack { mUndrawnActivitiesBelowTopTranslucent.clear(); mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG); - if (waitingActivity != null && waitingActivity.app != null && - waitingActivity.app.thread != null) { - try { - waitingActivity.app.thread.scheduleTranslucentConversionComplete( - waitingActivity.appToken, r != null); - } catch (RemoteException e) { + if (waitingActivity != null) { + mWindowManager.setWindowOpaque(waitingActivity.appToken, false); + if (waitingActivity.app != null && waitingActivity.app.thread != null) { + try { + waitingActivity.app.thread.scheduleTranslucentConversionComplete( + waitingActivity.appToken, r != null); + } catch (RemoteException e) { + } } } } @@ -1251,6 +1262,13 @@ final class ActivityStack { final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) { if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen(""); + ActivityRecord parent = mActivityContainer.mParentActivity; + if (parent != null && parent.state != ActivityState.RESUMED) { + // Do not resume this stack if its parent is not resumed. + // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st. + return false; + } + // Find the first activity that is not finishing. ActivityRecord next = topRunningActivityLocked(null); @@ -1265,7 +1283,8 @@ final class ActivityStack { ActivityOptions.abort(options); if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); - return mStackSupervisor.resumeHomeActivity(prev); + // Only resume home if on home display + return isOnHomeDisplay() && mStackSupervisor.resumeHomeActivity(prev); } next.delayedResume = false; @@ -1288,25 +1307,17 @@ final class ActivityStack { if (prevTask != null && prevTask.mOnTopOfHome && prev.finishing && prev.frontOfTask) { if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); if (prevTask == nextTask) { - ArrayList<ActivityRecord> activities = prevTask.mActivities; - final int numActivities = activities.size(); - for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) { - final ActivityRecord r = activities.get(activityNdx); - // r is usually the same as next, but what if two activities were launched - // before prev finished? - if (!r.finishing) { - r.frontOfTask = true; - break; - } - } + prevTask.setFrontOfTask(); } else if (prevTask != topTask()) { // This task is going away but it was supposed to return to the home task. // Now the task above it has to return to the home task instead. final int taskNdx = mTaskHistory.indexOf(prevTask) + 1; mTaskHistory.get(taskNdx).mOnTopOfHome = true; } else { - if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Launching home next"); - return mStackSupervisor.resumeHomeActivity(prev); + if (DEBUG_STATES && isOnHomeDisplay()) Slog.d(TAG, + "resumeTopActivityLocked: Launching home next"); + // Only resume home if on home display + return isOnHomeDisplay() && mStackSupervisor.resumeHomeActivity(prev); } } @@ -1668,10 +1679,14 @@ final class ActivityStack { private void insertTaskAtTop(TaskRecord task) { // If this is being moved to the top by another activity or being launched from the home // activity, set mOnTopOfHome accordingly. - ActivityStack lastStack = mStackSupervisor.getLastStack(); - final boolean fromHome = lastStack == null ? true : lastStack.isHomeStack(); - if (!isHomeStack() && (fromHome || topTask() != task)) { - task.mOnTopOfHome = fromHome; + if (isOnHomeDisplay()) { + ActivityStack lastStack = mStackSupervisor.getLastStack(); + final boolean fromHome = lastStack.isHomeStack(); + if (!isHomeStack() && (fromHome || topTask() != task)) { + task.mOnTopOfHome = fromHome; + } + } else { + task.mOnTopOfHome = false; } mTaskHistory.remove(task); @@ -1750,9 +1765,9 @@ final class ActivityStack { if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task, new RuntimeException("here").fillInStackTrace()); task.addActivityToTop(r); + task.setFrontOfTask(); r.putInHistory(); - r.frontOfTask = newTask; if (!isHomeStack() || numActivities() > 0) { // We want to show the starting preview window if we are // switching to a new task, or the next activity's process is @@ -2413,15 +2428,12 @@ final class ActivityStack { final ArrayList<ActivityRecord> activities = r.task.mActivities; final int index = activities.indexOf(r); if (index < (activities.size() - 1)) { - ActivityRecord next = activities.get(index+1); - if (r.frontOfTask) { - // The next activity is now the front of the task. - next.frontOfTask = true; - } + r.task.setFrontOfTask(); if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) { // If the caller asked that this activity (and all above it) // be cleared when the task is reset, don't lose that information, // but propagate it up to the next activity. + ActivityRecord next = activities.get(index+1); next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); } } @@ -2600,7 +2612,7 @@ final class ActivityStack { int res = mStackSupervisor.startActivityLocked(srec.app.thread, destIntent, null, aInfo, parent.appToken, null, 0, -1, parent.launchedFromUid, parent.launchedFromPackage, - 0, null, true, null); + 0, null, true, null, null); foundParentInTask = res == ActivityManager.START_SUCCESS; } catch (RemoteException e) { foundParentInTask = false; @@ -2678,7 +2690,8 @@ final class ActivityStack { r.finishLaunchTickingLocked(); } - final void removeActivityFromHistoryLocked(ActivityRecord r) { + private void removeActivityFromHistoryLocked(ActivityRecord r) { + mStackSupervisor.removeChildActivityContainers(r); finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null); r.makeFinishing(); if (DEBUG_ADD_REMOVE) { @@ -2686,15 +2699,6 @@ final class ActivityStack { here.fillInStackTrace(); Slog.i(TAG, "Removing activity " + r + " from stack"); } - final TaskRecord task = r.task; - if (task != null && task.removeActivity(r)) { - if (DEBUG_STACK) Slog.i(TAG, - "removeActivityFromHistoryLocked: last activity removed from " + this); - if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) { - mStackSupervisor.moveHomeToTop(); - } - mStackSupervisor.removeTask(task); - } r.takeFromHistory(); removeTimeoutsForActivityLocked(r); if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (removed from history)"); @@ -2705,6 +2709,15 @@ final class ActivityStack { if (VALIDATE_TOKENS) { validateAppTokensLocked(); } + final TaskRecord task = r.task; + if (task != null && task.removeActivity(r)) { + if (DEBUG_STACK) Slog.i(TAG, + "removeActivityFromHistoryLocked: last activity removed from " + this); + if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) { + mStackSupervisor.moveHomeToTop(); + } + removeTask(task); + } cleanUpActivityServicesLocked(r); r.removeUriPermissionsLocked(); } @@ -3052,7 +3065,7 @@ final class ActivityStack { return; } - mStackSupervisor.moveHomeStack(isHomeStack()); + moveToFront(); // Shift all activities with this task up to the top // of the stack, keeping them in the same internal order. @@ -3161,7 +3174,7 @@ final class ActivityStack { } final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null; - if (task == tr && task.mOnTopOfHome || numTasks <= 1) { + if (task == tr && tr.mOnTopOfHome || numTasks <= 1 && isOnHomeDisplay()) { tr.mOnTopOfHome = false; return mStackSupervisor.resumeHomeActivity(null); } @@ -3322,6 +3335,8 @@ final class ActivityStack { r.startFreezingScreenLocked(r.app, 0); + mStackSupervisor.removeChildActivityContainers(r); + try { if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ") @@ -3354,14 +3369,20 @@ final class ActivityStack { for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); if (r.appToken == token) { - return true; + return true; } if (r.fullscreen && !r.finishing) { return false; } } } - return true; + final ActivityRecord r = ActivityRecord.forToken(token); + if (r == null) { + return false; + } + if (r.finishing) Slog.e(TAG, "willActivityBeVisibleLocked: Returning false," + + " would have returned true for r=" + r); + return !r.finishing; } void closeSystemDialogsLocked() { @@ -3600,14 +3621,30 @@ final class ActivityStack { return starting; } - boolean removeTask(TaskRecord task) { + void removeTask(TaskRecord task) { + mWindowManager.removeTask(task.taskId); + final ActivityRecord r = mResumedActivity; + if (r != null && r.task == task) { + mResumedActivity = null; + } + final int taskNdx = mTaskHistory.indexOf(task); final int topTaskNdx = mTaskHistory.size() - 1; if (task.mOnTopOfHome && taskNdx < topTaskNdx) { mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true; } mTaskHistory.remove(task); - return mTaskHistory.isEmpty(); + + if (mTaskHistory.isEmpty()) { + if (DEBUG_STACK) Slog.i(TAG, "removeTask: moving to back stack=" + this); + if (isOnHomeDisplay()) { + mStackSupervisor.moveHomeStack(!isHomeStack()); + } + if (mStacks != null) { + mStacks.remove(this); + mStacks.add(0, this); + } + } } TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, boolean toTop) { diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 483b4a04390e..3587241aad1c 100644 --- a/services/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -34,8 +34,11 @@ import static com.android.server.am.ActivityManagerService.TAG; import android.app.Activity; import android.app.ActivityManager; +import android.app.ActivityManager.StackInfo; import android.app.ActivityOptions; import android.app.AppGlobals; +import android.app.IActivityContainer; +import android.app.IActivityContainerCallback; import android.app.IActivityManager; import android.app.IApplicationThread; import android.app.IThumbnailReceiver; @@ -53,6 +56,13 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; +import android.graphics.Point; +import android.hardware.display.DisplayManager; +import android.hardware.display.DisplayManager.DisplayListener; +import android.hardware.display.DisplayManagerGlobal; +import android.hardware.display.VirtualDisplay; +import android.hardware.input.InputManager; +import android.hardware.input.InputManagerInternal; import android.os.Binder; import android.os.Bundle; import android.os.Debug; @@ -68,22 +78,28 @@ import android.os.SystemClock; import android.os.UserHandle; import android.util.EventLog; import android.util.Slog; -import android.util.SparseIntArray; +import android.util.SparseArray; +import android.util.SparseIntArray; +import android.view.Display; +import android.view.DisplayInfo; +import android.view.InputEvent; +import android.view.Surface; import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.internal.os.TransferPipe; +import com.android.server.LocalServices; import com.android.server.am.ActivityManagerService.PendingActivityLaunch; import com.android.server.am.ActivityStack.ActivityState; -import com.android.server.wm.StackBox; import com.android.server.wm.WindowManagerService; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; -public final class ActivityStackSupervisor { +public final class ActivityStackSupervisor implements DisplayListener { static final boolean DEBUG = ActivityManagerService.DEBUG || false; static final boolean DEBUG_ADD_REMOVE = DEBUG || false; static final boolean DEBUG_APP = DEBUG || false; @@ -107,19 +123,23 @@ public final class ActivityStackSupervisor { static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2; static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3; static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4; + static final int HANDLE_DISPLAY_ADDED = FIRST_SUPERVISOR_STACK_MSG + 5; + static final int HANDLE_DISPLAY_CHANGED = FIRST_SUPERVISOR_STACK_MSG + 6; + static final int HANDLE_DISPLAY_REMOVED = FIRST_SUPERVISOR_STACK_MSG + 7; + + private final static String VIRTUAL_DISPLAY_BASE_NAME = "ActivityViewVirtualDisplay"; // For debugging to make sure the caller when acquiring/releasing our // wake lock is the system process. static final boolean VALIDATE_WAKE_LOCK_CALLER = false; final ActivityManagerService mService; - final Context mContext; - final Looper mLooper; final ActivityStackSupervisorHandler mHandler; /** Short cut */ WindowManagerService mWindowManager; + DisplayManager mDisplayManager; /** Dismiss the keyguard after the next activity is displayed? */ boolean mDismissKeyguardOnNextActivity = false; @@ -134,22 +154,17 @@ public final class ActivityStackSupervisor { /** The current user */ private int mCurrentUser; - /** The stack containing the launcher app */ + /** The stack containing the launcher app. Assumed to always be attached to + * Display.DEFAULT_DISPLAY. */ private ActivityStack mHomeStack; - /** The non-home stack currently receiving input or launching the next activity. If home is - * in front then mHomeStack overrides mFocusedStack. - * DO NOT ACCESS DIRECTLY - It may be null, use getFocusedStack() */ + /** The stack currently receiving input or launching the next activity. */ private ActivityStack mFocusedStack; - /** All the non-launcher stacks */ - private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>(); - - private static final int STACK_STATE_HOME_IN_FRONT = 0; - private static final int STACK_STATE_HOME_TO_BACK = 1; - private static final int STACK_STATE_HOME_IN_BACK = 2; - private static final int STACK_STATE_HOME_TO_FRONT = 3; - private int mStackState = STACK_STATE_HOME_IN_FRONT; + /** If this is the same as mFocusedStack then the activity on the top of the focused stack has + * been resumed. If stacks are changing position this will hold the old stack until the new + * stack becomes resumed after which it will be set to mFocusedStack. */ + private ActivityStack mLastFocusedStack; /** List of activities that are waiting for a new activity to become visible before completing * whatever operation they are supposed to do. */ @@ -206,14 +221,21 @@ public final class ActivityStackSupervisor { /** Stack id of the front stack when user switched, indexed by userId. */ SparseIntArray mUserStackInFront = new SparseIntArray(2); - public ActivityStackSupervisor(ActivityManagerService service, Context context, - Looper looper) { + // TODO: Add listener for removal of references. + /** Mapping from (ActivityStack/TaskStack).mStackId to their current state */ + SparseArray<WeakReference<ActivityContainer>> mActivityContainers = + new SparseArray<WeakReference<ActivityContainer>>(); + + /** Mapping from displayId to display current state */ + private SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<ActivityDisplay>(); + + InputManagerInternal mInputManagerInternal; + + public ActivityStackSupervisor(ActivityManagerService service) { mService = service; - mContext = context; - mLooper = looper; - PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); + PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE); mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep"); - mHandler = new ActivityStackSupervisorHandler(looper); + mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper()); if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) { throw new IllegalStateException("Calling must be system uid"); } @@ -223,9 +245,25 @@ public final class ActivityStackSupervisor { } void setWindowManager(WindowManagerService wm) { - mWindowManager = wm; - mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID); - mStacks.add(mHomeStack); + synchronized (mService) { + mWindowManager = wm; + + mDisplayManager = + (DisplayManager)mService.mContext.getSystemService(Context.DISPLAY_SERVICE); + mDisplayManager.registerDisplayListener(this, null); + + Display[] displays = mDisplayManager.getDisplays(); + for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) { + final int displayId = displays[displayNdx].getDisplayId(); + ActivityDisplay activityDisplay = new ActivityDisplay(displayId); + mActivityDisplays.put(displayId, activityDisplay); + } + + createStackOnDisplay(null, HOME_STACK_ID, Display.DEFAULT_DISPLAY); + mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID); + + mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); + } } void dismissKeyguard() { @@ -237,43 +275,42 @@ public final class ActivityStackSupervisor { } ActivityStack getFocusedStack() { - if (mFocusedStack == null) { - return mHomeStack; - } - switch (mStackState) { - case STACK_STATE_HOME_IN_FRONT: - case STACK_STATE_HOME_TO_FRONT: - return mHomeStack; - case STACK_STATE_HOME_IN_BACK: - case STACK_STATE_HOME_TO_BACK: - default: - return mFocusedStack; - } + return mFocusedStack; } ActivityStack getLastStack() { - switch (mStackState) { - case STACK_STATE_HOME_IN_FRONT: - case STACK_STATE_HOME_TO_BACK: - return mHomeStack; - case STACK_STATE_HOME_TO_FRONT: - case STACK_STATE_HOME_IN_BACK: - default: - return mFocusedStack; - } + return mLastFocusedStack; } + // TODO: Split into two methods isFrontStack for any visible stack and isFrontmostStack for the + // top of all visible stacks. boolean isFrontStack(ActivityStack stack) { - return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack()); + final ActivityRecord parent = stack.mActivityContainer.mParentActivity; + if (parent != null) { + stack = parent.task.stack; + } + ArrayList<ActivityStack> stacks = stack.mStacks; + if (stacks != null && !stacks.isEmpty()) { + return stack == stacks.get(stacks.size() - 1); + } + return false; } void moveHomeStack(boolean toFront) { - final boolean homeInFront = isFrontStack(mHomeStack); - if (homeInFront ^ toFront) { - if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: mStackState old=" + - stackStateToString(mStackState) + " new=" + stackStateToString(homeInFront ? - STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT)); - mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT; + ArrayList<ActivityStack> stacks = mHomeStack.mStacks; + int topNdx = stacks.size() - 1; + if (topNdx <= 0) { + return; + } + ActivityStack topStack = stacks.get(topNdx); + final boolean homeInFront = topStack == mHomeStack; + if (homeInFront != toFront) { + mLastFocusedStack = topStack; + stacks.remove(mHomeStack); + stacks.add(toFront ? topNdx : 0, mHomeStack); + mFocusedStack = stacks.get(topNdx); + if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: topStack old=" + topStack + " new=" + + mFocusedStack); } } @@ -301,21 +338,29 @@ public final class ActivityStackSupervisor { } TaskRecord anyTaskForIdLocked(int id) { - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - ActivityStack stack = mStacks.get(stackNdx); - TaskRecord task = stack.taskForIdLocked(id); - if (task != null) { - return task; + int numDisplays = mActivityDisplays.size(); + for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { + ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + ActivityStack stack = stacks.get(stackNdx); + TaskRecord task = stack.taskForIdLocked(id); + if (task != null) { + return task; + } } } return null; } ActivityRecord isInAnyStackLocked(IBinder token) { - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token); - if (r != null) { - return r; + int numDisplays = mActivityDisplays.size(); + for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { + ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityRecord r = stacks.get(stackNdx).isInStackLocked(token); + if (r != null) { + return r; + } } } return null; @@ -331,26 +376,6 @@ public final class ActivityStackSupervisor { return mCurTaskId; } - void removeTask(TaskRecord task) { - mWindowManager.removeTask(task.taskId); - final ActivityStack stack = task.stack; - final ActivityRecord r = stack.mResumedActivity; - if (r != null && r.task == task) { - stack.mResumedActivity = null; - } - if (stack.removeTask(task) && !stack.isHomeStack()) { - if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack); - mStacks.remove(stack); - final int stackId = stack.mStackId; - final int nextStackId = mWindowManager.removeStack(stackId); - // TODO: Perhaps we need to let the ActivityManager determine the next focus... - if (mFocusedStack == null || mFocusedStack.mStackId == stackId) { - // If this is the last app stack, set mFocusedStack to null. - mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId); - } - } - } - ActivityRecord resumedAppLocked() { ActivityStack stack = getFocusedStack(); if (stack == null) { @@ -366,29 +391,29 @@ public final class ActivityStackSupervisor { return resumedActivity; } - boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception { - boolean didSomething = false; + boolean attachApplicationLocked(ProcessRecord app) throws Exception { final String processName = app.processName; - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - if (!isFrontStack(stack)) { - continue; - } - ActivityRecord hr = stack.topRunningActivityLocked(null); - if (hr != null) { - if (hr.app == null && app.uid == hr.info.applicationInfo.uid - && processName.equals(hr.processName)) { - try { - if (headless) { - Slog.e(TAG, "Starting activities not supported on headless device: " - + hr); - } else if (realStartActivityLocked(hr, app, true, true)) { - didSomething = true; + boolean didSomething = false; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + if (!isFrontStack(stack)) { + continue; + } + ActivityRecord hr = stack.topRunningActivityLocked(null); + if (hr != null) { + if (hr.app == null && app.uid == hr.info.applicationInfo.uid + && processName.equals(hr.processName)) { + try { + if (realStartActivityLocked(hr, app, true, true)) { + didSomething = true; + } + } catch (Exception e) { + Slog.w(TAG, "Exception in new application when starting activity " + + hr.intent.getComponent().flattenToShortString(), e); + throw e; } - } catch (Exception e) { - Slog.w(TAG, "Exception in new application when starting activity " - + hr.intent.getComponent().flattenToShortString(), e); - throw e; } } } @@ -400,53 +425,54 @@ public final class ActivityStackSupervisor { } boolean allResumedActivitiesIdle() { - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - if (!isFrontStack(stack)) { - continue; - } - final ActivityRecord resumedActivity = stack.mResumedActivity; - if (resumedActivity == null || !resumedActivity.idle) { - return false; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + if (!isFrontStack(stack) || stack.numActivities() == 0) { + continue; + } + final ActivityRecord resumedActivity = stack.mResumedActivity; + if (resumedActivity == null || !resumedActivity.idle) { + if (DEBUG_STATES) Slog.d(TAG, "allResumedActivitiesIdle: stack=" + + stack.mStackId + " " + resumedActivity + " not idle"); + return false; + } } } return true; } boolean allResumedActivitiesComplete() { - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - if (isFrontStack(stack)) { - final ActivityRecord r = stack.mResumedActivity; - if (r != null && r.state != ActivityState.RESUMED) { - return false; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + if (isFrontStack(stack)) { + final ActivityRecord r = stack.mResumedActivity; + if (r != null && r.state != ActivityState.RESUMED) { + return false; + } } } } // TODO: Not sure if this should check if all Paused are complete too. - switch (mStackState) { - case STACK_STATE_HOME_TO_BACK: - if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" + - stackStateToString(STACK_STATE_HOME_TO_BACK) + " new=" + - stackStateToString(STACK_STATE_HOME_IN_BACK)); - mStackState = STACK_STATE_HOME_IN_BACK; - break; - case STACK_STATE_HOME_TO_FRONT: - if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" + - stackStateToString(STACK_STATE_HOME_TO_FRONT) + " new=" + - stackStateToString(STACK_STATE_HOME_IN_FRONT)); - mStackState = STACK_STATE_HOME_IN_FRONT; - break; - } + if (DEBUG_STACK) Slog.d(TAG, + "allResumedActivitiesComplete: mLastFocusedStack changing from=" + + mLastFocusedStack + " to=" + mFocusedStack); + mLastFocusedStack = mFocusedStack; return true; } boolean allResumedActivitiesVisible() { - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - final ActivityRecord r = stack.mResumedActivity; - if (r != null && (!r.nowVisible || r.waitingVisible)) { - return false; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + final ActivityRecord r = stack.mResumedActivity; + if (r != null && (!r.nowVisible || r.waitingVisible)) { + return false; + } } } return true; @@ -459,13 +485,16 @@ public final class ActivityStackSupervisor { */ boolean pauseBackStacks(boolean userLeaving) { boolean someActivityPaused = false; - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - if (!isFrontStack(stack) && stack.mResumedActivity != null) { - if (DEBUG_STATES) Slog.d(TAG, "pauseBackStacks: stack=" + stack + - " mResumedActivity=" + stack.mResumedActivity); - stack.startPausingLocked(userLeaving, false); - someActivityPaused = true; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + if (!isFrontStack(stack) && stack.mResumedActivity != null) { + if (DEBUG_STATES) Slog.d(TAG, "pauseBackStacks: stack=" + stack + + " mResumedActivity=" + stack.mResumedActivity); + stack.startPausingLocked(userLeaving, false); + someActivityPaused = true; + } } } return someActivityPaused; @@ -473,23 +502,40 @@ public final class ActivityStackSupervisor { boolean allPausedActivitiesComplete() { boolean pausing = true; - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - final ActivityRecord r = stack.mPausingActivity; - if (r != null && r.state != ActivityState.PAUSED - && r.state != ActivityState.STOPPED - && r.state != ActivityState.STOPPING) { - if (DEBUG_STATES) { - Slog.d(TAG, "allPausedActivitiesComplete: r=" + r + " state=" + r.state); - pausing = false; - } else { - return false; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + final ActivityRecord r = stack.mPausingActivity; + if (r != null && r.state != ActivityState.PAUSED + && r.state != ActivityState.STOPPED + && r.state != ActivityState.STOPPING) { + if (DEBUG_STATES) { + Slog.d(TAG, "allPausedActivitiesComplete: r=" + r + " state=" + r.state); + pausing = false; + } else { + return false; + } } } } return pausing; } + void pauseChildStacks(ActivityRecord parent, boolean userLeaving, boolean uiSleeping) { + // TODO: Put all stacks in supervisor and iterate through them instead. + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + if (stack.mResumedActivity != null && + stack.mActivityContainer.mParentActivity == parent) { + stack.startPausingLocked(userLeaving, uiSleeping); + } + } + } + } + void reportActivityVisibleLocked(ActivityRecord r) { for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) { WaitResult w = mWaitingActivityVisible.get(i); @@ -525,8 +571,10 @@ public final class ActivityStackSupervisor { return r; } - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); + // Return to the home stack. + final ArrayList<ActivityStack> stacks = mHomeStack.mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); if (stack != focusedStack && isFrontStack(stack)) { r = stack.topRunningActivityLocked(null); if (r != null) { @@ -542,15 +590,19 @@ public final class ActivityStackSupervisor { ActivityRecord r = null; // Gather all of the running tasks for each stack into runningTaskLists. - final int numStacks = mStacks.size(); - ArrayList<RunningTaskInfo>[] runningTaskLists = new ArrayList[numStacks]; - for (int stackNdx = numStacks - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>(); - runningTaskLists[stackNdx] = stackTaskList; - final ActivityRecord ar = stack.getTasksLocked(receiver, pending, stackTaskList); - if (isFrontStack(stack)) { - r = ar; + ArrayList<ArrayList<RunningTaskInfo>> runningTaskLists = + new ArrayList<ArrayList<RunningTaskInfo>>(); + final int numDisplays = mActivityDisplays.size(); + for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { + ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>(); + runningTaskLists.add(stackTaskList); + final ActivityRecord ar = stack.getTasksLocked(receiver, pending, stackTaskList); + if (r == null && isFrontStack(stack)) { + r = ar; + } } } @@ -559,8 +611,9 @@ public final class ActivityStackSupervisor { while (maxNum > 0) { long mostRecentActiveTime = Long.MIN_VALUE; ArrayList<RunningTaskInfo> selectedStackList = null; - for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { - ArrayList<RunningTaskInfo> stackTaskList = runningTaskLists[stackNdx]; + final int numTaskLists = runningTaskLists.size(); + for (int stackNdx = 0; stackNdx < numTaskLists; ++stackNdx) { + ArrayList<RunningTaskInfo> stackTaskList = runningTaskLists.get(stackNdx); if (!stackTaskList.isEmpty()) { final long lastActiveTime = stackTaskList.get(0).lastActiveTime; if (lastActiveTime > mostRecentActiveTime) { @@ -630,14 +683,14 @@ public final class ActivityStackSupervisor { void startHomeActivity(Intent intent, ActivityInfo aInfo) { moveHomeToTop(); startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0, - null, false, null); + null, false, null, null); } final int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, String profileFile, ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config, - Bundle options, int userId) { + Bundle options, int userId, IActivityContainer iContainer) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Intent"); @@ -651,6 +704,7 @@ public final class ActivityStackSupervisor { ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profileFile, profileFd, userId); + ActivityContainer container = (ActivityContainer)iContainer; synchronized (mService) { int callingPid; if (callingUid >= 0) { @@ -662,7 +716,12 @@ public final class ActivityStackSupervisor { callingPid = callingUid = -1; } - final ActivityStack stack = getFocusedStack(); + final ActivityStack stack; + if (container == null || container.mStack.isOnHomeDisplay()) { + stack = getFocusedStack(); + } else { + stack = container.mStack; + } stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0; if (DEBUG_CONFIGURATION) Slog.v(TAG, @@ -738,9 +797,9 @@ public final class ActivityStackSupervisor { } } - int res = startActivityLocked(caller, intent, resolvedType, - aInfo, resultTo, resultWho, requestCode, callingPid, callingUid, - callingPackage, startFlags, options, componentSpecified, null); + int res = startActivityLocked(caller, intent, resolvedType, aInfo, resultTo, resultWho, + requestCode, callingPid, callingUid, callingPackage, startFlags, options, + componentSpecified, null, container); if (stack.mConfigWillChange) { // If the caller also wants to switch to a new configuration, @@ -855,7 +914,7 @@ public final class ActivityStackSupervisor { } int res = startActivityLocked(caller, intent, resolvedTypes[i], aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage, - 0, theseOptions, componentSpecified, outActivity); + 0, theseOptions, componentSpecified, outActivity, null); if (res < 0) { return res; } @@ -1079,7 +1138,7 @@ public final class ActivityStackSupervisor { Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options, - boolean componentSpecified, ActivityRecord[] outActivity) { + boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container) { int err = ActivityManager.START_SUCCESS; ProcessRecord callerApp = null; @@ -1099,7 +1158,11 @@ public final class ActivityStackSupervisor { if (err == ActivityManager.START_SUCCESS) { final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0; Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false) - + "} from pid " + (callerApp != null ? callerApp.pid : callingPid)); + + "} from pid " + (callerApp != null ? callerApp.pid : callingPid) + + " on display " + (container == null ? (mFocusedStack == null ? + Display.DEFAULT_DISPLAY : mFocusedStack.mDisplayId) : + (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY : + container.mActivityDisplay.mDisplayId))); } ActivityRecord sourceRecord = null; @@ -1214,8 +1277,8 @@ public final class ActivityStackSupervisor { } ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage, - intent, resolvedType, aInfo, mService.mConfiguration, - resultRecord, resultWho, requestCode, componentSpecified, this); + intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, + requestCode, componentSpecified, this, container); if (outActivity != null) { outActivity[0] = r; } @@ -1263,25 +1326,35 @@ public final class ActivityStackSupervisor { if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) { if (task != null) { final ActivityStack taskStack = task.stack; - if (mFocusedStack != taskStack) { - if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, - "adjustStackFocus: Setting focused stack to r=" + r + " task=" + task); - mFocusedStack = taskStack.isHomeStack() ? null : taskStack; - } else { - if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, - "adjustStackFocus: Focused stack already=" + mFocusedStack); + if (taskStack.isOnHomeDisplay()) { + if (mFocusedStack != taskStack) { + if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: Setting " + + "focused stack to r=" + r + " task=" + task); + mFocusedStack = taskStack; + } else { + if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, + "adjustStackFocus: Focused stack already=" + mFocusedStack); + } } return taskStack; } - if (mFocusedStack != null) { + final ActivityContainer container = r.mInitialActivityContainer; + if (container != null) { + // The first time put it on the desired stack, after this put on task stack. + r.mInitialActivityContainer = null; + return container.mStack; + } + + if (mFocusedStack != mHomeStack) { if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: Have a focused stack=" + mFocusedStack); return mFocusedStack; } - for (int stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) { - ActivityStack stack = mStacks.get(stackNdx); + final ArrayList<ActivityStack> homeDisplayStacks = mHomeStack.mStacks; + for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = homeDisplayStacks.get(stackNdx); if (!stack.isHomeStack()) { if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: Setting focused stack=" + stack); @@ -1290,9 +1363,8 @@ public final class ActivityStackSupervisor { } } - // Time to create the first app stack for this user. - int stackId = - mService.createStack(-1, HOME_STACK_ID, StackBox.TASK_STACK_GOES_OVER, 1.0f); + // Need to create an app stack for this user. + int stackId = createStackOnDisplay(null, getNextStackId(), Display.DEFAULT_DISPLAY); if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r + " stackId=" + stackId); mFocusedStack = getStack(stackId); @@ -1302,30 +1374,17 @@ public final class ActivityStackSupervisor { } void setFocusedStack(ActivityRecord r) { - if (r == null) { - return; - } - if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) { - if (mStackState != STACK_STATE_HOME_IN_FRONT) { - if (DEBUG_STACK || DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: mStackState old=" + - stackStateToString(mStackState) + " new=" + - stackStateToString(STACK_STATE_HOME_TO_FRONT) + - " Callers=" + Debug.getCallers(3)); - mStackState = STACK_STATE_HOME_TO_FRONT; + if (r != null) { + final TaskRecord task = r.task; + boolean isHomeActivity = !r.isApplicationActivity(); + if (!isHomeActivity && task != null) { + isHomeActivity = !task.isApplicationTask(); } - } else { - if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, - "setFocusedStack: Setting focused stack to r=" + r + " task=" + r.task + - " Callers=" + Debug.getCallers(3)); - final ActivityStack taskStack = r.task.stack; - mFocusedStack = taskStack.isHomeStack() ? null : taskStack; - if (mStackState != STACK_STATE_HOME_IN_BACK) { - if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" + - stackStateToString(mStackState) + " new=" + - stackStateToString(STACK_STATE_HOME_TO_BACK) + - " Callers=" + Debug.getCallers(3)); - mStackState = STACK_STATE_HOME_TO_BACK; + if (!isHomeActivity && task != null) { + final ActivityRecord parent = task.stack.mActivityContainer.mParentActivity; + isHomeActivity = parent != null && parent.isHomeActivity(); } + moveHomeStack(isHomeActivity); } } @@ -1452,7 +1511,7 @@ public final class ActivityStackSupervisor { targetStack.mLastPausedActivity = null; if (DEBUG_TASKS) Slog.d(TAG, "Bring to front target: " + targetStack + " from " + intentActivity); - moveHomeStack(targetStack.isHomeStack()); + targetStack.moveToFront(); if (intentActivity.task.intent == null) { // This task was started because of movement of // the activity based on affinity... now that we @@ -1502,9 +1561,6 @@ public final class ActivityStackSupervisor { } else { ActivityOptions.abort(options); } - if (r.task == null) Slog.v(TAG, - "startActivityUncheckedLocked: task left null", - new RuntimeException("here").fillInStackTrace()); return ActivityManager.START_RETURN_INTENT_TO_CALLER; } if ((launchFlags & @@ -1597,9 +1653,6 @@ public final class ActivityStackSupervisor { } else { ActivityOptions.abort(options); } - if (r.task == null) Slog.v(TAG, - "startActivityUncheckedLocked: task left null", - new RuntimeException("here").fillInStackTrace()); return ActivityManager.START_TASK_TO_FRONT; } } @@ -1637,15 +1690,9 @@ public final class ActivityStackSupervisor { // We don't need to start a new activity, and // the client said not to do anything if that // is the case, so this is it! - if (r.task == null) Slog.v(TAG, - "startActivityUncheckedLocked: task left null", - new RuntimeException("here").fillInStackTrace()); return ActivityManager.START_RETURN_INTENT_TO_CALLER; } top.deliverNewIntentLocked(callingUid, r.intent); - if (r.task == null) Slog.v(TAG, - "startActivityUncheckedLocked: task left null", - new RuntimeException("here").fillInStackTrace()); return ActivityManager.START_DELIVERED_TO_TOP; } } @@ -1658,9 +1705,6 @@ public final class ActivityStackSupervisor { r.requestCode, Activity.RESULT_CANCELED, null); } ActivityOptions.abort(options); - if (r.task == null) Slog.v(TAG, - "startActivityUncheckedLocked: task left null", - new RuntimeException("here").fillInStackTrace()); return ActivityManager.START_CLASS_NOT_FOUND; } @@ -1671,7 +1715,7 @@ public final class ActivityStackSupervisor { if (r.resultTo == null && !addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { targetStack = adjustStackFocus(r); - moveHomeStack(targetStack.isHomeStack()); + targetStack.moveToFront(); if (reuseTask == null) { r.setTask(targetStack.createTaskRecord(getNextTaskId(), newTaskInfo != null ? newTaskInfo : r.info, @@ -1689,13 +1733,13 @@ public final class ActivityStackSupervisor { == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) { // Caller wants to appear on home activity, so before starting // their own activity we will bring home to the front. - r.task.mOnTopOfHome = true; + r.task.mOnTopOfHome = r.task.stack.isOnHomeDisplay(); } } } else if (sourceRecord != null) { TaskRecord sourceTask = sourceRecord.task; targetStack = sourceTask.stack; - moveHomeStack(targetStack.isHomeStack()); + targetStack.moveToFront(); if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { // In this case, we are adding the activity to an existing @@ -1713,9 +1757,6 @@ public final class ActivityStackSupervisor { targetStack.resumeTopActivityLocked(null); } ActivityOptions.abort(options); - if (r.task == null) Slog.w(TAG, - "startActivityUncheckedLocked: task left null", - new RuntimeException("here").fillInStackTrace()); return ActivityManager.START_DELIVERED_TO_TOP; } } else if (!addingToTask && @@ -1749,7 +1790,7 @@ public final class ActivityStackSupervisor { // of a new task... just put it in the top task, though these days // this case should never happen. targetStack = adjustStackFocus(r); - moveHomeStack(targetStack.isHomeStack()); + targetStack.moveToFront(); ActivityRecord prev = targetStack.topActivity(); r.setTask(prev != null ? prev.task : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true), @@ -1941,17 +1982,21 @@ public final class ActivityStackSupervisor { boolean handleAppDiedLocked(ProcessRecord app) { boolean hasVisibleActivities = false; - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - hasVisibleActivities |= mStacks.get(stackNdx).handleAppDiedLocked(app); + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + hasVisibleActivities |= stacks.get(stackNdx).handleAppDiedLocked(app); + } } return hasVisibleActivities; } void closeSystemDialogsLocked() { - final int numStacks = mStacks.size(); - for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - stack.closeSystemDialogsLocked(); + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + stacks.get(stackNdx).closeSystemDialogsLocked(); + } } } @@ -1964,11 +2009,14 @@ public final class ActivityStackSupervisor { */ boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) { boolean didSomething = false; - final int numStacks = mStacks.size(); - for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) { - didSomething = true; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + final int numStacks = stacks.size(); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) { + didSomething = true; + } } } return didSomething; @@ -1983,15 +2031,18 @@ public final class ActivityStackSupervisor { // we don't blow away the previous app if this activity is being // hosted by the process that is actually still the foreground. ProcessRecord fgApp = null; - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - if (isFrontStack(stack)) { - if (stack.mResumedActivity != null) { - fgApp = stack.mResumedActivity.app; - } else if (stack.mPausingActivity != null) { - fgApp = stack.mPausingActivity.app; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + if (isFrontStack(stack)) { + if (stack.mResumedActivity != null) { + fgApp = stack.mResumedActivity.app; + } else if (stack.mPausingActivity != null) { + fgApp = stack.mPausingActivity.app; + } + break; } - break; } } @@ -2014,13 +2065,20 @@ public final class ActivityStackSupervisor { if (targetStack == null) { targetStack = getFocusedStack(); } + // Do targetStack first. boolean result = false; - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - if (isFrontStack(stack)) { + if (isFrontStack(targetStack)) { + result = targetStack.resumeTopActivityLocked(target, targetOptions); + } + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); if (stack == targetStack) { - result = stack.resumeTopActivityLocked(target, targetOptions); - } else { + // Already started above. + continue; + } + if (isFrontStack(stack)) { stack.resumeTopActivityLocked(null); } } @@ -2029,38 +2087,118 @@ public final class ActivityStackSupervisor { } void finishTopRunningActivityLocked(ProcessRecord app) { - final int numStacks = mStacks.size(); - for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - stack.finishTopRunningActivityLocked(app); + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + final int numStacks = stacks.size(); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + stack.finishTopRunningActivityLocked(app); + } } } void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) { - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) { - if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" + - mStacks.get(stackNdx)); - return; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + if (stacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) { + if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" + + stacks.get(stackNdx)); + return; + } } } } ActivityStack getStack(int stackId) { - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - if (stack.getStackId() == stackId) { - return stack; + WeakReference<ActivityContainer> weakReference = mActivityContainers.get(stackId); + if (weakReference != null) { + ActivityContainer activityContainer = weakReference.get(); + if (activityContainer != null) { + return activityContainer.mStack; + } else { + mActivityContainers.remove(stackId); } } return null; } ArrayList<ActivityStack> getStacks() { - return new ArrayList<ActivityStack>(mStacks); + ArrayList<ActivityStack> allStacks = new ArrayList<ActivityStack>(); + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + allStacks.addAll(mActivityDisplays.valueAt(displayNdx).mStacks); + } + return allStacks; + } + + IBinder getHomeActivityToken() { + final ArrayList<TaskRecord> tasks = mHomeStack.getAllTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { + final TaskRecord task = tasks.get(taskNdx); + if (task.isHomeTask()) { + final ArrayList<ActivityRecord> activities = task.mActivities; + for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { + final ActivityRecord r = activities.get(activityNdx); + if (r.isHomeActivity()) { + return r.appToken; + } + } + } + } + return null; } - int createStack() { + ActivityContainer createActivityContainer(ActivityRecord parentActivity, int stackId, + IActivityContainerCallback callback) { + ActivityContainer activityContainer = new ActivityContainer(parentActivity, stackId, + callback); + mActivityContainers.put(stackId, new WeakReference<ActivityContainer>(activityContainer)); + if (parentActivity != null) { + parentActivity.mChildContainers.add(activityContainer.mStack); + } + return activityContainer; + } + + ActivityContainer createActivityContainer(ActivityRecord parentActivity, + IActivityContainerCallback callback) { + return createActivityContainer(parentActivity, getNextStackId(), callback); + } + + void removeChildActivityContainers(ActivityRecord parentActivity) { + for (int ndx = mActivityContainers.size() - 1; ndx >= 0; --ndx) { + final ActivityContainer container = mActivityContainers.valueAt(ndx).get(); + if (container == null) { + mActivityContainers.removeAt(ndx); + continue; + } + if (container.mParentActivity != parentActivity) { + continue; + } + + ActivityStack stack = container.mStack; + ActivityRecord top = stack.topRunningNonDelayedActivityLocked(null); + if (top != null) { + // TODO: Make sure the next activity doesn't start up when top is destroyed. + stack.destroyActivityLocked(top, true, true, "stack removal"); + } + mActivityContainers.removeAt(ndx); + container.detachLocked(); + } + } + + private int createStackOnDisplay(ActivityRecord parentActivity, int stackId, int displayId) { + ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); + if (activityDisplay == null) { + return -1; + } + + ActivityContainer activityContainer = + createActivityContainer(parentActivity, stackId, null); + activityContainer.attachToDisplayLocked(activityDisplay); + return stackId; + } + + int getNextStackId() { while (true) { if (++mLastStackId <= HOME_STACK_ID) { mLastStackId = HOME_STACK_ID + 1; @@ -2069,7 +2207,6 @@ public final class ActivityStackSupervisor { break; } } - mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId)); return mLastStackId; } @@ -2083,7 +2220,7 @@ public final class ActivityStackSupervisor { Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId); return; } - removeTask(task); + task.stack.removeTask(task); stack.addTask(task, toTop); mWindowManager.addTask(taskId, stackId, toTop); resumeTopActivitiesLocked(); @@ -2091,15 +2228,18 @@ public final class ActivityStackSupervisor { ActivityRecord findTaskLocked(ActivityRecord r) { if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + r); - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - if (!r.isApplicationActivity() && !stack.isHomeStack()) { - if (DEBUG_TASKS) Slog.d(TAG, "Skipping stack: " + stack); - continue; - } - final ActivityRecord ar = stack.findTaskLocked(r); - if (ar != null) { - return ar; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + if (!r.isApplicationActivity() && !stack.isHomeStack()) { + if (DEBUG_TASKS) Slog.d(TAG, "Skipping stack: " + stack); + continue; + } + final ActivityRecord ar = stack.findTaskLocked(r); + if (ar != null) { + return ar; + } } } if (DEBUG_TASKS) Slog.d(TAG, "No task found"); @@ -2107,10 +2247,13 @@ public final class ActivityStackSupervisor { } ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) { - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info); - if (ar != null) { - return ar; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityRecord ar = stacks.get(stackNdx).findActivityLocked(intent, info); + if (ar != null) { + return ar; + } } } return null; @@ -2138,8 +2281,11 @@ public final class ActivityStackSupervisor { final long endTime = System.currentTimeMillis() + timeout; while (true) { boolean cantShutdown = false; - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - cantShutdown |= mStacks.get(stackNdx).checkReadyForSleepLocked(); + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + cantShutdown |= stacks.get(stackNdx).checkReadyForSleepLocked(); + } } if (cantShutdown) { long timeRemaining = endTime - System.currentTimeMillis(); @@ -2170,11 +2316,14 @@ public final class ActivityStackSupervisor { if (mGoingToSleep.isHeld()) { mGoingToSleep.release(); } - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - stack.awakeFromSleepingLocked(); - if (isFrontStack(stack)) { - resumeTopActivitiesLocked(); + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + stack.awakeFromSleepingLocked(); + if (isFrontStack(stack)) { + resumeTopActivitiesLocked(); + } } } mGoingToSleepActivities.clear(); @@ -2193,8 +2342,11 @@ public final class ActivityStackSupervisor { if (!mSleepTimeout) { boolean dontSleep = false; - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - dontSleep |= mStacks.get(stackNdx).checkReadyForSleepLocked(); + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + dontSleep |= stacks.get(stackNdx).checkReadyForSleepLocked(); + } } if (mStoppingActivities.size() > 0) { @@ -2217,8 +2369,11 @@ public final class ActivityStackSupervisor { } } - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - mStacks.get(stackNdx).goToSleep(); + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + stacks.get(stackNdx).goToSleep(); + } } removeSleepTimeouts(); @@ -2245,37 +2400,45 @@ public final class ActivityStackSupervisor { } void handleAppCrashLocked(ProcessRecord app) { - final int numStacks = mStacks.size(); - for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - stack.handleAppCrashLocked(app); + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + final int numStacks = stacks.size(); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + stack.handleAppCrashLocked(app); + } } } void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) { // First the front stacks. In case any are not fullscreen and are in front of home. boolean showHomeBehindStack = false; - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - if (isFrontStack(stack)) { - showHomeBehindStack = - stack.ensureActivitiesVisibleLocked(starting, configChanges); - } - } - // Now do back stacks. - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - if (!isFrontStack(stack)) { - stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack); + 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); + if (stackNdx == topStackNdx) { + // Top stack. + showHomeBehindStack = + stack.ensureActivitiesVisibleLocked(starting, configChanges); + } else { + // Back stack. + stack.ensureActivitiesVisibleLocked(starting, configChanges, + showHomeBehindStack); + } } } } void scheduleDestroyAllActivities(ProcessRecord app, String reason) { - final int numStacks = mStacks.size(); - for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - stack.scheduleDestroyActivities(app, false, reason); + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + final int numStacks = stacks.size(); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + stack.scheduleDestroyActivities(app, false, reason); + } } } @@ -2285,8 +2448,13 @@ public final class ActivityStackSupervisor { mCurrentUser = userId; mStartingUsers.add(uss); - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - mStacks.get(stackNdx).switchUserLocked(userId); + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + stack.switchUserLocked(userId); + mWindowManager.moveTaskToTop(stack.topTask().taskId); + } } ActivityStack stack = getStack(restoreStackId); @@ -2294,8 +2462,13 @@ public final class ActivityStackSupervisor { stack = mHomeStack; } final boolean homeInFront = stack.isHomeStack(); - moveHomeStack(homeInFront); - mWindowManager.moveTaskToTop(stack.topTask().taskId); + if (stack.isOnHomeDisplay()) { + moveHomeStack(homeInFront); + mWindowManager.moveTaskToTop(stack.topTask().taskId); + } else { + // Stack was moved to another display while user was swapped out. + resumeHomeActivity(null); + } return homeInFront; } @@ -2340,8 +2513,9 @@ public final class ActivityStackSupervisor { } void validateTopActivitiesLocked() { - for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); + // FIXME +/* for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); final ActivityRecord r = stack.topRunningActivityLocked(null); final ActivityState state = r == null ? ActivityState.DESTROYED : r.state; if (isFrontStack(stack)) { @@ -2371,23 +2545,14 @@ public final class ActivityStackSupervisor { } } } - } - - private static String stackStateToString(int stackState) { - switch (stackState) { - case STACK_STATE_HOME_IN_FRONT: return "STACK_STATE_HOME_IN_FRONT"; - case STACK_STATE_HOME_TO_BACK: return "STACK_STATE_HOME_TO_BACK"; - case STACK_STATE_HOME_IN_BACK: return "STACK_STATE_HOME_IN_BACK"; - case STACK_STATE_HOME_TO_FRONT: return "STACK_STATE_HOME_TO_FRONT"; - default: return "Unknown stackState=" + stackState; - } +*/ } public void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity="); pw.println(mDismissKeyguardOnNextActivity); pw.print(prefix); pw.print("mFocusedStack=" + mFocusedStack); - pw.print(" mStackState="); pw.println(stackStateToString(mStackState)); + pw.print(" mLastFocusedStack="); pw.println(mLastFocusedStack); pw.print(prefix); pw.println("mSleepTimeout=" + mSleepTimeout); pw.print(prefix); pw.println("mCurTaskId=" + mCurTaskId); pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront); @@ -2416,42 +2581,48 @@ public final class ActivityStackSupervisor { boolean dumpClient, String dumpPackage) { boolean printed = false; boolean needSep = false; - final int numStacks = mStacks.size(); - for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { - final ActivityStack stack = mStacks.get(stackNdx); - StringBuilder stackHeader = new StringBuilder(128); - stackHeader.append(" Stack #"); - stackHeader.append(mStacks.indexOf(stack)); - stackHeader.append(":"); - printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, needSep, - stackHeader.toString()); - printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, - false, dumpPackage, true, " Running activities (most recent first):", null); - - needSep = printed; - boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep, - " mPausingActivity: "); - if (pr) { - printed = true; - needSep = false; - } - pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep, - " mResumedActivity: "); - if (pr) { - printed = true; - needSep = false; - } - if (dumpAll) { - pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep, - " mLastPausedActivity: "); + for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) { + ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx); + pw.print("Display #"); pw.println(activityDisplay.mDisplayId); + ArrayList<ActivityStack> stacks = activityDisplay.mStacks; + final int numStacks = stacks.size(); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + StringBuilder stackHeader = new StringBuilder(128); + stackHeader.append(" Stack #"); + stackHeader.append(stack.mStackId); + stackHeader.append(":"); + printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, + needSep, stackHeader.toString()); + printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, + !dumpAll, false, dumpPackage, true, + " Running activities (most recent first):", null); + + needSep = printed; + boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep, + " mPausingActivity: "); if (pr) { printed = true; - needSep = true; + needSep = false; } - printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage, - needSep, " mLastNoHistoryActivity: "); + pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep, + " mResumedActivity: "); + if (pr) { + printed = true; + needSep = false; + } + if (dumpAll) { + pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep, + " mLastPausedActivity: "); + if (pr) { + printed = true; + needSep = true; + } + printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage, + needSep, " mLastNoHistoryActivity: "); + } + needSep = printed; } - needSep = printed; } printed |= dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll, @@ -2568,7 +2739,9 @@ public final class ActivityStackSupervisor { } final void scheduleResumeTopActivities() { - mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG); + if (!mHandler.hasMessages(RESUME_TOP_ACTIVITY_MSG)) { + mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG); + } } void removeSleepTimeouts() { @@ -2581,6 +2754,101 @@ public final class ActivityStackSupervisor { mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT); } + @Override + public void onDisplayAdded(int displayId) { + mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_ADDED, displayId, 0)); + } + + @Override + public void onDisplayRemoved(int displayId) { + mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_REMOVED, displayId, 0)); + } + + @Override + public void onDisplayChanged(int displayId) { + mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_CHANGED, displayId, 0)); + } + + public void handleDisplayAddedLocked(int displayId) { + boolean newDisplay; + synchronized (mService) { + newDisplay = mActivityDisplays.get(displayId) == null; + if (newDisplay) { + ActivityDisplay activityDisplay = new ActivityDisplay(displayId); + mActivityDisplays.put(displayId, activityDisplay); + } + } + if (newDisplay) { + mWindowManager.onDisplayAdded(displayId); + } + } + + public void handleDisplayRemovedLocked(int displayId) { + synchronized (mService) { + ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); + if (activityDisplay != null) { + ArrayList<ActivityStack> stacks = activityDisplay.mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + stacks.get(stackNdx).mActivityContainer.detachLocked(); + } + mActivityDisplays.remove(displayId); + } + } + mWindowManager.onDisplayRemoved(displayId); + } + + public void handleDisplayChangedLocked(int displayId) { + synchronized (mService) { + ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); + if (activityDisplay != null) { + // TODO: Update the bounds. + } + } + mWindowManager.onDisplayChanged(displayId); + } + + StackInfo getStackInfo(ActivityStack stack) { + StackInfo info = new StackInfo(); + mWindowManager.getStackBounds(stack.mStackId, info.bounds); + info.displayId = Display.DEFAULT_DISPLAY; + info.stackId = stack.mStackId; + + ArrayList<TaskRecord> tasks = stack.getAllTasks(); + final int numTasks = tasks.size(); + int[] taskIds = new int[numTasks]; + String[] taskNames = new String[numTasks]; + for (int i = 0; i < numTasks; ++i) { + final TaskRecord task = tasks.get(i); + taskIds[i] = task.taskId; + taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString() + : task.realActivity != null ? task.realActivity.flattenToString() + : task.getTopActivity() != null ? task.getTopActivity().packageName + : "unknown"; + } + info.taskIds = taskIds; + info.taskNames = taskNames; + return info; + } + + StackInfo getStackInfoLocked(int stackId) { + ActivityStack stack = getStack(stackId); + if (stack != null) { + return getStackInfo(stack); + } + return null; + } + + ArrayList<StackInfo> getAllStackInfosLocked() { + ArrayList<StackInfo> list = new ArrayList<StackInfo>(); + for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) { + ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int ndx = stacks.size() - 1; ndx >= 0; --ndx) { + list.add(getStackInfo(stacks.get(ndx))); + } + } + return list; + } + private final class ActivityStackSupervisorHandler extends Handler { public ActivityStackSupervisorHandler(Looper looper) { @@ -2644,7 +2912,251 @@ public final class ActivityStackSupervisor { } } } break; + case HANDLE_DISPLAY_ADDED: { + handleDisplayAddedLocked(msg.arg1); + } break; + case HANDLE_DISPLAY_CHANGED: { + handleDisplayChangedLocked(msg.arg1); + } break; + case HANDLE_DISPLAY_REMOVED: { + handleDisplayRemovedLocked(msg.arg1); + } break; + } + } + } + + class ActivityContainer extends IActivityContainer.Stub { + final int mStackId; + final IActivityContainerCallback mCallback; + final ActivityStack mStack; + final ActivityRecord mParentActivity; + final String mIdString; + + /** Display this ActivityStack is currently on. Null if not attached to a Display. */ + ActivityDisplay mActivityDisplay; + + ActivityContainer(ActivityRecord parentActivity, int stackId, + IActivityContainerCallback callback) { + synchronized (mService) { + mStackId = stackId; + mStack = new ActivityStack(this); + mParentActivity = parentActivity; + mCallback = callback; + mIdString = "ActivtyContainer{" + mStackId + ", parent=" + mParentActivity + "}"; + if (DEBUG_STACK) Slog.d(TAG, "Creating " + this); + } + } + + void attachToDisplayLocked(ActivityDisplay activityDisplay) { + if (DEBUG_STACK) Slog.d(TAG, "attachToDisplayLocked: " + this + + " to display=" + activityDisplay); + mActivityDisplay = activityDisplay; + mStack.mDisplayId = activityDisplay.mDisplayId; + mStack.mStacks = activityDisplay.mStacks; + + activityDisplay.attachActivities(mStack); + mWindowManager.attachStack(mStackId, activityDisplay.mDisplayId); + } + + @Override + public void attachToDisplay(int displayId) { + synchronized (mService) { + ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); + if (activityDisplay == null) { + return; + } + attachToDisplayLocked(activityDisplay); } } + + @Override + public int getDisplayId() { + if (mActivityDisplay != null) { + return mActivityDisplay.mDisplayId; + } + return -1; + } + + @Override + public boolean injectEvent(InputEvent event) { + final long origId = Binder.clearCallingIdentity(); + try { + if (mActivityDisplay != null) { + return mInputManagerInternal.injectInputEvent(event, + mActivityDisplay.mDisplayId, + InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); + } + return false; + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + private void detachLocked() { + if (DEBUG_STACK) Slog.d(TAG, "detachLocked: " + this + " from display=" + + mActivityDisplay + " Callers=" + Debug.getCallers(2)); + if (mActivityDisplay != null) { + mActivityDisplay.detachActivitiesLocked(mStack); + mActivityDisplay = null; + mStack.mDisplayId = -1; + mStack.mStacks = null; + mWindowManager.detachStack(mStackId); + } + } + + @Override + public void detachFromDisplay() { + synchronized (mService) { + detachLocked(); + } + } + + @Override + public final int startActivity(Intent intent) { + mService.enforceNotIsolatedCaller("ActivityContainer.startActivity"); + int userId = mService.handleIncomingUser(Binder.getCallingPid(), + Binder.getCallingUid(), mCurrentUser, false, true, "ActivityContainer", null); + // TODO: Switch to user app stacks here. + String mimeType = intent.getType(); + if (mimeType == null && intent.getData() != null + && "content".equals(intent.getData().getScheme())) { + mimeType = mService.getProviderMimeType(intent.getData(), userId); + } + return startActivityMayWait(null, -1, null, intent, mimeType, null, null, 0, 0, null, + null, null, null, null, userId, this); + } + + @Override + public final int startActivityIntentSender(IIntentSender intentSender) { + mService.enforceNotIsolatedCaller("ActivityContainer.startActivityIntentSender"); + + if (!(intentSender instanceof PendingIntentRecord)) { + throw new IllegalArgumentException("Bad PendingIntent object"); + } + + return ((PendingIntentRecord)intentSender).sendInner(0, null, null, null, null, null, + null, 0, 0, 0, null, this); + } + + @Override + public IBinder asBinder() { + return this; + } + + @Override + public void attachToSurface(Surface surface, int width, int height, int density) { + mService.enforceNotIsolatedCaller("ActivityContainer.attachToSurface"); + + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mService) { + ActivityDisplay activityDisplay = + new ActivityDisplay(surface, width, height, density); + mActivityDisplays.put(activityDisplay.mDisplayId, activityDisplay); + attachToDisplayLocked(activityDisplay); + mStack.resumeTopActivityLocked(null); + } + if (DEBUG_STACK) Slog.d(TAG, "attachToSurface: " + this + " to display=" + + mActivityDisplay); + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + ActivityStackSupervisor getOuter() { + return ActivityStackSupervisor.this; + } + + boolean isAttached() { + return mActivityDisplay != null; + } + + void getBounds(Point outBounds) { + if (mActivityDisplay != null) { + mActivityDisplay.getBounds(outBounds); + } else { + outBounds.set(0, 0); + } + } + + @Override + public String toString() { + return mIdString + (mActivityDisplay == null ? "N" : "A"); + } + } + + /** Exactly one of these classes per Display in the system. Capable of holding zero or more + * attached {@link ActivityStack}s */ + final class ActivityDisplay { + /** Actual Display this object tracks. */ + int mDisplayId; + Display mDisplay; + DisplayInfo mDisplayInfo = new DisplayInfo(); + Surface mSurface; + + /** All of the stacks on this display. Order matters, topmost stack is in front of all other + * stacks, bottommost behind. Accessed directly by ActivityManager package classes */ + final ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>(); + + /** If this display is for an ActivityView then the VirtualDisplay created for it is stored + * here. */ + VirtualDisplay mVirtualDisplay; + + ActivityDisplay(int displayId) { + init(mDisplayManager.getDisplay(displayId)); + } + + ActivityDisplay(Surface surface, int width, int height, int density) { + DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance(); + long ident = Binder.clearCallingIdentity(); + try { + mVirtualDisplay = dm.createVirtualDisplay(mService.mContext, + VIRTUAL_DISPLAY_BASE_NAME, width, height, density, surface, + DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC | + DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY); + } finally { + Binder.restoreCallingIdentity(ident); + } + + init(mVirtualDisplay.getDisplay()); + mSurface = surface; + + mWindowManager.handleDisplayAdded(mDisplayId); + } + + private void init(Display display) { + mDisplay = display; + mDisplayId = display.getDisplayId(); + mDisplay.getDisplayInfo(mDisplayInfo); + } + + void attachActivities(ActivityStack stack) { + if (DEBUG_STACK) Slog.v(TAG, "attachActivities: attaching " + stack + " to displayId=" + + mDisplayId); + mStacks.add(stack); + } + + void detachActivitiesLocked(ActivityStack stack) { + if (DEBUG_STACK) Slog.v(TAG, "detachActivitiesLocked: detaching " + stack + + " from displayId=" + mDisplayId); + mStacks.remove(stack); + if (mStacks.isEmpty() && mVirtualDisplay != null) { + mVirtualDisplay.release(); + mVirtualDisplay = null; + } + mSurface.release(); + } + + void getBounds(Point bounds) { + mDisplay.getDisplayInfo(mDisplayInfo); + bounds.x = mDisplayInfo.appWidth; + bounds.y = mDisplayInfo.appHeight; + } + + @Override + public String toString() { + return "ActivityDisplay={" + mDisplayId + (mVirtualDisplay == null ? "" : "V") + + " numStacks=" + mStacks.size() + "}"; + } } } diff --git a/services/java/com/android/server/am/AppBindRecord.java b/services/core/java/com/android/server/am/AppBindRecord.java index 06265fd6856d..06265fd6856d 100644 --- a/services/java/com/android/server/am/AppBindRecord.java +++ b/services/core/java/com/android/server/am/AppBindRecord.java diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java index 0ba62c53dcd9..0ba62c53dcd9 100644 --- a/services/java/com/android/server/am/AppErrorDialog.java +++ b/services/core/java/com/android/server/am/AppErrorDialog.java diff --git a/services/java/com/android/server/am/AppErrorResult.java b/services/core/java/com/android/server/am/AppErrorResult.java index c6a5720b537e..c6a5720b537e 100644 --- a/services/java/com/android/server/am/AppErrorResult.java +++ b/services/core/java/com/android/server/am/AppErrorResult.java diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java index f4c166421c35..f4c166421c35 100644 --- a/services/java/com/android/server/am/AppNotRespondingDialog.java +++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java diff --git a/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java b/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java index 27865a88da99..27865a88da99 100644 --- a/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java +++ b/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java diff --git a/services/java/com/android/server/am/BackupRecord.java b/services/core/java/com/android/server/am/BackupRecord.java index 5fa7e6a37133..5fa7e6a37133 100644 --- a/services/java/com/android/server/am/BackupRecord.java +++ b/services/core/java/com/android/server/am/BackupRecord.java diff --git a/services/java/com/android/server/am/BaseErrorDialog.java b/services/core/java/com/android/server/am/BaseErrorDialog.java index 6ede8f865065..6ede8f865065 100644 --- a/services/java/com/android/server/am/BaseErrorDialog.java +++ b/services/core/java/com/android/server/am/BaseErrorDialog.java diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 2d596788a829..ff06513fb858 100644 --- a/services/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -24,6 +24,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.BatteryStats; import android.os.Binder; +import android.os.Handler; import android.os.IBinder; import android.os.Parcel; import android.os.Process; @@ -54,8 +55,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub { private boolean mBluetoothPendingStats; private BluetoothHeadset mBluetoothHeadset; - BatteryStatsService(String filename) { - mStats = new BatteryStatsImpl(filename); + BatteryStatsService(String filename, Handler handler) { + mStats = new BatteryStatsImpl(filename, handler); } public void publish(Context context) { diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/core/java/com/android/server/am/BroadcastFilter.java index 986b8ea3c41f..986b8ea3c41f 100644 --- a/services/java/com/android/server/am/BroadcastFilter.java +++ b/services/core/java/com/android/server/am/BroadcastFilter.java diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index bfb667f8aca0..aef9e5c38e6f 100644 --- a/services/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -33,6 +33,7 @@ import android.content.pm.ResolveInfo; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.Message; import android.os.Process; import android.os.RemoteException; @@ -132,7 +133,14 @@ public final class BroadcastQueue { static final int BROADCAST_INTENT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG; static final int BROADCAST_TIMEOUT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1; - final Handler mHandler = new Handler() { + final BroadcastHandler mHandler; + + private final class BroadcastHandler extends Handler { + public BroadcastHandler(Looper looper) { + super(looper, null, true); + } + + @Override public void handleMessage(Message msg) { switch (msg.what) { case BROADCAST_INTENT_MSG: { @@ -164,9 +172,10 @@ public final class BroadcastQueue { } } - BroadcastQueue(ActivityManagerService service, String name, long timeoutPeriod, - boolean allowDelayBehindServices) { + BroadcastQueue(ActivityManagerService service, Handler handler, + String name, long timeoutPeriod, boolean allowDelayBehindServices) { mService = service; + mHandler = new BroadcastHandler(handler.getLooper()); mQueueName = name; mTimeoutPeriod = timeoutPeriod; mDelayBehindServices = allowDelayBehindServices; diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java index b2cfd7a87242..b2cfd7a87242 100644 --- a/services/java/com/android/server/am/BroadcastRecord.java +++ b/services/core/java/com/android/server/am/BroadcastRecord.java diff --git a/services/java/com/android/server/am/CompatModeDialog.java b/services/core/java/com/android/server/am/CompatModeDialog.java index 202cc7cad79d..202cc7cad79d 100644 --- a/services/java/com/android/server/am/CompatModeDialog.java +++ b/services/core/java/com/android/server/am/CompatModeDialog.java diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java index 4d5577bdbd69..ec500c2ee154 100644 --- a/services/java/com/android/server/am/CompatModePackages.java +++ b/services/core/java/com/android/server/am/CompatModePackages.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.android.server.am; import java.io.File; @@ -19,6 +35,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.res.CompatibilityInfo; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.util.AtomicFile; @@ -41,22 +58,27 @@ public final class CompatModePackages { private static final int MSG_WRITE = ActivityManagerService.FIRST_COMPAT_MODE_MSG; - private final Handler mHandler = new Handler() { - @Override public void handleMessage(Message msg) { + private final CompatHandler mHandler; + + private final class CompatHandler extends Handler { + public CompatHandler(Looper looper) { + super(looper, null, true); + } + + @Override + public void handleMessage(Message msg) { switch (msg.what) { case MSG_WRITE: saveCompatModes(); break; - default: - super.handleMessage(msg); - break; } } }; - public CompatModePackages(ActivityManagerService service, File systemDir) { + public CompatModePackages(ActivityManagerService service, File systemDir, Handler handler) { mService = service; mFile = new AtomicFile(new File(systemDir, "packages-compat.xml")); + mHandler = new CompatHandler(handler.getLooper()); FileInputStream fis = null; try { diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java index 423e540229db..423e540229db 100644 --- a/services/java/com/android/server/am/ConnectionRecord.java +++ b/services/core/java/com/android/server/am/ConnectionRecord.java diff --git a/services/java/com/android/server/am/ContentProviderConnection.java b/services/core/java/com/android/server/am/ContentProviderConnection.java index f2c9e2fd2297..f2c9e2fd2297 100644 --- a/services/java/com/android/server/am/ContentProviderConnection.java +++ b/services/core/java/com/android/server/am/ContentProviderConnection.java diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/core/java/com/android/server/am/ContentProviderRecord.java index 646b7d2994de..646b7d2994de 100644 --- a/services/java/com/android/server/am/ContentProviderRecord.java +++ b/services/core/java/com/android/server/am/ContentProviderRecord.java diff --git a/services/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index 10ea67c34465..10ea67c34465 100644 --- a/services/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java diff --git a/services/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags index d3cc56b53028..d3cc56b53028 100644 --- a/services/java/com/android/server/am/EventLogTags.logtags +++ b/services/core/java/com/android/server/am/EventLogTags.logtags diff --git a/services/java/com/android/server/am/FactoryErrorDialog.java b/services/core/java/com/android/server/am/FactoryErrorDialog.java index f4632c135dfc..f4632c135dfc 100644 --- a/services/java/com/android/server/am/FactoryErrorDialog.java +++ b/services/core/java/com/android/server/am/FactoryErrorDialog.java diff --git a/services/java/com/android/server/am/IntentBindRecord.java b/services/core/java/com/android/server/am/IntentBindRecord.java index 21cf266c62b1..21cf266c62b1 100644 --- a/services/java/com/android/server/am/IntentBindRecord.java +++ b/services/core/java/com/android/server/am/IntentBindRecord.java diff --git a/services/java/com/android/server/am/LaunchWarningWindow.java b/services/core/java/com/android/server/am/LaunchWarningWindow.java index 30c306655af0..30c306655af0 100644 --- a/services/java/com/android/server/am/LaunchWarningWindow.java +++ b/services/core/java/com/android/server/am/LaunchWarningWindow.java diff --git a/services/java/com/android/server/am/NativeCrashListener.java b/services/core/java/com/android/server/am/NativeCrashListener.java index 2c7f1f13098b..b12843bcf678 100644 --- a/services/java/com/android/server/am/NativeCrashListener.java +++ b/services/core/java/com/android/server/am/NativeCrashListener.java @@ -95,8 +95,8 @@ final class NativeCrashListener extends Thread { * Daemon thread that accept()s incoming domain socket connections from debuggerd * and processes the crash dump that is passed through. */ - NativeCrashListener() { - mAm = ActivityManagerService.self(); + NativeCrashListener(ActivityManagerService am) { + mAm = am; } @Override diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java index 17f24a928b90..00fa21658e51 100644 --- a/services/java/com/android/server/am/PendingIntentRecord.java +++ b/services/core/java/com/android/server/am/PendingIntentRecord.java @@ -17,6 +17,7 @@ package com.android.server.am; import android.app.ActivityManager; +import android.app.IActivityContainer; import android.content.IIntentSender; import android.content.IIntentReceiver; import android.app.PendingIntent; @@ -190,13 +191,13 @@ final class PendingIntentRecord extends IIntentSender.Stub { public int send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission) { return sendInner(code, intent, resolvedType, finishedReceiver, - requiredPermission, null, null, 0, 0, 0, null); + requiredPermission, null, null, 0, 0, 0, null, null); } int sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, String resultWho, int requestCode, - int flagsMask, int flagsValues, Bundle options) { + int flagsMask, int flagsValues, Bundle options, IActivityContainer container) { synchronized(owner) { if (!canceled) { sent = true; @@ -251,7 +252,7 @@ final class PendingIntentRecord extends IIntentSender.Stub { } else { owner.startActivityInPackage(uid, key.packageName, finalIntent, resolvedType, resultTo, resultWho, requestCode, 0, - options, userId); + options, userId, container); } } catch (RuntimeException e) { Slog.w(ActivityManagerService.TAG, @@ -302,7 +303,8 @@ final class PendingIntentRecord extends IIntentSender.Stub { } return ActivityManager.START_CANCELED; } - + + @Override protected void finalize() throws Throwable { try { if (!canceled) { diff --git a/services/java/com/android/server/am/PendingThumbnailsRecord.java b/services/core/java/com/android/server/am/PendingThumbnailsRecord.java index e4eb4d04c155..e4eb4d04c155 100644 --- a/services/java/com/android/server/am/PendingThumbnailsRecord.java +++ b/services/core/java/com/android/server/am/PendingThumbnailsRecord.java diff --git a/services/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index d3777c7ae134..f5920c8db355 100644 --- a/services/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -18,6 +18,8 @@ package com.android.server.am; import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; import android.app.ActivityManager; import com.android.internal.util.MemInfoReader; @@ -26,6 +28,8 @@ import com.android.server.wm.WindowManagerService; import android.content.res.Resources; import android.graphics.Point; import android.os.SystemProperties; +import android.net.LocalSocketAddress; +import android.net.LocalSocket; import android.util.Slog; import android.view.Display; @@ -141,6 +145,16 @@ final class ProcessList { // Threshold of number of cached+empty where we consider memory critical. static final int TRIM_LOW_THRESHOLD = 5; + // Low Memory Killer Daemon command codes. + // These must be kept in sync with the definitions in lmkd.c + // + // LMK_TARGET <minfree> <minkillprio> ... (up to 6 pairs) + // LMK_PROCPRIO <pid> <prio> + // LMK_PROCREMOVE <pid> + static final byte LMK_TARGET = 0; + static final byte LMK_PROCPRIO = 1; + static final byte LMK_PROCREMOVE = 2; + // These are the various interesting memory levels that we will give to // the OOM killer. Note that the OOM killer only supports 6 slots, so we // can't give it a different value for every possible kind of process. @@ -150,18 +164,18 @@ final class ProcessList { }; // These are the low-end OOM level limits. This is appropriate for an // HVGA or smaller phone with less than 512MB. Values are in KB. - private final long[] mOomMinFreeLow = new long[] { + private final int[] mOomMinFreeLow = new int[] { 8192, 12288, 16384, 24576, 28672, 32768 }; // These are the high-end OOM level limits. This is appropriate for a // 1280x800 or larger screen with around 1GB RAM. Values are in KB. - private final long[] mOomMinFreeHigh = new long[] { + private final int[] mOomMinFreeHigh = new int[] { 49152, 61440, 73728, 86016, 98304, 122880 }; // The actual OOM killer memory levels we are using. - private final long[] mOomMinFree = new long[mOomAdj.length]; + private final int[] mOomMinFree = new int[mOomAdj.length]; private final long mTotalMemMb; @@ -169,6 +183,9 @@ final class ProcessList { private boolean mHaveDisplaySize; + private static LocalSocket sLmkdSocket; + private static OutputStream sLmkdOutputStream; + ProcessList() { MemInfoReader minfo = new MemInfoReader(); minfo.readMemInfo(); @@ -202,9 +219,6 @@ final class ProcessList { + " dh=" + displayHeight); } - StringBuilder adjString = new StringBuilder(); - StringBuilder memString = new StringBuilder(); - float scale = scaleMem > scaleDisp ? scaleMem : scaleDisp; if (scale < 0) scale = 0; else if (scale > 1) scale = 1; @@ -217,20 +231,20 @@ final class ProcessList { } for (int i=0; i<mOomAdj.length; i++) { - long low = mOomMinFreeLow[i]; - long high = mOomMinFreeHigh[i]; - mOomMinFree[i] = (long)(low + ((high-low)*scale)); + int low = mOomMinFreeLow[i]; + int high = mOomMinFreeHigh[i]; + mOomMinFree[i] = (int)(low + ((high-low)*scale)); } if (minfree_abs >= 0) { for (int i=0; i<mOomAdj.length; i++) { - mOomMinFree[i] = (long)((float)minfree_abs * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]); + mOomMinFree[i] = (int)((float)minfree_abs * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]); } } if (minfree_adj != 0) { for (int i=0; i<mOomAdj.length; i++) { - mOomMinFree[i] += (long)((float)minfree_adj * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]); + mOomMinFree[i] += (int)((float)minfree_adj * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]); if (mOomMinFree[i] < 0) { mOomMinFree[i] = 0; } @@ -242,15 +256,6 @@ final class ProcessList { // before killing background processes. mCachedRestoreLevel = (getMemLevel(ProcessList.CACHED_APP_MAX_ADJ)/1024) / 3; - for (int i=0; i<mOomAdj.length; i++) { - if (i > 0) { - adjString.append(','); - memString.append(','); - } - adjString.append(mOomAdj[i]); - memString.append((mOomMinFree[i]*1024)/PAGE_SIZE); - } - // Ask the kernel to try to keep enough memory free to allocate 3 full // screen 32bpp buffers without entering direct reclaim. int reserve = displayWidth * displayHeight * 4 * 3 / 1024; @@ -268,10 +273,15 @@ final class ProcessList { } } - //Slog.i("XXXXXXX", "******************************* MINFREE: " + memString); if (write) { - writeFile("/sys/module/lowmemorykiller/parameters/adj", adjString.toString()); - writeFile("/sys/module/lowmemorykiller/parameters/minfree", memString.toString()); + ByteBuffer buf = ByteBuffer.allocate(4 * (2*mOomAdj.length + 1)); + buf.putInt(LMK_TARGET); + for (int i=0; i<mOomAdj.length; i++) { + buf.putInt((mOomMinFree[i]*1024)/PAGE_SIZE); + buf.putInt(mOomAdj[i]); + } + + writeLmkd(buf); SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve)); } // GB: 2048,3072,4096,6144,7168,8192 @@ -506,19 +516,78 @@ final class ProcessList { return mCachedRestoreLevel; } - private void writeFile(String path, String data) { - FileOutputStream fos = null; + /** + * Set the out-of-memory badness adjustment for a process. + * + * @param pid The process identifier to set. + * @param amt Adjustment value -- lmkd allows -16 to +15. + * + * {@hide} + */ + public static final void setOomAdj(int pid, int amt) { + if (amt == UNKNOWN_ADJ) + return; + + ByteBuffer buf = ByteBuffer.allocate(4 * 3); + buf.putInt(LMK_PROCPRIO); + buf.putInt(pid); + buf.putInt(amt); + writeLmkd(buf); + } + + /* + * {@hide} + */ + public static final void remove(int pid) { + ByteBuffer buf = ByteBuffer.allocate(4 * 2); + buf.putInt(LMK_PROCREMOVE); + buf.putInt(pid); + writeLmkd(buf); + } + + private static boolean openLmkdSocket() { try { - fos = new FileOutputStream(path); - fos.write(data.getBytes()); - } catch (IOException e) { - Slog.w(ActivityManagerService.TAG, "Unable to write " + path); - } finally { - if (fos != null) { + sLmkdSocket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET); + sLmkdSocket.connect( + new LocalSocketAddress("lmkd", + LocalSocketAddress.Namespace.RESERVED)); + sLmkdOutputStream = sLmkdSocket.getOutputStream(); + } catch (IOException ex) { + Slog.w(ActivityManagerService.TAG, + "lowmemorykiller daemon socket open failed"); + sLmkdSocket = null; + return false; + } + + return true; + } + + private static void writeLmkd(ByteBuffer buf) { + + for (int i = 0; i < 3; i++) { + if (sLmkdSocket == null) { + if (openLmkdSocket() == false) { + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + } + continue; + } + } + + try { + sLmkdOutputStream.write(buf.array(), 0, buf.position()); + return; + } catch (IOException ex) { + Slog.w(ActivityManagerService.TAG, + "Error writing to lowmemorykiller socket"); + try { - fos.close(); - } catch (IOException e) { + sLmkdSocket.close(); + } catch (IOException ex2) { } + + sLmkdSocket = null; } } } diff --git a/services/java/com/android/server/am/ProcessMemInfo.java b/services/core/java/com/android/server/am/ProcessMemInfo.java index c94694e7c4b1..c94694e7c4b1 100644 --- a/services/java/com/android/server/am/ProcessMemInfo.java +++ b/services/core/java/com/android/server/am/ProcessMemInfo.java diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 217a8d6159a1..217a8d6159a1 100644 --- a/services/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java index e05fcda70ff0..e05fcda70ff0 100644 --- a/services/java/com/android/server/am/ProcessStatsService.java +++ b/services/core/java/com/android/server/am/ProcessStatsService.java diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/core/java/com/android/server/am/ProviderMap.java index 7da8c48dea35..7da8c48dea35 100644 --- a/services/java/com/android/server/am/ProviderMap.java +++ b/services/core/java/com/android/server/am/ProviderMap.java diff --git a/services/java/com/android/server/am/ReceiverList.java b/services/core/java/com/android/server/am/ReceiverList.java index fa8c1dfc4fda..fa8c1dfc4fda 100644 --- a/services/java/com/android/server/am/ReceiverList.java +++ b/services/core/java/com/android/server/am/ReceiverList.java diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index 80e6e9497ece..cb04835dce53 100644 --- a/services/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -18,7 +18,8 @@ package com.android.server.am; import com.android.internal.app.ProcessStats; import com.android.internal.os.BatteryStatsImpl; -import com.android.server.NotificationManagerService; +import com.android.server.LocalServices; +import com.android.server.notification.NotificationManagerInternal; import android.app.INotificationManager; import android.app.Notification; @@ -427,8 +428,8 @@ final class ServiceRecord extends Binder { final Notification localForegroundNoti = foregroundNoti; ams.mHandler.post(new Runnable() { public void run() { - NotificationManagerService nm = - (NotificationManagerService) NotificationManager.getService(); + NotificationManagerInternal nm = LocalServices.getService( + NotificationManagerInternal.class); if (nm == null) { return; } @@ -479,7 +480,7 @@ final class ServiceRecord extends Binder { throw new RuntimeException("icon must be non-zero"); } int[] outId = new int[1]; - nm.enqueueNotificationInternal(localPackageName, localPackageName, + nm.enqueueNotification(localPackageName, localPackageName, appUid, appPid, null, localForegroundId, localForegroundNoti, outId, userId); } catch (RuntimeException e) { diff --git a/services/java/com/android/server/am/StrictModeViolationDialog.java b/services/core/java/com/android/server/am/StrictModeViolationDialog.java index fda1ec130980..fda1ec130980 100644 --- a/services/java/com/android/server/am/StrictModeViolationDialog.java +++ b/services/core/java/com/android/server/am/StrictModeViolationDialog.java diff --git a/services/java/com/android/server/am/TaskAccessInfo.java b/services/core/java/com/android/server/am/TaskAccessInfo.java index 50aeec1172ca..50aeec1172ca 100644 --- a/services/java/com/android/server/am/TaskAccessInfo.java +++ b/services/core/java/com/android/server/am/TaskAccessInfo.java diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 3d568ffb8e07..9740812e654c 100644 --- a/services/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -60,7 +60,8 @@ final class TaskRecord extends ThumbnailHolder { /** Takes on same set of values as ActivityRecord.mActivityType */ private int mTaskType; - /** Launch the home activity when leaving this task. */ + /** Launch the home activity when leaving this task. Will be false for tasks that are not on + * Display.DEFAULT_DISPLAY. */ boolean mOnTopOfHome = false; TaskRecord(int _taskId, ActivityInfo info, Intent _intent) { @@ -159,18 +160,33 @@ final class TaskRecord extends ThumbnailHolder { return null; } + /** Call after activity movement or finish to make sure that frontOfTask is set correctly */ + final void setFrontOfTask() { + boolean foundFront = false; + final int numActivities = mActivities.size(); + for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) { + final ActivityRecord r = mActivities.get(activityNdx); + if (foundFront || r.finishing) { + r.frontOfTask = false; + } else { + r.frontOfTask = true; + // Set frontOfTask false for every following activity. + foundFront = true; + } + } + } + /** - * Reorder the history stack so that the activity at the given index is - * brought to the front. + * Reorder the history stack so that the passed activity is brought to the front. */ final void moveActivityToFrontLocked(ActivityRecord newTop) { if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing and adding activity " + newTop + " to stack at top", new RuntimeException("here").fillInStackTrace()); - getTopActivity().frontOfTask = false; mActivities.remove(newTop); mActivities.add(newTop); - newTop.frontOfTask = true; + + setFrontOfTask(); } void addActivityAtBottom(ActivityRecord r) { diff --git a/services/java/com/android/server/am/ThumbnailHolder.java b/services/core/java/com/android/server/am/ThumbnailHolder.java index a6974f56356d..a6974f56356d 100644 --- a/services/java/com/android/server/am/ThumbnailHolder.java +++ b/services/core/java/com/android/server/am/ThumbnailHolder.java diff --git a/services/java/com/android/server/am/UriPermission.java b/services/core/java/com/android/server/am/UriPermission.java index 1f12b74432a3..1f12b74432a3 100644 --- a/services/java/com/android/server/am/UriPermission.java +++ b/services/core/java/com/android/server/am/UriPermission.java diff --git a/services/java/com/android/server/am/UriPermissionOwner.java b/services/core/java/com/android/server/am/UriPermissionOwner.java index 7bbd3bcc2eb9..7bbd3bcc2eb9 100644 --- a/services/java/com/android/server/am/UriPermissionOwner.java +++ b/services/core/java/com/android/server/am/UriPermissionOwner.java diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/core/java/com/android/server/am/UsageStatsService.java index 09cb344531c3..09cb344531c3 100644 --- a/services/java/com/android/server/am/UsageStatsService.java +++ b/services/core/java/com/android/server/am/UsageStatsService.java diff --git a/services/java/com/android/server/am/UserStartedState.java b/services/core/java/com/android/server/am/UserStartedState.java index d3e73d5222a4..d3e73d5222a4 100644 --- a/services/java/com/android/server/am/UserStartedState.java +++ b/services/core/java/com/android/server/am/UserStartedState.java diff --git a/services/java/com/android/server/am/package.html b/services/core/java/com/android/server/am/package.html index c9f96a66ab3b..c9f96a66ab3b 100644 --- a/services/java/com/android/server/am/package.html +++ b/services/core/java/com/android/server/am/package.html diff --git a/services/java/com/android/server/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java index 069ae23f5596..6aa596d9d78e 100644 --- a/services/java/com/android/server/ClipboardService.java +++ b/services/core/java/com/android/server/clipboard/ClipboardService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.clipboard; import android.app.ActivityManagerNative; import android.app.AppGlobals; diff --git a/services/java/com/android/server/connectivity/DataConnectionStats.java b/services/core/java/com/android/server/connectivity/DataConnectionStats.java index 227ab2341012..227ab2341012 100644 --- a/services/java/com/android/server/connectivity/DataConnectionStats.java +++ b/services/core/java/com/android/server/connectivity/DataConnectionStats.java diff --git a/services/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index a15d678520bc..a15d678520bc 100644 --- a/services/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java diff --git a/services/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java index 7786fe6e4254..7786fe6e4254 100644 --- a/services/java/com/android/server/connectivity/PacManager.java +++ b/services/core/java/com/android/server/connectivity/PacManager.java diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index adf1dfc10ef5..adf1dfc10ef5 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 2ca2cc507f2e..2ca2cc507f2e 100644 --- a/services/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java diff --git a/services/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index 023bf2b20614..023bf2b20614 100644 --- a/services/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java diff --git a/services/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index 71d8d9911f9a..71d8d9911f9a 100644 --- a/services/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java diff --git a/services/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java index 485674782aeb..485674782aeb 100644 --- a/services/java/com/android/server/content/SyncOperation.java +++ b/services/core/java/com/android/server/content/SyncOperation.java diff --git a/services/java/com/android/server/content/SyncQueue.java b/services/core/java/com/android/server/content/SyncQueue.java index 6f3fe6e1d37b..6f3fe6e1d37b 100644 --- a/services/java/com/android/server/content/SyncQueue.java +++ b/services/core/java/com/android/server/content/SyncQueue.java diff --git a/services/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java index 124bc60df10c..124bc60df10c 100644 --- a/services/java/com/android/server/content/SyncStorageEngine.java +++ b/services/core/java/com/android/server/content/SyncStorageEngine.java diff --git a/services/java/com/android/server/display/DisplayAdapter.java b/services/core/java/com/android/server/display/DisplayAdapter.java index b411a0db7184..b411a0db7184 100644 --- a/services/java/com/android/server/display/DisplayAdapter.java +++ b/services/core/java/com/android/server/display/DisplayAdapter.java diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java index 41611475d9c8..9ec1122b7859 100644 --- a/services/java/com/android/server/display/DisplayDevice.java +++ b/services/core/java/com/android/server/display/DisplayDevice.java @@ -17,6 +17,7 @@ package com.android.server.display; import android.graphics.Rect; +import android.hardware.display.DisplayViewport; import android.os.IBinder; import android.view.Surface; import android.view.SurfaceControl; diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java index 11c5d879b498..75f1f53f79db 100644 --- a/services/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java @@ -16,6 +16,7 @@ package com.android.server.display; +import android.hardware.display.DisplayViewport; import android.util.DisplayMetrics; import android.view.Display; import android.view.Surface; @@ -63,6 +64,7 @@ final class DisplayDeviceInfo { /** * Flag: Indicates that the display device is owned by a particular application * and that no other application should be able to interact with it. + * Should typically be used together with {@link #FLAG_OWN_CONTENT_ONLY}. */ public static final int FLAG_PRIVATE = 1 << 4; @@ -78,6 +80,12 @@ final class DisplayDeviceInfo { public static final int FLAG_PRESENTATION = 1 << 6; /** + * Flag: Only show this display's own content; do not mirror + * the content of another display. + */ + public static final int FLAG_OWN_CONTENT_ONLY = 1 << 7; + + /** * Touch attachment: Display does not receive touch. */ public static final int TOUCH_NONE = 0; @@ -297,6 +305,9 @@ final class DisplayDeviceInfo { if ((flags & FLAG_PRESENTATION) != 0) { msg.append(", FLAG_PRESENTATION"); } + if ((flags & FLAG_OWN_CONTENT_ONLY) != 0) { + msg.append(", FLAG_OWN_CONTENT_ONLY"); + } return msg.toString(); } } diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index bcb677fa455f..6be6405daa4d 100644 --- a/services/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -23,14 +23,20 @@ import android.content.Context; import android.content.pm.PackageManager; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; +import android.hardware.display.DisplayManagerInternal; +import android.hardware.display.DisplayViewport; +import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener; import android.hardware.display.IDisplayManager; import android.hardware.display.IDisplayManagerCallback; import android.hardware.display.WifiDisplayStatus; +import android.hardware.input.InputManagerInternal; import android.os.Binder; import android.os.Handler; import android.os.IBinder; +import android.os.IBinder.DeathRecipient; import android.os.Looper; import android.os.Message; +import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; @@ -41,7 +47,11 @@ import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; +import android.view.WindowManagerInternal; +import com.android.server.DisplayThread; +import com.android.server.LocalServices; +import com.android.server.SystemService; import com.android.server.UiThread; import java.io.FileDescriptor; @@ -93,7 +103,7 @@ import java.util.concurrent.CopyOnWriteArrayList; * avoid this by making all potentially reentrant out-calls asynchronous. * </p> */ -public final class DisplayManagerService extends IDisplayManager.Stub { +public final class DisplayManagerService extends SystemService { private static final String TAG = "DisplayManagerService"; private static final boolean DEBUG = false; @@ -102,7 +112,6 @@ public final class DisplayManagerService extends IDisplayManager.Stub { // Otherwise WFD is enabled according to the value of config_enableWifiDisplay. private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable"; - private static final String SYSTEM_HEADLESS = "ro.config.headless"; private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000; private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1; @@ -116,12 +125,11 @@ public final class DisplayManagerService extends IDisplayManager.Stub { private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2; private final Context mContext; - private final boolean mHeadless; private final DisplayManagerHandler mHandler; private final Handler mUiHandler; private final DisplayAdapterListener mDisplayAdapterListener; - private WindowManagerFuncs mWindowManagerFuncs; - private InputManagerFuncs mInputManagerFuncs; + private WindowManagerInternal mWindowManagerInternal; + private InputManagerInternal mInputManagerInternal; // The synchronization root for the display manager. // This lock guards most of the display manager's state. @@ -200,59 +208,52 @@ public final class DisplayManagerService extends IDisplayManager.Stub { private final DisplayViewport mTempDefaultViewport = new DisplayViewport(); private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport(); - public DisplayManagerService(Context context, Handler mainHandler) { + public DisplayManagerService(Context context) { + super(context); mContext = context; - mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1"); - - mHandler = new DisplayManagerHandler(mainHandler.getLooper()); + mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper()); mUiHandler = UiThread.getHandler(); mDisplayAdapterListener = new DisplayAdapterListener(); mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false); + } + @Override + public void onStart() { mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER); + + publishBinderService(Context.DISPLAY_SERVICE, new BinderService(), + true /*allowIsolated*/); + publishLocalService(DisplayManagerInternal.class, new LocalService()); } - /** - * Pauses the boot process to wait for the first display to be initialized. - */ - public boolean waitForDefaultDisplay() { - synchronized (mSyncRoot) { - long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT; - while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) { - long delay = timeout - SystemClock.uptimeMillis(); - if (delay <= 0) { - return false; - } - if (DEBUG) { - Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay); - } - try { - mSyncRoot.wait(delay); - } catch (InterruptedException ex) { + @Override + public void onBootPhase(int phase) { + if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) { + synchronized (mSyncRoot) { + long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT; + while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) { + long delay = timeout - SystemClock.uptimeMillis(); + if (delay <= 0) { + throw new RuntimeException("Timeout waiting for default display " + + "to be initialized."); + } + if (DEBUG) { + Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay); + } + try { + mSyncRoot.wait(delay); + } catch (InterruptedException ex) { + } } } } - return true; } - /** - * Called during initialization to associate the display manager with the - * window manager. - */ - public void setWindowManager(WindowManagerFuncs windowManagerFuncs) { + // TODO: Use dependencies or a boot phase + public void windowManagerAndInputReady() { synchronized (mSyncRoot) { - mWindowManagerFuncs = windowManagerFuncs; - scheduleTraversalLocked(false); - } - } - - /** - * Called during initialization to associate the display manager with the - * input manager. - */ - public void setInputManager(InputManagerFuncs inputManagerFuncs) { - synchronized (mSyncRoot) { - mInputManagerFuncs = inputManagerFuncs; + mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); + mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); scheduleTraversalLocked(false); } } @@ -269,59 +270,19 @@ public final class DisplayManagerService extends IDisplayManager.Stub { mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS); } - /** - * Returns true if the device is headless. - * - * @return True if the device is headless. - */ - public boolean isHeadless() { - return mHeadless; - } - - /** - * Registers a display transaction listener to provide the client a chance to - * update its surfaces within the same transaction as any display layout updates. - * - * @param listener The listener to register. - */ - public void registerDisplayTransactionListener(DisplayTransactionListener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } - + private void registerDisplayTransactionListenerInternal( + DisplayTransactionListener listener) { // List is self-synchronized copy-on-write. mDisplayTransactionListeners.add(listener); } - /** - * Unregisters a display transaction listener to provide the client a chance to - * update its surfaces within the same transaction as any display layout updates. - * - * @param listener The listener to unregister. - */ - public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } - + private void unregisterDisplayTransactionListenerInternal( + DisplayTransactionListener listener) { // List is self-synchronized copy-on-write. mDisplayTransactionListeners.remove(listener); } - /** - * Overrides the display information of a particular logical display. - * This is used by the window manager to control the size and characteristics - * of the default display. It is expected to apply the requested change - * to the display information synchronously so that applications will immediately - * observe the new state. - * - * NOTE: This method must be the only entry point by which the window manager - * influences the logical configuration of displays. - * - * @param displayId The logical display id. - * @param info The new data to be stored. - */ - public void setDisplayInfoOverrideFromWindowManager( + private void setDisplayInfoOverrideFromWindowManagerInternal( int displayId, DisplayInfo info) { synchronized (mSyncRoot) { LogicalDisplay display = mLogicalDisplays.get(displayId); @@ -334,11 +295,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } } - /** - * Called by the window manager to perform traversals while holding a - * surface flinger transaction. - */ - public void performTraversalInTransactionFromWindowManager() { + private void performTraversalInTransactionFromWindowManagerInternal() { synchronized (mSyncRoot) { if (!mPendingTraversal) { return; @@ -354,10 +311,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } } - /** - * Called by the power manager to blank all displays. - */ - public void blankAllDisplaysFromPowerManager() { + private void blankAllDisplaysFromPowerManagerInternal() { synchronized (mSyncRoot) { if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) { mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED; @@ -367,10 +321,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } } - /** - * Called by the power manager to unblank all displays. - */ - public void unblankAllDisplaysFromPowerManager() { + private void unblankAllDisplaysFromPowerManagerInternal() { synchronized (mSyncRoot) { if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) { mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED; @@ -380,70 +331,40 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } } - /** - * Returns information about the specified logical display. - * - * @param displayId The logical display id. - * @return The logical display info, or null if the display does not exist. The - * returned object must be treated as immutable. - */ - @Override // Binder call - public DisplayInfo getDisplayInfo(int displayId) { - final int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - LogicalDisplay display = mLogicalDisplays.get(displayId); - if (display != null) { - DisplayInfo info = display.getDisplayInfoLocked(); - if (info.hasAccess(callingUid)) { - return info; - } + private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) { + synchronized (mSyncRoot) { + LogicalDisplay display = mLogicalDisplays.get(displayId); + if (display != null) { + DisplayInfo info = display.getDisplayInfoLocked(); + if (info.hasAccess(callingUid)) { + return info; } - return null; } - } finally { - Binder.restoreCallingIdentity(token); + return null; } } - /** - * Returns the list of all display ids. - */ - @Override // Binder call - public int[] getDisplayIds() { - final int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - final int count = mLogicalDisplays.size(); - int[] displayIds = new int[count]; - int n = 0; - for (int i = 0; i < count; i++) { - LogicalDisplay display = mLogicalDisplays.valueAt(i); - DisplayInfo info = display.getDisplayInfoLocked(); - if (info.hasAccess(callingUid)) { - displayIds[n++] = mLogicalDisplays.keyAt(i); - } - } - if (n != count) { - displayIds = Arrays.copyOfRange(displayIds, 0, n); + private int[] getDisplayIdsInternal(int callingUid) { + synchronized (mSyncRoot) { + final int count = mLogicalDisplays.size(); + int[] displayIds = new int[count]; + int n = 0; + for (int i = 0; i < count; i++) { + LogicalDisplay display = mLogicalDisplays.valueAt(i); + DisplayInfo info = display.getDisplayInfoLocked(); + if (info.hasAccess(callingUid)) { + displayIds[n++] = mLogicalDisplays.keyAt(i); } - return displayIds; } - } finally { - Binder.restoreCallingIdentity(token); + if (n != count) { + displayIds = Arrays.copyOfRange(displayIds, 0, n); + } + return displayIds; } } - @Override // Binder call - public void registerCallback(IDisplayManagerCallback callback) { - if (callback == null) { - throw new IllegalArgumentException("listener must not be null"); - } - + private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid) { synchronized (mSyncRoot) { - int callingPid = Binder.getCallingPid(); if (mCallbacks.get(callingPid) != null) { throw new SecurityException("The calling process has already " + "registered an IDisplayManagerCallback."); @@ -469,24 +390,14 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } } - @Override // Binder call - public void startWifiDisplayScan() { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to start wifi display scans"); - - final int callingPid = Binder.getCallingPid(); - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - CallbackRecord record = mCallbacks.get(callingPid); - if (record == null) { - throw new IllegalStateException("The calling process has not " - + "registered an IDisplayManagerCallback."); - } - startWifiDisplayScanLocked(record); + private void startWifiDisplayScanInternal(int callingPid) { + synchronized (mSyncRoot) { + CallbackRecord record = mCallbacks.get(callingPid); + if (record == null) { + throw new IllegalStateException("The calling process has not " + + "registered an IDisplayManagerCallback."); } - } finally { - Binder.restoreCallingIdentity(token); + startWifiDisplayScanLocked(record); } } @@ -501,24 +412,14 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } } - @Override // Binder call - public void stopWifiDisplayScan() { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to stop wifi display scans"); - - final int callingPid = Binder.getCallingPid(); - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - CallbackRecord record = mCallbacks.get(callingPid); - if (record == null) { - throw new IllegalStateException("The calling process has not " - + "registered an IDisplayManagerCallback."); - } - stopWifiDisplayScanLocked(record); + private void stopWifiDisplayScanInternal(int callingPid) { + synchronized (mSyncRoot) { + CallbackRecord record = mCallbacks.get(callingPid); + if (record == null) { + throw new IllegalStateException("The calling process has not " + + "registered an IDisplayManagerCallback."); } - } finally { - Binder.restoreCallingIdentity(token); + stopWifiDisplayScanLocked(record); } } @@ -537,255 +438,113 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } } - @Override // Binder call - public void connectWifiDisplay(String address) { - if (address == null) { - throw new IllegalArgumentException("address must not be null"); - } - mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to connect to a wifi display"); - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestConnectLocked(address); - } + private void connectWifiDisplayInternal(String address) { + synchronized (mSyncRoot) { + if (mWifiDisplayAdapter != null) { + mWifiDisplayAdapter.requestConnectLocked(address); } - } finally { - Binder.restoreCallingIdentity(token); } } - @Override - public void pauseWifiDisplay() { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to pause a wifi display session"); - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestPauseLocked(); - } + private void pauseWifiDisplayInternal() { + synchronized (mSyncRoot) { + if (mWifiDisplayAdapter != null) { + mWifiDisplayAdapter.requestPauseLocked(); } - } finally { - Binder.restoreCallingIdentity(token); } } - @Override - public void resumeWifiDisplay() { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to resume a wifi display session"); - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestResumeLocked(); - } + private void resumeWifiDisplayInternal() { + synchronized (mSyncRoot) { + if (mWifiDisplayAdapter != null) { + mWifiDisplayAdapter.requestResumeLocked(); } - } finally { - Binder.restoreCallingIdentity(token); } } - @Override // Binder call - public void disconnectWifiDisplay() { - // This request does not require special permissions. - // Any app can request disconnection from the currently active wifi display. - // This exception should no longer be needed once wifi display control moves - // to the media router service. - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestDisconnectLocked(); - } + private void disconnectWifiDisplayInternal() { + synchronized (mSyncRoot) { + if (mWifiDisplayAdapter != null) { + mWifiDisplayAdapter.requestDisconnectLocked(); } - } finally { - Binder.restoreCallingIdentity(token); } } - @Override // Binder call - public void renameWifiDisplay(String address, String alias) { - if (address == null) { - throw new IllegalArgumentException("address must not be null"); - } - mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to rename to a wifi display"); - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestRenameLocked(address, alias); - } + private void renameWifiDisplayInternal(String address, String alias) { + synchronized (mSyncRoot) { + if (mWifiDisplayAdapter != null) { + mWifiDisplayAdapter.requestRenameLocked(address, alias); } - } finally { - Binder.restoreCallingIdentity(token); } } - @Override // Binder call - public void forgetWifiDisplay(String address) { - if (address == null) { - throw new IllegalArgumentException("address must not be null"); - } - mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to forget to a wifi display"); - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestForgetLocked(address); - } + private void forgetWifiDisplayInternal(String address) { + synchronized (mSyncRoot) { + if (mWifiDisplayAdapter != null) { + mWifiDisplayAdapter.requestForgetLocked(address); } - } finally { - Binder.restoreCallingIdentity(token); } } - @Override // Binder call - public WifiDisplayStatus getWifiDisplayStatus() { - // This request does not require special permissions. - // Any app can get information about available wifi displays. - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mWifiDisplayAdapter != null) { - return mWifiDisplayAdapter.getWifiDisplayStatusLocked(); - } - return new WifiDisplayStatus(); + private WifiDisplayStatus getWifiDisplayStatusInternal() { + synchronized (mSyncRoot) { + if (mWifiDisplayAdapter != null) { + return mWifiDisplayAdapter.getWifiDisplayStatusLocked(); } - } finally { - Binder.restoreCallingIdentity(token); + return new WifiDisplayStatus(); } } - @Override // Binder call - public int createVirtualDisplay(IBinder appToken, String packageName, + private int createVirtualDisplayInternal(IBinder appToken, int callingUid, String packageName, String name, int width, int height, int densityDpi, Surface surface, int flags) { - final int callingUid = Binder.getCallingUid(); - if (!validatePackageName(callingUid, packageName)) { - throw new SecurityException("packageName must match the calling uid"); - } - if (appToken == null) { - throw new IllegalArgumentException("appToken must not be null"); - } - if (TextUtils.isEmpty(name)) { - throw new IllegalArgumentException("name must be non-null and non-empty"); - } - if (width <= 0 || height <= 0 || densityDpi <= 0) { - throw new IllegalArgumentException("width, height, and densityDpi must be " - + "greater than 0"); - } - if (surface == null) { - throw new IllegalArgumentException("surface must not be null"); - } - if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { - if (mContext.checkCallingPermission(android.Manifest.permission.CAPTURE_VIDEO_OUTPUT) - != PackageManager.PERMISSION_GRANTED - && mContext.checkCallingPermission( - android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or " - + "CAPTURE_SECURE_VIDEO_OUTPUT permission to create a " - + "public virtual display."); - } - } - if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { - if (mContext.checkCallingPermission( - android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT " - + "to create a secure virtual display."); + synchronized (mSyncRoot) { + if (mVirtualDisplayAdapter == null) { + Slog.w(TAG, "Rejecting request to create private virtual display " + + "because the virtual display adapter is not available."); + return -1; } - } - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mVirtualDisplayAdapter == null) { - Slog.w(TAG, "Rejecting request to create private virtual display " - + "because the virtual display adapter is not available."); - return -1; - } - - DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked( - appToken, callingUid, packageName, name, width, height, densityDpi, - surface, flags); - if (device == null) { - return -1; - } - - handleDisplayDeviceAddedLocked(device); - LogicalDisplay display = findLogicalDisplayForDeviceLocked(device); - if (display != null) { - return display.getDisplayIdLocked(); - } + DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked( + appToken, callingUid, packageName, name, width, height, densityDpi, + surface, flags); + if (device == null) { + return -1; + } - // Something weird happened and the logical display was not created. - Slog.w(TAG, "Rejecting request to create virtual display " - + "because the logical display was not created."); - mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken); - handleDisplayDeviceRemovedLocked(device); + handleDisplayDeviceAddedLocked(device); + LogicalDisplay display = findLogicalDisplayForDeviceLocked(device); + if (display != null) { + return display.getDisplayIdLocked(); } - } finally { - Binder.restoreCallingIdentity(token); + + // Something weird happened and the logical display was not created. + Slog.w(TAG, "Rejecting request to create virtual display " + + "because the logical display was not created."); + mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken); + handleDisplayDeviceRemovedLocked(device); } return -1; } - @Override // Binder call - public void releaseVirtualDisplay(IBinder appToken) { - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mVirtualDisplayAdapter == null) { - return; - } - - DisplayDevice device = - mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken); - if (device != null) { - handleDisplayDeviceRemovedLocked(device); - } + private void releaseVirtualDisplayInternal(IBinder appToken) { + synchronized (mSyncRoot) { + if (mVirtualDisplayAdapter == null) { + return; } - } finally { - Binder.restoreCallingIdentity(token); - } - } - private boolean validatePackageName(int uid, String packageName) { - if (packageName != null) { - String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); - if (packageNames != null) { - for (String n : packageNames) { - if (n.equals(packageName)) { - return true; - } - } + DisplayDevice device = + mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken); + if (device != null) { + handleDisplayDeviceRemovedLocked(device); } } - return false; } private void registerDefaultDisplayAdapter() { // Register default display adapter. synchronized (mSyncRoot) { - if (mHeadless) { - registerDisplayAdapterLocked(new HeadlessDisplayAdapter( - mSyncRoot, mContext, mHandler, mDisplayAdapterListener)); - } else { - registerDisplayAdapterLocked(new LocalDisplayAdapter( - mSyncRoot, mContext, mHandler, mDisplayAdapterListener)); - } + registerDisplayAdapterLocked(new LocalDisplayAdapter( + mSyncRoot, mContext, mHandler, mDisplayAdapterListener)); } } @@ -1002,26 +761,13 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } // Tell the input system about these new viewports. - if (mInputManagerFuncs != null) { + if (mInputManagerInternal != null) { mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT); } } - /** - * Tells the display manager whether there is interesting unique content on the - * specified logical display. This is used to control automatic mirroring. - * <p> - * If the display has unique content, then the display manager arranges for it - * to be presented on a physical display if appropriate. Otherwise, the display manager - * may choose to make the physical display mirror some other logical display. - * </p> - * - * @param displayId The logical display id to update. - * @param hasContent True if the logical display has content. - * @param inTraversal True if called from WindowManagerService during a window traversal prior - * to call to performTraversalInTransactionFromWindowManager. - */ - public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) { + private void setDisplayHasContentInternal(int displayId, boolean hasContent, + boolean inTraversal) { synchronized (mSyncRoot) { LogicalDisplay display = mLogicalDisplays.get(displayId); if (display != null && display.hasContentLocked() != hasContent) { @@ -1042,13 +788,13 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } private void configureDisplayInTransactionLocked(DisplayDevice device) { - DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); - boolean isPrivate = (info.flags & DisplayDeviceInfo.FLAG_PRIVATE) != 0; + final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); + final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0; // Find the logical display that the display device is showing. - // Private displays never mirror other displays. + // Certain displays only ever show their own content. LogicalDisplay display = findLogicalDisplayForDeviceLocked(device); - if (!isPrivate) { + if (!ownContent) { if (display != null && !display.hasContentLocked()) { // If the display does not have any content of its own, then // automatically mirror the default logical display contents. @@ -1107,7 +853,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { // Requests that performTraversalsInTransactionFromWindowManager be called at a // later time to apply changes to surfaces and displays. private void scheduleTraversalLocked(boolean inTraversal) { - if (!mPendingTraversal && mWindowManagerFuncs != null) { + if (!mPendingTraversal && mWindowManagerInternal != null) { mPendingTraversal = true; if (!inTraversal) { mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL); @@ -1140,20 +886,10 @@ public final class DisplayManagerService extends IDisplayManager.Stub { mTempCallbacks.clear(); } - @Override // Binder call - public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { - if (mContext == null - || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump DisplayManager from from pid=" - + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); - return; - } - + private void dumpInternal(PrintWriter pw) { pw.println("DISPLAY MANAGER (dumpsys display)"); synchronized (mSyncRoot) { - pw.println(" mHeadless=" + mHeadless); pw.println(" mOnlyCode=" + mOnlyCore); pw.println(" mSafeMode=" + mSafeMode); pw.println(" mPendingTraversal=" + mPendingTraversal); @@ -1212,30 +948,6 @@ public final class DisplayManagerService extends IDisplayManager.Stub { public static final class SyncRoot { } - /** - * Private interface to the window manager. - */ - public interface WindowManagerFuncs { - /** - * Request that the window manager call - * {@link #performTraversalInTransactionFromWindowManager} within a surface - * transaction at a later time. - */ - void requestTraversal(); - } - - /** - * Private interface to the input manager. - */ - public interface InputManagerFuncs { - /** - * Sets information about the displays as needed by the input system. - * The input system should copy this information if required. - */ - void setDisplayViewports(DisplayViewport defaultViewport, - DisplayViewport externalTouchViewport); - } - private final class DisplayManagerHandler extends Handler { public DisplayManagerHandler(Looper looper) { super(looper, null, true /*async*/); @@ -1257,7 +969,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { break; case MSG_REQUEST_TRAVERSAL: - mWindowManagerFuncs.requestTraversal(); + mWindowManagerInternal.requestTraversalFromDisplayManager(); break; case MSG_UPDATE_VIEWPORT: { @@ -1265,7 +977,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { mTempDefaultViewport.copyFrom(mDefaultViewport); mTempExternalTouchViewport.copyFrom(mExternalTouchViewport); } - mInputManagerFuncs.setDisplayViewports( + mInputManagerInternal.setDisplayViewports( mTempDefaultViewport, mTempExternalTouchViewport); break; } @@ -1328,4 +1040,325 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } } } + + private final class BinderService extends IDisplayManager.Stub { + /** + * Returns information about the specified logical display. + * + * @param displayId The logical display id. + * @return The logical display info, or null if the display does not exist. The + * returned object must be treated as immutable. + */ + @Override // Binder call + public DisplayInfo getDisplayInfo(int displayId) { + final int callingUid = Binder.getCallingUid(); + final long token = Binder.clearCallingIdentity(); + try { + return getDisplayInfoInternal(displayId, callingUid); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + /** + * Returns the list of all display ids. + */ + @Override // Binder call + public int[] getDisplayIds() { + final int callingUid = Binder.getCallingUid(); + final long token = Binder.clearCallingIdentity(); + try { + return getDisplayIdsInternal(callingUid); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override // Binder call + public void registerCallback(IDisplayManagerCallback callback) { + if (callback == null) { + throw new IllegalArgumentException("listener must not be null"); + } + + final int callingPid = Binder.getCallingPid(); + final long token = Binder.clearCallingIdentity(); + try { + registerCallbackInternal(callback, callingPid); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override // Binder call + public void startWifiDisplayScan() { + mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, + "Permission required to start wifi display scans"); + + final int callingPid = Binder.getCallingPid(); + final long token = Binder.clearCallingIdentity(); + try { + startWifiDisplayScanInternal(callingPid); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override // Binder call + public void stopWifiDisplayScan() { + mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, + "Permission required to stop wifi display scans"); + + final int callingPid = Binder.getCallingPid(); + final long token = Binder.clearCallingIdentity(); + try { + stopWifiDisplayScanInternal(callingPid); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override // Binder call + public void connectWifiDisplay(String address) { + if (address == null) { + throw new IllegalArgumentException("address must not be null"); + } + mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, + "Permission required to connect to a wifi display"); + + final long token = Binder.clearCallingIdentity(); + try { + connectWifiDisplayInternal(address); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override // Binder call + public void disconnectWifiDisplay() { + // This request does not require special permissions. + // Any app can request disconnection from the currently active wifi display. + // This exception should no longer be needed once wifi display control moves + // to the media router service. + + final long token = Binder.clearCallingIdentity(); + try { + disconnectWifiDisplayInternal(); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override // Binder call + public void renameWifiDisplay(String address, String alias) { + if (address == null) { + throw new IllegalArgumentException("address must not be null"); + } + mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, + "Permission required to rename to a wifi display"); + + final long token = Binder.clearCallingIdentity(); + try { + renameWifiDisplayInternal(address, alias); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override // Binder call + public void forgetWifiDisplay(String address) { + if (address == null) { + throw new IllegalArgumentException("address must not be null"); + } + mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, + "Permission required to forget to a wifi display"); + + final long token = Binder.clearCallingIdentity(); + try { + forgetWifiDisplayInternal(address); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override // Binder call + public void pauseWifiDisplay() { + mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, + "Permission required to pause a wifi display session"); + + final long token = Binder.clearCallingIdentity(); + try { + pauseWifiDisplayInternal(); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override // Binder call + public void resumeWifiDisplay() { + mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, + "Permission required to resume a wifi display session"); + + final long token = Binder.clearCallingIdentity(); + try { + resumeWifiDisplayInternal(); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override // Binder call + public WifiDisplayStatus getWifiDisplayStatus() { + // This request does not require special permissions. + // Any app can get information about available wifi displays. + + final long token = Binder.clearCallingIdentity(); + try { + return getWifiDisplayStatusInternal(); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override // Binder call + public int createVirtualDisplay(IBinder appToken, String packageName, + String name, int width, int height, int densityDpi, Surface surface, int flags) { + final int callingUid = Binder.getCallingUid(); + if (!validatePackageName(callingUid, packageName)) { + throw new SecurityException("packageName must match the calling uid"); + } + if (appToken == null) { + throw new IllegalArgumentException("appToken must not be null"); + } + if (TextUtils.isEmpty(name)) { + throw new IllegalArgumentException("name must be non-null and non-empty"); + } + if (width <= 0 || height <= 0 || densityDpi <= 0) { + throw new IllegalArgumentException("width, height, and densityDpi must be " + + "greater than 0"); + } + if (surface == null) { + throw new IllegalArgumentException("surface must not be null"); + } + if (callingUid != Process.SYSTEM_UID && + (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { + if (mContext.checkCallingPermission(android.Manifest.permission.CAPTURE_VIDEO_OUTPUT) + != PackageManager.PERMISSION_GRANTED + && mContext.checkCallingPermission( + android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or " + + "CAPTURE_SECURE_VIDEO_OUTPUT permission to create a " + + "public virtual display."); + } + } + if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { + if (mContext.checkCallingPermission( + android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT " + + "to create a secure virtual display."); + } + } + + final long token = Binder.clearCallingIdentity(); + try { + return createVirtualDisplayInternal(appToken, callingUid, packageName, + name, width, height, densityDpi, surface, flags); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override // Binder call + public void releaseVirtualDisplay(IBinder appToken) { + final long token = Binder.clearCallingIdentity(); + try { + releaseVirtualDisplayInternal(appToken); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override // Binder call + public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { + if (mContext == null + || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump DisplayManager from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); + return; + } + + final long token = Binder.clearCallingIdentity(); + try { + dumpInternal(pw); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + private boolean validatePackageName(int uid, String packageName) { + if (packageName != null) { + String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); + if (packageNames != null) { + for (String n : packageNames) { + if (n.equals(packageName)) { + return true; + } + } + } + } + return false; + } + } + + private final class LocalService extends DisplayManagerInternal { + @Override + public void blankAllDisplaysFromPowerManager() { + blankAllDisplaysFromPowerManagerInternal(); + } + + @Override + public void unblankAllDisplaysFromPowerManager() { + unblankAllDisplaysFromPowerManagerInternal(); + } + + @Override + public DisplayInfo getDisplayInfo(int displayId) { + return getDisplayInfoInternal(displayId, Process.myUid()); + } + + @Override + public void registerDisplayTransactionListener(DisplayTransactionListener listener) { + if (listener == null) { + throw new IllegalArgumentException("listener must not be null"); + } + + registerDisplayTransactionListenerInternal(listener); + } + + @Override + public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) { + if (listener == null) { + throw new IllegalArgumentException("listener must not be null"); + } + + unregisterDisplayTransactionListenerInternal(listener); + } + + @Override + public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) { + setDisplayInfoOverrideFromWindowManagerInternal(displayId, info); + } + + @Override + public void performTraversalInTransactionFromWindowManager() { + performTraversalInTransactionFromWindowManagerInternal(); + } + + @Override + public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) { + setDisplayHasContentInternal(displayId, hasContent, inTraversal); + } + } } diff --git a/services/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index cb8f3e20d368..cb8f3e20d368 100644 --- a/services/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java diff --git a/services/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index 7e357c0c3a7c..7e357c0c3a7c 100644 --- a/services/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java diff --git a/services/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java index 007acf716598..007acf716598 100644 --- a/services/java/com/android/server/display/OverlayDisplayAdapter.java +++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java diff --git a/services/java/com/android/server/display/OverlayDisplayWindow.java b/services/core/java/com/android/server/display/OverlayDisplayWindow.java index f1dd60a75424..f1dd60a75424 100644 --- a/services/java/com/android/server/display/OverlayDisplayWindow.java +++ b/services/core/java/com/android/server/display/OverlayDisplayWindow.java diff --git a/services/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java index 67b36958a35a..67b36958a35a 100644 --- a/services/java/com/android/server/display/PersistentDataStore.java +++ b/services/core/java/com/android/server/display/PersistentDataStore.java diff --git a/services/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java index 46d473ce6ba3..95ca0d2b4b43 100644 --- a/services/java/com/android/server/display/VirtualDisplayAdapter.java +++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java @@ -157,8 +157,11 @@ final class VirtualDisplayAdapter extends DisplayAdapter { mInfo.yDpi = mDensityDpi; mInfo.flags = 0; if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) { - mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE | - DisplayDeviceInfo.FLAG_NEVER_BLANK; + mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE + | DisplayDeviceInfo.FLAG_NEVER_BLANK + | DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY; + } else if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) { + mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY; } if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE; diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java index cd57941bcc3e..cd57941bcc3e 100644 --- a/services/java/com/android/server/display/WifiDisplayAdapter.java +++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/core/java/com/android/server/display/WifiDisplayController.java index dbb59b269bf5..dbb59b269bf5 100644 --- a/services/java/com/android/server/display/WifiDisplayController.java +++ b/services/core/java/com/android/server/display/WifiDisplayController.java diff --git a/services/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java index 85ef33e2742a..649b5c989fdb 100644 --- a/services/java/com/android/server/dreams/DreamController.java +++ b/services/core/java/com/android/server/dreams/DreamController.java @@ -85,6 +85,7 @@ final class DreamController { pw.println(" mToken=" + mCurrentDream.mToken); pw.println(" mName=" + mCurrentDream.mName); pw.println(" mIsTest=" + mCurrentDream.mIsTest); + pw.println(" mCanDoze=" + mCurrentDream.mCanDoze); pw.println(" mUserId=" + mCurrentDream.mUserId); pw.println(" mBound=" + mCurrentDream.mBound); pw.println(" mService=" + mCurrentDream.mService); @@ -94,15 +95,18 @@ final class DreamController { } } - public void startDream(Binder token, ComponentName name, boolean isTest, int userId) { + public void startDream(Binder token, ComponentName name, + boolean isTest, boolean canDoze, int userId) { stopDream(); // Close the notification shade. Don't need to send to all, but better to be explicit. mContext.sendBroadcastAsUser(mCloseNotificationShadeIntent, UserHandle.ALL); - Slog.i(TAG, "Starting dream: name=" + name + ", isTest=" + isTest + ", userId=" + userId); + Slog.i(TAG, "Starting dream: name=" + name + + ", isTest=" + isTest + ", canDoze=" + canDoze + + ", userId=" + userId); - mCurrentDream = new DreamRecord(token, name, isTest, userId); + mCurrentDream = new DreamRecord(token, name, isTest, canDoze, userId); try { mIWindowManager.addWindowToken(token, WindowManager.LayoutParams.TYPE_DREAM); @@ -140,7 +144,8 @@ final class DreamController { final DreamRecord oldDream = mCurrentDream; mCurrentDream = null; Slog.i(TAG, "Stopping dream: name=" + oldDream.mName - + ", isTest=" + oldDream.mIsTest + ", userId=" + oldDream.mUserId); + + ", isTest=" + oldDream.mIsTest + ", canDoze=" + oldDream.mCanDoze + + ", userId=" + oldDream.mUserId); mHandler.removeCallbacks(mStopUnconnectedDreamRunnable); @@ -187,7 +192,7 @@ final class DreamController { private void attach(IDreamService service) { try { service.asBinder().linkToDeath(mCurrentDream, 0); - service.attach(mCurrentDream.mToken); + service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze); } catch (RemoteException ex) { Slog.e(TAG, "The dream service died unexpectedly.", ex); stopDream(); @@ -213,6 +218,7 @@ final class DreamController { public final Binder mToken; public final ComponentName mName; public final boolean mIsTest; + public final boolean mCanDoze; public final int mUserId; public boolean mBound; @@ -221,10 +227,11 @@ final class DreamController { public boolean mSentStartBroadcast; public DreamRecord(Binder token, ComponentName name, - boolean isTest, int userId) { + boolean isTest, boolean canDoze, int userId) { mToken = token; mName = name; mIsTest = isTest; + mCanDoze = canDoze; mUserId = userId; } diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java new file mode 100644 index 000000000000..fd2f8a151f85 --- /dev/null +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -0,0 +1,655 @@ +/* + * 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.dreams; + +import com.android.internal.util.DumpUtils; +import com.android.server.FgThread; +import com.android.server.SystemService; + +import android.Manifest; +import android.app.ActivityManager; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Binder; +import android.os.Build; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.PowerManager; +import android.os.SystemClock; +import android.os.SystemProperties; +import android.os.UserHandle; +import android.provider.Settings; +import android.service.dreams.DreamManagerInternal; +import android.service.dreams.DreamService; +import android.service.dreams.IDozeHardware; +import android.service.dreams.IDreamManager; +import android.text.TextUtils; +import android.util.Slog; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +import libcore.util.Objects; + +/** + * Service api for managing dreams. + * + * @hide + */ +public final class DreamManagerService extends SystemService { + private static final boolean DEBUG = false; + private static final String TAG = "DreamManagerService"; + + private final Object mLock = new Object(); + + private final Context mContext; + private final DreamHandler mHandler; + private final DreamController mController; + private final PowerManager mPowerManager; + private final PowerManager.WakeLock mDozeWakeLock; + private final McuHal mMcuHal; // synchronized on self + + private Binder mCurrentDreamToken; + private ComponentName mCurrentDreamName; + private int mCurrentDreamUserId; + private boolean mCurrentDreamIsTest; + private boolean mCurrentDreamCanDoze; + private boolean mCurrentDreamIsDozing; + private DozeHardwareWrapper mCurrentDreamDozeHardware; + + public DreamManagerService(Context context) { + super(context); + mContext = context; + mHandler = new DreamHandler(FgThread.get().getLooper()); + mController = new DreamController(context, mHandler, mControllerListener); + + mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); + mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, TAG); + + mMcuHal = McuHal.open(); + if (mMcuHal != null) { + mMcuHal.reset(); + } + } + + @Override + public void onStart() { + publishBinderService(DreamService.DREAM_SERVICE, new BinderService()); + publishLocalService(DreamManagerInternal.class, new LocalService()); + } + + @Override + public void onBootPhase(int phase) { + if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { + mContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + synchronized (mLock) { + stopDreamLocked(); + } + } + }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler); + } + } + + private void dumpInternal(PrintWriter pw) { + pw.println("DREAM MANAGER (dumpsys dreams)"); + pw.println(); + + pw.println("mMcuHal=" + mMcuHal); + pw.println(); + pw.println("mCurrentDreamToken=" + mCurrentDreamToken); + pw.println("mCurrentDreamName=" + mCurrentDreamName); + pw.println("mCurrentDreamUserId=" + mCurrentDreamUserId); + pw.println("mCurrentDreamIsTest=" + mCurrentDreamIsTest); + pw.println("mCurrentDreamCanDoze=" + mCurrentDreamCanDoze); + pw.println("mCurrentDreamIsDozing=" + mCurrentDreamIsDozing); + pw.println("mCurrentDreamDozeHardware=" + mCurrentDreamDozeHardware); + pw.println(); + + DumpUtils.dumpAsync(mHandler, new DumpUtils.Dump() { + @Override + public void dump(PrintWriter pw) { + mController.dump(pw); + } + }, pw, 200); + } + + private boolean isDreamingInternal() { + synchronized (mLock) { + return mCurrentDreamToken != null && !mCurrentDreamIsTest; + } + } + + private void requestDreamInternal() { + // Ask the power manager to nap. It will eventually call back into + // startDream() if/when it is appropriate to start dreaming. + // Because napping could cause the screen to turn off immediately if the dream + // cannot be started, we keep one eye open and gently poke user activity. + long time = SystemClock.uptimeMillis(); + mPowerManager.userActivity(time, true /*noChangeLights*/); + mPowerManager.nap(time); + } + + private void requestAwakenInternal() { + // Treat an explicit request to awaken as user activity so that the + // device doesn't immediately go to sleep if the timeout expired, + // for example when being undocked. + long time = SystemClock.uptimeMillis(); + mPowerManager.userActivity(time, false /*noChangeLights*/); + stopDreamInternal(); + } + + private void finishSelfInternal(IBinder token) { + if (DEBUG) { + Slog.d(TAG, "Dream finished: " + token); + } + + // Note that a dream finishing and self-terminating is not + // itself considered user activity. If the dream is ending because + // the user interacted with the device then user activity will already + // have been poked so the device will stay awake a bit longer. + // If the dream is ending on its own for other reasons and no wake + // locks are held and the user activity timeout has expired then the + // device may simply go to sleep. + synchronized (mLock) { + if (mCurrentDreamToken == token) { + stopDreamLocked(); + } + } + } + + private void testDreamInternal(ComponentName dream, int userId) { + synchronized (mLock) { + startDreamLocked(dream, true /*isTest*/, false /*canDoze*/, userId); + } + } + + private void startDreamInternal(boolean doze) { + final int userId = ActivityManager.getCurrentUser(); + final ComponentName dream = doze ? getDozeComponent() : chooseDreamForUser(userId); + if (dream != null) { + synchronized (mLock) { + startDreamLocked(dream, false /*isTest*/, doze, userId); + } + } + } + + private void stopDreamInternal() { + synchronized (mLock) { + stopDreamLocked(); + } + } + + private void startDozingInternal(IBinder token) { + if (DEBUG) { + Slog.d(TAG, "Dream requested to start dozing: " + token); + } + + synchronized (mLock) { + if (mCurrentDreamToken == token && mCurrentDreamCanDoze + && !mCurrentDreamIsDozing) { + mCurrentDreamIsDozing = true; + mDozeWakeLock.acquire(); + } + } + } + + private void stopDozingInternal(IBinder token) { + if (DEBUG) { + Slog.d(TAG, "Dream requested to stop dozing: " + token); + } + + synchronized (mLock) { + if (mCurrentDreamToken == token && mCurrentDreamIsDozing) { + mCurrentDreamIsDozing = false; + mDozeWakeLock.release(); + } + } + } + + private IDozeHardware getDozeHardwareInternal(IBinder token) { + synchronized (mLock) { + if (mCurrentDreamToken == token && mCurrentDreamCanDoze + && mCurrentDreamDozeHardware == null && mMcuHal != null) { + mCurrentDreamDozeHardware = new DozeHardwareWrapper(); + return mCurrentDreamDozeHardware; + } + return null; + } + } + + private ComponentName chooseDreamForUser(int userId) { + ComponentName[] dreams = getDreamComponentsForUser(userId); + return dreams != null && dreams.length != 0 ? dreams[0] : null; + } + + private ComponentName[] getDreamComponentsForUser(int userId) { + String names = Settings.Secure.getStringForUser(mContext.getContentResolver(), + Settings.Secure.SCREENSAVER_COMPONENTS, + userId); + ComponentName[] components = componentsFromString(names); + + // first, ensure components point to valid services + List<ComponentName> validComponents = new ArrayList<ComponentName>(); + if (components != null) { + for (ComponentName component : components) { + if (serviceExists(component)) { + validComponents.add(component); + } else { + Slog.w(TAG, "Dream " + component + " does not exist"); + } + } + } + + // fallback to the default dream component if necessary + if (validComponents.isEmpty()) { + ComponentName defaultDream = getDefaultDreamComponentForUser(userId); + if (defaultDream != null) { + Slog.w(TAG, "Falling back to default dream " + defaultDream); + validComponents.add(defaultDream); + } + } + return validComponents.toArray(new ComponentName[validComponents.size()]); + } + + private void setDreamComponentsForUser(int userId, ComponentName[] componentNames) { + Settings.Secure.putStringForUser(mContext.getContentResolver(), + Settings.Secure.SCREENSAVER_COMPONENTS, + componentsToString(componentNames), + userId); + } + + private ComponentName getDefaultDreamComponentForUser(int userId) { + String name = Settings.Secure.getStringForUser(mContext.getContentResolver(), + Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT, + userId); + return name == null ? null : ComponentName.unflattenFromString(name); + } + + private ComponentName getDozeComponent() { + // Read the component from a system property to facilitate debugging. + // Note that for production devices, the dream should actually be declared in + // a config.xml resource. + String name = Build.IS_DEBUGGABLE ? SystemProperties.get("debug.doze.component") : null; + if (TextUtils.isEmpty(name)) { + // Read the component from a config.xml resource. + // The value should be specified in a resource overlay for the product. + name = mContext.getResources().getString( + com.android.internal.R.string.config_dozeComponent); + } + return TextUtils.isEmpty(name) ? null : ComponentName.unflattenFromString(name); + } + + private boolean serviceExists(ComponentName name) { + try { + return name != null && mContext.getPackageManager().getServiceInfo(name, 0) != null; + } catch (NameNotFoundException e) { + return false; + } + } + + private void startDreamLocked(final ComponentName name, + final boolean isTest, final boolean canDoze, final int userId) { + if (Objects.equal(mCurrentDreamName, name) + && mCurrentDreamIsTest == isTest + && mCurrentDreamCanDoze == canDoze + && mCurrentDreamUserId == userId) { + return; + } + + stopDreamLocked(); + + if (DEBUG) Slog.i(TAG, "Entering dreamland."); + + final Binder newToken = new Binder(); + mCurrentDreamToken = newToken; + mCurrentDreamName = name; + mCurrentDreamIsTest = isTest; + mCurrentDreamCanDoze = canDoze; + mCurrentDreamUserId = userId; + + mHandler.post(new Runnable() { + @Override + public void run() { + mController.startDream(newToken, name, isTest, canDoze, userId); + } + }); + } + + private void stopDreamLocked() { + if (mCurrentDreamToken != null) { + if (DEBUG) Slog.i(TAG, "Leaving dreamland."); + + cleanupDreamLocked(); + + mHandler.post(new Runnable() { + @Override + public void run() { + mController.stopDream(); + } + }); + } + } + + private void cleanupDreamLocked() { + mCurrentDreamToken = null; + mCurrentDreamName = null; + mCurrentDreamIsTest = false; + mCurrentDreamCanDoze = false; + mCurrentDreamUserId = 0; + if (mCurrentDreamIsDozing) { + mCurrentDreamIsDozing = false; + mDozeWakeLock.release(); + } + if (mCurrentDreamDozeHardware != null) { + mCurrentDreamDozeHardware.release(); + mCurrentDreamDozeHardware = null; + } + } + + private void checkPermission(String permission) { + if (mContext.checkCallingOrSelfPermission(permission) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Access denied to process: " + Binder.getCallingPid() + + ", must have permission " + permission); + } + } + + private static String componentsToString(ComponentName[] componentNames) { + StringBuilder names = new StringBuilder(); + if (componentNames != null) { + for (ComponentName componentName : componentNames) { + if (names.length() > 0) { + names.append(','); + } + names.append(componentName.flattenToString()); + } + } + return names.toString(); + } + + private static ComponentName[] componentsFromString(String names) { + if (names == null) { + return null; + } + String[] namesArray = names.split(","); + ComponentName[] componentNames = new ComponentName[namesArray.length]; + for (int i = 0; i < namesArray.length; i++) { + componentNames[i] = ComponentName.unflattenFromString(namesArray[i]); + } + return componentNames; + } + + private final DreamController.Listener mControllerListener = new DreamController.Listener() { + @Override + public void onDreamStopped(Binder token) { + synchronized (mLock) { + if (mCurrentDreamToken == token) { + cleanupDreamLocked(); + } + } + } + }; + + /** + * Handler for asynchronous operations performed by the dream manager. + * Ensures operations to {@link DreamController} are single-threaded. + */ + private final class DreamHandler extends Handler { + public DreamHandler(Looper looper) { + super(looper, null, true /*async*/); + } + } + + private final class BinderService extends IDreamManager.Stub { + @Override // Binder call + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump DreamManager from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + final long ident = Binder.clearCallingIdentity(); + try { + dumpInternal(pw); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public ComponentName[] getDreamComponents() { + checkPermission(android.Manifest.permission.READ_DREAM_STATE); + + final int userId = UserHandle.getCallingUserId(); + final long ident = Binder.clearCallingIdentity(); + try { + return getDreamComponentsForUser(userId); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void setDreamComponents(ComponentName[] componentNames) { + checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); + + final int userId = UserHandle.getCallingUserId(); + final long ident = Binder.clearCallingIdentity(); + try { + setDreamComponentsForUser(userId, componentNames); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public ComponentName getDefaultDreamComponent() { + checkPermission(android.Manifest.permission.READ_DREAM_STATE); + + final int userId = UserHandle.getCallingUserId(); + final long ident = Binder.clearCallingIdentity(); + try { + return getDefaultDreamComponentForUser(userId); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public boolean isDreaming() { + checkPermission(android.Manifest.permission.READ_DREAM_STATE); + + final long ident = Binder.clearCallingIdentity(); + try { + return isDreamingInternal(); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void dream() { + checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); + + final long ident = Binder.clearCallingIdentity(); + try { + requestDreamInternal(); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void testDream(ComponentName dream) { + if (dream == null) { + throw new IllegalArgumentException("dream must not be null"); + } + checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); + + final int callingUserId = UserHandle.getCallingUserId(); + final int currentUserId = ActivityManager.getCurrentUser(); + if (callingUserId != currentUserId) { + // This check is inherently prone to races but at least it's something. + Slog.w(TAG, "Aborted attempt to start a test dream while a different " + + " user is active: callingUserId=" + callingUserId + + ", currentUserId=" + currentUserId); + return; + } + final long ident = Binder.clearCallingIdentity(); + try { + testDreamInternal(dream, callingUserId); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void awaken() { + checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); + + final long ident = Binder.clearCallingIdentity(); + try { + requestAwakenInternal(); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void finishSelf(IBinder token) { + // Requires no permission, called by Dream from an arbitrary process. + if (token == null) { + throw new IllegalArgumentException("token must not be null"); + } + + final long ident = Binder.clearCallingIdentity(); + try { + finishSelfInternal(token); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void startDozing(IBinder token) { + // Requires no permission, called by Dream from an arbitrary process. + if (token == null) { + throw new IllegalArgumentException("token must not be null"); + } + + final long ident = Binder.clearCallingIdentity(); + try { + startDozingInternal(token); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void stopDozing(IBinder token) { + // Requires no permission, called by Dream from an arbitrary process. + if (token == null) { + throw new IllegalArgumentException("token must not be null"); + } + + final long ident = Binder.clearCallingIdentity(); + try { + stopDozingInternal(token); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public IDozeHardware getDozeHardware(IBinder token) { + // Requires no permission, called by Dream from an arbitrary process. + if (token == null) { + throw new IllegalArgumentException("token must not be null"); + } + + final long ident = Binder.clearCallingIdentity(); + try { + return getDozeHardwareInternal(token); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } + + private final class LocalService extends DreamManagerInternal { + @Override + public void startDream(boolean doze) { + startDreamInternal(doze); + } + + @Override + public void stopDream() { + stopDreamInternal(); + } + + @Override + public boolean isDreaming() { + return isDreamingInternal(); + } + } + + private final class DozeHardwareWrapper extends IDozeHardware.Stub { + private boolean mReleased; + + public void release() { + synchronized (mMcuHal) { + if (!mReleased) { + mReleased = true; + mMcuHal.reset(); + } + } + } + + @Override // Binder call + public byte[] sendMessage(String msg, byte[] arg) { + if (msg == null) { + throw new IllegalArgumentException("msg must not be null"); + } + + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mMcuHal) { + if (mReleased) { + throw new IllegalStateException("This operation cannot be performed " + + "because the dream has ended."); + } + return mMcuHal.sendMessage(msg, arg); + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } +} diff --git a/services/core/java/com/android/server/dreams/McuHal.java b/services/core/java/com/android/server/dreams/McuHal.java new file mode 100644 index 000000000000..1dc79c7bf0e6 --- /dev/null +++ b/services/core/java/com/android/server/dreams/McuHal.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.dreams; + +import android.service.dreams.DozeHardware; + +/** + * Provides access to the low-level microcontroller hardware abstraction layer. + */ +final class McuHal { + private final long mPtr; + + private static native long nativeOpen(); + private static native byte[] nativeSendMessage(long ptr, String msg, byte[] arg); + + private McuHal(long ptr) { + mPtr = ptr; + } + + public static McuHal open() { + long ptr = nativeOpen(); + return ptr != 0 ? new McuHal(ptr) : null; + } + + public void reset() { + sendMessage(DozeHardware.MSG_ENABLE_MCU, DozeHardware.VALUE_OFF); + } + + public byte[] sendMessage(String msg, byte[] arg) { + return nativeSendMessage(mPtr, msg, arg); + } +} diff --git a/services/java/com/android/server/firewall/AndFilter.java b/services/core/java/com/android/server/firewall/AndFilter.java index 13551de8a02f..13551de8a02f 100644 --- a/services/java/com/android/server/firewall/AndFilter.java +++ b/services/core/java/com/android/server/firewall/AndFilter.java diff --git a/services/java/com/android/server/firewall/CategoryFilter.java b/services/core/java/com/android/server/firewall/CategoryFilter.java index 246c09630c67..246c09630c67 100644 --- a/services/java/com/android/server/firewall/CategoryFilter.java +++ b/services/core/java/com/android/server/firewall/CategoryFilter.java diff --git a/services/java/com/android/server/firewall/Filter.java b/services/core/java/com/android/server/firewall/Filter.java index 0a124f768f6c..0a124f768f6c 100644 --- a/services/java/com/android/server/firewall/Filter.java +++ b/services/core/java/com/android/server/firewall/Filter.java diff --git a/services/java/com/android/server/firewall/FilterFactory.java b/services/core/java/com/android/server/firewall/FilterFactory.java index dea8b4000ccd..dea8b4000ccd 100644 --- a/services/java/com/android/server/firewall/FilterFactory.java +++ b/services/core/java/com/android/server/firewall/FilterFactory.java diff --git a/services/java/com/android/server/firewall/FilterList.java b/services/core/java/com/android/server/firewall/FilterList.java index d34b2038e5bf..d34b2038e5bf 100644 --- a/services/java/com/android/server/firewall/FilterList.java +++ b/services/core/java/com/android/server/firewall/FilterList.java diff --git a/services/java/com/android/server/firewall/IntentFirewall.java b/services/core/java/com/android/server/firewall/IntentFirewall.java index aaa0b585eddb..88a2207d53b6 100644 --- a/services/java/com/android/server/firewall/IntentFirewall.java +++ b/services/core/java/com/android/server/firewall/IntentFirewall.java @@ -26,6 +26,7 @@ import android.content.pm.PackageManager; import android.os.Environment; import android.os.FileObserver; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.util.ArrayMap; @@ -106,8 +107,9 @@ public class IntentFirewall { } } - public IntentFirewall(AMSInterface ams) { + public IntentFirewall(AMSInterface ams, Handler handler) { mAms = ams; + mHandler = new FirewallHandler(handler.getLooper()); File rulesDir = getRulesDir(); rulesDir.mkdirs(); @@ -531,7 +533,13 @@ public class IntentFirewall { new ArrayMap<ComponentName, Rule[]>(0); } - final Handler mHandler = new Handler() { + final FirewallHandler mHandler; + + private final class FirewallHandler extends Handler { + public FirewallHandler(Looper looper) { + super(looper, null, true); + } + @Override public void handleMessage(Message msg) { readRulesDir(getRulesDir()); diff --git a/services/java/com/android/server/firewall/NotFilter.java b/services/core/java/com/android/server/firewall/NotFilter.java index 09bf629a0df3..09bf629a0df3 100644 --- a/services/java/com/android/server/firewall/NotFilter.java +++ b/services/core/java/com/android/server/firewall/NotFilter.java diff --git a/services/java/com/android/server/firewall/OrFilter.java b/services/core/java/com/android/server/firewall/OrFilter.java index f6a6f22278e4..f6a6f22278e4 100644 --- a/services/java/com/android/server/firewall/OrFilter.java +++ b/services/core/java/com/android/server/firewall/OrFilter.java diff --git a/services/java/com/android/server/firewall/PortFilter.java b/services/core/java/com/android/server/firewall/PortFilter.java index 84ace553ee78..84ace553ee78 100644 --- a/services/java/com/android/server/firewall/PortFilter.java +++ b/services/core/java/com/android/server/firewall/PortFilter.java diff --git a/services/java/com/android/server/firewall/SenderFilter.java b/services/core/java/com/android/server/firewall/SenderFilter.java index c0eee69b4b0d..c0eee69b4b0d 100644 --- a/services/java/com/android/server/firewall/SenderFilter.java +++ b/services/core/java/com/android/server/firewall/SenderFilter.java diff --git a/services/java/com/android/server/firewall/SenderPermissionFilter.java b/services/core/java/com/android/server/firewall/SenderPermissionFilter.java index caa65f36157a..caa65f36157a 100644 --- a/services/java/com/android/server/firewall/SenderPermissionFilter.java +++ b/services/core/java/com/android/server/firewall/SenderPermissionFilter.java diff --git a/services/java/com/android/server/firewall/StringFilter.java b/services/core/java/com/android/server/firewall/StringFilter.java index 28e99b372d54..28e99b372d54 100644 --- a/services/java/com/android/server/firewall/StringFilter.java +++ b/services/core/java/com/android/server/firewall/StringFilter.java diff --git a/services/java/com/android/server/input/InputApplicationHandle.java b/services/core/java/com/android/server/input/InputApplicationHandle.java index 3cf7edcd6b2e..3cf7edcd6b2e 100644 --- a/services/java/com/android/server/input/InputApplicationHandle.java +++ b/services/core/java/com/android/server/input/InputApplicationHandle.java diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 91786643f7cc..73033e0b481b 100644 --- a/services/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -16,11 +16,12 @@ package com.android.server.input; +import android.view.Display; import com.android.internal.R; import com.android.internal.util.XmlUtils; +import com.android.server.DisplayThread; +import com.android.server.LocalServices; import com.android.server.Watchdog; -import com.android.server.display.DisplayManagerService; -import com.android.server.display.DisplayViewport; import org.xmlpull.v1.XmlPullParser; @@ -44,9 +45,11 @@ import android.content.res.Resources.NotFoundException; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.database.ContentObserver; +import android.hardware.display.DisplayViewport; import android.hardware.input.IInputDevicesChangedListener; import android.hardware.input.IInputManager; import android.hardware.input.InputManager; +import android.hardware.input.InputManagerInternal; import android.hardware.input.KeyboardLayout; import android.os.Binder; import android.os.Bundle; @@ -94,7 +97,7 @@ import libcore.util.Objects; * Wraps the C++ InputManager and provides its callbacks. */ public class InputManagerService extends IInputManager.Stub - implements Watchdog.Monitor, DisplayManagerService.InputManagerFuncs { + implements Watchdog.Monitor { static final String TAG = "InputManager"; static final boolean DEBUG = false; @@ -167,7 +170,7 @@ public class InputManagerService extends IInputManager.Stub InputWindowHandle inputWindowHandle, boolean monitor); private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel); private static native void nativeSetInputFilterEnabled(long ptr, boolean enable); - private static native int nativeInjectInputEvent(long ptr, InputEvent event, + private static native int nativeInjectInputEvent(long ptr, InputEvent event, int displayId, int injectorPid, int injectorUid, int syncMode, int timeoutMillis, int policyFlags); private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles); @@ -241,15 +244,17 @@ public class InputManagerService extends IInputManager.Stub /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */ final boolean mUseDevInputEventForAudioJack; - public InputManagerService(Context context, Handler handler) { + public InputManagerService(Context context) { this.mContext = context; - this.mHandler = new InputManagerHandler(handler.getLooper()); + this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper()); mUseDevInputEventForAudioJack = context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack); Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack=" + mUseDevInputEventForAudioJack); mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue()); + + LocalServices.addService(InputManagerInternal.class, new LocalService()); } public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) { @@ -329,8 +334,7 @@ public class InputManagerService extends IInputManager.Stub nativeReloadDeviceAliases(mPtr); } - @Override - public void setDisplayViewports(DisplayViewport defaultViewport, + private void setDisplayViewportsInternal(DisplayViewport defaultViewport, DisplayViewport externalTouchViewport) { if (defaultViewport.valid) { setDisplayViewport(false, defaultViewport); @@ -505,6 +509,10 @@ public class InputManagerService extends IInputManager.Stub @Override // Binder call public boolean injectInputEvent(InputEvent event, int mode) { + return injectInputEventInternal(event, Display.DEFAULT_DISPLAY, mode); + } + + private boolean injectInputEventInternal(InputEvent event, int displayId, int mode) { if (event == null) { throw new IllegalArgumentException("event must not be null"); } @@ -519,7 +527,7 @@ public class InputManagerService extends IInputManager.Stub final long ident = Binder.clearCallingIdentity(); final int result; try { - result = nativeInjectInputEvent(mPtr, event, pid, uid, mode, + result = nativeInjectInputEvent(mPtr, event, displayId, pid, uid, mode, INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT); } finally { Binder.restoreCallingIdentity(ident); @@ -1321,8 +1329,9 @@ public class InputManagerService extends IInputManager.Stub } // Native callback. - private int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) { - return mWindowManagerCallbacks.interceptMotionBeforeQueueingWhenScreenOff(policyFlags); + private int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags) { + return mWindowManagerCallbacks.interceptMotionBeforeQueueingWhenScreenOff( + whenNanos, policyFlags); } // Native callback. @@ -1483,7 +1492,7 @@ public class InputManagerService extends IInputManager.Stub public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn); - public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags); + public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags); public long interceptKeyBeforeDispatching(InputWindowHandle focus, KeyEvent event, int policyFlags); @@ -1549,7 +1558,7 @@ public class InputManagerService extends IInputManager.Stub synchronized (mInputFilterLock) { if (!mDisconnected) { - nativeInjectInputEvent(mPtr, event, 0, 0, + nativeInjectInputEvent(mPtr, event, Display.DEFAULT_DISPLAY, 0, 0, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0, policyFlags | WindowManagerPolicy.FLAG_FILTERED); } @@ -1639,4 +1648,17 @@ public class InputManagerService extends IInputManager.Stub onVibratorTokenDied(this); } } + + private final class LocalService extends InputManagerInternal { + @Override + public void setDisplayViewports( + DisplayViewport defaultViewport, DisplayViewport externalTouchViewport) { + setDisplayViewportsInternal(defaultViewport, externalTouchViewport); + } + + @Override + public boolean injectInputEvent(InputEvent event, int displayId, int mode) { + return injectInputEventInternal(event, displayId, mode); + } + } } diff --git a/services/java/com/android/server/input/InputWindowHandle.java b/services/core/java/com/android/server/input/InputWindowHandle.java index 9a70f38ceac7..9a70f38ceac7 100644 --- a/services/java/com/android/server/input/InputWindowHandle.java +++ b/services/core/java/com/android/server/input/InputWindowHandle.java diff --git a/services/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java index 71de776c081c..71de776c081c 100644 --- a/services/java/com/android/server/input/PersistentDataStore.java +++ b/services/core/java/com/android/server/input/PersistentDataStore.java diff --git a/services/core/java/com/android/server/lights/Light.java b/services/core/java/com/android/server/lights/Light.java new file mode 100644 index 000000000000..b496b4c6ce8c --- /dev/null +++ b/services/core/java/com/android/server/lights/Light.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.lights; + +public abstract class Light { + public static final int LIGHT_FLASH_NONE = 0; + public static final int LIGHT_FLASH_TIMED = 1; + public static final int LIGHT_FLASH_HARDWARE = 2; + + /** + * Light brightness is managed by a user setting. + */ + public static final int BRIGHTNESS_MODE_USER = 0; + + /** + * Light brightness is managed by a light sensor. + */ + public static final int BRIGHTNESS_MODE_SENSOR = 1; + + public abstract void setBrightness(int brightness); + public abstract void setBrightness(int brightness, int brightnessMode); + public abstract void setColor(int color); + public abstract void setFlashing(int color, int mode, int onMS, int offMS); + public abstract void pulse(); + public abstract void pulse(int color, int onMS); + public abstract void turnOff(); +}
\ No newline at end of file diff --git a/services/core/java/com/android/server/lights/LightsManager.java b/services/core/java/com/android/server/lights/LightsManager.java new file mode 100644 index 000000000000..2f20509dddf5 --- /dev/null +++ b/services/core/java/com/android/server/lights/LightsManager.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.lights; + +public abstract class LightsManager { + public static final int LIGHT_ID_BACKLIGHT = 0; + public static final int LIGHT_ID_KEYBOARD = 1; + public static final int LIGHT_ID_BUTTONS = 2; + public static final int LIGHT_ID_BATTERY = 3; + public static final int LIGHT_ID_NOTIFICATIONS = 4; + public static final int LIGHT_ID_ATTENTION = 5; + public static final int LIGHT_ID_BLUETOOTH = 6; + public static final int LIGHT_ID_WIFI = 7; + public static final int LIGHT_ID_COUNT = 8; + + public abstract Light getLight(int id); +} diff --git a/services/java/com/android/server/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java index a1d655bd4181..62c0ec9a2ce0 100644 --- a/services/java/com/android/server/LightsService.java +++ b/services/core/java/com/android/server/lights/LightsService.java @@ -14,59 +14,38 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.lights; + +import com.android.server.SystemService; import android.content.Context; import android.content.pm.PackageManager; import android.os.Handler; import android.os.IHardwareService; -import android.os.ServiceManager; import android.os.Message; import android.util.Slog; import java.io.FileInputStream; import java.io.FileOutputStream; -public class LightsService { - private static final String TAG = "LightsService"; - private static final boolean DEBUG = false; - - public static final int LIGHT_ID_BACKLIGHT = 0; - public static final int LIGHT_ID_KEYBOARD = 1; - public static final int LIGHT_ID_BUTTONS = 2; - public static final int LIGHT_ID_BATTERY = 3; - public static final int LIGHT_ID_NOTIFICATIONS = 4; - public static final int LIGHT_ID_ATTENTION = 5; - public static final int LIGHT_ID_BLUETOOTH = 6; - public static final int LIGHT_ID_WIFI = 7; - public static final int LIGHT_ID_COUNT = 8; - - public static final int LIGHT_FLASH_NONE = 0; - public static final int LIGHT_FLASH_TIMED = 1; - public static final int LIGHT_FLASH_HARDWARE = 2; - - /** - * Light brightness is managed by a user setting. - */ - public static final int BRIGHTNESS_MODE_USER = 0; - - /** - * Light brightness is managed by a light sensor. - */ - public static final int BRIGHTNESS_MODE_SENSOR = 1; +public class LightsService extends SystemService { + static final String TAG = "LightsService"; + static final boolean DEBUG = false; - private final Light mLights[] = new Light[LIGHT_ID_COUNT]; + final LightImpl mLights[] = new LightImpl[LightsManager.LIGHT_ID_COUNT]; - public final class Light { + private final class LightImpl extends Light { - private Light(int id) { + private LightImpl(int id) { mId = id; } + @Override public void setBrightness(int brightness) { setBrightness(brightness, BRIGHTNESS_MODE_USER); } + @Override public void setBrightness(int brightness, int brightnessMode) { synchronized (this) { int color = brightness & 0x000000ff; @@ -75,23 +54,26 @@ public class LightsService { } } + @Override public void setColor(int color) { synchronized (this) { setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, 0); } } + @Override public void setFlashing(int color, int mode, int onMS, int offMS) { synchronized (this) { setLightLocked(color, mode, onMS, offMS, BRIGHTNESS_MODE_USER); } } - + @Override public void pulse() { pulse(0x00ffffff, 7); } + @Override public void pulse(int color, int onMS) { synchronized (this) { if (mColor == 0 && !mFlashing) { @@ -101,6 +83,7 @@ public class LightsService { } } + @Override public void turnOff() { synchronized (this) { setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, 0); @@ -153,9 +136,10 @@ public class LightsService { } public void setFlashlightEnabled(boolean on) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.FLASHLIGHT) + final Context context = getContext(); + if (context.checkCallingOrSelfPermission(android.Manifest.permission.FLASHLIGHT) != PackageManager.PERMISSION_GRANTED && - mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) + context.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Requires FLASHLIGHT or HARDWARE_TEST permission"); } @@ -172,31 +156,43 @@ public class LightsService { } }; - LightsService(Context context) { + public LightsService(Context context) { + super(context); mNativePointer = init_native(); - mContext = context; - ServiceManager.addService("hardware", mLegacyFlashlightHack); - - for (int i = 0; i < LIGHT_ID_COUNT; i++) { - mLights[i] = new Light(i); + for (int i = 0; i < LightsManager.LIGHT_ID_COUNT; i++) { + mLights[i] = new LightImpl(i); } } + @Override + public void onStart() { + publishBinderService("hardware", mLegacyFlashlightHack); + publishLocalService(LightsManager.class, mService); + } + + private final LightsManager mService = new LightsManager() { + @Override + public com.android.server.lights.Light getLight(int id) { + if (id < LIGHT_ID_COUNT) { + return mLights[id]; + } else { + return null; + } + } + }; + + @Override protected void finalize() throws Throwable { finalize_native(mNativePointer); super.finalize(); } - public Light getLight(int id) { - return mLights[id]; - } - private Handler mH = new Handler() { @Override public void handleMessage(Message msg) { - Light light = (Light)msg.obj; + LightImpl light = (LightImpl)msg.obj; light.stopFlashing(); } }; @@ -204,10 +200,8 @@ public class LightsService { private static native long init_native(); private static native void finalize_native(long ptr); - private static native void setLight_native(long ptr, int light, int color, int mode, + static native void setLight_native(long ptr, int light, int color, int mode, int onMS, int offMS, int brightnessMode); - private final Context mContext; - private long mNativePointer; } diff --git a/services/java/com/android/server/location/ComprehensiveCountryDetector.java b/services/core/java/com/android/server/location/ComprehensiveCountryDetector.java index 354858b15368..354858b15368 100644 --- a/services/java/com/android/server/location/ComprehensiveCountryDetector.java +++ b/services/core/java/com/android/server/location/ComprehensiveCountryDetector.java diff --git a/services/java/com/android/server/location/CountryDetectorBase.java b/services/core/java/com/android/server/location/CountryDetectorBase.java index 8326ef949858..8326ef949858 100644 --- a/services/java/com/android/server/location/CountryDetectorBase.java +++ b/services/core/java/com/android/server/location/CountryDetectorBase.java diff --git a/services/java/com/android/server/location/FlpHardwareProvider.java b/services/core/java/com/android/server/location/FlpHardwareProvider.java index fab84a85ae0c..fab84a85ae0c 100644 --- a/services/java/com/android/server/location/FlpHardwareProvider.java +++ b/services/core/java/com/android/server/location/FlpHardwareProvider.java diff --git a/services/java/com/android/server/location/FusedLocationHardwareSecure.java b/services/core/java/com/android/server/location/FusedLocationHardwareSecure.java index 389bd2477c84..389bd2477c84 100644 --- a/services/java/com/android/server/location/FusedLocationHardwareSecure.java +++ b/services/core/java/com/android/server/location/FusedLocationHardwareSecure.java diff --git a/services/java/com/android/server/location/FusedProxy.java b/services/core/java/com/android/server/location/FusedProxy.java index f7fac774c979..f7fac774c979 100644 --- a/services/java/com/android/server/location/FusedProxy.java +++ b/services/core/java/com/android/server/location/FusedProxy.java diff --git a/services/java/com/android/server/location/GeocoderProxy.java b/services/core/java/com/android/server/location/GeocoderProxy.java index 5d4a7701fbfb..5d4a7701fbfb 100644 --- a/services/java/com/android/server/location/GeocoderProxy.java +++ b/services/core/java/com/android/server/location/GeocoderProxy.java diff --git a/services/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java index e24bf7620fe3..e24bf7620fe3 100644 --- a/services/java/com/android/server/location/GeofenceManager.java +++ b/services/core/java/com/android/server/location/GeofenceManager.java diff --git a/services/java/com/android/server/location/GeofenceProxy.java b/services/core/java/com/android/server/location/GeofenceProxy.java index bbc1f472387f..bbc1f472387f 100644 --- a/services/java/com/android/server/location/GeofenceProxy.java +++ b/services/core/java/com/android/server/location/GeofenceProxy.java diff --git a/services/java/com/android/server/location/GeofenceState.java b/services/core/java/com/android/server/location/GeofenceState.java index 3ebe20a7e8e6..3ebe20a7e8e6 100644 --- a/services/java/com/android/server/location/GeofenceState.java +++ b/services/core/java/com/android/server/location/GeofenceState.java diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java index 9c76c19051e8..9c76c19051e8 100644 --- a/services/java/com/android/server/location/GpsLocationProvider.java +++ b/services/core/java/com/android/server/location/GpsLocationProvider.java diff --git a/services/java/com/android/server/location/GpsXtraDownloader.java b/services/core/java/com/android/server/location/GpsXtraDownloader.java index e4200736fd8e..e4200736fd8e 100644 --- a/services/java/com/android/server/location/GpsXtraDownloader.java +++ b/services/core/java/com/android/server/location/GpsXtraDownloader.java diff --git a/services/java/com/android/server/location/LocationBasedCountryDetector.java b/services/core/java/com/android/server/location/LocationBasedCountryDetector.java index 03db621c03a8..03db621c03a8 100644 --- a/services/java/com/android/server/location/LocationBasedCountryDetector.java +++ b/services/core/java/com/android/server/location/LocationBasedCountryDetector.java diff --git a/services/java/com/android/server/location/LocationBlacklist.java b/services/core/java/com/android/server/location/LocationBlacklist.java index 6f22689320ca..6f22689320ca 100644 --- a/services/java/com/android/server/location/LocationBlacklist.java +++ b/services/core/java/com/android/server/location/LocationBlacklist.java diff --git a/services/java/com/android/server/location/LocationFudger.java b/services/core/java/com/android/server/location/LocationFudger.java index 2a68743c578d..2a68743c578d 100644 --- a/services/java/com/android/server/location/LocationFudger.java +++ b/services/core/java/com/android/server/location/LocationFudger.java diff --git a/services/java/com/android/server/location/LocationProviderInterface.java b/services/core/java/com/android/server/location/LocationProviderInterface.java index 6f0923233e19..6f0923233e19 100644 --- a/services/java/com/android/server/location/LocationProviderInterface.java +++ b/services/core/java/com/android/server/location/LocationProviderInterface.java diff --git a/services/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java index 14db862065e3..14db862065e3 100644 --- a/services/java/com/android/server/location/LocationProviderProxy.java +++ b/services/core/java/com/android/server/location/LocationProviderProxy.java diff --git a/services/java/com/android/server/location/MockProvider.java b/services/core/java/com/android/server/location/MockProvider.java index 36c43ff1ce1d..36c43ff1ce1d 100644 --- a/services/java/com/android/server/location/MockProvider.java +++ b/services/core/java/com/android/server/location/MockProvider.java diff --git a/services/java/com/android/server/location/PassiveProvider.java b/services/core/java/com/android/server/location/PassiveProvider.java index 71bae07680a3..71bae07680a3 100644 --- a/services/java/com/android/server/location/PassiveProvider.java +++ b/services/core/java/com/android/server/location/PassiveProvider.java diff --git a/services/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java index f91ea8c03a39..f91ea8c03a39 100644 --- a/services/java/com/android/server/media/MediaRouterService.java +++ b/services/core/java/com/android/server/media/MediaRouterService.java diff --git a/services/java/com/android/server/media/RemoteDisplayProviderProxy.java b/services/core/java/com/android/server/media/RemoteDisplayProviderProxy.java index a5fe9f2ceb39..a5fe9f2ceb39 100644 --- a/services/java/com/android/server/media/RemoteDisplayProviderProxy.java +++ b/services/core/java/com/android/server/media/RemoteDisplayProviderProxy.java diff --git a/services/java/com/android/server/media/RemoteDisplayProviderWatcher.java b/services/core/java/com/android/server/media/RemoteDisplayProviderWatcher.java index 6a5f563683a3..6a5f563683a3 100644 --- a/services/java/com/android/server/media/RemoteDisplayProviderWatcher.java +++ b/services/core/java/com/android/server/media/RemoteDisplayProviderWatcher.java diff --git a/services/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java index a2e9d6768696..a2e9d6768696 100644 --- a/services/java/com/android/server/net/LockdownVpnTracker.java +++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java diff --git a/services/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java index 397f9f41d8a0..397f9f41d8a0 100644 --- a/services/java/com/android/server/net/NetworkIdentitySet.java +++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index eb7cc4c89e4d..eb7cc4c89e4d 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java diff --git a/services/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 475482f6dd0b..475482f6dd0b 100644 --- a/services/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java diff --git a/services/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index cea084b51849..cea084b51849 100644 --- a/services/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 5d6adc22685e..5d6adc22685e 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java new file mode 100644 index 000000000000..df2aaca49eca --- /dev/null +++ b/services/core/java/com/android/server/notification/NotificationDelegate.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2013, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.notification; + +public interface NotificationDelegate { + void onSetDisabled(int status); + void onClearAll(); + void onNotificationClick(String pkg, String tag, int id); + void onNotificationClear(String pkg, String tag, int id); + void onNotificationError(String pkg, String tag, int id, + int uid, int initialPid, String message); + void onPanelRevealed(); +} diff --git a/services/core/java/com/android/server/notification/NotificationManagerInternal.java b/services/core/java/com/android/server/notification/NotificationManagerInternal.java new file mode 100644 index 000000000000..b695b6819b4f --- /dev/null +++ b/services/core/java/com/android/server/notification/NotificationManagerInternal.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.notification; + +import android.app.Notification; + +public interface NotificationManagerInternal { + void enqueueNotification(String pkg, String basePkg, int callingUid, int callingPid, + String tag, int id, Notification notification, int[] idReceived, int userId); +} diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 04386759df50..2ba6c711bce3 100644 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.notification; import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import static org.xmlpull.v1.XmlPullParser.END_TAG; @@ -47,7 +47,6 @@ import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Bitmap; import android.media.AudioManager; -import android.media.IAudioService; import android.media.IRingtonePlayer; import android.net.Uri; import android.os.Binder; @@ -56,9 +55,7 @@ import android.os.IBinder; import android.os.Message; import android.os.Process; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.UserHandle; -import android.os.UserManager; import android.os.Vibrator; import android.provider.Settings; import android.service.notification.INotificationListener; @@ -78,6 +75,12 @@ import android.widget.Toast; import com.android.internal.R; import com.android.internal.notification.NotificationScorer; +import com.android.server.EventLogTags; +import com.android.server.statusbar.StatusBarManagerInternal; +import com.android.server.SystemService; +import com.android.server.lights.Light; +import com.android.server.lights.LightsManager; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -99,66 +102,61 @@ import java.util.Set; import libcore.io.IoUtils; - /** {@hide} */ -public class NotificationManagerService extends INotificationManager.Stub -{ - private static final String TAG = "NotificationService"; - private static final boolean DBG = false; +public class NotificationManagerService extends SystemService { + static final String TAG = "NotificationService"; + static final boolean DBG = false; - private static final int MAX_PACKAGE_NOTIFICATIONS = 50; + static final int MAX_PACKAGE_NOTIFICATIONS = 50; // message codes - private static final int MESSAGE_TIMEOUT = 2; + static final int MESSAGE_TIMEOUT = 2; - private static final int LONG_DELAY = 3500; // 3.5 seconds - private static final int SHORT_DELAY = 2000; // 2 seconds + static final int LONG_DELAY = 3500; // 3.5 seconds + static final int SHORT_DELAY = 2000; // 2 seconds - private static final long[] DEFAULT_VIBRATE_PATTERN = {0, 250, 250, 250}; - private static final int VIBRATE_PATTERN_MAXLEN = 8 * 2 + 1; // up to eight bumps + static final long[] DEFAULT_VIBRATE_PATTERN = {0, 250, 250, 250}; + static final int VIBRATE_PATTERN_MAXLEN = 8 * 2 + 1; // up to eight bumps - private static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION; - private static final boolean SCORE_ONGOING_HIGHER = false; + static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION; + static final boolean SCORE_ONGOING_HIGHER = false; - private static final int JUNK_SCORE = -1000; - private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10; - private static final int SCORE_DISPLAY_THRESHOLD = Notification.PRIORITY_MIN * NOTIFICATION_PRIORITY_MULTIPLIER; + static final int JUNK_SCORE = -1000; + static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10; + static final int SCORE_DISPLAY_THRESHOLD = Notification.PRIORITY_MIN * NOTIFICATION_PRIORITY_MULTIPLIER; // Notifications with scores below this will not interrupt the user, either via LED or // sound or vibration - private static final int SCORE_INTERRUPTION_THRESHOLD = + static final int SCORE_INTERRUPTION_THRESHOLD = Notification.PRIORITY_LOW * NOTIFICATION_PRIORITY_MULTIPLIER; - private static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true; - private static final boolean ENABLE_BLOCKED_TOASTS = true; + static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true; + static final boolean ENABLE_BLOCKED_TOASTS = true; - private static final String ENABLED_NOTIFICATION_LISTENERS_SEPARATOR = ":"; + static final String ENABLED_NOTIFICATION_LISTENERS_SEPARATOR = ":"; - final Context mContext; - final IActivityManager mAm; - final UserManager mUserManager; - final IBinder mForegroundToken = new Binder(); + private IActivityManager mAm; + AudioManager mAudioManager; + StatusBarManagerInternal mStatusBar; + Vibrator mVibrator; + final IBinder mForegroundToken = new Binder(); private WorkerHandler mHandler; - private StatusBarManagerService mStatusBar; - private LightsService.Light mNotificationLight; - private LightsService.Light mAttentionLight; + private Light mNotificationLight; + Light mAttentionLight; private int mDefaultNotificationColor; private int mDefaultNotificationLedOn; - private int mDefaultNotificationLedOff; + private int mDefaultNotificationLedOff; private long[] mDefaultVibrationPattern; - private long[] mFallbackVibrationPattern; - - private boolean mSystemReady; - private int mDisabledNotifications; - private NotificationRecord mSoundNotification; - private NotificationRecord mVibrateNotification; + private long[] mFallbackVibrationPattern; + boolean mSystemReady; - private IAudioService mAudioService; - private Vibrator mVibrator; + int mDisabledNotifications; + NotificationRecord mSoundNotification; + NotificationRecord mVibrateNotification; // for enabling and disabling notification pulse behavior private boolean mScreenOn = true; @@ -166,15 +164,15 @@ public class NotificationManagerService extends INotificationManager.Stub private boolean mNotificationPulseEnabled; // used as a mutex for access to all active notifications & listeners - private final ArrayList<NotificationRecord> mNotificationList = + final ArrayList<NotificationRecord> mNotificationList = new ArrayList<NotificationRecord>(); - private ArrayList<ToastRecord> mToastQueue; + final ArrayList<ToastRecord> mToastQueue = new ArrayList<ToastRecord>(); - private ArrayList<NotificationRecord> mLights = new ArrayList<NotificationRecord>(); - private NotificationRecord mLedNotification; + ArrayList<NotificationRecord> mLights = new ArrayList<NotificationRecord>(); + NotificationRecord mLedNotification; - private final AppOpsManager mAppOps; + private AppOpsManager mAppOps; // contains connections to all connected listeners, including app services // and system listeners @@ -202,9 +200,9 @@ public class NotificationManagerService extends INotificationManager.Stub private static final String TAG_PACKAGE = "package"; private static final String ATTR_NAME = "name"; - private final ArrayList<NotificationScorer> mScorers = new ArrayList<NotificationScorer>(); + final ArrayList<NotificationScorer> mScorers = new ArrayList<NotificationScorer>(); - private class NotificationListenerInfo implements DeathRecipient { + private class NotificationListenerInfo implements IBinder.DeathRecipient { INotificationListener listener; ComponentName component; int userid; @@ -262,7 +260,7 @@ public class NotificationManagerService extends INotificationManager.Stub public void binderDied() { if (connection == null) { // This is not a service; it won't be recreated. We can give up this connection. - unregisterListener(this.listener, this.userid); + unregisterListenerImpl(this.listener, this.userid); } } @@ -400,12 +398,14 @@ public class NotificationManagerService extends INotificationManager.Stub tag = parser.getName(); if (type == START_TAG) { if (TAG_BODY.equals(tag)) { - version = Integer.parseInt(parser.getAttributeValue(null, ATTR_VERSION)); + version = Integer.parseInt( + parser.getAttributeValue(null, ATTR_VERSION)); } else if (TAG_BLOCKED_PKGS.equals(tag)) { while ((type = parser.next()) != END_DOCUMENT) { tag = parser.getName(); if (TAG_PACKAGE.equals(tag)) { - mBlockedPackages.add(parser.getAttributeValue(null, ATTR_NAME)); + mBlockedPackages.add( + parser.getAttributeValue(null, ATTR_NAME)); } else if (TAG_BLOCKED_PKGS.equals(tag) && type == END_TAG) { break; } @@ -428,15 +428,6 @@ public class NotificationManagerService extends INotificationManager.Stub } } - /** - * Use this when you just want to know if notifications are OK for this package. - */ - public boolean areNotificationsEnabledForPackage(String pkg, int uid) { - checkCallerIsSystem(); - return (mAppOps.checkOpNoThrow(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg) - == AppOpsManager.MODE_ALLOWED); - } - /** Use this when you actually want to post a notification or toast. * * Unchecked. Not exposed via Binder, but can be called in the course of enqueue*(). @@ -450,21 +441,6 @@ public class NotificationManagerService extends INotificationManager.Stub return true; } - public void setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled) { - checkCallerIsSystem(); - - Slog.v(TAG, (enabled?"en":"dis") + "abling notifications for " + pkg); - - mAppOps.setMode(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg, - enabled ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED); - - // Now, cancel any outstanding notifications that are part of a just-disabled app - if (ENABLE_BLOCKED_NOTIFICATIONS && !enabled) { - cancelAllNotificationsInt(pkg, 0, 0, true, UserHandle.getUserId(uid)); - } - } - - private static String idDebugString(Context baseContext, String packageName, int id) { Context c = null; @@ -490,57 +466,6 @@ public class NotificationManagerService extends INotificationManager.Stub } } - /** - * System-only API for getting a list of current (i.e. not cleared) notifications. - * - * Requires ACCESS_NOTIFICATIONS which is signature|system. - */ - @Override - public StatusBarNotification[] getActiveNotifications(String callingPkg) { - // enforce() will ensure the calling uid has the correct permission - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS, - "NotificationManagerService.getActiveNotifications"); - - StatusBarNotification[] tmp = null; - int uid = Binder.getCallingUid(); - - // noteOp will check to make sure the callingPkg matches the uid - if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg) - == AppOpsManager.MODE_ALLOWED) { - synchronized (mNotificationList) { - tmp = new StatusBarNotification[mNotificationList.size()]; - final int N = mNotificationList.size(); - for (int i=0; i<N; i++) { - tmp[i] = mNotificationList.get(i).sbn; - } - } - } - return tmp; - } - - /** - * System-only API for getting a list of recent (cleared, no longer shown) notifications. - * - * Requires ACCESS_NOTIFICATIONS which is signature|system. - */ - @Override - public StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count) { - // enforce() will ensure the calling uid has the correct permission - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS, - "NotificationManagerService.getHistoricalNotifications"); - - StatusBarNotification[] tmp = null; - int uid = Binder.getCallingUid(); - - // noteOp will check to make sure the callingPkg matches the uid - if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg) - == AppOpsManager.MODE_ALLOWED) { - synchronized (mArchive) { - tmp = mArchive.getArray(count); - } - } - return tmp; - } /** * Remove notification access for any services that no longer exist. @@ -548,12 +473,12 @@ public class NotificationManagerService extends INotificationManager.Stub void disableNonexistentListeners() { int currentUser = ActivityManager.getCurrentUser(); String flatIn = Settings.Secure.getStringForUser( - mContext.getContentResolver(), + getContext().getContentResolver(), Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, currentUser); if (!TextUtils.isEmpty(flatIn)) { if (DBG) Slog.v(TAG, "flat before: " + flatIn); - PackageManager pm = mContext.getPackageManager(); + PackageManager pm = getContext().getPackageManager(); List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser( new Intent(NotificationListenerService.SERVICE_INTERFACE), PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, @@ -589,7 +514,7 @@ public class NotificationManagerService extends INotificationManager.Stub } if (DBG) Slog.v(TAG, "flat after: " + flatOut); if (!flatIn.equals(flatOut)) { - Settings.Secure.putStringForUser(mContext.getContentResolver(), + Settings.Secure.putStringForUser(getContext().getContentResolver(), Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, flatOut, currentUser); } @@ -603,7 +528,7 @@ public class NotificationManagerService extends INotificationManager.Stub void rebindListenerServices() { final int currentUser = ActivityManager.getCurrentUser(); String flat = Settings.Secure.getStringForUser( - mContext.getContentResolver(), + getContext().getContentResolver(), Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, currentUser); @@ -652,28 +577,6 @@ public class NotificationManagerService extends INotificationManager.Stub } } - /** - * Register a listener binder directly with the notification manager. - * - * Only works with system callers. Apps should extend - * {@link android.service.notification.NotificationListenerService}. - */ - @Override - public void registerListener(final INotificationListener listener, - final ComponentName component, final int userid) { - checkCallerIsSystem(); - - synchronized (mNotificationList) { - try { - NotificationListenerInfo info - = new NotificationListenerInfo(listener, component, userid, true); - listener.asBinder().linkToDeath(info, 0); - mListeners.add(info); - } catch (RemoteException e) { - // already dead - } - } - } /** * Version of registerListener that takes the name of a @@ -703,7 +606,7 @@ public class NotificationManagerService extends INotificationManager.Stub if (DBG) Slog.v(TAG, " disconnecting old listener: " + info.listener); mListeners.remove(i); if (info.connection != null) { - mContext.unbindService(info.connection); + getContext().unbindService(info.connection); } } } @@ -713,21 +616,25 @@ public class NotificationManagerService extends INotificationManager.Stub intent.putExtra(Intent.EXTRA_CLIENT_LABEL, R.string.notification_listener_binding_label); - intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( - mContext, 0, new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS), 0)); + + final PendingIntent pendingIntent = PendingIntent.getActivity( + getContext(), 0, new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS), 0); + intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent); try { if (DBG) Slog.v(TAG, "binding: " + intent); - if (!mContext.bindServiceAsUser(intent, + if (!getContext().bindServiceAsUser(intent, new ServiceConnection() { INotificationListener mListener; + @Override public void onServiceConnected(ComponentName name, IBinder service) { synchronized (mNotificationList) { mServicesBinding.remove(servicesBindingTag); try { mListener = INotificationListener.Stub.asInterface(service); - NotificationListenerInfo info = new NotificationListenerInfo( + NotificationListenerInfo info + = new NotificationListenerInfo( mListener, name, userid, this); service.linkToDeath(info, 0); mListeners.add(info); @@ -756,28 +663,6 @@ public class NotificationManagerService extends INotificationManager.Stub } } - /** - * Remove a listener binder directly - */ - @Override - public void unregisterListener(INotificationListener listener, int userid) { - // no need to check permissions; if your listener binder is in the list, - // that's proof that you had permission to add it in the first place - - synchronized (mNotificationList) { - final int N = mListeners.size(); - for (int i=N-1; i>=0; i--) { - final NotificationListenerInfo info = mListeners.get(i); - if (info.listener.asBinder() == listener.asBinder() - && info.userid == userid) { - mListeners.remove(i); - if (info.connection != null) { - mContext.unbindService(info.connection); - } - } - } - } - } /** * Remove a listener service for the given user by ComponentName @@ -794,7 +679,7 @@ public class NotificationManagerService extends INotificationManager.Stub mListeners.remove(i); if (info.connection != null) { try { - mContext.unbindService(info.connection); + getContext().unbindService(info.connection); } catch (IllegalArgumentException ex) { // something happened to the service: we think we have a connection // but it's bogus. @@ -809,7 +694,7 @@ public class NotificationManagerService extends INotificationManager.Stub /** * asynchronously notify all listeners about a new notification */ - private void notifyPostedLocked(NotificationRecord n) { + void notifyPostedLocked(NotificationRecord n) { // make a copy in case changes are made to the underlying Notification object final StatusBarNotification sbn = n.sbn.clone(); for (final NotificationListenerInfo info : mListeners) { @@ -824,7 +709,7 @@ public class NotificationManagerService extends INotificationManager.Stub /** * asynchronously notify all listeners about a removed notification */ - private void notifyRemovedLocked(NotificationRecord n) { + void notifyRemovedLocked(NotificationRecord n) { // make a copy in case changes are made to the underlying Notification object // NOTE: this copy is lightweight: it doesn't include heavyweight parts of the notification final StatusBarNotification sbn_light = n.sbn.cloneLight(); @@ -840,7 +725,14 @@ public class NotificationManagerService extends INotificationManager.Stub // -- APIs to support listeners clicking/clearing notifications -- + private void checkNullListener(INotificationListener listener) { + if (listener == null) { + throw new IllegalArgumentException("Listener must not be null"); + } + } + private NotificationListenerInfo checkListenerToken(INotificationListener listener) { + checkNullListener(listener); final IBinder token = listener.asBinder(); final int N = mListeners.size(); for (int i=0; i<N; i++) { @@ -850,66 +742,7 @@ public class NotificationManagerService extends INotificationManager.Stub throw new SecurityException("Disallowed call from unknown listener: " + listener); } - /** - * Allow an INotificationListener to simulate a "clear all" operation. - * - * {@see com.android.server.StatusBarManagerService.NotificationCallbacks#onClearAllNotifications} - * - * @param token The binder for the listener, to check that the caller is allowed - */ - public void cancelAllNotificationsFromListener(INotificationListener token) { - NotificationListenerInfo info = checkListenerToken(token); - long identity = Binder.clearCallingIdentity(); - try { - cancelAll(info.userid); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - /** - * Allow an INotificationListener to simulate clearing (dismissing) a single notification. - * - * {@see com.android.server.StatusBarManagerService.NotificationCallbacks#onNotificationClear} - * - * @param token The binder for the listener, to check that the caller is allowed - */ - public void cancelNotificationFromListener(INotificationListener token, String pkg, String tag, int id) { - NotificationListenerInfo info = checkListenerToken(token); - long identity = Binder.clearCallingIdentity(); - try { - cancelNotification(pkg, tag, id, 0, - Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE, - true, - info.userid); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - /** - * Allow an INotificationListener to request the list of outstanding notifications seen by - * the current user. Useful when starting up, after which point the listener callbacks should - * be used. - * - * @param token The binder for the listener, to check that the caller is allowed - */ - public StatusBarNotification[] getActiveNotificationsFromListener(INotificationListener token) { - NotificationListenerInfo info = checkListenerToken(token); - StatusBarNotification[] result = new StatusBarNotification[0]; - ArrayList<StatusBarNotification> list = new ArrayList<StatusBarNotification>(); - synchronized (mNotificationList) { - final int N = mNotificationList.size(); - for (int i=0; i<N; i++) { - StatusBarNotification sbn = mNotificationList.get(i).sbn; - if (info.enabledAndUserMatches(sbn)) { - list.add(sbn); - } - } - } - return list.toArray(result); - } // -- end of listener APIs -- @@ -992,8 +825,8 @@ public class NotificationManagerService extends INotificationManager.Stub return String.format( "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s score=%d: %s)", System.identityHashCode(this), - this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(), this.sbn.getTag(), - this.sbn.getScore(), this.sbn.getNotification()); + this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(), + this.sbn.getTag(), this.sbn.getScore(), this.sbn.getNotification()); } } @@ -1031,9 +864,9 @@ public class NotificationManagerService extends INotificationManager.Stub } } - private StatusBarManagerService.NotificationCallbacks mNotificationCallbacks - = new StatusBarManagerService.NotificationCallbacks() { + private final NotificationDelegate mNotificationDelegate = new NotificationDelegate() { + @Override public void onSetDisabled(int status) { synchronized (mNotificationList) { mDisabledNotifications = status; @@ -1041,7 +874,7 @@ public class NotificationManagerService extends INotificationManager.Stub // cancel whatever's going on long identity = Binder.clearCallingIdentity(); try { - final IRingtonePlayer player = mAudioService.getRingtonePlayer(); + final IRingtonePlayer player = mAudioManager.getRingtonePlayer(); if (player != null) { player.stopAsync(); } @@ -1060,12 +893,14 @@ public class NotificationManagerService extends INotificationManager.Stub } } + @Override public void onClearAll() { // XXX to be totally correct, the caller should tell us which user // this is for. cancelAll(ActivityManager.getCurrentUser()); } + @Override public void onNotificationClick(String pkg, String tag, int id) { // XXX to be totally correct, the caller should tell us which user // this is for. @@ -1074,6 +909,7 @@ public class NotificationManagerService extends INotificationManager.Stub ActivityManager.getCurrentUser()); } + @Override public void onNotificationClear(String pkg, String tag, int id) { // XXX to be totally correct, the caller should tell us which user // this is for. @@ -1082,6 +918,7 @@ public class NotificationManagerService extends INotificationManager.Stub true, ActivityManager.getCurrentUser()); } + @Override public void onPanelRevealed() { synchronized (mNotificationList) { // sound @@ -1089,7 +926,7 @@ public class NotificationManagerService extends INotificationManager.Stub long identity = Binder.clearCallingIdentity(); try { - final IRingtonePlayer player = mAudioService.getRingtonePlayer(); + final IRingtonePlayer player = mAudioManager.getRingtonePlayer(); if (player != null) { player.stopAsync(); } @@ -1114,6 +951,7 @@ public class NotificationManagerService extends INotificationManager.Stub } } + @Override public void onNotificationError(String pkg, String tag, int id, int uid, int initialPid, String message) { Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id @@ -1168,7 +1006,7 @@ public class NotificationManagerService extends INotificationManager.Stub if (packageChanged) { // We cancel notifications for packages which have just been disabled try { - final int enabled = mContext.getPackageManager() + final int enabled = getContext().getPackageManager() .getApplicationEnabledSetting(pkgName); if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED || enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { @@ -1244,7 +1082,7 @@ public class NotificationManagerService extends INotificationManager.Stub } void observe() { - ContentResolver resolver = mContext.getContentResolver(); + ContentResolver resolver = getContext().getContentResolver(); resolver.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI, false, this, UserHandle.USER_ALL); resolver.registerContentObserver(ENABLED_NOTIFICATION_LISTENERS_URI, @@ -1257,7 +1095,7 @@ public class NotificationManagerService extends INotificationManager.Stub } public void update(Uri uri) { - ContentResolver resolver = mContext.getContentResolver(); + ContentResolver resolver = getContext().getContentResolver(); if (uri == null || NOTIFICATION_LIGHT_PULSE_URI.equals(uri)) { boolean pulseEnabled = Settings.System.getInt(resolver, Settings.System.NOTIFICATION_LIGHT_PULSE, 0) != 0; @@ -1287,28 +1125,28 @@ public class NotificationManagerService extends INotificationManager.Stub return out; } - NotificationManagerService(Context context, StatusBarManagerService statusBar, - LightsService lights) - { - super(); - mContext = context; - mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE); + public NotificationManagerService(Context context) { + super(context); + } + + @Override + public void onStart() { mAm = ActivityManagerNative.getDefault(); - mUserManager = (UserManager)context.getSystemService(Context.USER_SERVICE); - mToastQueue = new ArrayList<ToastRecord>(); - mHandler = new WorkerHandler(); + mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE); + mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE); - mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); + mHandler = new WorkerHandler(); importOldBlockDb(); - mStatusBar = statusBar; - statusBar.setNotificationCallbacks(mNotificationCallbacks); + mStatusBar = getLocalService(StatusBarManagerInternal.class); + mStatusBar.setNotificationDelegate(mNotificationDelegate); - mNotificationLight = lights.getLight(LightsService.LIGHT_ID_NOTIFICATIONS); - mAttentionLight = lights.getLight(LightsService.LIGHT_ID_ATTENTION); + final LightsManager lights = getLocalService(LightsManager.class); + mNotificationLight = lights.getLight(LightsManager.LIGHT_ID_NOTIFICATIONS); + mAttentionLight = lights.getLight(LightsManager.LIGHT_ID_ATTENTION); - Resources resources = mContext.getResources(); + Resources resources = getContext().getResources(); mDefaultNotificationColor = resources.getColor( R.color.config_defaultNotificationColor); mDefaultNotificationLedOn = resources.getInteger( @@ -1330,7 +1168,7 @@ public class NotificationManagerService extends INotificationManager.Stub // After that, including subsequent boots, init with notifications turned on. // This works on the first boot because the setup wizard will toggle this // flag at least once and we'll go back to 0 after that. - if (0 == Settings.Global.getInt(mContext.getContentResolver(), + if (0 == Settings.Global.getInt(getContext().getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0)) { mDisabledNotifications = StatusBarManager.DISABLE_NOTIFICATION_ALERTS; } @@ -1343,7 +1181,7 @@ public class NotificationManagerService extends INotificationManager.Stub filter.addAction(Intent.ACTION_USER_PRESENT); filter.addAction(Intent.ACTION_USER_STOPPED); filter.addAction(Intent.ACTION_USER_SWITCHED); - mContext.registerReceiver(mIntentReceiver, filter); + getContext().registerReceiver(mIntentReceiver, filter); IntentFilter pkgFilter = new IntentFilter(); pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED); pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); @@ -1351,9 +1189,9 @@ public class NotificationManagerService extends INotificationManager.Stub pkgFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED); pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); pkgFilter.addDataScheme("package"); - mContext.registerReceiver(mIntentReceiver, pkgFilter); + getContext().registerReceiver(mIntentReceiver, pkgFilter); IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); - mContext.registerReceiver(mIntentReceiver, sdFilter); + getContext().registerReceiver(mIntentReceiver, sdFilter); mSettingsObserver = new SettingsObserver(mHandler); mSettingsObserver.observe(); @@ -1363,9 +1201,9 @@ public class NotificationManagerService extends INotificationManager.Stub R.array.config_notificationScorers); for (String scorerName : notificationScorerNames) { try { - Class<?> scorerClass = mContext.getClassLoader().loadClass(scorerName); + Class<?> scorerClass = getContext().getClassLoader().loadClass(scorerName); NotificationScorer scorer = (NotificationScorer) scorerClass.newInstance(); - scorer.initialize(mContext); + scorer.initialize(getContext()); mScorers.add(scorer); } catch (ClassNotFoundException e) { Slog.w(TAG, "Couldn't find scorer " + scorerName + ".", e); @@ -1375,6 +1213,9 @@ public class NotificationManagerService extends INotificationManager.Stub Slog.w(TAG, "Problem accessing scorer " + scorerName + ".", e); } } + + publishBinderService(Context.NOTIFICATION_SERVICE, mService); + publishLocalService(NotificationManagerInternal.class, mInternalService); } /** @@ -1383,12 +1224,12 @@ public class NotificationManagerService extends INotificationManager.Stub private void importOldBlockDb() { loadBlockDb(); - PackageManager pm = mContext.getPackageManager(); + PackageManager pm = getContext().getPackageManager(); for (String pkg : mBlockedPackages) { PackageInfo info = null; try { info = pm.getPackageInfo(pkg, 0); - setNotificationsEnabledForPackage(pkg, info.applicationInfo.uid, false); + setNotificationsEnabledForPackageImpl(pkg, info.applicationInfo.uid, false); } catch (NameNotFoundException e) { // forget you } @@ -1399,244 +1240,423 @@ public class NotificationManagerService extends INotificationManager.Stub } } - void systemReady() { - mAudioService = IAudioService.Stub.asInterface( - ServiceManager.getService(Context.AUDIO_SERVICE)); + @Override + public void onBootPhase(int phase) { + if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { + // no beeping until we're basically done booting + mSystemReady = true; - // no beeping until we're basically done booting - mSystemReady = true; + // Grab our optional AudioService + mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); - // make sure our listener services are properly bound - rebindListenerServices(); + // make sure our listener services are properly bound + rebindListenerServices(); + } } - // Toasts - // ============================================================================ - public void enqueueToast(String pkg, ITransientNotification callback, int duration) - { - if (DBG) Slog.i(TAG, "enqueueToast pkg=" + pkg + " callback=" + callback + " duration=" + duration); + void setNotificationsEnabledForPackageImpl(String pkg, int uid, boolean enabled) { + Slog.v(TAG, (enabled?"en":"dis") + "abling notifications for " + pkg); - if (pkg == null || callback == null) { - Slog.e(TAG, "Not doing toast. pkg=" + pkg + " callback=" + callback); - return ; + mAppOps.setMode(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg, + enabled ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED); + + // Now, cancel any outstanding notifications that are part of a just-disabled app + if (ENABLE_BLOCKED_NOTIFICATIONS && !enabled) { + cancelAllNotificationsInt(pkg, 0, 0, true, UserHandle.getUserId(uid)); } + } - final boolean isSystemToast = isCallerSystem() || ("android".equals(pkg)); + private final IBinder mService = new INotificationManager.Stub() { + // Toasts + // ============================================================================ - if (ENABLE_BLOCKED_TOASTS && !noteNotificationOp(pkg, Binder.getCallingUid())) { - if (!isSystemToast) { - Slog.e(TAG, "Suppressing toast from package " + pkg + " by user request."); - return; + @Override + public void enqueueToast(String pkg, ITransientNotification callback, int duration) + { + if (DBG) { + Slog.i(TAG, "enqueueToast pkg=" + pkg + " callback=" + callback + + " duration=" + duration); } - } - synchronized (mToastQueue) { - int callingPid = Binder.getCallingPid(); - long callingId = Binder.clearCallingIdentity(); - try { - ToastRecord record; - int index = indexOfToastLocked(pkg, callback); - // If it's already in the queue, we update it in place, we don't - // move it to the end of the queue. - if (index >= 0) { - record = mToastQueue.get(index); - record.update(duration); - } else { - // Limit the number of toasts that any given package except the android - // package can enqueue. Prevents DOS attacks and deals with leaks. - if (!isSystemToast) { - int count = 0; - final int N = mToastQueue.size(); - for (int i=0; i<N; i++) { - final ToastRecord r = mToastQueue.get(i); - if (r.pkg.equals(pkg)) { - count++; - if (count >= MAX_PACKAGE_NOTIFICATIONS) { - Slog.e(TAG, "Package has already posted " + count - + " toasts. Not showing more. Package=" + pkg); - return; + if (pkg == null || callback == null) { + Slog.e(TAG, "Not doing toast. pkg=" + pkg + " callback=" + callback); + return ; + } + + final boolean isSystemToast = isCallerSystem() || ("android".equals(pkg)); + + if (ENABLE_BLOCKED_TOASTS && !noteNotificationOp(pkg, Binder.getCallingUid())) { + if (!isSystemToast) { + Slog.e(TAG, "Suppressing toast from package " + pkg + " by user request."); + return; + } + } + + synchronized (mToastQueue) { + int callingPid = Binder.getCallingPid(); + long callingId = Binder.clearCallingIdentity(); + try { + ToastRecord record; + int index = indexOfToastLocked(pkg, callback); + // If it's already in the queue, we update it in place, we don't + // move it to the end of the queue. + if (index >= 0) { + record = mToastQueue.get(index); + record.update(duration); + } else { + // Limit the number of toasts that any given package except the android + // package can enqueue. Prevents DOS attacks and deals with leaks. + if (!isSystemToast) { + int count = 0; + final int N = mToastQueue.size(); + for (int i=0; i<N; i++) { + final ToastRecord r = mToastQueue.get(i); + if (r.pkg.equals(pkg)) { + count++; + if (count >= MAX_PACKAGE_NOTIFICATIONS) { + Slog.e(TAG, "Package has already posted " + count + + " toasts. Not showing more. Package=" + pkg); + return; + } } - } + } } + + record = new ToastRecord(callingPid, pkg, callback, duration); + mToastQueue.add(record); + index = mToastQueue.size() - 1; + keepProcessAliveLocked(callingPid); } + // If it's at index 0, it's the current toast. It doesn't matter if it's + // new or just been updated. Call back and tell it to show itself. + // If the callback fails, this will remove it from the list, so don't + // assume that it's valid after this. + if (index == 0) { + showNextToastLocked(); + } + } finally { + Binder.restoreCallingIdentity(callingId); + } + } + } - record = new ToastRecord(callingPid, pkg, callback, duration); - mToastQueue.add(record); - index = mToastQueue.size() - 1; - keepProcessAliveLocked(callingPid); + @Override + public void cancelToast(String pkg, ITransientNotification callback) { + Slog.i(TAG, "cancelToast pkg=" + pkg + " callback=" + callback); + + if (pkg == null || callback == null) { + Slog.e(TAG, "Not cancelling notification. pkg=" + pkg + " callback=" + callback); + return ; + } + + synchronized (mToastQueue) { + long callingId = Binder.clearCallingIdentity(); + try { + int index = indexOfToastLocked(pkg, callback); + if (index >= 0) { + cancelToastLocked(index); + } else { + Slog.w(TAG, "Toast already cancelled. pkg=" + pkg + + " callback=" + callback); + } + } finally { + Binder.restoreCallingIdentity(callingId); } - // If it's at index 0, it's the current toast. It doesn't matter if it's - // new or just been updated. Call back and tell it to show itself. - // If the callback fails, this will remove it from the list, so don't - // assume that it's valid after this. - if (index == 0) { - showNextToastLocked(); + } + } + + @Override + public void enqueueNotificationWithTag(String pkg, String basePkg, String tag, int id, + Notification notification, int[] idOut, int userId) throws RemoteException { + enqueueNotificationInternal(pkg, basePkg, Binder.getCallingUid(), + Binder.getCallingPid(), tag, id, notification, idOut, userId); + } + + @Override + public void cancelNotificationWithTag(String pkg, String tag, int id, int userId) { + checkCallerIsSystemOrSameApp(pkg); + userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), + Binder.getCallingUid(), userId, true, false, "cancelNotificationWithTag", pkg); + // Don't allow client applications to cancel foreground service notis. + cancelNotification(pkg, tag, id, 0, + Binder.getCallingUid() == Process.SYSTEM_UID + ? 0 : Notification.FLAG_FOREGROUND_SERVICE, false, userId); + } + + @Override + public void cancelAllNotifications(String pkg, int userId) { + checkCallerIsSystemOrSameApp(pkg); + + userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), + Binder.getCallingUid(), userId, true, false, "cancelAllNotifications", pkg); + + // Calling from user space, don't allow the canceling of actively + // running foreground services. + cancelAllNotificationsInt(pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true, userId); + } + + @Override + public void setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled) { + checkCallerIsSystem(); + + setNotificationsEnabledForPackageImpl(pkg, uid, enabled); + } + + /** + * Use this when you just want to know if notifications are OK for this package. + */ + @Override + public boolean areNotificationsEnabledForPackage(String pkg, int uid) { + checkCallerIsSystem(); + return (mAppOps.checkOpNoThrow(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg) + == AppOpsManager.MODE_ALLOWED); + } + + /** + * System-only API for getting a list of current (i.e. not cleared) notifications. + * + * Requires ACCESS_NOTIFICATIONS which is signature|system. + */ + @Override + public StatusBarNotification[] getActiveNotifications(String callingPkg) { + // enforce() will ensure the calling uid has the correct permission + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_NOTIFICATIONS, + "NotificationManagerService.getActiveNotifications"); + + StatusBarNotification[] tmp = null; + int uid = Binder.getCallingUid(); + + // noteOp will check to make sure the callingPkg matches the uid + if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg) + == AppOpsManager.MODE_ALLOWED) { + synchronized (mNotificationList) { + tmp = new StatusBarNotification[mNotificationList.size()]; + final int N = mNotificationList.size(); + for (int i=0; i<N; i++) { + tmp[i] = mNotificationList.get(i).sbn; + } } - } finally { - Binder.restoreCallingIdentity(callingId); } + return tmp; } - } - public void cancelToast(String pkg, ITransientNotification callback) { - Slog.i(TAG, "cancelToast pkg=" + pkg + " callback=" + callback); + /** + * System-only API for getting a list of recent (cleared, no longer shown) notifications. + * + * Requires ACCESS_NOTIFICATIONS which is signature|system. + */ + @Override + public StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count) { + // enforce() will ensure the calling uid has the correct permission + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_NOTIFICATIONS, + "NotificationManagerService.getHistoricalNotifications"); + + StatusBarNotification[] tmp = null; + int uid = Binder.getCallingUid(); + + // noteOp will check to make sure the callingPkg matches the uid + if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg) + == AppOpsManager.MODE_ALLOWED) { + synchronized (mArchive) { + tmp = mArchive.getArray(count); + } + } + return tmp; + } - if (pkg == null || callback == null) { - Slog.e(TAG, "Not cancelling notification. pkg=" + pkg + " callback=" + callback); - return ; + /** + * Register a listener binder directly with the notification manager. + * + * Only works with system callers. Apps should extend + * {@link android.service.notification.NotificationListenerService}. + */ + @Override + public void registerListener(final INotificationListener listener, + final ComponentName component, final int userid) { + checkCallerIsSystem(); + checkNullListener(listener); + registerListenerImpl(listener, component, userid); } - synchronized (mToastQueue) { - long callingId = Binder.clearCallingIdentity(); + /** + * Remove a listener binder directly + */ + @Override + public void unregisterListener(INotificationListener listener, int userid) { + checkNullListener(listener); + // no need to check permissions; if your listener binder is in the list, + // that's proof that you had permission to add it in the first place + unregisterListenerImpl(listener, userid); + } + + /** + * Allow an INotificationListener to simulate a "clear all" operation. + * + * {@see com.android.server.StatusBarManagerService.NotificationCallbacks#onClearAllNotifications} + * + * @param token The binder for the listener, to check that the caller is allowed + */ + @Override + public void cancelAllNotificationsFromListener(INotificationListener token) { + NotificationListenerInfo info = checkListenerToken(token); + long identity = Binder.clearCallingIdentity(); try { - int index = indexOfToastLocked(pkg, callback); - if (index >= 0) { - cancelToastLocked(index); - } else { - Slog.w(TAG, "Toast already cancelled. pkg=" + pkg + " callback=" + callback); - } + cancelAll(info.userid); } finally { - Binder.restoreCallingIdentity(callingId); + Binder.restoreCallingIdentity(identity); } } - } - private void showNextToastLocked() { - ToastRecord record = mToastQueue.get(0); - while (record != null) { - if (DBG) Slog.d(TAG, "Show pkg=" + record.pkg + " callback=" + record.callback); + /** + * Allow an INotificationListener to simulate clearing (dismissing) a single notification. + * + * {@see com.android.server.StatusBarManagerService.NotificationCallbacks#onNotificationClear} + * + * @param token The binder for the listener, to check that the caller is allowed + */ + @Override + public void cancelNotificationFromListener(INotificationListener token, String pkg, + String tag, int id) { + NotificationListenerInfo info = checkListenerToken(token); + long identity = Binder.clearCallingIdentity(); try { - record.callback.show(); - scheduleTimeoutLocked(record); - return; - } catch (RemoteException e) { - Slog.w(TAG, "Object died trying to show notification " + record.callback - + " in package " + record.pkg); - // remove it from the list and let the process die - int index = mToastQueue.indexOf(record); - if (index >= 0) { - mToastQueue.remove(index); - } - keepProcessAliveLocked(record.pid); - if (mToastQueue.size() > 0) { - record = mToastQueue.get(0); - } else { - record = null; + cancelNotification(pkg, tag, id, 0, + Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE, + true, + info.userid); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + /** + * Allow an INotificationListener to request the list of outstanding notifications seen by + * the current user. Useful when starting up, after which point the listener callbacks + * should be used. + * + * @param token The binder for the listener, to check that the caller is allowed + */ + @Override + public StatusBarNotification[] getActiveNotificationsFromListener( + INotificationListener token) { + NotificationListenerInfo info = checkListenerToken(token); + + StatusBarNotification[] result = new StatusBarNotification[0]; + ArrayList<StatusBarNotification> list = new ArrayList<StatusBarNotification>(); + synchronized (mNotificationList) { + final int N = mNotificationList.size(); + for (int i=0; i<N; i++) { + StatusBarNotification sbn = mNotificationList.get(i).sbn; + if (info.enabledAndUserMatches(sbn)) { + list.add(sbn); + } } } + return list.toArray(result); } - } - private void cancelToastLocked(int index) { - ToastRecord record = mToastQueue.get(index); - try { - record.callback.hide(); - } catch (RemoteException e) { - Slog.w(TAG, "Object died trying to hide notification " + record.callback - + " in package " + record.pkg); - // don't worry about this, we're about to remove it from - // the list anyway + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump NotificationManager from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + dumpImpl(pw); } - mToastQueue.remove(index); - keepProcessAliveLocked(record.pid); - if (mToastQueue.size() > 0) { - // Show the next one. If the callback fails, this will remove - // it from the list, so don't assume that the list hasn't changed - // after this point. - showNextToastLocked(); + }; + + void dumpImpl(PrintWriter pw) { + pw.println("Current Notification Manager state:"); + + pw.println(" Listeners (" + mEnabledListenersForCurrentUser.size() + + ") enabled for current user:"); + for (ComponentName cmpt : mEnabledListenersForCurrentUser) { + pw.println(" " + cmpt); } - } - private void scheduleTimeoutLocked(ToastRecord r) - { - mHandler.removeCallbacksAndMessages(r); - Message m = Message.obtain(mHandler, MESSAGE_TIMEOUT, r); - long delay = r.duration == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY; - mHandler.sendMessageDelayed(m, delay); - } + pw.println(" Live listeners (" + mListeners.size() + "):"); + for (NotificationListenerInfo info : mListeners) { + pw.println(" " + info.component + + " (user " + info.userid + "): " + info.listener + + (info.isSystem?" SYSTEM":"")); + } + + int N; - private void handleTimeout(ToastRecord record) - { - if (DBG) Slog.d(TAG, "Timeout pkg=" + record.pkg + " callback=" + record.callback); synchronized (mToastQueue) { - int index = indexOfToastLocked(record.pkg, record.callback); - if (index >= 0) { - cancelToastLocked(index); + N = mToastQueue.size(); + if (N > 0) { + pw.println(" Toast Queue:"); + for (int i=0; i<N; i++) { + mToastQueue.get(i).dump(pw, " "); + } + pw.println(" "); } + } - } - // lock on mToastQueue - private int indexOfToastLocked(String pkg, ITransientNotification callback) - { - IBinder cbak = callback.asBinder(); - ArrayList<ToastRecord> list = mToastQueue; - int len = list.size(); - for (int i=0; i<len; i++) { - ToastRecord r = list.get(i); - if (r.pkg.equals(pkg) && r.callback.asBinder() == cbak) { - return i; + synchronized (mNotificationList) { + N = mNotificationList.size(); + if (N > 0) { + pw.println(" Notification List:"); + for (int i=0; i<N; i++) { + mNotificationList.get(i).dump(pw, " ", getContext()); + } + pw.println(" "); } - } - return -1; - } - // lock on mToastQueue - private void keepProcessAliveLocked(int pid) - { - int toastCount = 0; // toasts from this pid - ArrayList<ToastRecord> list = mToastQueue; - int N = list.size(); - for (int i=0; i<N; i++) { - ToastRecord r = list.get(i); - if (r.pid == pid) { - toastCount++; + N = mLights.size(); + if (N > 0) { + pw.println(" Lights List:"); + for (int i=0; i<N; i++) { + pw.println(" " + mLights.get(i)); + } + pw.println(" "); } - } - try { - mAm.setProcessForeground(mForegroundToken, pid, toastCount > 0); - } catch (RemoteException e) { - // Shouldn't happen. - } - } - private final class WorkerHandler extends Handler - { - @Override - public void handleMessage(Message msg) - { - switch (msg.what) - { - case MESSAGE_TIMEOUT: - handleTimeout((ToastRecord)msg.obj); + pw.println(" mSoundNotification=" + mSoundNotification); + pw.println(" mVibrateNotification=" + mVibrateNotification); + pw.println(" mDisabledNotifications=0x" + + Integer.toHexString(mDisabledNotifications)); + pw.println(" mSystemReady=" + mSystemReady); + pw.println(" mArchive=" + mArchive.toString()); + Iterator<StatusBarNotification> iter = mArchive.descendingIterator(); + int i=0; + while (iter.hasNext()) { + pw.println(" " + iter.next()); + if (++i >= 5) { + if (iter.hasNext()) pw.println(" ..."); break; + } } - } - } - - // Notifications - // ============================================================================ - public void enqueueNotificationWithTag(String pkg, String basePkg, String tag, int id, - Notification notification, int[] idOut, int userId) - { - enqueueNotificationInternal(pkg, basePkg, Binder.getCallingUid(), Binder.getCallingPid(), - tag, id, notification, idOut, userId); - } - - private final static int clamp(int x, int low, int high) { - return (x < low) ? low : ((x > high) ? high : x); + } } - // Not exposed via Binder; for system use only (otherwise malicious apps could spoof the - // uid/pid of another application) + /** + * The private API only accessible to the system process. + */ + private final NotificationManagerInternal mInternalService = new NotificationManagerInternal() { + @Override + public void enqueueNotification(String pkg, String basePkg, int callingUid, int callingPid, + String tag, int id, Notification notification, int[] idReceived, int userId) { + enqueueNotificationInternal(pkg, basePkg, callingUid, callingPid, tag, id, notification, + idReceived, userId); + } + }; - public void enqueueNotificationInternal(final String pkg, String basePkg, final int callingUid, + void enqueueNotificationInternal(final String pkg, String basePkg, final int callingUid, final int callingPid, final String tag, final int id, final Notification notification, - int[] idOut, int incomingUserId) - { + int[] idOut, int incomingUserId) { if (DBG) { - Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification); + Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + + " notification=" + notification); } checkCallerIsSystemOrSameApp(pkg); final boolean isSystemNotification = isUidSystem(callingUid) || ("android".equals(pkg)); @@ -1787,23 +1807,21 @@ public class NotificationManagerService extends INotificationManager.Stub if (notification.icon != 0) { if (old != null && old.statusBarKey != null) { r.statusBarKey = old.statusBarKey; - long identity = Binder.clearCallingIdentity(); + final long identity = Binder.clearCallingIdentity(); try { mStatusBar.updateNotification(r.statusBarKey, n); - } - finally { + } finally { Binder.restoreCallingIdentity(identity); } } else { - long identity = Binder.clearCallingIdentity(); + final long identity = Binder.clearCallingIdentity(); try { r.statusBarKey = mStatusBar.addNotification(n); if ((n.getNotification().flags & Notification.FLAG_SHOW_LIGHTS) != 0 && canInterrupt) { mAttentionLight.pulse(); } - } - finally { + } finally { Binder.restoreCallingIdentity(identity); } } @@ -1816,33 +1834,32 @@ public class NotificationManagerService extends INotificationManager.Stub } else { Slog.e(TAG, "Not posting notification with icon==0: " + notification); if (old != null && old.statusBarKey != null) { - long identity = Binder.clearCallingIdentity(); + final long identity = Binder.clearCallingIdentity(); try { mStatusBar.removeNotification(old.statusBarKey); - } - finally { + } finally { Binder.restoreCallingIdentity(identity); } notifyRemovedLocked(r); } // ATTENTION: in a future release we will bail out here - // so that we do not play sounds, show lights, etc. for invalid notifications + // so that we do not play sounds, show lights, etc. for invalid + // notifications Slog.e(TAG, "WARNING: In a future release this will crash the app: " + n.getPackageName()); } // If we're not supposed to beep, vibrate, etc. then don't. - if (((mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0) + if (((mDisabledNotifications + & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0) && (!(old != null && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 )) && (r.getUserId() == UserHandle.USER_ALL || (r.getUserId() == userId && r.getUserId() == currentUser)) && canInterrupt - && mSystemReady) { - - final AudioManager audioManager = (AudioManager) mContext - .getSystemService(Context.AUDIO_SERVICE); + && mSystemReady + && mAudioManager != null) { // sound @@ -1861,7 +1878,7 @@ public class NotificationManagerService extends INotificationManager.Stub soundUri = Settings.System.DEFAULT_NOTIFICATION_URI; // check to see if the default notification sound is silent - ContentResolver resolver = mContext.getContentResolver(); + ContentResolver resolver = getContext().getContentResolver(); hasValidSound = Settings.System.getString(resolver, Settings.System.NOTIFICATION_SOUND) != null; } else if (notification.sound != null) { @@ -1870,7 +1887,8 @@ public class NotificationManagerService extends INotificationManager.Stub } if (hasValidSound) { - boolean looping = (notification.flags & Notification.FLAG_INSISTENT) != 0; + boolean looping = + (notification.flags & Notification.FLAG_INSISTENT) != 0; int audioStreamType; if (notification.audioStreamType >= 0) { audioStreamType = notification.audioStreamType; @@ -1880,11 +1898,12 @@ public class NotificationManagerService extends INotificationManager.Stub mSoundNotification = r; // do not play notifications if stream volume is 0 (typically because // ringer mode is silent) or if there is a user of exclusive audio focus - if ((audioManager.getStreamVolume(audioStreamType) != 0) - && !audioManager.isAudioFocusExclusive()) { + if ((mAudioManager.getStreamVolume(audioStreamType) != 0) + && !mAudioManager.isAudioFocusExclusive()) { final long identity = Binder.clearCallingIdentity(); try { - final IRingtonePlayer player = mAudioService.getRingtonePlayer(); + final IRingtonePlayer player = + mAudioManager.getRingtonePlayer(); if (player != null) { player.playAsync(soundUri, user, looping, audioStreamType); } @@ -1904,7 +1923,7 @@ public class NotificationManagerService extends INotificationManager.Stub final boolean convertSoundToVibration = !hasCustomVibrate && hasValidSound - && (audioManager.getRingerMode() + && (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE); // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback. @@ -1912,7 +1931,7 @@ public class NotificationManagerService extends INotificationManager.Stub (notification.defaults & Notification.DEFAULT_VIBRATE) != 0; if ((useDefaultVibrate || convertSoundToVibration || hasCustomVibrate) - && !(audioManager.getRingerMode() + && !(mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)) { mVibrateNotification = r; @@ -1966,8 +1985,158 @@ public class NotificationManagerService extends INotificationManager.Stub idOut[0] = id; } - private void sendAccessibilityEvent(Notification notification, CharSequence packageName) { - AccessibilityManager manager = AccessibilityManager.getInstance(mContext); + void registerListenerImpl(final INotificationListener listener, + final ComponentName component, final int userid) { + synchronized (mNotificationList) { + try { + NotificationListenerInfo info + = new NotificationListenerInfo(listener, component, userid, true); + listener.asBinder().linkToDeath(info, 0); + mListeners.add(info); + } catch (RemoteException e) { + // already dead + } + } + } + + void unregisterListenerImpl(final INotificationListener listener, final int userid) { + synchronized (mNotificationList) { + final int N = mListeners.size(); + for (int i=N-1; i>=0; i--) { + final NotificationListenerInfo info = mListeners.get(i); + if (info.listener.asBinder() == listener.asBinder() + && info.userid == userid) { + mListeners.remove(i); + if (info.connection != null) { + getContext().unbindService(info.connection); + } + } + } + } + } + + void showNextToastLocked() { + ToastRecord record = mToastQueue.get(0); + while (record != null) { + if (DBG) Slog.d(TAG, "Show pkg=" + record.pkg + " callback=" + record.callback); + try { + record.callback.show(); + scheduleTimeoutLocked(record); + return; + } catch (RemoteException e) { + Slog.w(TAG, "Object died trying to show notification " + record.callback + + " in package " + record.pkg); + // remove it from the list and let the process die + int index = mToastQueue.indexOf(record); + if (index >= 0) { + mToastQueue.remove(index); + } + keepProcessAliveLocked(record.pid); + if (mToastQueue.size() > 0) { + record = mToastQueue.get(0); + } else { + record = null; + } + } + } + } + + void cancelToastLocked(int index) { + ToastRecord record = mToastQueue.get(index); + try { + record.callback.hide(); + } catch (RemoteException e) { + Slog.w(TAG, "Object died trying to hide notification " + record.callback + + " in package " + record.pkg); + // don't worry about this, we're about to remove it from + // the list anyway + } + mToastQueue.remove(index); + keepProcessAliveLocked(record.pid); + if (mToastQueue.size() > 0) { + // Show the next one. If the callback fails, this will remove + // it from the list, so don't assume that the list hasn't changed + // after this point. + showNextToastLocked(); + } + } + + private void scheduleTimeoutLocked(ToastRecord r) + { + mHandler.removeCallbacksAndMessages(r); + Message m = Message.obtain(mHandler, MESSAGE_TIMEOUT, r); + long delay = r.duration == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY; + mHandler.sendMessageDelayed(m, delay); + } + + private void handleTimeout(ToastRecord record) + { + if (DBG) Slog.d(TAG, "Timeout pkg=" + record.pkg + " callback=" + record.callback); + synchronized (mToastQueue) { + int index = indexOfToastLocked(record.pkg, record.callback); + if (index >= 0) { + cancelToastLocked(index); + } + } + } + + // lock on mToastQueue + int indexOfToastLocked(String pkg, ITransientNotification callback) + { + IBinder cbak = callback.asBinder(); + ArrayList<ToastRecord> list = mToastQueue; + int len = list.size(); + for (int i=0; i<len; i++) { + ToastRecord r = list.get(i); + if (r.pkg.equals(pkg) && r.callback.asBinder() == cbak) { + return i; + } + } + return -1; + } + + // lock on mToastQueue + void keepProcessAliveLocked(int pid) + { + int toastCount = 0; // toasts from this pid + ArrayList<ToastRecord> list = mToastQueue; + int N = list.size(); + for (int i=0; i<N; i++) { + ToastRecord r = list.get(i); + if (r.pid == pid) { + toastCount++; + } + } + try { + mAm.setProcessForeground(mForegroundToken, pid, toastCount > 0); + } catch (RemoteException e) { + // Shouldn't happen. + } + } + + private final class WorkerHandler extends Handler + { + @Override + public void handleMessage(Message msg) + { + switch (msg.what) + { + case MESSAGE_TIMEOUT: + handleTimeout((ToastRecord)msg.obj); + break; + } + } + } + + + // Notifications + // ============================================================================ + static int clamp(int x, int low, int high) { + return (x < low) ? low : ((x > high) ? high : x); + } + + void sendAccessibilityEvent(Notification notification, CharSequence packageName) { + AccessibilityManager manager = AccessibilityManager.getInstance(getContext()); if (!manager.isEnabled()) { return; } @@ -2001,11 +2170,10 @@ public class NotificationManagerService extends INotificationManager.Stub // status bar if (r.getNotification().icon != 0) { - long identity = Binder.clearCallingIdentity(); + final long identity = Binder.clearCallingIdentity(); try { mStatusBar.removeNotification(r.statusBarKey); - } - finally { + } finally { Binder.restoreCallingIdentity(identity); } r.statusBarKey = null; @@ -2017,7 +2185,7 @@ public class NotificationManagerService extends INotificationManager.Stub mSoundNotification = null; final long identity = Binder.clearCallingIdentity(); try { - final IRingtonePlayer player = mAudioService.getRingtonePlayer(); + final IRingtonePlayer player = mAudioManager.getRingtonePlayer(); if (player != null) { player.stopAsync(); } @@ -2053,7 +2221,7 @@ public class NotificationManagerService extends INotificationManager.Stub * Cancels a notification ONLY if it has all of the {@code mustHaveFlags} * and none of the {@code mustNotHaveFlags}. */ - private void cancelNotification(final String pkg, final String tag, final int id, + void cancelNotification(final String pkg, final String tag, final int id, final int mustHaveFlags, final int mustNotHaveFlags, final boolean sendDelete, final int userId) { // In enqueueNotificationInternal notifications are added by scheduling the @@ -2146,26 +2314,7 @@ public class NotificationManagerService extends INotificationManager.Stub } } - public void cancelNotificationWithTag(String pkg, String tag, int id, int userId) { - checkCallerIsSystemOrSameApp(pkg); - userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), - Binder.getCallingUid(), userId, true, false, "cancelNotificationWithTag", pkg); - // Don't allow client applications to cancel foreground service notis. - cancelNotification(pkg, tag, id, 0, - Binder.getCallingUid() == Process.SYSTEM_UID - ? 0 : Notification.FLAG_FOREGROUND_SERVICE, false, userId); - } - - public void cancelAllNotifications(String pkg, int userId) { - checkCallerIsSystemOrSameApp(pkg); - - userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), - Binder.getCallingUid(), userId, true, false, "cancelAllNotifications", pkg); - // Calling from user space, don't allow the canceling of actively - // running foreground services. - cancelAllNotificationsInt(pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true, userId); - } // Return true if the UID is a system or phone UID and therefore should not have // any notifications or toasts blocked. @@ -2225,7 +2374,7 @@ public class NotificationManagerService extends INotificationManager.Stub } // lock on mNotificationList - private void updateLightsLocked() + void updateLightsLocked() { // handle notification lights if (mLedNotification == null) { @@ -2251,14 +2400,14 @@ public class NotificationManagerService extends INotificationManager.Stub } if (mNotificationPulseEnabled) { // pulse repeatedly - mNotificationLight.setFlashing(ledARGB, LightsService.LIGHT_FLASH_TIMED, + mNotificationLight.setFlashing(ledARGB, Light.LIGHT_FLASH_TIMED, ledOnMS, ledOffMS); } } } // lock on mNotificationList - private int indexOfNotificationLocked(String pkg, String tag, int id, int userId) + int indexOfNotificationLocked(String pkg, String tag, int id, int userId) { ArrayList<NotificationRecord> list = mNotificationList; final int len = list.size(); @@ -2288,81 +2437,4 @@ public class NotificationManagerService extends INotificationManager.Stub updateLightsLocked(); } } - - // ====================================================================== - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump NotificationManager from from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return; - } - - pw.println("Current Notification Manager state:"); - - pw.println(" Listeners (" + mEnabledListenersForCurrentUser.size() - + ") enabled for current user:"); - for (ComponentName cmpt : mEnabledListenersForCurrentUser) { - pw.println(" " + cmpt); - } - - pw.println(" Live listeners (" + mListeners.size() + "):"); - for (NotificationListenerInfo info : mListeners) { - pw.println(" " + info.component - + " (user " + info.userid + "): " + info.listener - + (info.isSystem?" SYSTEM":"")); - } - - int N; - - synchronized (mToastQueue) { - N = mToastQueue.size(); - if (N > 0) { - pw.println(" Toast Queue:"); - for (int i=0; i<N; i++) { - mToastQueue.get(i).dump(pw, " "); - } - pw.println(" "); - } - - } - - synchronized (mNotificationList) { - N = mNotificationList.size(); - if (N > 0) { - pw.println(" Notification List:"); - for (int i=0; i<N; i++) { - mNotificationList.get(i).dump(pw, " ", mContext); - } - pw.println(" "); - } - - N = mLights.size(); - if (N > 0) { - pw.println(" Lights List:"); - for (int i=0; i<N; i++) { - pw.println(" " + mLights.get(i)); - } - pw.println(" "); - } - - pw.println(" mSoundNotification=" + mSoundNotification); - pw.println(" mVibrateNotification=" + mVibrateNotification); - pw.println(" mDisabledNotifications=0x" + Integer.toHexString(mDisabledNotifications)); - pw.println(" mSystemReady=" + mSystemReady); - pw.println(" mArchive=" + mArchive.toString()); - Iterator<StatusBarNotification> iter = mArchive.descendingIterator(); - int i=0; - while (iter.hasNext()) { - pw.println(" " + iter.next()); - if (++i >= 5) { - if (iter.hasNext()) pw.println(" ..."); - break; - } - } - - } - } } diff --git a/services/java/com/android/server/os/SchedulingPolicyService.java b/services/core/java/com/android/server/os/SchedulingPolicyService.java index c0123bf1b0f5..c0123bf1b0f5 100644 --- a/services/java/com/android/server/os/SchedulingPolicyService.java +++ b/services/core/java/com/android/server/os/SchedulingPolicyService.java diff --git a/services/java/com/android/server/pm/BasePermission.java b/services/core/java/com/android/server/pm/BasePermission.java index 4f27408a6fff..4f27408a6fff 100644 --- a/services/java/com/android/server/pm/BasePermission.java +++ b/services/core/java/com/android/server/pm/BasePermission.java diff --git a/services/java/com/android/server/pm/GrantedPermissions.java b/services/core/java/com/android/server/pm/GrantedPermissions.java index 14258a46a564..14258a46a564 100644 --- a/services/java/com/android/server/pm/GrantedPermissions.java +++ b/services/core/java/com/android/server/pm/GrantedPermissions.java diff --git a/services/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 0d2b50316366..6185e5010466 100644 --- a/services/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -16,6 +16,9 @@ package com.android.server.pm; +import com.android.server.SystemService; + +import android.content.Context; import android.content.pm.PackageStats; import android.net.LocalSocket; import android.net.LocalSocketAddress; @@ -25,21 +28,28 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -public final class Installer { +public final class Installer extends SystemService { private static final String TAG = "Installer"; private static final boolean LOCAL_DEBUG = false; InputStream mIn; - OutputStream mOut; - LocalSocket mSocket; byte buf[] = new byte[1024]; - int buflen = 0; + public Installer(Context context) { + super(context); + } + + @Override + public void onStart() { + Slog.i(TAG, "Waiting for installd to be ready."); + ping(); + } + private boolean connect() { if (mSocket != null) { return true; diff --git a/services/java/com/android/server/pm/KeySetManager.java b/services/core/java/com/android/server/pm/KeySetManager.java index 66dc1d13c0e1..66dc1d13c0e1 100644 --- a/services/java/com/android/server/pm/KeySetManager.java +++ b/services/core/java/com/android/server/pm/KeySetManager.java diff --git a/services/java/com/android/server/pm/PackageKeySetData.java b/services/core/java/com/android/server/pm/PackageKeySetData.java index cb60621a851d..cb60621a851d 100644 --- a/services/java/com/android/server/pm/PackageKeySetData.java +++ b/services/core/java/com/android/server/pm/PackageKeySetData.java diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 7e244b96b020..da0c38d5152a 100755 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -38,10 +38,11 @@ import com.android.internal.content.PackageHelper; import com.android.internal.util.FastPrintWriter; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.XmlUtils; -import com.android.server.DeviceStorageMonitorService; import com.android.server.EventLogTags; import com.android.server.IntentResolver; +import com.android.server.ServiceThread; +import com.android.server.LocalServices; import com.android.server.Watchdog; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -92,6 +93,7 @@ import android.content.pm.VerificationParams; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VerifierInfo; import android.content.res.Resources; +import android.hardware.display.DisplayManager; import android.net.Uri; import android.os.Binder; import android.os.Build; @@ -127,7 +129,6 @@ import android.util.Slog; import android.util.SparseArray; import android.util.Xml; import android.view.Display; -import android.view.WindowManager; import java.io.BufferedOutputStream; import java.io.File; @@ -162,6 +163,7 @@ import libcore.io.Libcore; import libcore.io.StructStat; import com.android.internal.R; +import com.android.server.storage.DeviceStorageMonitorInternal; /** * Keep track of all those .apks everywhere. @@ -259,8 +261,7 @@ public class PackageManagerService extends IPackageManager.Stub { static final String mTempContainerPrefix = "smdl2tmp"; - final HandlerThread mHandlerThread = new HandlerThread("PackageManager", - Process.THREAD_PRIORITY_BACKGROUND); + final ServiceThread mHandlerThread; final PackageHandler mHandler; final int mSdkVersion = Build.VERSION.SDK_INT; @@ -1067,6 +1068,12 @@ public class PackageManagerService extends IPackageManager.Stub { return res; } + private static void getDefaultDisplayMetrics(Context context, DisplayMetrics metrics) { + DisplayManager displayManager = (DisplayManager) context.getSystemService( + Context.DISPLAY_SERVICE); + displayManager.getDisplay(Display.DEFAULT_DISPLAY).getMetrics(metrics); + } + public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, @@ -1114,17 +1121,16 @@ public class PackageManagerService extends IPackageManager.Stub { mInstaller = installer; - WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); - Display d = wm.getDefaultDisplay(); - d.getMetrics(mMetrics); + getDefaultDisplayMetrics(context, mMetrics); synchronized (mInstallLock) { // writer synchronized (mPackages) { + mHandlerThread = new ServiceThread(TAG, + Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/); mHandlerThread.start(); mHandler = new PackageHandler(mHandlerThread.getLooper()); - Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName(), - WATCHDOG_TIMEOUT); + Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT); File dataDir = Environment.getDataDirectory(); mAppDataDir = new File(dataDir, "data"); @@ -2540,15 +2546,41 @@ public class PackageManagerService extends IPackageManager.Stub { } } + /** + * Compares two sets of signatures. Returns: + * <br /> + * {@link PackageManager#SIGNATURE_NEITHER_SIGNED}: if both signature sets are null, + * <br /> + * {@link PackageManager#SIGNATURE_FIRST_NOT_SIGNED}: if the first signature set is null, + * <br /> + * {@link PackageManager#SIGNATURE_SECOND_NOT_SIGNED}: if the second signature set is null, + * <br /> + * {@link PackageManager#SIGNATURE_MATCH}: if the two signature sets are identical, + * <br /> + * {@link PackageManager#SIGNATURE_NO_MATCH}: if the two signature sets differ. + */ static int compareSignatures(Signature[] s1, Signature[] s2) { if (s1 == null) { return s2 == null ? PackageManager.SIGNATURE_NEITHER_SIGNED : PackageManager.SIGNATURE_FIRST_NOT_SIGNED; } + if (s2 == null) { return PackageManager.SIGNATURE_SECOND_NOT_SIGNED; } + + if (s1.length != s2.length) { + return PackageManager.SIGNATURE_NO_MATCH; + } + + // Since both signature sets are of size 1, we can compare without HashSets. + if (s1.length == 1) { + return s1[0].equals(s2[0]) ? + PackageManager.SIGNATURE_MATCH : + PackageManager.SIGNATURE_NO_MATCH; + } + HashSet<Signature> set1 = new HashSet<Signature>(); for (Signature sig : s1) { set1.add(sig); @@ -7345,6 +7377,15 @@ public class PackageManagerService extends IPackageManager.Stub { return pkgLite.recommendedInstallLocation; } + private long getMemoryLowThreshold() { + final DeviceStorageMonitorInternal + dsm = LocalServices.getService(DeviceStorageMonitorInternal.class); + if (dsm == null) { + return 0L; + } + return dsm.getMemoryLowThreshold(); + } + /* * Invoke remote method to get package information and install * location values. Override install location based on default @@ -7362,15 +7403,9 @@ public class PackageManagerService extends IPackageManager.Stub { Slog.w(TAG, "Conflicting flags specified for installing on both internal and external"); ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; } else { - final long lowThreshold; - - final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager - .getService(DeviceStorageMonitorService.SERVICE); - if (dsm == null) { + final long lowThreshold = getMemoryLowThreshold(); + if (lowThreshold == 0L) { Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed"); - lowThreshold = 0L; - } else { - lowThreshold = dsm.getMemoryLowThreshold(); } try { @@ -7928,8 +7963,8 @@ public class PackageManagerService extends IPackageManager.Stub { boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException { final long lowThreshold; - final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager - .getService(DeviceStorageMonitorService.SERVICE); + final DeviceStorageMonitorInternal + dsm = LocalServices.getService(DeviceStorageMonitorInternal.class); if (dsm == null) { Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed"); lowThreshold = 0L; @@ -9744,10 +9779,10 @@ public class PackageManagerService extends IPackageManager.Stub { clearExternalStorageDataSync(packageName, userId, true); if (succeeded) { // invoke DeviceStorageMonitor's update method to clear any notifications - DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) - ServiceManager.getService(DeviceStorageMonitorService.SERVICE); + DeviceStorageMonitorInternal + dsm = LocalServices.getService(DeviceStorageMonitorInternal.class); if (dsm != null) { - dsm.updateMemory(); + dsm.checkMemory(); } } if(observer != null) { @@ -11572,12 +11607,17 @@ public class PackageManagerService extends IPackageManager.Stub { return true; } + @Override public boolean isStorageLow() { final long token = Binder.clearCallingIdentity(); try { - final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager - .getService(DeviceStorageMonitorService.SERVICE); - return dsm.isMemoryLow(); + final DeviceStorageMonitorInternal + dsm = LocalServices.getService(DeviceStorageMonitorInternal.class); + if (dsm != null) { + return dsm.isMemoryLow(); + } else { + return false; + } } finally { Binder.restoreCallingIdentity(token); } diff --git a/services/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index b4478610509d..b4478610509d 100644 --- a/services/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java diff --git a/services/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index 7747c8f9ecdf..7747c8f9ecdf 100644 --- a/services/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java diff --git a/services/java/com/android/server/pm/PackageSignatures.java b/services/core/java/com/android/server/pm/PackageSignatures.java index 9a20be7c8d76..9a20be7c8d76 100644 --- a/services/java/com/android/server/pm/PackageSignatures.java +++ b/services/core/java/com/android/server/pm/PackageSignatures.java diff --git a/services/java/com/android/server/pm/PackageVerificationResponse.java b/services/core/java/com/android/server/pm/PackageVerificationResponse.java index b2ae0dd433da..b2ae0dd433da 100644 --- a/services/java/com/android/server/pm/PackageVerificationResponse.java +++ b/services/core/java/com/android/server/pm/PackageVerificationResponse.java diff --git a/services/java/com/android/server/pm/PackageVerificationState.java b/services/core/java/com/android/server/pm/PackageVerificationState.java index 3214e8895fd5..3214e8895fd5 100644 --- a/services/java/com/android/server/pm/PackageVerificationState.java +++ b/services/core/java/com/android/server/pm/PackageVerificationState.java diff --git a/services/java/com/android/server/pm/PendingPackage.java b/services/core/java/com/android/server/pm/PendingPackage.java index c17cc46dbfb5..c17cc46dbfb5 100644 --- a/services/java/com/android/server/pm/PendingPackage.java +++ b/services/core/java/com/android/server/pm/PendingPackage.java diff --git a/services/java/com/android/server/pm/PreferredActivity.java b/services/core/java/com/android/server/pm/PreferredActivity.java index f93ba2fe9c59..89169264b0b6 100644 --- a/services/java/com/android/server/pm/PreferredActivity.java +++ b/services/core/java/com/android/server/pm/PreferredActivity.java @@ -17,7 +17,6 @@ package com.android.server.pm; import com.android.internal.util.XmlUtils; -import com.android.server.PreferredComponent; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; diff --git a/services/java/com/android/server/PreferredComponent.java b/services/core/java/com/android/server/pm/PreferredComponent.java index a7af252ca2ed..f437372e31a0 100644 --- a/services/java/com/android/server/PreferredComponent.java +++ b/services/core/java/com/android/server/pm/PreferredComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.pm; import com.android.internal.util.XmlUtils; diff --git a/services/java/com/android/server/pm/PreferredIntentResolver.java b/services/core/java/com/android/server/pm/PreferredIntentResolver.java index bce24d7b8817..bce24d7b8817 100644 --- a/services/java/com/android/server/pm/PreferredIntentResolver.java +++ b/services/core/java/com/android/server/pm/PreferredIntentResolver.java diff --git a/services/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java index 1d68afa546e8..1d68afa546e8 100644 --- a/services/java/com/android/server/pm/SELinuxMMAC.java +++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java diff --git a/services/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index e59940950136..e59940950136 100644 --- a/services/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java diff --git a/services/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java index ca1eeea69745..ca1eeea69745 100644 --- a/services/java/com/android/server/pm/SharedUserSetting.java +++ b/services/core/java/com/android/server/pm/SharedUserSetting.java diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index c33134a24d19..c33134a24d19 100644 --- a/services/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java diff --git a/services/java/com/android/server/power/DisplayBlanker.java b/services/core/java/com/android/server/power/DisplayBlanker.java index 6072053f96f2..6072053f96f2 100644 --- a/services/java/com/android/server/power/DisplayBlanker.java +++ b/services/core/java/com/android/server/power/DisplayBlanker.java diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/core/java/com/android/server/power/DisplayPowerController.java index 60d44c78e5b6..bd9acb9f69fb 100644 --- a/services/java/com/android/server/power/DisplayPowerController.java +++ b/services/core/java/com/android/server/power/DisplayPowerController.java @@ -16,10 +16,10 @@ package com.android.server.power; -import com.android.server.LightsService; -import com.android.server.TwilightService; -import com.android.server.TwilightService.TwilightState; -import com.android.server.display.DisplayManagerService; +import com.android.server.lights.LightsManager; +import com.android.server.twilight.TwilightListener; +import com.android.server.twilight.TwilightManager; +import com.android.server.twilight.TwilightState; import android.animation.Animator; import android.animation.ObjectAnimator; @@ -179,13 +179,10 @@ final class DisplayPowerController { private Handler mCallbackHandler; // The lights service. - private final LightsService mLights; + private final LightsManager mLights; // The twilight service. - private final TwilightService mTwilight; - - // The display manager. - private final DisplayManagerService mDisplayManager; + private final TwilightManager mTwilight; // The sensor manager. private final SensorManager mSensorManager; @@ -196,6 +193,9 @@ final class DisplayPowerController { // The light sensor, or null if not available or needed. private Sensor mLightSensor; + // The doze screen brightness. + private final int mScreenBrightnessDozeConfig; + // The dim screen brightness. private final int mScreenBrightnessDimConfig; @@ -351,8 +351,7 @@ final class DisplayPowerController { * Creates the display power controller. */ public DisplayPowerController(Looper looper, Context context, Notifier notifier, - LightsService lights, TwilightService twilight, SensorManager sensorManager, - DisplayManagerService displayManager, + LightsManager lights, TwilightManager twilight, SensorManager sensorManager, SuspendBlocker displaySuspendBlocker, DisplayBlanker displayBlanker, Callbacks callbacks, Handler callbackHandler) { mHandler = new DisplayControllerHandler(looper); @@ -365,10 +364,12 @@ final class DisplayPowerController { mLights = lights; mTwilight = twilight; mSensorManager = sensorManager; - mDisplayManager = displayManager; final Resources resources = context.getResources(); + mScreenBrightnessDozeConfig = clampAbsoluteBrightness(resources.getInteger( + com.android.internal.R.integer.config_screenBrightnessDoze)); + mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger( com.android.internal.R.integer.config_screenBrightnessDim)); @@ -526,9 +527,8 @@ final class DisplayPowerController { } private void initialize() { - mPowerState = new DisplayPowerState( - new ElectronBeam(mDisplayManager), mDisplayBlanker, - mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT)); + mPowerState = new DisplayPowerState(new ElectronBeam(), mDisplayBlanker, + mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT)); mElectronBeamOnAnimator = ObjectAnimator.ofFloat( mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f); @@ -565,7 +565,7 @@ final class DisplayPowerController { final boolean mustNotify; boolean mustInitialize = false; boolean updateAutoBrightness = mTwilightChanged; - boolean wasDim = false; + boolean wasDimOrDoze = false; mTwilightChanged = false; synchronized (mLock) { @@ -585,7 +585,8 @@ final class DisplayPowerController { != mPendingRequestLocked.screenAutoBrightnessAdjustment) { updateAutoBrightness = true; } - wasDim = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM); + wasDimOrDoze = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM + || mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE); mPowerRequest.copyFrom(mPendingRequestLocked); mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked; mPendingWaitForNegativeProximityLocked = false; @@ -632,12 +633,12 @@ final class DisplayPowerController { // Turn on the light sensor if needed. if (mLightSensor != null) { - setLightSensorEnabled(mPowerRequest.useAutoBrightness - && wantScreenOn(mPowerRequest.screenState), updateAutoBrightness); + setLightSensorEnabled(mPowerRequest.wantLightSensorEnabled(), + updateAutoBrightness); } // Set the screen brightness. - if (wantScreenOn(mPowerRequest.screenState)) { + if (mPowerRequest.wantScreenOnAny()) { int target; boolean slow; if (mScreenAutoBrightness >= 0 && mLightSensorEnabled) { @@ -654,12 +655,16 @@ final class DisplayPowerController { slow = false; mUsingScreenAutoBrightness = false; } - if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) { + if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE) { + // Dim quickly to the doze state. + target = mScreenBrightnessDozeConfig; + slow = false; + } else if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) { // Dim quickly by at least some minimum amount. target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION, mScreenBrightnessDimConfig); slow = false; - } else if (wasDim) { + } else if (wasDimOrDoze) { // Brighten quickly. slow = false; } @@ -672,7 +677,7 @@ final class DisplayPowerController { // Animate the screen on or off. if (!mScreenOffBecauseOfProximity) { - if (wantScreenOn(mPowerRequest.screenState)) { + if (mPowerRequest.wantScreenOnAny()) { // Want screen on. // Wait for previous off animation to complete beforehand. // It is relatively short but if we cancel it and switch to the @@ -1217,6 +1222,7 @@ final class DisplayPowerController { pw.println(); pw.println("Display Controller Configuration:"); + pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig); pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig); pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum); pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum); @@ -1294,15 +1300,6 @@ final class DisplayPowerController { } } - private static boolean wantScreenOn(int state) { - switch (state) { - case DisplayPowerRequest.SCREEN_STATE_BRIGHT: - case DisplayPowerRequest.SCREEN_STATE_DIM: - return true; - } - return false; - } - /** * Asynchronous callbacks from the power controller to the power manager service. */ @@ -1368,8 +1365,7 @@ final class DisplayPowerController { } }; - private final TwilightService.TwilightListener mTwilightListener = - new TwilightService.TwilightListener() { + private final TwilightListener mTwilightListener = new TwilightListener() { @Override public void onTwilightStateChanged() { mTwilightChanged = true; diff --git a/services/java/com/android/server/power/DisplayPowerRequest.java b/services/core/java/com/android/server/power/DisplayPowerRequest.java index 22f17d77ef71..6061a4037d33 100644 --- a/services/java/com/android/server/power/DisplayPowerRequest.java +++ b/services/core/java/com/android/server/power/DisplayPowerRequest.java @@ -30,10 +30,11 @@ import android.os.PowerManager; */ final class DisplayPowerRequest { public static final int SCREEN_STATE_OFF = 0; - public static final int SCREEN_STATE_DIM = 1; - public static final int SCREEN_STATE_BRIGHT = 2; + public static final int SCREEN_STATE_DOZE = 1; + public static final int SCREEN_STATE_DIM = 2; + public static final int SCREEN_STATE_BRIGHT = 3; - // The requested minimum screen power state: off, dim or bright. + // The requested minimum screen power state: off, doze, dim or bright. public int screenState; // If true, the proximity sensor overrides the screen state when an object is @@ -75,6 +76,23 @@ final class DisplayPowerRequest { copyFrom(other); } + // Returns true if we want the screen on in any mode, including doze. + public boolean wantScreenOnAny() { + return screenState != SCREEN_STATE_OFF; + } + + // Returns true if we want the screen on in a normal mode, excluding doze. + // This is usually what we want to tell the rest of the system. For compatibility + // reasons, we pretend the screen is off when dozing. + public boolean wantScreenOnNormal() { + return screenState == SCREEN_STATE_DIM || screenState == SCREEN_STATE_BRIGHT; + } + + public boolean wantLightSensorEnabled() { + // Specifically, we don't want the light sensor while dozing. + return useAutoBrightness && wantScreenOnNormal(); + } + public void copyFrom(DisplayPowerRequest other) { screenState = other.screenState; useProximitySensor = other.useProximitySensor; diff --git a/services/java/com/android/server/power/DisplayPowerState.java b/services/core/java/com/android/server/power/DisplayPowerState.java index fa318f8b6198..42af4b48bde9 100644 --- a/services/java/com/android/server/power/DisplayPowerState.java +++ b/services/core/java/com/android/server/power/DisplayPowerState.java @@ -16,7 +16,7 @@ package com.android.server.power; -import com.android.server.LightsService; +import com.android.server.lights.Light; import android.os.AsyncTask; import android.os.Handler; @@ -56,7 +56,7 @@ final class DisplayPowerState { private final Choreographer mChoreographer; private final ElectronBeam mElectronBeam; private final DisplayBlanker mDisplayBlanker; - private final LightsService.Light mBacklight; + private final Light mBacklight; private final PhotonicModulator mPhotonicModulator; private boolean mScreenOn; @@ -72,7 +72,7 @@ final class DisplayPowerState { private Runnable mCleanListener; public DisplayPowerState(ElectronBeam electronBean, - DisplayBlanker displayBlanker, LightsService.Light backlight) { + DisplayBlanker displayBlanker, Light backlight) { mHandler = new Handler(true /*async*/); mChoreographer = Choreographer.getInstance(); mElectronBeam = electronBean; diff --git a/services/java/com/android/server/power/ElectronBeam.java b/services/core/java/com/android/server/power/ElectronBeam.java index 729bd1669e83..64921d73a784 100644 --- a/services/java/com/android/server/power/ElectronBeam.java +++ b/services/core/java/com/android/server/power/ElectronBeam.java @@ -23,6 +23,8 @@ import java.nio.FloatBuffer; import android.graphics.PixelFormat; import android.graphics.SurfaceTexture; +import android.hardware.display.DisplayManagerInternal; +import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener; import android.opengl.EGL14; import android.opengl.EGLConfig; import android.opengl.EGLContext; @@ -40,8 +42,7 @@ import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceSession; -import com.android.server.display.DisplayManagerService; -import com.android.server.display.DisplayTransactionListener; +import com.android.server.LocalServices; /** * Bzzzoooop! *crackle* @@ -77,7 +78,7 @@ final class ElectronBeam { private boolean mPrepared; private int mMode; - private final DisplayManagerService mDisplayManager; + private final DisplayManagerInternal mDisplayManagerInternal; private int mDisplayLayerStack; // layer stack associated with primary display private int mDisplayWidth; // real width, not rotated private int mDisplayHeight; // real height, not rotated @@ -118,8 +119,8 @@ final class ElectronBeam { public static final int MODE_FADE = 2; - public ElectronBeam(DisplayManagerService displayManager) { - mDisplayManager = displayManager; + public ElectronBeam() { + mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); } /** @@ -138,7 +139,7 @@ final class ElectronBeam { // Get the display size and layer stack. // This is not expected to change while the electron beam surface is showing. - DisplayInfo displayInfo = mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY); + DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY); mDisplayLayerStack = displayInfo.layerStack; mDisplayWidth = displayInfo.getNaturalWidth(); mDisplayHeight = displayInfo.getNaturalHeight(); @@ -527,7 +528,7 @@ final class ElectronBeam { mSurface = new Surface(); mSurface.copyFrom(mSurfaceControl); - mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManager, mSurfaceControl); + mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal, mSurfaceControl); mSurfaceLayout.onDisplayTransaction(); } finally { SurfaceControl.closeTransaction(); @@ -685,20 +686,21 @@ final class ElectronBeam { * owns the electron beam. */ private static final class NaturalSurfaceLayout implements DisplayTransactionListener { - private final DisplayManagerService mDisplayManager; + private final DisplayManagerInternal mDisplayManagerInternal; private SurfaceControl mSurfaceControl; - public NaturalSurfaceLayout(DisplayManagerService displayManager, SurfaceControl surfaceControl) { - mDisplayManager = displayManager; + public NaturalSurfaceLayout(DisplayManagerInternal displayManagerInternal, + SurfaceControl surfaceControl) { + mDisplayManagerInternal = displayManagerInternal; mSurfaceControl = surfaceControl; - mDisplayManager.registerDisplayTransactionListener(this); + mDisplayManagerInternal.registerDisplayTransactionListener(this); } public void dispose() { synchronized (this) { mSurfaceControl = null; } - mDisplayManager.unregisterDisplayTransactionListener(this); + mDisplayManagerInternal.unregisterDisplayTransactionListener(this); } @Override @@ -708,7 +710,8 @@ final class ElectronBeam { return; } - DisplayInfo displayInfo = mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY); + DisplayInfo displayInfo = + mDisplayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY); switch (displayInfo.rotation) { case Surface.ROTATION_0: mSurfaceControl.setPosition(0, 0); diff --git a/services/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index 264e2e9c3b15..264e2e9c3b15 100644 --- a/services/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index da9548f7266e..9ffcc8cfba72 100644 --- a/services/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -20,12 +20,12 @@ import com.android.internal.app.IAppOpsService; import com.android.internal.app.IBatteryStats; import com.android.server.BatteryService; import com.android.server.EventLogTags; -import com.android.server.LightsService; -import com.android.server.TwilightService; +import com.android.server.LocalServices; +import com.android.server.ServiceThread; +import com.android.server.lights.Light; +import com.android.server.lights.LightsManager; +import com.android.server.twilight.TwilightManager; import com.android.server.Watchdog; -import com.android.server.am.ActivityManagerService; -import com.android.server.display.DisplayManagerService; -import com.android.server.dreams.DreamManagerService; import android.Manifest; import android.content.BroadcastReceiver; @@ -38,16 +38,17 @@ import android.content.res.Resources; import android.database.ContentObserver; import android.hardware.SensorManager; import android.hardware.SystemSensorManager; +import android.hardware.display.DisplayManagerInternal; import android.net.Uri; import android.os.BatteryManager; import android.os.Binder; import android.os.Handler; -import android.os.HandlerThread; import android.os.IBinder; import android.os.IPowerManager; import android.os.Looper; import android.os.Message; import android.os.PowerManager; +import android.os.PowerManagerInternal; import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; @@ -56,6 +57,7 @@ import android.os.SystemService; import android.os.UserHandle; import android.os.WorkSource; import android.provider.Settings; +import android.service.dreams.DreamManagerInternal; import android.util.EventLog; import android.util.Log; import android.util.Slog; @@ -72,7 +74,7 @@ import libcore.util.Objects; * The power manager service is responsible for coordinating power management * functions on the device. */ -public final class PowerManagerService extends IPowerManager.Stub +public final class PowerManagerService extends com.android.server.SystemService implements Watchdog.Monitor { private static final String TAG = "PowerManagerService"; @@ -81,7 +83,7 @@ public final class PowerManagerService extends IPowerManager.Stub // Message: Sent when a user activity timeout occurs to update the power state. private static final int MSG_USER_ACTIVITY_TIMEOUT = 1; - // Message: Sent when the device enters or exits a napping or dreaming state. + // Message: Sent when the device enters or exits a dreaming or dozing state. private static final int MSG_SANDMAN = 2; // Message: Sent when the screen on blocker is released. private static final int MSG_SCREEN_ON_BLOCKER_RELEASED = 3; @@ -115,19 +117,21 @@ public final class PowerManagerService extends IPowerManager.Stub // Wakefulness: The device is asleep and can only be awoken by a call to wakeUp(). // The screen should be off or in the process of being turned off by the display controller. + // The device typically passes through the dozing state first. private static final int WAKEFULNESS_ASLEEP = 0; // Wakefulness: The device is fully awake. It can be put to sleep by a call to goToSleep(). - // When the user activity timeout expires, the device may start napping or go to sleep. + // When the user activity timeout expires, the device may start dreaming or go to sleep. private static final int WAKEFULNESS_AWAKE = 1; - // Wakefulness: The device is napping. It is deciding whether to dream or go to sleep - // but hasn't gotten around to it yet. It can be awoken by a call to wakeUp(), which - // ends the nap. User activity may brighten the screen but does not end the nap. - private static final int WAKEFULNESS_NAPPING = 2; // Wakefulness: The device is dreaming. It can be awoken by a call to wakeUp(), // which ends the dream. The device goes to sleep when goToSleep() is called, when // the dream ends or when unplugged. // User activity may brighten the screen but does not end the dream. - private static final int WAKEFULNESS_DREAMING = 3; + private static final int WAKEFULNESS_DREAMING = 2; + // Wakefulness: The device is dozing. It is almost asleep but is allowing a special + // low-power "doze" dream to run which keeps the display on but lets the application + // processor be suspended. It can be awoken by a call to wakeUp() which ends the dream. + // The device fully goes to sleep if the dream cannot be started or ends on its own. + private static final int WAKEFULNESS_DOZING = 3; // Summarizes the state of all active wakelocks. private static final int WAKE_LOCK_CPU = 1 << 0; @@ -136,6 +140,7 @@ public final class PowerManagerService extends IPowerManager.Stub private static final int WAKE_LOCK_BUTTON_BRIGHT = 1 << 3; private static final int WAKE_LOCK_PROXIMITY_SCREEN_OFF = 1 << 4; private static final int WAKE_LOCK_STAY_AWAKE = 1 << 5; // only set if already awake + private static final int WAKE_LOCK_DOZE = 1 << 6; // Summarizes the user activity state. private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0; @@ -162,26 +167,21 @@ public final class PowerManagerService extends IPowerManager.Stub // Poll interval in milliseconds for watching boot animation finished. private static final int BOOT_ANIMATION_POLL_INTERVAL = 200; - // If the battery level drops by this percentage and the user activity timeout - // has expired, then assume the device is receiving insufficient current to charge - // effectively and terminate the dream. - private static final int DREAM_BATTERY_LEVEL_DRAIN_CUTOFF = 5; - - private Context mContext; - private LightsService mLightsService; + private final Context mContext; + private LightsManager mLightsManager; private BatteryService mBatteryService; - private DisplayManagerService mDisplayManagerService; + private DisplayManagerInternal mDisplayManagerInternal; private IBatteryStats mBatteryStats; private IAppOpsService mAppOps; - private HandlerThread mHandlerThread; + private ServiceThread mHandlerThread; private PowerManagerHandler mHandler; private WindowManagerPolicy mPolicy; private Notifier mNotifier; private DisplayPowerController mDisplayPowerController; private WirelessChargerDetector mWirelessChargerDetector; private SettingsObserver mSettingsObserver; - private DreamManagerService mDreamManager; - private LightsService.Light mAttentionLight; + private DreamManagerInternal mDreamManager; + private Light mAttentionLight; private final Object mLock = new Object(); @@ -193,6 +193,10 @@ public final class PowerManagerService extends IPowerManager.Stub // This is distinct from the screen power state, which is managed separately. private int mWakefulness; + // True if the sandman has just been summoned for the first time since entering the + // dreaming or dozing state. Indicates whether a new dream should begin. + private boolean mSandmanSummoned; + // True if MSG_SANDMAN has been scheduled. private boolean mSandmanScheduled; @@ -231,9 +235,6 @@ public final class PowerManagerService extends IPowerManager.Stub // requested because it is updated asynchronously by the display power controller. private final DisplayPowerRequest mDisplayPowerRequest = new DisplayPowerRequest(); - // The time the screen was last turned off, in elapsedRealtime() timebase. - private long mLastScreenOffEventElapsedRealTime; - // True if the display power state has been fully applied, which means the display // is actually on or actually off or whatever was requested. private boolean mDisplayReady; @@ -266,6 +267,14 @@ public final class PowerManagerService extends IPowerManager.Stub // True if boot completed occurred. We keep the screen on until this happens. private boolean mBootCompleted; + // True if auto-suspend mode is enabled. + // Refer to autosuspend.h. + private boolean mAutoSuspendModeEnabled; + + // True if interactive mode is enabled. + // Refer to power.h. + private boolean mInteractiveModeEnabled; + // True if the device is plugged into a power source. private boolean mIsPowered; @@ -283,6 +292,12 @@ public final class PowerManagerService extends IPowerManager.Stub // The current dock state. private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED; + // True to decouple auto-suspend mode from the display state. + private boolean mDecoupleAutoSuspendModeFromDisplayConfig; + + // True to decouple interactive mode from the display state. + private boolean mDecoupleInteractiveModeFromDisplayConfig; + // True if the device should wake up when plugged or unplugged. private boolean mWakeUpWhenPluggedOrUnpluggedConfig; @@ -301,6 +316,22 @@ public final class PowerManagerService extends IPowerManager.Stub // Default value for dreams activate-on-dock private boolean mDreamsActivatedOnDockByDefaultConfig; + // True if dreams can run while not plugged in. + private boolean mDreamsEnabledOnBatteryConfig; + + // Minimum battery level to allow dreaming when powered. + // Use -1 to disable this safety feature. + private int mDreamsBatteryLevelMinimumWhenPoweredConfig; + + // Minimum battery level to allow dreaming when not powered. + // Use -1 to disable this safety feature. + private int mDreamsBatteryLevelMinimumWhenNotPoweredConfig; + + // If the battery level drops by this percentage and the user activity timeout + // has expired, then assume the device is receiving insufficient current to charge + // effectively and terminate the dream. Use -1 to disable this safety feature. + private int mDreamsBatteryLevelDrainCutoffConfig; + // True if dreams are enabled by the user. private boolean mDreamsEnabledSetting; @@ -376,7 +407,9 @@ public final class PowerManagerService extends IPowerManager.Stub private static native void nativeSetInteractive(boolean enable); private static native void nativeSetAutoSuspend(boolean enable); - public PowerManagerService() { + public PowerManagerService(Context context) { + super(context); + mContext = context; synchronized (mLock) { mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks"); mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display"); @@ -392,25 +425,31 @@ public final class PowerManagerService extends IPowerManager.Stub nativeSetPowerState(true, true); } + @Override + public void onStart() { + publishBinderService(Context.POWER_SERVICE, new BinderService()); + publishLocalService(PowerManagerInternal.class, new LocalService()); + } + /** * Initialize the power manager. * Must be called before any other functions within the power manager are called. */ - public void init(Context context, LightsService ls, - ActivityManagerService am, BatteryService bs, IBatteryStats bss, - IAppOpsService appOps, DisplayManagerService dm) { - mContext = context; - mLightsService = ls; + public void init(LightsManager ls, + BatteryService bs, IBatteryStats bss, + IAppOpsService appOps) { + mLightsManager = ls; mBatteryService = bs; mBatteryStats = bss; mAppOps = appOps; - mDisplayManagerService = dm; - mHandlerThread = new HandlerThread(TAG); + mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class); + mHandlerThread = new ServiceThread(TAG, + Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/); mHandlerThread.start(); mHandler = new PowerManagerHandler(mHandlerThread.getLooper()); Watchdog.getInstance().addMonitor(this); - Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName()); + Watchdog.getInstance().addThread(mHandler); // Forcibly turn the screen on at boot so that it is in a known power state. // We do this in init() rather than in the constructor because setting the @@ -421,18 +460,18 @@ public final class PowerManagerService extends IPowerManager.Stub mDisplayBlanker.unblankAllDisplays(); } - public void setPolicy(WindowManagerPolicy policy) { + void setPolicy(WindowManagerPolicy policy) { synchronized (mLock) { mPolicy = policy; } } - public void systemReady(TwilightService twilight, DreamManagerService dreamManager) { + public void systemReady() { synchronized (mLock) { mSystemReady = true; - mDreamManager = dreamManager; + mDreamManager = LocalServices.getService(DreamManagerInternal.class); - PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE); + PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting(); mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting(); mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting(); @@ -448,15 +487,16 @@ public final class PowerManagerService extends IPowerManager.Stub // The display power controller runs on the power manager service's // own handler thread to ensure timely operation. mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(), - mContext, mNotifier, mLightsService, twilight, sensorManager, - mDisplayManagerService, mDisplaySuspendBlocker, mDisplayBlanker, + mContext, mNotifier, mLightsManager, + LocalServices.getService(TwilightManager.class), sensorManager, + mDisplaySuspendBlocker, mDisplayBlanker, mDisplayPowerControllerCallbacks, mHandler); mWirelessChargerDetector = new WirelessChargerDetector(sensorManager, createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"), mHandler); mSettingsObserver = new SettingsObserver(mHandler); - mAttentionLight = mLightsService.getLight(LightsService.LIGHT_ID_ATTENTION); + mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION); // Register for broadcasts from other components of the system. IntentFilter filter = new IntentFilter(); @@ -515,6 +555,10 @@ public final class PowerManagerService extends IPowerManager.Stub private void readConfigurationLocked() { final Resources resources = mContext.getResources(); + mDecoupleAutoSuspendModeFromDisplayConfig = resources.getBoolean( + com.android.internal.R.bool.config_powerDecoupleAutoSuspendModeFromDisplay); + mDecoupleInteractiveModeFromDisplayConfig = resources.getBoolean( + com.android.internal.R.bool.config_powerDecoupleInteractiveModeFromDisplay); mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean( com.android.internal.R.bool.config_unplugTurnsOnScreen); mSuspendWhenScreenOffDueToProximityConfig = resources.getBoolean( @@ -527,6 +571,14 @@ public final class PowerManagerService extends IPowerManager.Stub com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault); mDreamsActivatedOnDockByDefaultConfig = resources.getBoolean( com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault); + mDreamsEnabledOnBatteryConfig = resources.getBoolean( + com.android.internal.R.bool.config_dreamsEnabledOnBattery); + mDreamsBatteryLevelMinimumWhenPoweredConfig = resources.getInteger( + com.android.internal.R.integer.config_dreamsBatteryLevelMinimumWhenPowered); + mDreamsBatteryLevelMinimumWhenNotPoweredConfig = resources.getInteger( + com.android.internal.R.integer.config_dreamsBatteryLevelMinimumWhenNotPowered); + mDreamsBatteryLevelDrainCutoffConfig = resources.getInteger( + com.android.internal.R.integer.config_dreamsBatteryLevelDrainCutoff); } private void updateSettingsLocked() { @@ -579,41 +631,6 @@ public final class PowerManagerService extends IPowerManager.Stub updatePowerStateLocked(); } - @Override // Binder call - public void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName, - int uid) { - acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid)); - } - - @Override // Binder call - public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, - WorkSource ws) { - if (lock == null) { - throw new IllegalArgumentException("lock must not be null"); - } - if (packageName == null) { - throw new IllegalArgumentException("packageName must not be null"); - } - PowerManager.validateWakeLockParameters(flags, tag); - - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); - if (ws != null && ws.size() != 0) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.UPDATE_DEVICE_STATS, null); - } else { - ws = null; - } - - final int uid = Binder.getCallingUid(); - final int pid = Binder.getCallingPid(); - final long ident = Binder.clearCallingIdentity(); - try { - acquireWakeLockInternal(lock, flags, tag, packageName, ws, uid, pid); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName, WorkSource ws, int uid, int pid) { synchronized (mLock) { @@ -668,22 +685,6 @@ public final class PowerManagerService extends IPowerManager.Stub } } - @Override // Binder call - public void releaseWakeLock(IBinder lock, int flags) { - if (lock == null) { - throw new IllegalArgumentException("lock must not be null"); - } - - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); - - final long ident = Binder.clearCallingIdentity(); - try { - releaseWakeLockInternal(lock, flags); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - private void releaseWakeLockInternal(IBinder lock, int flags) { synchronized (mLock) { int index = findWakeLockIndexLocked(lock); @@ -746,43 +747,6 @@ public final class PowerManagerService extends IPowerManager.Stub } } - @Override // Binder call - public void updateWakeLockUids(IBinder lock, int[] uids) { - WorkSource ws = null; - - if (uids != null) { - ws = new WorkSource(); - // XXX should WorkSource have a way to set uids as an int[] instead of adding them - // one at a time? - for (int i = 0; i < uids.length; i++) { - ws.add(uids[i]); - } - } - updateWakeLockWorkSource(lock, ws); - } - - @Override // Binder call - public void updateWakeLockWorkSource(IBinder lock, WorkSource ws) { - if (lock == null) { - throw new IllegalArgumentException("lock must not be null"); - } - - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); - if (ws != null && ws.size() != 0) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.UPDATE_DEVICE_STATS, null); - } else { - ws = null; - } - - final long ident = Binder.clearCallingIdentity(); - try { - updateWakeLockWorkSourceInternal(lock, ws); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - private void updateWakeLockWorkSourceInternal(IBinder lock, WorkSource ws) { synchronized (mLock) { int index = findWakeLockIndexLocked(lock); @@ -834,16 +798,6 @@ public final class PowerManagerService extends IPowerManager.Stub } } - @Override // Binder call - public boolean isWakeLockLevelSupported(int level) { - final long ident = Binder.clearCallingIdentity(); - try { - return isWakeLockLevelSupportedInternal(level); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - @SuppressWarnings("deprecation") private boolean isWakeLockLevelSupportedInternal(int level) { synchronized (mLock) { @@ -852,6 +806,7 @@ public final class PowerManagerService extends IPowerManager.Stub case PowerManager.SCREEN_DIM_WAKE_LOCK: case PowerManager.SCREEN_BRIGHT_WAKE_LOCK: case PowerManager.FULL_WAKE_LOCK: + case PowerManager.DOZE_WAKE_LOCK: return true; case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: @@ -863,40 +818,6 @@ public final class PowerManagerService extends IPowerManager.Stub } } - @Override // Binder call - public void userActivity(long eventTime, int event, int flags) { - final long now = SystemClock.uptimeMillis(); - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER) - != PackageManager.PERMISSION_GRANTED) { - // Once upon a time applications could call userActivity(). - // Now we require the DEVICE_POWER permission. Log a warning and ignore the - // request instead of throwing a SecurityException so we don't break old apps. - synchronized (mLock) { - if (now >= mLastWarningAboutUserActivityPermission + (5 * 60 * 1000)) { - mLastWarningAboutUserActivityPermission = now; - Slog.w(TAG, "Ignoring call to PowerManager.userActivity() because the " - + "caller does not have DEVICE_POWER permission. " - + "Please fix your app! " - + " pid=" + Binder.getCallingPid() - + " uid=" + Binder.getCallingUid()); - } - } - return; - } - - if (eventTime > SystemClock.uptimeMillis()) { - throw new IllegalArgumentException("event time must not be in the future"); - } - - final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - try { - userActivityInternal(eventTime, event, flags, uid); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - // Called from native code. private void userActivityFromNative(long eventTime, int event, int flags) { userActivityInternal(eventTime, event, flags, Process.SYSTEM_UID); @@ -918,7 +839,8 @@ public final class PowerManagerService extends IPowerManager.Stub } if (eventTime < mLastSleepTime || eventTime < mLastWakeTime - || mWakefulness == WAKEFULNESS_ASLEEP || !mBootCompleted || !mSystemReady) { + || mWakefulness == WAKEFULNESS_ASLEEP || mWakefulness == WAKEFULNESS_DOZING + || !mBootCompleted || !mSystemReady) { return false; } @@ -941,22 +863,6 @@ public final class PowerManagerService extends IPowerManager.Stub return false; } - @Override // Binder call - public void wakeUp(long eventTime) { - if (eventTime > SystemClock.uptimeMillis()) { - throw new IllegalArgumentException("event time must not be in the future"); - } - - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); - - final long ident = Binder.clearCallingIdentity(); - try { - wakeUpInternal(eventTime); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - // Called from native code. private void wakeUpFromNative(long eventTime) { wakeUpInternal(eventTime); @@ -983,18 +889,21 @@ public final class PowerManagerService extends IPowerManager.Stub switch (mWakefulness) { case WAKEFULNESS_ASLEEP: Slog.i(TAG, "Waking up from sleep..."); - sendPendingNotificationsLocked(); - mNotifier.onWakeUpStarted(); - mSendWakeUpFinishedNotificationWhenReady = true; break; case WAKEFULNESS_DREAMING: Slog.i(TAG, "Waking up from dream..."); break; - case WAKEFULNESS_NAPPING: - Slog.i(TAG, "Waking up from nap..."); + case WAKEFULNESS_DOZING: + Slog.i(TAG, "Waking up from dozing..."); break; } + if (mWakefulness != WAKEFULNESS_DREAMING) { + sendPendingNotificationsLocked(); + mNotifier.onWakeUpStarted(); + mSendWakeUpFinishedNotificationWhenReady = true; + } + mLastWakeTime = eventTime; mWakefulness = WAKEFULNESS_AWAKE; mDirty |= DIRTY_WAKEFULNESS; @@ -1004,22 +913,6 @@ public final class PowerManagerService extends IPowerManager.Stub return true; } - @Override // Binder call - public void goToSleep(long eventTime, int reason) { - if (eventTime > SystemClock.uptimeMillis()) { - throw new IllegalArgumentException("event time must not be in the future"); - } - - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); - - final long ident = Binder.clearCallingIdentity(); - try { - goToSleepInternal(eventTime, reason); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - // Called from native code. private void goToSleepFromNative(long eventTime, int reason) { goToSleepInternal(eventTime, reason); @@ -1033,13 +926,17 @@ public final class PowerManagerService extends IPowerManager.Stub } } + // This method is called goToSleep for historical reasons but we actually start + // dozing before really going to sleep. @SuppressWarnings("deprecation") private boolean goToSleepNoUpdateLocked(long eventTime, int reason) { if (DEBUG_SPEW) { Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime + ", reason=" + reason); } - if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP + if (eventTime < mLastWakeTime + || mWakefulness == WAKEFULNESS_ASLEEP + || mWakefulness == WAKEFULNESS_DOZING || !mBootCompleted || !mSystemReady) { return false; } @@ -1063,7 +960,8 @@ public final class PowerManagerService extends IPowerManager.Stub mLastSleepTime = eventTime; mDirty |= DIRTY_WAKEFULNESS; - mWakefulness = WAKEFULNESS_ASLEEP; + mWakefulness = WAKEFULNESS_DOZING; + mSandmanSummoned = true; // Report the number of wake locks that will be cleared by going to sleep. int numWakeLocksCleared = 0; @@ -1082,22 +980,6 @@ public final class PowerManagerService extends IPowerManager.Stub return true; } - @Override // Binder call - public void nap(long eventTime) { - if (eventTime > SystemClock.uptimeMillis()) { - throw new IllegalArgumentException("event time must not be in the future"); - } - - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); - - final long ident = Binder.clearCallingIdentity(); - try { - napInternal(eventTime); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - private void napInternal(long eventTime) { synchronized (mLock) { if (napNoUpdateLocked(eventTime)) { @@ -1119,7 +1001,26 @@ public final class PowerManagerService extends IPowerManager.Stub Slog.i(TAG, "Nap time..."); mDirty |= DIRTY_WAKEFULNESS; - mWakefulness = WAKEFULNESS_NAPPING; + mWakefulness = WAKEFULNESS_DREAMING; + mSandmanSummoned = true; + return true; + } + + // Done dozing, drop everything and go to sleep. + private boolean reallyGoToSleepNoUpdateLocked(long eventTime) { + if (DEBUG_SPEW) { + Slog.d(TAG, "reallyGoToSleepNoUpdateLocked: eventTime=" + eventTime); + } + + if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP + || !mBootCompleted || !mSystemReady) { + return false; + } + + Slog.i(TAG, "Sleeping..."); + + mDirty |= DIRTY_WAKEFULNESS; + mWakefulness = WAKEFULNESS_ASLEEP; return true; } @@ -1195,7 +1096,7 @@ public final class PowerManagerService extends IPowerManager.Stub mPlugType = mBatteryService.getPlugType(); mBatteryLevel = mBatteryService.getBatteryLevel(); - if (DEBUG) { + if (DEBUG_SPEW) { Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered + ", mIsPowered=" + mIsPowered + ", oldPlugType=" + oldPlugType @@ -1255,8 +1156,7 @@ public final class PowerManagerService extends IPowerManager.Stub } // If already dreaming and becoming powered, then don't wake. - if (mIsPowered && (mWakefulness == WAKEFULNESS_NAPPING - || mWakefulness == WAKEFULNESS_DREAMING)) { + if (mIsPowered && mWakefulness == WAKEFULNESS_DREAMING) { return false; } @@ -1303,35 +1203,45 @@ public final class PowerManagerService extends IPowerManager.Stub mWakeLockSummary |= WAKE_LOCK_CPU; break; case PowerManager.FULL_WAKE_LOCK: - if (mWakefulness != WAKEFULNESS_ASLEEP) { + if (mWakefulness == WAKEFULNESS_AWAKE + || mWakefulness == WAKEFULNESS_DREAMING) { mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT; - if (mWakefulness == WAKEFULNESS_AWAKE) { - mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE; - } + } + if (mWakefulness == WAKEFULNESS_AWAKE) { + mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE; } break; case PowerManager.SCREEN_BRIGHT_WAKE_LOCK: - if (mWakefulness != WAKEFULNESS_ASLEEP) { + if (mWakefulness == WAKEFULNESS_AWAKE + || mWakefulness == WAKEFULNESS_DREAMING) { mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_BRIGHT; - if (mWakefulness == WAKEFULNESS_AWAKE) { - mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE; - } + } + if (mWakefulness == WAKEFULNESS_AWAKE) { + mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE; } break; case PowerManager.SCREEN_DIM_WAKE_LOCK: - if (mWakefulness != WAKEFULNESS_ASLEEP) { + if (mWakefulness == WAKEFULNESS_AWAKE + || mWakefulness == WAKEFULNESS_DREAMING) { mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_DIM; - if (mWakefulness == WAKEFULNESS_AWAKE) { - mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE; - } + } + if (mWakefulness == WAKEFULNESS_AWAKE) { + mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE; } break; case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: - if (mWakefulness != WAKEFULNESS_ASLEEP) { + if (mWakefulness == WAKEFULNESS_AWAKE + || mWakefulness == WAKEFULNESS_DREAMING + || mWakefulness == WAKEFULNESS_DOZING) { mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF; } break; + case PowerManager.DOZE_WAKE_LOCK: + if (mWakefulness == WAKEFULNESS_DOZING) { + mWakeLockSummary |= WAKE_LOCK_DOZE; + } + break; } } @@ -1356,7 +1266,8 @@ public final class PowerManagerService extends IPowerManager.Stub mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT); long nextTimeout = 0; - if (mWakefulness != WAKEFULNESS_ASLEEP) { + if (mWakefulness == WAKEFULNESS_AWAKE + || mWakefulness == WAKEFULNESS_DREAMING) { final int screenOffTimeout = getScreenOffTimeoutLocked(); final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout); @@ -1377,8 +1288,7 @@ public final class PowerManagerService extends IPowerManager.Stub && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) { nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout; if (now < nextTimeout - && mDisplayPowerRequest.screenState - != DisplayPowerRequest.SCREEN_STATE_OFF) { + && mDisplayPowerRequest.wantScreenOnNormal()) { mUserActivitySummary = mDisplayPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT ? USER_ACTIVITY_SCREEN_BRIGHT : USER_ACTIVITY_SCREEN_DIM; @@ -1440,7 +1350,7 @@ public final class PowerManagerService extends IPowerManager.Stub /** * Updates the wakefulness of the device. * - * This is the function that decides whether the device should start napping + * This is the function that decides whether the device should start dreaming * based on the current wake locks and user activity state. It may modify mDirty * if the wakefulness changes. * @@ -1529,7 +1439,7 @@ public final class PowerManagerService extends IPowerManager.Stub } /** - * Called when the device enters or exits a napping or dreaming state. + * Called when the device enters or exits a dreaming or dozing state. * * We do this asynchronously because we must call out of the power manager to start * the dream and we don't want to hold our lock while doing so. There is a risk that @@ -1537,46 +1447,60 @@ public final class PowerManagerService extends IPowerManager.Stub */ private void handleSandman() { // runs on handler thread // Handle preconditions. - boolean startDreaming = false; + final boolean startDreaming; + final int wakefulness; synchronized (mLock) { mSandmanScheduled = false; - boolean canDream = canDreamLocked(); - if (DEBUG_SPEW) { - Slog.d(TAG, "handleSandman: canDream=" + canDream - + ", mWakefulness=" + wakefulnessToString(mWakefulness)); - } - - if (canDream && mWakefulness == WAKEFULNESS_NAPPING) { - startDreaming = true; + wakefulness = mWakefulness; + if (mSandmanSummoned) { + startDreaming = ((wakefulness == WAKEFULNESS_DREAMING && canDreamLocked()) + || wakefulness == WAKEFULNESS_DOZING); + mSandmanSummoned = false; + } else { + startDreaming = false; } } // Start dreaming if needed. // We only control the dream on the handler thread, so we don't need to worry about // concurrent attempts to start or stop the dream. - boolean isDreaming = false; + final boolean isDreaming; if (mDreamManager != null) { + // Restart the dream whenever the sandman is summoned. if (startDreaming) { - mDreamManager.startDream(); + mDreamManager.stopDream(); + mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING); } isDreaming = mDreamManager.isDreaming(); + } else { + isDreaming = false; } // Update dream state. - // We might need to stop the dream again if the preconditions changed. - boolean continueDreaming = false; synchronized (mLock) { - if (isDreaming && canDreamLocked()) { - if (mWakefulness == WAKEFULNESS_NAPPING) { - mWakefulness = WAKEFULNESS_DREAMING; - mDirty |= DIRTY_WAKEFULNESS; - mBatteryLevelWhenDreamStarted = mBatteryLevel; - updatePowerStateLocked(); - continueDreaming = true; - } else if (mWakefulness == WAKEFULNESS_DREAMING) { - if (!isBeingKeptAwakeLocked() + // Remember the initial battery level when the dream started. + if (startDreaming && isDreaming) { + mBatteryLevelWhenDreamStarted = mBatteryLevel; + if (wakefulness == WAKEFULNESS_DOZING) { + Slog.i(TAG, "Dozing..."); + } else { + Slog.i(TAG, "Dreaming..."); + } + } + + // If preconditions changed, wait for the next iteration to determine + // whether the dream should continue (or be restarted). + if (mSandmanSummoned || mWakefulness != wakefulness) { + return; // wait for next cycle + } + + // Determine whether the dream should continue. + if (wakefulness == WAKEFULNESS_DREAMING) { + if (isDreaming && canDreamLocked()) { + if (mDreamsBatteryLevelDrainCutoffConfig >= 0 && mBatteryLevel < mBatteryLevelWhenDreamStarted - - DREAM_BATTERY_LEVEL_DRAIN_CUTOFF) { + - mDreamsBatteryLevelDrainCutoffConfig + && !isBeingKeptAwakeLocked()) { // If the user activity timeout expired and the battery appears // to be draining faster than it is charging then stop dreaming // and go to sleep. @@ -1586,53 +1510,64 @@ public final class PowerManagerService extends IPowerManager.Stub + mBatteryLevelWhenDreamStarted + "%. " + "Battery level now: " + mBatteryLevel + "%."); } else { - continueDreaming = true; + return; // continue dreaming } } - } - if (!continueDreaming) { - handleDreamFinishedLocked(); + + // Dream has ended or will be stopped. Update the power state. + if (isItBedTimeYetLocked()) { + goToSleepNoUpdateLocked(SystemClock.uptimeMillis(), + PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); + updatePowerStateLocked(); + } else { + wakeUpNoUpdateLocked(SystemClock.uptimeMillis()); + updatePowerStateLocked(); + } + } else if (wakefulness == WAKEFULNESS_DOZING) { + if (isDreaming) { + return; // continue dozing + } + + // Doze has ended or will be stopped. Update the power state. + reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis()); + updatePowerStateLocked(); } } - // Stop dreaming if needed. - // It's possible that something else changed to make us need to start the dream again. - // If so, then the power manager will have posted another message to the handler - // to take care of it later. - if (mDreamManager != null) { - if (!continueDreaming) { - mDreamManager.stopDream(); - } + // Stop dream. + if (isDreaming) { + mDreamManager.stopDream(); } } /** - * Returns true if the device is allowed to dream in its current state - * assuming that it is currently napping or dreaming. + * Returns true if the device is allowed to dream in its current state. + * This function is not called when dozing. */ private boolean canDreamLocked() { - return mDreamsSupportedConfig - && mDreamsEnabledSetting - && mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF - && mBootCompleted - && (mIsPowered || isBeingKeptAwakeLocked()); - } - - /** - * Called when a dream is ending to figure out what to do next. - */ - private void handleDreamFinishedLocked() { - if (mWakefulness == WAKEFULNESS_NAPPING - || mWakefulness == WAKEFULNESS_DREAMING) { - if (isItBedTimeYetLocked()) { - goToSleepNoUpdateLocked(SystemClock.uptimeMillis(), - PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); - updatePowerStateLocked(); - } else { - wakeUpNoUpdateLocked(SystemClock.uptimeMillis()); - updatePowerStateLocked(); + if (mWakefulness != WAKEFULNESS_DREAMING + || !mDreamsSupportedConfig + || !mDreamsEnabledSetting + || !mDisplayPowerRequest.wantScreenOnNormal() + || !mBootCompleted) { + return false; + } + if (!isBeingKeptAwakeLocked()) { + if (!mIsPowered && !mDreamsEnabledOnBatteryConfig) { + return false; + } + if (!mIsPowered + && mDreamsBatteryLevelMinimumWhenNotPoweredConfig >= 0 + && mBatteryLevel < mDreamsBatteryLevelMinimumWhenNotPoweredConfig) { + return false; + } + if (mIsPowered + && mDreamsBatteryLevelMinimumWhenPoweredConfig >= 0 + && mBatteryLevel < mDreamsBatteryLevelMinimumWhenPoweredConfig) { + return false; } } + return true; } private void handleScreenOnBlockerReleased() { @@ -1654,17 +1589,11 @@ public final class PowerManagerService extends IPowerManager.Stub if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED | DIRTY_SETTINGS | DIRTY_SCREEN_ON_BLOCKER_RELEASED)) != 0) { - int newScreenState = getDesiredScreenPowerStateLocked(); + final int newScreenState = getDesiredScreenPowerStateLocked(); if (newScreenState != mDisplayPowerRequest.screenState) { - if (newScreenState == DisplayPowerRequest.SCREEN_STATE_OFF - && mDisplayPowerRequest.screenState - != DisplayPowerRequest.SCREEN_STATE_OFF) { - mLastScreenOffEventElapsedRealTime = SystemClock.elapsedRealtime(); - } - mDisplayPowerRequest.screenState = newScreenState; nativeSetPowerState( - newScreenState != DisplayPowerRequest.SCREEN_STATE_OFF, + mDisplayPowerRequest.wantScreenOnNormal(), newScreenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT); } @@ -1733,6 +1662,10 @@ public final class PowerManagerService extends IPowerManager.Stub return DisplayPowerRequest.SCREEN_STATE_OFF; } + if ((mWakeLockSummary & WAKE_LOCK_DOZE) != 0) { + return DisplayPowerRequest.SCREEN_STATE_DOZE; + } + if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0 || (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0 || !mBootCompleted) { @@ -1784,7 +1717,18 @@ public final class PowerManagerService extends IPowerManager.Stub */ private void updateSuspendBlockerLocked() { final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0); - final boolean needDisplaySuspendBlocker = needDisplaySuspendBlocker(); + final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked(); + final boolean autoSuspend = !needDisplaySuspendBlocker; + + // Disable auto-suspend if needed. + if (!autoSuspend) { + if (mDecoupleAutoSuspendModeFromDisplayConfig) { + setAutoSuspendModeLocked(false); + } + if (mDecoupleInteractiveModeFromDisplayConfig) { + setInteractiveModeLocked(true); + } + } // First acquire suspend blockers if needed. if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) { @@ -1805,17 +1749,27 @@ public final class PowerManagerService extends IPowerManager.Stub mDisplaySuspendBlocker.release(); mHoldingDisplaySuspendBlocker = false; } + + // Enable auto-suspend if needed. + if (autoSuspend) { + if (mDecoupleInteractiveModeFromDisplayConfig) { + setInteractiveModeLocked(false); + } + if (mDecoupleAutoSuspendModeFromDisplayConfig) { + setAutoSuspendModeLocked(true); + } + } } /** * Return true if we must keep a suspend blocker active on behalf of the display. * We do so if the screen is on or is in transition between states. */ - private boolean needDisplaySuspendBlocker() { + private boolean needDisplaySuspendBlockerLocked() { if (!mDisplayReady) { return true; } - if (mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) { + if (mDisplayPowerRequest.wantScreenOnNormal()) { // If we asked for the screen to be on but it is off due to the proximity // sensor then we may suspend but only if the configuration allows it. // On some hardware it may not be safe to suspend because the proximity @@ -1825,23 +1779,34 @@ public final class PowerManagerService extends IPowerManager.Stub return true; } } + // Let the system suspend if the screen is off or dozing. return false; } - @Override // Binder call - public boolean isScreenOn() { - final long ident = Binder.clearCallingIdentity(); - try { - return isScreenOnInternal(); - } finally { - Binder.restoreCallingIdentity(ident); + private void setAutoSuspendModeLocked(boolean enable) { + if (enable != mAutoSuspendModeEnabled) { + if (DEBUG) { + Slog.d(TAG, "Setting auto-suspend mode to " + enable); + } + mAutoSuspendModeEnabled = enable; + nativeSetAutoSuspend(enable); + } + } + + private void setInteractiveModeLocked(boolean enable) { + if (enable != mInteractiveModeEnabled) { + if (DEBUG) { + Slog.d(TAG, "Setting interactive mode to " + enable); + } + mInteractiveModeEnabled = enable; + nativeSetInteractive(enable); } } private boolean isScreenOnInternal() { synchronized (mLock) { return !mSystemReady - || mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF; + || mDisplayPowerRequest.wantScreenOnNormal(); } } @@ -1882,43 +1847,6 @@ public final class PowerManagerService extends IPowerManager.Stub updatePowerStateLocked(); } - /** - * Reboots the device. - * - * @param confirm If true, shows a reboot confirmation dialog. - * @param reason The reason for the reboot, or null if none. - * @param wait If true, this call waits for the reboot to complete and does not return. - */ - @Override // Binder call - public void reboot(boolean confirm, String reason, boolean wait) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null); - - final long ident = Binder.clearCallingIdentity(); - try { - shutdownOrRebootInternal(false, confirm, reason, wait); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - /** - * Shuts down the device. - * - * @param confirm If true, shows a shutdown confirmation dialog. - * @param wait If true, this call waits for the shutdown to complete and does not return. - */ - @Override // Binder call - public void shutdown(boolean confirm, boolean wait) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null); - - final long ident = Binder.clearCallingIdentity(); - try { - shutdownOrRebootInternal(true, confirm, null, wait); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm, final String reason, boolean wait) { if (mHandler == null || !mSystemReady) { @@ -1956,22 +1884,6 @@ public final class PowerManagerService extends IPowerManager.Stub } } - /** - * Crash the runtime (causing a complete restart of the Android framework). - * Requires REBOOT permission. Mostly for testing. Should not return. - */ - @Override // Binder call - public void crash(String message) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null); - - final long ident = Binder.clearCallingIdentity(); - try { - crashInternal(message); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - private void crashInternal(final String message) { Thread t = new Thread("PowerManagerService.crash()") { @Override @@ -1987,51 +1899,11 @@ public final class PowerManagerService extends IPowerManager.Stub } } - /** - * Set the setting that determines whether the device stays on when plugged in. - * The argument is a bit string, with each bit specifying a power source that, - * when the device is connected to that source, causes the device to stay on. - * See {@link android.os.BatteryManager} for the list of power sources that - * can be specified. Current values include {@link android.os.BatteryManager#BATTERY_PLUGGED_AC} - * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB} - * - * Used by "adb shell svc power stayon ..." - * - * @param val an {@code int} containing the bits that specify which power sources - * should cause the device to stay on. - */ - @Override // Binder call - public void setStayOnSetting(int val) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS, null); - - final long ident = Binder.clearCallingIdentity(); - try { - setStayOnSettingInternal(val); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - private void setStayOnSettingInternal(int val) { Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.STAY_ON_WHILE_PLUGGED_IN, val); } - /** - * Used by device administration to set the maximum screen off timeout. - * - * This method must only be called by the device administration policy manager. - */ - @Override // Binder call - public void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs) { - final long ident = Binder.clearCallingIdentity(); - try { - setMaximumScreenOffTimeoutFromDeviceAdminInternal(timeMs); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - private void setMaximumScreenOffTimeoutFromDeviceAdminInternal(int timeMs) { synchronized (mLock) { mMaximumScreenOffTimeoutFromDeviceAdmin = timeMs; @@ -2045,23 +1917,8 @@ public final class PowerManagerService extends IPowerManager.Stub && mMaximumScreenOffTimeoutFromDeviceAdmin < Integer.MAX_VALUE; } - /** - * Used by the phone application to make the attention LED flash when ringing. - */ - @Override // Binder call - public void setAttentionLight(boolean on, int color) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); - - final long ident = Binder.clearCallingIdentity(); - try { - setAttentionLightInternal(on, color); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - private void setAttentionLightInternal(boolean on, int color) { - LightsService.Light light; + Light light; synchronized (mLock) { if (!mSystemReady) { return; @@ -2070,38 +1927,7 @@ public final class PowerManagerService extends IPowerManager.Stub } // Control light outside of lock. - light.setFlashing(color, LightsService.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0); - } - - /** - * Used by the Watchdog. - */ - public long timeSinceScreenWasLastOn() { - synchronized (mLock) { - if (mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) { - return 0; - } - return SystemClock.elapsedRealtime() - mLastScreenOffEventElapsedRealTime; - } - } - - /** - * Used by the window manager to override the screen brightness based on the - * current foreground activity. - * - * This method must only be called by the window manager. - * - * @param brightness The overridden brightness, or -1 to disable the override. - */ - public void setScreenBrightnessOverrideFromWindowManager(int brightness) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); - - final long ident = Binder.clearCallingIdentity(); - try { - setScreenBrightnessOverrideFromWindowManagerInternal(brightness); - } finally { - Binder.restoreCallingIdentity(ident); - } + light.setFlashing(color, Light.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0); } private void setScreenBrightnessOverrideFromWindowManagerInternal(int brightness) { @@ -2114,40 +1940,6 @@ public final class PowerManagerService extends IPowerManager.Stub } } - /** - * Used by the window manager to override the button brightness based on the - * current foreground activity. - * - * This method must only be called by the window manager. - * - * @param brightness The overridden brightness, or -1 to disable the override. - */ - public void setButtonBrightnessOverrideFromWindowManager(int brightness) { - // Do nothing. - // Button lights are not currently supported in the new implementation. - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); - } - - /** - * Used by the window manager to override the user activity timeout based on the - * current foreground activity. It can only be used to make the timeout shorter - * than usual, not longer. - * - * This method must only be called by the window manager. - * - * @param timeoutMillis The overridden timeout, or -1 to disable the override. - */ - public void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); - - final long ident = Binder.clearCallingIdentity(); - try { - setUserActivityTimeoutOverrideFromWindowManagerInternal(timeoutMillis); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - private void setUserActivityTimeoutOverrideFromWindowManagerInternal(long timeoutMillis) { synchronized (mLock) { if (mUserActivityTimeoutOverrideFromWindowManager != timeoutMillis) { @@ -2158,30 +1950,6 @@ public final class PowerManagerService extends IPowerManager.Stub } } - /** - * Used by the settings application and brightness control widgets to - * temporarily override the current screen brightness setting so that the - * user can observe the effect of an intended settings change without applying - * it immediately. - * - * The override will be canceled when the setting value is next updated. - * - * @param brightness The overridden brightness. - * - * @see android.provider.Settings.System#SCREEN_BRIGHTNESS - */ - @Override // Binder call - public void setTemporaryScreenBrightnessSettingOverride(int brightness) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); - - final long ident = Binder.clearCallingIdentity(); - try { - setTemporaryScreenBrightnessSettingOverrideInternal(brightness); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - private void setTemporaryScreenBrightnessSettingOverrideInternal(int brightness) { synchronized (mLock) { if (mTemporaryScreenBrightnessSettingOverride != brightness) { @@ -2192,30 +1960,6 @@ public final class PowerManagerService extends IPowerManager.Stub } } - /** - * Used by the settings application and brightness control widgets to - * temporarily override the current screen auto-brightness adjustment setting so that the - * user can observe the effect of an intended settings change without applying - * it immediately. - * - * The override will be canceled when the setting value is next updated. - * - * @param adj The overridden brightness, or Float.NaN to disable the override. - * - * @see Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ - */ - @Override // Binder call - public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); - - final long ident = Binder.clearCallingIdentity(); - try { - setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(adj); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - private void setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(float adj) { synchronized (mLock) { // Note: This condition handles NaN because NaN is not equal to any other @@ -2262,16 +2006,7 @@ public final class PowerManagerService extends IPowerManager.Stub } } - @Override // Binder call - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump PowerManager from from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return; - } - + private void dumpInternal(PrintWriter pw) { pw.println("POWER MANAGER (dumpsys power)\n"); final DisplayPowerController dpc; @@ -2289,10 +2024,13 @@ public final class PowerManagerService extends IPowerManager.Stub pw.println(" mProximityPositive=" + mProximityPositive); pw.println(" mBootCompleted=" + mBootCompleted); pw.println(" mSystemReady=" + mSystemReady); + pw.println(" mAutoSuspendModeEnabled=" + mAutoSuspendModeEnabled); + pw.println(" mInteactiveModeEnabled=" + mInteractiveModeEnabled); pw.println(" mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)); pw.println(" mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)); pw.println(" mRequestWaitForNegativeProximity=" + mRequestWaitForNegativeProximity); pw.println(" mSandmanScheduled=" + mSandmanScheduled); + pw.println(" mSandmanSummoned=" + mSandmanSummoned); pw.println(" mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime)); pw.println(" mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime)); pw.println(" mSendWakeUpFinishedNotificationWhenReady=" @@ -2308,6 +2046,10 @@ public final class PowerManagerService extends IPowerManager.Stub pw.println(); pw.println("Settings and Configuration:"); + pw.println(" mDecoupleAutoSuspendModeFromDisplayConfig=" + + mDecoupleAutoSuspendModeFromDisplayConfig); + pw.println(" mDecoupleInteractiveModeFromDisplayConfig=" + + mDecoupleInteractiveModeFromDisplayConfig); pw.println(" mWakeUpWhenPluggedOrUnpluggedConfig=" + mWakeUpWhenPluggedOrUnpluggedConfig); pw.println(" mSuspendWhenScreenOffDueToProximityConfig=" @@ -2318,6 +2060,14 @@ public final class PowerManagerService extends IPowerManager.Stub + mDreamsActivatedOnSleepByDefaultConfig); pw.println(" mDreamsActivatedOnDockByDefaultConfig=" + mDreamsActivatedOnDockByDefaultConfig); + pw.println(" mDreamsEnabledOnBatteryConfig=" + + mDreamsEnabledOnBatteryConfig); + pw.println(" mDreamsBatteryLevelMinimumWhenPoweredConfig=" + + mDreamsBatteryLevelMinimumWhenPoweredConfig); + pw.println(" mDreamsBatteryLevelMinimumWhenNotPoweredConfig=" + + mDreamsBatteryLevelMinimumWhenNotPoweredConfig); + pw.println(" mDreamsBatteryLevelDrainCutoffConfig=" + + mDreamsBatteryLevelDrainCutoffConfig); pw.println(" mDreamsEnabledSetting=" + mDreamsEnabledSetting); pw.println(" mDreamsActivateOnSleepSetting=" + mDreamsActivateOnSleepSetting); pw.println(" mDreamsActivateOnDockSetting=" + mDreamsActivateOnDockSetting); @@ -2393,8 +2143,8 @@ public final class PowerManagerService extends IPowerManager.Stub return "Awake"; case WAKEFULNESS_DREAMING: return "Dreaming"; - case WAKEFULNESS_NAPPING: - return "Napping"; + case WAKEFULNESS_DOZING: + return "Dozing"; default: return Integer.toString(wakefulness); } @@ -2571,6 +2321,7 @@ public final class PowerManagerService extends IPowerManager.Stub + " (uid=" + mOwnerUid + ", pid=" + mOwnerPid + ", ws=" + mWorkSource + ")"; } + @SuppressWarnings("deprecation") private String getLockLevelString() { switch (mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) { case PowerManager.FULL_WAKE_LOCK: @@ -2583,6 +2334,8 @@ public final class PowerManagerService extends IPowerManager.Stub return "PARTIAL_WAKE_LOCK "; case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: return "PROXIMITY_SCREEN_OFF_WAKE_LOCK"; + case PowerManager.DOZE_WAKE_LOCK: + return "DOZE_WAKE_LOCK "; default: return "??? "; } @@ -2712,18 +2465,26 @@ public final class PowerManagerService extends IPowerManager.Stub public void blankAllDisplays() { synchronized (this) { mBlanked = true; - mDisplayManagerService.blankAllDisplaysFromPowerManager(); - nativeSetInteractive(false); - nativeSetAutoSuspend(true); + mDisplayManagerInternal.blankAllDisplaysFromPowerManager(); + if (!mDecoupleInteractiveModeFromDisplayConfig) { + setInteractiveModeLocked(false); + } + if (!mDecoupleAutoSuspendModeFromDisplayConfig) { + setAutoSuspendModeLocked(true); + } } } @Override public void unblankAllDisplays() { synchronized (this) { - nativeSetAutoSuspend(false); - nativeSetInteractive(true); - mDisplayManagerService.unblankAllDisplaysFromPowerManager(); + if (!mDecoupleAutoSuspendModeFromDisplayConfig) { + setAutoSuspendModeLocked(false); + } + if (!mDecoupleInteractiveModeFromDisplayConfig) { + setInteractiveModeLocked(true); + } + mDisplayManagerInternal.unblankAllDisplaysFromPowerManager(); mBlanked = false; } } @@ -2735,4 +2496,444 @@ public final class PowerManagerService extends IPowerManager.Stub } } } + + private final class BinderService extends IPowerManager.Stub { + @Override // Binder call + public void acquireWakeLockWithUid(IBinder lock, int flags, String tag, + String packageName, int uid) { + acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid)); + } + + @Override // Binder call + public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, + WorkSource ws) { + if (lock == null) { + throw new IllegalArgumentException("lock must not be null"); + } + if (packageName == null) { + throw new IllegalArgumentException("packageName must not be null"); + } + PowerManager.validateWakeLockParameters(flags, tag); + + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); + if (ws != null && ws.size() != 0) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.UPDATE_DEVICE_STATS, null); + } else { + ws = null; + } + + final int uid = Binder.getCallingUid(); + final int pid = Binder.getCallingPid(); + final long ident = Binder.clearCallingIdentity(); + try { + acquireWakeLockInternal(lock, flags, tag, packageName, ws, uid, pid); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void releaseWakeLock(IBinder lock, int flags) { + if (lock == null) { + throw new IllegalArgumentException("lock must not be null"); + } + + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); + + final long ident = Binder.clearCallingIdentity(); + try { + releaseWakeLockInternal(lock, flags); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void updateWakeLockUids(IBinder lock, int[] uids) { + WorkSource ws = null; + + if (uids != null) { + ws = new WorkSource(); + // XXX should WorkSource have a way to set uids as an int[] instead of adding them + // one at a time? + for (int i = 0; i < uids.length; i++) { + ws.add(uids[i]); + } + } + updateWakeLockWorkSource(lock, ws); + } + + @Override // Binder call + public void updateWakeLockWorkSource(IBinder lock, WorkSource ws) { + if (lock == null) { + throw new IllegalArgumentException("lock must not be null"); + } + + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); + if (ws != null && ws.size() != 0) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.UPDATE_DEVICE_STATS, null); + } else { + ws = null; + } + + final long ident = Binder.clearCallingIdentity(); + try { + updateWakeLockWorkSourceInternal(lock, ws); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public boolean isWakeLockLevelSupported(int level) { + final long ident = Binder.clearCallingIdentity(); + try { + return isWakeLockLevelSupportedInternal(level); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void userActivity(long eventTime, int event, int flags) { + final long now = SystemClock.uptimeMillis(); + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER) + != PackageManager.PERMISSION_GRANTED) { + // Once upon a time applications could call userActivity(). + // Now we require the DEVICE_POWER permission. Log a warning and ignore the + // request instead of throwing a SecurityException so we don't break old apps. + synchronized (mLock) { + if (now >= mLastWarningAboutUserActivityPermission + (5 * 60 * 1000)) { + mLastWarningAboutUserActivityPermission = now; + Slog.w(TAG, "Ignoring call to PowerManager.userActivity() because the " + + "caller does not have DEVICE_POWER permission. " + + "Please fix your app! " + + " pid=" + Binder.getCallingPid() + + " uid=" + Binder.getCallingUid()); + } + } + return; + } + + if (eventTime > SystemClock.uptimeMillis()) { + throw new IllegalArgumentException("event time must not be in the future"); + } + + final int uid = Binder.getCallingUid(); + final long ident = Binder.clearCallingIdentity(); + try { + userActivityInternal(eventTime, event, flags, uid); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void wakeUp(long eventTime) { + if (eventTime > SystemClock.uptimeMillis()) { + throw new IllegalArgumentException("event time must not be in the future"); + } + + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.DEVICE_POWER, null); + + final long ident = Binder.clearCallingIdentity(); + try { + wakeUpInternal(eventTime); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void goToSleep(long eventTime, int reason) { + if (eventTime > SystemClock.uptimeMillis()) { + throw new IllegalArgumentException("event time must not be in the future"); + } + + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.DEVICE_POWER, null); + + final long ident = Binder.clearCallingIdentity(); + try { + goToSleepInternal(eventTime, reason); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void nap(long eventTime) { + if (eventTime > SystemClock.uptimeMillis()) { + throw new IllegalArgumentException("event time must not be in the future"); + } + + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.DEVICE_POWER, null); + + final long ident = Binder.clearCallingIdentity(); + try { + napInternal(eventTime); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public boolean isScreenOn() { + final long ident = Binder.clearCallingIdentity(); + try { + return isScreenOnInternal(); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + /** + * Reboots the device. + * + * @param confirm If true, shows a reboot confirmation dialog. + * @param reason The reason for the reboot, or null if none. + * @param wait If true, this call waits for the reboot to complete and does not return. + */ + @Override // Binder call + public void reboot(boolean confirm, String reason, boolean wait) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null); + + final long ident = Binder.clearCallingIdentity(); + try { + shutdownOrRebootInternal(false, confirm, reason, wait); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + /** + * Shuts down the device. + * + * @param confirm If true, shows a shutdown confirmation dialog. + * @param wait If true, this call waits for the shutdown to complete and does not return. + */ + @Override // Binder call + public void shutdown(boolean confirm, boolean wait) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null); + + final long ident = Binder.clearCallingIdentity(); + try { + shutdownOrRebootInternal(true, confirm, null, wait); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + /** + * Crash the runtime (causing a complete restart of the Android framework). + * Requires REBOOT permission. Mostly for testing. Should not return. + */ + @Override // Binder call + public void crash(String message) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null); + + final long ident = Binder.clearCallingIdentity(); + try { + crashInternal(message); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + /** + * Set the setting that determines whether the device stays on when plugged in. + * The argument is a bit string, with each bit specifying a power source that, + * when the device is connected to that source, causes the device to stay on. + * See {@link android.os.BatteryManager} for the list of power sources that + * can be specified. Current values include + * {@link android.os.BatteryManager#BATTERY_PLUGGED_AC} + * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB} + * + * Used by "adb shell svc power stayon ..." + * + * @param val an {@code int} containing the bits that specify which power sources + * should cause the device to stay on. + */ + @Override // Binder call + public void setStayOnSetting(int val) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.WRITE_SETTINGS, null); + + final long ident = Binder.clearCallingIdentity(); + try { + setStayOnSettingInternal(val); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + /** + * Used by device administration to set the maximum screen off timeout. + * + * This method must only be called by the device administration policy manager. + */ + @Override // Binder call + public void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs) { + final long ident = Binder.clearCallingIdentity(); + try { + setMaximumScreenOffTimeoutFromDeviceAdminInternal(timeMs); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + /** + * Used by the settings application and brightness control widgets to + * temporarily override the current screen brightness setting so that the + * user can observe the effect of an intended settings change without applying + * it immediately. + * + * The override will be canceled when the setting value is next updated. + * + * @param brightness The overridden brightness. + * + * @see android.provider.Settings.System#SCREEN_BRIGHTNESS + */ + @Override // Binder call + public void setTemporaryScreenBrightnessSettingOverride(int brightness) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.DEVICE_POWER, null); + + final long ident = Binder.clearCallingIdentity(); + try { + setTemporaryScreenBrightnessSettingOverrideInternal(brightness); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + /** + * Used by the settings application and brightness control widgets to + * temporarily override the current screen auto-brightness adjustment setting so that the + * user can observe the effect of an intended settings change without applying + * it immediately. + * + * The override will be canceled when the setting value is next updated. + * + * @param adj The overridden brightness, or Float.NaN to disable the override. + * + * @see Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ + */ + @Override // Binder call + public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.DEVICE_POWER, null); + + final long ident = Binder.clearCallingIdentity(); + try { + setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(adj); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + /** + * Used by the phone application to make the attention LED flash when ringing. + */ + @Override // Binder call + public void setAttentionLight(boolean on, int color) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.DEVICE_POWER, null); + + final long ident = Binder.clearCallingIdentity(); + try { + setAttentionLightInternal(on, color); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump PowerManager from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + final long ident = Binder.clearCallingIdentity(); + try { + dumpInternal(pw); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } + + private final class LocalService extends PowerManagerInternal { + /** + * Used by the window manager to override the screen brightness based on the + * current foreground activity. + * + * This method must only be called by the window manager. + * + * @param brightness The overridden brightness, or -1 to disable the override. + */ + @Override + public void setScreenBrightnessOverrideFromWindowManager(int brightness) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.DEVICE_POWER, null); + + final long ident = Binder.clearCallingIdentity(); + try { + setScreenBrightnessOverrideFromWindowManagerInternal(brightness); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + /** + * Used by the window manager to override the button brightness based on the + * current foreground activity. + * + * This method must only be called by the window manager. + * + * @param brightness The overridden brightness, or -1 to disable the override. + */ + @Override + public void setButtonBrightnessOverrideFromWindowManager(int brightness) { + // Do nothing. + // Button lights are not currently supported in the new implementation. + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.DEVICE_POWER, null); + } + + /** + * Used by the window manager to override the user activity timeout based on the + * current foreground activity. It can only be used to make the timeout shorter + * than usual, not longer. + * + * This method must only be called by the window manager. + * + * @param timeoutMillis The overridden timeout, or -1 to disable the override. + */ + @Override + public void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.DEVICE_POWER, null); + + final long ident = Binder.clearCallingIdentity(); + try { + setUserActivityTimeoutOverrideFromWindowManagerInternal(timeoutMillis); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override + public void setPolicy(WindowManagerPolicy policy) { + PowerManagerService.this.setPolicy(policy); + } + } } diff --git a/services/java/com/android/server/power/RampAnimator.java b/services/core/java/com/android/server/power/RampAnimator.java index 4a4f0801240e..4a4f0801240e 100644 --- a/services/java/com/android/server/power/RampAnimator.java +++ b/services/core/java/com/android/server/power/RampAnimator.java diff --git a/services/java/com/android/server/power/ScreenOnBlocker.java b/services/core/java/com/android/server/power/ScreenOnBlocker.java index dbbbc6d2ab20..dbbbc6d2ab20 100644 --- a/services/java/com/android/server/power/ScreenOnBlocker.java +++ b/services/core/java/com/android/server/power/ScreenOnBlocker.java diff --git a/services/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java index 88a27f5f74dd..88a27f5f74dd 100644 --- a/services/java/com/android/server/power/ShutdownThread.java +++ b/services/core/java/com/android/server/power/ShutdownThread.java diff --git a/services/java/com/android/server/power/SuspendBlocker.java b/services/core/java/com/android/server/power/SuspendBlocker.java index 70b278a6f2df..70b278a6f2df 100644 --- a/services/java/com/android/server/power/SuspendBlocker.java +++ b/services/core/java/com/android/server/power/SuspendBlocker.java diff --git a/services/java/com/android/server/power/WirelessChargerDetector.java b/services/core/java/com/android/server/power/WirelessChargerDetector.java index 38f5d7740842..38f5d7740842 100644 --- a/services/java/com/android/server/power/WirelessChargerDetector.java +++ b/services/core/java/com/android/server/power/WirelessChargerDetector.java diff --git a/services/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java index b5d81d1a10fd..b5d81d1a10fd 100644 --- a/services/java/com/android/server/search/SearchManagerService.java +++ b/services/core/java/com/android/server/search/SearchManagerService.java diff --git a/services/java/com/android/server/search/Searchables.java b/services/core/java/com/android/server/search/Searchables.java index 0ffbb7d0aa59..0ffbb7d0aa59 100644 --- a/services/java/com/android/server/search/Searchables.java +++ b/services/core/java/com/android/server/search/Searchables.java diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java new file mode 100644 index 000000000000..4f7518966681 --- /dev/null +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2013, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.statusbar; + +import com.android.server.notification.NotificationDelegate; + +import android.os.IBinder; +import android.service.notification.StatusBarNotification; + +public interface StatusBarManagerInternal { + void setNotificationDelegate(NotificationDelegate delegate); + IBinder addNotification(StatusBarNotification notification); + void updateNotification(IBinder key, StatusBarNotification notification); + void removeNotification(IBinder key); +} diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index f207c08c579c..2ae467eabdd1 100644 --- a/services/java/com/android/server/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -14,26 +14,28 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.statusbar; import android.app.StatusBarManager; +import android.os.Binder; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.UserHandle; import android.service.notification.StatusBarNotification; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Resources; -import android.os.Binder; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.UserHandle; import android.util.Slog; import com.android.internal.statusbar.IStatusBar; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.statusbar.StatusBarIconList; +import com.android.server.LocalServices; +import com.android.server.notification.NotificationDelegate; import com.android.server.wm.WindowManagerService; import java.io.FileDescriptor; @@ -51,31 +53,31 @@ import java.util.Map; public class StatusBarManagerService extends IStatusBarService.Stub implements WindowManagerService.OnHardKeyboardStatusChangeListener { - static final String TAG = "StatusBarManagerService"; - static final boolean SPEW = false; - - final Context mContext; - final WindowManagerService mWindowManager; - Handler mHandler = new Handler(); - NotificationCallbacks mNotificationCallbacks; - volatile IStatusBar mBar; - StatusBarIconList mIcons = new StatusBarIconList(); - HashMap<IBinder,StatusBarNotification> mNotifications + private static final String TAG = "StatusBarManagerService"; + private static final boolean SPEW = false; + + private final Context mContext; + private final WindowManagerService mWindowManager; + private Handler mHandler = new Handler(); + private NotificationDelegate mNotificationDelegate; + private volatile IStatusBar mBar; + private StatusBarIconList mIcons = new StatusBarIconList(); + private HashMap<IBinder,StatusBarNotification> mNotifications = new HashMap<IBinder,StatusBarNotification>(); // for disabling the status bar - final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>(); - IBinder mSysUiVisToken = new Binder(); - int mDisabled = 0; + private final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>(); + private IBinder mSysUiVisToken = new Binder(); + private int mDisabled = 0; - Object mLock = new Object(); + private Object mLock = new Object(); // encompasses lights-out mode and other flags defined on View - int mSystemUiVisibility = 0; - boolean mMenuVisible = false; - int mImeWindowVis = 0; - int mImeBackDisposition; - IBinder mImeToken = null; - int mCurrentUserId; + private int mSystemUiVisibility = 0; + private boolean mMenuVisible = false; + private int mImeWindowVis = 0; + private int mImeBackDisposition; + private IBinder mImeToken = null; + private int mCurrentUserId; private class DisableRecord implements IBinder.DeathRecipient { int userId; @@ -90,16 +92,6 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } - public interface NotificationCallbacks { - void onSetDisabled(int status); - void onClearAll(); - void onNotificationClick(String pkg, String tag, int id); - void onNotificationClear(String pkg, String tag, int id); - void onPanelRevealed(); - void onNotificationError(String pkg, String tag, int id, - int uid, int initialPid, String message); - } - /** * Construct the service, add the status bar view to the window manager */ @@ -110,15 +102,74 @@ public class StatusBarManagerService extends IStatusBarService.Stub final Resources res = context.getResources(); mIcons.defineSlots(res.getStringArray(com.android.internal.R.array.config_statusBarIcons)); - } - public void setNotificationCallbacks(NotificationCallbacks listener) { - mNotificationCallbacks = listener; + LocalServices.addService(StatusBarManagerInternal.class, mInternalService); } + /** + * Private API used by NotificationManagerService. + */ + private final StatusBarManagerInternal mInternalService = new StatusBarManagerInternal() { + @Override + public void setNotificationDelegate(NotificationDelegate delegate) { + synchronized (mNotifications) { + mNotificationDelegate = delegate; + } + } + + @Override + public IBinder addNotification(StatusBarNotification notification) { + synchronized (mNotifications) { + IBinder key = new Binder(); + mNotifications.put(key, notification); + if (mBar != null) { + try { + mBar.addNotification(key, notification); + } catch (RemoteException ex) { + } + } + return key; + } + } + + @Override + public void updateNotification(IBinder key, StatusBarNotification notification) { + synchronized (mNotifications) { + if (!mNotifications.containsKey(key)) { + throw new IllegalArgumentException("updateNotification key not found: " + key); + } + mNotifications.put(key, notification); + if (mBar != null) { + try { + mBar.updateNotification(key, notification); + } catch (RemoteException ex) { + } + } + } + } + + @Override + public void removeNotification(IBinder key) { + synchronized (mNotifications) { + final StatusBarNotification n = mNotifications.remove(key); + if (n == null) { + Slog.e(TAG, "removeNotification key not found: " + key); + return; + } + if (mBar != null) { + try { + mBar.removeNotification(key); + } catch (RemoteException ex) { + } + } + } + } + }; + // ================================================================================ // From IStatusBarService // ================================================================================ + @Override public void expandNotificationsPanel() { enforceExpandStatusBar(); @@ -130,6 +181,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } + @Override public void collapsePanels() { enforceExpandStatusBar(); @@ -141,6 +193,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } + @Override public void expandSettingsPanel() { enforceExpandStatusBar(); @@ -152,6 +205,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } + @Override public void disable(int what, IBinder token, String pkg) { disableInternal(mCurrentUserId, what, token, pkg); } @@ -177,7 +231,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub mDisabled = net; mHandler.post(new Runnable() { public void run() { - mNotificationCallbacks.onSetDisabled(net); + mNotificationDelegate.onSetDisabled(net); } }); if (mBar != null) { @@ -189,6 +243,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } + @Override public void setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription) { enforceStatusBar(); @@ -214,6 +269,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } + @Override public void setIconVisibility(String slot, boolean visible) { enforceStatusBar(); @@ -241,6 +297,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } + @Override public void removeIcon(String slot) { enforceStatusBar(); @@ -265,6 +322,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub * Hide or show the on-screen Menu key. Only call this from the window manager, typically in * response to a window with FLAG_NEEDS_MENU_KEY set. */ + @Override public void topAppWindowChanged(final boolean menuVisible) { enforceStatusBar(); @@ -285,6 +343,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } + @Override public void setImeWindowStatus(final IBinder token, final int vis, final int backDisposition) { enforceStatusBar(); @@ -312,6 +371,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } + @Override public void setSystemUiVisibility(int vis, int mask) { // also allows calls from window manager which is in this process. enforceStatusBarService(); @@ -344,6 +404,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } + @Override public void setHardKeyboardEnabled(final boolean enabled) { mHandler.post(new Runnable() { public void run() { @@ -426,6 +487,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub // ================================================================================ // Callbacks from the status bar service. // ================================================================================ + @Override public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList, List<IBinder> notificationKeys, List<StatusBarNotification> notifications, int switches[], List<IBinder> binders) { @@ -458,86 +520,64 @@ public class StatusBarManagerService extends IStatusBarService.Stub * The status bar service should call this each time the user brings the panel from * invisible to visible in order to clear the notification light. */ + @Override public void onPanelRevealed() { enforceStatusBarService(); - - // tell the notification manager to turn off the lights. - mNotificationCallbacks.onPanelRevealed(); + long identity = Binder.clearCallingIdentity(); + try { + // tell the notification manager to turn off the lights. + mNotificationDelegate.onPanelRevealed(); + } finally { + Binder.restoreCallingIdentity(identity); + } } + @Override public void onNotificationClick(String pkg, String tag, int id) { enforceStatusBarService(); - - mNotificationCallbacks.onNotificationClick(pkg, tag, id); + long identity = Binder.clearCallingIdentity(); + try { + mNotificationDelegate.onNotificationClick(pkg, tag, id); + } finally { + Binder.restoreCallingIdentity(identity); + } } + @Override public void onNotificationError(String pkg, String tag, int id, int uid, int initialPid, String message) { enforceStatusBarService(); - - // WARNING: this will call back into us to do the remove. Don't hold any locks. - mNotificationCallbacks.onNotificationError(pkg, tag, id, uid, initialPid, message); + long identity = Binder.clearCallingIdentity(); + try { + // WARNING: this will call back into us to do the remove. Don't hold any locks. + mNotificationDelegate.onNotificationError(pkg, tag, id, uid, initialPid, message); + } finally { + Binder.restoreCallingIdentity(identity); + } } + @Override public void onNotificationClear(String pkg, String tag, int id) { enforceStatusBarService(); - - mNotificationCallbacks.onNotificationClear(pkg, tag, id); + long identity = Binder.clearCallingIdentity(); + try { + mNotificationDelegate.onNotificationClear(pkg, tag, id); + } finally { + Binder.restoreCallingIdentity(identity); + } } + @Override public void onClearAllNotifications() { enforceStatusBarService(); - - mNotificationCallbacks.onClearAll(); - } - - // ================================================================================ - // Callbacks for NotificationManagerService. - // ================================================================================ - public IBinder addNotification(StatusBarNotification notification) { - synchronized (mNotifications) { - IBinder key = new Binder(); - mNotifications.put(key, notification); - if (mBar != null) { - try { - mBar.addNotification(key, notification); - } catch (RemoteException ex) { - } - } - return key; + long identity = Binder.clearCallingIdentity(); + try { + mNotificationDelegate.onClearAll(); + } finally { + Binder.restoreCallingIdentity(identity); } } - public void updateNotification(IBinder key, StatusBarNotification notification) { - synchronized (mNotifications) { - if (!mNotifications.containsKey(key)) { - throw new IllegalArgumentException("updateNotification key not found: " + key); - } - mNotifications.put(key, notification); - if (mBar != null) { - try { - mBar.updateNotification(key, notification); - } catch (RemoteException ex) { - } - } - } - } - - public void removeNotification(IBinder key) { - synchronized (mNotifications) { - final StatusBarNotification n = mNotifications.remove(key); - if (n == null) { - Slog.e(TAG, "removeNotification key not found: " + key); - return; - } - if (mBar != null) { - try { - mBar.removeNotification(key); - } catch (RemoteException ex) { - } - } - } - } // ================================================================================ // Can be called from any thread diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorInternal.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorInternal.java new file mode 100644 index 000000000000..a91a81b3bffc --- /dev/null +++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorInternal.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2013, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.storage; + +public interface DeviceStorageMonitorInternal { + boolean isMemoryLow(); + long getMemoryLowThreshold(); + void checkMemory(); +} + diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java index 016c561077dc..43a99e082295 100644 --- a/services/java/com/android/server/DeviceStorageMonitorService.java +++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java @@ -14,7 +14,10 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.storage; + +import com.android.server.EventLogTags; +import com.android.server.SystemService; import android.app.Notification; import android.app.NotificationManager; @@ -29,8 +32,8 @@ import android.os.Binder; import android.os.Environment; import android.os.FileObserver; import android.os.Handler; +import android.os.IBinder; import android.os.Message; -import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.StatFs; @@ -66,13 +69,13 @@ import java.io.PrintWriter; * settings parameter with a default value of 2MB), the free memory is * logged to the event log. */ -public class DeviceStorageMonitorService extends Binder { - private static final String TAG = "DeviceStorageMonitorService"; +public class DeviceStorageMonitorService extends SystemService { + static final String TAG = "DeviceStorageMonitorService"; - private static final boolean DEBUG = false; - private static final boolean localLOGV = false; + static final boolean DEBUG = false; + static final boolean localLOGV = false; - private static final int DEVICE_MEMORY_WHAT = 1; + static final int DEVICE_MEMORY_WHAT = 1; private static final int MONITOR_INTERVAL = 1; //in minutes private static final int LOW_MEMORY_NOTIFICATION_ID = 1; @@ -84,33 +87,32 @@ public class DeviceStorageMonitorService extends Binder { private long mFreeMemAfterLastCacheClear; // on /data private long mLastReportedFreeMem; private long mLastReportedFreeMemTime; - private boolean mLowMemFlag=false; + boolean mLowMemFlag=false; private boolean mMemFullFlag=false; - private Context mContext; - private ContentResolver mResolver; - private long mTotalMemory; // on /data - private StatFs mDataFileStats; - private StatFs mSystemFileStats; - private StatFs mCacheFileStats; + private final ContentResolver mResolver; + private final long mTotalMemory; // on /data + private final StatFs mDataFileStats; + private final StatFs mSystemFileStats; + private final StatFs mCacheFileStats; private static final File DATA_PATH = Environment.getDataDirectory(); private static final File SYSTEM_PATH = Environment.getRootDirectory(); private static final File CACHE_PATH = Environment.getDownloadCacheDirectory(); private long mThreadStartTime = -1; - private boolean mClearSucceeded = false; - private boolean mClearingCache; - private Intent mStorageLowIntent; - private Intent mStorageOkIntent; - private Intent mStorageFullIntent; - private Intent mStorageNotFullIntent; + boolean mClearSucceeded = false; + boolean mClearingCache; + private final Intent mStorageLowIntent; + private final Intent mStorageOkIntent; + private final Intent mStorageFullIntent; + private final Intent mStorageNotFullIntent; private CachePackageDataObserver mClearCacheObserver; - private final CacheFileDeletedObserver mCacheFileDeletedObserver; + private CacheFileDeletedObserver mCacheFileDeletedObserver; private static final int _TRUE = 1; private static final int _FALSE = 0; // This is the raw threshold that has been set at which we consider // storage to be low. - private long mMemLowThreshold; + long mMemLowThreshold; // This is the threshold at which we start trying to flush caches // to get below the low threshold limit. It is less than the low // threshold; we will allow storage to get a bit beyond the limit @@ -126,13 +128,13 @@ public class DeviceStorageMonitorService extends Binder { /** * This string is used for ServiceManager access to this class. */ - public static final String SERVICE = "devicestoragemonitor"; + static final String SERVICE = "devicestoragemonitor"; /** * Handler that checks the amount of disk space on the device and sends a * notification if the device runs low on disk space */ - Handler mHandler = new Handler() { + private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { //don't handle an invalid message @@ -144,7 +146,7 @@ public class DeviceStorageMonitorService extends Binder { } }; - class CachePackageDataObserver extends IPackageDataObserver.Stub { + private class CachePackageDataObserver extends IPackageDataObserver.Stub { public void onRemoveCompleted(String packageName, boolean succeeded) { mClearSucceeded = succeeded; mClearingCache = false; @@ -154,7 +156,7 @@ public class DeviceStorageMonitorService extends Binder { } } - private final void restatDataDir() { + private void restatDataDir() { try { mDataFileStats.restat(DATA_PATH.getAbsolutePath()); mFreeMem = (long) mDataFileStats.getAvailableBlocks() * @@ -206,7 +208,7 @@ public class DeviceStorageMonitorService extends Binder { } } - private final void clearCache() { + private void clearCache() { if (mClearCacheObserver == null) { // Lazy instantiation mClearCacheObserver = new CachePackageDataObserver(); @@ -223,7 +225,7 @@ public class DeviceStorageMonitorService extends Binder { } } - private final void checkMemory(boolean checkCache) { + void checkMemory(boolean checkCache) { //if the thread that was started to clear cache is still running do nothing till its //finished clearing cache. Ideally this flag could be modified by clearCache // and should be accessed via a lock but even if it does this test will fail now and @@ -300,7 +302,7 @@ public class DeviceStorageMonitorService extends Binder { postCheckMemoryMsg(true, DEFAULT_CHECK_INTERVAL); } - private void postCheckMemoryMsg(boolean clearCache, long delay) { + void postCheckMemoryMsg(boolean clearCache, long delay) { // Remove queued messages mHandler.removeMessages(DEVICE_MEMORY_WHAT); mHandler.sendMessageDelayed(mHandler.obtainMessage(DEVICE_MEMORY_WHAT, @@ -308,14 +310,10 @@ public class DeviceStorageMonitorService extends Binder { delay); } - /** - * Constructor to run service. initializes the disk space threshold value - * and posts an empty message to kickstart the process. - */ public DeviceStorageMonitorService(Context context) { + super(context); mLastReportedFreeMemTime = 0; - mContext = context; - mResolver = mContext.getContentResolver(); + mResolver = context.getContentResolver(); //create StatFs object mDataFileStats = new StatFs(DATA_PATH.getAbsolutePath()); mSystemFileStats = new StatFs(SYSTEM_PATH.getAbsolutePath()); @@ -331,9 +329,16 @@ public class DeviceStorageMonitorService extends Binder { mStorageFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mStorageNotFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_NOT_FULL); mStorageNotFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + } + /** + * Initializes the disk space threshold value and posts an empty message to + * kickstart the process. + */ + @Override + public void onStart() { // cache storage thresholds - final StorageManager sm = StorageManager.from(context); + final StorageManager sm = StorageManager.from(getContext()); mMemLowThreshold = sm.getStorageLowBytes(DATA_PATH); mMemFullThreshold = sm.getStorageFullBytes(DATA_PATH); @@ -345,6 +350,78 @@ public class DeviceStorageMonitorService extends Binder { mCacheFileDeletedObserver = new CacheFileDeletedObserver(); mCacheFileDeletedObserver.startWatching(); + + publishBinderService(SERVICE, mRemoteService); + publishLocalService(DeviceStorageMonitorInternal.class, mLocalService); + } + + private final DeviceStorageMonitorInternal mLocalService = new DeviceStorageMonitorInternal() { + @Override + public void checkMemory() { + // force an early check + postCheckMemoryMsg(true, 0); + } + + @Override + public boolean isMemoryLow() { + return mLowMemFlag; + } + + @Override + public long getMemoryLowThreshold() { + return mMemLowThreshold; + } + }; + + private final IBinder mRemoteService = new Binder() { + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + + pw.println("Permission Denial: can't dump " + SERVICE + " from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + dumpImpl(pw); + } + }; + + void dumpImpl(PrintWriter pw) { + final Context context = getContext(); + + pw.println("Current DeviceStorageMonitor state:"); + + pw.print(" mFreeMem="); pw.print(Formatter.formatFileSize(context, mFreeMem)); + pw.print(" mTotalMemory="); + pw.println(Formatter.formatFileSize(context, mTotalMemory)); + + pw.print(" mFreeMemAfterLastCacheClear="); + pw.println(Formatter.formatFileSize(context, mFreeMemAfterLastCacheClear)); + + pw.print(" mLastReportedFreeMem="); + pw.print(Formatter.formatFileSize(context, mLastReportedFreeMem)); + pw.print(" mLastReportedFreeMemTime="); + TimeUtils.formatDuration(mLastReportedFreeMemTime, SystemClock.elapsedRealtime(), pw); + pw.println(); + + pw.print(" mLowMemFlag="); pw.print(mLowMemFlag); + pw.print(" mMemFullFlag="); pw.println(mMemFullFlag); + + pw.print(" mClearSucceeded="); pw.print(mClearSucceeded); + pw.print(" mClearingCache="); pw.println(mClearingCache); + + pw.print(" mMemLowThreshold="); + pw.print(Formatter.formatFileSize(context, mMemLowThreshold)); + pw.print(" mMemFullThreshold="); + pw.println(Formatter.formatFileSize(context, mMemFullThreshold)); + + pw.print(" mMemCacheStartTrimThreshold="); + pw.print(Formatter.formatFileSize(context, mMemCacheStartTrimThreshold)); + pw.print(" mMemCacheTrimToThreshold="); + pw.println(Formatter.formatFileSize(context, mMemCacheTrimToThreshold)); } /** @@ -352,7 +429,8 @@ public class DeviceStorageMonitorService extends Binder { * an error dialog indicating low disk space and launch the Installer * application */ - private final void sendNotification() { + private void sendNotification() { + final Context context = getContext(); if(localLOGV) Slog.i(TAG, "Sending low memory notification"); //log the event to event log with the amount of free storage(in bytes) left on the device EventLog.writeEvent(EventLogTags.LOW_STORAGE, mFreeMem); @@ -363,86 +441,58 @@ public class DeviceStorageMonitorService extends Binder { lowMemIntent.putExtra("memory", mFreeMem); lowMemIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); NotificationManager mNotificationMgr = - (NotificationManager)mContext.getSystemService( + (NotificationManager)context.getSystemService( Context.NOTIFICATION_SERVICE); - CharSequence title = mContext.getText( + CharSequence title = context.getText( com.android.internal.R.string.low_internal_storage_view_title); - CharSequence details = mContext.getText( + CharSequence details = context.getText( com.android.internal.R.string.low_internal_storage_view_text); - PendingIntent intent = PendingIntent.getActivityAsUser(mContext, 0, lowMemIntent, 0, + PendingIntent intent = PendingIntent.getActivityAsUser(context, 0, lowMemIntent, 0, null, UserHandle.CURRENT); Notification notification = new Notification(); notification.icon = com.android.internal.R.drawable.stat_notify_disk_full; notification.tickerText = title; notification.flags |= Notification.FLAG_NO_CLEAR; - notification.setLatestEventInfo(mContext, title, details, intent); + notification.setLatestEventInfo(context, title, details, intent); mNotificationMgr.notifyAsUser(null, LOW_MEMORY_NOTIFICATION_ID, notification, UserHandle.ALL); - mContext.sendStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL); + context.sendStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL); } /** * Cancels low storage notification and sends OK intent. */ - private final void cancelNotification() { + private void cancelNotification() { + final Context context = getContext(); if(localLOGV) Slog.i(TAG, "Canceling low memory notification"); NotificationManager mNotificationMgr = - (NotificationManager)mContext.getSystemService( + (NotificationManager)context.getSystemService( Context.NOTIFICATION_SERVICE); //cancel notification since memory has been freed mNotificationMgr.cancelAsUser(null, LOW_MEMORY_NOTIFICATION_ID, UserHandle.ALL); - mContext.removeStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL); - mContext.sendBroadcastAsUser(mStorageOkIntent, UserHandle.ALL); + context.removeStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL); + context.sendBroadcastAsUser(mStorageOkIntent, UserHandle.ALL); } /** * Send a notification when storage is full. */ - private final void sendFullNotification() { + private void sendFullNotification() { if(localLOGV) Slog.i(TAG, "Sending memory full notification"); - mContext.sendStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL); + getContext().sendStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL); } /** * Cancels memory full notification and sends "not full" intent. */ - private final void cancelFullNotification() { + private void cancelFullNotification() { if(localLOGV) Slog.i(TAG, "Canceling memory full notification"); - mContext.removeStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL); - mContext.sendBroadcastAsUser(mStorageNotFullIntent, UserHandle.ALL); - } - - public void updateMemory() { - int callingUid = getCallingUid(); - if(callingUid != Process.SYSTEM_UID) { - return; - } - // force an early check - postCheckMemoryMsg(true, 0); - } - - /** - * Callable from other things in the system service to obtain the low memory - * threshold. - * - * @return low memory threshold in bytes - */ - public long getMemoryLowThreshold() { - return mMemLowThreshold; + getContext().removeStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL); + getContext().sendBroadcastAsUser(mStorageNotFullIntent, UserHandle.ALL); } - /** - * Callable from other things in the system process to check whether memory - * is low. - * - * @return true is memory is low - */ - public boolean isMemoryLow() { - return mLowMemFlag; - } - - public static class CacheFileDeletedObserver extends FileObserver { + private static class CacheFileDeletedObserver extends FileObserver { public CacheFileDeletedObserver() { super(Environment.getDownloadCacheDirectory().getAbsolutePath(), FileObserver.DELETE); } @@ -452,40 +502,4 @@ public class DeviceStorageMonitorService extends Binder { EventLogTags.writeCacheFileDeleted(path); } } - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - - pw.println("Permission Denial: can't dump " + SERVICE + " from from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return; - } - - pw.println("Current DeviceStorageMonitor state:"); - pw.print(" mFreeMem="); pw.print(Formatter.formatFileSize(mContext, mFreeMem)); - pw.print(" mTotalMemory="); - pw.println(Formatter.formatFileSize(mContext, mTotalMemory)); - pw.print(" mFreeMemAfterLastCacheClear="); - pw.println(Formatter.formatFileSize(mContext, mFreeMemAfterLastCacheClear)); - pw.print(" mLastReportedFreeMem="); - pw.print(Formatter.formatFileSize(mContext, mLastReportedFreeMem)); - pw.print(" mLastReportedFreeMemTime="); - TimeUtils.formatDuration(mLastReportedFreeMemTime, SystemClock.elapsedRealtime(), pw); - pw.println(); - pw.print(" mLowMemFlag="); pw.print(mLowMemFlag); - pw.print(" mMemFullFlag="); pw.println(mMemFullFlag); - pw.print(" mClearSucceeded="); pw.print(mClearSucceeded); - pw.print(" mClearingCache="); pw.println(mClearingCache); - pw.print(" mMemLowThreshold="); - pw.print(Formatter.formatFileSize(mContext, mMemLowThreshold)); - pw.print(" mMemFullThreshold="); - pw.println(Formatter.formatFileSize(mContext, mMemFullThreshold)); - pw.print(" mMemCacheStartTrimThreshold="); - pw.print(Formatter.formatFileSize(mContext, mMemCacheStartTrimThreshold)); - pw.print(" mMemCacheTrimToThreshold="); - pw.println(Formatter.formatFileSize(mContext, mMemCacheTrimToThreshold)); - } } diff --git a/services/core/java/com/android/server/twilight/TwilightListener.java b/services/core/java/com/android/server/twilight/TwilightListener.java new file mode 100644 index 000000000000..29ead445892e --- /dev/null +++ b/services/core/java/com/android/server/twilight/TwilightListener.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.twilight; + +public interface TwilightListener { + void onTwilightStateChanged(); +}
\ No newline at end of file diff --git a/services/core/java/com/android/server/twilight/TwilightManager.java b/services/core/java/com/android/server/twilight/TwilightManager.java new file mode 100644 index 000000000000..b3de58b279af --- /dev/null +++ b/services/core/java/com/android/server/twilight/TwilightManager.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.twilight; + +import android.os.Handler; + +public interface TwilightManager { + void registerListener(TwilightListener listener, Handler handler); + TwilightState getCurrentState(); +} diff --git a/services/java/com/android/server/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java index 0356faa610f5..a71961c8fe9b 100644 --- a/services/java/com/android/server/TwilightService.java +++ b/services/core/java/com/android/server/twilight/TwilightService.java @@ -14,7 +14,10 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.twilight; + +import com.android.server.SystemService; +import com.android.server.TwilightCalculator; import android.app.AlarmManager; import android.app.PendingIntent; @@ -34,9 +37,7 @@ import android.text.format.DateUtils; import android.text.format.Time; import android.util.Slog; -import java.text.DateFormat; import java.util.ArrayList; -import java.util.Date; import java.util.Iterator; import libcore.util.Objects; @@ -47,78 +48,92 @@ import libcore.util.Objects; * Used by the UI mode manager and other components to adjust night mode * effects based on sunrise and sunset. */ -public final class TwilightService { - private static final String TAG = "TwilightService"; - - private static final boolean DEBUG = false; - - private static final String ACTION_UPDATE_TWILIGHT_STATE = +public final class TwilightService extends SystemService { + static final String TAG = "TwilightService"; + static final boolean DEBUG = false; + static final String ACTION_UPDATE_TWILIGHT_STATE = "com.android.server.action.UPDATE_TWILIGHT_STATE"; - private final Context mContext; - private final AlarmManager mAlarmManager; - private final LocationManager mLocationManager; - private final LocationHandler mLocationHandler; + final Object mLock = new Object(); - private final Object mLock = new Object(); + AlarmManager mAlarmManager; + LocationManager mLocationManager; + LocationHandler mLocationHandler; - private final ArrayList<TwilightListenerRecord> mListeners = + final ArrayList<TwilightListenerRecord> mListeners = new ArrayList<TwilightListenerRecord>(); - private boolean mSystemReady; - - private TwilightState mTwilightState; + TwilightState mTwilightState; public TwilightService(Context context) { - mContext = context; + super(context); + } - mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); - mLocationManager = (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE); + @Override + public void onStart() { + mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); + mLocationManager = (LocationManager) getContext().getSystemService( + Context.LOCATION_SERVICE); mLocationHandler = new LocationHandler(); + + IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED); + filter.addAction(Intent.ACTION_TIME_CHANGED); + filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); + filter.addAction(ACTION_UPDATE_TWILIGHT_STATE); + getContext().registerReceiver(mUpdateLocationReceiver, filter); + + publishLocalService(TwilightManager.class, mService); } - void systemReady() { - synchronized (mLock) { - mSystemReady = true; + private static class TwilightListenerRecord implements Runnable { + private final TwilightListener mListener; + private final Handler mHandler; - IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED); - filter.addAction(Intent.ACTION_TIME_CHANGED); - filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); - filter.addAction(ACTION_UPDATE_TWILIGHT_STATE); - mContext.registerReceiver(mUpdateLocationReceiver, filter); + public TwilightListenerRecord(TwilightListener listener, Handler handler) { + mListener = listener; + mHandler = handler; + } - if (!mListeners.isEmpty()) { - mLocationHandler.enableLocationUpdates(); - } + public void postUpdate() { + mHandler.post(this); } - } - /** - * Gets the current twilight state. - * - * @return The current twilight state, or null if no information is available. - */ - public TwilightState getCurrentState() { - synchronized (mLock) { - return mTwilightState; + @Override + public void run() { + mListener.onTwilightStateChanged(); } + } - /** - * Listens for twilight time. - * - * @param listener The listener. - * @param handler The handler on which to post calls into the listener. - */ - public void registerListener(TwilightListener listener, Handler handler) { - synchronized (mLock) { - mListeners.add(new TwilightListenerRecord(listener, handler)); + private final TwilightManager mService = new TwilightManager() { + /** + * Gets the current twilight state. + * + * @return The current twilight state, or null if no information is available. + */ + @Override + public TwilightState getCurrentState() { + synchronized (mLock) { + return mTwilightState; + } + } + + /** + * Listens for twilight time. + * + * @param listener The listener. + */ + @Override + public void registerListener(TwilightListener listener, Handler handler) { + synchronized (mLock) { + mListeners.add(new TwilightListenerRecord(listener, handler)); - if (mSystemReady && mListeners.size() == 1) { - mLocationHandler.enableLocationUpdates(); + if (mListeners.size() == 1) { + mLocationHandler.enableLocationUpdates(); + } } } - } + }; private void setTwilightState(TwilightState state) { synchronized (mLock) { @@ -128,9 +143,10 @@ public final class TwilightService { } mTwilightState = state; - int count = mListeners.size(); - for (int i = 0; i < count; i++) { - mListeners.get(i).post(); + + final int listenerLen = mListeners.size(); + for (int i = 0; i < listenerLen; i++) { + mListeners.get(i).postUpdate(); } } } @@ -162,124 +178,6 @@ public final class TwilightService { return distance >= totalAccuracy; } - /** - * Describes whether it is day or night. - * This object is immutable. - */ - public static final class TwilightState { - private final boolean mIsNight; - private final long mYesterdaySunset; - private final long mTodaySunrise; - private final long mTodaySunset; - private final long mTomorrowSunrise; - - TwilightState(boolean isNight, - long yesterdaySunset, - long todaySunrise, long todaySunset, - long tomorrowSunrise) { - mIsNight = isNight; - mYesterdaySunset = yesterdaySunset; - mTodaySunrise = todaySunrise; - mTodaySunset = todaySunset; - mTomorrowSunrise = tomorrowSunrise; - } - - /** - * Returns true if it is currently night time. - */ - public boolean isNight() { - return mIsNight; - } - - /** - * Returns the time of yesterday's sunset in the System.currentTimeMillis() timebase, - * or -1 if the sun never sets. - */ - public long getYesterdaySunset() { - return mYesterdaySunset; - } - - /** - * Returns the time of today's sunrise in the System.currentTimeMillis() timebase, - * or -1 if the sun never rises. - */ - public long getTodaySunrise() { - return mTodaySunrise; - } - - /** - * Returns the time of today's sunset in the System.currentTimeMillis() timebase, - * or -1 if the sun never sets. - */ - public long getTodaySunset() { - return mTodaySunset; - } - - /** - * Returns the time of tomorrow's sunrise in the System.currentTimeMillis() timebase, - * or -1 if the sun never rises. - */ - public long getTomorrowSunrise() { - return mTomorrowSunrise; - } - - @Override - public boolean equals(Object o) { - return o instanceof TwilightState && equals((TwilightState)o); - } - - public boolean equals(TwilightState other) { - return other != null - && mIsNight == other.mIsNight - && mYesterdaySunset == other.mYesterdaySunset - && mTodaySunrise == other.mTodaySunrise - && mTodaySunset == other.mTodaySunset - && mTomorrowSunrise == other.mTomorrowSunrise; - } - - @Override - public int hashCode() { - return 0; // don't care - } - - @Override - public String toString() { - DateFormat f = DateFormat.getDateTimeInstance(); - return "{TwilightState: isNight=" + mIsNight - + ", mYesterdaySunset=" + f.format(new Date(mYesterdaySunset)) - + ", mTodaySunrise=" + f.format(new Date(mTodaySunrise)) - + ", mTodaySunset=" + f.format(new Date(mTodaySunset)) - + ", mTomorrowSunrise=" + f.format(new Date(mTomorrowSunrise)) - + "}"; - } - } - - /** - * Listener for changes in twilight state. - */ - public interface TwilightListener { - public void onTwilightStateChanged(); - } - - private static final class TwilightListenerRecord implements Runnable { - private final TwilightListener mListener; - private final Handler mHandler; - - public TwilightListenerRecord(TwilightListener listener, Handler handler) { - mListener = listener; - mHandler = handler; - } - - public void post() { - mHandler.post(this); - } - - @Override - public void run() { - mListener.onTwilightStateChanged(); - } - } - private final class LocationHandler extends Handler { private static final int MSG_ENABLE_LOCATION_UPDATES = 1; private static final int MSG_GET_NEW_LOCATION_UPDATE = 2; @@ -518,11 +416,12 @@ public final class TwilightService { } Intent updateIntent = new Intent(ACTION_UPDATE_TWILIGHT_STATE); - PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, updateIntent, 0); + PendingIntent pendingIntent = PendingIntent.getBroadcast( + getContext(), 0, updateIntent, 0); mAlarmManager.cancel(pendingIntent); mAlarmManager.setExact(AlarmManager.RTC, nextUpdate, pendingIntent); } - }; + } private final BroadcastReceiver mUpdateLocationReceiver = new BroadcastReceiver() { @Override diff --git a/services/core/java/com/android/server/twilight/TwilightState.java b/services/core/java/com/android/server/twilight/TwilightState.java new file mode 100644 index 000000000000..91e24d7d55bf --- /dev/null +++ b/services/core/java/com/android/server/twilight/TwilightState.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.twilight; + +import java.text.DateFormat; +import java.util.Date; + +/** + * Describes whether it is day or night. + * This object is immutable. + */ +public class TwilightState { + private final boolean mIsNight; + private final long mYesterdaySunset; + private final long mTodaySunrise; + private final long mTodaySunset; + private final long mTomorrowSunrise; + + TwilightState(boolean isNight, + long yesterdaySunset, + long todaySunrise, long todaySunset, + long tomorrowSunrise) { + mIsNight = isNight; + mYesterdaySunset = yesterdaySunset; + mTodaySunrise = todaySunrise; + mTodaySunset = todaySunset; + mTomorrowSunrise = tomorrowSunrise; + } + + /** + * Returns true if it is currently night time. + */ + public boolean isNight() { + return mIsNight; + } + + /** + * Returns the time of yesterday's sunset in the System.currentTimeMillis() timebase, + * or -1 if the sun never sets. + */ + public long getYesterdaySunset() { + return mYesterdaySunset; + } + + /** + * Returns the time of today's sunrise in the System.currentTimeMillis() timebase, + * or -1 if the sun never rises. + */ + public long getTodaySunrise() { + return mTodaySunrise; + } + + /** + * Returns the time of today's sunset in the System.currentTimeMillis() timebase, + * or -1 if the sun never sets. + */ + public long getTodaySunset() { + return mTodaySunset; + } + + /** + * Returns the time of tomorrow's sunrise in the System.currentTimeMillis() timebase, + * or -1 if the sun never rises. + */ + public long getTomorrowSunrise() { + return mTomorrowSunrise; + } + + @Override + public boolean equals(Object o) { + return o instanceof TwilightState && equals((TwilightState)o); + } + + public boolean equals(TwilightState other) { + return other != null + && mIsNight == other.mIsNight + && mYesterdaySunset == other.mYesterdaySunset + && mTodaySunrise == other.mTodaySunrise + && mTodaySunset == other.mTodaySunset + && mTomorrowSunrise == other.mTomorrowSunrise; + } + + @Override + public int hashCode() { + return 0; // don't care + } + + @Override + public String toString() { + DateFormat f = DateFormat.getDateTimeInstance(); + return "{TwilightState: isNight=" + mIsNight + + ", mYesterdaySunset=" + f.format(new Date(mYesterdaySunset)) + + ", mTodaySunrise=" + f.format(new Date(mTodaySunrise)) + + ", mTodaySunset=" + f.format(new Date(mTodaySunset)) + + ", mTomorrowSunrise=" + f.format(new Date(mTomorrowSunrise)) + + "}"; + } +} diff --git a/services/java/com/android/server/updates/CarrierProvisioningUrlsInstallReceiver.java b/services/core/java/com/android/server/updates/CarrierProvisioningUrlsInstallReceiver.java index b53fb650c627..b53fb650c627 100644 --- a/services/java/com/android/server/updates/CarrierProvisioningUrlsInstallReceiver.java +++ b/services/core/java/com/android/server/updates/CarrierProvisioningUrlsInstallReceiver.java diff --git a/services/java/com/android/server/updates/CertPinInstallReceiver.java b/services/core/java/com/android/server/updates/CertPinInstallReceiver.java index c03fbc3d0aed..c03fbc3d0aed 100644 --- a/services/java/com/android/server/updates/CertPinInstallReceiver.java +++ b/services/core/java/com/android/server/updates/CertPinInstallReceiver.java diff --git a/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java b/services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java index 9601e9ad7ccb..9601e9ad7ccb 100644 --- a/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java +++ b/services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java diff --git a/services/java/com/android/server/updates/IntentFirewallInstallReceiver.java b/services/core/java/com/android/server/updates/IntentFirewallInstallReceiver.java index 0b54f92103dd..0b54f92103dd 100644 --- a/services/java/com/android/server/updates/IntentFirewallInstallReceiver.java +++ b/services/core/java/com/android/server/updates/IntentFirewallInstallReceiver.java diff --git a/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java b/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java index e43081436324..e43081436324 100644 --- a/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java +++ b/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java diff --git a/services/java/com/android/server/updates/SmsShortCodesInstallReceiver.java b/services/core/java/com/android/server/updates/SmsShortCodesInstallReceiver.java index 0f14f57cbd5a..0f14f57cbd5a 100644 --- a/services/java/com/android/server/updates/SmsShortCodesInstallReceiver.java +++ b/services/core/java/com/android/server/updates/SmsShortCodesInstallReceiver.java diff --git a/services/java/com/android/server/updates/TZInfoInstallReceiver.java b/services/core/java/com/android/server/updates/TZInfoInstallReceiver.java index 83adbdbd7799..83adbdbd7799 100644 --- a/services/java/com/android/server/updates/TZInfoInstallReceiver.java +++ b/services/core/java/com/android/server/updates/TZInfoInstallReceiver.java diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index e6b6b93a1d46..97ea52c0a4a2 100644 --- a/services/java/com/android/server/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.wallpaper; import static android.os.ParcelFileDescriptor.*; @@ -85,8 +85,8 @@ import com.android.internal.content.PackageMonitor; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.JournaledFile; -class WallpaperManagerService extends IWallpaperManager.Stub { - static final String TAG = "WallpaperService"; +public class WallpaperManagerService extends IWallpaperManager.Stub { + static final String TAG = "WallpaperManagerService"; static final boolean DEBUG = false; final Object mLock = new Object[0]; @@ -98,7 +98,6 @@ class WallpaperManagerService extends IWallpaperManager.Stub { static final long MIN_WALLPAPER_CRASH_TIME = 10000; static final String WALLPAPER = "wallpaper"; static final String WALLPAPER_INFO = "wallpaper_info.xml"; - /** * Name of the component used to display bitmap wallpapers from either the gallery or * built-in wallpapers. @@ -505,7 +504,12 @@ class WallpaperManagerService extends IWallpaperManager.Stub { } } - String getName() { + /** Called by SystemBackupAgent */ + public String getName() { + // Verify caller is the system + if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { + throw new RuntimeException("getName() can only be called from the system process"); + } synchronized (mLock) { return mWallpaperMap.get(0).name; } @@ -1175,7 +1179,11 @@ class WallpaperManagerService extends IWallpaperManager.Stub { } // Called by SystemBackupAgent after files are restored to disk. - void settingsRestored() { + public void settingsRestored() { + // Verify caller is the system + if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { + throw new RuntimeException("settingsRestored() can only be called from the system process"); + } // TODO: If necessary, make it work for secondary users as well. This currently assumes // restores only to the primary user if (DEBUG) Slog.v(TAG, "settingsRestored"); diff --git a/services/java/com/android/server/wifi/README.txt b/services/core/java/com/android/server/wifi/README.txt index 39e14751ab13..39e14751ab13 100644 --- a/services/java/com/android/server/wifi/README.txt +++ b/services/core/java/com/android/server/wifi/README.txt diff --git a/services/java/com/android/server/wifi/WifiController.java b/services/core/java/com/android/server/wifi/WifiController.java index a3d514e304ca..a3d514e304ca 100644 --- a/services/java/com/android/server/wifi/WifiController.java +++ b/services/core/java/com/android/server/wifi/WifiController.java diff --git a/services/java/com/android/server/wifi/WifiNotificationController.java b/services/core/java/com/android/server/wifi/WifiNotificationController.java index a9206e09b803..a9206e09b803 100644 --- a/services/java/com/android/server/wifi/WifiNotificationController.java +++ b/services/core/java/com/android/server/wifi/WifiNotificationController.java diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/core/java/com/android/server/wifi/WifiService.java index f2efde101565..f2efde101565 100644 --- a/services/java/com/android/server/wifi/WifiService.java +++ b/services/core/java/com/android/server/wifi/WifiService.java diff --git a/services/java/com/android/server/wifi/WifiSettingsStore.java b/services/core/java/com/android/server/wifi/WifiSettingsStore.java index 3ff80616142c..3ff80616142c 100644 --- a/services/java/com/android/server/wifi/WifiSettingsStore.java +++ b/services/core/java/com/android/server/wifi/WifiSettingsStore.java diff --git a/services/java/com/android/server/wifi/WifiTrafficPoller.java b/services/core/java/com/android/server/wifi/WifiTrafficPoller.java index b4985509047c..b4985509047c 100644 --- a/services/java/com/android/server/wifi/WifiTrafficPoller.java +++ b/services/core/java/com/android/server/wifi/WifiTrafficPoller.java diff --git a/services/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 756e06a68d87..756e06a68d87 100644 --- a/services/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java index 3cccf1d534f2..7fe895b57a90 100644 --- a/services/java/com/android/server/wm/AppWindowAnimator.java +++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java @@ -1,4 +1,18 @@ -// Copyright 2012 Google Inc. All Rights Reserved. +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.android.server.wm; diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index e98014bdea3e..ca4ad8a32e0d 100644 --- a/services/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -105,6 +105,8 @@ class AppWindowToken extends WindowToken { // Input application handle used by the input dispatcher. final InputApplicationHandle mInputApplicationHandle; + boolean mDeferRemoval; + AppWindowToken(WindowManagerService _service, IApplicationToken _token) { super(_service, _token.asBinder(), WindowManager.LayoutParams.TYPE_APPLICATION, true); diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java index 5aa266d473bd..5aa266d473bd 100644 --- a/services/java/com/android/server/wm/BlackFrame.java +++ b/services/core/java/com/android/server/wm/BlackFrame.java diff --git a/services/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java index c189ddd86c14..c09ea5cead82 100644 --- a/services/java/com/android/server/wm/DimLayer.java +++ b/services/core/java/com/android/server/wm/DimLayer.java @@ -1,4 +1,18 @@ -// Copyright 2012 Google Inc. All Rights Reserved. +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.android.server.wm; @@ -51,9 +65,9 @@ public class DimLayer { /** Owning stack */ final TaskStack mStack; - DimLayer(WindowManagerService service, TaskStack stack) { + DimLayer(WindowManagerService service, TaskStack stack, DisplayContent displayContent) { mStack = stack; - mDisplayContent = stack.getDisplayContent(); + mDisplayContent = displayContent; final int displayId = mDisplayContent.getDisplayId(); if (DEBUG) Slog.v(TAG, "Ctor: displayId=" + displayId); SurfaceControl.openTransaction(); @@ -125,8 +139,54 @@ public class DimLayer { } } + /** + * @param layer The new layer value. + * @param inTransaction Whether the call is made within a surface transaction. + */ + void adjustSurface(int layer, boolean inTransaction) { + final int dw, dh; + final float xPos, yPos; + if (!mStack.isFullscreen()) { + dw = mBounds.width(); + dh = mBounds.height(); + xPos = mBounds.left; + yPos = mBounds.top; + } else { + // Set surface size to screen size. + final DisplayInfo info = mDisplayContent.getDisplayInfo(); + // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose + // a corner. + dw = (int) (info.logicalWidth * 1.5); + dh = (int) (info.logicalHeight * 1.5); + // back off position so 1/4 of Surface is before and 1/4 is after. + xPos = -1 * dw / 6; + yPos = -1 * dh / 6; + } + + try { + if (!inTransaction) { + SurfaceControl.openTransaction(); + } + mDimSurface.setPosition(xPos, yPos); + mDimSurface.setSize(dw, dh); + mDimSurface.setLayer(layer); + } catch (RuntimeException e) { + Slog.w(TAG, "Failure setting size or layer", e); + } finally { + if (!inTransaction) { + SurfaceControl.closeTransaction(); + } + } + mLastBounds.set(mBounds); + mLayer = layer; + } + + // Assumes that surface transactions are currently closed. void setBounds(Rect bounds) { mBounds.set(bounds); + if (isDimming() && !mLastBounds.equals(bounds)) { + adjustSurface(mLayer, false); + } } /** @@ -164,35 +224,8 @@ public class DimLayer { return; } - final int dw, dh; - final float xPos, yPos; - if (mStack.hasSibling()) { - dw = mBounds.width(); - dh = mBounds.height(); - xPos = mBounds.left; - yPos = mBounds.right; - } else { - // Set surface size to screen size. - final DisplayInfo info = mDisplayContent.getDisplayInfo(); - // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose a - // corner. - dw = (int) (info.logicalWidth * 1.5); - dh = (int) (info.logicalHeight * 1.5); - // back off position so 1/4 of Surface is before and 1/4 is after. - xPos = -1 * dw / 6; - yPos = -1 * dh / 6; - } - if (!mLastBounds.equals(mBounds) || mLayer != layer) { - try { - mDimSurface.setPosition(xPos, yPos); - mDimSurface.setSize(dw, dh); - mDimSurface.setLayer(layer); - } catch (RuntimeException e) { - Slog.w(TAG, "Failure setting size or layer", e); - } - mLastBounds.set(mBounds); - mLayer = layer; + adjustSurface(layer, true); } long curTime = SystemClock.uptimeMillis(); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java new file mode 100644 index 000000000000..68834d8f691b --- /dev/null +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -0,0 +1,372 @@ +/* + * 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 com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; +import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY; +import static com.android.server.wm.WindowManagerService.TAG; + +import android.graphics.Rect; +import android.graphics.Region; +import android.util.Slog; +import android.view.Display; +import android.view.DisplayInfo; +import android.view.Surface; + +import java.io.PrintWriter; +import java.util.ArrayList; + +class DisplayContentList extends ArrayList<DisplayContent> { +} + +/** + * Utility class for keeping track of the WindowStates and other pertinent contents of a + * particular Display. + * + * IMPORTANT: No method from this class should ever be used without holding + * WindowManagerService.mWindowMap. + */ +class DisplayContent { + + /** Unique identifier of this stack. */ + private final int mDisplayId; + + /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element + * from mDisplayWindows; */ + private final WindowList mWindows = new WindowList(); + + // This protects the following display size properties, so that + // getDisplaySize() doesn't need to acquire the global lock. This is + // needed because the window manager sometimes needs to use ActivityThread + // while it has its global state locked (for example to load animation + // resources), but the ActivityThread also needs get the current display + // size sometimes when it has its package lock held. + // + // These will only be modified with both mWindowMap and mDisplaySizeLock + // held (in that order) so the window manager doesn't need to acquire this + // lock when needing these values in its normal operation. + final Object mDisplaySizeLock = new Object(); + int mInitialDisplayWidth = 0; + int mInitialDisplayHeight = 0; + int mInitialDisplayDensity = 0; + int mBaseDisplayWidth = 0; + int mBaseDisplayHeight = 0; + int mBaseDisplayDensity = 0; + private final DisplayInfo mDisplayInfo = new DisplayInfo(); + private final Display mDisplay; + + Rect mBaseDisplayRect = new Rect(); + Rect mContentRect = new Rect(); + + // Accessed directly by all users. + boolean layoutNeeded; + int pendingLayoutChanges; + final boolean isDefaultDisplay; + + /** Window tokens that are in the process of exiting, but still on screen for animations. */ + final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>(); + + /** Array containing all TaskStacks on this display. Array + * is stored in display order with the current bottom stack at 0. */ + private final ArrayList<TaskStack> mStacks = new ArrayList<TaskStack>(); + + /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack + * (except a future lockscreen TaskStack) moves to the top. */ + private TaskStack mHomeStack = null; + + /** Detect user tapping outside of current focused stack bounds .*/ + StackTapPointerEventListener mTapDetector; + + /** Detect user tapping outside of current focused stack bounds .*/ + Region mTouchExcludeRegion = new Region(); + + /** Save allocating when calculating rects */ + Rect mTmpRect = new Rect(); + + /** For gathering Task objects in order. */ + final ArrayList<Task> mTmpTaskHistory = new ArrayList<Task>(); + + final WindowManagerService mService; + + static final int DEFER_DETACH = 1; + static final int DEFER_REMOVAL = 2; + int mDeferredActions; + + /** + * @param display May not be null. + * @param service You know. + */ + DisplayContent(Display display, WindowManagerService service) { + mDisplay = display; + mDisplayId = display.getDisplayId(); + display.getDisplayInfo(mDisplayInfo); + isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY; + mService = service; + } + + int getDisplayId() { + return mDisplayId; + } + + WindowList getWindowList() { + return mWindows; + } + + Display getDisplay() { + return mDisplay; + } + + DisplayInfo getDisplayInfo() { + return mDisplayInfo; + } + + /** + * Returns true if the specified UID has access to this display. + */ + public boolean hasAccess(int uid) { + return mDisplay.hasAccess(uid); + } + + public boolean isPrivate() { + return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0; + } + + ArrayList<TaskStack> getStacks() { + return mStacks; + } + + /** + * Retrieve the tasks on this display in stack order from the bottommost TaskStack up. + * @return All the Tasks, in order, on this display. + */ + ArrayList<Task> getTasks() { + mTmpTaskHistory.clear(); + final int numStacks = mStacks.size(); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + mTmpTaskHistory.addAll(mStacks.get(stackNdx).getTasks()); + } + return mTmpTaskHistory; + } + + TaskStack getHomeStack() { + if (mHomeStack == null) { + Slog.e(TAG, "getHomeStack: Returning null from this=" + this); + } + return mHomeStack; + } + + void updateDisplayInfo() { + mDisplay.getDisplayInfo(mDisplayInfo); + for (int i = mStacks.size() - 1; i >= 0; --i) { + mStacks.get(i).updateDisplayInfo(); + } + } + + void getLogicalDisplayRect(Rect out) { + // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. + final int orientation = mDisplayInfo.rotation; + boolean rotated = (orientation == Surface.ROTATION_90 + || orientation == Surface.ROTATION_270); + final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; + final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; + int width = mDisplayInfo.logicalWidth; + int left = (physWidth - width) / 2; + int height = mDisplayInfo.logicalHeight; + int top = (physHeight - height) / 2; + out.set(left, top, left + width, top + height); + } + + /** Refer to {@link WindowManagerService#attachStack(int, int)} */ + void attachStack(TaskStack stack) { + if (stack.mStackId == HOME_STACK_ID) { + if (mHomeStack != null) { + throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first."); + } + mHomeStack = stack; + } + mStacks.add(stack); + layoutNeeded = true; + } + + void moveStack(TaskStack stack, boolean toTop) { + mStacks.remove(stack); + mStacks.add(toTop ? mStacks.size() : 0, stack); + } + + void detachStack(TaskStack stack) { + mStacks.remove(stack); + } + + /** + * Propagate the new bounds to all child stacks. + * @param contentRect The bounds to apply at the top level. + */ + void resize(Rect contentRect) { + mContentRect.set(contentRect); + } + + int stackIdFromPoint(int x, int y) { + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + final TaskStack stack = mStacks.get(stackNdx); + stack.getBounds(mTmpRect); + if (mTmpRect.contains(x, y)) { + return stack.mStackId; + } + } + return -1; + } + + void setTouchExcludeRegion(TaskStack focusedStack) { + mTouchExcludeRegion.set(mBaseDisplayRect); + WindowList windows = getWindowList(); + for (int i = windows.size() - 1; i >= 0; --i) { + final WindowState win = windows.get(i); + final TaskStack stack = win.getStack(); + if (win.isVisibleLw() && stack != null && stack != focusedStack) { + mTmpRect.set(win.mVisibleFrame); + mTmpRect.intersect(win.mVisibleInsets); + mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE); + } + } + } + + void switchUserStacks(int newUserId) { + final WindowList windows = getWindowList(); + for (int i = 0; i < windows.size(); i++) { + final WindowState win = windows.get(i); + if (win.isHiddenFromUserLocked()) { + if (DEBUG_VISIBILITY) Slog.w(TAG, "user changing " + newUserId + " hiding " + + win + ", attrs=" + win.mAttrs.type + ", belonging to " + + win.mOwnerUid); + win.hideLw(false); + } + } + + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + mStacks.get(stackNdx).switchUser(newUserId); + } + } + + void resetAnimationBackgroundAnimator() { + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + mStacks.get(stackNdx).resetAnimationBackgroundAnimator(); + } + } + + boolean animateDimLayers() { + boolean result = false; + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + result |= mStacks.get(stackNdx).animateDimLayers(); + } + return result; + } + + void resetDimming() { + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + mStacks.get(stackNdx).resetDimmingTag(); + } + } + + boolean isDimming() { + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + if (mStacks.get(stackNdx).isDimming()) { + return true; + } + } + return false; + } + + void stopDimmingIfNeeded() { + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + mStacks.get(stackNdx).stopDimmingIfNeeded(); + } + } + + void close() { + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + mStacks.get(stackNdx).close(); + } + } + + public void dump(String prefix, PrintWriter pw) { + pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); + final String subPrefix = " " + prefix; + pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x"); + pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity); + pw.print("dpi"); + if (mInitialDisplayWidth != mBaseDisplayWidth + || mInitialDisplayHeight != mBaseDisplayHeight + || mInitialDisplayDensity != mBaseDisplayDensity) { + pw.print(" base="); + pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); + pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi"); + } + pw.print(" cur="); + pw.print(mDisplayInfo.logicalWidth); + pw.print("x"); pw.print(mDisplayInfo.logicalHeight); + pw.print(" app="); + pw.print(mDisplayInfo.appWidth); + pw.print("x"); pw.print(mDisplayInfo.appHeight); + pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth); + pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); + pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); + pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); + pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded); + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + final TaskStack stack = mStacks.get(stackNdx); + pw.print(prefix); pw.print("mStacks[" + stackNdx + "]"); pw.println(stack.mStackId); + stack.dump(prefix + " ", pw); + } + pw.println(); + pw.println(" Application tokens in bottom up Z order:"); + int ndx = 0; + final int numStacks = mStacks.size(); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { + AppTokenList tokens = tasks.get(taskNdx).mAppTokens; + for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { + final AppWindowToken wtoken = tokens.get(tokenNdx); + pw.print(" App #"); pw.print(ndx++); + pw.print(' '); pw.print(wtoken); pw.println(":"); + wtoken.dump(pw, " "); + } + } + } + if (ndx == 0) { + pw.println(" None"); + } + pw.println(); + if (!mExitingTokens.isEmpty()) { + pw.println(); + pw.println(" Exiting tokens:"); + for (int i=mExitingTokens.size()-1; i>=0; i--) { + WindowToken token = mExitingTokens.get(i); + pw.print(" Exiting #"); pw.print(i); + pw.print(' '); pw.print(token); + pw.println(':'); + token.dump(pw, " "); + } + } + pw.println(); + } + + @Override + public String toString() { + return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mStacks; + } +} diff --git a/services/java/com/android/server/wm/DisplayMagnifier.java b/services/core/java/com/android/server/wm/DisplayMagnifier.java index 382d7b4a94af..382d7b4a94af 100644 --- a/services/java/com/android/server/wm/DisplayMagnifier.java +++ b/services/core/java/com/android/server/wm/DisplayMagnifier.java diff --git a/services/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplaySettings.java index 34d1a647e10f..34d1a647e10f 100644 --- a/services/java/com/android/server/wm/DisplaySettings.java +++ b/services/core/java/com/android/server/wm/DisplaySettings.java diff --git a/services/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index a73793968f49..a73793968f49 100644 --- a/services/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java diff --git a/services/java/com/android/server/wm/FakeWindowImpl.java b/services/core/java/com/android/server/wm/FakeWindowImpl.java index 5a3471b06215..5a3471b06215 100644 --- a/services/java/com/android/server/wm/FakeWindowImpl.java +++ b/services/core/java/com/android/server/wm/FakeWindowImpl.java diff --git a/services/java/com/android/server/wm/FocusedStackFrame.java b/services/core/java/com/android/server/wm/FocusedStackFrame.java index cc48b867f6df..f1f5fe88cc85 100644 --- a/services/java/com/android/server/wm/FocusedStackFrame.java +++ b/services/core/java/com/android/server/wm/FocusedStackFrame.java @@ -41,7 +41,7 @@ class FocusedStackFrame { private final SurfaceControl mSurfaceControl; private final Surface mSurface = new Surface(); private final Rect mLastBounds = new Rect(); - private final Rect mBounds = new Rect(); + final Rect mBounds = new Rect(); private final Rect mTmpDrawRect = new Rect(); public FocusedStackFrame(Display display, SurfaceSession session) { @@ -131,9 +131,9 @@ class FocusedStackFrame { } } - public void setBounds(Rect bounds) { - if (false && DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + bounds); - mBounds.set(bounds); + public void setBounds(TaskStack stack) { + stack.getBounds(mBounds); + if (false && DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + mBounds); } public void setLayer(int layer) { diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 3d2ec4577acf..4aae5c12383a 100644 --- a/services/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -58,6 +58,8 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { private final Object mInputDevicesReadyMonitor = new Object(); private boolean mInputDevicesReady; + Rect mTmpRect = new Rect(); + public InputMonitor(WindowManagerService service) { mService = service; } @@ -175,7 +177,8 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { if (modal && child.mAppToken != null) { // Limit the outer touch to the activity stack region. flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; - inputWindowHandle.touchableRegion.set(child.getStackBounds()); + child.getStackBounds(mTmpRect); + inputWindowHandle.touchableRegion.set(mTmpRect); } else { // Not modal or full screen modal child.getTouchableRegion(inputWindowHandle.touchableRegion); @@ -361,8 +364,8 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { * motion event processing when the screen is off since these events are normally * dropped. */ @Override - public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) { - return mService.mPolicy.interceptMotionBeforeQueueingWhenScreenOff(policyFlags); + public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags) { + return mService.mPolicy.interceptMotionBeforeQueueingWhenScreenOff(whenNanos, policyFlags); } /* Provides an opportunity for the window manager policy to process a key before diff --git a/services/java/com/android/server/wm/KeyguardDisableHandler.java b/services/core/java/com/android/server/wm/KeyguardDisableHandler.java index 859df519169c..859df519169c 100644 --- a/services/java/com/android/server/wm/KeyguardDisableHandler.java +++ b/services/core/java/com/android/server/wm/KeyguardDisableHandler.java diff --git a/services/java/com/android/server/wm/PointerEventDispatcher.java b/services/core/java/com/android/server/wm/PointerEventDispatcher.java index 6b0e4c9f010a..6b0e4c9f010a 100644 --- a/services/java/com/android/server/wm/PointerEventDispatcher.java +++ b/services/core/java/com/android/server/wm/PointerEventDispatcher.java diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index e630737b40b7..e630737b40b7 100644 --- a/services/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java diff --git a/services/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 87cabc9a510b..ca9076f51496 100644 --- a/services/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -293,7 +293,11 @@ final class Session extends IWindowSession.Stub // !!! FIXME: put all this heavy stuff onto the mH looper, as well as // the actual drag event dispatch stuff in the dragstate - Display display = callingWin.mDisplayContent.getDisplay(); + final DisplayContent displayContent = callingWin.getDisplayContent(); + if (displayContent == null) { + return false; + } + Display display = displayContent.getDisplay(); mService.mDragState.register(display); mService.mInputMonitor.updateInputWindowsLw(true /*force*/); if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel, diff --git a/services/java/com/android/server/wm/StackTapPointerEventListener.java b/services/core/java/com/android/server/wm/StackTapPointerEventListener.java index 19d8ab372afe..19d8ab372afe 100644 --- a/services/java/com/android/server/wm/StackTapPointerEventListener.java +++ b/services/core/java/com/android/server/wm/StackTapPointerEventListener.java diff --git a/services/java/com/android/server/wm/StartingData.java b/services/core/java/com/android/server/wm/StartingData.java index 7115b0fd02e5..7115b0fd02e5 100644 --- a/services/java/com/android/server/wm/StartingData.java +++ b/services/core/java/com/android/server/wm/StartingData.java diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/core/java/com/android/server/wm/StrictModeFlash.java index fb5876b65aed..fb5876b65aed 100644 --- a/services/java/com/android/server/wm/StrictModeFlash.java +++ b/services/core/java/com/android/server/wm/StrictModeFlash.java diff --git a/services/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 13fdbc83b2ce..09c4e20b6d5a 100644 --- a/services/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -16,15 +16,17 @@ package com.android.server.wm; +import static com.android.server.wm.WindowManagerService.TAG; + import android.util.EventLog; -import com.android.server.EventLogTags; +import android.util.Slog; class Task { -// private final String TAG = "TaskGroup"; TaskStack mStack; final AppTokenList mAppTokens = new AppTokenList(); final int taskId; final int mUserId; + boolean mDeferRemoval = false; Task(AppWindowToken wtoken, TaskStack stack, int userId) { taskId = wtoken.groupId; @@ -38,18 +40,24 @@ class Task { } void addAppToken(int addPos, AppWindowToken wtoken) { + final int lastPos = mAppTokens.size(); + if (addPos > lastPos) { + // We lost an app token. Don't crash though. + Slog.e(TAG, "Task.addAppToken: Out of bounds attempt token=" + wtoken + " addPos=" + + addPos + " lastPos=" + lastPos); + addPos = lastPos; + } mAppTokens.add(addPos, wtoken); + mDeferRemoval = false; } boolean removeAppToken(AppWindowToken wtoken) { - mAppTokens.remove(wtoken); + boolean removed = mAppTokens.remove(wtoken); if (mAppTokens.size() == 0) { EventLog.writeEvent(com.android.server.EventLogTags.WM_TASK_REMOVED, taskId, "removeAppToken: last token"); - mStack.removeTask(this); - return true; } - return false; + return removed; } @Override diff --git a/services/java/com/android/server/wm/TaskGroup.java b/services/core/java/com/android/server/wm/TaskGroup.java index 1f1dd5832d55..1f1dd5832d55 100644 --- a/services/java/com/android/server/wm/TaskGroup.java +++ b/services/core/java/com/android/server/wm/TaskGroup.java diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index cb29df474874..c70bc621658b 100644 --- a/services/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -26,8 +26,6 @@ import android.util.Slog; import android.util.TypedValue; import com.android.server.EventLogTags; -import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; - import java.io.PrintWriter; import java.util.ArrayList; @@ -43,23 +41,29 @@ public class TaskStack { private final WindowManagerService mService; /** The display this stack sits under. */ - private final DisplayContent mDisplayContent; + private DisplayContent mDisplayContent; /** The Tasks that define this stack. Oldest Tasks are at the bottom. The ordering must match * mTaskHistory in the ActivityStack with the same mStackId */ private final ArrayList<Task> mTasks = new ArrayList<Task>(); - /** The StackBox this sits in. */ - StackBox mStackBox; + /** For comparison with DisplayContent bounds. */ + private Rect mTmpRect = new Rect(); + + /** Content limits relative to the DisplayContent this sits in. */ + private Rect mBounds = new Rect(); + + /** Whether mBounds is fullscreen */ + private boolean mFullscreen = true; /** Used to support {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND} */ - final DimLayer mDimLayer; + private DimLayer mDimLayer; /** The particular window with FLAG_DIM_BEHIND set. If null, hide mDimLayer. */ WindowStateAnimator mDimWinAnimator; /** Support for non-zero {@link android.view.animation.Animation#getBackgroundColor()} */ - final DimLayer mAnimationBackgroundSurface; + DimLayer mAnimationBackgroundSurface; /** The particular window with an Animation with non-zero background color. */ WindowStateAnimator mAnimationBackgroundAnimator; @@ -68,12 +72,15 @@ public class TaskStack { * then stop any dimming. */ boolean mDimmingTag; - TaskStack(WindowManagerService service, int stackId, DisplayContent displayContent) { + /** Application tokens that are exiting, but still on screen for animations. */ + final AppTokenList mExitingAppTokens = new AppTokenList(); + + TaskStack(WindowManagerService service, int stackId) { mService = service; mStackId = stackId; - mDisplayContent = displayContent; - mDimLayer = new DimLayer(service, this); - mAnimationBackgroundSurface = new DimLayer(service, this); + // TODO: remove bounds from log, they are always 0. + EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, mBounds.left, mBounds.top, + mBounds.right, mBounds.bottom); } DisplayContent getDisplayContent() { @@ -84,12 +91,73 @@ public class TaskStack { return mTasks; } - boolean isHomeStack() { - return mStackId == HOME_STACK_ID; + void resizeWindows() { + final boolean underStatusBar = mBounds.top == 0; + + final ArrayList<WindowState> resizingWindows = mService.mResizingWindows; + for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { + final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens; + for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { + final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows; + for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { + final WindowState win = windows.get(winNdx); + if (!resizingWindows.contains(win)) { + if (WindowManagerService.DEBUG_RESIZE) Slog.d(TAG, + "setBounds: Resizing " + win); + resizingWindows.add(win); + } + win.mUnderStatusBar = underStatusBar; + } + } + } } - boolean hasSibling() { - return mStackBox.mParent != null; + boolean setBounds(Rect bounds) { + boolean oldFullscreen = mFullscreen; + if (mDisplayContent != null) { + mDisplayContent.getLogicalDisplayRect(mTmpRect); + mFullscreen = mTmpRect.equals(bounds); + } + + if (mBounds.equals(bounds) && oldFullscreen == mFullscreen) { + return false; + } + + mDimLayer.setBounds(bounds); + mAnimationBackgroundSurface.setBounds(bounds); + mBounds.set(bounds); + + return true; + } + + void getBounds(Rect out) { + out.set(mBounds); + } + + void updateDisplayInfo() { + if (mFullscreen && mDisplayContent != null) { + mDisplayContent.getLogicalDisplayRect(mTmpRect); + setBounds(mTmpRect); + } + } + + boolean isFullscreen() { + return mFullscreen; + } + + boolean isAnimating() { + for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { + final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens; + for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { + final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows; + for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { + if (windows.get(winNdx).mWinAnimator.isAnimating()) { + return true; + } + } + } + } + return false; } /** @@ -97,9 +165,7 @@ public class TaskStack { * @param task The task to add. * @param toTop Whether to add it to the top or bottom. */ - boolean addTask(Task task, boolean toTop) { - mStackBox.makeDirty(); - + void addTask(Task task, boolean toTop) { int stackNdx; if (!toTop) { stackNdx = 0; @@ -121,40 +187,60 @@ public class TaskStack { mTasks.add(stackNdx, task); task.mStack = this; - mDisplayContent.addTask(task, toTop); - return mDisplayContent.moveHomeStackBox(mStackId == HOME_STACK_ID); + mDisplayContent.moveStack(this, true); + EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.taskId, toTop ? 1 : 0, stackNdx); } - boolean moveTaskToTop(Task task) { + void moveTaskToTop(Task task) { if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "moveTaskToTop: task=" + task + " Callers=" + Debug.getCallers(6)); mTasks.remove(task); - return addTask(task, true); + addTask(task, true); } - boolean moveTaskToBottom(Task task) { + void moveTaskToBottom(Task task) { if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "moveTaskToBottom: task=" + task); mTasks.remove(task); - return addTask(task, false); + addTask(task, false); } /** - * Delete a Task from this stack. If it is the last Task in the stack, remove this stack from - * its parent StackBox and merge the parent. + * Delete a Task from this stack. If it is the last Task in the stack, move this stack to the + * back. * @param task The Task to delete. */ void removeTask(Task task) { if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "removeTask: task=" + task); - mStackBox.makeDirty(); mTasks.remove(task); - mDisplayContent.removeTask(task); + if (mDisplayContent != null) { + if (mTasks.isEmpty()) { + mDisplayContent.moveStack(this, false); + } + mDisplayContent.layoutNeeded = true; + } + } + + void attachDisplayContent(DisplayContent displayContent) { + if (mDisplayContent != null) { + throw new IllegalStateException("attachDisplayContent: Already attached"); + } + + mDisplayContent = displayContent; + mDimLayer = new DimLayer(mService, this, displayContent); + mAnimationBackgroundSurface = new DimLayer(mService, this, displayContent); + updateDisplayInfo(); } - int remove() { + void detachDisplay() { + EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId); + for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { + mService.tmpRemoveTaskWindowsLocked(mTasks.get(taskNdx)); + } mAnimationBackgroundSurface.destroySurface(); + mAnimationBackgroundSurface = null; mDimLayer.destroySurface(); - EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId); - return mStackBox.remove(); + mDimLayer = null; + mDisplayContent = null; } void resetAnimationBackgroundAnimator() { @@ -259,28 +345,6 @@ public class TaskStack { } } - void setBounds(Rect bounds, boolean underStatusBar) { - mDimLayer.setBounds(bounds); - mAnimationBackgroundSurface.setBounds(bounds); - - final ArrayList<WindowState> resizingWindows = mService.mResizingWindows; - for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { - final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens; - for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { - final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows; - for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { - final WindowState win = windows.get(winNdx); - if (!resizingWindows.contains(win)) { - if (WindowManagerService.DEBUG_RESIZE) Slog.d(TAG, - "setBounds: Resizing " + win); - resizingWindows.add(win); - } - win.mUnderStatusBar = underStatusBar; - } - } - } - } - void switchUser(int userId) { int top = mTasks.size(); for (int taskNdx = 0; taskNdx < top; ++taskNdx) { @@ -293,6 +357,39 @@ public class TaskStack { } } + void close() { + mDimLayer.mDimSurface.destroy(); + mAnimationBackgroundSurface.mDimSurface.destroy(); + } + + void checkForDeferredActions() { + if (mDisplayContent != null && + (mDisplayContent.mDeferredActions & DisplayContent.DEFER_DETACH) != 0 && + !isAnimating()) { + mDisplayContent.mDeferredActions &= ~DisplayContent.DEFER_DETACH; + if ((mDisplayContent.mDeferredActions & DisplayContent.DEFER_REMOVAL) != 0) { + mDisplayContent.mDeferredActions &= ~DisplayContent.DEFER_REMOVAL; + mService.onDisplayRemoved(mDisplayContent.getDisplayId()); + } + mService.detachStack(mStackId); + } + for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { + final Task task = mTasks.get(taskNdx); + AppTokenList tokens = task.mAppTokens; + for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { + AppWindowToken wtoken = tokens.get(tokenNdx); + if (wtoken.mDeferRemoval) { + wtoken.mDeferRemoval = false; + mService.removeAppFromTaskLocked(wtoken); + } + } + if (task.mDeferRemoval) { + task.mDeferRemoval = false; + mService.removeTaskLocked(task); + } + } + } + public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("mStackId="); pw.println(mStackId); for (int taskNdx = 0; taskNdx < mTasks.size(); ++taskNdx) { @@ -307,6 +404,17 @@ public class TaskStack { mDimLayer.printTo(prefix, pw); pw.print(prefix); pw.print("mDimWinAnimator="); pw.println(mDimWinAnimator); } + if (!mExitingAppTokens.isEmpty()) { + pw.println(); + pw.println(" Exiting application tokens:"); + for (int i=mExitingAppTokens.size()-1; i>=0; i--) { + WindowToken token = mExitingAppTokens.get(i); + pw.print(" Exiting App #"); pw.print(i); + pw.print(' '); pw.print(token); + pw.println(':'); + token.dump(pw, " "); + } + } } @Override diff --git a/services/java/com/android/server/wm/ViewServer.java b/services/core/java/com/android/server/wm/ViewServer.java index a763e2c724c4..a763e2c724c4 100644 --- a/services/java/com/android/server/wm/ViewServer.java +++ b/services/core/java/com/android/server/wm/ViewServer.java diff --git a/services/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java index e226e3d73e47..e226e3d73e47 100644 --- a/services/java/com/android/server/wm/Watermark.java +++ b/services/core/java/com/android/server/wm/Watermark.java diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 91f15f3fb7f1..0c682587f19d 100644 --- a/services/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -1,4 +1,18 @@ -// Copyright 2012 Google Inc. All Rights Reserved. +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.android.server.wm; @@ -64,7 +78,7 @@ public class WindowAnimator { Object mLastWindowFreezeSource; SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = - new SparseArray<WindowAnimator.DisplayContentsAnimator>(2); + new SparseArray<DisplayContentsAnimator>(2); boolean mInitialized = false; @@ -151,14 +165,33 @@ public class WindowAnimator { } private void updateAppWindowsLocked(int displayId) { - final DisplayContent displayContent = mService.getDisplayContentLocked(displayId); - final ArrayList<Task> tasks = displayContent.getTasks(); - final int numTasks = tasks.size(); - for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { - final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; - final int numTokens = tokens.size(); - for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { - final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator; + ArrayList<TaskStack> stacks = mService.getDisplayContentLocked(displayId).getStacks(); + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final TaskStack stack = stacks.get(stackNdx); + final ArrayList<Task> tasks = stack.getTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { + final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; + for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { + final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator; + final boolean wasAnimating = appAnimator.animation != null + && appAnimator.animation != AppWindowAnimator.sDummyAnimation; + if (appAnimator.stepAnimationLocked(mCurrentTime)) { + mAnimating = true; + } else if (wasAnimating) { + // stopped animating, do one more pass through the layout + setAppLayoutChanges(appAnimator, + WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, + "appToken " + appAnimator.mAppToken + " done"); + if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, + "updateWindowsApps...: done animating " + appAnimator.mAppToken); + } + } + } + + final AppTokenList exitingAppTokens = stack.mExitingAppTokens; + final int NEAT = exitingAppTokens.size(); + for (int i = 0; i < NEAT; i++) { + final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator; final boolean wasAnimating = appAnimator.animation != null && appAnimator.animation != AppWindowAnimator.sDummyAnimation; if (appAnimator.stepAnimationLocked(mCurrentTime)) { @@ -166,29 +199,12 @@ public class WindowAnimator { } else if (wasAnimating) { // stopped animating, do one more pass through the layout setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, - "appToken " + appAnimator.mAppToken + " done"); + "exiting appToken " + appAnimator.mAppToken + " done"); if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, - "updateWindowsApps...: done animating " + appAnimator.mAppToken); + "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken); } } } - - final AppTokenList exitingAppTokens = displayContent.mExitingAppTokens; - final int NEAT = exitingAppTokens.size(); - for (int i = 0; i < NEAT; i++) { - final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator; - final boolean wasAnimating = appAnimator.animation != null - && appAnimator.animation != AppWindowAnimator.sDummyAnimation; - if (appAnimator.stepAnimationLocked(mCurrentTime)) { - mAnimating = true; - } else if (wasAnimating) { - // stopped animating, do one more pass through the layout - setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, - "exiting appToken " + appAnimator.mAppToken + " done"); - if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, - "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken); - } - } } private void updateWindowsLocked(final int displayId) { @@ -449,11 +465,6 @@ public class WindowAnimator { } } - private void performAnimationsLocked(final int displayId) { - updateWindowsLocked(displayId); - updateWallpaperLocked(displayId); - } - /** Locked on mService.mWindowMap. */ private void animateLocked() { @@ -494,7 +505,8 @@ public class WindowAnimator { // Update animations of all applications, including those // associated with exiting/removed apps - performAnimationsLocked(displayId); + updateWindowsLocked(displayId); + updateWallpaperLocked(displayId); final WindowList windows = mService.getWindowListLocked(displayId); final int N = windows.size(); @@ -642,11 +654,16 @@ public class WindowAnimator { } int getPendingLayoutChanges(final int displayId) { + if (displayId < 0) { + return 0; + } return mService.getDisplayContentLocked(displayId).pendingLayoutChanges; } void setPendingLayoutChanges(final int displayId, final int changes) { - mService.getDisplayContentLocked(displayId).pendingLayoutChanges |= changes; + if (displayId >= 0) { + mService.getDisplayContentLocked(displayId).pendingLayoutChanges |= changes; + } } void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String s) { @@ -655,7 +672,7 @@ public class WindowAnimator { WindowList windows = appAnimator.mAppToken.allAppWindows; for (int i = windows.size() - 1; i >= 0; i--) { final int displayId = windows.get(i).getDisplayId(); - if (displays.indexOfKey(displayId) < 0) { + if (displayId >= 0 && displays.indexOfKey(displayId) < 0) { setPendingLayoutChanges(displayId, changes); if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { mService.debugLayoutRepeats(s, getPendingLayoutChanges(displayId)); @@ -676,10 +693,15 @@ public class WindowAnimator { } void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) { - getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation; + if (displayId >= 0) { + getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation; + } } ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) { + if (displayId < 0) { + return null; + } return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation; } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index f9773a6f25cf..9557b1b152f4 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -18,11 +18,10 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.*; -import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; - import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import android.app.AppOpsManager; +import android.util.ArraySet; import android.util.TimeUtils; import android.view.IWindowId; @@ -35,17 +34,16 @@ import com.android.internal.view.IInputMethodClient; import com.android.internal.view.IInputMethodManager; import com.android.internal.view.WindowManagerPolicyThread; import com.android.server.AttributeCache; +import com.android.server.DisplayThread; import com.android.server.EventLogTags; +import com.android.server.LocalServices; import com.android.server.UiThread; import com.android.server.Watchdog; import com.android.server.am.BatteryStatsService; -import com.android.server.display.DisplayManagerService; import com.android.server.input.InputManagerService; -import com.android.server.power.PowerManagerService; import com.android.server.power.ShutdownThread; import android.Manifest; -import android.app.ActivityManager.StackBoxInfo; import android.app.ActivityManagerNative; import android.app.IActivityManager; import android.app.StatusBarManager; @@ -69,6 +67,7 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.hardware.display.DisplayManager; +import android.hardware.display.DisplayManagerInternal; import android.os.Binder; import android.os.Bundle; import android.os.Debug; @@ -80,6 +79,7 @@ import android.os.Message; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.PowerManager; +import android.os.PowerManagerInternal; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; @@ -117,6 +117,7 @@ import android.view.InputEventReceiver; import android.view.KeyEvent; import android.view.MagnificationSpec; import android.view.MotionEvent; +import android.view.WindowManagerInternal; import android.view.Surface.OutOfResourcesException; import android.view.Surface; import android.view.SurfaceControl; @@ -155,8 +156,7 @@ import java.util.List; /** {@hide} */ public class WindowManagerService extends IWindowManager.Stub - implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs, - DisplayManagerService.WindowManagerFuncs, DisplayManager.DisplayListener { + implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { static final String TAG = "WindowManager"; static final boolean DEBUG = false; static final boolean DEBUG_ADD_REMOVE = false; @@ -272,10 +272,10 @@ public class WindowManagerService extends IWindowManager.Stub // Default input dispatching timeout in nanoseconds. static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; - /** Minimum value for createStack and resizeStack weight value */ + /** Minimum value for attachStack and resizeStack weight value */ public static final float STACK_WEIGHT_MIN = 0.2f; - /** Maximum value for createStack and resizeStack weight value */ + /** Maximum value for attachStack and resizeStack weight value */ public static final float STACK_WEIGHT_MAX = 0.8f; static final int UPDATE_FOCUS_NORMAL = 0; @@ -293,8 +293,6 @@ public class WindowManagerService extends IWindowManager.Stub final private KeyguardDisableHandler mKeyguardDisableHandler; - private final boolean mHeadless; - final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -369,6 +367,11 @@ public class WindowManagerService extends IWindowManager.Stub final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>(); /** + * Stacks whose animations have ended and whose tasks, apps, selves may now be removed. + */ + final ArraySet<TaskStack> mPendingStacksRemove = new ArraySet<TaskStack>(); + + /** * Used when processing mPendingRemove to avoid working on the original array. */ WindowState[] mPendingRemoveTmp = new WindowState[20]; @@ -534,14 +537,15 @@ public class WindowManagerService extends IWindowManager.Stub AppWindowToken mFocusedApp = null; - PowerManagerService mPowerManager; + PowerManager mPowerManager; + PowerManagerInternal mPowerManagerInternal; float mWindowAnimationScale = 1.0f; float mTransitionAnimationScale = 1.0f; float mAnimatorDurationScale = 1.0f; final InputManagerService mInputManager; - final DisplayManagerService mDisplayManagerService; + final DisplayManagerInternal mDisplayManagerInternal; final DisplayManager mDisplayManager; // Who is holding the screen on. @@ -600,6 +604,9 @@ public class WindowManagerService extends IWindowManager.Stub final WindowAnimator mAnimator; SparseArray<Task> mTaskIdToTask = new SparseArray<Task>(); + + /** All of the TaskStacks in the window manager, unordered. For an ordered list call + * DisplayContent.getStacks(). */ SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>(); private final PointerEventDispatcher mPointerEventDispatcher; @@ -694,23 +701,22 @@ public class WindowManagerService extends IWindowManager.Stub final boolean mOnlyCore; public static WindowManagerService main(final Context context, - final PowerManagerService pm, final DisplayManagerService dm, - final InputManagerService im, final Handler wmHandler, + final InputManagerService im, final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore) { final WindowManagerService[] holder = new WindowManagerService[1]; - wmHandler.runWithScissors(new Runnable() { + DisplayThread.getHandler().runWithScissors(new Runnable() { @Override public void run() { - holder[0] = new WindowManagerService(context, pm, dm, im, + holder[0] = new WindowManagerService(context, im, haveInputMethods, showBootMsgs, onlyCore); } }, 0); return holder[0]; } - private void initPolicy(Handler uiHandler) { - uiHandler.runWithScissors(new Runnable() { + private void initPolicy() { + UiThread.getHandler().runWithScissors(new Runnable() { @Override public void run() { WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); @@ -723,8 +729,7 @@ public class WindowManagerService extends IWindowManager.Stub }, 0); } - private WindowManagerService(Context context, PowerManagerService pm, - DisplayManagerService displayManager, InputManagerService inputManager, + private WindowManagerService(Context context, InputManagerService inputManager, boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) { mContext = context; mHaveInputMethods = haveInputMethods; @@ -733,8 +738,7 @@ public class WindowManagerService extends IWindowManager.Stub mLimitedAlphaCompositing = context.getResources().getBoolean( com.android.internal.R.bool.config_sf_limitedAlpha); mInputManager = inputManager; // Must be before createDisplayContentLocked. - mDisplayManagerService = displayManager; - mHeadless = displayManager.isHeadless(); + mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); mDisplaySettings = new DisplaySettings(context); mDisplaySettings.readSettingsLocked(); @@ -742,7 +746,6 @@ public class WindowManagerService extends IWindowManager.Stub mFxSession = new SurfaceSession(); mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); - mDisplayManager.registerDisplayListener(this, null); Display[] displays = mDisplayManager.getDisplays(); for (Display display : displays) { createDisplayContentLocked(display); @@ -750,10 +753,11 @@ public class WindowManagerService extends IWindowManager.Stub mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy); - mPowerManager = pm; - mPowerManager.setPolicy(mPolicy); - PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE); - mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); + mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); + mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); + mPowerManagerInternal.setPolicy(mPolicy); // TODO: register as local service instead + mScreenFrozenLock = mPowerManager.newWakeLock( + PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); mScreenFrozenLock.setReferenceCounted(false); mAppTransition = new AppTransition(context, mH); @@ -783,13 +787,13 @@ public class WindowManagerService extends IWindowManager.Stub filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); mContext.registerReceiver(mBroadcastReceiver, filter); - mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK - | PowerManager.ON_AFTER_RELEASE, TAG); + mHoldingScreenWakeLock = mPowerManager.newWakeLock( + PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG); mHoldingScreenWakeLock.setReferenceCounted(false); mAnimator = new WindowAnimator(this); - initPolicy(UiThread.getHandler()); + initPolicy(); // Add ourself to the Watchdog monitors. Watchdog.getInstance().addMonitor(this); @@ -802,6 +806,8 @@ public class WindowManagerService extends IWindowManager.Stub } finally { SurfaceControl.closeTransaction(); } + + LocalServices.addService(WindowManagerInternal.class, new LocalService()); } public InputMonitor getInputMonitor() { @@ -871,7 +877,7 @@ public class WindowManagerService extends IWindowManager.Stub final int count = token.windows.size(); for (int i = 0; i < count; i++) { final WindowState win = token.windows.get(i); - if (win.mDisplayContent == displayContent) { + if (win.getDisplayContent() == displayContent) { windowList.add(win); } } @@ -902,7 +908,7 @@ public class WindowManagerService extends IWindowManager.Stub private int addAppWindowToListLocked(final WindowState win) { final IWindow client = win.mClient; final WindowToken token = win.mToken; - final DisplayContent displayContent = win.mDisplayContent; + final DisplayContent displayContent = win.getDisplayContent(); final WindowList windows = win.getWindowList(); final int N = windows.size(); @@ -1079,7 +1085,7 @@ public class WindowManagerService extends IWindowManager.Stub private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) { final WindowToken token = win.mToken; - final DisplayContent displayContent = win.mDisplayContent; + final DisplayContent displayContent = win.getDisplayContent(); final WindowState attached = win.mAttachedWindow; WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); @@ -2013,7 +2019,10 @@ public class WindowManagerService extends IWindowManager.Stub } void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) { - final DisplayContent displayContent = changingTarget.mDisplayContent; + final DisplayContent displayContent = changingTarget.getDisplayContent(); + if (displayContent == null) { + return; + } final DisplayInfo displayInfo = displayContent.getDisplayInfo(); final int dw = displayInfo.logicalWidth; final int dh = displayInfo.logicalHeight; @@ -2073,7 +2082,10 @@ public class WindowManagerService extends IWindowManager.Stub void updateWallpaperVisibilityLocked() { final boolean visible = isWallpaperVisible(mWallpaperTarget); - final DisplayContent displayContent = mWallpaperTarget.mDisplayContent; + final DisplayContent displayContent = mWallpaperTarget.getDisplayContent(); + if (displayContent == null) { + return; + } final DisplayInfo displayInfo = displayContent.getDisplayInfo(); final int dw = displayInfo.logicalWidth; final int dh = displayInfo.logicalHeight; @@ -2428,7 +2440,10 @@ public class WindowManagerService extends IWindowManager.Stub //Slog.i(TAG, "*** Running exit animation..."); win.mExiting = true; win.mRemoveOnExit = true; - win.mDisplayContent.layoutNeeded = true; + final DisplayContent displayContent = win.getDisplayContent(); + if (displayContent != null) { + displayContent.layoutNeeded = true; + } updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); performLayoutAndPlaceSurfacesLocked(); @@ -2485,8 +2500,6 @@ public class WindowManagerService extends IWindowManager.Stub mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage()); } - final WindowList windows = win.getWindowList(); - windows.remove(win); mPendingRemove.remove(win); mResizingWindows.remove(win); mWindowsChanged = true; @@ -2542,12 +2555,19 @@ public class WindowManagerService extends IWindowManager.Stub WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; } - if (!mInLayout) { - assignLayersLocked(windows); - win.mDisplayContent.layoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); - if (win.mAppToken != null) { - win.mAppToken.updateReportedVisibilityLocked(); + final WindowList windows = win.getWindowList(); + if (windows != null) { + windows.remove(win); + if (!mInLayout) { + assignLayersLocked(windows); + final DisplayContent displayContent = win.getDisplayContent(); + if (displayContent != null) { + displayContent.layoutNeeded = true; + } + performLayoutAndPlaceSurfacesLocked(); + if (win.mAppToken != null) { + win.mAppToken.updateReportedVisibilityLocked(); + } } } @@ -2622,7 +2642,10 @@ public class WindowManagerService extends IWindowManager.Stub w.mGivenVisibleInsets.scale(w.mGlobalScale); w.mGivenTouchableRegion.scale(w.mGlobalScale); } - w.mDisplayContent.layoutNeeded = true; + final DisplayContent displayContent = w.getDisplayContent(); + if (displayContent != null) { + displayContent.layoutNeeded = true; + } performLayoutAndPlaceSurfacesLocked(); } } @@ -2708,7 +2731,12 @@ public class WindowManagerService extends IWindowManager.Stub mTmpFloats[Matrix.MSKEW_X] = dsdy; mTmpFloats[Matrix.MSCALE_Y] = dtdy; matrix.setValues(mTmpFloats); - final DisplayInfo displayInfo = window.mDisplayContent.getDisplayInfo(); + final DisplayContent displayContent = window.getDisplayContent(); + if (displayContent == null) { + return; + } + + final DisplayInfo displayInfo = window.getDisplayContent().getDisplayInfo(); final RectF dispRect = new RectF(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight); matrix.mapRect(dispRect); @@ -2717,7 +2745,7 @@ public class WindowManagerService extends IWindowManager.Stub window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top, (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE); window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; - window.mDisplayContent.layoutNeeded = true; + displayContent.layoutNeeded = true; performLayoutAndPlaceSurfacesLocked(); } @@ -2998,7 +3026,10 @@ public class WindowManagerService extends IWindowManager.Stub WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; } - win.mDisplayContent.layoutNeeded = true; + final DisplayContent displayContent = win.getDisplayContent(); + if (displayContent != null) { + displayContent.layoutNeeded = true; + } win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0; configChanged = updateOrientationFromAppTokensLocked(false); performLayoutAndPlaceSurfacesLocked(); @@ -3092,7 +3123,10 @@ public class WindowManagerService extends IWindowManager.Stub getDefaultDisplayContentLocked().pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; } - win.mDisplayContent.layoutNeeded = true; + final DisplayContent displayContent = win.getDisplayContent(); + if (displayContent != null) { + displayContent.layoutNeeded = true; + } requestTraversalLocked(); } } @@ -3350,7 +3384,7 @@ public class WindowManagerService extends IWindowManager.Stub for (int i=0; i<N; i++) { WindowState win = wtoken.windows.get(i); - displayContent = win.mDisplayContent; + displayContent = win.getDisplayContent(); if (win.mWinAnimator.isAnimating()) { delayed = true; @@ -3365,7 +3399,9 @@ public class WindowManagerService extends IWindowManager.Stub WindowManagerPolicy.TRANSIT_EXIT); } changed = true; - displayContent.layoutNeeded = true; + if (displayContent != null) { + displayContent.layoutNeeded = true; + } } } @@ -3378,7 +3414,9 @@ public class WindowManagerService extends IWindowManager.Stub } if (delayed) { - displayContent.mExitingTokens.add(wtoken); + if (displayContent != null) { + displayContent.mExitingTokens.add(wtoken); + } } else if (wtoken.windowType == TYPE_WALLPAPER) { mWallpaperTokens.remove(wtoken); } @@ -3393,6 +3431,8 @@ public class WindowManagerService extends IWindowManager.Stub } private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) { + if (DEBUG_STACK) Slog.i(TAG, "createTask: taskId=" + taskId + " stackId=" + stackId + + " atoken=" + atoken); final TaskStack stack = mStackIdToStack.get(stackId); if (stack == null) { throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId); @@ -3446,7 +3486,7 @@ public class WindowManagerService extends IWindowManager.Stub Task task = mTaskIdToTask.get(taskId); if (task == null) { - task = createTask(taskId, stackId, userId, atoken); + createTask(taskId, stackId, userId, atoken); } else { task.addAppToken(addPos, atoken); } @@ -3474,8 +3514,8 @@ public class WindowManagerService extends IWindowManager.Stub Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token); return; } - Task oldTask = mTaskIdToTask.get(atoken.groupId); - oldTask.removeAppToken(atoken); + final Task oldTask = mTaskIdToTask.get(atoken.groupId); + removeAppFromTaskLocked(atoken); atoken.groupId = groupId; Task newTask = mTaskIdToTask.get(groupId); @@ -3626,7 +3666,7 @@ public class WindowManagerService extends IWindowManager.Stub if (freezeThisOneIfNeeded != null) { AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded); if (atoken != null) { - startAppFreezingScreenLocked(atoken, ActivityInfo.CONFIG_ORIENTATION); + startAppFreezingScreenLocked(atoken); } } config = computeNewConfigurationLocked(); @@ -3768,7 +3808,10 @@ public class WindowManagerService extends IWindowManager.Stub if (mFocusedApp != null) { Task task = mTaskIdToTask.get(mFocusedApp.groupId); stack = task.mStack; - task.getDisplayContent().setTouchExcludeRegion(stack); + final DisplayContent displayContent = task.getDisplayContent(); + if (displayContent != null) { + displayContent.setTouchExcludeRegion(stack); + } } else { stack = null; } @@ -3778,10 +3821,8 @@ public class WindowManagerService extends IWindowManager.Stub if (stack == null) { mFocusedStackFrame.setVisibility(false); } else { - final StackBox box = stack.mStackBox; - final Rect bounds = box.mBounds; - final boolean multipleStacks = box.mParent != null; - mFocusedStackFrame.setBounds(bounds); + mFocusedStackFrame.setBounds(stack); + final boolean multipleStacks = !stack.isFullscreen(); mFocusedStackFrame.setVisibility(multipleStacks); } } finally { @@ -3798,27 +3839,23 @@ public class WindowManagerService extends IWindowManager.Stub } synchronized(mWindowMap) { - boolean changed = false; + final AppWindowToken newFocus; if (token == null) { if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp); - changed = mFocusedApp != null; - mFocusedApp = null; - if (changed) { - mInputMonitor.setFocusedAppLw(null); - } + newFocus = null; } else { - AppWindowToken newFocus = findAppWindowToken(token); + newFocus = findAppWindowToken(token); if (newFocus == null) { Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token); - return; } - changed = mFocusedApp != newFocus; if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow); + } + + final boolean changed = mFocusedApp != newFocus; + if (changed) { mFocusedApp = newFocus; - if (changed) { - mInputMonitor.setFocusedAppLw(newFocus); - } + mInputMonitor.setFocusedAppLw(null); } if (moveFocusNow && changed) { @@ -4159,10 +4196,25 @@ public class WindowManagerService extends IWindowManager.Stub AppWindowToken atoken = findAppWindowToken(token); if (atoken != null) { atoken.appFullscreen = toOpaque; + // When making translucent, wait until windows below have been drawn. + if (toOpaque) { + // Making opaque so do it now. + setWindowOpaque(token, true); + } requestTraversal(); } } + public void setWindowOpaque(IBinder token, boolean isOpaque) { + AppWindowToken wtoken = findAppWindowToken(token); + if (wtoken != null) { + WindowState win = wtoken.findMainWindow(); + if (win != null) { + win.mWinAnimator.setOpaque(isOpaque); + } + } + } + boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, boolean visible, int transit, boolean performLayout) { boolean delayed = false; @@ -4219,7 +4271,10 @@ public class WindowManagerService extends IWindowManager.Stub } } changed = true; - win.mDisplayContent.layoutNeeded = true; + final DisplayContent displayContent = win.getDisplayContent(); + if (displayContent != null) { + displayContent.layoutNeeded = true; + } } } else if (win.isVisibleNow()) { if (!runningAppAnimation) { @@ -4233,7 +4288,10 @@ public class WindowManagerService extends IWindowManager.Stub } } changed = true; - win.mDisplayContent.layoutNeeded = true; + final DisplayContent displayContent = win.getDisplayContent(); + if (displayContent != null) { + displayContent.layoutNeeded = true; + } } } @@ -4381,7 +4439,10 @@ public class WindowManagerService extends IWindowManager.Stub } w.mLastFreezeDuration = 0; unfrozeWindows = true; - w.mDisplayContent.layoutNeeded = true; + final DisplayContent displayContent = w.getDisplayContent(); + if (displayContent != null) { + displayContent.layoutNeeded = true; + } } } if (force || unfrozeWindows) { @@ -4401,8 +4462,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - public void startAppFreezingScreenLocked(AppWindowToken wtoken, - int configChanges) { + private void startAppFreezingScreenLocked(AppWindowToken wtoken) { if (DEBUG_ORIENTATION) { RuntimeException e = null; if (!HIDE_STACK_CRAWLS) { @@ -4451,7 +4511,7 @@ public class WindowManagerService extends IWindowManager.Stub return; } final long origId = Binder.clearCallingIdentity(); - startAppFreezingScreenLocked(wtoken, configChanges); + startAppFreezingScreenLocked(wtoken); Binder.restoreCallingIdentity(origId); } } @@ -4476,6 +4536,15 @@ public class WindowManagerService extends IWindowManager.Stub } } + void removeAppFromTaskLocked(AppWindowToken wtoken) { + final Task task = mTaskIdToTask.get(wtoken.groupId); + if (task != null) { + if (!task.removeAppToken(wtoken)) { + Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found."); + } + } + } + @Override public void removeAppToken(IBinder token) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, @@ -4508,26 +4577,24 @@ public class WindowManagerService extends IWindowManager.Stub TAG, "Removing app " + wtoken + " delayed=" + delayed + " animation=" + wtoken.mAppAnimator.animation + " animating=" + wtoken.mAppAnimator.animating); - final Task task = mTaskIdToTask.get(wtoken.groupId); - DisplayContent displayContent = task.getDisplayContent(); + if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: " + + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4)); + final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack; if (delayed) { // set the token aside because it has an active animation to be finished if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken make exiting: " + wtoken); - displayContent.mExitingAppTokens.add(wtoken); + stack.mExitingAppTokens.add(wtoken); + wtoken.mDeferRemoval = true; } else { // Make sure there is no animation running on this token, // so any windows associated with it will be removed as // soon as their animations are complete wtoken.mAppAnimator.clearAnimation(); wtoken.mAppAnimator.animating = false; + removeAppFromTaskLocked(wtoken); } - if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, - "removeAppToken: " + wtoken); - if (task.removeAppToken(wtoken)) { - mTaskIdToTask.delete(wtoken.groupId); - } wtoken.removed = true; if (wtoken.startingData != null) { startingToken = wtoken; @@ -4572,13 +4639,15 @@ public class WindowManagerService extends IWindowManager.Stub mH.sendMessage(m); } } + private boolean tmpRemoveAppWindowsLocked(WindowToken token) { - final int NW = token.windows.size(); + WindowList windows = token.windows; + final int NW = windows.size(); if (NW > 0) { mWindowsChanged = true; } - for (int i=0; i<NW; i++) { - WindowState win = token.windows.get(i); + for (int i = 0; i < NW; i++) { + WindowState win = windows.get(i); if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win); win.getWindowList().remove(win); int j = win.mChildWindows.size(); @@ -4594,29 +4663,32 @@ public class WindowManagerService extends IWindowManager.Stub } void dumpAppTokensLocked() { - final int numDisplays = mDisplayContents.size(); - for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); - Slog.v(TAG, " Display " + displayContent.getDisplayId()); - final ArrayList<Task> tasks = displayContent.getTasks(); - int i = displayContent.numTokens(); - for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { - AppTokenList tokens = tasks.get(taskNdx).mAppTokens; - for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { - final AppWindowToken wtoken = tokens.get(tokenNdx); - Slog.v(TAG, " #" + --i + ": " + wtoken.token); + final int numStacks = mStackIdToStack.size(); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + final TaskStack stack = mStackIdToStack.valueAt(stackNdx); + Slog.v(TAG, " Stack #" + stack.mStackId + " tasks from bottom to top:"); + final ArrayList<Task> tasks = stack.getTasks(); + final int numTasks = tasks.size(); + for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { + final Task task = tasks.get(taskNdx); + Slog.v(TAG, " Task #" + task.taskId + " activities from bottom to top:"); + AppTokenList tokens = task.mAppTokens; + final int numTokens = tokens.size(); + for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { + Slog.v(TAG, " activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token); } } } } void dumpWindowsLocked() { - int i = 0; final int numDisplays = mDisplayContents.size(); for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); + final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); + Slog.v(TAG, " Display #" + displayContent.getDisplayId()); + final WindowList windows = displayContent.getWindowList(); for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { - Slog.v(TAG, " #" + i++ + ": " + windows.get(winNdx)); + Slog.v(TAG, " #" + winNdx + ": " + windows.get(winNdx)); } } } @@ -4728,23 +4800,28 @@ public class WindowManagerService extends IWindowManager.Stub final int NW = token.windows.size(); for (int i=0; i<NW; i++) { final WindowState win = token.windows.get(i); - if (win.mDisplayContent == displayContent) { + final DisplayContent winDisplayContent = win.getDisplayContent(); + if (winDisplayContent == displayContent || winDisplayContent == null) { + win.mDisplayContent = displayContent; index = reAddWindowLocked(index, win); } } return index; } + void tmpRemoveTaskWindowsLocked(Task task) { + AppTokenList tokens = task.mAppTokens; + for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { + tmpRemoveAppWindowsLocked(tokens.get(tokenNdx)); + } + } + void moveStackWindowsLocked(DisplayContent displayContent) { // First remove all of the windows from the list. final ArrayList<Task> tasks = displayContent.getTasks(); final int numTasks = tasks.size(); for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { - AppTokenList tokens = tasks.get(taskNdx).mAppTokens; - final int numTokens = tokens.size(); - for (int tokenNdx = numTokens - 1; tokenNdx >= 0; --tokenNdx) { - tmpRemoveAppWindowsLocked(tokens.get(tokenNdx)); - } + tmpRemoveTaskWindowsLocked(tasks.get(taskNdx)); } // And now add them back at the correct place. @@ -4788,10 +4865,14 @@ public class WindowManagerService extends IWindowManager.Stub } final TaskStack stack = task.mStack; final DisplayContent displayContent = task.getDisplayContent(); - final boolean isHomeStackTask = stack.isHomeStack(); - if (isHomeStackTask != displayContent.homeOnTop()) { - // First move the stack itself. - displayContent.moveHomeStackBox(isHomeStackTask); + displayContent.moveStack(stack, true); + if (displayContent.isDefaultDisplay) { + final TaskStack homeStack = displayContent.getHomeStack(); + if (homeStack != stack) { + // When a non-home stack moves to the top, the home stack moves to the + // bottom. + displayContent.moveStack(homeStack, false); + } } stack.moveTaskToTop(task); } @@ -4820,54 +4901,66 @@ public class WindowManagerService extends IWindowManager.Stub } /** - * Create a new TaskStack and place it next to an existing stack. + * Create a new TaskStack and place it on a DisplayContent. * @param stackId The unique identifier of the new stack. - * @param relativeStackBoxId The existing stack that this stack goes before or after. - * @param position One of: - * {@link StackBox#TASK_STACK_GOES_BEFORE} - * {@link StackBox#TASK_STACK_GOES_AFTER} - * {@link StackBox#TASK_STACK_GOES_ABOVE} - * {@link StackBox#TASK_STACK_GOES_BELOW} - * {@link StackBox#TASK_STACK_GOES_UNDER} - * {@link StackBox#TASK_STACK_GOES_OVER} - * @param weight Relative weight for determining how big to make the new TaskStack. + * @param displayId The unique identifier of the DisplayContent. */ - public void createStack(int stackId, int relativeStackBoxId, int position, float weight) { - synchronized (mWindowMap) { - if (position <= StackBox.TASK_STACK_GOES_BELOW && - (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX)) { - throw new IllegalArgumentException( - "createStack: weight must be between " + STACK_WEIGHT_MIN + " and " + - STACK_WEIGHT_MAX + ", weight=" + weight); - } - final int numDisplays = mDisplayContents.size(); - for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); - TaskStack stack = displayContent.createStack(stackId, relativeStackBoxId, position, - weight); - if (stack != null) { - mStackIdToStack.put(stackId, stack); - performLayoutAndPlaceSurfacesLocked(); - return; + public void attachStack(int stackId, int displayId) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mWindowMap) { + final DisplayContent displayContent = mDisplayContents.get(displayId); + if (displayContent != null) { + TaskStack stack = mStackIdToStack.get(stackId); + if (stack == null) { + if (DEBUG_STACK) Slog.d(TAG, "attachStack: stackId=" + stackId); + stack = new TaskStack(this, stackId); + mStackIdToStack.put(stackId, stack); + } + stack.attachDisplayContent(displayContent); + displayContent.attachStack(stack); + moveStackWindowsLocked(displayContent); + final WindowList windows = displayContent.getWindowList(); + for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { + windows.get(winNdx).reportResized(); + } } } - Slog.e(TAG, "createStack: Unable to find relativeStackBoxId=" + relativeStackBoxId); + } finally { + Binder.restoreCallingIdentity(origId); } } - public int removeStack(int stackId) { + public void detachStack(int stackId) { synchronized (mWindowMap) { - final TaskStack stack = mStackIdToStack.get(stackId); + TaskStack stack = mStackIdToStack.get(stackId); if (stack != null) { - mStackIdToStack.delete(stackId); - int nextStackId = stack.remove(); - stack.getDisplayContent().layoutNeeded = true; - requestTraversalLocked(); - return nextStackId; + final DisplayContent displayContent = stack.getDisplayContent(); + if (displayContent != null) { + if (stack.isAnimating()) { + displayContent.mDeferredActions |= DisplayContent.DEFER_DETACH; + return; + } + displayContent.detachStack(stack); + stack.detachDisplay(); + } } - if (DEBUG_STACK) Slog.i(TAG, "removeStack: could not find stackId=" + stackId); } - return HOME_STACK_ID; + } + + void removeTaskLocked(Task task) { + final int taskId = task.taskId; + final TaskStack stack = task.mStack; + if (stack.isAnimating()) { + if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId); + task.mDeferRemoval = true; + return; + } + if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId); + EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask"); + task.mDeferRemoval = false; + task.mStack.removeTask(task); + mTaskIdToTask.delete(task.taskId); } public void removeTask(int taskId) { @@ -4877,15 +4970,14 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId); return; } - final TaskStack stack = task.mStack; - EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask"); - stack.removeTask(task); - stack.getDisplayContent().layoutNeeded = true; + removeTaskLocked(task); } } public void addTask(int taskId, int stackId, boolean toTop) { synchronized (mWindowMap) { + if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId + + " to " + (toTop ? "top" : "bottom")); Task task = mTaskIdToTask.get(taskId); if (task == null) { return; @@ -4898,40 +4990,28 @@ public class WindowManagerService extends IWindowManager.Stub } } - public void resizeStackBox(int stackBoxId, float weight) { - if (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX) { - throw new IllegalArgumentException( - "resizeStack: weight must be between " + STACK_WEIGHT_MIN + " and " + - STACK_WEIGHT_MAX + ", weight=" + weight); - } + public void resizeStack(int stackId, Rect bounds) { synchronized (mWindowMap) { - final int numDisplays = mDisplayContents.size(); - for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - if (mDisplayContents.valueAt(displayNdx).resizeStack(stackBoxId, weight)) { - performLayoutAndPlaceSurfacesLocked(); - return; - } + final TaskStack stack = mStackIdToStack.get(stackId); + if (stack == null) { + throw new IllegalArgumentException("resizeStack: stackId " + stackId + + " not found."); + } + if (stack.setBounds(bounds)) { + stack.resizeWindows(); + stack.getDisplayContent().layoutNeeded = true; + performLayoutAndPlaceSurfacesLocked(); } - } - throw new IllegalArgumentException("resizeStack: stackBoxId " + stackBoxId - + " not found."); - } - - public ArrayList<StackBoxInfo> getStackBoxInfos() { - synchronized(mWindowMap) { - return getDefaultDisplayContentLocked().getStackBoxInfos(); } } - public Rect getStackBounds(int stackId) { - final int numDisplays = mDisplayContents.size(); - for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - Rect bounds = mDisplayContents.valueAt(displayNdx).getStackBounds(stackId); - if (bounds != null) { - return bounds; - } + public void getStackBounds(int stackId, Rect bounds) { + final TaskStack stack = mStackIdToStack.get(stackId); + if (stack != null) { + stack.getBounds(bounds); + return; } - return null; + bounds.setEmpty(); } // ------------------------------------------------------------- @@ -5207,7 +5287,7 @@ public class WindowManagerService extends IWindowManager.Stub final int numDisplays = mDisplayContents.size(); for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); - displayContent.switchUserStacks(oldUserId, newUserId); + displayContent.switchUserStacks(newUserId); rebuildAppWindowListLocked(displayContent); } performLayoutAndPlaceSurfacesLocked(); @@ -5259,7 +5339,7 @@ public class WindowManagerService extends IWindowManager.Stub public void performBootTimeout() { synchronized(mWindowMap) { - if (mDisplayEnabled || mHeadless) { + if (mDisplayEnabled) { return; } Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled"); @@ -5443,7 +5523,6 @@ public class WindowManagerService extends IWindowManager.Stub // only allow disables from pids which have count on, etc. @Override public void showStrictModeViolation(boolean on) { - if (mHeadless) return; int pid = Binder.getCallingPid(); mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid)); } @@ -5589,7 +5668,7 @@ public class WindowManagerService extends IWindowManager.Stub continue; } appWin = ws; - stackBounds.set(ws.getStackBounds()); + ws.getStackBounds(stackBounds); } } @@ -5964,7 +6043,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - mDisplayManagerService.performTraversalInTransactionFromWindowManager(); + mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); } finally { if (!inTransaction) { SurfaceControl.closeTransaction(); @@ -6658,7 +6737,7 @@ public class WindowManagerService extends IWindowManager.Stub displayInfo.getLogicalMetrics(mRealDisplayMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); displayInfo.getAppMetrics(mDisplayMetrics); - mDisplayManagerService.setDisplayInfoOverrideFromWindowManager( + mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( displayContent.getDisplayId(), displayInfo); } if (false) { @@ -6991,7 +7070,7 @@ public class WindowManagerService extends IWindowManager.Stub synchronized(displayContent.mDisplaySizeLock) { // Bootstrap the default logical display from the display manager. final DisplayInfo displayInfo = displayContent.getDisplayInfo(); - DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId); + DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId); if (newDisplayInfo != null) { displayInfo.copyFrom(newDisplayInfo); } @@ -7361,15 +7440,18 @@ public class WindowManagerService extends IWindowManager.Stub case APP_FREEZE_TIMEOUT: { synchronized (mWindowMap) { Slog.w(TAG, "App freeze timeout expired."); - DisplayContent displayContent = getDefaultDisplayContentLocked(); - final ArrayList<Task> tasks = displayContent.getTasks(); - for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { - AppTokenList tokens = tasks.get(taskNdx).mAppTokens; - for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { - AppWindowToken tok = tokens.get(tokenNdx); - if (tok.mAppAnimator.freezingScreen) { - Slog.w(TAG, "Force clearing freeze: " + tok); - unsetAppFreezingScreenLocked(tok, true, true); + final int numStacks = mStackIdToStack.size(); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + final TaskStack stack = mStackIdToStack.valueAt(stackNdx); + final ArrayList<Task> tasks = stack.getTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { + AppTokenList tokens = tasks.get(taskNdx).mAppTokens; + for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { + AppWindowToken tok = tokens.get(tokenNdx); + if (tok.mAppAnimator.freezingScreen) { + Slog.w(TAG, "Force clearing freeze: " + tok); + unsetAppFreezingScreenLocked(tok, true, true); + } } } } @@ -7476,9 +7558,7 @@ public class WindowManagerService extends IWindowManager.Stub } case DO_DISPLAY_ADDED: - synchronized (mWindowMap) { - handleDisplayAddedLocked(msg.arg1); - } + handleDisplayAdded(msg.arg1); break; case DO_DISPLAY_REMOVED: @@ -7937,7 +8017,6 @@ public class WindowManagerService extends IWindowManager.Stub } final void rebuildAppWindowListLocked() { - // TODO: Multidisplay, when ActivityStacks and tasks exist on more than one display. rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); } @@ -7982,27 +8061,37 @@ public class WindowManagerService extends IWindowManager.Stub // in the main app list, but still have windows shown. We put them // in the back because now that the animation is over we no longer // will care about them. - AppTokenList exitingAppTokens = displayContent.mExitingAppTokens; - int NT = exitingAppTokens.size(); - for (int j=0; j<NT; j++) { - i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); + final ArrayList<TaskStack> stacks = displayContent.getStacks(); + final int numStacks = stacks.size(); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; + int NT = exitingAppTokens.size(); + for (int j = 0; j < NT; j++) { + i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); + } } // And add in the still active app tokens in Z order. - final ArrayList<Task> tasks = displayContent.getTasks(); - final int numTasks = tasks.size(); - for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { - final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; - final int numTokens = tokens.size(); - for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { - final AppWindowToken wtoken = tokens.get(tokenNdx); - i = reAddAppWindowsLocked(displayContent, i, wtoken); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); + final int numTasks = tasks.size(); + for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { + final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; + final int numTokens = tokens.size(); + for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { + final AppWindowToken wtoken = tokens.get(tokenNdx); + if (wtoken.mDeferRemoval) { + continue; + } + i = reAddAppWindowsLocked(displayContent, i, wtoken); + } } } i -= lastBelow; if (i != numRemoved) { - Slog.w(TAG, "Rebuild removed " + numRemoved + " windows but added " + i, + Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + + numRemoved + " windows but added " + i, new RuntimeException("here").fillInStackTrace()); for (i=0; i<numRemoved; i++) { WindowState ws = mRebuildTmp[i]; @@ -8218,7 +8307,7 @@ public class WindowManagerService extends IWindowManager.Stub } mPolicy.getContentRectLw(mTmpContentRect); - displayContent.setStackBoxSize(mTmpContentRect); + displayContent.resize(mTmpContentRect); int seq = mLayoutSeq+1; if (seq < 0) seq = 0; @@ -8362,8 +8451,7 @@ public class WindowManagerService extends IWindowManager.Stub // it frozen/off until this window draws at its new // orientation. if (!okToDisplay()) { - if (DEBUG_ORIENTATION) Slog.v(TAG, - "Changing surface while display frozen: " + w); + if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w); w.mOrientationChanging = true; w.mLastFreezeDuration = 0; mInnerFields.mOrientationChangeComplete = false; @@ -8671,15 +8759,14 @@ public class WindowManagerService extends IWindowManager.Stub mAppTransition.setIdle(); // Restore window app tokens to the ActivityManager views - final DisplayContent displayContent = getDefaultDisplayContentLocked(); - final ArrayList<Task> tasks = displayContent.getTasks(); - final int numTasks = tasks.size(); - for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { - final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; - final int numTokens = tokens.size(); - for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { - final AppWindowToken wtoken = tokens.get(tokenNdx); - wtoken.sendingToBottom = false; + ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { + final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; + for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { + tokens.get(tokenNdx).sendingToBottom = false; + } } } rebuildAppWindowListLocked(); @@ -8813,7 +8900,8 @@ public class WindowManagerService extends IWindowManager.Stub if (canBeSeen) { // This function assumes that the contents of the default display are // processed first before secondary displays. - if (w.mDisplayContent.isDefaultDisplay) { + final DisplayContent displayContent = w.getDisplayContent(); + if (displayContent != null && displayContent.isDefaultDisplay) { // While a dream or keyguard is showing, obscure ordinary application // content on secondary displays (by forcibly enabling mirroring unless // there is other content we want to show) but still allow opaque @@ -8822,8 +8910,9 @@ public class WindowManagerService extends IWindowManager.Stub mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true; } mInnerFields.mDisplayHasContent = true; - } else if (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays - || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG)) { + } else if (displayContent != null && + (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays + || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) { // Allow full screen keyguard presentation dialogs to be seen. mInnerFields.mDisplayHasContent = true; } @@ -8831,7 +8920,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - private void handleFlagDimBehind(WindowState w, int innerDw, int innerDh) { + private void handleFlagDimBehind(WindowState w) { final WindowManager.LayoutParams attrs = w.mAttrs; if ((attrs.flags & FLAG_DIM_BEHIND) != 0 && w.isDisplayedLw() @@ -8849,22 +8938,23 @@ public class WindowManagerService extends IWindowManager.Stub private void updateAllDrawnLocked(DisplayContent displayContent) { // See if any windows have been drawn, so they (and others // associated with them) can now be shown. - final ArrayList<Task> tasks = displayContent.getTasks(); - final int numTasks = tasks.size(); - for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { - final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; - final int numTokens = tokens.size(); - for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { - final AppWindowToken wtoken = tokens.get(tokenNdx); - if (!wtoken.allDrawn) { - int numInteresting = wtoken.numInterestingWindows; - if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { - if (DEBUG_VISIBILITY) Slog.v(TAG, - "allDrawn: " + wtoken - + " interesting=" + numInteresting - + " drawn=" + wtoken.numDrawnWindows); - wtoken.allDrawn = true; - mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); + ArrayList<TaskStack> stacks = displayContent.getStacks(); + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { + final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; + for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { + final AppWindowToken wtoken = tokens.get(tokenNdx); + if (!wtoken.allDrawn) { + int numInteresting = wtoken.numInterestingWindows; + if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { + if (DEBUG_VISIBILITY) Slog.v(TAG, + "allDrawn: " + wtoken + + " interesting=" + numInteresting + + " drawn=" + wtoken.numDrawnWindows); + wtoken.allDrawn = true; + mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); + } } } } @@ -8895,10 +8985,14 @@ public class WindowManagerService extends IWindowManager.Stub for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { displayContent.mExitingTokens.get(i).hasVisible = false; } + } + for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { // Initialize state of exiting applications. - for (i=displayContent.mExitingAppTokens.size()-1; i>=0; i--) { - displayContent.mExitingAppTokens.get(i).hasVisible = false; + final AppTokenList exitingAppTokens = + mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; + for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { + exitingAppTokens.get(tokenNdx).hasVisible = false; } } @@ -9017,6 +9111,10 @@ public class WindowManagerService extends IWindowManager.Stub final int N = windows.size(); for (i=N-1; i>=0; i--) { WindowState w = windows.get(i); + final TaskStack stack = w.getStack(); + if (stack == null) { + continue; + } final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; @@ -9026,8 +9124,8 @@ public class WindowManagerService extends IWindowManager.Stub handleNotObscuredLocked(w, currentTime, innerDw, innerDh); } - if (!w.getStack().testDimmingTag()) { - handleFlagDimBehind(w, innerDw, innerDh); + if (!stack.testDimmingTag()) { + handleFlagDimBehind(w); } if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) @@ -9151,7 +9249,7 @@ public class WindowManagerService extends IWindowManager.Stub updateResizingWindows(w); } - mDisplayManagerService.setDisplayHasContent(displayId, + mDisplayManagerInternal.setDisplayHasContent(displayId, mInnerFields.mDisplayHasContent, true /* inTraversal, must call performTraversalInTrans... below */); @@ -9168,7 +9266,7 @@ public class WindowManagerService extends IWindowManager.Stub // Give the display manager a chance to adjust properties // like display rotation if it needs to. - mDisplayManagerService.performTraversalInTransactionFromWindowManager(); + mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); } catch (RuntimeException e) { Log.wtf(TAG, "Unhandled exception in Window Manager", e); @@ -9243,57 +9341,7 @@ public class WindowManagerService extends IWindowManager.Stub // Don't remove this window until rotation has completed. continue; } - final WindowStateAnimator winAnimator = win.mWinAnimator; - try { - if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, - "Reporting new frame to " + win + ": " + win.mCompatFrame); - int diff = 0; - boolean configChanged = win.isConfigChanged(); - if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) - && configChanged) { - Slog.i(TAG, "Sending new config to window " + win + ": " - + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH - + " / " + mCurConfiguration + " / 0x" - + Integer.toHexString(diff)); - } - win.setConfiguration(mCurConfiguration); - if (DEBUG_ORIENTATION && - winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i( - TAG, "Resizing " + win + " WITH DRAW PENDING"); - final IWindow client = win.mClient; - final Rect frame = win.mFrame; - final Rect overscanInsets = win.mLastOverscanInsets; - final Rect contentInsets = win.mLastContentInsets; - final Rect visibleInsets = win.mLastVisibleInsets; - final boolean reportDraw - = winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING; - final Configuration newConfig = configChanged ? win.mConfiguration : null; - if (win.mClient instanceof IWindow.Stub) { - // To prevent deadlock simulate one-way call if win.mClient is a local object. - mH.post(new Runnable() { - @Override - public void run() { - try { - client.resized(frame, overscanInsets, contentInsets, - visibleInsets, reportDraw, newConfig); - } catch (RemoteException e) { - // Not a remote call, RemoteException won't be raised. - } - } - }); - } else { - client.resized(frame, overscanInsets, contentInsets, visibleInsets, reportDraw, - newConfig); - } - win.mOverscanInsetsChanged = false; - win.mContentInsetsChanged = false; - win.mVisibleInsetsChanged = false; - winAnimator.mSurfaceResized = false; - } catch (RemoteException e) { - win.mOrientationChanging = false; - win.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() - - mDisplayFreezeTime); - } + win.reportResized(); mResizingWindows.remove(i); } @@ -9341,9 +9389,13 @@ public class WindowManagerService extends IWindowManager.Stub } } } + } - // Time to remove any exiting applications? - AppTokenList exitingAppTokens = displayContent.mExitingAppTokens; + // Time to remove any exiting applications? + for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { + // Initialize state of exiting applications. + final AppTokenList exitingAppTokens = + mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; for (i = exitingAppTokens.size() - 1; i >= 0; i--) { AppWindowToken token = exitingAppTokens.get(i); if (!token.hasVisible && !mClosingApps.contains(token)) { @@ -9354,10 +9406,7 @@ public class WindowManagerService extends IWindowManager.Stub token.mAppAnimator.animating = false; if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "performLayout: App token exiting now removed" + token); - final Task task = mTaskIdToTask.get(token.groupId); - if (task != null && task.removeAppToken(token)) { - mTaskIdToTask.delete(token.groupId); - } + removeAppFromTaskLocked(token); exitingAppTokens.remove(i); } } @@ -9392,18 +9441,18 @@ public class WindowManagerService extends IWindowManager.Stub setHoldScreenLocked(mInnerFields.mHoldScreen); if (!mDisplayFrozen) { if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { - mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1); + mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); } else { - mPowerManager.setScreenBrightnessOverrideFromWindowManager( + mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( toBrightnessOverride(mInnerFields.mScreenBrightness)); } if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { - mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1); + mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); } else { - mPowerManager.setButtonBrightnessOverrideFromWindowManager( + mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( toBrightnessOverride(mInnerFields.mButtonBrightness)); } - mPowerManager.setUserActivityTimeoutOverrideFromWindowManager( + mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( mInnerFields.mUserActivityTimeout); } @@ -9438,8 +9487,9 @@ public class WindowManagerService extends IWindowManager.Stub for (i = 0; i < N; i++) { WindowState w = mPendingRemoveTmp[i]; removeWindowInnerLocked(w.mSession, w); - if (!displayList.contains(w.mDisplayContent)) { - displayList.add(w.mDisplayContent); + final DisplayContent displayContent = w.getDisplayContent(); + if (displayContent != null && !displayList.contains(displayContent)) { + displayList.add(displayContent); } } @@ -9449,6 +9499,11 @@ public class WindowManagerService extends IWindowManager.Stub } } + // Remove all deferred Stacks, tasks, and activities. + for (int stackNdx = mPendingStacksRemove.size() - 1; stackNdx >= 0; --stackNdx) { + mPendingStacksRemove.removeAt(stackNdx).checkForDeferredActions(); + } + setFocusedStackFrame(); // Check to see if we are now in a state where the screen should @@ -9537,8 +9592,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - @Override - public void requestTraversal() { + void requestTraversal() { synchronized (mWindowMap) { requestTraversalLocked(); } @@ -9916,6 +9970,7 @@ public class WindowManagerService extends IWindowManager.Stub } // TODO(multidisplay): rotation on main screen only. + displayContent.updateDisplayInfo(); screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, mFxSession, inTransaction, mPolicy.isDefaultOrientationForced()); mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); @@ -10735,7 +10790,7 @@ public class WindowManagerService extends IWindowManager.Stub displayInfo.overscanTop = rect.top; displayInfo.overscanRight = rect.right; displayInfo.overscanBottom = rect.bottom; - mDisplayManagerService.setDisplayInfoOverrideFromWindowManager( + mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( displayId, displayInfo); } configureDisplayPolicyLocked(displayContent); @@ -10805,20 +10860,20 @@ public class WindowManagerService extends IWindowManager.Stub return displayContent != null ? displayContent.getWindowList() : null; } - @Override public void onDisplayAdded(int displayId) { mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); } - private void handleDisplayAddedLocked(int displayId) { - final Display display = mDisplayManager.getDisplay(displayId); - if (display != null) { - createDisplayContentLocked(display); - displayReady(displayId); + public void handleDisplayAdded(int displayId) { + synchronized (mWindowMap) { + final Display display = mDisplayManager.getDisplay(displayId); + if (display != null) { + createDisplayContentLocked(display); + displayReady(displayId); + } } } - @Override public void onDisplayRemoved(int displayId) { mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); } @@ -10826,21 +10881,19 @@ public class WindowManagerService extends IWindowManager.Stub private void handleDisplayRemovedLocked(int displayId) { final DisplayContent displayContent = getDisplayContentLocked(displayId); if (displayContent != null) { + if ((displayContent.mDeferredActions & DisplayContent.DEFER_DETACH) != 0) { + displayContent.mDeferredActions |= DisplayContent.DEFER_REMOVAL; + return; + } mDisplayContents.delete(displayId); displayContent.close(); if (displayId == Display.DEFAULT_DISPLAY) { unregisterPointerEventListener(displayContent.mTapDetector); } - WindowList windows = displayContent.getWindowList(); - while (!windows.isEmpty()) { - final WindowState win = windows.get(windows.size() - 1); - removeWindowLocked(win.mSession, win); - } } mAnimator.removeDisplayLocked(displayId); } - @Override public void onDisplayChanged(int displayId) { mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); } @@ -10856,4 +10909,11 @@ public class WindowManagerService extends IWindowManager.Stub public Object getWindowManagerLock() { return mWindowMap; } + + private final class LocalService extends WindowManagerInternal { + @Override + public void requestTraversalFromDisplayManager() { + requestTraversal(); + } + } } diff --git a/services/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 4d53cea4370d..9f3415e63586 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -16,8 +16,11 @@ package com.android.server.wm; -import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY; +import static com.android.server.wm.WindowManagerService.DEBUG_CONFIGURATION; import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT; +import static com.android.server.wm.WindowManagerService.DEBUG_ORIENTATION; +import static com.android.server.wm.WindowManagerService.DEBUG_RESIZE; +import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; @@ -29,7 +32,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import android.app.AppOpsManager; +import android.os.Debug; import android.os.RemoteCallbackList; +import android.os.SystemClock; import android.util.TimeUtils; import android.view.IWindowFocusObserver; import android.view.IWindowId; @@ -370,19 +375,17 @@ final class WindowState implements WindowManagerPolicy.WindowState { mAttachedWindow.mChildWindows.add(this); } else { for (int i = 0; i < children_size; i++) { - WindowState child = (WindowState)mAttachedWindow.mChildWindows.get(i); - if (this.mSubLayer < child.mSubLayer) { + WindowState child = mAttachedWindow.mChildWindows.get(i); + if (mSubLayer < child.mSubLayer) { mAttachedWindow.mChildWindows.add(i, this); break; - } else if (this.mSubLayer > child.mSubLayer) { + } else if (mSubLayer > child.mSubLayer) { continue; } - if (this.mBaseLayer <= child.mBaseLayer) { + if (mBaseLayer <= child.mBaseLayer) { mAttachedWindow.mChildWindows.add(i, this); break; - } else { - continue; } } if (children_size == mAttachedWindow.mChildWindows.size()) { @@ -463,8 +466,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { mHaveFrame = true; TaskStack stack = mAppToken != null ? getStack() : null; - if (stack != null && stack.hasSibling()) { - mContainingFrame.set(getStackBounds(stack)); + if (stack != null && !stack.isFullscreen()) { + getStackBounds(stack, mContainingFrame); if (mUnderStatusBar) { mContainingFrame.top = pf.top; } @@ -593,9 +596,12 @@ final class WindowState implements WindowManagerPolicy.WindowState { } if (mIsWallpaper && (fw != mFrame.width() || fh != mFrame.height())) { - final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo(); - mService.updateWallpaperOffsetLocked(this, - displayInfo.logicalWidth, displayInfo.logicalHeight, false); + final DisplayContent displayContent = getDisplayContent(); + if (displayContent != null) { + final DisplayInfo displayInfo = displayContent.getDisplayInfo(); + mService.updateWallpaperOffsetLocked(this, + displayInfo.logicalWidth, displayInfo.logicalHeight, false); + } } if (DEBUG_LAYOUT || WindowManagerService.localLOGV) Slog.v(TAG, @@ -708,8 +714,16 @@ final class WindowState implements WindowManagerPolicy.WindowState { return mOverscanInsetsChanged || mContentInsetsChanged || mVisibleInsetsChanged; } + public DisplayContent getDisplayContent() { + return mAppToken == null ? mDisplayContent : getStack().getDisplayContent(); + } + public int getDisplayId() { - return mDisplayContent.getDisplayId(); + final DisplayContent displayContent = getDisplayContent(); + if (displayContent == null) { + return -1; + } + return displayContent.getDisplayId(); } TaskStack getStack() { @@ -717,21 +731,28 @@ final class WindowState implements WindowManagerPolicy.WindowState { if (wtoken != null) { Task task = mService.mTaskIdToTask.get(wtoken.groupId); if (task != null) { - return task.mStack; + if (task.mStack != null) { + return task.mStack; + } + Slog.e(TAG, "getStack: mStack null for task=" + task); + } else { + Slog.e(TAG, "getStack: " + this + " couldn't find taskId=" + wtoken.groupId + + " Callers=" + Debug.getCallers(4)); } } return mDisplayContent.getHomeStack(); } - Rect getStackBounds() { - return getStackBounds(getStack()); + void getStackBounds(Rect bounds) { + getStackBounds(getStack(), bounds); } - private Rect getStackBounds(TaskStack stack) { + private void getStackBounds(TaskStack stack, Rect bounds) { if (stack != null) { - return stack.mStackBox.mBounds; + stack.getBounds(bounds); + return; } - return mFrame; + bounds.set(mFrame); } public long getInputDispatchingTimeoutNanos() { @@ -1190,7 +1211,12 @@ final class WindowState implements WindowManagerPolicy.WindowState { @Override public boolean isDefaultDisplay() { - return mDisplayContent.isDefaultDisplay; + final DisplayContent displayContent = getDisplayContent(); + if (displayContent == null) { + // Only a window that was on a non-default display can be detached from it. + return false; + } + return getDisplayContent().isDefaultDisplay; } public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) { @@ -1207,7 +1233,11 @@ final class WindowState implements WindowManagerPolicy.WindowState { && win.mAppToken != null && win.mAppToken.showWhenLocked) { // Save some cycles by not calling getDisplayInfo unless it is an application // window intended for all users. - final DisplayInfo displayInfo = win.mDisplayContent.getDisplayInfo(); + final DisplayContent displayContent = win.getDisplayContent(); + if (displayContent == null) { + return true; + } + final DisplayInfo displayInfo = displayContent.getDisplayInfo(); if (win.mFrame.left <= 0 && win.mFrame.top <= 0 && win.mFrame.right >= displayInfo.appWidth && win.mFrame.bottom >= displayInfo.appHeight) { @@ -1249,7 +1279,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { } WindowList getWindowList() { - return mDisplayContent.getWindowList(); + final DisplayContent displayContent = getDisplayContent(); + return displayContent == null ? null : displayContent.getWindowList(); } /** @@ -1278,6 +1309,54 @@ final class WindowState implements WindowManagerPolicy.WindowState { } } + void reportResized() { + try { + if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this + + ": " + mCompatFrame); + boolean configChanged = isConfigChanged(); + if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) && configChanged) { + Slog.i(TAG, "Sending new config to window " + this + ": " + + mWinAnimator.mSurfaceW + "x" + mWinAnimator.mSurfaceH + + " / " + mService.mCurConfiguration); + } + setConfiguration(mService.mCurConfiguration); + if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) + Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING"); + + final Rect frame = mFrame; + final Rect overscanInsets = mLastOverscanInsets; + final Rect contentInsets = mLastContentInsets; + final Rect visibleInsets = mLastVisibleInsets; + final boolean reportDraw = mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING; + final Configuration newConfig = configChanged ? mConfiguration : null; + if (mClient instanceof IWindow.Stub) { + // To prevent deadlock simulate one-way call if win.mClient is a local object. + mService.mH.post(new Runnable() { + @Override + public void run() { + try { + mClient.resized(frame, overscanInsets, contentInsets, + visibleInsets, reportDraw, newConfig); + } catch (RemoteException e) { + // Not a remote call, RemoteException won't be raised. + } + } + }); + } else { + mClient.resized(frame, overscanInsets, contentInsets, visibleInsets, reportDraw, + newConfig); + } + mOverscanInsetsChanged = false; + mContentInsetsChanged = false; + mVisibleInsetsChanged = false; + mWinAnimator.mSurfaceResized = false; + } catch (RemoteException e) { + mOrientationChanging = false; + mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() + - mService.mDisplayFreezeTime); + } + } + public void registerFocusObserver(IWindowFocusObserver observer) { synchronized(mService.mWindowMap) { if (mFocusCallbacks == null) { @@ -1302,7 +1381,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { } void dump(PrintWriter pw, String prefix, boolean dumpAll) { - pw.print(prefix); pw.print("mDisplayId="); pw.print(mDisplayContent.getDisplayId()); + pw.print(prefix); pw.print("mDisplayId="); pw.print(getDisplayId()); pw.print(" mSession="); pw.print(mSession); pw.print(" mClient="); pw.println(mClient.asBinder()); pw.print(prefix); pw.print("mOwnerUid="); pw.print(mOwnerUid); diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index c405170da280..f98b724d339b 100644 --- a/services/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -1,4 +1,18 @@ -// Copyright 2012 Google Inc. All Rights Reserved. +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.android.server.wm; @@ -150,8 +164,6 @@ class WindowStateAnimator { int mAttrFlags; int mAttrType; - final int mLayerStack; - public WindowStateAnimator(final WindowState win) { final WindowManagerService service = win.mService; @@ -159,7 +171,7 @@ class WindowStateAnimator { mAnimator = service.mAnimator; mPolicy = service.mPolicy; mContext = service.mContext; - final DisplayInfo displayInfo = win.mDisplayContent.getDisplayInfo(); + final DisplayInfo displayInfo = win.getDisplayContent().getDisplayInfo(); mAnimDw = displayInfo.appWidth; mAnimDh = displayInfo.appHeight; @@ -171,7 +183,6 @@ class WindowStateAnimator { mAttrFlags = win.mAttrs.flags; mAttrType = win.mAttrs.type; mIsWallpaper = win.mIsWallpaper; - mLayerStack = win.mDisplayContent.getDisplay().getLayerStack(); } public void setAnimation(Animation anim) { @@ -243,7 +254,8 @@ class WindowStateAnimator { // Save the animation state as it was before this step so WindowManagerService can tell if // we just started or just stopped animating by comparing mWasAnimating with isAnimating(). mWasAnimating = mAnimating; - if (mService.okToDisplay()) { + final DisplayContent displayContent = mWin.getDisplayContent(); + if (displayContent != null && mService.okToDisplay()) { // We will run animations as long as the display isn't frozen. if (mWin.isDrawnLw() && mAnimation != null) { @@ -258,7 +270,7 @@ class WindowStateAnimator { " scale=" + mService.mWindowAnimationScale); mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), mAnimDw, mAnimDh); - final DisplayInfo displayInfo = mWin.mDisplayContent.getDisplayInfo(); + final DisplayInfo displayInfo = displayContent.getDisplayInfo(); mAnimDw = displayInfo.appWidth; mAnimDh = displayInfo.appHeight; mAnimation.setStartTime(currentTime); @@ -337,7 +349,9 @@ class WindowStateAnimator { + mWin.mPolicyVisibilityAfterAnim); } mWin.mPolicyVisibility = mWin.mPolicyVisibilityAfterAnim; - mWin.mDisplayContent.layoutNeeded = true; + if (displayContent != null) { + displayContent.layoutNeeded = true; + } if (!mWin.mPolicyVisibility) { if (mService.mCurrentFocus == mWin) { if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.i(TAG, @@ -363,11 +377,13 @@ class WindowStateAnimator { } else if (mAttrType == LayoutParams.TYPE_STATUS_BAR && mWin.mPolicyVisibility) { // Upon completion of a not-visible to visible status bar animation a relayout is // required. - mWin.mDisplayContent.layoutNeeded = true; + if (displayContent != null) { + displayContent.layoutNeeded = true; + } } finishExit(); - final int displayId = mWin.mDisplayContent.getDisplayId(); + final int displayId = mWin.getDisplayId(); mAnimator.setPendingLayoutChanges(displayId, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM); if (WindowManagerService.DEBUG_LAYOUT_REPEATS) mService.debugLayoutRepeats( "WindowStateAnimator", mAnimator.getPendingLayoutChanges(displayId)); @@ -414,6 +430,7 @@ class WindowStateAnimator { mService.mPendingRemove.add(mWin); mWin.mRemoveOnExit = false; } + mService.mPendingStacksRemove.add(mWin.getStack()); mAnimator.hideWallpapersLocked(mWin); } @@ -487,6 +504,7 @@ class WindowStateAnimator { private final Rect mWindowCrop = new Rect(); private boolean mShown = false; private int mLayerStack; + private boolean mIsOpaque; private final String mName; public SurfaceTrace(SurfaceSession s, @@ -572,6 +590,16 @@ class WindowStateAnimator { } @Override + public void setOpaque(boolean isOpaque) { + if (isOpaque != mIsOpaque) { + Slog.v(SURFACE_TAG, "setOpaque(" + isOpaque + "): OLD:" + this + + ". Called by " + Debug.getCallers(3)); + mIsOpaque = isOpaque; + } + super.setOpaque(isOpaque); + } + + @Override public void hide() { if (mShown) { Slog.v(SURFACE_TAG, "hide: OLD:" + this + ". Called by " + Debug.getCallers(3)); @@ -617,7 +645,8 @@ class WindowStateAnimator { + mName + " (" + mLayerStack + "): shown=" + mShown + " layer=" + mLayer + " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y + " " + mSize.x + "x" + mSize.y - + " crop=" + mWindowCrop.toShortString(); + + " crop=" + mWindowCrop.toShortString() + + " opaque=" + mIsOpaque; } } @@ -732,7 +761,10 @@ class WindowStateAnimator { mSurfaceY = mWin.mFrame.top + mWin.mYOffset; mSurfaceControl.setPosition(mSurfaceX, mSurfaceY); mSurfaceLayer = mAnimLayer; - mSurfaceControl.setLayerStack(mLayerStack); + final DisplayContent displayContent = mWin.getDisplayContent(); + if (displayContent != null) { + mSurfaceControl.setLayerStack(displayContent.getDisplay().getLayerStack()); + } mSurfaceControl.setLayer(mAnimLayer); mSurfaceControl.setAlpha(0); mSurfaceShown = false; @@ -921,8 +953,7 @@ class WindowStateAnimator { tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix()); } //TODO (multidisplay): Magnification is supported only for the default display. - if (mService.mDisplayMagnifier != null - && mWin.getDisplayId() == Display.DEFAULT_DISPLAY) { + if (mService.mDisplayMagnifier != null && displayId == Display.DEFAULT_DISPLAY) { MagnificationSpec spec = mService.mDisplayMagnifier .getMagnificationSpecForWindowLocked(mWin); if (spec != null && !spec.isNop()) { @@ -1002,7 +1033,7 @@ class WindowStateAnimator { && mWin.mBaseLayer < mAnimator.mAboveUniverseLayer); MagnificationSpec spec = null; //TODO (multidisplay): Magnification is supported only for the default display. - if (mService.mDisplayMagnifier != null && mWin.getDisplayId() == Display.DEFAULT_DISPLAY) { + if (mService.mDisplayMagnifier != null && displayId == Display.DEFAULT_DISPLAY) { spec = mService.mDisplayMagnifier.getMagnificationSpecForWindowLocked(mWin); } if (applyUniverseTransformation || spec != null) { @@ -1080,7 +1111,11 @@ class WindowStateAnimator { void updateSurfaceWindowCrop(final boolean recoveringMemory) { final WindowState w = mWin; - DisplayInfo displayInfo = w.mDisplayContent.getDisplayInfo(); + final DisplayContent displayContent = w.getDisplayContent(); + if (displayContent == null) { + return; + } + DisplayInfo displayInfo = displayContent.getDisplayInfo(); // Need to recompute a new system decor rect each time. if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) { @@ -1181,8 +1216,7 @@ class WindowStateAnimator { "SIZE " + width + "x" + height, null); mSurfaceResized = true; mSurfaceControl.setSize(width, height); - final int displayId = w.mDisplayContent.getDisplayId(); - mAnimator.setPendingLayoutChanges(displayId, + mAnimator.setPendingLayoutChanges(w.getDisplayId(), WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) { w.getStack().startDimmingIfNeeded(this); @@ -1329,8 +1363,7 @@ class WindowStateAnimator { Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true"); return; } - if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, - ">>> OPEN TRANSACTION setTransparentRegion"); + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setTransparentRegion"); SurfaceControl.openTransaction(); try { if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, @@ -1356,8 +1389,7 @@ class WindowStateAnimator { // transformation is being applied by the animation. return; } - if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, - ">>> OPEN TRANSACTION setWallpaperOffset"); + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset"); SurfaceControl.openTransaction(); try { if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, @@ -1375,6 +1407,22 @@ class WindowStateAnimator { } } + void setOpaque(boolean isOpaque) { + if (mSurfaceControl == null) { + return; + } + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaque"); + SurfaceControl.openTransaction(); + try { + if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "isOpaque=" + isOpaque, + null); + mSurfaceControl.setOpaque(isOpaque); + } finally { + SurfaceControl.closeTransaction(); + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaque"); + } + } + // This must be called while inside a transaction. boolean performShowLocked() { if (mWin.isHiddenFromUserLocked()) { @@ -1444,7 +1492,10 @@ class WindowStateAnimator { // do a layout. If called from within the transaction // loop, this will cause it to restart with a new // layout. - c.mDisplayContent.layoutNeeded = true; + final DisplayContent displayContent = c.getDisplayContent(); + if (displayContent != null) { + displayContent.layoutNeeded = true; + } } } } diff --git a/services/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 22671234c538..22671234c538 100644 --- a/services/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk new file mode 100644 index 000000000000..d1cfff4909b1 --- /dev/null +++ b/services/core/jni/Android.mk @@ -0,0 +1,57 @@ +# This file is included by the top level services directory to collect source +# files +LOCAL_REL_DIR := core/jni + +LOCAL_SRC_FILES += \ + $(LOCAL_REL_DIR)/com_android_server_AlarmManagerService.cpp \ + $(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \ + $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \ + $(LOCAL_REL_DIR)/com_android_server_dreams_McuHal.cpp \ + $(LOCAL_REL_DIR)/com_android_server_input_InputApplicationHandle.cpp \ + $(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \ + $(LOCAL_REL_DIR)/com_android_server_input_InputWindowHandle.cpp \ + $(LOCAL_REL_DIR)/com_android_server_lights_LightsService.cpp \ + $(LOCAL_REL_DIR)/com_android_server_power_PowerManagerService.cpp \ + $(LOCAL_REL_DIR)/com_android_server_SerialService.cpp \ + $(LOCAL_REL_DIR)/com_android_server_SystemServer.cpp \ + $(LOCAL_REL_DIR)/com_android_server_UsbDeviceManager.cpp \ + $(LOCAL_REL_DIR)/com_android_server_UsbHostManager.cpp \ + $(LOCAL_REL_DIR)/com_android_server_VibratorService.cpp \ + $(LOCAL_REL_DIR)/com_android_server_location_GpsLocationProvider.cpp \ + $(LOCAL_REL_DIR)/com_android_server_location_FlpHardwareProvider.cpp \ + $(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \ + $(LOCAL_REL_DIR)/onload.cpp + +LOCAL_C_INCLUDES += \ + $(JNI_H_INCLUDE) \ + frameworks/base/services \ + frameworks/base/libs \ + frameworks/base/core/jni \ + frameworks/native/services \ + external/skia/include/core \ + libcore/include \ + libcore/include/libsuspend \ + $(call include-path-for, libhardware)/hardware \ + $(call include-path-for, libhardware_legacy)/hardware_legacy \ + +LOCAL_SHARED_LIBRARIES += \ + libandroid_runtime \ + libandroidfw \ + libbinder \ + libcutils \ + liblog \ + libhardware \ + libhardware_legacy \ + libnativehelper \ + libutils \ + libui \ + libinput \ + libinputservice \ + libsensorservice \ + libskia \ + libgui \ + libusbhost \ + libsuspend \ + libEGL \ + libGLESv2 + diff --git a/services/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp index 342515bb3bb0..342515bb3bb0 100644 --- a/services/jni/com_android_server_AlarmManagerService.cpp +++ b/services/core/jni/com_android_server_AlarmManagerService.cpp diff --git a/services/jni/com_android_server_AssetAtlasService.cpp b/services/core/jni/com_android_server_AssetAtlasService.cpp index 4a1b55d5d9d5..4a1b55d5d9d5 100644 --- a/services/jni/com_android_server_AssetAtlasService.cpp +++ b/services/core/jni/com_android_server_AssetAtlasService.cpp diff --git a/services/jni/com_android_server_ConsumerIrService.cpp b/services/core/jni/com_android_server_ConsumerIrService.cpp index 004c0aaad445..004c0aaad445 100644 --- a/services/jni/com_android_server_ConsumerIrService.cpp +++ b/services/core/jni/com_android_server_ConsumerIrService.cpp diff --git a/services/jni/com_android_server_SerialService.cpp b/services/core/jni/com_android_server_SerialService.cpp index b889b78cc1f9..b889b78cc1f9 100644 --- a/services/jni/com_android_server_SerialService.cpp +++ b/services/core/jni/com_android_server_SerialService.cpp diff --git a/services/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp index 0625544effdc..0625544effdc 100644 --- a/services/jni/com_android_server_SystemServer.cpp +++ b/services/core/jni/com_android_server_SystemServer.cpp diff --git a/services/jni/com_android_server_UsbDeviceManager.cpp b/services/core/jni/com_android_server_UsbDeviceManager.cpp index 355173384892..355173384892 100644 --- a/services/jni/com_android_server_UsbDeviceManager.cpp +++ b/services/core/jni/com_android_server_UsbDeviceManager.cpp diff --git a/services/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp index f1fa6cf07f60..f1fa6cf07f60 100644 --- a/services/jni/com_android_server_UsbHostManager.cpp +++ b/services/core/jni/com_android_server_UsbHostManager.cpp diff --git a/services/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp index 2b3f74a97184..2b3f74a97184 100644 --- a/services/jni/com_android_server_VibratorService.cpp +++ b/services/core/jni/com_android_server_VibratorService.cpp diff --git a/services/jni/com_android_server_connectivity_Vpn.cpp b/services/core/jni/com_android_server_connectivity_Vpn.cpp index ab8c959f692f..ab8c959f692f 100644 --- a/services/jni/com_android_server_connectivity_Vpn.cpp +++ b/services/core/jni/com_android_server_connectivity_Vpn.cpp diff --git a/services/core/jni/com_android_server_dreams_McuHal.cpp b/services/core/jni/com_android_server_dreams_McuHal.cpp new file mode 100644 index 000000000000..a6d929730683 --- /dev/null +++ b/services/core/jni/com_android_server_dreams_McuHal.cpp @@ -0,0 +1,100 @@ +/* + * 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. + */ + +#define LOG_TAG "McuHal" + +//#define LOG_NDEBUG 0 + +#include "JNIHelp.h" +#include "jni.h" + +#include <ScopedUtfChars.h> +#include <ScopedPrimitiveArray.h> + +#include <utils/Errors.h> +#include <utils/Log.h> +#include <hardware/mcu.h> + +namespace android { + +static jlong nativeOpen(JNIEnv* env, jclass clazz) { + mcu_module_t* module = NULL; + status_t err = hw_get_module(MCU_HARDWARE_MODULE_ID, + (hw_module_t const**)&module); + if (err) { + ALOGE("Couldn't load %s module (%s)", MCU_HARDWARE_MODULE_ID, strerror(-err)); + return 0; + } + + err = module->init(module); + if (err) { + ALOGE("Couldn't initialize %s module (%s)", MCU_HARDWARE_MODULE_ID, strerror(-err)); + return 0; + } + + return reinterpret_cast<jlong>(module); +} + +static jbyteArray nativeSendMessage(JNIEnv* env, jclass clazz, + jlong ptr, jstring msgStr, jbyteArray argArray) { + mcu_module_t* module = reinterpret_cast<mcu_module_t*>(ptr); + + ScopedUtfChars msg(env, msgStr); + ALOGV("Sending message %s to MCU", msg.c_str()); + + void* result = NULL; + size_t resultSize = 0; + status_t err; + if (argArray) { + ScopedByteArrayRO arg(env, argArray); + err = module->sendMessage(module, msg.c_str(), arg.get(), arg.size(), + &result, &resultSize); + } else { + err = module->sendMessage(module, msg.c_str(), NULL, 0, &result, &resultSize); + } + if (err) { + ALOGE("Couldn't send message to MCU (%s)", strerror(-err)); + return NULL; + } + + if (!result) { + return NULL; + } + + jbyteArray resultArray = env->NewByteArray(resultSize); + if (resultArray) { + env->SetByteArrayRegion(resultArray, 0, resultSize, static_cast<jbyte*>(result)); + } + free(result); + return resultArray; +} + +static JNINativeMethod gMcuHalMethods[] = { + /* name, signature, funcPtr */ + { "nativeOpen", "()J", + (void*) nativeOpen }, + { "nativeSendMessage", "(JLjava/lang/String;[B)[B", + (void*) nativeSendMessage }, +}; + +int register_android_server_dreams_McuHal(JNIEnv* env) { + int res = jniRegisterNativeMethods(env, "com/android/server/dreams/McuHal", + gMcuHalMethods, NELEM(gMcuHalMethods)); + LOG_FATAL_IF(res < 0, "Unable to register native methods."); + return 0; +} + +} /* namespace android */ diff --git a/services/jni/com_android_server_input_InputApplicationHandle.cpp b/services/core/jni/com_android_server_input_InputApplicationHandle.cpp index f943d168e7d6..f943d168e7d6 100644 --- a/services/jni/com_android_server_input_InputApplicationHandle.cpp +++ b/services/core/jni/com_android_server_input_InputApplicationHandle.cpp diff --git a/services/jni/com_android_server_input_InputApplicationHandle.h b/services/core/jni/com_android_server_input_InputApplicationHandle.h index 89d48c63cf3a..89d48c63cf3a 100644 --- a/services/jni/com_android_server_input_InputApplicationHandle.h +++ b/services/core/jni/com_android_server_input_InputApplicationHandle.h diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 10ad278a8e10..697f56de76d2 100644 --- a/services/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -144,8 +144,6 @@ static void loadSystemIconAsSprite(JNIEnv* env, jobject contextObj, int32_t styl enum { WM_ACTION_PASS_TO_USER = 1, - WM_ACTION_WAKE_UP = 2, - WM_ACTION_GO_TO_SLEEP = 4, }; @@ -834,7 +832,7 @@ void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& p JNIEnv* env = jniEnv(); jint wmActions = env->CallIntMethod(mServiceObj, gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff, - policyFlags); + when, policyFlags); if (checkAndClearExceptionFromCallback(env, "interceptMotionBeforeQueueingWhenScreenOff")) { wmActions = 0; @@ -850,20 +848,6 @@ void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& p void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags) { - if (wmActions & WM_ACTION_GO_TO_SLEEP) { -#if DEBUG_INPUT_DISPATCHER_POLICY - ALOGD("handleInterceptActions: Going to sleep."); -#endif - android_server_PowerManagerService_goToSleep(when); - } - - if (wmActions & WM_ACTION_WAKE_UP) { -#if DEBUG_INPUT_DISPATCHER_POLICY - ALOGD("handleInterceptActions: Waking up."); -#endif - android_server_PowerManagerService_wakeUp(when); - } - if (wmActions & WM_ACTION_PASS_TO_USER) { policyFlags |= POLICY_FLAG_PASS_TO_USER; } else { @@ -1143,7 +1127,7 @@ static void nativeSetInputFilterEnabled(JNIEnv* env, jclass clazz, } static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz, - jlong ptr, jobject inputEventObj, jint injectorPid, jint injectorUid, + jlong ptr, jobject inputEventObj, jint displayId, jint injectorPid, jint injectorUid, jint syncMode, jint timeoutMillis, jint policyFlags) { NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); @@ -1156,7 +1140,7 @@ static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz, } return (jint) im->getInputManager()->getDispatcher()->injectInputEvent( - & keyEvent, injectorPid, injectorUid, syncMode, timeoutMillis, + & keyEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis, uint32_t(policyFlags)); } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) { const MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, inputEventObj); @@ -1166,7 +1150,7 @@ static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz, } return (jint) im->getInputManager()->getDispatcher()->injectInputEvent( - motionEvent, injectorPid, injectorUid, syncMode, timeoutMillis, + motionEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis, uint32_t(policyFlags)); } else { jniThrowRuntimeException(env, "Invalid input event type."); @@ -1326,7 +1310,7 @@ static JNINativeMethod gInputManagerMethods[] = { (void*) nativeUnregisterInputChannel }, { "nativeSetInputFilterEnabled", "(JZ)V", (void*) nativeSetInputFilterEnabled }, - { "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIII)I", + { "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIIII)I", (void*) nativeInjectInputEvent }, { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V", (void*) nativeSetInputWindows }, @@ -1402,7 +1386,7 @@ int register_android_server_InputManager(JNIEnv* env) { GET_METHOD_ID(gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff, clazz, - "interceptMotionBeforeQueueingWhenScreenOff", "(I)I"); + "interceptMotionBeforeQueueingWhenScreenOff", "(JI)I"); GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz, "interceptKeyBeforeDispatching", diff --git a/services/jni/com_android_server_input_InputWindowHandle.cpp b/services/core/jni/com_android_server_input_InputWindowHandle.cpp index b80183c73b80..b80183c73b80 100644 --- a/services/jni/com_android_server_input_InputWindowHandle.cpp +++ b/services/core/jni/com_android_server_input_InputWindowHandle.cpp diff --git a/services/jni/com_android_server_input_InputWindowHandle.h b/services/core/jni/com_android_server_input_InputWindowHandle.h index 2cfa17d34b83..2cfa17d34b83 100644 --- a/services/jni/com_android_server_input_InputWindowHandle.h +++ b/services/core/jni/com_android_server_input_InputWindowHandle.h diff --git a/services/jni/com_android_server_LightsService.cpp b/services/core/jni/com_android_server_lights_LightsService.cpp index 69793f7c1af9..d51e044c4dbe 100644 --- a/services/jni/com_android_server_LightsService.cpp +++ b/services/core/jni/com_android_server_lights_LightsService.cpp @@ -134,7 +134,7 @@ static JNINativeMethod method_table[] = { int register_android_server_LightsService(JNIEnv *env) { - return jniRegisterNativeMethods(env, "com/android/server/LightsService", + return jniRegisterNativeMethods(env, "com/android/server/lights/LightsService", method_table, NELEM(method_table)); } diff --git a/services/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp index 6c14887ef627..6c14887ef627 100644 --- a/services/jni/com_android_server_location_FlpHardwareProvider.cpp +++ b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp diff --git a/services/jni/com_android_server_location_GpsLocationProvider.cpp b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp index e9ba116c26bf..e9ba116c26bf 100644 --- a/services/jni/com_android_server_location_GpsLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp diff --git a/services/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp index 151e134ee3ba..151e134ee3ba 100644 --- a/services/jni/com_android_server_power_PowerManagerService.cpp +++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp diff --git a/services/jni/com_android_server_power_PowerManagerService.h b/services/core/jni/com_android_server_power_PowerManagerService.h index 0808b80f18ff..0808b80f18ff 100644 --- a/services/jni/com_android_server_power_PowerManagerService.h +++ b/services/core/jni/com_android_server_power_PowerManagerService.h diff --git a/services/jni/onload.cpp b/services/core/jni/onload.cpp index efc34a2aca41..00986d5d3537 100644 --- a/services/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -36,6 +36,7 @@ int register_android_server_location_GpsLocationProvider(JNIEnv* env); int register_android_server_location_FlpHardwareProvider(JNIEnv* env); int register_android_server_connectivity_Vpn(JNIEnv* env); int register_android_server_AssetAtlasService(JNIEnv* env); +int register_android_server_dreams_McuHal(JNIEnv* env); }; using namespace android; @@ -67,7 +68,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) register_android_server_connectivity_Vpn(env); register_android_server_AssetAtlasService(env); register_android_server_ConsumerIrService(env); - + register_android_server_dreams_McuHal(env); return JNI_VERSION_1_4; } diff --git a/services/devicepolicy/Android.mk b/services/devicepolicy/Android.mk new file mode 100644 index 000000000000..a55d1386671c --- /dev/null +++ b/services/devicepolicy/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := services.devicepolicy + +LOCAL_SRC_FILES += \ + $(call all-java-files-under,java) + +LOCAL_JAVA_LIBRARIES := conscrypt + +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 2bb99d68ed77..296d852248d1 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.devicepolicy; import static android.Manifest.permission.MANAGE_CA_CERTIFICATES; @@ -25,6 +25,7 @@ import com.android.internal.util.JournaledFile; import com.android.internal.util.XmlUtils; import com.android.internal.widget.LockPatternUtils; import com.android.org.conscrypt.TrustedCertificateStore; +import com.android.server.SystemService; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -117,7 +118,7 @@ import java.util.Set; */ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { - private static final String TAG = "DevicePolicyManagerService"; + private static final String LOG_TAG = "DevicePolicyManagerService"; private static final String DEVICE_POLICIES_XML = "device_policies.xml"; @@ -149,6 +150,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { */ private boolean mHasFeature; + public static final class Lifecycle extends SystemService { + private DevicePolicyManagerService mService; + + public Lifecycle(Context context) { + super(context); + mService = new DevicePolicyManagerService(context); + } + + @Override + public void onStart() { + publishBinderService(Context.DEVICE_POLICY_SERVICE, mService); + } + + @Override + public void onBootPhase(int phase) { + if (phase == PHASE_LOCK_SETTINGS_READY) { + mService.systemReady(); + } + } + } public static class DevicePolicyData { int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; int mActivePasswordLength = 0; @@ -186,7 +207,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { getSendingUserId()); if (Intent.ACTION_BOOT_COMPLETED.equals(action) || ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) { - if (DBG) Slog.v(TAG, "Sending password expiration notifications for action " + if (DBG) Slog.v(LOG_TAG, "Sending password expiration notifications for action " + action + " for user " + userHandle); mHandler.post(new Runnable() { public void run() { @@ -218,6 +239,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { }; static class ActiveAdmin { + private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features"; + private static final String TAG_DISABLE_CAMERA = "disable-camera"; + private static final String TAG_ENCRYPTION_REQUESTED = "encryption-requested"; + private static final String TAG_PASSWORD_EXPIRATION_DATE = "password-expiration-date"; + private static final String TAG_PASSWORD_EXPIRATION_TIMEOUT = "password-expiration-timeout"; + private static final String TAG_GLOBAL_PROXY_EXCLUSION_LIST = "global-proxy-exclusion-list"; + private static final String TAG_GLOBAL_PROXY_SPEC = "global-proxy-spec"; + private static final String TAG_SPECIFIES_GLOBAL_PROXY = "specifies-global-proxy"; + private static final String TAG_MAX_FAILED_PASSWORD_WIPE = "max-failed-password-wipe"; + private static final String TAG_MAX_TIME_TO_UNLOCK = "max-time-to-unlock"; + private static final String TAG_MIN_PASSWORD_NONLETTER = "min-password-nonletter"; + private static final String TAG_MIN_PASSWORD_SYMBOLS = "min-password-symbols"; + private static final String TAG_MIN_PASSWORD_NUMERIC = "min-password-numeric"; + private static final String TAG_MIN_PASSWORD_LETTERS = "min-password-letters"; + private static final String TAG_MIN_PASSWORD_LOWERCASE = "min-password-lowercase"; + private static final String TAG_MIN_PASSWORD_UPPERCASE = "min-password-uppercase"; + private static final String TAG_PASSWORD_HISTORY_LENGTH = "password-history-length"; + private static final String TAG_MIN_PASSWORD_LENGTH = "min-password-length"; + private static final String ATTR_VALUE = "value"; + private static final String TAG_PASSWORD_QUALITY = "password-quality"; + private static final String TAG_POLICIES = "policies"; + final DeviceAdminInfo info; int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; @@ -281,103 +324,103 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { void writeToXml(XmlSerializer out) throws IllegalArgumentException, IllegalStateException, IOException { - out.startTag(null, "policies"); + out.startTag(null, TAG_POLICIES); info.writePoliciesToXml(out); - out.endTag(null, "policies"); + out.endTag(null, TAG_POLICIES); if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { - out.startTag(null, "password-quality"); - out.attribute(null, "value", Integer.toString(passwordQuality)); - out.endTag(null, "password-quality"); + out.startTag(null, TAG_PASSWORD_QUALITY); + out.attribute(null, ATTR_VALUE, Integer.toString(passwordQuality)); + out.endTag(null, TAG_PASSWORD_QUALITY); if (minimumPasswordLength != DEF_MINIMUM_PASSWORD_LENGTH) { - out.startTag(null, "min-password-length"); - out.attribute(null, "value", Integer.toString(minimumPasswordLength)); - out.endTag(null, "min-password-length"); + out.startTag(null, TAG_MIN_PASSWORD_LENGTH); + out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordLength)); + out.endTag(null, TAG_MIN_PASSWORD_LENGTH); } if(passwordHistoryLength != DEF_PASSWORD_HISTORY_LENGTH) { - out.startTag(null, "password-history-length"); - out.attribute(null, "value", Integer.toString(passwordHistoryLength)); - out.endTag(null, "password-history-length"); + out.startTag(null, TAG_PASSWORD_HISTORY_LENGTH); + out.attribute(null, ATTR_VALUE, Integer.toString(passwordHistoryLength)); + out.endTag(null, TAG_PASSWORD_HISTORY_LENGTH); } if (minimumPasswordUpperCase != DEF_MINIMUM_PASSWORD_UPPER_CASE) { - out.startTag(null, "min-password-uppercase"); - out.attribute(null, "value", Integer.toString(minimumPasswordUpperCase)); - out.endTag(null, "min-password-uppercase"); + out.startTag(null, TAG_MIN_PASSWORD_UPPERCASE); + out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordUpperCase)); + out.endTag(null, TAG_MIN_PASSWORD_UPPERCASE); } if (minimumPasswordLowerCase != DEF_MINIMUM_PASSWORD_LOWER_CASE) { - out.startTag(null, "min-password-lowercase"); - out.attribute(null, "value", Integer.toString(minimumPasswordLowerCase)); - out.endTag(null, "min-password-lowercase"); + out.startTag(null, TAG_MIN_PASSWORD_LOWERCASE); + out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordLowerCase)); + out.endTag(null, TAG_MIN_PASSWORD_LOWERCASE); } if (minimumPasswordLetters != DEF_MINIMUM_PASSWORD_LETTERS) { - out.startTag(null, "min-password-letters"); - out.attribute(null, "value", Integer.toString(minimumPasswordLetters)); - out.endTag(null, "min-password-letters"); + out.startTag(null, TAG_MIN_PASSWORD_LETTERS); + out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordLetters)); + out.endTag(null, TAG_MIN_PASSWORD_LETTERS); } if (minimumPasswordNumeric != DEF_MINIMUM_PASSWORD_NUMERIC) { - out.startTag(null, "min-password-numeric"); - out.attribute(null, "value", Integer.toString(minimumPasswordNumeric)); - out.endTag(null, "min-password-numeric"); + out.startTag(null, TAG_MIN_PASSWORD_NUMERIC); + out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordNumeric)); + out.endTag(null, TAG_MIN_PASSWORD_NUMERIC); } if (minimumPasswordSymbols != DEF_MINIMUM_PASSWORD_SYMBOLS) { - out.startTag(null, "min-password-symbols"); - out.attribute(null, "value", Integer.toString(minimumPasswordSymbols)); - out.endTag(null, "min-password-symbols"); + out.startTag(null, TAG_MIN_PASSWORD_SYMBOLS); + out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordSymbols)); + out.endTag(null, TAG_MIN_PASSWORD_SYMBOLS); } if (minimumPasswordNonLetter > DEF_MINIMUM_PASSWORD_NON_LETTER) { - out.startTag(null, "min-password-nonletter"); - out.attribute(null, "value", Integer.toString(minimumPasswordNonLetter)); - out.endTag(null, "min-password-nonletter"); + out.startTag(null, TAG_MIN_PASSWORD_NONLETTER); + out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordNonLetter)); + out.endTag(null, TAG_MIN_PASSWORD_NONLETTER); } } if (maximumTimeToUnlock != DEF_MAXIMUM_TIME_TO_UNLOCK) { - out.startTag(null, "max-time-to-unlock"); - out.attribute(null, "value", Long.toString(maximumTimeToUnlock)); - out.endTag(null, "max-time-to-unlock"); + out.startTag(null, TAG_MAX_TIME_TO_UNLOCK); + out.attribute(null, ATTR_VALUE, Long.toString(maximumTimeToUnlock)); + out.endTag(null, TAG_MAX_TIME_TO_UNLOCK); } if (maximumFailedPasswordsForWipe != DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) { - out.startTag(null, "max-failed-password-wipe"); - out.attribute(null, "value", Integer.toString(maximumFailedPasswordsForWipe)); - out.endTag(null, "max-failed-password-wipe"); + out.startTag(null, TAG_MAX_FAILED_PASSWORD_WIPE); + out.attribute(null, ATTR_VALUE, Integer.toString(maximumFailedPasswordsForWipe)); + out.endTag(null, TAG_MAX_FAILED_PASSWORD_WIPE); } if (specifiesGlobalProxy) { - out.startTag(null, "specifies-global-proxy"); - out.attribute(null, "value", Boolean.toString(specifiesGlobalProxy)); - out.endTag(null, "specifies_global_proxy"); + out.startTag(null, TAG_SPECIFIES_GLOBAL_PROXY); + out.attribute(null, ATTR_VALUE, Boolean.toString(specifiesGlobalProxy)); + out.endTag(null, TAG_SPECIFIES_GLOBAL_PROXY); if (globalProxySpec != null) { - out.startTag(null, "global-proxy-spec"); - out.attribute(null, "value", globalProxySpec); - out.endTag(null, "global-proxy-spec"); + out.startTag(null, TAG_GLOBAL_PROXY_SPEC); + out.attribute(null, ATTR_VALUE, globalProxySpec); + out.endTag(null, TAG_GLOBAL_PROXY_SPEC); } if (globalProxyExclusionList != null) { - out.startTag(null, "global-proxy-exclusion-list"); - out.attribute(null, "value", globalProxyExclusionList); - out.endTag(null, "global-proxy-exclusion-list"); + out.startTag(null, TAG_GLOBAL_PROXY_EXCLUSION_LIST); + out.attribute(null, ATTR_VALUE, globalProxyExclusionList); + out.endTag(null, TAG_GLOBAL_PROXY_EXCLUSION_LIST); } } if (passwordExpirationTimeout != DEF_PASSWORD_EXPIRATION_TIMEOUT) { - out.startTag(null, "password-expiration-timeout"); - out.attribute(null, "value", Long.toString(passwordExpirationTimeout)); - out.endTag(null, "password-expiration-timeout"); + out.startTag(null, TAG_PASSWORD_EXPIRATION_TIMEOUT); + out.attribute(null, ATTR_VALUE, Long.toString(passwordExpirationTimeout)); + out.endTag(null, TAG_PASSWORD_EXPIRATION_TIMEOUT); } if (passwordExpirationDate != DEF_PASSWORD_EXPIRATION_DATE) { - out.startTag(null, "password-expiration-date"); - out.attribute(null, "value", Long.toString(passwordExpirationDate)); - out.endTag(null, "password-expiration-date"); + out.startTag(null, TAG_PASSWORD_EXPIRATION_DATE); + out.attribute(null, ATTR_VALUE, Long.toString(passwordExpirationDate)); + out.endTag(null, TAG_PASSWORD_EXPIRATION_DATE); } if (encryptionRequested) { - out.startTag(null, "encryption-requested"); - out.attribute(null, "value", Boolean.toString(encryptionRequested)); - out.endTag(null, "encryption-requested"); + out.startTag(null, TAG_ENCRYPTION_REQUESTED); + out.attribute(null, ATTR_VALUE, Boolean.toString(encryptionRequested)); + out.endTag(null, TAG_ENCRYPTION_REQUESTED); } if (disableCamera) { - out.startTag(null, "disable-camera"); - out.attribute(null, "value", Boolean.toString(disableCamera)); - out.endTag(null, "disable-camera"); + out.startTag(null, TAG_DISABLE_CAMERA); + out.attribute(null, ATTR_VALUE, Boolean.toString(disableCamera)); + out.endTag(null, TAG_DISABLE_CAMERA); } if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) { - out.startTag(null, "disable-keyguard-features"); - out.attribute(null, "value", Integer.toString(disabledKeyguardFeatures)); - out.endTag(null, "disable-keyguard-features"); + out.startTag(null, TAG_DISABLE_KEYGUARD_FEATURES); + out.attribute(null, ATTR_VALUE, Integer.toString(disabledKeyguardFeatures)); + out.endTag(null, TAG_DISABLE_KEYGUARD_FEATURES); } } @@ -391,67 +434,67 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { continue; } String tag = parser.getName(); - if ("policies".equals(tag)) { + if (TAG_POLICIES.equals(tag)) { info.readPoliciesFromXml(parser); - } else if ("password-quality".equals(tag)) { + } else if (TAG_PASSWORD_QUALITY.equals(tag)) { passwordQuality = Integer.parseInt( - parser.getAttributeValue(null, "value")); - } else if ("min-password-length".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_MIN_PASSWORD_LENGTH.equals(tag)) { minimumPasswordLength = Integer.parseInt( - parser.getAttributeValue(null, "value")); - } else if ("password-history-length".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_PASSWORD_HISTORY_LENGTH.equals(tag)) { passwordHistoryLength = Integer.parseInt( - parser.getAttributeValue(null, "value")); - } else if ("min-password-uppercase".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_MIN_PASSWORD_UPPERCASE.equals(tag)) { minimumPasswordUpperCase = Integer.parseInt( - parser.getAttributeValue(null, "value")); - } else if ("min-password-lowercase".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_MIN_PASSWORD_LOWERCASE.equals(tag)) { minimumPasswordLowerCase = Integer.parseInt( - parser.getAttributeValue(null, "value")); - } else if ("min-password-letters".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_MIN_PASSWORD_LETTERS.equals(tag)) { minimumPasswordLetters = Integer.parseInt( - parser.getAttributeValue(null, "value")); - } else if ("min-password-numeric".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_MIN_PASSWORD_NUMERIC.equals(tag)) { minimumPasswordNumeric = Integer.parseInt( - parser.getAttributeValue(null, "value")); - } else if ("min-password-symbols".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_MIN_PASSWORD_SYMBOLS.equals(tag)) { minimumPasswordSymbols = Integer.parseInt( - parser.getAttributeValue(null, "value")); - } else if ("min-password-nonletter".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_MIN_PASSWORD_NONLETTER.equals(tag)) { minimumPasswordNonLetter = Integer.parseInt( - parser.getAttributeValue(null, "value")); - } else if ("max-time-to-unlock".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_MAX_TIME_TO_UNLOCK.equals(tag)) { maximumTimeToUnlock = Long.parseLong( - parser.getAttributeValue(null, "value")); - } else if ("max-failed-password-wipe".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_MAX_FAILED_PASSWORD_WIPE.equals(tag)) { maximumFailedPasswordsForWipe = Integer.parseInt( - parser.getAttributeValue(null, "value")); - } else if ("specifies-global-proxy".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_SPECIFIES_GLOBAL_PROXY.equals(tag)) { specifiesGlobalProxy = Boolean.parseBoolean( - parser.getAttributeValue(null, "value")); - } else if ("global-proxy-spec".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_GLOBAL_PROXY_SPEC.equals(tag)) { globalProxySpec = - parser.getAttributeValue(null, "value"); - } else if ("global-proxy-exclusion-list".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE); + } else if (TAG_GLOBAL_PROXY_EXCLUSION_LIST.equals(tag)) { globalProxyExclusionList = - parser.getAttributeValue(null, "value"); - } else if ("password-expiration-timeout".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE); + } else if (TAG_PASSWORD_EXPIRATION_TIMEOUT.equals(tag)) { passwordExpirationTimeout = Long.parseLong( - parser.getAttributeValue(null, "value")); - } else if ("password-expiration-date".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_PASSWORD_EXPIRATION_DATE.equals(tag)) { passwordExpirationDate = Long.parseLong( - parser.getAttributeValue(null, "value")); - } else if ("encryption-requested".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_ENCRYPTION_REQUESTED.equals(tag)) { encryptionRequested = Boolean.parseBoolean( - parser.getAttributeValue(null, "value")); - } else if ("disable-camera".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_DISABLE_CAMERA.equals(tag)) { disableCamera = Boolean.parseBoolean( - parser.getAttributeValue(null, "value")); - } else if ("disable-keyguard-features".equals(tag)) { + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_DISABLE_KEYGUARD_FEATURES.equals(tag)) { disabledKeyguardFeatures = Integer.parseInt( - parser.getAttributeValue(null, "value")); + parser.getAttributeValue(null, ATTR_VALUE)); } else { - Slog.w(TAG, "Unknown admin tag: " + tag); + Slog.w(LOG_TAG, "Unknown admin tag: " + tag); } XmlUtils.skipCurrentTag(parser); } @@ -513,7 +556,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private void handlePackagesChanged(int userHandle) { boolean removed = false; - if (DBG) Slog.d(TAG, "Handling package changes for user " + userHandle); + if (DBG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle); DevicePolicyData policy = getUserData(userHandle); IPackageManager pm = AppGlobals.getPackageManager(); for (int i = policy.mAdminList.size() - 1; i >= 0; i--) { @@ -585,7 +628,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { void removeUserData(int userHandle) { synchronized (this) { if (userHandle == UserHandle.USER_OWNER) { - Slog.w(TAG, "Tried to remove device policy file for user 0! Ignoring."); + Slog.w(LOG_TAG, "Tried to remove device policy file for user 0! Ignoring."); return; } DevicePolicyData policy = mUserData.get(userHandle); @@ -595,7 +638,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { File policyFile = new File(Environment.getUserSystemDirectory(userHandle), DEVICE_POLICIES_XML); policyFile.delete(); - Slog.i(TAG, "Removed device policy file " + policyFile.getAbsolutePath()); + Slog.i(LOG_TAG, "Removed device policy file " + policyFile.getAbsolutePath()); } } @@ -792,10 +835,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { try { return new DeviceAdminInfo(mContext, infos.get(0)); } catch (XmlPullParserException e) { - Slog.w(TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName, e); + Slog.w(LOG_TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName, + e); return null; } catch (IOException e) { - Slog.w(TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName, e); + Slog.w(LOG_TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName, + e); return null; } } @@ -922,7 +967,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { ComponentName.unflattenFromString(name), userHandle); if (DBG && (UserHandle.getUserId(dai.getActivityInfo().applicationInfo.uid) != userHandle)) { - Slog.w(TAG, "findAdmin returned an incorrect uid " + Slog.w(LOG_TAG, "findAdmin returned an incorrect uid " + dai.getActivityInfo().applicationInfo.uid + " for user " + userHandle); } @@ -933,7 +978,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { policy.mAdminList.add(ap); } } catch (RuntimeException e) { - Slog.w(TAG, "Failed loading admin " + name, e); + Slog.w(LOG_TAG, "Failed loading admin " + name, e); } } else if ("failed-password-attempts".equals(tag)) { policy.mFailedPasswordAttempts = Integer.parseInt( @@ -962,22 +1007,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { parser.getAttributeValue(null, "nonletter")); XmlUtils.skipCurrentTag(parser); } else { - Slog.w(TAG, "Unknown tag: " + tag); + Slog.w(LOG_TAG, "Unknown tag: " + tag); XmlUtils.skipCurrentTag(parser); } } } catch (NullPointerException e) { - Slog.w(TAG, "failed parsing " + file + " " + e); + Slog.w(LOG_TAG, "failed parsing " + file + " " + e); } catch (NumberFormatException e) { - Slog.w(TAG, "failed parsing " + file + " " + e); + Slog.w(LOG_TAG, "failed parsing " + file + " " + e); } catch (XmlPullParserException e) { - Slog.w(TAG, "failed parsing " + file + " " + e); + Slog.w(LOG_TAG, "failed parsing " + file + " " + e); } catch (FileNotFoundException e) { // Don't be noisy, this is normal if we haven't defined any policies. } catch (IOException e) { - Slog.w(TAG, "failed parsing " + file + " " + e); + Slog.w(LOG_TAG, "failed parsing " + file + " " + e); } catch (IndexOutOfBoundsException e) { - Slog.w(TAG, "failed parsing " + file + " " + e); + Slog.w(LOG_TAG, "failed parsing " + file + " " + e); } try { if (stream != null) { @@ -993,7 +1038,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // never normally happen. LockPatternUtils utils = new LockPatternUtils(mContext); if (utils.getActivePasswordQuality() < policy.mActivePasswordQuality) { - Slog.w(TAG, "Active password quality 0x" + Slog.w(LOG_TAG, "Active password quality 0x" + Integer.toHexString(policy.mActivePasswordQuality) + " does not match actual quality 0x" + Integer.toHexString(utils.getActivePasswordQuality())); @@ -1037,7 +1082,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } if (!haveOwner) { - Slog.w(TAG, "Previous password owner " + policy.mPasswordOwner + Slog.w(LOG_TAG, "Previous password owner " + policy.mPasswordOwner + " no longer active; disabling"); policy.mPasswordOwner = -1; } @@ -1057,7 +1102,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { long token = Binder.clearCallingIdentity(); try { String value = cameraDisabled ? "1" : "0"; - if (DBG) Slog.v(TAG, "Change in camera state [" + if (DBG) Slog.v(LOG_TAG, "Change in camera state [" + SYSTEM_PROP_DISABLE_CAMERA + "] = " + value); SystemProperties.set(SYSTEM_PROP_DISABLE_CAMERA, value); } finally { @@ -1173,7 +1218,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (this) { long ident = Binder.clearCallingIdentity(); try { - if (!refreshing && getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null) { + if (!refreshing + && getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null) { throw new IllegalArgumentException("Admin is already added"); } ActiveAdmin newAdmin = new ActiveAdmin(info); @@ -1443,7 +1489,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { ap.passwordExpirationDate = expiration; ap.passwordExpirationTimeout = timeout; if (timeout > 0L) { - Slog.w(TAG, "setPasswordExpiration(): password will expire on " + Slog.w(LOG_TAG, "setPasswordExpiration(): password will expire on " + DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT) .format(new Date(expiration))); } @@ -1789,11 +1835,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return true; } return policy.mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null, userHandle) - && policy.mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null, userHandle) - && policy.mActivePasswordLetters >= getPasswordMinimumLetters(null, userHandle) - && policy.mActivePasswordNumeric >= getPasswordMinimumNumeric(null, userHandle) - && policy.mActivePasswordSymbols >= getPasswordMinimumSymbols(null, userHandle) - && policy.mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null, userHandle); + && policy.mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null, userHandle) + && policy.mActivePasswordLetters >= getPasswordMinimumLetters(null, userHandle) + && policy.mActivePasswordNumeric >= getPasswordMinimumNumeric(null, userHandle) + && policy.mActivePasswordSymbols >= getPasswordMinimumSymbols(null, userHandle) + && policy.mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null, userHandle); } } @@ -1871,7 +1917,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int realQuality = LockPatternUtils.computePasswordQuality(password); if (realQuality < quality && quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) { - Slog.w(TAG, "resetPassword: password quality 0x" + Slog.w(LOG_TAG, "resetPassword: password quality 0x" + Integer.toHexString(realQuality) + " does not meet required quality 0x" + Integer.toHexString(quality)); @@ -1881,7 +1927,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } int length = getPasswordMinimumLength(null, userHandle); if (password.length() < length) { - Slog.w(TAG, "resetPassword: password length " + password.length() + Slog.w(LOG_TAG, "resetPassword: password length " + password.length() + " does not meet required length " + length); return false; } @@ -1910,40 +1956,40 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } int neededLetters = getPasswordMinimumLetters(null, userHandle); if(letters < neededLetters) { - Slog.w(TAG, "resetPassword: number of letters " + letters + Slog.w(LOG_TAG, "resetPassword: number of letters " + letters + " does not meet required number of letters " + neededLetters); return false; } int neededNumbers = getPasswordMinimumNumeric(null, userHandle); if (numbers < neededNumbers) { - Slog.w(TAG, "resetPassword: number of numerical digits " + numbers + Slog.w(LOG_TAG, "resetPassword: number of numerical digits " + numbers + " does not meet required number of numerical digits " + neededNumbers); return false; } int neededLowerCase = getPasswordMinimumLowerCase(null, userHandle); if (lowercase < neededLowerCase) { - Slog.w(TAG, "resetPassword: number of lowercase letters " + lowercase + Slog.w(LOG_TAG, "resetPassword: number of lowercase letters " + lowercase + " does not meet required number of lowercase letters " + neededLowerCase); return false; } int neededUpperCase = getPasswordMinimumUpperCase(null, userHandle); if (uppercase < neededUpperCase) { - Slog.w(TAG, "resetPassword: number of uppercase letters " + uppercase + Slog.w(LOG_TAG, "resetPassword: number of uppercase letters " + uppercase + " does not meet required number of uppercase letters " + neededUpperCase); return false; } int neededSymbols = getPasswordMinimumSymbols(null, userHandle); if (symbols < neededSymbols) { - Slog.w(TAG, "resetPassword: number of special symbols " + symbols + Slog.w(LOG_TAG, "resetPassword: number of special symbols " + symbols + " does not meet required number of special symbols " + neededSymbols); return false; } int neededNonLetter = getPasswordMinimumNonLetter(null, userHandle); if (nonletter < neededNonLetter) { - Slog.w(TAG, "resetPassword: number of non-letter characters " + nonletter + Slog.w(LOG_TAG, "resetPassword: number of non-letter characters " + nonletter + " does not meet required number of non-letter characters " + neededNonLetter); return false; @@ -1954,7 +2000,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int callingUid = Binder.getCallingUid(); DevicePolicyData policy = getUserData(userHandle); if (policy.mPasswordOwner >= 0 && policy.mPasswordOwner != callingUid) { - Slog.w(TAG, "resetPassword: already set by another uid and not entered by user"); + Slog.w(LOG_TAG, "resetPassword: already set by another uid and not entered by user"); return false; } @@ -2020,7 +2066,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { try { getIPowerManager().setMaximumScreenOffTimeoutFromDeviceAdmin((int)timeMs); } catch (RemoteException e) { - Slog.w(TAG, "Failure talking with power manager", e); + Slog.w(LOG_TAG, "Failure talking with power manager", e); } } finally { Binder.restoreCallingIdentity(ident); @@ -2095,10 +2141,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { X509Certificate cert = parseCert(certBuffer); pemCert = Credentials.convertToPem(cert); } catch (CertificateException ce) { - Log.e(TAG, "Problem converting cert", ce); + Log.e(LOG_TAG, "Problem converting cert", ce); return false; } catch (IOException ioe) { - Log.e(TAG, "Problem reading cert", ioe); + Log.e(LOG_TAG, "Problem reading cert", ioe); return false; } try { @@ -2113,7 +2159,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } catch (InterruptedException e1) { - Log.w(TAG, "installCaCertsToKeyChain(): ", e1); + Log.w(LOG_TAG, "installCaCertsToKeyChain(): ", e1); Thread.currentThread().interrupt(); } return false; @@ -2134,10 +2180,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { X509Certificate cert = parseCert(certBuffer); alias = certStore.getCertificateAlias(cert); } catch (CertificateException ce) { - Log.e(TAG, "Problem creating X509Certificate", ce); + Log.e(LOG_TAG, "Problem creating X509Certificate", ce); return; } catch (IOException ioe) { - Log.e(TAG, "Problem reading certificate", ioe); + Log.e(LOG_TAG, "Problem reading certificate", ioe); return; } try { @@ -2146,13 +2192,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { try { service.deleteCaCertificate(alias); } catch (RemoteException e) { - Log.e(TAG, "from CaCertUninstaller: ", e); + Log.e(LOG_TAG, "from CaCertUninstaller: ", e); } finally { keyChainConnection.close(); keyChainConnection = null; } } catch (InterruptedException ie) { - Log.w(TAG, "CaCertUninstaller: ", ie); + Log.w(LOG_TAG, "CaCertUninstaller: ", ie); Thread.currentThread().interrupt(); } } @@ -2173,7 +2219,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { try { RecoverySystem.rebootWipeUserData(mContext); } catch (IOException e) { - Slog.w(TAG, "Failed requesting data wipe", e); + Slog.w(LOG_TAG, "Failed requesting data wipe", e); } } } @@ -2264,8 +2310,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (p.mActivePasswordQuality != quality || p.mActivePasswordLength != length || p.mFailedPasswordAttempts != 0 || p.mActivePasswordLetters != letters || p.mActivePasswordUpperCase != uppercase - || p.mActivePasswordLowerCase != lowercase || p.mActivePasswordNumeric != numbers - || p.mActivePasswordSymbols != symbols || p.mActivePasswordNonLetter != nonletter) { + || p.mActivePasswordLowerCase != lowercase + || p.mActivePasswordNumeric != numbers + || p.mActivePasswordSymbols != symbols + || p.mActivePasswordNonLetter != nonletter) { long ident = Binder.clearCallingIdentity(); try { p.mActivePasswordQuality = quality; @@ -2387,7 +2435,7 @@ 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) { - Slog.w(TAG, "Only the owner is allowed to set the global proxy. User " + Slog.w(LOG_TAG, "Only the owner is allowed to set the global proxy. User " + userHandle + " is not permitted."); return null; } @@ -2468,7 +2516,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { ProxyProperties proxyProperties = new ProxyProperties(data[0], proxyPort, exclusionList); if (!proxyProperties.isValid()) { - Slog.e(TAG, "Invalid proxy properties, ignoring: " + proxyProperties.toString()); + Slog.e(LOG_TAG, "Invalid proxy properties, ignoring: " + proxyProperties.toString()); return; } Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, data[0]); @@ -2494,7 +2542,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // Only owner can set storage encryption if (userHandle != UserHandle.USER_OWNER || UserHandle.getCallingUserId() != UserHandle.USER_OWNER) { - Slog.w(TAG, "Only owner is allowed to set storage encryption. User " + Slog.w(LOG_TAG, "Only owner is allowed to set storage encryption. User " + UserHandle.getCallingUserId() + " is not permitted."); return 0; } @@ -2880,7 +2928,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } catch (NameNotFoundException nnfe) { - Slog.w(TAG, "Device Owner package " + packageName + " not installed."); + Slog.w(LOG_TAG, "Device Owner package " + packageName + " not installed."); } return false; } @@ -2905,9 +2953,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mOwnerName = parser.getAttributeValue(null, ATTR_NAME); input.close(); } catch (XmlPullParserException xppe) { - Slog.e(TAG, "Error parsing device-owner file\n" + xppe); + Slog.e(LOG_TAG, "Error parsing device-owner file\n" + xppe); } catch (IOException ioe) { - Slog.e(TAG, "IO Exception when reading device-owner file\n" + ioe); + Slog.e(LOG_TAG, "IO Exception when reading device-owner file\n" + ioe); } } @@ -2935,7 +2983,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.flush(); file.finishWrite(output); } catch (IOException ioe) { - Slog.e(TAG, "IO Exception when writing device-owner file\n" + ioe); + Slog.e(LOG_TAG, "IO Exception when writing device-owner file\n" + ioe); } } } diff --git a/services/java/Android.mk b/services/java/Android.mk deleted file mode 100644 index 8c3d0f09197c..000000000000 --- a/services/java/Android.mk +++ /dev/null @@ -1,18 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -# the library -# ============================================================ -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - $(call all-subdir-java-files) \ - com/android/server/EventLogTags.logtags \ - com/android/server/am/EventLogTags.logtags - -LOCAL_MODULE:= services - -LOCAL_JAVA_LIBRARIES := android.policy conscrypt telephony-common - -include $(BUILD_JAVA_LIBRARY) - -include $(BUILD_DROIDDOC) diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java deleted file mode 100644 index 203cca692df0..000000000000 --- a/services/java/com/android/server/AppWidgetService.java +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import android.app.ActivityManager; -import android.appwidget.AppWidgetProviderInfo; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.os.Binder; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.UserHandle; -import android.util.Slog; -import android.util.SparseArray; -import android.widget.RemoteViews; - -import com.android.internal.appwidget.IAppWidgetHost; -import com.android.internal.appwidget.IAppWidgetService; -import com.android.internal.os.BackgroundThread; -import com.android.internal.util.IndentingPrintWriter; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.List; -import java.util.Locale; - - -/** - * Redirects calls to this service to the instance of the service for the appropriate user. - */ -class AppWidgetService extends IAppWidgetService.Stub -{ - private static final String TAG = "AppWidgetService"; - - Context mContext; - Locale mLocale; - PackageManager mPackageManager; - boolean mSafeMode; - private final Handler mSaveStateHandler; - - private final SparseArray<AppWidgetServiceImpl> mAppWidgetServices; - - AppWidgetService(Context context) { - mContext = context; - - mSaveStateHandler = BackgroundThread.getHandler(); - - mAppWidgetServices = new SparseArray<AppWidgetServiceImpl>(5); - AppWidgetServiceImpl primary = new AppWidgetServiceImpl(context, 0, mSaveStateHandler); - mAppWidgetServices.append(0, primary); - } - - public void systemRunning(boolean safeMode) { - mSafeMode = safeMode; - - mAppWidgetServices.get(0).systemReady(safeMode); - - // Register for the boot completed broadcast, so we can send the - // ENABLE broacasts. If we try to send them now, they time out, - // because the system isn't ready to handle them yet. - mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, - new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null); - - // Register for configuration changes so we can update the names - // of the widgets when the locale changes. - mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, - new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED), null, null); - - // Register for broadcasts about package install, etc., so we can - // update the provider list. - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_PACKAGE_ADDED); - filter.addAction(Intent.ACTION_PACKAGE_CHANGED); - filter.addAction(Intent.ACTION_PACKAGE_REMOVED); - filter.addDataScheme("package"); - mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, - filter, null, null); - // Register for events related to sdcard installation. - IntentFilter sdFilter = new IntentFilter(); - sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); - sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); - mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, - sdFilter, null, null); - - IntentFilter userFilter = new IntentFilter(); - userFilter.addAction(Intent.ACTION_USER_REMOVED); - userFilter.addAction(Intent.ACTION_USER_STOPPING); - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) { - onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, - UserHandle.USER_NULL)); - } else if (Intent.ACTION_USER_STOPPING.equals(intent.getAction())) { - onUserStopping(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, - UserHandle.USER_NULL)); - } - } - }, userFilter); - } - - @Override - public int allocateAppWidgetId(String packageName, int hostId, int userId) - throws RemoteException { - return getImplForUser(userId).allocateAppWidgetId(packageName, hostId); - } - - @Override - public int[] getAppWidgetIdsForHost(int hostId, int userId) throws RemoteException { - return getImplForUser(userId).getAppWidgetIdsForHost(hostId); - } - - @Override - public void deleteAppWidgetId(int appWidgetId, int userId) throws RemoteException { - getImplForUser(userId).deleteAppWidgetId(appWidgetId); - } - - @Override - public void deleteHost(int hostId, int userId) throws RemoteException { - getImplForUser(userId).deleteHost(hostId); - } - - @Override - public void deleteAllHosts(int userId) throws RemoteException { - getImplForUser(userId).deleteAllHosts(); - } - - @Override - public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options, int userId) - throws RemoteException { - getImplForUser(userId).bindAppWidgetId(appWidgetId, provider, options); - } - - @Override - public boolean bindAppWidgetIdIfAllowed( - String packageName, int appWidgetId, ComponentName provider, Bundle options, int userId) - throws RemoteException { - return getImplForUser(userId).bindAppWidgetIdIfAllowed( - packageName, appWidgetId, provider, options); - } - - @Override - public boolean hasBindAppWidgetPermission(String packageName, int userId) - throws RemoteException { - return getImplForUser(userId).hasBindAppWidgetPermission(packageName); - } - - @Override - public void setBindAppWidgetPermission(String packageName, boolean permission, int userId) - throws RemoteException { - getImplForUser(userId).setBindAppWidgetPermission(packageName, permission); - } - - @Override - public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection, - int userId) throws RemoteException { - getImplForUser(userId).bindRemoteViewsService(appWidgetId, intent, connection); - } - - @Override - public int[] startListening(IAppWidgetHost host, String packageName, int hostId, - List<RemoteViews> updatedViews, int userId) throws RemoteException { - return getImplForUser(userId).startListening(host, packageName, hostId, updatedViews); - } - - public void onUserRemoved(int userId) { - if (userId < 1) return; - synchronized (mAppWidgetServices) { - AppWidgetServiceImpl impl = mAppWidgetServices.get(userId); - mAppWidgetServices.remove(userId); - - if (impl == null) { - AppWidgetServiceImpl.getSettingsFile(userId).delete(); - } else { - impl.onUserRemoved(); - } - } - } - - public void onUserStopping(int userId) { - if (userId < 1) return; - synchronized (mAppWidgetServices) { - AppWidgetServiceImpl impl = mAppWidgetServices.get(userId); - if (impl != null) { - mAppWidgetServices.remove(userId); - impl.onUserStopping(); - } - } - } - - private void checkPermission(int userId) { - int realUserId = ActivityManager.handleIncomingUser( - Binder.getCallingPid(), - Binder.getCallingUid(), - userId, - false, /* allowAll */ - true, /* requireFull */ - this.getClass().getSimpleName(), - this.getClass().getPackage().getName()); - } - - private AppWidgetServiceImpl getImplForUser(int userId) { - checkPermission(userId); - boolean sendInitial = false; - AppWidgetServiceImpl service; - synchronized (mAppWidgetServices) { - service = mAppWidgetServices.get(userId); - if (service == null) { - Slog.i(TAG, "Unable to find AppWidgetServiceImpl for user " + userId + ", adding"); - // TODO: Verify that it's a valid user - service = new AppWidgetServiceImpl(mContext, userId, mSaveStateHandler); - service.systemReady(mSafeMode); - // Assume that BOOT_COMPLETED was received, as this is a non-primary user. - mAppWidgetServices.append(userId, service); - sendInitial = true; - } - } - if (sendInitial) { - service.sendInitialBroadcasts(); - } - return service; - } - - @Override - public int[] getAppWidgetIds(ComponentName provider, int userId) throws RemoteException { - return getImplForUser(userId).getAppWidgetIds(provider); - } - - @Override - public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId, int userId) - throws RemoteException { - return getImplForUser(userId).getAppWidgetInfo(appWidgetId); - } - - @Override - public RemoteViews getAppWidgetViews(int appWidgetId, int userId) throws RemoteException { - return getImplForUser(userId).getAppWidgetViews(appWidgetId); - } - - @Override - public void updateAppWidgetOptions(int appWidgetId, Bundle options, int userId) { - getImplForUser(userId).updateAppWidgetOptions(appWidgetId, options); - } - - @Override - public Bundle getAppWidgetOptions(int appWidgetId, int userId) { - return getImplForUser(userId).getAppWidgetOptions(appWidgetId); - } - - @Override - public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter, int userId) - throws RemoteException { - return getImplForUser(userId).getInstalledProviders(categoryFilter); - } - - @Override - public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId, int userId) - throws RemoteException { - getImplForUser(userId).notifyAppWidgetViewDataChanged( - appWidgetIds, viewId); - } - - @Override - public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId) - throws RemoteException { - getImplForUser(userId).partiallyUpdateAppWidgetIds( - appWidgetIds, views); - } - - @Override - public void stopListening(int hostId, int userId) throws RemoteException { - getImplForUser(userId).stopListening(hostId); - } - - @Override - public void unbindRemoteViewsService(int appWidgetId, Intent intent, int userId) - throws RemoteException { - getImplForUser(userId).unbindRemoteViewsService( - appWidgetId, intent); - } - - @Override - public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId) - throws RemoteException { - getImplForUser(userId).updateAppWidgetIds(appWidgetIds, views); - } - - @Override - public void updateAppWidgetProvider(ComponentName provider, RemoteViews views, int userId) - throws RemoteException { - getImplForUser(userId).updateAppWidgetProvider(provider, views); - } - - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); - - // Dump the state of all the app widget providers - synchronized (mAppWidgetServices) { - IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); - for (int i = 0; i < mAppWidgetServices.size(); i++) { - pw.println("User: " + mAppWidgetServices.keyAt(i)); - ipw.increaseIndent(); - AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); - service.dump(fd, ipw, args); - ipw.decreaseIndent(); - } - } - } - - BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - // Slog.d(TAG, "received " + action); - if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { - int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); - if (userId >= 0) { - getImplForUser(userId).sendInitialBroadcasts(); - } else { - Slog.w(TAG, "Incorrect user handle supplied in " + intent); - } - } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) { - for (int i = 0; i < mAppWidgetServices.size(); i++) { - AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); - service.onConfigurationChanged(); - } - } else { - int sendingUser = getSendingUserId(); - if (sendingUser == UserHandle.USER_ALL) { - for (int i = 0; i < mAppWidgetServices.size(); i++) { - AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); - service.onBroadcastReceived(intent); - } - } else { - AppWidgetServiceImpl service = mAppWidgetServices.get(sendingUser); - if (service != null) { - service.onBroadcastReceived(intent); - } - } - } - } - }; -} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index a42cbcfe0d64..db40cbe499c9 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -17,6 +17,9 @@ package com.android.server; import android.app.ActivityManagerNative; +import android.app.ActivityThread; +import android.app.IAlarmManager; +import android.app.INotificationManager; import android.bluetooth.BluetoothAdapter; import android.content.ComponentName; import android.content.ContentResolver; @@ -28,8 +31,10 @@ import android.content.res.Configuration; import android.media.AudioService; import android.net.wifi.p2p.WifiP2pService; import android.os.Environment; +import android.os.FactoryTest; import android.os.Handler; -import android.os.HandlerThread; +import android.os.IBinder; +import android.os.IPowerManager; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; @@ -47,26 +52,32 @@ import android.view.WindowManager; import com.android.internal.R; import com.android.internal.os.BinderInternal; import com.android.internal.os.SamplingProfilerIntegration; -import com.android.server.accessibility.AccessibilityManagerService; import com.android.server.accounts.AccountManagerService; import com.android.server.am.ActivityManagerService; import com.android.server.am.BatteryStatsService; +import com.android.server.clipboard.ClipboardService; import com.android.server.content.ContentService; import com.android.server.display.DisplayManagerService; import com.android.server.dreams.DreamManagerService; import com.android.server.input.InputManagerService; +import com.android.server.lights.LightsManager; +import com.android.server.lights.LightsService; import com.android.server.media.MediaRouterService; import com.android.server.net.NetworkPolicyManagerService; import com.android.server.net.NetworkStatsService; +import com.android.server.notification.NotificationManagerService; import com.android.server.os.SchedulingPolicyService; import com.android.server.pm.Installer; import com.android.server.pm.PackageManagerService; import com.android.server.pm.UserManagerService; import com.android.server.power.PowerManagerService; import com.android.server.power.ShutdownThread; -import com.android.server.print.PrintManagerService; import com.android.server.search.SearchManagerService; +import com.android.server.statusbar.StatusBarManagerService; +import com.android.server.storage.DeviceStorageMonitorService; +import com.android.server.twilight.TwilightService; import com.android.server.usb.UsbService; +import com.android.server.wallpaper.WallpaperManagerService; import com.android.server.wifi.WifiService; import com.android.server.wm.WindowManagerService; @@ -77,62 +88,212 @@ import java.io.File; import java.util.Timer; import java.util.TimerTask; -class ServerThread { +public final class SystemServer { private static final String TAG = "SystemServer"; + private static final String ENCRYPTING_STATE = "trigger_restart_min_framework"; private static final String ENCRYPTED_STATE = "1"; - ContentResolver mContentResolver; + private static final long SNAPSHOT_INTERVAL = 60 * 60 * 1000; // 1hr - void reportWtf(String msg, Throwable e) { - Slog.w(TAG, "***********************************************"); - Log.wtf(TAG, "BOOT FAILURE " + msg, e); + // The earliest supported time. We pick one day into 1970, to + // give any timezone code room without going into negative time. + private static final long EARLIEST_SUPPORTED_TIME = 86400 * 1000; + + /* + * Implementation class names. TODO: Move them to a codegen class or load + * them from the build system somehow. + */ + private static final String BACKUP_MANAGER_SERVICE_CLASS = + "com.android.server.backup.BackupManagerService$Lifecycle"; + private static final String DEVICE_POLICY_MANAGER_SERVICE_CLASS = + "com.android.server.devicepolicy.DevicePolicyManagerService$Lifecycle"; + private static final String APPWIDGET_SERVICE_CLASS = + "com.android.server.appwidget.AppWidgetService"; + private static final String PRINT_MANAGER_SERVICE_CLASS = + "com.android.server.print.PrintManagerService"; + private static final String USB_SERVICE_CLASS = + "com.android.server.usb.UsbService$Lifecycle"; + + private final int mFactoryTestMode; + private Timer mProfilerSnapshotTimer; + + private Context mSystemContext; + private SystemServiceManager mSystemServiceManager; + + // TODO: remove all of these references by improving dependency resolution and boot phases + private Installer mInstaller; + private PowerManagerService mPowerManagerService; + private ActivityManagerService mActivityManagerService; + private DisplayManagerService mDisplayManagerService; + private ContentResolver mContentResolver; + + /** + * Called to initialize native system services. + */ + private static native void nativeInit(); + + /** + * The main entry point from zygote. + */ + public static void main(String[] args) { + new SystemServer().run(); } - public void initAndLoop() { - EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, - SystemClock.uptimeMillis()); + public SystemServer() { + mFactoryTestMode = FactoryTest.getMode(); + } - Looper.prepareMainLooper(); + private void run() { + // If a device's clock is before 1970 (before 0), a lot of + // APIs crash dealing with negative numbers, notably + // java.io.File#setLastModified, so instead we fake it and + // hope that time from cell towers or NTP fixes it shortly. + if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { + Slog.w(TAG, "System clock is before 1970; setting to 1970."); + SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); + } - android.os.Process.setThreadPriority( - android.os.Process.THREAD_PRIORITY_FOREGROUND); + // Here we go! + Slog.i(TAG, "Entered the Android system server!"); + EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis()); + + // In case the runtime switched since last boot (such as when + // the old runtime was removed in an OTA), set the system + // property so that it is in sync. We can't do this in + // libnativehelper's JniInvocation::Init code where we already + // had to fallback to a different runtime because it is + // running as root and we need to be the system user to set + // the property. http://b/11463182 + SystemProperties.set("persist.sys.dalvik.vm.lib", VMRuntime.getRuntime().vmLibrary()); + + // Enable the sampling profiler. + if (SamplingProfilerIntegration.isEnabled()) { + SamplingProfilerIntegration.start(); + mProfilerSnapshotTimer = new Timer(); + mProfilerSnapshotTimer.schedule(new TimerTask() { + @Override + public void run() { + SamplingProfilerIntegration.writeSnapshot("system_server", null); + } + }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL); + } + + // Mmmmmm... more memory! + VMRuntime.getRuntime().clearGrowthLimit(); + + // The system server has to run all of the time, so it needs to be + // as efficient as possible with its memory usage. + VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); + // Within the system server, it is an error to access Environment paths without + // explicitly specifying a user. + Environment.setUserRequired(true); + + // Ensure binder calls into the system always run at foreground priority. BinderInternal.disableBackgroundScheduling(true); + + // Prepare the main looper thread (this thread). + android.os.Process.setThreadPriority( + android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); + Looper.prepareMainLooper(); + + // Initialize native services. + System.loadLibrary("android_servers"); + nativeInit(); // Check whether we failed to shut down last time we tried. - { - final String shutdownAction = SystemProperties.get( - ShutdownThread.SHUTDOWN_ACTION_PROPERTY, ""); - if (shutdownAction != null && shutdownAction.length() > 0) { - boolean reboot = (shutdownAction.charAt(0) == '1'); - - final String reason; - if (shutdownAction.length() > 1) { - reason = shutdownAction.substring(1, shutdownAction.length()); - } else { - reason = null; - } + // This call may not return. + performPendingShutdown(); + + // Initialize the system context. + createSystemContext(); + + // Create the system service manager. + mSystemServiceManager = new SystemServiceManager(mSystemContext); + LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); - ShutdownThread.rebootOrShutdown(reboot, reason); + // Start services. + try { + startBootstrapServices(); + startCoreServices(); + startOtherServices(); + } catch (RuntimeException ex) { + Slog.e("System", "******************************************"); + Slog.e("System", "************ Failure starting system services", ex); + throw ex; + } + + // For debug builds, log event loop stalls to dropbox for analysis. + if (StrictMode.conditionallyEnableDebugLogging()) { + Slog.i(TAG, "Enabled StrictMode for system server main thread."); + } + + // Loop forever. + Looper.loop(); + throw new RuntimeException("Main thread loop unexpectedly exited"); + } + + private void reportWtf(String msg, Throwable e) { + Slog.w(TAG, "***********************************************"); + Log.wtf(TAG, "BOOT FAILURE " + msg, e); + } + + private void performPendingShutdown() { + final String shutdownAction = SystemProperties.get( + ShutdownThread.SHUTDOWN_ACTION_PROPERTY, ""); + if (shutdownAction != null && shutdownAction.length() > 0) { + boolean reboot = (shutdownAction.charAt(0) == '1'); + + final String reason; + if (shutdownAction.length() > 1) { + reason = shutdownAction.substring(1, shutdownAction.length()); + } else { + reason = null; } + + ShutdownThread.rebootOrShutdown(reboot, reason); } + } - String factoryTestStr = SystemProperties.get("ro.factorytest"); - int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF - : Integer.parseInt(factoryTestStr); - final boolean headless = "1".equals(SystemProperties.get("ro.config.headless", "0")); + private void createSystemContext() { + ActivityThread activityThread = ActivityThread.systemMain(); + mSystemContext = activityThread.getSystemContext(); + mSystemContext.setTheme(android.R.style.Theme_Holo); + } + + private void startBootstrapServices() { + // Wait for installd to finish starting up so that it has a chance to + // create critical directories such as /data/user with the appropriate + // permissions. We need this to complete before we initialize other services. + mInstaller = mSystemServiceManager.startService(Installer.class); + + // Power manager needs to be started early because other services need it. + // TODO: The conversion to the new pattern is incomplete. We need to switch + // the power manager's dependencies over then we can use boot phases to arrange + // initialization order and remove the mPowerManagerService field. + mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class); + + // Activity manager runs the show. + mActivityManagerService = mSystemServiceManager.startService( + ActivityManagerService.Lifecycle.class).getService(); + } - Installer installer = null; + private void startCoreServices() { + // Display manager is needed to provide display metrics before package manager + // starts up. + mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class); + } + + private void startOtherServices() { + final Context context = mSystemContext; AccountManagerService accountManager = null; ContentService contentService = null; - LightsService lights = null; - PowerManagerService power = null; - DisplayManagerService display = null; + LightsManager lights = null; BatteryService battery = null; VibratorService vibrator = null; - AlarmManagerService alarm = null; + IAlarmManager alarm = null; MountService mountService = null; NetworkManagementService networkManagement = null; NetworkStatsService networkStats = null; @@ -142,14 +303,11 @@ class ServerThread { WifiService wifi = null; NsdService serviceDiscovery= null; IPackageManager pm = null; - Context context = null; WindowManagerService wm = null; BluetoothManagerService bluetooth = null; DockObserver dock = null; UsbService usb = null; SerialService serial = null; - TwilightService twilight = null; - UiModeManagerService uiMode = null; RecognitionManagerService recognition = null; NetworkTimeUpdateService networkTimeUpdater = null; CommonTimeManagementService commonTimeMgmtService = null; @@ -157,48 +315,8 @@ class ServerThread { TelephonyRegistry telephonyRegistry = null; ConsumerIrService consumerIr = null; - // Create a handler thread just for the window manager to enjoy. - HandlerThread wmHandlerThread = new HandlerThread("WindowManager"); - wmHandlerThread.start(); - Handler wmHandler = new Handler(wmHandlerThread.getLooper()); - wmHandler.post(new Runnable() { - @Override - public void run() { - //Looper.myLooper().setMessageLogging(new LogPrinter( - // android.util.Log.DEBUG, TAG, android.util.Log.LOG_ID_SYSTEM)); - android.os.Process.setThreadPriority( - android.os.Process.THREAD_PRIORITY_DISPLAY); - android.os.Process.setCanSelfBackground(false); - - // For debug builds, log event loop stalls to dropbox for analysis. - if (StrictMode.conditionallyEnableDebugLogging()) { - Slog.i(TAG, "Enabled StrictMode logging for WM Looper"); - } - } - }); - - // bootstrap services boolean onlyCore = false; boolean firstBoot = false; - try { - // Wait for installd to finished starting up so that it has a chance to - // create critical directories such as /data/user with the appropriate - // permissions. We need this to complete before we initialize other services. - Slog.i(TAG, "Waiting for installd to be ready."); - installer = new Installer(); - installer.ping(); - - Slog.i(TAG, "Power Manager"); - power = new PowerManagerService(); - ServiceManager.addService(Context.POWER_SERVICE, power); - - Slog.i(TAG, "Activity Manager"); - context = ActivityManagerService.main(factoryTest); - } catch (RuntimeException e) { - Slog.e("System", "******************************************"); - Slog.e("System", "************ Failure starting bootstrap service", e); - } - boolean disableStorage = SystemProperties.getBoolean("config.disable_storage", false); boolean disableMedia = SystemProperties.getBoolean("config.disable_media", false); boolean disableBluetooth = SystemProperties.getBoolean("config.disable_bluetooth", false); @@ -209,10 +327,6 @@ class ServerThread { boolean disableNetwork = SystemProperties.getBoolean("config.disable_network", false); try { - Slog.i(TAG, "Display Manager"); - display = new DisplayManagerService(context, wmHandler); - ServiceManager.addService(Context.DISPLAY_SERVICE, display, true); - Slog.i(TAG, "Telephony Registry"); telephonyRegistry = new TelephonyRegistry(context); ServiceManager.addService("telephony.registry", telephonyRegistry); @@ -222,10 +336,8 @@ class ServerThread { AttributeCache.init(context); - if (!display.waitForDefaultDisplay()) { - reportWtf("Timeout waiting for default display to be initialized.", - new Throwable()); - } + // We need the default display before we can initialize the package manager. + mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY); Slog.i(TAG, "Package Manager"); // Only run "core" apps if we're encrypting the device. @@ -238,15 +350,15 @@ class ServerThread { onlyCore = true; } - pm = PackageManagerService.main(context, installer, - factoryTest != SystemServer.FACTORY_TEST_OFF, + pm = PackageManagerService.main(context, mInstaller, + mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, onlyCore); try { firstBoot = pm.isFirstBoot(); } catch (RemoteException e) { } - ActivityManagerService.setSystemProcess(); + mActivityManagerService.setSystemProcess(); Slog.i(TAG, "Entropy Mixer"); ServiceManager.addService("entropy", new EntropyMixer(context)); @@ -269,13 +381,13 @@ class ServerThread { Slog.i(TAG, "Content Manager"); contentService = ContentService.main(context, - factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL); + mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL); Slog.i(TAG, "System Content Providers"); - ActivityManagerService.installSystemProviders(); + mActivityManagerService.installSystemProviders(); - Slog.i(TAG, "Lights Service"); - lights = new LightsService(context); + mSystemServiceManager.startService(LightsService.class); + lights = LocalServices.getService(LightsManager.class); Slog.i(TAG, "Battery Service"); battery = new BatteryService(context, lights); @@ -285,49 +397,49 @@ class ServerThread { vibrator = new VibratorService(context); ServiceManager.addService("vibrator", vibrator); - Slog.i(TAG, "Consumer IR Service"); - consumerIr = new ConsumerIrService(context); - ServiceManager.addService(Context.CONSUMER_IR_SERVICE, consumerIr); - + // TODO: use boot phase // only initialize the power service after we have started the // lights service, content providers and the battery service. - power.init(context, lights, ActivityManagerService.self(), battery, + mPowerManagerService.init(lights, battery, BatteryStatsService.getService(), - ActivityManagerService.self().getAppOpsService(), display); + mActivityManagerService.getAppOpsService()); + + Slog.i(TAG, "Consumer IR Service"); + consumerIr = new ConsumerIrService(context); + ServiceManager.addService(Context.CONSUMER_IR_SERVICE, consumerIr); - Slog.i(TAG, "Alarm Manager"); - alarm = new AlarmManagerService(context); - ServiceManager.addService(Context.ALARM_SERVICE, alarm); + mSystemServiceManager.startService(AlarmManagerService.class); + alarm = IAlarmManager.Stub.asInterface( + ServiceManager.getService(Context.ALARM_SERVICE)); Slog.i(TAG, "Init Watchdog"); - Watchdog.getInstance().init(context, battery, power, alarm, - ActivityManagerService.self()); - Watchdog.getInstance().addThread(wmHandler, "WindowManager thread"); + final Watchdog watchdog = Watchdog.getInstance(); + watchdog.init(context, mActivityManagerService); Slog.i(TAG, "Input Manager"); - inputManager = new InputManagerService(context, wmHandler); + inputManager = new InputManagerService(context); Slog.i(TAG, "Window Manager"); - wm = WindowManagerService.main(context, power, display, inputManager, - wmHandler, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL, + wm = WindowManagerService.main(context, inputManager, + mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL, !firstBoot, onlyCore); ServiceManager.addService(Context.WINDOW_SERVICE, wm); ServiceManager.addService(Context.INPUT_SERVICE, inputManager); - ActivityManagerService.self().setWindowManager(wm); + mActivityManagerService.setWindowManager(wm); inputManager.setWindowManagerCallbacks(wm.getInputMonitor()); inputManager.start(); - display.setWindowManager(wm); - display.setInputManager(inputManager); + // TODO: Use service dependencies instead. + mDisplayManagerService.windowManagerAndInputReady(); // Skip Bluetooth if we have an emulator kernel // TODO: Use a more reliable check to see if this product should // support Bluetooth - see bug 988521 if (SystemProperties.get("ro.kernel.qemu").equals("1")) { Slog.i(TAG, "No Bluetooh Service (emulator)"); - } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) { + } else if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) { Slog.i(TAG, "No Bluetooth Service (factory test)"); } else if (!context.getPackageManager().hasSystemFeature (PackageManager.FEATURE_BLUETOOTH)) { @@ -344,23 +456,19 @@ class ServerThread { Slog.e("System", "************ Failure starting core service", e); } - DevicePolicyManagerService devicePolicy = null; StatusBarManagerService statusBar = null; + INotificationManager notification = null; InputMethodManagerService imm = null; - AppWidgetService appWidget = null; - NotificationManagerService notification = null; WallpaperManagerService wallpaper = null; LocationManagerService location = null; CountryDetectorService countryDetector = null; TextServicesManagerService tsms = null; LockSettingsService lockSettings = null; - DreamManagerService dreamy = null; AssetAtlasService atlas = null; - PrintManagerService printManager = null; MediaRouterService mediaRouter = null; // Bring up services needed for UI. - if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { + if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) { //if (!disableNonCoreServices) { // TODO: View depends on these; mock them? if (true) { try { @@ -373,8 +481,8 @@ class ServerThread { try { Slog.i(TAG, "Accessibility Manager"); - ServiceManager.addService(Context.ACCESSIBILITY_SERVICE, - new AccessibilityManagerService(context)); + ServiceManager.addService(Context.ACCESSIBILITY_SERVICE, (IBinder) + getClass().getClassLoader().loadClass("com.android.server.accessibility.AccessibilityManagerService").getConstructor(Context.class).newInstance(context)); } catch (Throwable e) { reportWtf("starting Accessibility Manager", e); } @@ -397,11 +505,11 @@ class ServerThread { ActivityManagerNative.getDefault().showBootMessage( context.getResources().getText( com.android.internal.R.string.android_upgrading_starting_apps), - false); + false); } catch (RemoteException e) { } - if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { + if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) { if (!disableStorage && !"0".equals(SystemProperties.get("system_init.startmountservice"))) { try { @@ -427,9 +535,9 @@ class ServerThread { } try { - Slog.i(TAG, "Device Policy"); - devicePolicy = new DevicePolicyManagerService(context); - ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy); + if (pm.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)) { + mSystemServiceManager.startService(DEVICE_POLICY_MANAGER_SERVICE_CLASS); + } } catch (Throwable e) { reportWtf("starting DevicePolicyService", e); } @@ -487,7 +595,8 @@ class ServerThread { try { Slog.i(TAG, "NetworkPolicy Service"); networkPolicy = new NetworkPolicyManagerService( - context, ActivityManagerService.self(), power, + context, mActivityManagerService, + (IPowerManager)ServiceManager.getService(Context.POWER_SERVICE), networkStats, networkManagement); ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy); } catch (Throwable e) { @@ -567,22 +676,12 @@ class ServerThread { reportWtf("making Content Service ready", e); } - try { - Slog.i(TAG, "Notification Manager"); - notification = new NotificationManagerService(context, statusBar, lights); - ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification); - networkPolicy.bindNotificationManager(notification); - } catch (Throwable e) { - reportWtf("starting Notification Manager", e); - } + mSystemServiceManager.startService(NotificationManagerService.class); + notification = INotificationManager.Stub.asInterface( + ServiceManager.getService(Context.NOTIFICATION_SERVICE)); + networkPolicy.bindNotificationManager(notification); - try { - Slog.i(TAG, "Device Storage Monitor"); - ServiceManager.addService(DeviceStorageMonitorService.SERVICE, - new DeviceStorageMonitorService(context)); - } catch (Throwable e) { - reportWtf("starting DeviceStorageMonitor service", e); - } + mSystemServiceManager.startService(DeviceStorageMonitorService.class); if (!disableLocation) { try { @@ -624,10 +723,8 @@ class ServerThread { R.bool.config_enableWallpaperService)) { try { Slog.i(TAG, "Wallpaper Service"); - if (!headless) { - wallpaper = new WallpaperManagerService(context); - ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper); - } + wallpaper = new WallpaperManagerService(context); + ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper); } catch (Throwable e) { reportWtf("starting Wallpaper Service", e); } @@ -665,10 +762,11 @@ class ServerThread { if (!disableNonCoreServices) { try { - Slog.i(TAG, "USB Service"); - // Manage USB host and device support - usb = new UsbService(context); - ServiceManager.addService(Context.USB_SERVICE, usb); + if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST) || + pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY)) { + // Manage USB host and device support + mSystemServiceManager.startService(USB_SERVICE_CLASS); + } } catch (Throwable e) { reportWtf("starting UsbService", e); } @@ -683,34 +781,23 @@ class ServerThread { } } - try { - Slog.i(TAG, "Twilight Service"); - twilight = new TwilightService(context); - } catch (Throwable e) { - reportWtf("starting TwilightService", e); - } + mSystemServiceManager.startService(TwilightService.class); - try { - Slog.i(TAG, "UI Mode Manager Service"); - // Listen for UI mode changes - uiMode = new UiModeManagerService(context, twilight); - } catch (Throwable e) { - reportWtf("starting UiModeManagerService", e); - } + mSystemServiceManager.startService(UiModeManagerService.class); if (!disableNonCoreServices) { try { - Slog.i(TAG, "Backup Service"); - ServiceManager.addService(Context.BACKUP_SERVICE, - new BackupManagerService(context)); + if (pm.hasSystemFeature(PackageManager.FEATURE_BACKUP)) { + mSystemServiceManager.startService(BACKUP_MANAGER_SERVICE_CLASS); + } } catch (Throwable e) { Slog.e(TAG, "Failure starting Backup Service", e); } try { - Slog.i(TAG, "AppWidget Service"); - appWidget = new AppWidgetService(context); - ServiceManager.addService(Context.APPWIDGET_SERVICE, appWidget); + if (pm.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) { + mSystemServiceManager.startService(APPWIDGET_SERVICE_CLASS); + } } catch (Throwable e) { reportWtf("starting AppWidget Service", e); } @@ -770,16 +857,9 @@ class ServerThread { } } - if (!disableNonCoreServices && - context.getResources().getBoolean(R.bool.config_dreamsSupported)) { - try { - Slog.i(TAG, "Dreams Service"); - // Dreams (interactive idle-time views, a/k/a screen savers) - dreamy = new DreamManagerService(context, wmHandler); - ServiceManager.addService(DreamService.DREAM_SERVICE, dreamy); - } catch (Throwable e) { - reportWtf("starting DreamManagerService", e); - } + if (!disableNonCoreServices) { + // Dreams (interactive idle-time views, a/k/a screen savers, and doze mode) + mSystemServiceManager.startService(DreamManagerService.class); } if (!disableNonCoreServices) { @@ -800,9 +880,9 @@ class ServerThread { } try { - Slog.i(TAG, "Print Service"); - printManager = new PrintManagerService(context); - ServiceManager.addService(Context.PRINT_SERVICE, printManager); + if (pm.hasSystemFeature(PackageManager.FEATURE_PRINTING)) { + mSystemServiceManager.startService(PRINT_MANAGER_SERVICE_CLASS); + } } catch (Throwable e) { reportWtf("starting Print Service", e); } @@ -822,7 +902,7 @@ class ServerThread { // we are in safe mode. final boolean safeMode = wm.detectSafeMode(); if (safeMode) { - ActivityManagerService.self().enterSafeMode(); + mActivityManagerService.enterSafeMode(); // Post the safe mode state in the Zygote class Zygote.systemInSafeMode = true; // Disable the JIT for the system_server process @@ -848,21 +928,10 @@ class ServerThread { } } - if (devicePolicy != null) { - try { - devicePolicy.systemReady(); - } catch (Throwable e) { - reportWtf("making Device Policy Service ready", e); - } - } + // Needed by DevicePolicyManager for initialization + mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY); - if (notification != null) { - try { - notification.systemReady(); - } catch (Throwable e) { - reportWtf("making Notification Service ready", e); - } - } + mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); try { wm.systemReady(); @@ -871,7 +940,7 @@ class ServerThread { } if (safeMode) { - ActivityManagerService.self().showSafeModeOverlay(); + mActivityManagerService.showSafeModeOverlay(); } // Update the configuration for this context by hand, because we're going @@ -884,7 +953,8 @@ class ServerThread { context.getResources().updateConfiguration(config, metrics); try { - power.systemReady(twilight, dreamy); + // TODO: use boot phase + mPowerManagerService.systemReady(); } catch (Throwable e) { reportWtf("making Power Manager Service ready", e); } @@ -896,13 +966,13 @@ class ServerThread { } try { - display.systemReady(safeMode, onlyCore); + // TODO: use boot phase and communicate these flags some other way + mDisplayManagerService.systemReady(safeMode, onlyCore); } catch (Throwable e) { reportWtf("making Display Manager Service ready", e); } // These are needed to propagate to the runnable below. - final Context contextF = context; final MountService mountServiceF = mountService; final BatteryService batteryF = battery; final NetworkManagementService networkManagementF = networkManagement; @@ -910,10 +980,6 @@ class ServerThread { final NetworkPolicyManagerService networkPolicyF = networkPolicy; final ConnectivityService connectivityF = connectivity; final DockObserver dockF = dock; - final UsbService usbF = usb; - final TwilightService twilightF = twilight; - final UiModeManagerService uiModeF = uiMode; - final AppWidgetService appWidgetF = appWidget; final WallpaperManagerService wallpaperF = wallpaper; final InputMethodManagerService immF = imm; final RecognitionManagerService recognitionF = recognition; @@ -923,11 +989,9 @@ class ServerThread { final CommonTimeManagementService commonTimeMgmtServiceF = commonTimeMgmtService; final TextServicesManagerService textServiceManagerServiceF = tsms; final StatusBarManagerService statusBarF = statusBar; - final DreamManagerService dreamyF = dreamy; final AssetAtlasService atlasF = atlas; final InputManagerService inputManagerF = inputManager; final TelephonyRegistry telephonyRegistryF = telephonyRegistry; - final PrintManagerService printManagerF = printManager; final MediaRouterService mediaRouterF = mediaRouter; // We now tell the activity manager it is okay to run third party @@ -935,17 +999,22 @@ class ServerThread { // where third party code can really run (but before it has actually // started launching the initial applications), for us to complete our // initialization. - ActivityManagerService.self().systemReady(new Runnable() { + mActivityManagerService.systemReady(new Runnable() { + @Override public void run() { Slog.i(TAG, "Making services ready"); + mSystemServiceManager.startBootPhase( + SystemService.PHASE_ACTIVITY_MANAGER_READY); try { - ActivityManagerService.self().startObservingNativeCrashes(); + mActivityManagerService.startObservingNativeCrashes(); } catch (Throwable e) { reportWtf("observing native crashes", e); } - if (!headless) { - startSystemUi(contextF); + try { + startSystemUi(context); + } catch (Throwable e) { + reportWtf("starting System UI", e); } try { if (mountServiceF != null) mountServiceF.systemReady(); @@ -983,21 +1052,6 @@ class ServerThread { reportWtf("making Dock Service ready", e); } try { - if (usbF != null) usbF.systemReady(); - } catch (Throwable e) { - reportWtf("making USB Service ready", e); - } - try { - if (twilightF != null) twilightF.systemReady(); - } catch (Throwable e) { - reportWtf("makin Twilight Service ready", e); - } - try { - if (uiModeF != null) uiModeF.systemReady(); - } catch (Throwable e) { - reportWtf("making UI Mode Service ready", e); - } - try { if (recognitionF != null) recognitionF.systemReady(); } catch (Throwable e) { reportWtf("making Recognition Service ready", e); @@ -1006,13 +1060,10 @@ class ServerThread { // It is now okay to let the various system services start their // third party code... + mSystemServiceManager.startBootPhase( + SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); try { - if (appWidgetF != null) appWidgetF.systemRunning(safeMode); - } catch (Throwable e) { - reportWtf("Notifying AppWidgetService running", e); - } - try { if (wallpaperF != null) wallpaperF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying WallpaperService running", e); @@ -1038,7 +1089,9 @@ class ServerThread { reportWtf("Notifying NetworkTimeService running", e); } try { - if (commonTimeMgmtServiceF != null) commonTimeMgmtServiceF.systemRunning(); + if (commonTimeMgmtServiceF != null) { + commonTimeMgmtServiceF.systemRunning(); + } } catch (Throwable e) { reportWtf("Notifying CommonTimeManagementService running", e); } @@ -1049,11 +1102,6 @@ class ServerThread { reportWtf("Notifying TextServicesManagerService running", e); } try { - if (dreamyF != null) dreamyF.systemRunning(); - } catch (Throwable e) { - reportWtf("Notifying DreamManagerService running", e); - } - try { if (atlasF != null) atlasF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying AssetAtlasService running", e); @@ -1064,34 +1112,20 @@ class ServerThread { } catch (Throwable e) { reportWtf("Notifying InputManagerService running", e); } - try { if (telephonyRegistryF != null) telephonyRegistryF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying TelephonyRegistry running", e); } - - try { - if (printManagerF != null) printManagerF.systemRuning(); - } catch (Throwable e) { - reportWtf("Notifying PrintManagerService running", e); - } - try { if (mediaRouterF != null) mediaRouterF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying MediaRouterService running", e); } + + mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETE); } }); - - // For debug builds, log event loop stalls to dropbox for analysis. - if (StrictMode.conditionallyEnableDebugLogging()) { - Slog.i(TAG, "Enabled StrictMode for system server main thread."); - } - - Looper.loop(); - Slog.d(TAG, "System ServerThread is exiting!"); } static final void startSystemUi(Context context) { @@ -1102,80 +1136,3 @@ class ServerThread { context.startServiceAsUser(intent, UserHandle.OWNER); } } - -public class SystemServer { - private static final String TAG = "SystemServer"; - - public static final int FACTORY_TEST_OFF = 0; - public static final int FACTORY_TEST_LOW_LEVEL = 1; - public static final int FACTORY_TEST_HIGH_LEVEL = 2; - - static Timer timer; - static final long SNAPSHOT_INTERVAL = 60 * 60 * 1000; // 1hr - - // The earliest supported time. We pick one day into 1970, to - // give any timezone code room without going into negative time. - private static final long EARLIEST_SUPPORTED_TIME = 86400 * 1000; - - /** - * Called to initialize native system services. - */ - private static native void nativeInit(); - - public static void main(String[] args) { - - /* - * In case the runtime switched since last boot (such as when - * the old runtime was removed in an OTA), set the system - * property so that it is in sync. We can't do this in - * libnativehelper's JniInvocation::Init code where we already - * had to fallback to a different runtime because it is - * running as root and we need to be the system user to set - * the property. http://b/11463182 - */ - SystemProperties.set("persist.sys.dalvik.vm.lib", - VMRuntime.getRuntime().vmLibrary()); - - if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { - // If a device's clock is before 1970 (before 0), a lot of - // APIs crash dealing with negative numbers, notably - // java.io.File#setLastModified, so instead we fake it and - // hope that time from cell towers or NTP fixes it - // shortly. - Slog.w(TAG, "System clock is before 1970; setting to 1970."); - SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); - } - - if (SamplingProfilerIntegration.isEnabled()) { - SamplingProfilerIntegration.start(); - timer = new Timer(); - timer.schedule(new TimerTask() { - @Override - public void run() { - SamplingProfilerIntegration.writeSnapshot("system_server", null); - } - }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL); - } - - // Mmmmmm... more memory! - dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); - - // The system server has to run all of the time, so it needs to be - // as efficient as possible with its memory usage. - VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); - - Environment.setUserRequired(true); - - System.loadLibrary("android_servers"); - - Slog.i(TAG, "Entered the Android system server!"); - - // Initialize native services. - nativeInit(); - - // This used to be its own separate thread, but now it is - // just the loop we run on the main thread. - ServerThread thr = new ServerThread(); - thr.initAndLoop(); - } -} diff --git a/services/java/com/android/server/display/HeadlessDisplayAdapter.java b/services/java/com/android/server/display/HeadlessDisplayAdapter.java deleted file mode 100644 index 7a104d7e5a8a..000000000000 --- a/services/java/com/android/server/display/HeadlessDisplayAdapter.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.display; - -import android.content.Context; -import android.os.Handler; -import android.util.DisplayMetrics; -import android.view.Display; - -/** - * Provides a fake default display for headless systems. - * <p> - * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock. - * </p> - */ -final class HeadlessDisplayAdapter extends DisplayAdapter { - private static final String TAG = "HeadlessDisplayAdapter"; - - // Called with SyncRoot lock held. - public HeadlessDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, - Context context, Handler handler, Listener listener) { - super(syncRoot, context, handler, listener, TAG); - } - - @Override - public void registerLocked() { - super.registerLocked(); - sendDisplayDeviceEventLocked(new HeadlessDisplayDevice(), DISPLAY_DEVICE_EVENT_ADDED); - } - - private final class HeadlessDisplayDevice extends DisplayDevice { - private DisplayDeviceInfo mInfo; - - public HeadlessDisplayDevice() { - super(HeadlessDisplayAdapter.this, null); - } - - @Override - public DisplayDeviceInfo getDisplayDeviceInfoLocked() { - if (mInfo == null) { - mInfo = new DisplayDeviceInfo(); - mInfo.name = getContext().getResources().getString( - com.android.internal.R.string.display_manager_built_in_display_name); - mInfo.width = 640; - mInfo.height = 480; - mInfo.refreshRate = 60; - mInfo.densityDpi = DisplayMetrics.DENSITY_DEFAULT; - mInfo.xDpi = 160; - mInfo.yDpi = 160; - mInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY - | DisplayDeviceInfo.FLAG_SECURE - | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS; - mInfo.type = Display.TYPE_BUILT_IN; - mInfo.touch = DisplayDeviceInfo.TOUCH_NONE; - } - return mInfo; - } - } -} diff --git a/services/java/com/android/server/dreams/DreamManagerService.java b/services/java/com/android/server/dreams/DreamManagerService.java deleted file mode 100644 index b6e778170d17..000000000000 --- a/services/java/com/android/server/dreams/DreamManagerService.java +++ /dev/null @@ -1,425 +0,0 @@ -/* - * 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.dreams; - -import com.android.internal.util.DumpUtils; - -import android.app.ActivityManager; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Binder; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.PowerManager; -import android.os.SystemClock; -import android.os.UserHandle; -import android.provider.Settings; -import android.service.dreams.IDreamManager; -import android.util.Slog; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; - -import libcore.util.Objects; - -/** - * Service api for managing dreams. - * - * @hide - */ -public final class DreamManagerService extends IDreamManager.Stub { - private static final boolean DEBUG = false; - private static final String TAG = "DreamManagerService"; - - private final Object mLock = new Object(); - - private final Context mContext; - private final DreamHandler mHandler; - private final DreamController mController; - private final PowerManager mPowerManager; - - private Binder mCurrentDreamToken; - private ComponentName mCurrentDreamName; - private int mCurrentDreamUserId; - private boolean mCurrentDreamIsTest; - - public DreamManagerService(Context context, Handler mainHandler) { - mContext = context; - mHandler = new DreamHandler(mainHandler.getLooper()); - mController = new DreamController(context, mHandler, mControllerListener); - - mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); - } - - public void systemRunning() { - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - synchronized (mLock) { - stopDreamLocked(); - } - } - }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler); - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump DreamManager from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return; - } - - pw.println("DREAM MANAGER (dumpsys dreams)"); - pw.println(); - - pw.println("mCurrentDreamToken=" + mCurrentDreamToken); - pw.println("mCurrentDreamName=" + mCurrentDreamName); - pw.println("mCurrentDreamUserId=" + mCurrentDreamUserId); - pw.println("mCurrentDreamIsTest=" + mCurrentDreamIsTest); - pw.println(); - - DumpUtils.dumpAsync(mHandler, new DumpUtils.Dump() { - @Override - public void dump(PrintWriter pw) { - mController.dump(pw); - } - }, pw, 200); - } - - @Override // Binder call - public ComponentName[] getDreamComponents() { - checkPermission(android.Manifest.permission.READ_DREAM_STATE); - - final int userId = UserHandle.getCallingUserId(); - final long ident = Binder.clearCallingIdentity(); - try { - return getDreamComponentsForUser(userId); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override // Binder call - public void setDreamComponents(ComponentName[] componentNames) { - checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); - - final int userId = UserHandle.getCallingUserId(); - final long ident = Binder.clearCallingIdentity(); - try { - Settings.Secure.putStringForUser(mContext.getContentResolver(), - Settings.Secure.SCREENSAVER_COMPONENTS, - componentsToString(componentNames), - userId); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override // Binder call - public ComponentName getDefaultDreamComponent() { - checkPermission(android.Manifest.permission.READ_DREAM_STATE); - - final int userId = UserHandle.getCallingUserId(); - final long ident = Binder.clearCallingIdentity(); - try { - String name = Settings.Secure.getStringForUser(mContext.getContentResolver(), - Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT, - userId); - return name == null ? null : ComponentName.unflattenFromString(name); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override // Binder call - public boolean isDreaming() { - checkPermission(android.Manifest.permission.READ_DREAM_STATE); - - synchronized (mLock) { - return mCurrentDreamToken != null && !mCurrentDreamIsTest; - } - } - - @Override // Binder call - public void dream() { - checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); - - final long ident = Binder.clearCallingIdentity(); - try { - // Ask the power manager to nap. It will eventually call back into - // startDream() if/when it is appropriate to start dreaming. - // Because napping could cause the screen to turn off immediately if the dream - // cannot be started, we keep one eye open and gently poke user activity. - long time = SystemClock.uptimeMillis(); - mPowerManager.userActivity(time, true /*noChangeLights*/); - mPowerManager.nap(time); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override // Binder call - public void testDream(ComponentName dream) { - checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); - - if (dream == null) { - throw new IllegalArgumentException("dream must not be null"); - } - - final int callingUserId = UserHandle.getCallingUserId(); - final int currentUserId = ActivityManager.getCurrentUser(); - if (callingUserId != currentUserId) { - // This check is inherently prone to races but at least it's something. - Slog.w(TAG, "Aborted attempt to start a test dream while a different " - + " user is active: callingUserId=" + callingUserId - + ", currentUserId=" + currentUserId); - return; - } - final long ident = Binder.clearCallingIdentity(); - try { - synchronized (mLock) { - startDreamLocked(dream, true /*isTest*/, callingUserId); - } - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override // Binder call - public void awaken() { - checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); - - final long ident = Binder.clearCallingIdentity(); - try { - // Treat an explicit request to awaken as user activity so that the - // device doesn't immediately go to sleep if the timeout expired, - // for example when being undocked. - long time = SystemClock.uptimeMillis(); - mPowerManager.userActivity(time, false /*noChangeLights*/); - stopDream(); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override // Binder call - public void finishSelf(IBinder token) { - // Requires no permission, called by Dream from an arbitrary process. - if (token == null) { - throw new IllegalArgumentException("token must not be null"); - } - - final long ident = Binder.clearCallingIdentity(); - try { - if (DEBUG) { - Slog.d(TAG, "Dream finished: " + token); - } - - // Note that a dream finishing and self-terminating is not - // itself considered user activity. If the dream is ending because - // the user interacted with the device then user activity will already - // have been poked so the device will stay awake a bit longer. - // If the dream is ending on its own for other reasons and no wake - // locks are held and the user activity timeout has expired then the - // device may simply go to sleep. - synchronized (mLock) { - if (mCurrentDreamToken == token) { - stopDreamLocked(); - } - } - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - /** - * Called by the power manager to start a dream. - */ - public void startDream() { - int userId = ActivityManager.getCurrentUser(); - ComponentName dream = chooseDreamForUser(userId); - if (dream != null) { - synchronized (mLock) { - startDreamLocked(dream, false /*isTest*/, userId); - } - } - } - - /** - * Called by the power manager to stop a dream. - */ - public void stopDream() { - synchronized (mLock) { - stopDreamLocked(); - } - } - - private ComponentName chooseDreamForUser(int userId) { - ComponentName[] dreams = getDreamComponentsForUser(userId); - return dreams != null && dreams.length != 0 ? dreams[0] : null; - } - - private ComponentName[] getDreamComponentsForUser(int userId) { - String names = Settings.Secure.getStringForUser(mContext.getContentResolver(), - Settings.Secure.SCREENSAVER_COMPONENTS, - userId); - ComponentName[] components = componentsFromString(names); - - // first, ensure components point to valid services - List<ComponentName> validComponents = new ArrayList<ComponentName>(); - if (components != null) { - for (ComponentName component : components) { - if (serviceExists(component)) { - validComponents.add(component); - } else { - Slog.w(TAG, "Dream " + component + " does not exist"); - } - } - } - - // fallback to the default dream component if necessary - if (validComponents.isEmpty()) { - ComponentName defaultDream = getDefaultDreamComponent(); - if (defaultDream != null) { - Slog.w(TAG, "Falling back to default dream " + defaultDream); - validComponents.add(defaultDream); - } - } - return validComponents.toArray(new ComponentName[validComponents.size()]); - } - - private boolean serviceExists(ComponentName name) { - try { - return name != null && mContext.getPackageManager().getServiceInfo(name, 0) != null; - } catch (NameNotFoundException e) { - return false; - } - } - - private void startDreamLocked(final ComponentName name, - final boolean isTest, final int userId) { - if (Objects.equal(mCurrentDreamName, name) - && mCurrentDreamIsTest == isTest - && mCurrentDreamUserId == userId) { - return; - } - - stopDreamLocked(); - - if (DEBUG) Slog.i(TAG, "Entering dreamland."); - - final Binder newToken = new Binder(); - mCurrentDreamToken = newToken; - mCurrentDreamName = name; - mCurrentDreamIsTest = isTest; - mCurrentDreamUserId = userId; - - mHandler.post(new Runnable() { - @Override - public void run() { - mController.startDream(newToken, name, isTest, userId); - } - }); - } - - private void stopDreamLocked() { - if (mCurrentDreamToken != null) { - if (DEBUG) Slog.i(TAG, "Leaving dreamland."); - - cleanupDreamLocked(); - - mHandler.post(new Runnable() { - @Override - public void run() { - mController.stopDream(); - } - }); - } - } - - private void cleanupDreamLocked() { - mCurrentDreamToken = null; - mCurrentDreamName = null; - mCurrentDreamIsTest = false; - mCurrentDreamUserId = 0; - } - - private void checkPermission(String permission) { - if (mContext.checkCallingOrSelfPermission(permission) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Access denied to process: " + Binder.getCallingPid() - + ", must have permission " + permission); - } - } - - private static String componentsToString(ComponentName[] componentNames) { - StringBuilder names = new StringBuilder(); - if (componentNames != null) { - for (ComponentName componentName : componentNames) { - if (names.length() > 0) { - names.append(','); - } - names.append(componentName.flattenToString()); - } - } - return names.toString(); - } - - private static ComponentName[] componentsFromString(String names) { - if (names == null) { - return null; - } - String[] namesArray = names.split(","); - ComponentName[] componentNames = new ComponentName[namesArray.length]; - for (int i = 0; i < namesArray.length; i++) { - componentNames[i] = ComponentName.unflattenFromString(namesArray[i]); - } - return componentNames; - } - - private final DreamController.Listener mControllerListener = new DreamController.Listener() { - @Override - public void onDreamStopped(Binder token) { - synchronized (mLock) { - if (mCurrentDreamToken == token) { - cleanupDreamLocked(); - } - } - } - }; - - /** - * Handler for asynchronous operations performed by the dream manager. - * Ensures operations to {@link DreamController} are single-threaded. - */ - private final class DreamHandler extends Handler { - public DreamHandler(Looper looper) { - super(looper, null, true /*async*/); - } - } -} diff --git a/services/java/com/android/server/print/PrintManagerService.java b/services/java/com/android/server/print/PrintManagerService.java deleted file mode 100644 index 98acc27741fa..000000000000 --- a/services/java/com/android/server/print/PrintManagerService.java +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.print; - -import android.Manifest; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Binder; -import android.os.Bundle; -import android.os.Process; -import android.os.RemoteException; -import android.os.UserHandle; -import android.print.IPrintDocumentAdapter; -import android.print.IPrintJobStateChangeListener; -import android.print.IPrintManager; -import android.print.IPrinterDiscoveryObserver; -import android.print.PrintAttributes; -import android.print.PrintJobId; -import android.print.PrintJobInfo; -import android.print.PrinterId; -import android.printservice.PrintServiceInfo; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.SparseArray; - -import com.android.internal.R; -import com.android.internal.content.PackageMonitor; -import com.android.internal.os.BackgroundThread; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -public final class PrintManagerService extends IPrintManager.Stub { - - private static final char COMPONENT_NAME_SEPARATOR = ':'; - - private static final String EXTRA_PRINT_SERVICE_COMPONENT_NAME = - "EXTRA_PRINT_SERVICE_COMPONENT_NAME"; - - private final Object mLock = new Object(); - - private final Context mContext; - - private final SparseArray<UserState> mUserStates = new SparseArray<UserState>(); - - private int mCurrentUserId = UserHandle.USER_OWNER; - - public PrintManagerService(Context context) { - mContext = context; - registerContentObservers(); - registerBoradcastReceivers(); - } - - public void systemRuning() { - BackgroundThread.getHandler().post(new Runnable() { - @Override - public void run() { - final UserState userState; - synchronized (mLock) { - userState = getCurrentUserStateLocked(); - userState.updateIfNeededLocked(); - } - // This is the first time we switch to this user after boot, so - // now is the time to remove obsolete print jobs since they - // are from the last boot and no application would query them. - userState.removeObsoletePrintJobs(); - } - }); - } - - @Override - public Bundle print(String printJobName, IPrintDocumentAdapter adapter, - PrintAttributes attributes, String packageName, int appId, int userId) { - final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - String resolvedPackageName = resolveCallingPackageNameEnforcingSecurity(packageName); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - return userState.print(printJobName, adapter, attributes, - resolvedPackageName, resolvedAppId); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public List<PrintJobInfo> getPrintJobInfos(int appId, int userId) { - final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - return userState.getPrintJobInfos(resolvedAppId); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId, int userId) { - final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - return userState.getPrintJobInfo(printJobId, resolvedAppId); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public void cancelPrintJob(PrintJobId printJobId, int appId, int userId) { - final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - userState.cancelPrintJob(printJobId, resolvedAppId); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public void restartPrintJob(PrintJobId printJobId, int appId, int userId) { - final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - userState.restartPrintJob(printJobId, resolvedAppId); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public List<PrintServiceInfo> getEnabledPrintServices(int userId) { - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - return userState.getEnabledPrintServices(); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public List<PrintServiceInfo> getInstalledPrintServices(int userId) { - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - return userState.getInstalledPrintServices(); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public void createPrinterDiscoverySession(IPrinterDiscoveryObserver observer, - int userId) { - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - userState.createPrinterDiscoverySession(observer); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public void destroyPrinterDiscoverySession(IPrinterDiscoveryObserver observer, - int userId) { - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - userState.destroyPrinterDiscoverySession(observer); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public void startPrinterDiscovery(IPrinterDiscoveryObserver observer, - List<PrinterId> priorityList, int userId) { - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - userState.startPrinterDiscovery(observer, priorityList); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public void stopPrinterDiscovery(IPrinterDiscoveryObserver observer, int userId) { - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - userState.stopPrinterDiscovery(observer); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public void validatePrinters(List<PrinterId> printerIds, int userId) { - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - userState.validatePrinters(printerIds); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public void startPrinterStateTracking(PrinterId printerId, int userId) { - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - userState.startPrinterStateTracking(printerId); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public void stopPrinterStateTracking(PrinterId printerId, int userId) { - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - userState.stopPrinterStateTracking(printerId); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener, - int appId, int userId) throws RemoteException { - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - userState.addPrintJobStateChangeListener(listener, resolvedAppId); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public void removePrintJobStateChangeListener(IPrintJobStateChangeListener listener, - int userId) { - final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); - final UserState userState; - synchronized (mLock) { - userState = getOrCreateUserStateLocked(resolvedUserId); - } - final long identity = Binder.clearCallingIdentity(); - try { - userState.removePrintJobStateChangeListener(listener); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump PrintManager from from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return; - } - - synchronized (mLock) { - final long identity = Binder.clearCallingIdentity(); - try { - pw.println("PRINT MANAGER STATE (dumpsys print)"); - final int userStateCount = mUserStates.size(); - for (int i = 0; i < userStateCount; i++) { - UserState userState = mUserStates.valueAt(i); - userState.dump(fd, pw, ""); - pw.println(); - } - } finally { - Binder.restoreCallingIdentity(identity); - } - } - } - - private void registerContentObservers() { - final Uri enabledPrintServicesUri = Settings.Secure.getUriFor( - Settings.Secure.ENABLED_PRINT_SERVICES); - - ContentObserver observer = new ContentObserver(BackgroundThread.getHandler()) { - @Override - public void onChange(boolean selfChange, Uri uri) { - if (enabledPrintServicesUri.equals(uri)) { - synchronized (mLock) { - UserState userState = getCurrentUserStateLocked(); - userState.updateIfNeededLocked(); - } - } - } - }; - - mContext.getContentResolver().registerContentObserver(enabledPrintServicesUri, - false, observer, UserHandle.USER_ALL); - } - - private void registerBoradcastReceivers() { - PackageMonitor monitor = new PackageMonitor() { - @Override - public boolean onPackageChanged(String packageName, int uid, String[] components) { - synchronized (mLock) { - UserState userState = getOrCreateUserStateLocked(getChangingUserId()); - Iterator<ComponentName> iterator = userState.getEnabledServices().iterator(); - while (iterator.hasNext()) { - ComponentName componentName = iterator.next(); - if (packageName.equals(componentName.getPackageName())) { - userState.updateIfNeededLocked(); - return true; - } - } - } - return false; - } - - @Override - public void onPackageRemoved(String packageName, int uid) { - synchronized (mLock) { - UserState userState = getOrCreateUserStateLocked(getChangingUserId()); - Iterator<ComponentName> iterator = userState.getEnabledServices().iterator(); - while (iterator.hasNext()) { - ComponentName componentName = iterator.next(); - if (packageName.equals(componentName.getPackageName())) { - iterator.remove(); - persistComponentNamesToSettingLocked( - Settings.Secure.ENABLED_PRINT_SERVICES, - userState.getEnabledServices(), getChangingUserId()); - userState.updateIfNeededLocked(); - return; - } - } - } - } - - @Override - public boolean onHandleForceStop(Intent intent, String[] stoppedPackages, - int uid, boolean doit) { - synchronized (mLock) { - UserState userState = getOrCreateUserStateLocked(getChangingUserId()); - boolean stoppedSomePackages = false; - Iterator<ComponentName> iterator = userState.getEnabledServices().iterator(); - while (iterator.hasNext()) { - ComponentName componentName = iterator.next(); - String componentPackage = componentName.getPackageName(); - for (String stoppedPackage : stoppedPackages) { - if (componentPackage.equals(stoppedPackage)) { - if (!doit) { - return true; - } - stoppedSomePackages = true; - break; - } - } - } - if (stoppedSomePackages) { - userState.updateIfNeededLocked(); - } - return false; - } - } - - @Override - public void onPackageAdded(String packageName, int uid) { - Intent intent = new Intent(android.printservice.PrintService.SERVICE_INTERFACE); - intent.setPackage(packageName); - - List<ResolveInfo> installedServices = mContext.getPackageManager() - .queryIntentServicesAsUser(intent, PackageManager.GET_SERVICES, - getChangingUserId()); - - if (installedServices == null) { - return; - } - - final int installedServiceCount = installedServices.size(); - for (int i = 0; i < installedServiceCount; i++) { - ServiceInfo serviceInfo = installedServices.get(i).serviceInfo; - ComponentName component = new ComponentName(serviceInfo.packageName, - serviceInfo.name); - String label = serviceInfo.loadLabel(mContext.getPackageManager()).toString(); - showEnableInstalledPrintServiceNotification(component, label, - getChangingUserId()); - } - } - - private void persistComponentNamesToSettingLocked(String settingName, - Set<ComponentName> componentNames, int userId) { - StringBuilder builder = new StringBuilder(); - for (ComponentName componentName : componentNames) { - if (builder.length() > 0) { - builder.append(COMPONENT_NAME_SEPARATOR); - } - builder.append(componentName.flattenToShortString()); - } - Settings.Secure.putStringForUser(mContext.getContentResolver(), - settingName, builder.toString(), userId); - } - }; - - // package changes - monitor.register(mContext, BackgroundThread.getHandler().getLooper(), - UserHandle.ALL, true); - - // user changes - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(Intent.ACTION_USER_SWITCHED); - intentFilter.addAction(Intent.ACTION_USER_REMOVED); - - mContext.registerReceiverAsUser(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (Intent.ACTION_USER_SWITCHED.equals(action)) { - switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); - } else if (Intent.ACTION_USER_REMOVED.equals(action)) { - removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); - } - } - }, UserHandle.ALL, intentFilter, null, BackgroundThread.getHandler()); - } - - private UserState getCurrentUserStateLocked() { - return getOrCreateUserStateLocked(mCurrentUserId); - } - - private UserState getOrCreateUserStateLocked(int userId) { - UserState userState = mUserStates.get(userId); - if (userState == null) { - userState = new UserState(mContext, userId, mLock); - mUserStates.put(userId, userState); - } - return userState; - } - - private void switchUser(int newUserId) { - UserState userState; - synchronized (mLock) { - if (newUserId == mCurrentUserId) { - return; - } - mCurrentUserId = newUserId; - userState = mUserStates.get(mCurrentUserId); - if (userState == null) { - userState = getCurrentUserStateLocked(); - userState.updateIfNeededLocked(); - } else { - userState.updateIfNeededLocked(); - } - } - // This is the first time we switch to this user after boot, so - // now is the time to remove obsolete print jobs since they - // are from the last boot and no application would query them. - userState.removeObsoletePrintJobs(); - } - - private void removeUser(int removedUserId) { - synchronized (mLock) { - UserState userState = mUserStates.get(removedUserId); - if (userState != null) { - userState.destroyLocked(); - mUserStates.remove(removedUserId); - } - } - } - - private int resolveCallingAppEnforcingPermissions(int appId) { - final int callingUid = Binder.getCallingUid(); - if (callingUid == 0 || callingUid == Process.SYSTEM_UID - || callingUid == Process.SHELL_UID) { - return appId; - } - final int callingAppId = UserHandle.getAppId(callingUid); - if (appId == callingAppId) { - return appId; - } - if (mContext.checkCallingPermission( - "com.android.printspooler.permission.ACCESS_ALL_PRINT_JOBS") - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Call from app " + callingAppId + " as app " - + appId + " without com.android.printspooler.permission" - + ".ACCESS_ALL_PRINT_JOBS"); - } - return appId; - } - - private int resolveCallingUserEnforcingPermissions(int userId) { - final int callingUid = Binder.getCallingUid(); - if (callingUid == 0 || callingUid == Process.SYSTEM_UID - || callingUid == Process.SHELL_UID) { - return userId; - } - final int callingUserId = UserHandle.getUserId(callingUid); - if (callingUserId == userId) { - return userId; - } - if (mContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL) - != PackageManager.PERMISSION_GRANTED - || mContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS) - != PackageManager.PERMISSION_GRANTED) { - if (userId == UserHandle.USER_CURRENT_OR_SELF) { - return callingUserId; - } - throw new SecurityException("Call from user " + callingUserId + " as user " - + userId + " without permission INTERACT_ACROSS_USERS or " - + "INTERACT_ACROSS_USERS_FULL not allowed."); - } - if (userId == UserHandle.USER_CURRENT || userId == UserHandle.USER_CURRENT_OR_SELF) { - return mCurrentUserId; - } - throw new IllegalArgumentException("Calling user can be changed to only " - + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF."); - } - - private String resolveCallingPackageNameEnforcingSecurity(String packageName) { - if (TextUtils.isEmpty(packageName)) { - return null; - } - String[] packages = mContext.getPackageManager().getPackagesForUid( - Binder.getCallingUid()); - final int packageCount = packages.length; - for (int i = 0; i < packageCount; i++) { - if (packageName.equals(packages[i])) { - return packageName; - } - } - return null; - } - - private void showEnableInstalledPrintServiceNotification(ComponentName component, - String label, int userId) { - UserHandle userHandle = new UserHandle(userId); - - Intent intent = new Intent(Settings.ACTION_PRINT_SETTINGS); - intent.putExtra(EXTRA_PRINT_SERVICE_COMPONENT_NAME, component.flattenToString()); - - PendingIntent pendingIntent = PendingIntent.getActivityAsUser(mContext, 0, intent, - PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT, null, userHandle); - - Notification.Builder builder = new Notification.Builder(mContext) - .setSmallIcon(R.drawable.ic_print) - .setContentTitle(mContext.getString(R.string.print_service_installed_title, label)) - .setContentText(mContext.getString(R.string.print_service_installed_message)) - .setContentIntent(pendingIntent) - .setWhen(System.currentTimeMillis()) - .setAutoCancel(true) - .setShowWhen(true); - - NotificationManager notificationManager = (NotificationManager) mContext - .getSystemService(Context.NOTIFICATION_SERVICE); - - String notificationTag = getClass().getName() + ":" + component.flattenToString(); - notificationManager.notifyAsUser(notificationTag, 0, builder.build(), - userHandle); - } -} diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java deleted file mode 100644 index d358b4c6ed67..000000000000 --- a/services/java/com/android/server/wm/DisplayContent.java +++ /dev/null @@ -1,523 +0,0 @@ -/* - * 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 com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; -import static com.android.server.wm.WindowManagerService.DEBUG_STACK; -import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY; -import static com.android.server.wm.WindowManagerService.TAG; - -import android.app.ActivityManager.StackBoxInfo; -import android.graphics.Rect; -import android.graphics.Region; -import android.os.Debug; -import android.util.EventLog; -import android.util.Slog; -import android.view.Display; -import android.view.DisplayInfo; -import com.android.server.EventLogTags; - -import java.io.PrintWriter; -import java.util.ArrayList; - -class DisplayContentList extends ArrayList<DisplayContent> { -} - -/** - * Utility class for keeping track of the WindowStates and other pertinent contents of a - * particular Display. - * - * IMPORTANT: No method from this class should ever be used without holding - * WindowManagerService.mWindowMap. - */ -class DisplayContent { - - /** Unique identifier of this stack. */ - private final int mDisplayId; - - /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element - * from mDisplayWindows; */ - private WindowList mWindows = new WindowList(); - - // This protects the following display size properties, so that - // getDisplaySize() doesn't need to acquire the global lock. This is - // needed because the window manager sometimes needs to use ActivityThread - // while it has its global state locked (for example to load animation - // resources), but the ActivityThread also needs get the current display - // size sometimes when it has its package lock held. - // - // These will only be modified with both mWindowMap and mDisplaySizeLock - // held (in that order) so the window manager doesn't need to acquire this - // lock when needing these values in its normal operation. - final Object mDisplaySizeLock = new Object(); - int mInitialDisplayWidth = 0; - int mInitialDisplayHeight = 0; - int mInitialDisplayDensity = 0; - int mBaseDisplayWidth = 0; - int mBaseDisplayHeight = 0; - int mBaseDisplayDensity = 0; - private final DisplayInfo mDisplayInfo = new DisplayInfo(); - private final Display mDisplay; - - Rect mBaseDisplayRect = new Rect(); - - // Accessed directly by all users. - boolean layoutNeeded; - int pendingLayoutChanges; - final boolean isDefaultDisplay; - - /** - * Window tokens that are in the process of exiting, but still - * on screen for animations. - */ - final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>(); - - /** - * Application tokens that are in the process of exiting, but still - * on screen for animations. - */ - final AppTokenList mExitingAppTokens = new AppTokenList(); - - /** Array containing the home StackBox and possibly one more which would contain apps. Array - * is stored in display order with the current bottom stack at 0. */ - private ArrayList<StackBox> mStackBoxes = new ArrayList<StackBox>(); - - /** True when the home StackBox is at the top of mStackBoxes, false otherwise. */ - private TaskStack mHomeStack = null; - - /** Detect user tapping outside of current focused stack bounds .*/ - StackTapPointerEventListener mTapDetector; - - /** Detect user tapping outside of current focused stack bounds .*/ - Region mTouchExcludeRegion = new Region(); - - /** Save allocating when retrieving tasks */ - private ArrayList<Task> mTaskHistory = new ArrayList<Task>(); - - /** Save allocating when calculating rects */ - Rect mTmpRect = new Rect(); - - final WindowManagerService mService; - - /** - * @param display May not be null. - * @param service TODO(cmautner): - */ - DisplayContent(Display display, WindowManagerService service) { - mDisplay = display; - mDisplayId = display.getDisplayId(); - display.getDisplayInfo(mDisplayInfo); - isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY; - mService = service; - - StackBox newBox = new StackBox(service, this, null); - mStackBoxes.add(newBox); - TaskStack newStack = new TaskStack(service, HOME_STACK_ID, this); - newStack.mStackBox = newBox; - newBox.mStack = newStack; - mHomeStack = newStack; - } - - int getDisplayId() { - return mDisplayId; - } - - WindowList getWindowList() { - return mWindows; - } - - Display getDisplay() { - return mDisplay; - } - - DisplayInfo getDisplayInfo() { - return mDisplayInfo; - } - - /** - * Returns true if the specified UID has access to this display. - */ - public boolean hasAccess(int uid) { - return mDisplay.hasAccess(uid); - } - - boolean homeOnTop() { - return mStackBoxes.get(0).mStack != mHomeStack; - } - - public boolean isPrivate() { - return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0; - } - - /** - * Retrieve the tasks on this display in stack order from the bottommost TaskStack up. - * @return All the Tasks, in order, on this display. - */ - ArrayList<Task> getTasks() { - return mTaskHistory; - } - - void addTask(Task task, boolean toTop) { - mTaskHistory.remove(task); - - final int userId = task.mUserId; - int taskNdx; - final int numTasks = mTaskHistory.size(); - if (toTop) { - for (taskNdx = numTasks - 1; taskNdx >= 0; --taskNdx) { - if (mTaskHistory.get(taskNdx).mUserId == userId) { - break; - } - } - ++taskNdx; - } else { - for (taskNdx = 0; taskNdx < numTasks; ++taskNdx) { - if (mTaskHistory.get(taskNdx).mUserId == userId) { - break; - } - } - } - - mTaskHistory.add(taskNdx, task); - EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.taskId, toTop ? 1 : 0, taskNdx); - } - - void removeTask(Task task) { - mTaskHistory.remove(task); - } - - TaskStack getHomeStack() { - return mHomeStack; - } - - void updateDisplayInfo() { - mDisplay.getDisplayInfo(mDisplayInfo); - } - - void getLogicalDisplayRect(Rect out) { - updateDisplayInfo(); - // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. - int width = mDisplayInfo.logicalWidth; - int left = (mBaseDisplayWidth - width) / 2; - int height = mDisplayInfo.logicalHeight; - int top = (mBaseDisplayHeight - height) / 2; - out.set(left, top, left + width, top + height); - } - - /** @return The number of tokens in all of the Tasks on this display. */ - int numTokens() { - int count = 0; - for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { - count += mTaskHistory.get(taskNdx).mAppTokens.size(); - } - return count; - } - - /** Refer to {@link WindowManagerService#createStack(int, int, int, float)} */ - TaskStack createStack(int stackId, int relativeStackBoxId, int position, float weight) { - TaskStack newStack = null; - if (DEBUG_STACK) Slog.d(TAG, "createStack: stackId=" + stackId + " relativeStackBoxId=" - + relativeStackBoxId + " position=" + position + " weight=" + weight); - if (stackId == HOME_STACK_ID) { - if (mStackBoxes.size() != 1) { - throw new IllegalArgumentException("createStack: HOME_STACK_ID (0) not first."); - } - newStack = mHomeStack; - } else { - int stackBoxNdx; - for (stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) { - final StackBox box = mStackBoxes.get(stackBoxNdx); - if (position == StackBox.TASK_STACK_GOES_OVER - || position == StackBox.TASK_STACK_GOES_UNDER) { - // Position indicates a new box is added at top level only. - if (box.contains(relativeStackBoxId)) { - StackBox newBox = new StackBox(mService, this, null); - newStack = new TaskStack(mService, stackId, this); - newStack.mStackBox = newBox; - newBox.mStack = newStack; - final int offset = position == StackBox.TASK_STACK_GOES_OVER ? 1 : 0; - if (DEBUG_STACK) Slog.d(TAG, "createStack: inserting stack at " + - (stackBoxNdx + offset)); - mStackBoxes.add(stackBoxNdx + offset, newBox); - break; - } - } else { - // Remaining position values indicate a box must be split. - newStack = box.split(stackId, relativeStackBoxId, position, weight); - if (newStack != null) { - break; - } - } - } - if (stackBoxNdx < 0) { - throw new IllegalArgumentException("createStack: stackBoxId " + relativeStackBoxId - + " not found."); - } - } - if (newStack != null) { - layoutNeeded = true; - } - EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, relativeStackBoxId, position, - (int)(weight * 100 + 0.5)); - return newStack; - } - - /** Refer to {@link WindowManagerService#resizeStackBox(int, float)} */ - boolean resizeStack(int stackBoxId, float weight) { - for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) { - final StackBox box = mStackBoxes.get(stackBoxNdx); - if (box.resize(stackBoxId, weight)) { - layoutNeeded = true; - return true; - } - } - return false; - } - - void addStackBox(StackBox box, boolean toTop) { - if (mStackBoxes.size() >= 2) { - throw new RuntimeException("addStackBox: Too many toplevel StackBoxes!"); - } - mStackBoxes.add(toTop ? mStackBoxes.size() : 0, box); - } - - void removeStackBox(StackBox box) { - if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: box=" + box); - final TaskStack stack = box.mStack; - if (stack != null && stack.mStackId == HOME_STACK_ID) { - // Never delete the home stack, even if it is empty. - if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: Not deleting home stack."); - return; - } - mStackBoxes.remove(box); - } - - StackBoxInfo getStackBoxInfo(StackBox box) { - StackBoxInfo info = new StackBoxInfo(); - info.stackBoxId = box.mStackBoxId; - info.weight = box.mWeight; - info.vertical = box.mVertical; - info.bounds = new Rect(box.mBounds); - if (box.mStack != null) { - info.stackId = box.mStack.mStackId; - // ActivityManagerService will fill in the StackInfo. - } else { - info.stackId = -1; - info.children = new StackBoxInfo[2]; - info.children[0] = getStackBoxInfo(box.mFirst); - info.children[1] = getStackBoxInfo(box.mSecond); - } - return info; - } - - ArrayList<StackBoxInfo> getStackBoxInfos() { - ArrayList<StackBoxInfo> list = new ArrayList<StackBoxInfo>(); - for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) { - list.add(getStackBoxInfo(mStackBoxes.get(stackBoxNdx))); - } - return list; - } - - /** - * Move the home StackBox to the top or bottom of mStackBoxes. That is the only place - * it is allowed to be. This is a nop if the home StackBox is already in the correct position. - * @param toTop Move home to the top of mStackBoxes if true, to the bottom if false. - * @return true if a change was made, false otherwise. - */ - boolean moveHomeStackBox(boolean toTop) { - if (DEBUG_STACK) Slog.d(TAG, "moveHomeStackBox: toTop=" + toTop + " Callers=" + - Debug.getCallers(4)); - EventLog.writeEvent(EventLogTags.WM_HOME_STACK_MOVED, toTop ? 1 : 0); - switch (mStackBoxes.size()) { - case 0: throw new RuntimeException("moveHomeStackBox: No home StackBox!"); - case 1: return false; // Only the home StackBox exists. - case 2: - if (homeOnTop() ^ toTop) { - mStackBoxes.add(mStackBoxes.remove(0)); - return true; - } - return false; - default: throw new RuntimeException("moveHomeStackBox: Too many toplevel StackBoxes!"); - } - } - - /** - * Propagate the new bounds to all child stack boxes, applying weights as we move down. - * @param contentRect The bounds to apply at the top level. - */ - boolean setStackBoxSize(Rect contentRect) { - boolean change = false; - for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) { - change |= mStackBoxes.get(stackBoxNdx).setStackBoxSizes(contentRect, true); - } - return change; - } - - Rect getStackBounds(int stackId) { - for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) { - Rect bounds = mStackBoxes.get(stackBoxNdx).getStackBounds(stackId); - if (bounds != null) { - return bounds; - } - } - return null; - } - - int stackIdFromPoint(int x, int y) { - StackBox topBox = mStackBoxes.get(mStackBoxes.size() - 1); - return topBox.stackIdFromPoint(x, y); - } - - void setTouchExcludeRegion(TaskStack focusedStack) { - mTouchExcludeRegion.set(mBaseDisplayRect); - WindowList windows = getWindowList(); - for (int i = windows.size() - 1; i >= 0; --i) { - final WindowState win = windows.get(i); - final TaskStack stack = win.getStack(); - if (win.isVisibleLw() && stack != null && stack != focusedStack) { - mTmpRect.set(win.mVisibleFrame); - mTmpRect.intersect(win.mVisibleInsets); - mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE); - } - } - } - - void switchUserStacks(int oldUserId, int newUserId) { - final WindowList windows = getWindowList(); - for (int i = 0; i < windows.size(); i++) { - final WindowState win = windows.get(i); - if (win.isHiddenFromUserLocked()) { - if (DEBUG_VISIBILITY) Slog.w(TAG, "user changing " + newUserId + " hiding " - + win + ", attrs=" + win.mAttrs.type + ", belonging to " - + win.mOwnerUid); - win.hideLw(false); - } - } - - for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) { - mStackBoxes.get(stackBoxNdx).switchUserStacks(newUserId); - } - } - - void resetAnimationBackgroundAnimator() { - for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) { - mStackBoxes.get(stackBoxNdx).resetAnimationBackgroundAnimator(); - } - } - - boolean animateDimLayers() { - boolean result = false; - for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) { - result |= mStackBoxes.get(stackBoxNdx).animateDimLayers(); - } - return result; - } - - void resetDimming() { - for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) { - mStackBoxes.get(stackBoxNdx).resetDimming(); - } - } - - boolean isDimming() { - boolean result = false; - for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) { - result |= mStackBoxes.get(stackBoxNdx).isDimming(); - } - return result; - } - - void stopDimmingIfNeeded() { - for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) { - mStackBoxes.get(stackBoxNdx).stopDimmingIfNeeded(); - } - } - - void close() { - for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) { - mStackBoxes.get(stackBoxNdx).close(); - } - } - - public void dump(String prefix, PrintWriter pw) { - pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); - final String subPrefix = " " + prefix; - pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x"); - pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity); - pw.print("dpi"); - if (mInitialDisplayWidth != mBaseDisplayWidth - || mInitialDisplayHeight != mBaseDisplayHeight - || mInitialDisplayDensity != mBaseDisplayDensity) { - pw.print(" base="); - pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); - pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi"); - } - pw.print(" cur="); - pw.print(mDisplayInfo.logicalWidth); - pw.print("x"); pw.print(mDisplayInfo.logicalHeight); - pw.print(" app="); - pw.print(mDisplayInfo.appWidth); - pw.print("x"); pw.print(mDisplayInfo.appHeight); - pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth); - pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); - pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); - pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); - pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded); - for (int boxNdx = 0; boxNdx < mStackBoxes.size(); ++boxNdx) { - pw.print(prefix); pw.print("StackBox #"); pw.println(boxNdx); - mStackBoxes.get(boxNdx).dump(prefix + " ", pw); - } - int ndx = numTokens(); - if (ndx > 0) { - pw.println(); - pw.println(" Application tokens in Z order:"); - getTasks(); - for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { - AppTokenList tokens = mTaskHistory.get(taskNdx).mAppTokens; - for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { - final AppWindowToken wtoken = tokens.get(tokenNdx); - pw.print(" App #"); pw.print(ndx--); - pw.print(' '); pw.print(wtoken); pw.println(":"); - wtoken.dump(pw, " "); - } - } - } - if (mExitingTokens.size() > 0) { - pw.println(); - pw.println(" Exiting tokens:"); - for (int i=mExitingTokens.size()-1; i>=0; i--) { - WindowToken token = mExitingTokens.get(i); - pw.print(" Exiting #"); pw.print(i); - pw.print(' '); pw.print(token); - pw.println(':'); - token.dump(pw, " "); - } - } - if (mExitingAppTokens.size() > 0) { - pw.println(); - pw.println(" Exiting application tokens:"); - for (int i=mExitingAppTokens.size()-1; i>=0; i--) { - WindowToken token = mExitingAppTokens.get(i); - pw.print(" Exiting App #"); pw.print(i); - pw.print(' '); pw.print(token); - pw.println(':'); - token.dump(pw, " "); - } - } - pw.println(); - } -} diff --git a/services/java/com/android/server/wm/StackBox.java b/services/java/com/android/server/wm/StackBox.java deleted file mode 100644 index d351925015ee..000000000000 --- a/services/java/com/android/server/wm/StackBox.java +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import android.graphics.Rect; -import android.util.Slog; - -import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; -import static com.android.server.wm.WindowManagerService.DEBUG_STACK; -import static com.android.server.wm.WindowManagerService.TAG; - -import java.io.PrintWriter; - -public class StackBox { - /** Used with {@link WindowManagerService#createStack}. Dependent on Configuration LTR/RTL. */ - public static final int TASK_STACK_GOES_BEFORE = 0; - /** Used with {@link WindowManagerService#createStack}. Dependent on Configuration LTR/RTL. */ - public static final int TASK_STACK_GOES_AFTER = 1; - /** Used with {@link WindowManagerService#createStack}. Horizontal to left of. */ - public static final int TASK_STACK_TO_LEFT_OF = 2; - /** Used with {@link WindowManagerService#createStack}. Horizontal to right of. */ - public static final int TASK_STACK_TO_RIGHT_OF = 3; - /** Used with {@link WindowManagerService#createStack}. Vertical: lower t/b Rect values. */ - public static final int TASK_STACK_GOES_ABOVE = 4; - /** Used with {@link WindowManagerService#createStack}. Vertical: higher t/b Rect values. */ - public static final int TASK_STACK_GOES_BELOW = 5; - /** Used with {@link WindowManagerService#createStack}. Put on a higher layer on display. */ - public static final int TASK_STACK_GOES_OVER = 6; - /** Used with {@link WindowManagerService#createStack}. Put on a lower layer on display. */ - public static final int TASK_STACK_GOES_UNDER = 7; - - static int sCurrentBoxId = 0; - - /** Unique id for this box */ - final int mStackBoxId; - - /** The service */ - final WindowManagerService mService; - - /** The display this box sits in. */ - final DisplayContent mDisplayContent; - - /** Non-null indicates this is mFirst or mSecond of a parent StackBox. Null indicates this - * is this entire size of mDisplayContent. */ - StackBox mParent; - - /** First child, this is null exactly when mStack is non-null. */ - StackBox mFirst; - - /** Second child, this is null exactly when mStack is non-null. */ - StackBox mSecond; - - /** Stack of Tasks, this is null exactly when mFirst and mSecond are non-null. */ - TaskStack mStack; - - /** Content limits relative to the DisplayContent this sits in. */ - Rect mBounds = new Rect(); - - /** Relative orientation of mFirst and mSecond. */ - boolean mVertical; - - /** Fraction of mBounds to devote to mFirst, remainder goes to mSecond */ - float mWeight; - - /** Dirty flag. Something inside this or some descendant of this has changed. */ - boolean layoutNeeded; - - /** True if this StackBox sits below the Status Bar. */ - boolean mUnderStatusBar; - - /** Used to keep from reallocating a temporary Rect for propagating bounds to child boxes */ - Rect mTmpRect = new Rect(); - - StackBox(WindowManagerService service, DisplayContent displayContent, StackBox parent) { - synchronized (StackBox.class) { - mStackBoxId = sCurrentBoxId++; - } - - mService = service; - mDisplayContent = displayContent; - mParent = parent; - } - - /** Propagate #layoutNeeded bottom up. */ - void makeDirty() { - layoutNeeded = true; - if (mParent != null) { - mParent.makeDirty(); - } - } - - /** - * Determine if a particular StackBox is this one or a descendant of this one. - * @param stackBoxId The StackBox being searched for. - * @return true if the specified StackBox matches this or one of its descendants. - */ - boolean contains(int stackBoxId) { - return mStackBoxId == stackBoxId || - (mStack == null && (mFirst.contains(stackBoxId) || mSecond.contains(stackBoxId))); - } - - /** - * Return the stackId of the stack that intersects the passed point. - * @param x coordinate of point. - * @param y coordinate of point. - * @return -1 if point is outside of mBounds, otherwise the stackId of the containing stack. - */ - int stackIdFromPoint(int x, int y) { - if (!mBounds.contains(x, y)) { - return -1; - } - if (mStack != null) { - return mStack.mStackId; - } - int stackId = mFirst.stackIdFromPoint(x, y); - if (stackId >= 0) { - return stackId; - } - return mSecond.stackIdFromPoint(x, y); - } - - /** Determine if this StackBox is the first child or second child. - * @return true if this is the first child. - */ - boolean isFirstChild() { - return mParent != null && mParent.mFirst == this; - } - - /** Returns the bounds of the specified TaskStack if it is contained in this StackBox. - * @param stackId the TaskStack to find the bounds of. - * @return a new Rect with the bounds of stackId if it is within this StackBox, null otherwise. - */ - Rect getStackBounds(int stackId) { - if (mStack != null) { - return mStack.mStackId == stackId ? new Rect(mBounds) : null; - } - Rect bounds = mFirst.getStackBounds(stackId); - if (bounds != null) { - return bounds; - } - return mSecond.getStackBounds(stackId); - } - - /** - * Create a new TaskStack relative to a specified one by splitting the StackBox containing - * the specified TaskStack into two children. The size and position each of the new StackBoxes - * is determined by the passed parameters. - * @param stackId The id of the new TaskStack to create. - * @param relativeStackBoxId The id of the StackBox to place the new TaskStack next to. - * @param position One of the static TASK_STACK_GOES_xxx positions defined in this class. - * @param weight The percentage size of the parent StackBox to devote to the new TaskStack. - * @return The new TaskStack. - */ - TaskStack split(int stackId, int relativeStackBoxId, int position, float weight) { - if (mStackBoxId != relativeStackBoxId) { - // This is not the targeted StackBox. - if (mStack != null) { - return null; - } - // Propagate the split to see if the targeted StackBox is in either sub box. - TaskStack stack = mFirst.split(stackId, relativeStackBoxId, position, weight); - if (stack != null) { - return stack; - } - return mSecond.split(stackId, relativeStackBoxId, position, weight); - } - - // Found it! - TaskStack stack = new TaskStack(mService, stackId, mDisplayContent); - TaskStack firstStack; - TaskStack secondStack; - if (position == TASK_STACK_GOES_BEFORE) { - // TODO: Test Configuration here for LTR/RTL. - position = TASK_STACK_TO_LEFT_OF; - } else if (position == TASK_STACK_GOES_AFTER) { - // TODO: Test Configuration here for LTR/RTL. - position = TASK_STACK_TO_RIGHT_OF; - } - switch (position) { - default: - case TASK_STACK_TO_LEFT_OF: - case TASK_STACK_TO_RIGHT_OF: - mVertical = false; - if (position == TASK_STACK_TO_LEFT_OF) { - mWeight = weight; - firstStack = stack; - secondStack = mStack; - } else { - mWeight = 1.0f - weight; - firstStack = mStack; - secondStack = stack; - } - break; - case TASK_STACK_GOES_ABOVE: - case TASK_STACK_GOES_BELOW: - mVertical = true; - if (position == TASK_STACK_GOES_ABOVE) { - mWeight = weight; - firstStack = stack; - secondStack = mStack; - } else { - mWeight = 1.0f - weight; - firstStack = mStack; - secondStack = stack; - } - break; - } - - mFirst = new StackBox(mService, mDisplayContent, this); - firstStack.mStackBox = mFirst; - mFirst.mStack = firstStack; - - mSecond = new StackBox(mService, mDisplayContent, this); - secondStack.mStackBox = mSecond; - mSecond.mStack = secondStack; - - mStack = null; - return stack; - } - - /** Return the stackId of the first mFirst StackBox with a non-null mStack */ - int getStackId() { - if (mStack != null) { - return mStack.mStackId; - } - return mFirst.getStackId(); - } - - /** Remove this box and propagate its sibling's content up to their parent. - * @return The first stackId of the resulting StackBox. */ - int remove() { - mDisplayContent.layoutNeeded = true; - - if (mParent == null) { - // This is the top-plane stack. - if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: removing top plane."); - mDisplayContent.removeStackBox(this); - return HOME_STACK_ID; - } - - StackBox sibling = isFirstChild() ? mParent.mSecond : mParent.mFirst; - StackBox grandparent = mParent.mParent; - sibling.mParent = grandparent; - if (grandparent == null) { - // mParent is a top-plane stack. Now sibling will be. - if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: grandparent null"); - mDisplayContent.removeStackBox(mParent); - mDisplayContent.addStackBox(sibling, true); - } else { - if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: grandparent getting sibling"); - if (mParent.isFirstChild()) { - grandparent.mFirst = sibling; - } else { - grandparent.mSecond = sibling; - } - } - return sibling.getStackId(); - } - - boolean resize(int stackBoxId, float weight) { - if (mStackBoxId != stackBoxId) { - return mStack == null && - (mFirst.resize(stackBoxId, weight) || mSecond.resize(stackBoxId, weight)); - } - // Don't change weight on topmost stack. - if (mParent != null) { - mParent.mWeight = isFirstChild() ? weight : 1.0f - weight; - } - return true; - } - - /** If this is a terminal StackBox (contains a TaskStack) set the bounds. - * @param bounds The rectangle to set the bounds to. - * @param underStatusBar True if the StackBox is directly below the Status Bar. - * @return True if the bounds changed, false otherwise. */ - boolean setStackBoxSizes(Rect bounds, boolean underStatusBar) { - boolean change = false; - if (mUnderStatusBar != underStatusBar) { - change = true; - mUnderStatusBar = underStatusBar; - } - if (mStack != null) { - change |= !mBounds.equals(bounds); - if (change) { - mBounds.set(bounds); - mStack.setBounds(bounds, underStatusBar); - } - } else { - mTmpRect.set(bounds); - if (mVertical) { - final int height = bounds.height(); - int firstHeight = (int)(height * mWeight); - mTmpRect.bottom = bounds.top + firstHeight; - change |= mFirst.setStackBoxSizes(mTmpRect, underStatusBar); - mTmpRect.top = mTmpRect.bottom; - mTmpRect.bottom = bounds.top + height; - change |= mSecond.setStackBoxSizes(mTmpRect, false); - } else { - final int width = bounds.width(); - int firstWidth = (int)(width * mWeight); - mTmpRect.right = bounds.left + firstWidth; - change |= mFirst.setStackBoxSizes(mTmpRect, underStatusBar); - mTmpRect.left = mTmpRect.right; - mTmpRect.right = bounds.left + width; - change |= mSecond.setStackBoxSizes(mTmpRect, underStatusBar); - } - } - return change; - } - - void resetAnimationBackgroundAnimator() { - if (mStack != null) { - mStack.resetAnimationBackgroundAnimator(); - return; - } - mFirst.resetAnimationBackgroundAnimator(); - mSecond.resetAnimationBackgroundAnimator(); - } - - boolean animateDimLayers() { - if (mStack != null) { - return mStack.animateDimLayers(); - } - boolean result = mFirst.animateDimLayers(); - result |= mSecond.animateDimLayers(); - return result; - } - - void resetDimming() { - if (mStack != null) { - mStack.resetDimmingTag(); - return; - } - mFirst.resetDimming(); - mSecond.resetDimming(); - } - - boolean isDimming() { - if (mStack != null) { - return mStack.isDimming(); - } - boolean result = mFirst.isDimming(); - result |= mSecond.isDimming(); - return result; - } - - void stopDimmingIfNeeded() { - if (mStack != null) { - mStack.stopDimmingIfNeeded(); - return; - } - mFirst.stopDimmingIfNeeded(); - mSecond.stopDimmingIfNeeded(); - } - - void switchUserStacks(int userId) { - if (mStack != null) { - mStack.switchUser(userId); - return; - } - mFirst.switchUserStacks(userId); - mSecond.switchUserStacks(userId); - } - - void close() { - if (mStack != null) { - mStack.mDimLayer.mDimSurface.destroy(); - mStack.mAnimationBackgroundSurface.mDimSurface.destroy(); - return; - } - mFirst.close(); - mSecond.close(); - } - - public void dump(String prefix, PrintWriter pw) { - pw.print(prefix); pw.print("mParent="); pw.println(mParent); - pw.print(prefix); pw.print("mBounds="); pw.print(mBounds.toShortString()); - pw.print(" mVertical="); pw.print(mVertical); - pw.print(" layoutNeeded="); pw.println(layoutNeeded); - if (mFirst != null) { - pw.print(prefix); pw.print("mFirst="); pw.println(System.identityHashCode(mFirst)); - mFirst.dump(prefix + " ", pw); - pw.print(prefix); pw.print("mSecond="); pw.println(System.identityHashCode(mSecond)); - mSecond.dump(prefix + " ", pw); - } else { - pw.print(prefix); pw.print("mStack="); pw.println(mStack); - mStack.dump(prefix + " ", pw); - } - } - - @Override - public String toString() { - if (mStack != null) { - return "Box{" + hashCode() + " stack=" + mStack.mStackId + "}"; - } - return "Box{" + hashCode() + " parent=" + System.identityHashCode(mParent) - + " first=" + System.identityHashCode(mFirst) - + " second=" + System.identityHashCode(mSecond) + "}"; - } -} diff --git a/services/jni/Android.mk b/services/jni/Android.mk deleted file mode 100644 index 98e9b3085736..000000000000 --- a/services/jni/Android.mk +++ /dev/null @@ -1,63 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - com_android_server_AlarmManagerService.cpp \ - com_android_server_AssetAtlasService.cpp \ - com_android_server_ConsumerIrService.cpp \ - com_android_server_input_InputApplicationHandle.cpp \ - com_android_server_input_InputManagerService.cpp \ - com_android_server_input_InputWindowHandle.cpp \ - com_android_server_LightsService.cpp \ - com_android_server_power_PowerManagerService.cpp \ - com_android_server_SerialService.cpp \ - com_android_server_SystemServer.cpp \ - com_android_server_UsbDeviceManager.cpp \ - com_android_server_UsbHostManager.cpp \ - com_android_server_VibratorService.cpp \ - com_android_server_location_GpsLocationProvider.cpp \ - com_android_server_location_FlpHardwareProvider.cpp \ - com_android_server_connectivity_Vpn.cpp \ - onload.cpp - -LOCAL_C_INCLUDES += \ - $(JNI_H_INCLUDE) \ - frameworks/base/services \ - frameworks/base/core/jni \ - frameworks/native/services \ - external/skia/include/core \ - libcore/include \ - libcore/include/libsuspend \ - $(call include-path-for, libhardware)/hardware \ - $(call include-path-for, libhardware_legacy)/hardware_legacy \ - -LOCAL_SHARED_LIBRARIES := \ - libandroid_runtime \ - libandroidfw \ - libbinder \ - libcutils \ - liblog \ - libhardware \ - libhardware_legacy \ - libnativehelper \ - libutils \ - libui \ - libinput \ - libinputservice \ - libsensorservice \ - libskia \ - libgui \ - libusbhost \ - libsuspend \ - libEGL \ - libGLESv2 - -LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES - -ifeq ($(WITH_MALLOC_LEAK_CHECK),true) - LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK -endif - -LOCAL_MODULE:= libandroid_servers - -include $(BUILD_SHARED_LIBRARY) diff --git a/services/print/Android.mk b/services/print/Android.mk new file mode 100644 index 000000000000..33604b711159 --- /dev/null +++ b/services/print/Android.mk @@ -0,0 +1,10 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := services.print + +LOCAL_SRC_FILES += \ + $(call all-java-files-under,java) + +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java new file mode 100644 index 000000000000..c6fdbe5c90c8 --- /dev/null +++ b/services/print/java/com/android/server/print/PrintManagerService.java @@ -0,0 +1,689 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.print; + +import android.Manifest; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Binder; +import android.os.Bundle; +import android.os.Process; +import android.os.RemoteException; +import android.os.UserHandle; +import android.print.IPrintDocumentAdapter; +import android.print.IPrintJobStateChangeListener; +import android.print.IPrintManager; +import android.print.IPrinterDiscoveryObserver; +import android.print.PrintAttributes; +import android.print.PrintJobId; +import android.print.PrintJobInfo; +import android.print.PrinterId; +import android.printservice.PrintServiceInfo; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.SparseArray; + +import com.android.internal.R; +import com.android.internal.content.PackageMonitor; +import com.android.internal.os.BackgroundThread; +import com.android.server.SystemService; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +/** + * SystemService wrapper for the PrintManager implementation. Publishes + * Context.PRINT_SERVICE. + * PrintManager implementation is contained within. + */ + +public final class PrintManagerService extends SystemService { + private final PrintManagerImpl mPrintManagerImpl; + + public PrintManagerService(Context context) { + super(context); + mPrintManagerImpl = new PrintManagerImpl(context); + } + + @Override + public void onStart() { + publishBinderService(Context.PRINT_SERVICE, mPrintManagerImpl); + } + + @Override + public void onBootPhase(int phase) { + if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { + mPrintManagerImpl.systemRunning(); + } + } + + class PrintManagerImpl extends IPrintManager.Stub { + private static final char COMPONENT_NAME_SEPARATOR = ':'; + + private static final String EXTRA_PRINT_SERVICE_COMPONENT_NAME = + "EXTRA_PRINT_SERVICE_COMPONENT_NAME"; + + private final Object mLock = new Object(); + + private final Context mContext; + + private final SparseArray<UserState> mUserStates = new SparseArray<UserState>(); + + private int mCurrentUserId = UserHandle.USER_OWNER; + + PrintManagerImpl(Context context) { + mContext = context; + registerContentObservers(); + registerBoradcastReceivers(); + } + + public void systemRunning() { + BackgroundThread.getHandler().post(new Runnable() { + @Override + public void run() { + final UserState userState; + synchronized (mLock) { + userState = getCurrentUserStateLocked(); + userState.updateIfNeededLocked(); + } + // This is the first time we switch to this user after boot, so + // now is the time to remove obsolete print jobs since they + // are from the last boot and no application would query them. + userState.removeObsoletePrintJobs(); + } + }); + } + + @Override + public Bundle print(String printJobName, IPrintDocumentAdapter adapter, + PrintAttributes attributes, String packageName, int appId, int userId) { + final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + String resolvedPackageName = resolveCallingPackageNameEnforcingSecurity(packageName); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + return userState.print(printJobName, adapter, attributes, + resolvedPackageName, resolvedAppId); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public List<PrintJobInfo> getPrintJobInfos(int appId, int userId) { + final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + return userState.getPrintJobInfos(resolvedAppId); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId, int userId) { + final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + return userState.getPrintJobInfo(printJobId, resolvedAppId); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void cancelPrintJob(PrintJobId printJobId, int appId, int userId) { + final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + userState.cancelPrintJob(printJobId, resolvedAppId); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void restartPrintJob(PrintJobId printJobId, int appId, int userId) { + final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + userState.restartPrintJob(printJobId, resolvedAppId); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public List<PrintServiceInfo> getEnabledPrintServices(int userId) { + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + return userState.getEnabledPrintServices(); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public List<PrintServiceInfo> getInstalledPrintServices(int userId) { + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + return userState.getInstalledPrintServices(); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void createPrinterDiscoverySession(IPrinterDiscoveryObserver observer, + int userId) { + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + userState.createPrinterDiscoverySession(observer); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void destroyPrinterDiscoverySession(IPrinterDiscoveryObserver observer, + int userId) { + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + userState.destroyPrinterDiscoverySession(observer); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void startPrinterDiscovery(IPrinterDiscoveryObserver observer, + List<PrinterId> priorityList, int userId) { + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + userState.startPrinterDiscovery(observer, priorityList); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void stopPrinterDiscovery(IPrinterDiscoveryObserver observer, int userId) { + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + userState.stopPrinterDiscovery(observer); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void validatePrinters(List<PrinterId> printerIds, int userId) { + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + userState.validatePrinters(printerIds); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void startPrinterStateTracking(PrinterId printerId, int userId) { + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + userState.startPrinterStateTracking(printerId); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void stopPrinterStateTracking(PrinterId printerId, int userId) { + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + userState.stopPrinterStateTracking(printerId); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener, + int appId, int userId) throws RemoteException { + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + userState.addPrintJobStateChangeListener(listener, resolvedAppId); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void removePrintJobStateChangeListener(IPrintJobStateChangeListener listener, + int userId) { + final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); + final UserState userState; + synchronized (mLock) { + userState = getOrCreateUserStateLocked(resolvedUserId); + } + final long identity = Binder.clearCallingIdentity(); + try { + userState.removePrintJobStateChangeListener(listener); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump PrintManager from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + synchronized (mLock) { + final long identity = Binder.clearCallingIdentity(); + try { + pw.println("PRINT MANAGER STATE (dumpsys print)"); + final int userStateCount = mUserStates.size(); + for (int i = 0; i < userStateCount; i++) { + UserState userState = mUserStates.valueAt(i); + userState.dump(fd, pw, ""); + pw.println(); + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + } + + private void registerContentObservers() { + final Uri enabledPrintServicesUri = Settings.Secure.getUriFor( + Settings.Secure.ENABLED_PRINT_SERVICES); + + ContentObserver observer = new ContentObserver(BackgroundThread.getHandler()) { + @Override + public void onChange(boolean selfChange, Uri uri) { + if (enabledPrintServicesUri.equals(uri)) { + synchronized (mLock) { + UserState userState = getCurrentUserStateLocked(); + userState.updateIfNeededLocked(); + } + } + } + }; + + mContext.getContentResolver().registerContentObserver(enabledPrintServicesUri, + false, observer, UserHandle.USER_ALL); + } + + private void registerBoradcastReceivers() { + PackageMonitor monitor = new PackageMonitor() { + @Override + public boolean onPackageChanged(String packageName, int uid, String[] components) { + synchronized (mLock) { + UserState userState = getOrCreateUserStateLocked(getChangingUserId()); + Iterator<ComponentName> iterator = userState.getEnabledServices() + .iterator(); + while (iterator.hasNext()) { + ComponentName componentName = iterator.next(); + if (packageName.equals(componentName.getPackageName())) { + userState.updateIfNeededLocked(); + return true; + } + } + } + return false; + } + + @Override + public void onPackageRemoved(String packageName, int uid) { + synchronized (mLock) { + UserState userState = getOrCreateUserStateLocked(getChangingUserId()); + Iterator<ComponentName> iterator = userState.getEnabledServices() + .iterator(); + while (iterator.hasNext()) { + ComponentName componentName = iterator.next(); + if (packageName.equals(componentName.getPackageName())) { + iterator.remove(); + persistComponentNamesToSettingLocked( + Settings.Secure.ENABLED_PRINT_SERVICES, + userState.getEnabledServices(), getChangingUserId()); + userState.updateIfNeededLocked(); + return; + } + } + } + } + + @Override + public boolean onHandleForceStop(Intent intent, String[] stoppedPackages, + int uid, boolean doit) { + synchronized (mLock) { + UserState userState = getOrCreateUserStateLocked(getChangingUserId()); + boolean stoppedSomePackages = false; + Iterator<ComponentName> iterator = userState.getEnabledServices() + .iterator(); + while (iterator.hasNext()) { + ComponentName componentName = iterator.next(); + String componentPackage = componentName.getPackageName(); + for (String stoppedPackage : stoppedPackages) { + if (componentPackage.equals(stoppedPackage)) { + if (!doit) { + return true; + } + stoppedSomePackages = true; + break; + } + } + } + if (stoppedSomePackages) { + userState.updateIfNeededLocked(); + } + return false; + } + } + + @Override + public void onPackageAdded(String packageName, int uid) { + Intent intent = new Intent(android.printservice.PrintService.SERVICE_INTERFACE); + intent.setPackage(packageName); + + List<ResolveInfo> installedServices = mContext.getPackageManager() + .queryIntentServicesAsUser(intent, PackageManager.GET_SERVICES, + getChangingUserId()); + + if (installedServices == null) { + return; + } + + final int installedServiceCount = installedServices.size(); + for (int i = 0; i < installedServiceCount; i++) { + ServiceInfo serviceInfo = installedServices.get(i).serviceInfo; + ComponentName component = new ComponentName(serviceInfo.packageName, + serviceInfo.name); + String label = serviceInfo.loadLabel(mContext.getPackageManager()) + .toString(); + showEnableInstalledPrintServiceNotification(component, label, + getChangingUserId()); + } + } + + private void persistComponentNamesToSettingLocked(String settingName, + Set<ComponentName> componentNames, int userId) { + StringBuilder builder = new StringBuilder(); + for (ComponentName componentName : componentNames) { + if (builder.length() > 0) { + builder.append(COMPONENT_NAME_SEPARATOR); + } + builder.append(componentName.flattenToShortString()); + } + Settings.Secure.putStringForUser(mContext.getContentResolver(), + settingName, builder.toString(), userId); + } + }; + + // package changes + monitor.register(mContext, BackgroundThread.getHandler().getLooper(), + UserHandle.ALL, true); + + // user changes + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(Intent.ACTION_USER_SWITCHED); + intentFilter.addAction(Intent.ACTION_USER_REMOVED); + + mContext.registerReceiverAsUser(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (Intent.ACTION_USER_SWITCHED.equals(action)) { + switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); + } else if (Intent.ACTION_USER_REMOVED.equals(action)) { + removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); + } + } + }, UserHandle.ALL, intentFilter, null, BackgroundThread.getHandler()); + } + + private UserState getCurrentUserStateLocked() { + return getOrCreateUserStateLocked(mCurrentUserId); + } + + private UserState getOrCreateUserStateLocked(int userId) { + UserState userState = mUserStates.get(userId); + if (userState == null) { + userState = new UserState(mContext, userId, mLock); + mUserStates.put(userId, userState); + } + return userState; + } + + private void switchUser(int newUserId) { + UserState userState; + synchronized (mLock) { + if (newUserId == mCurrentUserId) { + return; + } + mCurrentUserId = newUserId; + userState = mUserStates.get(mCurrentUserId); + if (userState == null) { + userState = getCurrentUserStateLocked(); + userState.updateIfNeededLocked(); + } else { + userState.updateIfNeededLocked(); + } + } + // This is the first time we switch to this user after boot, so + // now is the time to remove obsolete print jobs since they + // are from the last boot and no application would query them. + userState.removeObsoletePrintJobs(); + } + + private void removeUser(int removedUserId) { + synchronized (mLock) { + UserState userState = mUserStates.get(removedUserId); + if (userState != null) { + userState.destroyLocked(); + mUserStates.remove(removedUserId); + } + } + } + + private int resolveCallingAppEnforcingPermissions(int appId) { + final int callingUid = Binder.getCallingUid(); + if (callingUid == 0 || callingUid == Process.SYSTEM_UID + || callingUid == Process.SHELL_UID) { + return appId; + } + final int callingAppId = UserHandle.getAppId(callingUid); + if (appId == callingAppId) { + return appId; + } + if (mContext.checkCallingPermission( + "com.android.printspooler.permission.ACCESS_ALL_PRINT_JOBS") + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Call from app " + callingAppId + " as app " + + appId + " without com.android.printspooler.permission" + + ".ACCESS_ALL_PRINT_JOBS"); + } + return appId; + } + + private int resolveCallingUserEnforcingPermissions(int userId) { + final int callingUid = Binder.getCallingUid(); + if (callingUid == 0 || callingUid == Process.SYSTEM_UID + || callingUid == Process.SHELL_UID) { + return userId; + } + final int callingUserId = UserHandle.getUserId(callingUid); + if (callingUserId == userId) { + return userId; + } + if (mContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL) + != PackageManager.PERMISSION_GRANTED + || mContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS) + != PackageManager.PERMISSION_GRANTED) { + if (userId == UserHandle.USER_CURRENT_OR_SELF) { + return callingUserId; + } + throw new SecurityException("Call from user " + callingUserId + " as user " + + userId + " without permission INTERACT_ACROSS_USERS or " + + "INTERACT_ACROSS_USERS_FULL not allowed."); + } + if (userId == UserHandle.USER_CURRENT || userId == UserHandle.USER_CURRENT_OR_SELF) { + return mCurrentUserId; + } + throw new IllegalArgumentException("Calling user can be changed to only " + + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF."); + } + + private String resolveCallingPackageNameEnforcingSecurity(String packageName) { + if (TextUtils.isEmpty(packageName)) { + return null; + } + String[] packages = mContext.getPackageManager().getPackagesForUid( + Binder.getCallingUid()); + final int packageCount = packages.length; + for (int i = 0; i < packageCount; i++) { + if (packageName.equals(packages[i])) { + return packageName; + } + } + return null; + } + + private void showEnableInstalledPrintServiceNotification(ComponentName component, + String label, int userId) { + UserHandle userHandle = new UserHandle(userId); + + Intent intent = new Intent(Settings.ACTION_PRINT_SETTINGS); + intent.putExtra(EXTRA_PRINT_SERVICE_COMPONENT_NAME, component.flattenToString()); + + PendingIntent pendingIntent = PendingIntent.getActivityAsUser(mContext, 0, intent, + PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT, null, + userHandle); + + Notification.Builder builder = new Notification.Builder(mContext) + .setSmallIcon(R.drawable.ic_print) + .setContentTitle(mContext.getString(R.string.print_service_installed_title, + label)) + .setContentText(mContext.getString(R.string.print_service_installed_message)) + .setContentIntent(pendingIntent) + .setWhen(System.currentTimeMillis()) + .setAutoCancel(true) + .setShowWhen(true); + + NotificationManager notificationManager = (NotificationManager) mContext + .getSystemService(Context.NOTIFICATION_SERVICE); + + String notificationTag = getClass().getName() + ":" + component.flattenToString(); + notificationManager.notifyAsUser(notificationTag, 0, builder.build(), + userHandle); + } + } +} diff --git a/services/java/com/android/server/print/RemotePrintService.java b/services/print/java/com/android/server/print/RemotePrintService.java index 1bb61d246eb8..1bb61d246eb8 100644 --- a/services/java/com/android/server/print/RemotePrintService.java +++ b/services/print/java/com/android/server/print/RemotePrintService.java diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java index ffe9806a2418..ffe9806a2418 100644 --- a/services/java/com/android/server/print/RemotePrintSpooler.java +++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java diff --git a/services/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java index f23a992cd58f..f23a992cd58f 100644 --- a/services/java/com/android/server/print/UserState.java +++ b/services/print/java/com/android/server/print/UserState.java diff --git a/services/tests/Android.mk b/services/tests/Android.mk new file mode 100644 index 000000000000..40369ee2ec5c --- /dev/null +++ b/services/tests/Android.mk @@ -0,0 +1,3 @@ +LOCAL_PATH:= $(call my-dir) + +include $(call all-makefiles-under, $(LOCAL_PATH)) diff --git a/services/usb/Android.mk b/services/usb/Android.mk new file mode 100644 index 000000000000..feabf0a970c2 --- /dev/null +++ b/services/usb/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := services.usb + +LOCAL_SRC_FILES += \ + $(call all-java-files-under,java) + +LOCAL_JAVA_LIBRARIES := services.core + +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/services/java/com/android/server/usb/UsbDebuggingManager.java b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java index ce953a4b134e..ce953a4b134e 100644 --- a/services/java/com/android/server/usb/UsbDebuggingManager.java +++ b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 8a5e2914f562..bef33b9406c6 100644 --- a/services/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -832,7 +832,7 @@ public class UsbDeviceManager { if (mOemModeMap == null) { mOemModeMap = new HashMap<String, List<Pair<String, String>>>(); } - List overrideList = mOemModeMap.get(items[0]); + List<Pair<String, String>> overrideList = mOemModeMap.get(items[0]); if (overrideList == null) { overrideList = new LinkedList<Pair<String, String>>(); mOemModeMap.put(items[0], overrideList); diff --git a/services/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java index dfaad0bcece9..dfaad0bcece9 100644 --- a/services/java/com/android/server/usb/UsbHostManager.java +++ b/services/usb/java/com/android/server/usb/UsbHostManager.java diff --git a/services/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java index 36669b1a8178..b6ae192234fc 100644 --- a/services/java/com/android/server/usb/UsbService.java +++ b/services/usb/java/com/android/server/usb/UsbService.java @@ -32,6 +32,7 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; +import com.android.server.SystemService; import java.io.File; import java.io.FileDescriptor; @@ -43,6 +44,28 @@ import java.io.PrintWriter; * support is delegated to UsbDeviceManager. */ public class UsbService extends IUsbManager.Stub { + + public static class Lifecycle extends SystemService { + private UsbService mUsbService; + + public Lifecycle(Context context) { + super(context); + } + + @Override + public void onStart() { + mUsbService = new UsbService(getContext()); + publishBinderService(Context.USB_SERVICE, mUsbService); + } + + @Override + public void onBootPhase(int phase) { + if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { + mUsbService.systemReady(); + } + } + } + private static final String TAG = "UsbService"; private final Context mContext; diff --git a/services/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java index ff4857ba1be8..ff4857ba1be8 100644 --- a/services/java/com/android/server/usb/UsbSettingsManager.java +++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java diff --git a/tests/DozeTest/Android.mk b/tests/DozeTest/Android.mk new file mode 100644 index 000000000000..01f10e5ac1de --- /dev/null +++ b/tests/DozeTest/Android.mk @@ -0,0 +1,14 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +# Only compile source java files in this apk. +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := DozeTest + +include $(BUILD_PACKAGE) + +# Use the following include to make our test apk. +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/tests/DozeTest/AndroidManifest.xml b/tests/DozeTest/AndroidManifest.xml new file mode 100644 index 000000000000..c199f69aeb1e --- /dev/null +++ b/tests/DozeTest/AndroidManifest.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.dreams.dozetest"> + <uses-permission android:name="android.permission.WAKE_LOCK" /> + + <application android:label="@string/app_name"> + <service + android:name="DozeTestDream" + android:exported="true" + android:icon="@drawable/ic_app" + android:label="@string/doze_dream_name"> + <!-- Commented out to prevent this dream from appearing in the list of + dreams that the user can select via the Settings application. + <intent-filter> + <action android:name="android.service.dreams.DreamService" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + --> + </service> + </application> +</manifest> diff --git a/tests/DozeTest/res/drawable-hdpi/ic_app.png b/tests/DozeTest/res/drawable-hdpi/ic_app.png Binary files differnew file mode 100755 index 000000000000..66a198496cfb --- /dev/null +++ b/tests/DozeTest/res/drawable-hdpi/ic_app.png diff --git a/tests/DozeTest/res/drawable-mdpi/ic_app.png b/tests/DozeTest/res/drawable-mdpi/ic_app.png Binary files differnew file mode 100644 index 000000000000..5ae7701a8a85 --- /dev/null +++ b/tests/DozeTest/res/drawable-mdpi/ic_app.png diff --git a/tests/DozeTest/res/layout/dream.xml b/tests/DozeTest/res/layout/dream.xml new file mode 100644 index 000000000000..1c8fd3fccbf4 --- /dev/null +++ b/tests/DozeTest/res/layout/dream.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:orientation="vertical"> + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/alarm_clock_label" /> + <TextView android:id="@+id/alarm_clock" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + + <Space + android:layout_width="match_parent" + android:layout_height="32dp" /> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/tick_clock_label" /> + <TextClock android:id="@+id/tick_clock" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> +</LinearLayout> diff --git a/tests/DozeTest/res/values/strings.xml b/tests/DozeTest/res/values/strings.xml new file mode 100644 index 000000000000..f21911fdffe0 --- /dev/null +++ b/tests/DozeTest/res/values/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<resources> + <!-- Name of the package of basic screensavers, shown in Settings > Apps. [CHAR LIMIT=40] --> + <string name="app_name">Doze Test</string> + + <!-- Name of the screensaver. [CHAR LIMIT=40] --> + <string name="doze_dream_name">Doze Test</string> + + <string name="alarm_clock_label">This clock is updated using the Alarm Manager</string> + <string name="tick_clock_label">This clock is updated using TIME_TICK Broadcasts</string> +</resources> diff --git a/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java b/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java new file mode 100644 index 000000000000..bf35db4ac118 --- /dev/null +++ b/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java @@ -0,0 +1,165 @@ +/* + * 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.dreams.dozetest; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.PowerManager; +import android.service.dreams.DozeHardware; +import android.service.dreams.DreamService; +import android.text.format.DateFormat; +import android.util.Log; +import android.widget.TextView; + +import java.util.Date; + +/** + * Simple test for doze mode. + * <p> + * adb shell setprop debug.doze.component com.android.dreams.dozetest/.DozeTestDream + * </p> + */ +public class DozeTestDream extends DreamService { + private static final String TAG = DozeTestDream.class.getSimpleName(); + private static final boolean DEBUG = false; + + // Amount of time to allow to update the time shown on the screen before releasing + // the wakelock. This timeout is design to compensate for the fact that we don't + // currently have a way to know when time display contents have actually been + // refreshed once the dream has finished rendering a new frame. + private static final int UPDATE_TIME_TIMEOUT = 100; + + // A doze hardware message string we use for end-to-end testing. + // Doesn't mean anything. Real hardware won't handle it. + private static final String TEST_PING_MESSAGE = "test.ping"; + + private PowerManager mPowerManager; + private PowerManager.WakeLock mWakeLock; + private AlarmManager mAlarmManager; + private PendingIntent mAlarmIntent; + + private TextView mAlarmClock; + + private final Date mTime = new Date(); + private java.text.DateFormat mTimeFormat; + + private boolean mDreaming; + private DozeHardware mDozeHardware; + + @Override + public void onCreate() { + super.onCreate(); + + mPowerManager = (PowerManager)getSystemService(Context.POWER_SERVICE); + mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); + + mAlarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE); + + Intent intent = new Intent("com.android.dreams.dozetest.ACTION_ALARM"); + intent.setPackage(getPackageName()); + IntentFilter filter = new IntentFilter(); + filter.addAction(intent.getAction()); + registerReceiver(mAlarmReceiver, filter); + mAlarmIntent = PendingIntent.getBroadcast(this, 0, intent, + PendingIntent.FLAG_CANCEL_CURRENT); + } + + @Override + public void onDestroy() { + super.onDestroy(); + + unregisterReceiver(mAlarmReceiver); + mAlarmIntent.cancel(); + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + setInteractive(false); + setLowProfile(true); + setFullscreen(true); + setContentView(R.layout.dream); + + mAlarmClock = (TextView)findViewById(R.id.alarm_clock); + + mTimeFormat = DateFormat.getTimeFormat(this); + } + + @Override + public void onDreamingStarted() { + super.onDreamingStarted(); + + mDreaming = true; + mDozeHardware = getDozeHardware(); + + Log.d(TAG, "Dream started: canDoze=" + canDoze() + + ", dozeHardware=" + mDozeHardware); + + performTimeUpdate(); + + if (mDozeHardware != null) { + mDozeHardware.sendMessage(TEST_PING_MESSAGE, null); + mDozeHardware.setEnableMcu(true); + } + startDozing(); + } + + @Override + public void onDreamingStopped() { + super.onDreamingStopped(); + + mDreaming = false; + if (mDozeHardware != null) { + mDozeHardware.setEnableMcu(false); + mDozeHardware = null; + } + + Log.d(TAG, "Dream ended: isDozing=" + isDozing()); + + stopDozing(); + cancelTimeUpdate(); + } + + private void performTimeUpdate() { + if (mDreaming) { + long now = System.currentTimeMillis(); + now -= now % 60000; // back up to last minute boundary + + mTime.setTime(now); + mAlarmClock.setText(mTimeFormat.format(mTime)); + + mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, now + 60000, mAlarmIntent); + + mWakeLock.acquire(UPDATE_TIME_TIMEOUT); + } + } + + private void cancelTimeUpdate() { + mAlarmManager.cancel(mAlarmIntent); + } + + private final BroadcastReceiver mAlarmReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + performTimeUpdate(); + } + }; +} diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp index d8e113a2d140..62200d91996a 100644 --- a/tools/aapt/AaptAssets.cpp +++ b/tools/aapt/AaptAssets.cpp @@ -1631,9 +1631,18 @@ String8 AaptFile::getPrintableSource() const // ========================================================================= // ========================================================================= -status_t AaptGroup::addFile(const sp<AaptFile>& file) +status_t AaptGroup::addFile(const sp<AaptFile>& file, const bool overwriteDuplicate) { - if (mFiles.indexOfKey(file->getGroupEntry()) < 0) { + ssize_t index = mFiles.indexOfKey(file->getGroupEntry()); + if (index >= 0 && overwriteDuplicate) { + fprintf(stderr, "warning: overwriting '%s' with '%s'\n", + mFiles[index]->getSourceFile().string(), + file->getSourceFile().string()); + removeFile(index); + index = -1; + } + + if (index < 0) { file->mPath = mPath; mFiles.add(file->getGroupEntry(), file); return NO_ERROR; @@ -1739,7 +1748,8 @@ void AaptDir::removeDir(const String8& name) mDirs.removeItem(name); } -status_t AaptDir::addLeafFile(const String8& leafName, const sp<AaptFile>& file) +status_t AaptDir::addLeafFile(const String8& leafName, const sp<AaptFile>& file, + const bool overwrite) { sp<AaptGroup> group; if (mFiles.indexOfKey(leafName) >= 0) { @@ -1749,12 +1759,12 @@ status_t AaptDir::addLeafFile(const String8& leafName, const sp<AaptFile>& file) mFiles.add(leafName, group); } - return group->addFile(file); + return group->addFile(file, overwrite); } ssize_t AaptDir::slurpFullTree(Bundle* bundle, const String8& srcDir, const AaptGroupEntry& kind, const String8& resType, - sp<FilePathStore>& fullResPaths) + sp<FilePathStore>& fullResPaths, const bool overwrite) { Vector<String8> fileNames; { @@ -1813,7 +1823,7 @@ ssize_t AaptDir::slurpFullTree(Bundle* bundle, const String8& srcDir, notAdded = true; } ssize_t res = subdir->slurpFullTree(bundle, pathName, kind, - resType, fullResPaths); + resType, fullResPaths, overwrite); if (res < NO_ERROR) { return res; } @@ -1823,7 +1833,7 @@ ssize_t AaptDir::slurpFullTree(Bundle* bundle, const String8& srcDir, count += res; } else if (type == kFileTypeRegular) { sp<AaptFile> file = new AaptFile(pathName, kind, resType); - status_t err = addLeafFile(fileNames[i], file); + status_t err = addLeafFile(fileNames[i], file, overwrite); if (err != NO_ERROR) { return err; } @@ -2089,24 +2099,24 @@ ssize_t AaptAssets::slurpFromArgs(Bundle* bundle) /* * If a directory of custom assets was supplied, slurp 'em up. */ - if (bundle->getAssetSourceDir()) { - const char* assetDir = bundle->getAssetSourceDir(); - - FileType type = getFileType(assetDir); + const Vector<const char*>& assetDirs = bundle->getAssetSourceDirs(); + const int AN = assetDirs.size(); + for (int i = 0; i < AN; i++) { + FileType type = getFileType(assetDirs[i]); if (type == kFileTypeNonexistent) { - fprintf(stderr, "ERROR: asset directory '%s' does not exist\n", assetDir); + fprintf(stderr, "ERROR: asset directory '%s' does not exist\n", assetDirs[i]); return UNKNOWN_ERROR; } if (type != kFileTypeDirectory) { - fprintf(stderr, "ERROR: '%s' is not a directory\n", assetDir); + fprintf(stderr, "ERROR: '%s' is not a directory\n", assetDirs[i]); return UNKNOWN_ERROR; } - String8 assetRoot(assetDir); + String8 assetRoot(assetDirs[i]); sp<AaptDir> assetAaptDir = makeDir(String8(kAssetDir)); AaptGroupEntry group; count = assetAaptDir->slurpFullTree(bundle, assetRoot, group, - String8(), mFullAssetPaths); + String8(), mFullAssetPaths, true); if (count < 0) { totalCount = count; goto bail; @@ -2116,9 +2126,10 @@ ssize_t AaptAssets::slurpFromArgs(Bundle* bundle) } totalCount += count; - if (bundle->getVerbose()) + if (bundle->getVerbose()) { printf("Found %d custom asset file%s in %s\n", - count, (count==1) ? "" : "s", assetDir); + count, (count==1) ? "" : "s", assetDirs[i]); + } } /* diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h index 5cfa91350063..9cc9007e4d48 100644 --- a/tools/aapt/AaptAssets.h +++ b/tools/aapt/AaptAssets.h @@ -235,7 +235,7 @@ public: const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& getFiles() const { return mFiles; } - status_t addFile(const sp<AaptFile>& file); + status_t addFile(const sp<AaptFile>& file, const bool overwriteDuplicate=false); void removeFile(size_t index); void print(const String8& prefix) const; @@ -301,12 +301,14 @@ private: status_t addDir(const String8& name, const sp<AaptDir>& dir); sp<AaptDir> makeDir(const String8& name); status_t addLeafFile(const String8& leafName, - const sp<AaptFile>& file); + const sp<AaptFile>& file, + const bool overwrite=false); virtual ssize_t slurpFullTree(Bundle* bundle, const String8& srcDir, const AaptGroupEntry& kind, const String8& resType, - sp<FilePathStore>& fullResPaths); + sp<FilePathStore>& fullResPaths, + const bool overwrite=false); String8 mLeaf; String8 mPath; diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h index 5089b9de28a8..26b10a65f79d 100644 --- a/tools/aapt/Bundle.h +++ b/tools/aapt/Bundle.h @@ -55,7 +55,6 @@ public: mCompressionMethod(0), mJunkPath(false), mOutputAPKFile(NULL), mManifestPackageNameOverride(NULL), mInstrumentationPackageNameOverride(NULL), mAutoAddOverlay(false), mGenDependencies(false), - mAssetSourceDir(NULL), mCrunchedOutputDir(NULL), mProguardFile(NULL), mAndroidManifestFile(NULL), mPublicOutputFile(NULL), mRClassDir(NULL), mResourceIntermediatesDir(NULL), mManifestMinSdkVersion(NULL), @@ -123,8 +122,8 @@ public: /* * Input options. */ - const char* getAssetSourceDir() const { return mAssetSourceDir; } - void setAssetSourceDir(const char* dir) { mAssetSourceDir = dir; } + const android::Vector<const char*>& getAssetSourceDirs() const { return mAssetSourceDirs; } + void addAssetSourceDir(const char* dir) { mAssetSourceDirs.insertAt(dir,0); } const char* getCrunchedOutputDir() const { return mCrunchedOutputDir; } void setCrunchedOutputDir(const char* dir) { mCrunchedOutputDir = dir; } const char* getProguardFile() const { return mProguardFile; } @@ -272,6 +271,7 @@ private: android::Vector<const char*> mPackageIncludes; android::Vector<const char*> mJarFiles; android::Vector<const char*> mNoCompressExtensions; + android::Vector<const char*> mAssetSourceDirs; android::Vector<const char*> mResourceSourceDirs; const char* mManifestMinSdkVersion; diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 8a6faed585a2..5d4232d97537 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -1896,7 +1896,7 @@ int doPackage(Bundle* bundle) N = bundle->getFileSpecCount(); if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0 - && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDir() == NULL) { + && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDirs().size() == 0) { fprintf(stderr, "ERROR: no input files\n"); goto bail; } diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp index 977226b61471..d1d3deb0106b 100644 --- a/tools/aapt/Main.cpp +++ b/tools/aapt/Main.cpp @@ -345,7 +345,7 @@ int main(int argc, char* const argv[]) goto bail; } convertPath(argv[0]); - bundle.setAssetSourceDir(argv[0]); + bundle.addAssetSourceDir(argv[0]); break; case 'G': argc--; |