summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.txt143
-rw-r--r--api/system-current.txt149
-rw-r--r--api/test-current.txt144
-rw-r--r--cmds/bootanimation/Android.mk3
-rw-r--r--cmds/bootanimation/BootAnimation.cpp40
-rw-r--r--cmds/bootanimation/BootAnimation.h1
-rw-r--r--cmds/bootanimation/bootanim.rc4
-rw-r--r--core/java/android/animation/AnimatorSet.java10
-rw-r--r--core/java/android/app/Activity.java88
-rw-r--r--core/java/android/app/ActivityManager.java52
-rw-r--r--core/java/android/app/ActivityThread.java67
-rw-r--r--core/java/android/app/AppOpsManager.java20
-rw-r--r--core/java/android/app/ApplicationPackageManager.java4
-rw-r--r--core/java/android/app/ContextImpl.java12
-rw-r--r--core/java/android/app/Fragment.java54
-rw-r--r--core/java/android/app/FragmentController.java29
-rw-r--r--core/java/android/app/FragmentManager.java42
-rw-r--r--core/java/android/app/IApplicationThread.aidl7
-rw-r--r--core/java/android/app/IServiceConnection.aidl2
-rw-r--r--core/java/android/app/LoadedApk.java36
-rw-r--r--core/java/android/app/ResourcesManager.java2
-rw-r--r--core/java/android/app/admin/DeviceAdminService.java56
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java10
-rw-r--r--core/java/android/app/admin/IDeviceAdminService.aidl23
-rw-r--r--core/java/android/content/Context.java14
-rw-r--r--core/java/android/content/Intent.java70
-rw-r--r--core/java/android/content/ServiceConnection.java17
-rw-r--r--core/java/android/content/pm/ILauncherApps.aidl3
-rw-r--r--core/java/android/content/pm/LauncherApps.java21
-rw-r--r--core/java/android/content/pm/PackageManager.java1
-rw-r--r--core/java/android/content/pm/PackageManagerInternal.java8
-rw-r--r--core/java/android/content/pm/ShortcutInfo.java185
-rw-r--r--core/java/android/content/pm/ShortcutServiceInternal.java4
-rw-r--r--core/java/android/content/res/Configuration.java68
-rw-r--r--core/java/android/hardware/display/DisplayManagerInternal.java10
-rw-r--r--core/java/android/hardware/usb/UsbRequest.java38
-rw-r--r--core/java/android/net/INetworkPolicyManager.aidl3
-rwxr-xr-xcore/java/android/provider/Settings.java4
-rw-r--r--core/java/android/service/quicksettings/TileService.java13
-rw-r--r--core/java/android/view/Display.java4
-rw-r--r--core/java/android/view/DisplayInfo.java10
-rw-r--r--core/java/android/view/FocusFinder.java2
-rw-r--r--core/java/android/view/View.java2
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java13
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java164
-rw-r--r--core/java/com/android/internal/policy/BackdropFrameRenderer.java17
-rw-r--r--core/java/com/android/internal/policy/DecorView.java122
-rw-r--r--core/jni/android_hardware_UsbRequest.cpp6
-rw-r--r--core/jni/android_view_Surface.cpp22
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp5
-rw-r--r--core/jni/include/android_runtime/android_view_Surface.h4
-rw-r--r--core/res/AndroidManifest.xml24
-rw-r--r--core/res/res/values/attrs.xml5
-rw-r--r--core/res/res/values/config.xml3
-rw-r--r--core/res/res/values/strings.xml10
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java102
-rw-r--r--core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java8
-rw-r--r--data/etc/platform.xml3
-rw-r--r--graphics/java/android/graphics/Color.java2
-rw-r--r--graphics/java/android/graphics/Rect.java7
-rw-r--r--media/java/android/media/AudioManager.java44
-rw-r--r--media/java/android/media/IAudioService.aidl9
-rw-r--r--media/java/android/media/MediaRecorder.java18
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicy.java89
-rw-r--r--media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl5
-rw-r--r--media/java/android/media/tv/TvContract.java121
-rw-r--r--native/android/libandroid.map.txt1
-rw-r--r--native/android/native_window_jni.cpp9
-rw-r--r--packages/SettingsLib/res/values/attrs.xml3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java21
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java9
-rwxr-xr-xpackages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java2
-rwxr-xr-xpackages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java6
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java9
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java64
-rw-r--r--packages/SystemUI/Android.mk1
-rw-r--r--packages/SystemUI/res/anim/ic_bluetooth_transient_group_1_animation.xml59
-rw-r--r--packages/SystemUI/res/anim/ic_bluetooth_transient_group_2_animation.xml52
-rw-r--r--packages/SystemUI/res/anim/ic_signal_wifi_transient_wifi_1_animation.xml66
-rw-r--r--packages/SystemUI/res/drawable/ic_bluetooth_transient.xml97
-rw-r--r--packages/SystemUI/res/drawable/ic_bluetooth_transient_animation.xml11
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_wifi_transient.xml39
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_wifi_transient_animation.xml8
-rw-r--r--packages/SystemUI/res/interpolator/ic_bluetooth_transient_animation_interpolator_0.xml4
-rw-r--r--packages/SystemUI/res/layout/menu_ime.xml1
-rw-r--r--packages/SystemUI/res/values/attrs.xml2
-rw-r--r--packages/SystemUI/res/values/strings.xml27
-rw-r--r--packages/SystemUI/src/com/android/systemui/BatteryMeterView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java12
-rw-r--r--packages/SystemUI/tests/Android.mk1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java97
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java8
-rw-r--r--proto/src/metrics_constants.proto16
-rw-r--r--proto/src/system_messages.proto12
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java17
-rw-r--r--services/autofill/java/com/android/server/autofill/ViewState.java2
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java173
-rw-r--r--services/core/java/com/android/server/SystemService.java11
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java19
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java115
-rw-r--r--services/core/java/com/android/server/am/ActivityRecord.java117
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java184
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java126
-rw-r--r--services/core/java/com/android/server/am/ActivityStartInterceptor.java4
-rw-r--r--services/core/java/com/android/server/am/ActivityStarter.java134
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java1
-rw-r--r--services/core/java/com/android/server/am/BaseErrorDialog.java1
-rw-r--r--services/core/java/com/android/server/am/PersistentConnection.java168
-rw-r--r--services/core/java/com/android/server/am/PinnedActivityStack.java15
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java36
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java4
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java4
-rw-r--r--services/core/java/com/android/server/am/TaskRecord.java121
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java39
-rw-r--r--services/core/java/com/android/server/audio/FocusRequester.java50
-rw-r--r--services/core/java/com/android/server/audio/MediaFocusControl.java202
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java17
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplay.java21
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java11
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java168
-rw-r--r--services/core/java/com/android/server/notification/RankingHelper.java2
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java25
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java196
-rw-r--r--services/core/java/com/android/server/pm/Settings.java2
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java93
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java43
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java5
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java6
-rw-r--r--services/core/java/com/android/server/power/ShutdownThread.java17
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java8
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarShellCommand.java9
-rw-r--r--services/core/java/com/android/server/wm/AppWindowContainerController.java2
-rw-r--r--services/core/java/com/android/server/wm/BoundsAnimationController.java115
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java74
-rw-r--r--services/core/java/com/android/server/wm/DockedStackDividerController.java19
-rw-r--r--services/core/java/com/android/server/wm/SnapshotStartingData.java5
-rw-r--r--services/core/java/com/android/server/wm/StackWindowController.java19
-rw-r--r--services/core/java/com/android/server/wm/StackWindowListener.java6
-rw-r--r--services/core/java/com/android/server/wm/Task.java6
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java14
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotSurface.java295
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java8
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java20
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java211
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java85
-rw-r--r--services/java/com/android/server/SystemServer.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java85
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java239
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java70
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java135
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java82
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/AppBoundsTests.java144
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java57
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java19
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java21
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java154
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java15
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java48
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java76
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java308
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java249
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java13
-rw-r--r--services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java7
-rw-r--r--services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java41
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java1
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java57
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyIntents.java8
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java4
-rw-r--r--tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTestBase.java14
189 files changed, 5535 insertions, 2451 deletions
diff --git a/Android.mk b/Android.mk
index eb649c9152c3..634272b1d7ea 100644
--- a/Android.mk
+++ b/Android.mk
@@ -102,6 +102,7 @@ LOCAL_SRC_FILES += \
core/java/android/app/IUserSwitchObserver.aidl \
core/java/android/app/IWallpaperManager.aidl \
core/java/android/app/IWallpaperManagerCallback.aidl \
+ core/java/android/app/admin/IDeviceAdminService.aidl \
core/java/android/app/admin/IDevicePolicyManager.aidl \
core/java/android/app/trust/IStrongAuthTracker.aidl \
core/java/android/app/trust/ITrustManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index 392b60dc9c80..5926e9876364 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -104,7 +104,7 @@ package android {
field public static final java.lang.String READ_FRAME_BUFFER = "android.permission.READ_FRAME_BUFFER";
field public static final deprecated java.lang.String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE";
field public static final java.lang.String READ_LOGS = "android.permission.READ_LOGS";
- field public static final java.lang.String READ_PHONE_NUMBER = "android.permission.READ_PHONE_NUMBER";
+ field public static final java.lang.String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS";
field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
@@ -3675,7 +3675,8 @@ package android.app {
method public boolean onMenuItemSelected(int, android.view.MenuItem);
method public boolean onMenuOpened(int, android.view.Menu);
method public void onMovedToDisplay(int, android.content.res.Configuration);
- method public void onMultiWindowModeChanged(boolean);
+ method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onNavigateUp();
method public boolean onNavigateUpFromChild(android.app.Activity);
method protected void onNewIntent(android.content.Intent);
@@ -3683,7 +3684,8 @@ package android.app {
method public void onOptionsMenuClosed(android.view.Menu);
method public void onPanelClosed(int, android.view.Menu);
method protected void onPause();
- method public void onPictureInPictureModeChanged(boolean);
+ method public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onPictureInPictureModeChanged(boolean);
method protected void onPostCreate(android.os.Bundle);
method public void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
method protected void onPostResume();
@@ -4180,7 +4182,7 @@ package android.app {
field public static final java.lang.String OPSTR_READ_CELL_BROADCASTS = "android:read_cell_broadcasts";
field public static final java.lang.String OPSTR_READ_CONTACTS = "android:read_contacts";
field public static final java.lang.String OPSTR_READ_EXTERNAL_STORAGE = "android:read_external_storage";
- field public static final java.lang.String OPSTR_READ_PHONE_NUMBER = "android:read_phone_number";
+ field public static final java.lang.String OPSTR_READ_PHONE_NUMBERS = "android:read_phone_numbers";
field public static final java.lang.String OPSTR_READ_PHONE_STATE = "android:read_phone_state";
field public static final java.lang.String OPSTR_READ_SMS = "android:read_sms";
field public static final java.lang.String OPSTR_RECEIVE_MMS = "android:receive_mms";
@@ -4616,11 +4618,13 @@ package android.app {
method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
method public void onLowMemory();
- method public void onMultiWindowModeChanged(boolean);
+ method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onOptionsItemSelected(android.view.MenuItem);
method public void onOptionsMenuClosed(android.view.Menu);
method public void onPause();
- method public void onPictureInPictureModeChanged(boolean);
+ method public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onPictureInPictureModeChanged(boolean);
method public void onPrepareOptionsMenu(android.view.Menu);
method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
method public void onResume();
@@ -4705,11 +4709,13 @@ package android.app {
method public void dispatchDestroy();
method public void dispatchDestroyView();
method public void dispatchLowMemory();
- method public void dispatchMultiWindowModeChanged(boolean);
+ method public deprecated void dispatchMultiWindowModeChanged(boolean);
+ method public void dispatchMultiWindowModeChanged(boolean, android.content.res.Configuration);
method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
method public void dispatchOptionsMenuClosed(android.view.Menu);
method public void dispatchPause();
- method public void dispatchPictureInPictureModeChanged(boolean);
+ method public deprecated void dispatchPictureInPictureModeChanged(boolean);
+ method public void dispatchPictureInPictureModeChanged(boolean, android.content.res.Configuration);
method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
method public void dispatchResume();
method public void dispatchStart();
@@ -6226,6 +6232,11 @@ package android.app.admin {
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
}
+ public class DeviceAdminService extends android.app.Service {
+ ctor public DeviceAdminService();
+ method public final android.os.IBinder onBind(android.content.Intent);
+ }
+
public class DevicePolicyManager {
method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@@ -6392,6 +6403,7 @@ package android.app.admin {
method public void wipeData(int);
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
field public static final java.lang.String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
+ field public static final java.lang.String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
field public static final java.lang.String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
field public static final java.lang.String ACTION_PROVISIONING_SUCCESSFUL = "android.app.action.PROVISIONING_SUCCESSFUL";
@@ -9264,6 +9276,8 @@ package android.content {
field public static final java.lang.String ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT";
field public static final java.lang.String ACTION_DATE_CHANGED = "android.intent.action.DATE_CHANGED";
field public static final java.lang.String ACTION_DEFAULT = "android.intent.action.VIEW";
+ field public static final java.lang.String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED";
+ field public static final java.lang.String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_SUBSCRIPTION_CHANGED";
field public static final java.lang.String ACTION_DELETE = "android.intent.action.DELETE";
field public static final deprecated java.lang.String ACTION_DEVICE_STORAGE_LOW = "android.intent.action.DEVICE_STORAGE_LOW";
field public static final deprecated java.lang.String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK";
@@ -9463,8 +9477,9 @@ package android.content {
field public static final deprecated java.lang.String EXTRA_SHORTCUT_INTENT = "android.intent.extra.shortcut.INTENT";
field public static final deprecated java.lang.String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME";
field public static final java.lang.String EXTRA_SHUTDOWN_USERSPACE_ONLY = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
- field public static final deprecated java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
+ field public static final java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
field public static final java.lang.String EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
+ field public static final java.lang.String EXTRA_SUBSCRIPTION_INDEX = "android.intent.extra.SUBSCRIPTION_INDEX";
field public static final java.lang.String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";
field public static final java.lang.String EXTRA_TEXT = "android.intent.extra.TEXT";
field public static final java.lang.String EXTRA_TITLE = "android.intent.extra.TITLE";
@@ -9823,6 +9838,7 @@ package android.content {
}
public abstract interface ServiceConnection {
+ method public default void onBindingDead(android.content.ComponentName);
method public abstract void onServiceConnected(android.content.ComponentName, android.os.IBinder);
method public abstract void onServiceDisconnected(android.content.ComponentName);
}
@@ -10327,12 +10343,12 @@ package android.content.pm {
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
- method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
+ method public deprecated android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
- field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
+ field public static final deprecated int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10629,6 +10645,7 @@ package android.content.pm {
field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
+ field public static final java.lang.String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
field public static final java.lang.String FEATURE_LIVE_TV = "android.software.live_tv";
field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
@@ -10882,9 +10899,9 @@ package android.content.pm {
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
- method public android.content.ComponentName[] getChooserComponentNames();
- method public android.os.PersistableBundle getChooserExtras();
- method public android.content.IntentFilter[] getChooserIntentFilters();
+ method public deprecated android.content.ComponentName[] getChooserComponentNames();
+ method public deprecated android.os.PersistableBundle getChooserExtras();
+ method public deprecated android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -10897,7 +10914,7 @@ package android.content.pm {
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
- method public boolean isChooser();
+ method public deprecated boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -10910,11 +10927,11 @@ package android.content.pm {
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
- method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
+ method public deprecated android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
- method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
+ method public deprecated android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -12687,7 +12704,7 @@ package android.graphics {
enum_constant public static final android.graphics.Canvas.VertexMode TRIANGLE_STRIP;
}
- public final class Color {
+ public class Color {
ctor public Color();
method public static int HSVToColor(float[]);
method public static int HSVToColor(int, float[]);
@@ -15966,11 +15983,11 @@ package android.hardware.usb {
ctor public UsbRequest();
method public boolean cancel();
method public void close();
- method public boolean enqueue(java.nio.ByteBuffer);
method public java.lang.Object getClientData();
method public android.hardware.usb.UsbEndpoint getEndpoint();
method public boolean initialize(android.hardware.usb.UsbDeviceConnection, android.hardware.usb.UsbEndpoint);
method public deprecated boolean queue(java.nio.ByteBuffer, int);
+ method public boolean queue(java.nio.ByteBuffer);
method public void setClientData(java.lang.Object);
}
@@ -22983,6 +23000,7 @@ package android.media {
method public void setProfile(android.media.CamcorderProfile);
method public void setVideoEncoder(int) throws java.lang.IllegalStateException;
method public void setVideoEncodingBitRate(int);
+ method public void setVideoEncodingProfileLevel(int, int);
method public void setVideoFrameRate(int) throws java.lang.IllegalStateException;
method public void setVideoSize(int, int) throws java.lang.IllegalStateException;
method public void setVideoSource(int) throws java.lang.IllegalStateException;
@@ -24525,19 +24543,19 @@ package android.media.tv {
}
public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
- field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
- field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
- field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
- field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
- field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
- field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
- field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
- field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
field public static final java.lang.String COLUMN_AUTHOR = "author";
field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+ field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
@@ -24555,28 +24573,28 @@ package android.media.tv {
field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
field public static final java.lang.String COLUMN_TRANSIENT = "transient";
field public static final java.lang.String COLUMN_TYPE = "type";
- field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
- field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
- field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
- field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
- field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
- field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
- field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
- field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
- field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
- field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
- field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
- field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
- field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
- field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
- field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
- field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
- field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
- field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
- field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
- field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
- field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
- field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
}
public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
@@ -24755,10 +24773,10 @@ package android.media.tv {
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/watch_next_program";
field public static final android.net.Uri CONTENT_URI;
- field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
- field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
- field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
- field public static final java.lang.String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+ field public static final int WATCH_NEXT_TYPE_CONTINUE = 0; // 0x0
+ field public static final int WATCH_NEXT_TYPE_NEW = 2; // 0x2
+ field public static final int WATCH_NEXT_TYPE_NEXT = 1; // 0x1
+ field public static final int WATCH_NEXT_TYPE_WATCHLIST = 3; // 0x3
}
public final class TvInputInfo implements android.os.Parcelable {
@@ -39991,7 +40009,7 @@ package android.telephony {
method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
- method public boolean isConcurrentVoiceAndDataAllowed();
+ method public boolean isConcurrentVoiceAndDataSupported();
method public boolean isDataEnabled();
method public boolean isHearingAidCompatibilitySupported();
method public boolean isNetworkRoaming();
@@ -40004,7 +40022,7 @@ package android.telephony {
method public deprecated boolean sendDialerCode(java.lang.String);
method public void sendDialerSpecialCode(java.lang.String);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
- method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+ method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
method public void setDataEnabled(boolean);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
@@ -40080,14 +40098,17 @@ package android.telephony {
field public static final int SIM_STATE_PUK_REQUIRED = 3; // 0x3
field public static final int SIM_STATE_READY = 5; // 0x5
field public static final int SIM_STATE_UNKNOWN = 0; // 0x0
+ field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe
+ field public static final int USSD_RETURN_FAILURE = -1; // 0xffffffff
+ field public static final int USSD_RETURN_SUCCESS = 100; // 0x64
field public static final java.lang.String VVM_TYPE_CVVM = "vvm_type_cvvm";
field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
}
- public static abstract class TelephonyManager.OnReceiveUssdResponseCallback {
- ctor public TelephonyManager.OnReceiveUssdResponseCallback();
- method public void onReceiveUssdResponse(java.lang.String, java.lang.CharSequence);
- method public void onReceiveUssdResponseFailed(java.lang.String, int);
+ public static abstract class TelephonyManager.UssdResponseCallback {
+ ctor public TelephonyManager.UssdResponseCallback();
+ method public void onReceiveUssdResponse(android.telephony.TelephonyManager, java.lang.String, java.lang.CharSequence);
+ method public void onReceiveUssdResponseFailed(android.telephony.TelephonyManager, java.lang.String, int);
}
public abstract class VisualVoicemailService extends android.app.Service {
@@ -45992,7 +46013,6 @@ package android.view {
method public static deprecated int getEdgeSlop();
method public static deprecated int getFadingEdgeLength();
method public static deprecated long getGlobalActionKeyTimeout();
- method public float getScaledHorizontalScrollFactor();
method public static int getJumpTapTimeout();
method public static int getKeyRepeatDelay();
method public static int getKeyRepeatTimeout();
@@ -46004,6 +46024,7 @@ package android.view {
method public int getScaledDoubleTapSlop();
method public int getScaledEdgeSlop();
method public int getScaledFadingEdgeLength();
+ method public float getScaledHorizontalScrollFactor();
method public int getScaledMaximumDrawingCacheSize();
method public int getScaledMaximumFlingVelocity();
method public int getScaledMinimumFlingVelocity();
@@ -46012,6 +46033,7 @@ package android.view {
method public int getScaledPagingTouchSlop();
method public int getScaledScrollBarSize();
method public int getScaledTouchSlop();
+ method public float getScaledVerticalScrollFactor();
method public int getScaledWindowTouchSlop();
method public static int getScrollBarFadeDuration();
method public static deprecated int getScrollBarSize();
@@ -46019,7 +46041,6 @@ package android.view {
method public static float getScrollFriction();
method public static int getTapTimeout();
method public static deprecated int getTouchSlop();
- method public float getScaledVerticalScrollFactor();
method public static deprecated int getWindowTouchSlop();
method public static long getZoomControlsTimeout();
method public boolean hasPermanentMenuKey();
diff --git a/api/system-current.txt b/api/system-current.txt
index ac1597f0162a..a5f10cd42c72 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -182,7 +182,7 @@ package android {
field public static final java.lang.String READ_LOGS = "android.permission.READ_LOGS";
field public static final java.lang.String READ_NETWORK_USAGE_HISTORY = "android.permission.READ_NETWORK_USAGE_HISTORY";
field public static final java.lang.String READ_OEM_UNLOCK_STATE = "android.permission.READ_OEM_UNLOCK_STATE";
- field public static final java.lang.String READ_PHONE_NUMBER = "android.permission.READ_PHONE_NUMBER";
+ field public static final java.lang.String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS";
field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
field public static final java.lang.String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
field public static final java.lang.String READ_SEARCH_INDEXABLES = "android.permission.READ_SEARCH_INDEXABLES";
@@ -3801,7 +3801,8 @@ package android.app {
method public boolean onMenuItemSelected(int, android.view.MenuItem);
method public boolean onMenuOpened(int, android.view.Menu);
method public void onMovedToDisplay(int, android.content.res.Configuration);
- method public void onMultiWindowModeChanged(boolean);
+ method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onNavigateUp();
method public boolean onNavigateUpFromChild(android.app.Activity);
method protected void onNewIntent(android.content.Intent);
@@ -3809,7 +3810,8 @@ package android.app {
method public void onOptionsMenuClosed(android.view.Menu);
method public void onPanelClosed(int, android.view.Menu);
method protected void onPause();
- method public void onPictureInPictureModeChanged(boolean);
+ method public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onPictureInPictureModeChanged(boolean);
method protected void onPostCreate(android.os.Bundle);
method public void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
method protected void onPostResume();
@@ -4325,7 +4327,7 @@ package android.app {
field public static final java.lang.String OPSTR_READ_CELL_BROADCASTS = "android:read_cell_broadcasts";
field public static final java.lang.String OPSTR_READ_CONTACTS = "android:read_contacts";
field public static final java.lang.String OPSTR_READ_EXTERNAL_STORAGE = "android:read_external_storage";
- field public static final java.lang.String OPSTR_READ_PHONE_NUMBER = "android:read_phone_number";
+ field public static final java.lang.String OPSTR_READ_PHONE_NUMBERS = "android:read_phone_numbers";
field public static final java.lang.String OPSTR_READ_PHONE_STATE = "android:read_phone_state";
field public static final java.lang.String OPSTR_READ_SMS = "android:read_sms";
field public static final java.lang.String OPSTR_RECEIVE_MMS = "android:receive_mms";
@@ -4775,11 +4777,13 @@ package android.app {
method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
method public void onLowMemory();
- method public void onMultiWindowModeChanged(boolean);
+ method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onOptionsItemSelected(android.view.MenuItem);
method public void onOptionsMenuClosed(android.view.Menu);
method public void onPause();
- method public void onPictureInPictureModeChanged(boolean);
+ method public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onPictureInPictureModeChanged(boolean);
method public void onPrepareOptionsMenu(android.view.Menu);
method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
method public void onResume();
@@ -4864,11 +4868,13 @@ package android.app {
method public void dispatchDestroy();
method public void dispatchDestroyView();
method public void dispatchLowMemory();
- method public void dispatchMultiWindowModeChanged(boolean);
+ method public deprecated void dispatchMultiWindowModeChanged(boolean);
+ method public void dispatchMultiWindowModeChanged(boolean, android.content.res.Configuration);
method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
method public void dispatchOptionsMenuClosed(android.view.Menu);
method public void dispatchPause();
- method public void dispatchPictureInPictureModeChanged(boolean);
+ method public deprecated void dispatchPictureInPictureModeChanged(boolean);
+ method public void dispatchPictureInPictureModeChanged(boolean, android.content.res.Configuration);
method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
method public void dispatchResume();
method public void dispatchStart();
@@ -6429,6 +6435,11 @@ package android.app.admin {
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
}
+ public class DeviceAdminService extends android.app.Service {
+ ctor public DeviceAdminService();
+ method public final android.os.IBinder onBind(android.content.Intent);
+ }
+
public class DevicePolicyManager {
method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@@ -6616,6 +6627,7 @@ package android.app.admin {
field public static final java.lang.String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
field public static final java.lang.String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
+ field public static final java.lang.String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
field public static final java.lang.String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
field public static final java.lang.String ACTION_PROVISIONING_SUCCESSFUL = "android.app.action.PROVISIONING_SUCCESSFUL";
@@ -9763,6 +9775,8 @@ package android.content {
field public static final java.lang.String ACTION_BUG_REPORT = "android.intent.action.BUG_REPORT";
field public static final java.lang.String ACTION_CALL = "android.intent.action.CALL";
field public static final java.lang.String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
+ field public static final java.lang.String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY";
+ field public static final java.lang.String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";
field public static final java.lang.String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
field public static final java.lang.String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
field public static final java.lang.String ACTION_CHOOSER = "android.intent.action.CHOOSER";
@@ -9773,6 +9787,8 @@ package android.content {
field public static final java.lang.String ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT";
field public static final java.lang.String ACTION_DATE_CHANGED = "android.intent.action.DATE_CHANGED";
field public static final java.lang.String ACTION_DEFAULT = "android.intent.action.VIEW";
+ field public static final java.lang.String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED";
+ field public static final java.lang.String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_SUBSCRIPTION_CHANGED";
field public static final java.lang.String ACTION_DELETE = "android.intent.action.DELETE";
field public static final deprecated java.lang.String ACTION_DEVICE_STORAGE_LOW = "android.intent.action.DEVICE_STORAGE_LOW";
field public static final deprecated java.lang.String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK";
@@ -9992,8 +10008,9 @@ package android.content {
field public static final deprecated java.lang.String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME";
field public static final java.lang.String EXTRA_SHUTDOWN_USERSPACE_ONLY = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
field public static final java.lang.String EXTRA_SPLIT_NAME = "android.intent.extra.SPLIT_NAME";
- field public static final deprecated java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
+ field public static final java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
field public static final java.lang.String EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
+ field public static final java.lang.String EXTRA_SUBSCRIPTION_INDEX = "android.intent.extra.SUBSCRIPTION_INDEX";
field public static final java.lang.String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";
field public static final java.lang.String EXTRA_TEXT = "android.intent.extra.TEXT";
field public static final java.lang.String EXTRA_TITLE = "android.intent.extra.TITLE";
@@ -10354,6 +10371,7 @@ package android.content {
}
public abstract interface ServiceConnection {
+ method public default void onBindingDead(android.content.ComponentName);
method public abstract void onServiceConnected(android.content.ComponentName, android.os.IBinder);
method public abstract void onServiceDisconnected(android.content.ComponentName);
}
@@ -10949,12 +10967,12 @@ package android.content.pm {
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
- method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
+ method public deprecated android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
- field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
+ field public static final deprecated int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -11280,6 +11298,7 @@ package android.content.pm {
field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
+ field public static final java.lang.String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
field public static final java.lang.String FEATURE_LIVE_TV = "android.software.live_tv";
field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
@@ -11598,9 +11617,9 @@ package android.content.pm {
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
- method public android.content.ComponentName[] getChooserComponentNames();
- method public android.os.PersistableBundle getChooserExtras();
- method public android.content.IntentFilter[] getChooserIntentFilters();
+ method public deprecated android.content.ComponentName[] getChooserComponentNames();
+ method public deprecated android.os.PersistableBundle getChooserExtras();
+ method public deprecated android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -11613,7 +11632,7 @@ package android.content.pm {
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
- method public boolean isChooser();
+ method public deprecated boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -11626,11 +11645,11 @@ package android.content.pm {
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
- method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
+ method public deprecated android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
- method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
+ method public deprecated android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -13417,7 +13436,7 @@ package android.graphics {
enum_constant public static final android.graphics.Canvas.VertexMode TRIANGLE_STRIP;
}
- public final class Color {
+ public class Color {
ctor public Color();
method public static int HSVToColor(float[]);
method public static int HSVToColor(int, float[]);
@@ -17424,11 +17443,11 @@ package android.hardware.usb {
ctor public UsbRequest();
method public boolean cancel();
method public void close();
- method public boolean enqueue(java.nio.ByteBuffer);
method public java.lang.Object getClientData();
method public android.hardware.usb.UsbEndpoint getEndpoint();
method public boolean initialize(android.hardware.usb.UsbDeviceConnection, android.hardware.usb.UsbEndpoint);
method public deprecated boolean queue(java.nio.ByteBuffer, int);
+ method public boolean queue(java.nio.ByteBuffer);
method public void setClientData(java.lang.Object);
}
@@ -22823,6 +22842,7 @@ package android.media {
method public void adjustStreamVolume(int, int, int);
method public void adjustSuggestedStreamVolume(int, int, int);
method public void adjustVolume(int, int);
+ method public int dispatchAudioFocusChange(android.media.AudioFocusInfo, int, android.media.audiopolicy.AudioPolicy);
method public void dispatchMediaKeyEvent(android.view.KeyEvent);
method public int generateAudioSessionId();
method public java.util.List<android.media.AudioPlaybackConfiguration> getActivePlaybackConfigurations();
@@ -24774,6 +24794,7 @@ package android.media {
method public void setProfile(android.media.CamcorderProfile);
method public void setVideoEncoder(int) throws java.lang.IllegalStateException;
method public void setVideoEncodingBitRate(int);
+ method public void setVideoEncodingProfileLevel(int, int);
method public void setVideoFrameRate(int) throws java.lang.IllegalStateException;
method public void setVideoSize(int, int) throws java.lang.IllegalStateException;
method public void setVideoSource(int) throws java.lang.IllegalStateException;
@@ -25824,8 +25845,10 @@ package android.media.audiopolicy {
public static abstract class AudioPolicy.AudioPolicyFocusListener {
ctor public AudioPolicy.AudioPolicyFocusListener();
+ method public void onAudioFocusAbandon(android.media.AudioFocusInfo);
method public void onAudioFocusGrant(android.media.AudioFocusInfo, int);
method public void onAudioFocusLoss(android.media.AudioFocusInfo, boolean);
+ method public void onAudioFocusRequest(android.media.AudioFocusInfo, int);
}
public static abstract class AudioPolicy.AudioPolicyStatusListener {
@@ -25840,6 +25863,7 @@ package android.media.audiopolicy {
method public android.media.audiopolicy.AudioPolicy build();
method public void setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener);
method public void setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener);
+ method public android.media.audiopolicy.AudioPolicy.Builder setIsAudioFocusPolicy(boolean);
method public android.media.audiopolicy.AudioPolicy.Builder setLooper(android.os.Looper) throws java.lang.IllegalArgumentException;
}
@@ -26464,19 +26488,19 @@ package android.media.tv {
}
public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
- field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
- field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
- field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
- field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
- field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
- field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
- field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
- field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
field public static final java.lang.String COLUMN_AUTHOR = "author";
field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+ field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
@@ -26494,28 +26518,28 @@ package android.media.tv {
field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
field public static final java.lang.String COLUMN_TRANSIENT = "transient";
field public static final java.lang.String COLUMN_TYPE = "type";
- field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
- field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
- field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
- field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
- field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
- field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
- field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
- field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
- field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
- field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
- field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
- field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
- field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
- field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
- field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
- field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
- field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
- field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
- field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
- field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
- field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
- field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
}
public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
@@ -26695,10 +26719,10 @@ package android.media.tv {
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/watch_next_program";
field public static final android.net.Uri CONTENT_URI;
- field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
- field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
- field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
- field public static final java.lang.String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+ field public static final int WATCH_NEXT_TYPE_CONTINUE = 0; // 0x0
+ field public static final int WATCH_NEXT_TYPE_NEW = 2; // 0x2
+ field public static final int WATCH_NEXT_TYPE_NEXT = 1; // 0x1
+ field public static final int WATCH_NEXT_TYPE_WATCHLIST = 3; // 0x3
}
public static final class TvContract.WatchedPrograms implements android.media.tv.TvContract.BaseTvColumns {
@@ -43391,7 +43415,7 @@ package android.telephony {
method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
- method public boolean isConcurrentVoiceAndDataAllowed();
+ method public boolean isConcurrentVoiceAndDataSupported();
method public boolean isDataConnectivityPossible();
method public boolean isDataEnabled();
method public boolean isHearingAidCompatibilitySupported();
@@ -43412,7 +43436,7 @@ package android.telephony {
method public deprecated boolean sendDialerCode(java.lang.String);
method public void sendDialerSpecialCode(java.lang.String);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
- method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+ method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method public void setDataEnabled(boolean);
method public void setDataEnabled(int, boolean);
@@ -43504,14 +43528,17 @@ package android.telephony {
field public static final int SIM_STATE_PUK_REQUIRED = 3; // 0x3
field public static final int SIM_STATE_READY = 5; // 0x5
field public static final int SIM_STATE_UNKNOWN = 0; // 0x0
+ field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe
+ field public static final int USSD_RETURN_FAILURE = -1; // 0xffffffff
+ field public static final int USSD_RETURN_SUCCESS = 100; // 0x64
field public static final java.lang.String VVM_TYPE_CVVM = "vvm_type_cvvm";
field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
}
- public static abstract class TelephonyManager.OnReceiveUssdResponseCallback {
- ctor public TelephonyManager.OnReceiveUssdResponseCallback();
- method public void onReceiveUssdResponse(java.lang.String, java.lang.CharSequence);
- method public void onReceiveUssdResponseFailed(java.lang.String, int);
+ public static abstract class TelephonyManager.UssdResponseCallback {
+ ctor public TelephonyManager.UssdResponseCallback();
+ method public void onReceiveUssdResponse(android.telephony.TelephonyManager, java.lang.String, java.lang.CharSequence);
+ method public void onReceiveUssdResponseFailed(android.telephony.TelephonyManager, java.lang.String, int);
}
public abstract class VisualVoicemailService extends android.app.Service {
@@ -49449,7 +49476,6 @@ package android.view {
method public static deprecated int getEdgeSlop();
method public static deprecated int getFadingEdgeLength();
method public static deprecated long getGlobalActionKeyTimeout();
- method public float getScaledHorizontalScrollFactor();
method public static int getJumpTapTimeout();
method public static int getKeyRepeatDelay();
method public static int getKeyRepeatTimeout();
@@ -49461,6 +49487,7 @@ package android.view {
method public int getScaledDoubleTapSlop();
method public int getScaledEdgeSlop();
method public int getScaledFadingEdgeLength();
+ method public float getScaledHorizontalScrollFactor();
method public int getScaledMaximumDrawingCacheSize();
method public int getScaledMaximumFlingVelocity();
method public int getScaledMinimumFlingVelocity();
@@ -49469,6 +49496,7 @@ package android.view {
method public int getScaledPagingTouchSlop();
method public int getScaledScrollBarSize();
method public int getScaledTouchSlop();
+ method public float getScaledVerticalScrollFactor();
method public int getScaledWindowTouchSlop();
method public static int getScrollBarFadeDuration();
method public static deprecated int getScrollBarSize();
@@ -49476,7 +49504,6 @@ package android.view {
method public static float getScrollFriction();
method public static int getTapTimeout();
method public static deprecated int getTouchSlop();
- method public float getScaledVerticalScrollFactor();
method public static deprecated int getWindowTouchSlop();
method public static long getZoomControlsTimeout();
method public boolean hasPermanentMenuKey();
diff --git a/api/test-current.txt b/api/test-current.txt
index fc3c9e74e440..1b5eeedfdf12 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -104,7 +104,7 @@ package android {
field public static final java.lang.String READ_FRAME_BUFFER = "android.permission.READ_FRAME_BUFFER";
field public static final deprecated java.lang.String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE";
field public static final java.lang.String READ_LOGS = "android.permission.READ_LOGS";
- field public static final java.lang.String READ_PHONE_NUMBER = "android.permission.READ_PHONE_NUMBER";
+ field public static final java.lang.String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS";
field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
@@ -3677,7 +3677,8 @@ package android.app {
method public boolean onMenuItemSelected(int, android.view.MenuItem);
method public boolean onMenuOpened(int, android.view.Menu);
method public void onMovedToDisplay(int, android.content.res.Configuration);
- method public void onMultiWindowModeChanged(boolean);
+ method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onNavigateUp();
method public boolean onNavigateUpFromChild(android.app.Activity);
method protected void onNewIntent(android.content.Intent);
@@ -3685,7 +3686,8 @@ package android.app {
method public void onOptionsMenuClosed(android.view.Menu);
method public void onPanelClosed(int, android.view.Menu);
method protected void onPause();
- method public void onPictureInPictureModeChanged(boolean);
+ method public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onPictureInPictureModeChanged(boolean);
method protected void onPostCreate(android.os.Bundle);
method public void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
method protected void onPostResume();
@@ -4192,7 +4194,7 @@ package android.app {
field public static final java.lang.String OPSTR_READ_CELL_BROADCASTS = "android:read_cell_broadcasts";
field public static final java.lang.String OPSTR_READ_CONTACTS = "android:read_contacts";
field public static final java.lang.String OPSTR_READ_EXTERNAL_STORAGE = "android:read_external_storage";
- field public static final java.lang.String OPSTR_READ_PHONE_NUMBER = "android:read_phone_number";
+ field public static final java.lang.String OPSTR_READ_PHONE_NUMBERS = "android:read_phone_numbers";
field public static final java.lang.String OPSTR_READ_PHONE_STATE = "android:read_phone_state";
field public static final java.lang.String OPSTR_READ_SMS = "android:read_sms";
field public static final java.lang.String OPSTR_RECEIVE_MMS = "android:receive_mms";
@@ -4628,11 +4630,13 @@ package android.app {
method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
method public void onLowMemory();
- method public void onMultiWindowModeChanged(boolean);
+ method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onOptionsItemSelected(android.view.MenuItem);
method public void onOptionsMenuClosed(android.view.Menu);
method public void onPause();
- method public void onPictureInPictureModeChanged(boolean);
+ method public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onPictureInPictureModeChanged(boolean);
method public void onPrepareOptionsMenu(android.view.Menu);
method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
method public void onResume();
@@ -4717,11 +4721,13 @@ package android.app {
method public void dispatchDestroy();
method public void dispatchDestroyView();
method public void dispatchLowMemory();
- method public void dispatchMultiWindowModeChanged(boolean);
+ method public deprecated void dispatchMultiWindowModeChanged(boolean);
+ method public void dispatchMultiWindowModeChanged(boolean, android.content.res.Configuration);
method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
method public void dispatchOptionsMenuClosed(android.view.Menu);
method public void dispatchPause();
- method public void dispatchPictureInPictureModeChanged(boolean);
+ method public deprecated void dispatchPictureInPictureModeChanged(boolean);
+ method public void dispatchPictureInPictureModeChanged(boolean, android.content.res.Configuration);
method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
method public void dispatchResume();
method public void dispatchStart();
@@ -6245,6 +6251,11 @@ package android.app.admin {
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
}
+ public class DeviceAdminService extends android.app.Service {
+ ctor public DeviceAdminService();
+ method public final android.os.IBinder onBind(android.content.Intent);
+ }
+
public class DevicePolicyManager {
method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@@ -6420,6 +6431,7 @@ package android.app.admin {
field public static final java.lang.String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
field public static final java.lang.String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
+ field public static final java.lang.String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
field public static final java.lang.String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
field public static final java.lang.String ACTION_PROVISIONING_SUCCESSFUL = "android.app.action.PROVISIONING_SUCCESSFUL";
@@ -9297,6 +9309,8 @@ package android.content {
field public static final java.lang.String ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT";
field public static final java.lang.String ACTION_DATE_CHANGED = "android.intent.action.DATE_CHANGED";
field public static final java.lang.String ACTION_DEFAULT = "android.intent.action.VIEW";
+ field public static final java.lang.String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED";
+ field public static final java.lang.String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_SUBSCRIPTION_CHANGED";
field public static final java.lang.String ACTION_DELETE = "android.intent.action.DELETE";
field public static final deprecated java.lang.String ACTION_DEVICE_STORAGE_LOW = "android.intent.action.DEVICE_STORAGE_LOW";
field public static final deprecated java.lang.String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK";
@@ -9496,8 +9510,9 @@ package android.content {
field public static final deprecated java.lang.String EXTRA_SHORTCUT_INTENT = "android.intent.extra.shortcut.INTENT";
field public static final deprecated java.lang.String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME";
field public static final java.lang.String EXTRA_SHUTDOWN_USERSPACE_ONLY = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
- field public static final deprecated java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
+ field public static final java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
field public static final java.lang.String EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
+ field public static final java.lang.String EXTRA_SUBSCRIPTION_INDEX = "android.intent.extra.SUBSCRIPTION_INDEX";
field public static final java.lang.String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";
field public static final java.lang.String EXTRA_TEXT = "android.intent.extra.TEXT";
field public static final java.lang.String EXTRA_TITLE = "android.intent.extra.TITLE";
@@ -9856,6 +9871,7 @@ package android.content {
}
public abstract interface ServiceConnection {
+ method public default void onBindingDead(android.content.ComponentName);
method public abstract void onServiceConnected(android.content.ComponentName, android.os.IBinder);
method public abstract void onServiceDisconnected(android.content.ComponentName);
}
@@ -10363,12 +10379,12 @@ package android.content.pm {
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
- method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
+ method public deprecated android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
- field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
+ field public static final deprecated int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10668,6 +10684,7 @@ package android.content.pm {
field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
+ field public static final java.lang.String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
field public static final java.lang.String FEATURE_LIVE_TV = "android.software.live_tv";
field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
@@ -10922,9 +10939,9 @@ package android.content.pm {
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
- method public android.content.ComponentName[] getChooserComponentNames();
- method public android.os.PersistableBundle getChooserExtras();
- method public android.content.IntentFilter[] getChooserIntentFilters();
+ method public deprecated android.content.ComponentName[] getChooserComponentNames();
+ method public deprecated android.os.PersistableBundle getChooserExtras();
+ method public deprecated android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -10937,7 +10954,7 @@ package android.content.pm {
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
- method public boolean isChooser();
+ method public deprecated boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -10950,11 +10967,11 @@ package android.content.pm {
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
- method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
+ method public deprecated android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
- method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
+ method public deprecated android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -12737,7 +12754,7 @@ package android.graphics {
enum_constant public static final android.graphics.Canvas.VertexMode TRIANGLE_STRIP;
}
- public final class Color {
+ public class Color {
ctor public Color();
method public static int HSVToColor(float[]);
method public static int HSVToColor(int, float[]);
@@ -16021,11 +16038,11 @@ package android.hardware.usb {
ctor public UsbRequest();
method public boolean cancel();
method public void close();
- method public boolean enqueue(java.nio.ByteBuffer);
method public java.lang.Object getClientData();
method public android.hardware.usb.UsbEndpoint getEndpoint();
method public boolean initialize(android.hardware.usb.UsbDeviceConnection, android.hardware.usb.UsbEndpoint);
method public deprecated boolean queue(java.nio.ByteBuffer, int);
+ method public boolean queue(java.nio.ByteBuffer);
method public void setClientData(java.lang.Object);
}
@@ -23096,6 +23113,7 @@ package android.media {
method public void setProfile(android.media.CamcorderProfile);
method public void setVideoEncoder(int) throws java.lang.IllegalStateException;
method public void setVideoEncodingBitRate(int);
+ method public void setVideoEncodingProfileLevel(int, int);
method public void setVideoFrameRate(int) throws java.lang.IllegalStateException;
method public void setVideoSize(int, int) throws java.lang.IllegalStateException;
method public void setVideoSource(int) throws java.lang.IllegalStateException;
@@ -24638,19 +24656,19 @@ package android.media.tv {
}
public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
- field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
- field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
- field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
- field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
- field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
- field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
- field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
- field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
field public static final java.lang.String COLUMN_AUTHOR = "author";
field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+ field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
@@ -24668,28 +24686,28 @@ package android.media.tv {
field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
field public static final java.lang.String COLUMN_TRANSIENT = "transient";
field public static final java.lang.String COLUMN_TYPE = "type";
- field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
- field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
- field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
- field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
- field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
- field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
- field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
- field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
- field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
- field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
- field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
- field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
- field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
- field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
- field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
- field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
- field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
- field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
- field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
- field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
- field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
- field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
}
public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
@@ -24868,10 +24886,10 @@ package android.media.tv {
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/watch_next_program";
field public static final android.net.Uri CONTENT_URI;
- field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
- field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
- field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
- field public static final java.lang.String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+ field public static final int WATCH_NEXT_TYPE_CONTINUE = 0; // 0x0
+ field public static final int WATCH_NEXT_TYPE_NEW = 2; // 0x2
+ field public static final int WATCH_NEXT_TYPE_NEXT = 1; // 0x1
+ field public static final int WATCH_NEXT_TYPE_WATCHLIST = 3; // 0x3
}
public final class TvInputInfo implements android.os.Parcelable {
@@ -37522,6 +37540,7 @@ package android.service.quicksettings {
ctor public TileService();
method public final android.service.quicksettings.Tile getQsTile();
method public final boolean isLocked();
+ method public static boolean isQuickSettingsSupported();
method public final boolean isSecure();
method public android.os.IBinder onBind(android.content.Intent);
method public void onClick();
@@ -40194,7 +40213,7 @@ package android.telephony {
method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
- method public boolean isConcurrentVoiceAndDataAllowed();
+ method public boolean isConcurrentVoiceAndDataSupported();
method public boolean isDataEnabled();
method public boolean isHearingAidCompatibilitySupported();
method public boolean isNetworkRoaming();
@@ -40207,7 +40226,7 @@ package android.telephony {
method public deprecated boolean sendDialerCode(java.lang.String);
method public void sendDialerSpecialCode(java.lang.String);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
- method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+ method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
method public void setDataEnabled(boolean);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
@@ -40283,14 +40302,17 @@ package android.telephony {
field public static final int SIM_STATE_PUK_REQUIRED = 3; // 0x3
field public static final int SIM_STATE_READY = 5; // 0x5
field public static final int SIM_STATE_UNKNOWN = 0; // 0x0
+ field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe
+ field public static final int USSD_RETURN_FAILURE = -1; // 0xffffffff
+ field public static final int USSD_RETURN_SUCCESS = 100; // 0x64
field public static final java.lang.String VVM_TYPE_CVVM = "vvm_type_cvvm";
field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
}
- public static abstract class TelephonyManager.OnReceiveUssdResponseCallback {
- ctor public TelephonyManager.OnReceiveUssdResponseCallback();
- method public void onReceiveUssdResponse(java.lang.String, java.lang.CharSequence);
- method public void onReceiveUssdResponseFailed(java.lang.String, int);
+ public static abstract class TelephonyManager.UssdResponseCallback {
+ ctor public TelephonyManager.UssdResponseCallback();
+ method public void onReceiveUssdResponse(android.telephony.TelephonyManager, java.lang.String, java.lang.CharSequence);
+ method public void onReceiveUssdResponseFailed(android.telephony.TelephonyManager, java.lang.String, int);
}
public abstract class VisualVoicemailService extends android.app.Service {
@@ -46369,7 +46391,6 @@ package android.view {
method public static deprecated int getEdgeSlop();
method public static deprecated int getFadingEdgeLength();
method public static deprecated long getGlobalActionKeyTimeout();
- method public float getScaledHorizontalScrollFactor();
method public static int getHoverTooltipHideShortTimeout();
method public static int getHoverTooltipHideTimeout();
method public static int getHoverTooltipShowTimeout();
@@ -46385,6 +46406,7 @@ package android.view {
method public int getScaledDoubleTapSlop();
method public int getScaledEdgeSlop();
method public int getScaledFadingEdgeLength();
+ method public float getScaledHorizontalScrollFactor();
method public int getScaledMaximumDrawingCacheSize();
method public int getScaledMaximumFlingVelocity();
method public int getScaledMinimumFlingVelocity();
@@ -46393,6 +46415,7 @@ package android.view {
method public int getScaledPagingTouchSlop();
method public int getScaledScrollBarSize();
method public int getScaledTouchSlop();
+ method public float getScaledVerticalScrollFactor();
method public int getScaledWindowTouchSlop();
method public static int getScrollBarFadeDuration();
method public static deprecated int getScrollBarSize();
@@ -46400,7 +46423,6 @@ package android.view {
method public static float getScrollFriction();
method public static int getTapTimeout();
method public static deprecated int getTouchSlop();
- method public float getScaledVerticalScrollFactor();
method public static deprecated int getWindowTouchSlop();
method public static long getZoomControlsTimeout();
method public boolean hasPermanentMenuKey();
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index 3a92b9e74144..0e2c13ee1719 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -26,7 +26,8 @@ LOCAL_SHARED_LIBRARIES := \
libGLESv1_CM \
libgui \
libOpenSLES \
- libtinyalsa
+ libtinyalsa \
+ libbase
LOCAL_MODULE:= bootanimation
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index a6d2986e185a..2435ffadd879 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -38,6 +38,8 @@
#include <utils/Log.h>
#include <utils/SystemClock.h>
+#include <android-base/properties.h>
+
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -67,6 +69,9 @@ namespace android {
static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";
+static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip";
+static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip";
+
static const char SYSTEM_DATA_DIR_PATH[] = "/data/system";
static const char SYSTEM_TIME_DIR_NAME[] = "time";
static const char SYSTEM_TIME_DIR_PATH[] = "/data/system/time";
@@ -106,7 +111,13 @@ BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true), mTimeIsAccu
mSession = new SurfaceComposerClient();
// If the system has already booted, the animation is not being used for a boot.
- mSystemBoot = !property_get_bool(BOOT_COMPLETED_PROP_NAME, 0);
+ mSystemBoot = !android::base::GetBoolProperty(BOOT_COMPLETED_PROP_NAME, false);
+ std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
+ if (powerCtl.empty()) {
+ mShuttingDown = false;
+ } else {
+ mShuttingDown = true;
+ }
}
void BootAnimation::onFirstRef() {
@@ -314,16 +325,23 @@ status_t BootAnimation::readyToRun() {
char decrypt[PROPERTY_VALUE_MAX];
property_get("vold.decrypt", decrypt, "");
- bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
+ bool encryptedAnimation = atoi(decrypt) != 0 ||
+ !strcmp("trigger_restart_min_framework", decrypt);
- if (encryptedAnimation && (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) {
+ if (!mShuttingDown && encryptedAnimation &&
+ (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) {
mZipFileName = SYSTEM_ENCRYPTED_BOOTANIMATION_FILE;
+ return NO_ERROR;
}
- else if (access(OEM_BOOTANIMATION_FILE, R_OK) == 0) {
- mZipFileName = OEM_BOOTANIMATION_FILE;
- }
- else if (access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) {
- mZipFileName = SYSTEM_BOOTANIMATION_FILE;
+ static const char* bootFiles[] = {OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE};
+ static const char* shutdownFiles[] =
+ {OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE};
+
+ for (const char* f : (!mShuttingDown ? bootFiles : shutdownFiles)) {
+ if (access(f, R_OK) == 0) {
+ mZipFileName = f;
+ return NO_ERROR;
+ }
}
return NO_ERROR;
}
@@ -1047,7 +1065,9 @@ bool BootAnimation::playSoundsAllowed() const {
if (!mSystemBoot) {
return false;
}
-
+ if (mShuttingDown) { // no audio while shutting down
+ return false;
+ }
// Read the system property to see if we should play the sound.
// If it's not present, default to allowed.
if (!property_get_bool(PLAY_SOUND_PROP_NAME, 1)) {
@@ -1073,7 +1093,7 @@ bool BootAnimation::updateIsTimeAccurate() {
if (mTimeIsAccurate) {
return true;
}
-
+ if (mShuttingDown) return true;
struct stat statResult;
if(stat(TIME_FORMAT_12_HOUR_FLAG_FILE_PATH, &statResult) == 0) {
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index f1fc98e10c1e..181ef1c596d1 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -163,6 +163,7 @@ private:
bool mTimeIsAccurate;
bool mTimeFormat12Hour;
bool mSystemBoot;
+ bool mShuttingDown;
String8 mZipFileName;
SortedVector<String8> mLoadedFiles;
sp<TimeCheckThread> mTimeCheckThread = nullptr;
diff --git a/cmds/bootanimation/bootanim.rc b/cmds/bootanimation/bootanim.rc
index 7344ba74f70b..469c9646a4aa 100644
--- a/cmds/bootanimation/bootanim.rc
+++ b/cmds/bootanimation/bootanim.rc
@@ -1,7 +1,7 @@
service bootanim /system/bin/bootanimation
- class core
+ class core animation
user graphics
group graphics audio
disabled
oneshot
- writepid /dev/stune/top-app/tasks \ No newline at end of file
+ writepid /dev/stune/top-app/tasks
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 5c7a12cf5eb9..fe496e398988 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -431,12 +431,10 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
// Force all the animations to end when the duration scale is 0.
private void forceToEnd() {
- // TODO: Below is commented out to temp work around b/36241584, uncomment this when it's
- // fixed.
-// if (mEndCanBeCalled) {
-// end();
-// return;
-// }
+ if (mEndCanBeCalled) {
+ end();
+ return;
+ }
// Note: we don't want to combine this case with the end() method below because in
// the case of developer calling end(), we still need to make sure end() is explicitly
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 147b5d034fd1..d432160ccfbf 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1889,11 +1889,32 @@ public class Activity extends ContextThemeWrapper
/**
* Called by the system when the activity changes from fullscreen mode to multi-window mode and
+ * visa-versa. This method provides the same configuration that will be sent in the following
+ * {@link #onConfigurationChanged(Configuration)} call after the activity enters this mode.
+ *
+ * @see android.R.attr#resizeableActivity
+ *
+ * @param isInMultiWindowMode True if the activity is in multi-window mode.
+ * @param newConfig The new configuration of the activity with the state
+ * {@param isInMultiWindowMode}.
+ */
+ public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
+ // Left deliberately empty. There should be no side effects if a direct
+ // subclass of Activity does not call super.
+ onMultiWindowModeChanged(isInMultiWindowMode);
+ }
+
+ /**
+ * Called by the system when the activity changes from fullscreen mode to multi-window mode and
* visa-versa.
+ *
* @see android.R.attr#resizeableActivity
*
* @param isInMultiWindowMode True if the activity is in multi-window mode.
+ *
+ * @deprecated Use {@link #onMultiWindowModeChanged(boolean, Configuration)} instead.
*/
+ @Deprecated
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
// Left deliberately empty. There should be no side effects if a direct
// subclass of Activity does not call super.
@@ -1914,11 +1935,33 @@ public class Activity extends ContextThemeWrapper
}
/**
+ * Called by the system when the activity changes to and from picture-in-picture mode. This
+ * method provides the same configuration that will be sent in the following
+ * {@link #onConfigurationChanged(Configuration)} call after the activity enters this mode.
+ *
+ * @see android.R.attr#supportsPictureInPicture
+ *
+ * @param isInPictureInPictureMode True if the activity is in picture-in-picture mode.
+ * @param newConfig The new configuration of the activity with the state
+ * {@param isInPictureInPictureMode}.
+ */
+ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode,
+ Configuration newConfig) {
+ // Left deliberately empty. There should be no side effects if a direct
+ // subclass of Activity does not call super.
+ onPictureInPictureModeChanged(isInPictureInPictureMode);
+ }
+
+ /**
* Called by the system when the activity changes to and from picture-in-picture mode.
+ *
* @see android.R.attr#supportsPictureInPicture
*
* @param isInPictureInPictureMode True if the activity is in picture-in-picture mode.
+ *
+ * @deprecated Use {@link #onPictureInPictureModeChanged(boolean, Configuration)} instead.
*/
+ @Deprecated
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
// Left deliberately empty. There should be no side effects if a direct
// subclass of Activity does not call super.
@@ -4116,14 +4159,25 @@ public class Activity extends ContextThemeWrapper
mTaskDescription.setPrimaryColor(colorPrimary);
}
}
- // For dev-preview only.
- if (mTaskDescription.getBackgroundColor() == 0) {
- int colorBackground = a.getColor(
- com.android.internal.R.styleable.ActivityTaskDescription_colorBackground, 0);
- if (colorBackground != 0 && Color.alpha(colorBackground) == 0xFF) {
- mTaskDescription.setBackgroundColor(colorBackground);
- }
+
+ int colorBackground = a.getColor(
+ com.android.internal.R.styleable.ActivityTaskDescription_colorBackground, 0);
+ if (colorBackground != 0 && Color.alpha(colorBackground) == 0xFF) {
+ mTaskDescription.setBackgroundColor(colorBackground);
}
+
+ final int statusBarColor = a.getColor(
+ com.android.internal.R.styleable.ActivityTaskDescription_statusBarColor, 0);
+ if (statusBarColor != 0) {
+ mTaskDescription.setStatusBarColor(statusBarColor);
+ }
+
+ final int navigationBarColor = a.getColor(
+ com.android.internal.R.styleable.ActivityTaskDescription_navigationBarColor, 0);
+ if (navigationBarColor != 0) {
+ mTaskDescription.setNavigationBarColor(navigationBarColor);
+ }
+
a.recycle();
setTaskDescription(mTaskDescription);
}
@@ -6993,21 +7047,25 @@ public class Activity extends ContextThemeWrapper
}
}
- final void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode) {
+ final void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode,
+ Configuration newConfig) {
if (DEBUG_LIFECYCLE) Slog.v(TAG,
- "dispatchMultiWindowModeChanged " + this + ": " + isInMultiWindowMode);
- mFragments.dispatchMultiWindowModeChanged(isInMultiWindowMode);
+ "dispatchMultiWindowModeChanged " + this + ": " + isInMultiWindowMode
+ + " " + newConfig);
+ mFragments.dispatchMultiWindowModeChanged(isInMultiWindowMode, newConfig);
if (mWindow != null) {
mWindow.onMultiWindowModeChanged();
}
- onMultiWindowModeChanged(isInMultiWindowMode);
+ onMultiWindowModeChanged(isInMultiWindowMode, newConfig);
}
- final void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+ final void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode,
+ Configuration newConfig) {
if (DEBUG_LIFECYCLE) Slog.v(TAG,
- "dispatchPictureInPictureModeChanged " + this + ": " + isInPictureInPictureMode);
- mFragments.dispatchPictureInPictureModeChanged(isInPictureInPictureMode);
- onPictureInPictureModeChanged(isInPictureInPictureMode);
+ "dispatchPictureInPictureModeChanged " + this + ": " + isInPictureInPictureMode
+ + " " + newConfig);
+ mFragments.dispatchPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
+ onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
}
/**
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 4004bd6686b1..aede1bb67f80 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1145,6 +1145,8 @@ public class ActivityManager {
private String mIconFilename;
private int mColorPrimary;
private int mColorBackground;
+ private int mStatusBarColor;
+ private int mNavigationBarColor;
/**
* Creates the TaskDescription to the specified values.
@@ -1155,7 +1157,7 @@ public class ActivityManager {
* opaque.
*/
public TaskDescription(String label, Bitmap icon, int colorPrimary) {
- this(label, icon, null, colorPrimary, 0);
+ this(label, icon, null, colorPrimary, 0, 0, 0);
if ((colorPrimary != 0) && (Color.alpha(colorPrimary) != 255)) {
throw new RuntimeException("A TaskDescription's primary color should be opaque");
}
@@ -1168,7 +1170,7 @@ public class ActivityManager {
* @param icon An icon that represents the current state of this activity.
*/
public TaskDescription(String label, Bitmap icon) {
- this(label, icon, null, 0, 0);
+ this(label, icon, null, 0, 0, 0, 0);
}
/**
@@ -1177,24 +1179,26 @@ public class ActivityManager {
* @param label A label and description of the current state of this activity.
*/
public TaskDescription(String label) {
- this(label, null, null, 0, 0);
+ this(label, null, null, 0, 0, 0, 0);
}
/**
* Creates an empty TaskDescription.
*/
public TaskDescription() {
- this(null, null, null, 0, 0);
+ this(null, null, null, 0, 0, 0, 0);
}
/** @hide */
public TaskDescription(String label, Bitmap icon, String iconFilename, int colorPrimary,
- int colorBackground) {
+ int colorBackground, int statusBarColor, int navigationBarColor) {
mLabel = label;
mIcon = icon;
mIconFilename = iconFilename;
mColorPrimary = colorPrimary;
mColorBackground = colorBackground;
+ mStatusBarColor = statusBarColor;
+ mNavigationBarColor = navigationBarColor;
}
/**
@@ -1214,6 +1218,8 @@ public class ActivityManager {
mIconFilename = other.mIconFilename;
mColorPrimary = other.mColorPrimary;
mColorBackground = other.mColorBackground;
+ mStatusBarColor = other.mStatusBarColor;
+ mNavigationBarColor = other.mNavigationBarColor;
}
private TaskDescription(Parcel source) {
@@ -1253,6 +1259,20 @@ public class ActivityManager {
}
/**
+ * @hide
+ */
+ public void setStatusBarColor(int statusBarColor) {
+ mStatusBarColor = statusBarColor;
+ }
+
+ /**
+ * @hide
+ */
+ public void setNavigationBarColor(int navigationBarColor) {
+ mNavigationBarColor = navigationBarColor;
+ }
+
+ /**
* Sets the icon for this task description.
* @hide
*/
@@ -1325,6 +1345,20 @@ public class ActivityManager {
return mColorBackground;
}
+ /**
+ * @hide
+ */
+ public int getStatusBarColor() {
+ return mStatusBarColor;
+ }
+
+ /**
+ * @hide
+ */
+ public int getNavigationBarColor() {
+ return mNavigationBarColor;
+ }
+
/** @hide */
public void saveToXml(XmlSerializer out) throws IOException {
if (mLabel != null) {
@@ -1377,6 +1411,8 @@ public class ActivityManager {
}
dest.writeInt(mColorPrimary);
dest.writeInt(mColorBackground);
+ dest.writeInt(mStatusBarColor);
+ dest.writeInt(mNavigationBarColor);
if (mIconFilename == null) {
dest.writeInt(0);
} else {
@@ -1390,6 +1426,8 @@ public class ActivityManager {
mIcon = source.readInt() > 0 ? Bitmap.CREATOR.createFromParcel(source) : null;
mColorPrimary = source.readInt();
mColorBackground = source.readInt();
+ mStatusBarColor = source.readInt();
+ mNavigationBarColor = source.readInt();
mIconFilename = source.readInt() > 0 ? source.readString() : null;
}
@@ -1407,7 +1445,9 @@ public class ActivityManager {
public String toString() {
return "TaskDescription Label: " + mLabel + " Icon: " + mIcon +
" IconFilename: " + mIconFilename + " colorPrimary: " + mColorPrimary +
- " colorBackground: " + mColorBackground;
+ " colorBackground: " + mColorBackground +
+ " statusBarColor: " + mColorBackground +
+ " navigationBarColor: " + mNavigationBarColor;
}
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b5d1fa8550df..d1d462c2fbe8 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -221,6 +221,7 @@ public final class ActivityThread {
private long mNetworkBlockSeq = INVALID_PROC_STATE_SEQ;
private ContextImpl mSystemContext;
+ private ContextImpl mSystemUiContext;
static volatile IPackageManager sPackageManager;
@@ -1411,15 +1412,23 @@ public final class ActivityThread {
}
@Override
- public void scheduleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode)
- throws RemoteException {
- sendMessage(H.MULTI_WINDOW_MODE_CHANGED, token, isInMultiWindowMode ? 1 : 0);
+ public void scheduleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode,
+ Configuration overrideConfig) throws RemoteException {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = token;
+ args.arg2 = overrideConfig;
+ args.argi1 = isInMultiWindowMode ? 1 : 0;
+ sendMessage(H.MULTI_WINDOW_MODE_CHANGED, args);
}
@Override
- public void schedulePictureInPictureModeChanged(IBinder token, boolean isInPipMode)
- throws RemoteException {
- sendMessage(H.PICTURE_IN_PICTURE_MODE_CHANGED, token, isInPipMode ? 1 : 0);
+ public void schedulePictureInPictureModeChanged(IBinder token, boolean isInPipMode,
+ Configuration overrideConfig) throws RemoteException {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = token;
+ args.arg2 = overrideConfig;
+ args.argi1 = isInPipMode ? 1 : 0;
+ sendMessage(H.PICTURE_IN_PICTURE_MODE_CHANGED, args);
}
@Override
@@ -1816,10 +1825,14 @@ public final class ActivityThread {
handleStopBinderTrackingAndDump((ParcelFileDescriptor) msg.obj);
break;
case MULTI_WINDOW_MODE_CHANGED:
- handleMultiWindowModeChanged((IBinder) msg.obj, msg.arg1 == 1);
+ handleMultiWindowModeChanged((IBinder) ((SomeArgs) msg.obj).arg1,
+ ((SomeArgs) msg.obj).argi1 == 1,
+ (Configuration) ((SomeArgs) msg.obj).arg2);
break;
case PICTURE_IN_PICTURE_MODE_CHANGED:
- handlePictureInPictureModeChanged((IBinder) msg.obj, msg.arg1 == 1);
+ handlePictureInPictureModeChanged((IBinder) ((SomeArgs) msg.obj).arg1,
+ ((SomeArgs) msg.obj).argi1 == 1,
+ (Configuration) ((SomeArgs) msg.obj).arg2);
break;
case LOCAL_VOICE_INTERACTION_STARTED:
handleLocalVoiceInteractionStarted((IBinder) ((SomeArgs) msg.obj).arg1,
@@ -2178,9 +2191,19 @@ public final class ActivityThread {
}
}
+ public ContextImpl getSystemUiContext() {
+ synchronized (this) {
+ if (mSystemUiContext == null) {
+ mSystemUiContext = ContextImpl.createSystemUiContext(this);
+ }
+ return mSystemUiContext;
+ }
+ }
+
public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
synchronized (this) {
getSystemContext().installSystemApplicationInfo(info, classLoader);
+ getSystemUiContext().installSystemApplicationInfo(info, classLoader);
// give ourselves a default profiler
mProfiler = new Profiler();
@@ -3119,17 +3142,27 @@ public final class ActivityThread {
}
}
- private void handleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode) {
+ private void handleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode,
+ Configuration overrideConfig) {
final ActivityClientRecord r = mActivities.get(token);
if (r != null) {
- r.activity.dispatchMultiWindowModeChanged(isInMultiWindowMode);
+ final Configuration newConfig = new Configuration(mConfiguration);
+ if (overrideConfig != null) {
+ newConfig.updateFrom(overrideConfig);
+ }
+ r.activity.dispatchMultiWindowModeChanged(isInMultiWindowMode, newConfig);
}
}
- private void handlePictureInPictureModeChanged(IBinder token, boolean isInPipMode) {
+ private void handlePictureInPictureModeChanged(IBinder token, boolean isInPipMode,
+ Configuration overrideConfig) {
final ActivityClientRecord r = mActivities.get(token);
if (r != null) {
- r.activity.dispatchPictureInPictureModeChanged(isInPipMode);
+ final Configuration newConfig = new Configuration(mConfiguration);
+ if (overrideConfig != null) {
+ newConfig.updateFrom(overrideConfig);
+ }
+ r.activity.dispatchPictureInPictureModeChanged(isInPipMode, newConfig);
}
}
@@ -5009,6 +5042,11 @@ public final class ActivityThread {
if ((systemTheme.getChangingConfigurations() & configDiff) != 0) {
systemTheme.rebase();
}
+
+ final Theme systemUiTheme = getSystemUiContext().getTheme();
+ if ((systemUiTheme.getChangingConfigurations() & configDiff) != 0) {
+ systemUiTheme.rebase();
+ }
}
ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
@@ -5064,9 +5102,10 @@ public final class ActivityThread {
// Trigger a regular Configuration change event, only with a different assetsSeq number
// so that we actually call through to all components.
+ // TODO(adamlesinski): Change this to make use of ActivityManager's upcoming ability to
+ // store configurations per-process.
Configuration newConfig = new Configuration();
- newConfig.unset();
- newConfig.assetsSeq = mConfiguration.assetsSeq + 1;
+ newConfig.assetsSeq = (mConfiguration != null ? mConfiguration.assetsSeq : 0) + 1;
handleConfigurationChanged(newConfig, null);
// Schedule all activities to reload
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index cbd7b9d4aa9c..82921524457f 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -242,7 +242,7 @@ public class AppOpsManager {
/** @hide */
public static final int OP_AUDIO_ACCESSIBILITY_VOLUME = 64;
/** @hide Read the phone number. */
- public static final int OP_READ_PHONE_NUMBER = 65;
+ public static final int OP_READ_PHONE_NUMBERS = 65;
/** @hide Request package installs through package installer */
public static final int OP_REQUEST_INSTALL_PACKAGES = 66;
/** @hide Enter picture-in-picture. */
@@ -353,8 +353,8 @@ public class AppOpsManager {
/** @hide Get device accounts. */
public static final String OPSTR_GET_ACCOUNTS
= "android:get_accounts";
- public static final String OPSTR_READ_PHONE_NUMBER
- = "android:read_phone_number";
+ public static final String OPSTR_READ_PHONE_NUMBERS
+ = "android:read_phone_numbers";
/** Access to picture-in-picture. */
public static final String OPSTR_PICTURE_IN_PICTURE
= "android:picture_in_picture";
@@ -391,7 +391,7 @@ public class AppOpsManager {
OP_FINE_LOCATION,
// Phone
OP_READ_PHONE_STATE,
- OP_READ_PHONE_NUMBER,
+ OP_READ_PHONE_NUMBERS,
OP_CALL_PHONE,
OP_READ_CALL_LOG,
OP_WRITE_CALL_LOG,
@@ -487,7 +487,7 @@ public class AppOpsManager {
OP_GET_ACCOUNTS,
OP_RUN_IN_BACKGROUND,
OP_AUDIO_ACCESSIBILITY_VOLUME,
- OP_READ_PHONE_NUMBER,
+ OP_READ_PHONE_NUMBERS,
OP_REQUEST_INSTALL_PACKAGES,
OP_PICTURE_IN_PICTURE,
OP_INSTANT_APP_START_FOREGROUND,
@@ -564,7 +564,7 @@ public class AppOpsManager {
OPSTR_GET_ACCOUNTS,
null,
null, // OP_AUDIO_ACCESSIBILITY_VOLUME
- OPSTR_READ_PHONE_NUMBER,
+ OPSTR_READ_PHONE_NUMBERS,
null, // OP_REQUEST_INSTALL_PACKAGES
OPSTR_PICTURE_IN_PICTURE,
OPSTR_INSTANT_APP_START_FOREGROUND,
@@ -641,7 +641,7 @@ public class AppOpsManager {
"GET_ACCOUNTS",
"RUN_IN_BACKGROUND",
"AUDIO_ACCESSIBILITY_VOLUME",
- "READ_PHONE_NUMBER",
+ "READ_PHONE_NUMBERS",
"REQUEST_INSTALL_PACKAGES",
"PICTURE_IN_PICTURE",
"INSTANT_APP_START_FOREGROUND",
@@ -718,7 +718,7 @@ public class AppOpsManager {
Manifest.permission.GET_ACCOUNTS,
null, // no permission for running in background
null, // no permission for changing accessibility volume
- Manifest.permission.READ_PHONE_NUMBER,
+ Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.REQUEST_INSTALL_PACKAGES,
null, // no permission for entering picture-in-picture on hide
Manifest.permission.INSTANT_APP_FOREGROUND_SERVICE,
@@ -796,7 +796,7 @@ public class AppOpsManager {
null, // GET_ACCOUNTS
null, // RUN_IN_BACKGROUND
UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_ACCESSIBILITY_VOLUME
- null, // READ_PHONE_NUMBER
+ null, // READ_PHONE_NUMBERS
null, // REQUEST_INSTALL_PACKAGES
null, // ENTER_PICTURE_IN_PICTURE_ON_HIDE
null, // INSTANT_APP_START_FOREGROUND
@@ -873,7 +873,7 @@ public class AppOpsManager {
false, // GET_ACCOUNTS
false, // RUN_IN_BACKGROUND
false, // AUDIO_ACCESSIBILITY_VOLUME
- false, // READ_PHONE_NUMBER
+ false, // READ_PHONE_NUMBERS
false, // REQUEST_INSTALL_PACKAGES
false, // ENTER_PICTURE_IN_PICTURE_ON_HIDE
false, // INSTANT_APP_START_FOREGROUND
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 461f9cc35125..a6838f8bbf0a 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1352,7 +1352,7 @@ public class ApplicationPackageManager extends PackageManager {
public Resources getResourcesForApplication(@NonNull ApplicationInfo app)
throws NameNotFoundException {
if (app.packageName.equals("system")) {
- return mContext.mMainThread.getSystemContext().getResources();
+ return mContext.mMainThread.getSystemUiContext().getResources();
}
final boolean sameUid = (app.uid == Process.myUid());
final Resources r = mContext.mMainThread.getTopLevelResources(
@@ -1383,7 +1383,7 @@ public class ApplicationPackageManager extends PackageManager {
"Call does not support special user #" + userId);
}
if ("system".equals(appPackageName)) {
- return mContext.mMainThread.getSystemContext().getResources();
+ return mContext.mMainThread.getSystemUiContext().getResources();
}
try {
ApplicationInfo ai = mPM.getApplicationInfo(appPackageName, sDefaultFlags, userId);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 5a7246a4ed38..75f9d671fbad 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2218,6 +2218,18 @@ class ContextImpl extends Context {
return context;
}
+ /**
+ * System Context to be used for UI. This Context has resources that can be themed.
+ */
+ static ContextImpl createSystemUiContext(ActivityThread mainThread) {
+ LoadedApk packageInfo = new LoadedApk(mainThread);
+ ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
+ null);
+ context.setResources(createResources(null, packageInfo, null, Display.DEFAULT_DISPLAY, null,
+ packageInfo.getCompatibilityInfo()));
+ return context;
+ }
+
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 02fe101c9152..3102a93790b2 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1716,19 +1716,55 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
/**
* Called when the Fragment's activity changes from fullscreen mode to multi-window mode and
* visa-versa. This is generally tied to {@link Activity#onMultiWindowModeChanged} of the
+ * containing Activity. This method provides the same configuration that will be sent in the
+ * following {@link #onConfigurationChanged(Configuration)} call after the activity enters this
+ * mode.
+ *
+ * @param isInMultiWindowMode True if the activity is in multi-window mode.
+ * @param newConfig The new configuration of the activity with the state
+ * {@param isInMultiWindowMode}.
+ */
+ public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
+ onMultiWindowModeChanged(isInMultiWindowMode);
+ }
+
+ /**
+ * Called when the Fragment's activity changes from fullscreen mode to multi-window mode and
+ * visa-versa. This is generally tied to {@link Activity#onMultiWindowModeChanged} of the
* containing Activity.
*
* @param isInMultiWindowMode True if the activity is in multi-window mode.
+ *
+ * @deprecated Use {@link #onMultiWindowModeChanged(boolean, Configuration)} instead.
*/
+ @Deprecated
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
}
/**
* Called by the system when the activity changes to and from picture-in-picture mode. This is
* generally tied to {@link Activity#onPictureInPictureModeChanged} of the containing Activity.
+ * This method provides the same configuration that will be sent in the following
+ * {@link #onConfigurationChanged(Configuration)} call after the activity enters this mode.
+ *
+ * @param isInPictureInPictureMode True if the activity is in picture-in-picture mode.
+ * @param newConfig The new configuration of the activity with the state
+ * {@param isInPictureInPictureMode}.
+ */
+ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode,
+ Configuration newConfig) {
+ onPictureInPictureModeChanged(isInPictureInPictureMode);
+ }
+
+ /**
+ * Called by the system when the activity changes to and from picture-in-picture mode. This is
+ * generally tied to {@link Activity#onPictureInPictureModeChanged} of the containing Activity.
*
* @param isInPictureInPictureMode True if the activity is in picture-in-picture mode.
+ *
+ * @deprecated Use {@link #onPictureInPictureModeChanged(boolean, Configuration)} instead.
*/
+ @Deprecated
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
}
@@ -2572,6 +2608,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
}
}
+ @Deprecated
void performMultiWindowModeChanged(boolean isInMultiWindowMode) {
onMultiWindowModeChanged(isInMultiWindowMode);
if (mChildFragmentManager != null) {
@@ -2579,6 +2616,14 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
}
}
+ void performMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
+ onMultiWindowModeChanged(isInMultiWindowMode, newConfig);
+ if (mChildFragmentManager != null) {
+ mChildFragmentManager.dispatchMultiWindowModeChanged(isInMultiWindowMode, newConfig);
+ }
+ }
+
+ @Deprecated
void performPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
onPictureInPictureModeChanged(isInPictureInPictureMode);
if (mChildFragmentManager != null) {
@@ -2586,6 +2631,15 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
}
}
+ void performPictureInPictureModeChanged(boolean isInPictureInPictureMode,
+ Configuration newConfig) {
+ onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
+ if (mChildFragmentManager != null) {
+ mChildFragmentManager.dispatchPictureInPictureModeChanged(isInPictureInPictureMode,
+ newConfig);
+ }
+ }
+
void performConfigurationChanged(Configuration newConfig) {
onConfigurationChanged(newConfig);
if (mChildFragmentManager != null) {
diff --git a/core/java/android/app/FragmentController.java b/core/java/android/app/FragmentController.java
index 9ea15a04e150..cff94d8cbf2d 100644
--- a/core/java/android/app/FragmentController.java
+++ b/core/java/android/app/FragmentController.java
@@ -250,23 +250,52 @@ public class FragmentController {
* <p>Call when the multi-window mode of the activity changed.
*
* @see Fragment#onMultiWindowModeChanged
+ * @deprecated use {@link #dispatchMultiWindowModeChanged(boolean, Configuration)}
*/
+ @Deprecated
public void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode) {
mHost.mFragmentManager.dispatchMultiWindowModeChanged(isInMultiWindowMode);
}
/**
+ * Lets all Fragments managed by the controller's FragmentManager know the multi-window mode of
+ * the activity changed.
+ * <p>Call when the multi-window mode of the activity changed.
+ *
+ * @see Fragment#onMultiWindowModeChanged
+ */
+ public void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode,
+ Configuration newConfig) {
+ mHost.mFragmentManager.dispatchMultiWindowModeChanged(isInMultiWindowMode, newConfig);
+ }
+
+ /**
* Lets all Fragments managed by the controller's FragmentManager know the picture-in-picture
* mode of the activity changed.
* <p>Call when the picture-in-picture mode of the activity changed.
*
* @see Fragment#onPictureInPictureModeChanged
+ * @deprecated use {@link #dispatchPictureInPictureModeChanged(boolean, Configuration)}
*/
+ @Deprecated
public void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
mHost.mFragmentManager.dispatchPictureInPictureModeChanged(isInPictureInPictureMode);
}
/**
+ * Lets all Fragments managed by the controller's FragmentManager know the picture-in-picture
+ * mode of the activity changed.
+ * <p>Call when the picture-in-picture mode of the activity changed.
+ *
+ * @see Fragment#onPictureInPictureModeChanged
+ */
+ public void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode,
+ Configuration newConfig) {
+ mHost.mFragmentManager.dispatchPictureInPictureModeChanged(isInPictureInPictureMode,
+ newConfig);
+ }
+
+ /**
* Lets all Fragments managed by the controller's FragmentManager
* know a configuration change occurred.
* <p>Call when there is a configuration change.
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 0c1be07ab231..279b9003f8c0 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1844,6 +1844,10 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
}
synchronized (this) {
if (mDestroyed || mHost == null) {
+ if (allowStateLoss) {
+ // This FragmentManager isn't attached, so drop the entire transaction.
+ return;
+ }
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
@@ -1960,6 +1964,10 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
}
public void execSingleAction(OpGenerator action, boolean allowStateLoss) {
+ if (allowStateLoss && (mHost == null || mDestroyed)) {
+ // This FragmentManager isn't attached, so drop the entire transaction.
+ return;
+ }
ensureExecReady(allowStateLoss);
if (action.generateOps(mTmpRecords, mTmpIsPop)) {
mExecutingActions = true;
@@ -2944,6 +2952,10 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
}
}
+ /**
+ * @deprecated use {@link #dispatchMultiWindowModeChanged(boolean, Configuration)}
+ */
+ @Deprecated
public void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode) {
if (mAdded == null) {
return;
@@ -2956,6 +2968,23 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
}
}
+ public void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode,
+ Configuration newConfig) {
+ if (mAdded == null) {
+ return;
+ }
+ for (int i = mAdded.size() - 1; i >= 0; --i) {
+ final Fragment f = mAdded.get(i);
+ if (f != null) {
+ f.performMultiWindowModeChanged(isInMultiWindowMode, newConfig);
+ }
+ }
+ }
+
+ /**
+ * @deprecated use {@link #dispatchPictureInPictureModeChanged(boolean, Configuration)}
+ */
+ @Deprecated
public void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
if (mAdded == null) {
return;
@@ -2968,6 +2997,19 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
}
}
+ public void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode,
+ Configuration newConfig) {
+ if (mAdded == null) {
+ return;
+ }
+ for (int i = mAdded.size() - 1; i >= 0; --i) {
+ final Fragment f = mAdded.get(i);
+ if (f != null) {
+ f.performPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
+ }
+ }
+ }
+
public void dispatchConfigurationChanged(Configuration newConfig) {
if (mAdded != null) {
for (int i=0; i<mAdded.size(); i++) {
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index e99691d5a8de..6c43fe3beca1 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -146,9 +146,10 @@ oneway interface IApplicationThread {
void notifyCleartextNetwork(in byte[] firstPacket);
void startBinderTracking();
void stopBinderTrackingAndDump(in ParcelFileDescriptor fd);
- void scheduleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode);
- void schedulePictureInPictureModeChanged(IBinder token,
- boolean isInPictureInPictureMode);
+ void scheduleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode,
+ in Configuration newConfig);
+ void schedulePictureInPictureModeChanged(IBinder token, boolean isInPictureInPictureMode,
+ in Configuration newConfig);
void scheduleLocalVoiceInteractionStarted(IBinder token,
IVoiceInteractor voiceInteractor);
void handleTrustStorageUpdate();
diff --git a/core/java/android/app/IServiceConnection.aidl b/core/java/android/app/IServiceConnection.aidl
index 6804071f26eb..97042aa2919f 100644
--- a/core/java/android/app/IServiceConnection.aidl
+++ b/core/java/android/app/IServiceConnection.aidl
@@ -21,6 +21,6 @@ import android.content.ComponentName;
/** @hide */
oneway interface IServiceConnection {
- void connected(in ComponentName name, IBinder service);
+ void connected(in ComponentName name, IBinder service, boolean dead);
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index dbed1beb4cf7..4205db098ef6 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -88,8 +88,8 @@ final class ServiceConnectionLeaked extends AndroidRuntimeException {
* @hide
*/
public final class LoadedApk {
-
- private static final String TAG = "LoadedApk";
+ static final String TAG = "LoadedApk";
+ static final boolean DEBUG = false;
private final ActivityThread mActivityThread;
final String mPackageName;
@@ -641,8 +641,7 @@ public final class LoadedApk {
final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
TextUtils.join(File.pathSeparator, zipPaths);
- if (ActivityThread.localLOGV)
- Slog.v(ActivityThread.TAG, "Class path: " + zip +
+ if (DEBUG) Slog.v(ActivityThread.TAG, "Class path: " + zip +
", JNI path: " + librarySearchPath);
boolean needToSetupJitProfiles = false;
@@ -1371,12 +1370,14 @@ public final class LoadedApk {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
+ if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
sd = map.get(c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
+ if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
if (map == null) {
- map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
+ map = new ArrayMap<>();
mServices.put(context, map);
}
map.put(c, sd);
@@ -1396,6 +1397,7 @@ public final class LoadedApk {
if (map != null) {
sd = map.get(c);
if (sd != null) {
+ if (DEBUG) Slog.d(TAG, "Removing dispatcher " + sd + " for conn " + c);
map.remove(c);
sd.doForget();
if (map.size() == 0) {
@@ -1461,10 +1463,11 @@ public final class LoadedApk {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
- public void connected(ComponentName name, IBinder service) throws RemoteException {
+ public void connected(ComponentName name, IBinder service, boolean dead)
+ throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
- sd.connected(name, service);
+ sd.connected(name, service, dead);
}
}
}
@@ -1533,23 +1536,23 @@ public final class LoadedApk {
return mUnbindLocation;
}
- public void connected(ComponentName name, IBinder service) {
+ public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityThread != null) {
- mActivityThread.post(new RunConnection(name, service, 0));
+ mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
- doConnected(name, service);
+ doConnected(name, service, dead);
}
}
public void death(ComponentName name, IBinder service) {
if (mActivityThread != null) {
- mActivityThread.post(new RunConnection(name, service, 1));
+ mActivityThread.post(new RunConnection(name, service, 1, false));
} else {
doDeath(name, service);
}
}
- public void doConnected(ComponentName name, IBinder service) {
+ public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
@@ -1594,6 +1597,9 @@ public final class LoadedApk {
if (old != null) {
mConnection.onServiceDisconnected(name);
}
+ if (dead) {
+ mConnection.onBindingDead(name);
+ }
// If there is a new service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
@@ -1616,15 +1622,16 @@ public final class LoadedApk {
}
private final class RunConnection implements Runnable {
- RunConnection(ComponentName name, IBinder service, int command) {
+ RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
mName = name;
mService = service;
mCommand = command;
+ mDead = dead;
}
public void run() {
if (mCommand == 0) {
- doConnected(mName, mService);
+ doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
@@ -1633,6 +1640,7 @@ public final class LoadedApk {
final ComponentName mName;
final IBinder mService;
final int mCommand;
+ final boolean mDead;
}
private final class DeathMonitor implements IBinder.DeathRecipient
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index b42df5e2e0fb..489a0f0975ae 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -984,7 +984,7 @@ public class ResourcesManager {
final ResourcesKey key = mResourceImpls.keyAt(i);
final WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i);
final ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
- if (impl != null && key.mResDir != null && key.mResDir.equals(baseCodePath)) {
+ if (impl != null && (key.mResDir == null || key.mResDir.equals(baseCodePath))) {
updatedResourceKeys.put(impl, new ResourcesKey(
key.mResDir,
key.mSplitResDirs,
diff --git a/core/java/android/app/admin/DeviceAdminService.java b/core/java/android/app/admin/DeviceAdminService.java
new file mode 100644
index 000000000000..cd0b1bf3d0a8
--- /dev/null
+++ b/core/java/android/app/admin/DeviceAdminService.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 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.admin;
+
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * Base class for a service that device owner/profile owners can optionally have.
+ *
+ * <p>The system searches for it with an intent filter with the
+ * {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE} action, and tries to keep a bound
+ * connection as long as the hosting user is running, so that the device/profile owner is always
+ * considered to be in the foreground.
+ *
+ * <p>Device/profile owners can use
+ * {@link android.content.pm.PackageManager#setComponentEnabledSetting(ComponentName, int, int)}
+ * to disable/enable its own service. For example, when a device/profile owner no longer needs
+ * to be in the foreground, it can (and should) disable its service.
+ *
+ * <p>The service must not be exported.
+ *
+ * <p>TODO: Describe how the system handles crashes in DO/PO.
+ */
+public class DeviceAdminService extends Service {
+ private final IDeviceAdminServiceImpl mImpl;
+
+ public DeviceAdminService() {
+ mImpl = new IDeviceAdminServiceImpl();
+ }
+
+ @Override
+ public final IBinder onBind(Intent intent) {
+ return mImpl.asBinder();
+ }
+
+ private class IDeviceAdminServiceImpl extends IDeviceAdminService.Stub {
+ }
+
+ // So far, we have no methods in this class.
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 6d8d5e93c1ee..2f0a630bcd04 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1515,6 +1515,16 @@ public class DevicePolicyManager {
public @interface ProvisioningPreCondition {}
/**
+ * Service action: Action for a service that device owner and profile owner can optionally
+ * own. If a device owner or a profile owner has such a service, the system tries to keep
+ * a bound connection to it, in order to keep their process always running.
+ * The service must not be exported.
+ */
+ @SdkConstant(SdkConstantType.SERVICE_ACTION)
+ public static final String ACTION_DEVICE_ADMIN_SERVICE
+ = "android.app.action.DEVICE_ADMIN_SERVICE";
+
+ /**
* Return true if the given administrator component is currently active (enabled) in the system.
*
* @param admin The administrator component to check for.
diff --git a/core/java/android/app/admin/IDeviceAdminService.aidl b/core/java/android/app/admin/IDeviceAdminService.aidl
new file mode 100644
index 000000000000..5276ed599226
--- /dev/null
+++ b/core/java/android/app/admin/IDeviceAdminService.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 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.admin;
+
+/**
+ * @hide
+ */
+interface IDeviceAdminService {
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index dbbfe308868c..be267b308bf3 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4631,4 +4631,18 @@ public abstract class Context {
public Handler getMainThreadHandler() {
throw new RuntimeException("Not implemented. Must override in a subclass.");
}
+
+ /**
+ * Throws an exception if the Context is using system resources,
+ * which are non-runtime-overlay-themable and may show inconsistent UI.
+ * @hide
+ */
+ public void assertRuntimeOverlayThemable() {
+ // Resources.getSystem() is a singleton and the only Resources not managed by
+ // ResourcesManager; therefore Resources.getSystem() is not themable.
+ if (getResources() == Resources.getSystem()) {
+ throw new IllegalArgumentException("Non-UI context used to display UI; "
+ + "get a UI context from ActivityThread#getSystemUiContext()");
+ }
+ }
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 116224b35d06..da887af52b2a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -16,8 +16,6 @@
package android.content;
-import static android.content.ContentProvider.maybeAddUserId;
-
import android.annotation.AnyRes;
import android.annotation.BroadcastBehavior;
import android.annotation.IntDef;
@@ -43,6 +41,7 @@ import android.os.ResultReceiver;
import android.os.ShellCommand;
import android.os.StrictMode;
import android.os.UserHandle;
+import android.os.storage.StorageManager;
import android.provider.DocumentsContract;
import android.provider.DocumentsProvider;
import android.provider.MediaStore;
@@ -50,9 +49,7 @@ import android.provider.OpenableColumns;
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
-
import com.android.internal.util.XmlUtils;
-
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -70,6 +67,8 @@ import java.util.Locale;
import java.util.Objects;
import java.util.Set;
+import static android.content.ContentProvider.maybeAddUserId;
+
/**
* An intent is an abstract description of an operation to be performed. It
* can be used with {@link Context#startActivity(Intent) startActivity} to
@@ -1093,6 +1092,8 @@ public class Intent implements Parcelable, Cloneable {
* <p>Output: nothing.
* @hide
*/
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY";
/**
* Activity action: Perform a call to any number (emergency or not)
@@ -1102,6 +1103,8 @@ public class Intent implements Parcelable, Cloneable {
* <p>Output: nothing.
* @hide
*/
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";
/**
@@ -3349,6 +3352,32 @@ public class Intent implements Parcelable, Cloneable {
ACTION_DYNAMIC_SENSOR_CHANGED = "android.intent.action.DYNAMIC_SENSOR_CHANGED";
/**
+ * Broadcast Action: The default subscription has changed. This has the following
+ * extra values:</p>
+ * The {@link #EXTRA_SUBSCRIPTION_INDEX} extra indicates the current default subscription index
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED
+ = "android.intent.action.ACTION_DEFAULT_SUBSCRIPTION_CHANGED";
+
+ /**
+ * Broadcast Action: The default sms subscription has changed. This has the following
+ * extra values:</p>
+ * {@link #EXTRA_SUBSCRIPTION_INDEX} extra indicates the current default sms
+ * subscription index
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED
+ = "android.intent.action.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED";
+
+ /**
+ * Integer extra used with {@link #ACTION_DEFAULT_SUBSCRIPTION_CHANGED} and
+ * {@link #ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED} to indicate the subscription
+ * which has changed.
+ */
+ public static final String EXTRA_SUBSCRIPTION_INDEX = "android.intent.extra.SUBSCRIPTION_INDEX";
+
+ /**
* Deprecated - use {@link #ACTION_FACTORY_RESET} instead.
*
* {@hide}
@@ -3868,23 +3897,9 @@ public class Intent implements Parcelable, Cloneable {
public static final String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
/**
- * A content: URI holding a stream of data associated with the Intent, used
- * with {@link #ACTION_SEND} to supply the data being sent.
- * <p>
- * Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN} this value
- * will be automatically promoted to {@link Intent#setClipData(ClipData)}
- * when that value is not already defined.
- * <p>
- * Starting in {@link android.os.Build.VERSION_CODES#O} this value will be
- * automatically demoted from {@link Intent#getClipData()} when this value
- * is not already defined.
- *
- * @deprecated apps should use {@link Intent#setClipData(ClipData)} and
- * {@link Intent#getClipData()} instead of this extra, since
- * only those APIs can extend temporary permission grants to the
- * underlying resource.
+ * A content: URI holding a stream of data associated with the Intent,
+ * used with {@link #ACTION_SEND} to supply the data being sent.
*/
- @Deprecated
public static final String EXTRA_STREAM = "android.intent.extra.STREAM";
/**
@@ -9429,21 +9444,6 @@ public class Intent implements Parcelable, Cloneable {
mContentUserHint = UserHandle.USER_CURRENT;
}
}
-
- // If someone is sending us ClipData, but not EXTRA_STREAM, offer to
- // downgrade that content for older apps to find
- if (mClipData != null && mClipData.getItemCount() > 0 && !hasExtra(EXTRA_STREAM)) {
- final String action = getAction();
- if (ACTION_SEND.equals(action)) {
- putExtra(EXTRA_STREAM, mClipData.getItemAt(0).getUri());
- } else if (ACTION_SEND_MULTIPLE.equals(action)) {
- final ArrayList<Uri> list = new ArrayList<>();
- for (int i = 0; i < mClipData.getItemCount(); i++) {
- list.add(mClipData.getItemAt(i).getUri());
- }
- putExtra(EXTRA_STREAM, list);
- }
- }
}
/**
diff --git a/core/java/android/content/ServiceConnection.java b/core/java/android/content/ServiceConnection.java
index d115ce43e93d..8e428f9e9b3d 100644
--- a/core/java/android/content/ServiceConnection.java
+++ b/core/java/android/content/ServiceConnection.java
@@ -37,7 +37,7 @@ public interface ServiceConnection {
* @param service The IBinder of the Service's communication channel,
* which you can now make calls on.
*/
- public void onServiceConnected(ComponentName name, IBinder service);
+ void onServiceConnected(ComponentName name, IBinder service);
/**
* Called when a connection to the Service has been lost. This typically
@@ -49,5 +49,18 @@ public interface ServiceConnection {
* @param name The concrete component name of the service whose
* connection has been lost.
*/
- public void onServiceDisconnected(ComponentName name);
+ void onServiceDisconnected(ComponentName name);
+
+ /**
+ * Called when the binding to this connection is dead. This means the
+ * interface will never receive another connection. The application will
+ * need to unbind and rebind the connection to activate it again. This may
+ * happen, for example, if the application hosting the service it is bound to
+ * has been updated.
+ *
+ * @param name The concrete component name of the service whose
+ * connection is dead.
+ */
+ default void onBindingDead(ComponentName name) {
+ }
}
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 41311eb04837..c08bd1db8302 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -55,8 +55,7 @@ interface ILauncherApps {
String callingPackage, String packageName, int flags, in UserHandle user);
ParceledListSlice getShortcuts(String callingPackage, long changedSince, String packageName,
- in List shortcutIds, in ComponentName componentName, in Intent intent, int flags,
- in UserHandle user);
+ in List shortcutIds, in ComponentName componentName, int flags, in UserHandle user);
void pinShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
in UserHandle user);
boolean startShortcut(String callingPackage, String packageName, String id,
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index abdef084aacc..4d767555e3b3 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -275,11 +275,8 @@ public class LauncherApps {
@Deprecated
public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
- /**
- * Include chooser shortcuts in the result.
- * STOPSHIP TODO: Unless explicitly requesting chooser fields, we should strip out chooser
- * relevant fields from the Shortcut. This should also be adequately documented.
- */
+ /** @deprecated punted, don't use. */
+ @Deprecated
public static final int FLAG_MATCH_CHOOSER = 1 << 4;
/**
@@ -319,7 +316,6 @@ public class LauncherApps {
FLAG_MATCH_DYNAMIC,
FLAG_MATCH_PINNED,
FLAG_MATCH_MANIFEST,
- FLAG_MATCH_CHOOSER,
FLAG_GET_KEY_FIELDS_ONLY,
})
@Retention(RetentionPolicy.SOURCE)
@@ -336,9 +332,6 @@ public class LauncherApps {
@Nullable
ComponentName mActivity;
- @Nullable
- Intent mIntent;
-
@QueryFlags
int mQueryFlags;
@@ -382,11 +375,9 @@ public class LauncherApps {
return this;
}
- /**
- * If non-null, returns only shortcuts with intent filters that match this intent.
- */
+ /** @deprecated punted, don't use. */
+ @Deprecated
public ShortcutQuery setIntent(@Nullable Intent intent) {
- mIntent = intent;
return this;
}
@@ -428,7 +419,7 @@ public class LauncherApps {
*/
private void logErrorForInvalidProfileAccess(@NonNull UserHandle target) {
if (UserHandle.myUserId() != target.getIdentifier() && mUserManager.isManagedProfile()) {
- Log.e(TAG, "Accessing other profiles/users from managed profile is no longer allowed.");
+ Log.w(TAG, "Accessing other profiles/users from managed profile is no longer allowed.");
}
}
@@ -704,7 +695,7 @@ public class LauncherApps {
try {
return mService.getShortcuts(mContext.getPackageName(),
query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity,
- query.mIntent, query.mQueryFlags, user)
+ query.mQueryFlags, user)
.getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 136c13b6f37d..a493f33cfcb1 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2158,7 +2158,6 @@ public abstract class PackageManager {
* {@link #hasSystemFeature}: The device supports only leanback UI. Only
* applications designed for this experience should be run, though this is
* not enforced by the system.
- * @hide
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 16d582efb730..7bfde751e155 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -310,12 +310,18 @@ public abstract class PackageManagerInternal {
List<String> overlayPackageNames);
/**
- * Resolves an intent, allowing instant apps to be resolved.
+ * Resolves an activity intent, allowing instant apps to be resolved.
*/
public abstract ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId);
/**
+ * Resolves a service intent, allowing instant apps to be resolved.
+ */
+ public abstract ResolveInfo resolveService(Intent intent, String resolvedType,
+ int flags, int userId, int callingUid);
+
+ /**
* Track the creator of a new isolated uid.
* @param isolatedUid The newly created isolated uid.
* @param ownerUid The uid of the app that created the isolated process.
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 520169499718..3f4a09072540 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -21,7 +21,6 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.TaskStackBuilder;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -40,12 +39,10 @@ import android.util.ArraySet;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -99,14 +96,6 @@ public final class ShortcutInfo implements Parcelable {
public static final int FLAG_ADAPTIVE_BITMAP = 1 << 9;
/** @hide */
- public static final int FLAG_CHOOSER = 1 << 10;
-
- /**
- * TODO: Add FLAG_CHOOSER_INFO_OMITTED to reflect that chooser info was omitted in the Shortcut
- * due to the context in which it was retrieved.
- * TODO: Add a FLAG_LAUNCHABLE to reflect whether or not the Shortcut has a launchable intent
- * @hide
- */
@IntDef(flag = true,
value = {
FLAG_DYNAMIC,
@@ -119,7 +108,6 @@ public final class ShortcutInfo implements Parcelable {
FLAG_STRINGS_RESOLVED,
FLAG_IMMUTABLE,
FLAG_ADAPTIVE_BITMAP,
- FLAG_CHOOSER,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ShortcutFlags {}
@@ -214,24 +202,6 @@ public final class ShortcutInfo implements Parcelable {
@Nullable
private PersistableBundle[] mIntentPersistableExtrases;
- /**
- * If used in a chooser, extras that should be added into the intent passed through.
- */
- @Nullable
- private PersistableBundle mChooserExtras;
-
- /**
- * Intent filters to be used if the shortcut is to be used in a chooser context.
- */
- @Nullable
- private IntentFilter[] mChooserIntentFilters;
-
- /**
- * Component names corresponding to the above intent filters.
- */
- @Nullable
- private ComponentName[] mChooserComponentNames;
-
private int mRank;
/**
@@ -281,13 +251,6 @@ public final class ShortcutInfo implements Parcelable {
mDisabledMessageResId = b.mDisabledMessageResId;
mCategories = cloneCategories(b.mCategories);
mIntents = cloneIntents(b.mIntents);
- if (b.mChooserIntentFilters != null) {
- mChooserIntentFilters = b.mChooserIntentFilters.toArray(new IntentFilter[0]);
- }
- if (b.mChooserComponentNames != null) {
- mChooserComponentNames = b.mChooserComponentNames.toArray(new ComponentName[0]);
- }
- mChooserExtras = b.mChooserExtras;
fixUpIntentExtras();
mRank = b.mRank;
mExtras = b.mExtras;
@@ -368,28 +331,8 @@ public final class ShortcutInfo implements Parcelable {
if (mTitle == null && mTitleResId == 0) {
throw new IllegalArgumentException("Short label must be provided");
}
-
- // For a shortcut to be valid, there should either be an Intent, or a non-empty set of
- // intent filters.
- if (mIntents == null || mIntents.length == 0) {
- Preconditions.checkNotNull(mChooserIntentFilters,
- "Intent must be provided if not a chooser target");
- Preconditions.checkNotNull(mChooserComponentNames,
- "Intent must be provided if not a chooser target");
- }
-
- // If ChooserIntentFilter are provided, they should match the length of the provided
- // component names.
- if (mChooserIntentFilters != null) {
- if (mChooserComponentNames == null
- || mChooserIntentFilters.length != mChooserComponentNames.length) {
- throw new IllegalArgumentException("Inconsistent intent filters and "
- + "component names given");
- }
- if (mChooserIntentFilters.length == 0 || mChooserComponentNames.length == 0) {
- throw new IllegalArgumentException("Empty intent filter and component names given");
- }
- }
+ Preconditions.checkNotNull(mIntents, "Shortcut Intent must be provided");
+ Preconditions.checkArgument(mIntents.length > 0, "Shortcut Intent must be provided");
}
/**
@@ -434,10 +377,6 @@ public final class ShortcutInfo implements Parcelable {
mDisabledMessageResName = source.mDisabledMessageResName;
mIconResName = source.mIconResName;
}
- // TODO: Omit these by default and add a new clone flag.
- mChooserIntentFilters = source.mChooserIntentFilters;
- mChooserComponentNames = source.mChooserComponentNames;
- mChooserExtras = source.mChooserExtras;
} else {
// Set this bit.
mFlags |= FLAG_KEY_FIELDS_ONLY;
@@ -565,25 +504,6 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Whether the shortcut has any intentFilter matching the passed in one.
- * @hide
- */
- @VisibleForTesting
- public boolean hasMatchingFilter(ContentResolver resolver, Intent intent) {
- if (mChooserIntentFilters == null) {
- return false;
- }
- for (IntentFilter filter : mChooserIntentFilters) {
- int match = filter.match(resolver, intent, false, TAG);
- if (match > 0) {
- return true;
- }
- }
- return false;
- }
-
-
- /**
* Extract the entry name from a fully-donated resource name.
* e.g. "com.android.app1:drawable/icon1" -> "icon1"
* @hide
@@ -766,15 +686,6 @@ public final class ShortcutInfo implements Parcelable {
if (source.mExtras != null) {
mExtras = source.mExtras;
}
- if (source.mChooserExtras != null) {
- mChooserExtras = source.mChooserExtras;
- }
- if (source.mChooserIntentFilters != null) {
- mChooserIntentFilters = source.mChooserIntentFilters;
- }
- if (source.mChooserComponentNames != null) {
- mChooserComponentNames = source.mChooserComponentNames;
- }
}
/**
@@ -836,12 +747,6 @@ public final class ShortcutInfo implements Parcelable {
private PersistableBundle mExtras;
- private PersistableBundle mChooserExtras;
-
- private List<IntentFilter> mChooserIntentFilters;
-
- private List<ComponentName> mChooserComponentNames;
-
/**
* Old style constructor.
* @hide
@@ -1127,37 +1032,17 @@ public final class ShortcutInfo implements Parcelable {
return this;
}
- /**
- * Extras that can be added which will be added to the Intent used to launch the app if
- * launched from a chooser context.
- */
+ /** @deprecated punted, don't use. */
+ @Deprecated
@NonNull
public Builder setChooserExtras(@NonNull PersistableBundle extras) {
- mChooserExtras = extras;
return this;
}
- /**
- * IntentFilters and the components that should resolve a match for a given chooser target.
- * If multiple matches are found, the component corresponding to the closest match will be
- * used.
- *
- * @param filter IntendFilter that if matched will have the intent forwarded to the given
- * component
- * @param name The component that an intent that passes this filter will resolve to.
- */
+ /** @deprecated punted, don't use. */
+ @Deprecated
public Builder addChooserIntentFilter(@NonNull IntentFilter filter,
@NonNull ComponentName name) {
- Preconditions.checkNotNull(filter, "intent filter cannot be null");
- Preconditions.checkNotNull(name, "component name cannot be null");
-
- if (mChooserIntentFilters == null || mChooserComponentNames == null) {
- mChooserIntentFilters = new ArrayList<>();
- mChooserComponentNames = new ArrayList<>();
- }
-
- mChooserIntentFilters.add(filter);
- mChooserComponentNames.add(name);
return this;
}
@@ -1361,28 +1246,25 @@ public final class ShortcutInfo implements Parcelable {
return mIntentPersistableExtrases;
}
- /**
- * Retrieve the extras that will be added in to any intent launched through the chooser.
- */
+ /** @deprecated punted, don't use. */
+ @Deprecated
@NonNull
public PersistableBundle getChooserExtras() {
- return mChooserExtras;
+ return new PersistableBundle();
}
- /**
- * Retrieve the list of intent filters for chooser targets.
- */
+ /** @deprecated punted, don't use. */
+ @Deprecated
@NonNull
public IntentFilter[] getChooserIntentFilters() {
- return mChooserIntentFilters;
+ return new IntentFilter[0];
}
- /**
- * Retrieve the list of component names corresponding to the above intent filters.
- */
+ /** @deprecated punted, don't use. */
+ @Deprecated
@NonNull
public ComponentName[] getChooserComponentNames() {
- return mChooserComponentNames;
+ return new ComponentName[0];
}
/**
@@ -1506,9 +1388,10 @@ public final class ShortcutInfo implements Parcelable {
return hasFlags(FLAG_PINNED);
}
- /** Return whether a shortcut can be shown in the chooser. */
+ /** @deprecated punted, don't use. */
+ @Deprecated
public boolean isChooser() {
- return hasFlags(FLAG_CHOOSER);
+ return false;
}
/**
@@ -1539,14 +1422,6 @@ public final class ShortcutInfo implements Parcelable {
return isPinned() && !(isDynamic() || isManifestShortcut());
}
- /**
- * @return true if pinned but neither static nor dynamic.
- * @hide
- */
- public boolean isDynamicOrChooser() {
- return hasFlags(FLAG_DYNAMIC) || hasFlags(FLAG_CHOOSER);
- }
-
/** @hide */
public boolean isOriginallyFromManifest() {
return hasFlags(FLAG_IMMUTABLE);
@@ -1829,19 +1704,6 @@ public final class ShortcutInfo implements Parcelable {
mCategories.add(source.readString().intern());
}
}
-
- // We put a placeholder empty array in to keep the parcelable order, but can do away with
- // them at this point if they're empty.
- mChooserComponentNames = source.readParcelableArray(cl, ComponentName.class);
- if (mChooserComponentNames.length == 0) {
- mChooserComponentNames = null;
- }
-
- mChooserIntentFilters = source.readParcelableArray(cl, IntentFilter.class);
- if (mChooserIntentFilters.length == 0) {
- mChooserIntentFilters = null;
- }
- mChooserExtras = source.readPersistableBundle(cl);
}
@Override
@@ -1888,17 +1750,6 @@ public final class ShortcutInfo implements Parcelable {
} else {
dest.writeInt(0);
}
- if (mChooserComponentNames != null) {
- dest.writeParcelableArray(mChooserComponentNames, flags);
- } else {
- dest.writeParcelableArray(new ComponentName[0], flags);
- }
- if (mChooserIntentFilters != null) {
- dest.writeParcelableArray(mChooserIntentFilters, flags);
- } else {
- dest.writeParcelableArray(new IntentFilter[0], flags);
- }
- dest.writePersistableBundle(mChooserExtras);
}
public static final Creator<ShortcutInfo> CREATOR =
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index 3de19d19bfc3..7b7d8ae42528 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -45,8 +45,8 @@ public abstract class ShortcutServiceInternal {
getShortcuts(int launcherUserId,
@NonNull String callingPackage, long changedSince,
@Nullable String packageName, @Nullable List<String> shortcutIds,
- @Nullable ComponentName componentName, @Nullable Intent intent,
- @ShortcutQuery.QueryFlags int flags, int userId);
+ @Nullable ComponentName componentName, @ShortcutQuery.QueryFlags int flags,
+ int userId);
public abstract boolean
isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 99fbee1ea3cc..c8353c9bffb9 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -16,6 +16,11 @@
package android.content.res;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.DisplayInfo;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -293,6 +298,16 @@ public final class Configuration implements Parcelable, Comparable<Configuration
*/
public int screenLayout;
+ /**
+ * @hide
+ * {@link android.graphics.Rect} defining app bounds. The dimensions override usages of
+ * {@link DisplayInfo#appHeight} and {@link DisplayInfo#appWidth} and mirrors these values at
+ * the display level. Lower levels can override these values to provide custom bounds to enforce
+ * features such as a max aspect ratio.
+ * TODO(b/36812336): Move appBounds out of {@link Configuration}.
+ */
+ public Rect appBounds;
+
/** @hide */
static public int resetScreenLayout(int curLayout) {
return (curLayout&~(SCREENLAYOUT_LONG_MASK | SCREENLAYOUT_SIZE_MASK
@@ -882,6 +897,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
compatScreenWidthDp = o.compatScreenWidthDp;
compatScreenHeightDp = o.compatScreenHeightDp;
compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
+ setAppBounds(o.appBounds);
assetsSeq = o.assetsSeq;
seq = o.seq;
}
@@ -1032,6 +1048,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration
case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
default: sb.append("/"); sb.append(navigationHidden); break;
}
+ if (appBounds != null) {
+ sb.append(" appBounds="); sb.append(appBounds);
+ }
if (assetsSeq != 0) {
sb.append(" as.").append(assetsSeq);
}
@@ -1066,6 +1085,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
densityDpi = DENSITY_DPI_UNDEFINED;
assetsSeq = ASSETS_SEQ_UNDEFINED;
+ appBounds = null;
seq = 0;
}
@@ -1253,6 +1273,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration
if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
}
+ if (delta.appBounds != null && !delta.appBounds.equals(appBounds)) {
+ changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
+ setAppBounds(delta.appBounds);
+ }
if (delta.assetsSeq != ASSETS_SEQ_UNDEFINED) {
changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
assetsSeq = delta.assetsSeq;
@@ -1399,6 +1423,13 @@ public final class Configuration implements Parcelable, Comparable<Configuration
changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
}
+ // Make sure that one of the values is not null and that they are not equal.
+ if ((compareUndefined || delta.appBounds != null)
+ && appBounds != delta.appBounds
+ && (appBounds == null || !appBounds.equals(delta.appBounds))) {
+ changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
+ }
+
return changed;
}
@@ -1494,6 +1525,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
dest.writeInt(compatScreenWidthDp);
dest.writeInt(compatScreenHeightDp);
dest.writeInt(compatSmallestScreenWidthDp);
+ dest.writeValue(appBounds);
dest.writeInt(assetsSeq);
dest.writeInt(seq);
}
@@ -1529,6 +1561,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
compatScreenWidthDp = source.readInt();
compatScreenHeightDp = source.readInt();
compatSmallestScreenWidthDp = source.readInt();
+ appBounds = (Rect) source.readValue(null);
assetsSeq = source.readInt();
seq = source.readInt();
}
@@ -1706,6 +1739,33 @@ public final class Configuration implements Parcelable, Comparable<Configuration
/**
* @hide
*
+ * Helper method for setting the app bounds.
+ */
+ public void setAppBounds(Rect rect) {
+ if (rect == null) {
+ appBounds = null;
+ return;
+ }
+
+ setAppBounds(rect.left, rect.top, rect.right, rect.bottom);
+ }
+
+ /**
+ * @hide
+ *
+ * Helper method for setting the app bounds.
+ */
+ public void setAppBounds(int left, int top, int right, int bottom) {
+ if (appBounds == null) {
+ appBounds = new Rect();
+ }
+
+ appBounds.set(left, top, right, bottom);
+ }
+
+ /**
+ * @hide
+ *
* Clears the locale without changing layout direction.
*/
public void clearLocales() {
@@ -2212,6 +2272,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
private static final String XML_ATTR_SCREEN_HEIGHT = "height";
private static final String XML_ATTR_SMALLEST_WIDTH = "sw";
private static final String XML_ATTR_DENSITY = "density";
+ private static final String XML_ATTR_APP_BOUNDS = "app_bounds";
/**
* Reads the attributes corresponding to Configuration member fields from the Xml parser.
@@ -2261,6 +2322,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY,
DENSITY_DPI_UNDEFINED);
+ configOut.appBounds =
+ Rect.unflattenFromString(XmlUtils.readStringAttribute(parser, XML_ATTR_APP_BOUNDS));
// For persistence, we don't care about assetsSeq, so do not read it out.
}
@@ -2332,6 +2395,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
XmlUtils.writeIntAttribute(xml, XML_ATTR_DENSITY, config.densityDpi);
}
+ if (config.appBounds != null) {
+ XmlUtils.writeStringAttribute(xml, XML_ATTR_APP_BOUNDS,
+ config.appBounds.flattenToString());
+ }
+
// For persistence, we do not care about assetsSeq, so do not write it out.
}
}
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index b27600800cc6..e845359a35c4 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -102,6 +102,16 @@ public abstract class DisplayManagerInternal {
int displayId, DisplayInfo info);
/**
+ * Get current display info without override from WindowManager.
+ * Current implementation of LogicalDisplay#getDisplayInfoLocked() always returns display info
+ * with overrides from WM if set. This method can be used for getting real display size without
+ * overrides to determine if real changes to display metrics happened.
+ * @param displayId Id of the target display.
+ * @param outInfo {@link DisplayInfo} to fill.
+ */
+ public abstract void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo);
+
+ /**
* Called by the window manager to perform traversals while holding a
* surface flinger transaction.
*/
diff --git a/core/java/android/hardware/usb/UsbRequest.java b/core/java/android/hardware/usb/UsbRequest.java
index badb344aabad..239a2df5e1c3 100644
--- a/core/java/android/hardware/usb/UsbRequest.java
+++ b/core/java/android/hardware/usb/UsbRequest.java
@@ -60,9 +60,11 @@ public class UsbRequest {
// Prevent the connection from being finalized
private UsbDeviceConnection mConnection;
- /** Whether this buffer was {@link #enqueue enqueued (new behavior)} or {@link #queue queued
- * (deprecared behavior)}. */
- private boolean mIsUsingEnqueue;
+ /**
+ * Whether this buffer was {@link #queue(ByteBuffer) queued using the new behavior} or
+ * {@link #queue(ByteBuffer, int) queued using the deprecated behavior}.
+ */
+ private boolean mIsUsingNewQueue;
/** Temporary buffer than might be used while buffer is enqueued */
private ByteBuffer mTempBuffer;
@@ -172,7 +174,7 @@ public class UsbRequest {
*
* @return true if the queueing operation succeeded
*
- * @deprecated Use {@link #enqueue(ByteBuffer)} instead.
+ * @deprecated Use {@link #queue(ByteBuffer)} instead.
*/
@Deprecated
public boolean queue(ByteBuffer buffer, int length) {
@@ -219,23 +221,23 @@ public class UsbRequest {
*
* @return true if the queueing operation succeeded
*/
- public boolean enqueue(@Nullable ByteBuffer buffer) {
+ public boolean queue(@Nullable ByteBuffer buffer) {
// Request need to be initialized
Preconditions.checkState(mNativeContext != 0, "request is not initialized");
- // Request can not be currently enqueued
- Preconditions.checkState(!mIsUsingEnqueue, "request is currently enqueued");
+ // Request can not be currently queued
+ Preconditions.checkState(!mIsUsingNewQueue, "this request is currently queued");
boolean isSend = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT);
- boolean wasEnqueued;
+ boolean wasQueued;
synchronized (mLock) {
mBuffer = buffer;
if (buffer == null) {
// Null buffers enqueue empty USB requests which is supported
- mIsUsingEnqueue = true;
- wasEnqueued = native_enqueue(null, 0, 0);
+ mIsUsingNewQueue = true;
+ wasQueued = native_queue(null, 0, 0);
} else {
// Can only send/receive MAX_USBFS_BUFFER_SIZE bytes at once
Preconditions.checkArgumentInRange(buffer.remaining(), 0, MAX_USBFS_BUFFER_SIZE,
@@ -260,18 +262,18 @@ public class UsbRequest {
buffer = mTempBuffer;
}
- mIsUsingEnqueue = true;
- wasEnqueued = native_enqueue(buffer, buffer.position(), buffer.remaining());
+ mIsUsingNewQueue = true;
+ wasQueued = native_queue(buffer, buffer.position(), buffer.remaining());
}
}
- if (!wasEnqueued) {
- mIsUsingEnqueue = false;
+ if (!wasQueued) {
+ mIsUsingNewQueue = false;
mTempBuffer = null;
mBuffer = null;
}
- return wasEnqueued;
+ return wasQueued;
}
/* package */ void dequeue() {
@@ -279,9 +281,9 @@ public class UsbRequest {
int bytesTransferred;
synchronized (mLock) {
- if (mIsUsingEnqueue) {
+ if (mIsUsingNewQueue) {
bytesTransferred = native_dequeue_direct();
- mIsUsingEnqueue = false;
+ mIsUsingNewQueue = false;
if (mBuffer == null) {
// Nothing to do
@@ -332,7 +334,7 @@ public class UsbRequest {
private native boolean native_init(UsbDeviceConnection connection, int ep_address,
int ep_attributes, int ep_max_packet_size, int ep_interval);
private native void native_close();
- private native boolean native_enqueue(ByteBuffer buffer, int offset, int length);
+ private native boolean native_queue(ByteBuffer buffer, int offset, int length);
private native boolean native_queue_array(byte[] buffer, int length, boolean out);
private native int native_dequeue_array(byte[] buffer, int length, boolean out);
private native boolean native_queue_direct(ByteBuffer buffer, int length, boolean out);
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 495340dc7222..63bbd96bd01d 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -38,9 +38,6 @@ interface INetworkPolicyManager {
boolean isUidForeground(int uid);
- /** Higher priority listener before general event dispatch */
- void setConnectivityListener(INetworkPolicyListener listener);
-
void registerListener(INetworkPolicyListener listener);
void unregisterListener(INetworkPolicyListener listener);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e2100bd43898..660d53a91b99 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10324,6 +10324,10 @@ public final class Settings {
INSTANT_APP_SETTINGS.add(DEVELOPMENT_FORCE_RTL);
INSTANT_APP_SETTINGS.add(EPHEMERAL_COOKIE_MAX_SIZE_BYTES);
INSTANT_APP_SETTINGS.add(AIRPLANE_MODE_ON);
+ INSTANT_APP_SETTINGS.add(WINDOW_ANIMATION_SCALE);
+ INSTANT_APP_SETTINGS.add(TRANSITION_ANIMATION_SCALE);
+ INSTANT_APP_SETTINGS.add(ANIMATOR_DURATION_SCALE);
+ INSTANT_APP_SETTINGS.add(DEBUG_VIEW_ATTRIBUTES);
}
/**
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index 8e0103078a42..56b267fb2c9d 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -19,11 +19,13 @@ import android.Manifest;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.app.Dialog;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.os.Handler;
import android.os.IBinder;
@@ -34,6 +36,8 @@ import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.WindowManager;
+import com.android.internal.R;
+
/**
* A TileService provides the user a tile that can be added to Quick Settings.
* Quick Settings is a space provided that allows the user to change settings and
@@ -425,6 +429,15 @@ public class TileService extends Service {
}
/**
+ * @return True if the device supports quick settings and its assocated APIs.
+ * @hide
+ */
+ @TestApi
+ public static boolean isQuickSettingsSupported() {
+ return Resources.getSystem().getBoolean(R.bool.config_quickSettingsSupported);
+ }
+
+ /**
* Requests that a tile be put in the listening state so it can send an update.
*
* This method is only applicable to tiles that have {@link #META_DATA_ACTIVE_TILE} defined
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 5494377ceebd..6dedbde01995 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -50,7 +50,7 @@ import java.util.Arrays;
* <li>The real display area specifies the part of the display that contains content
* including the system decorations. Even so, the real display area may be smaller than the
* physical size of the display if the window manager is emulating a smaller display
- * using (adb shell am display-size). Use the following methods to query the
+ * using (adb shell wm size). Use the following methods to query the
* real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li>
* </ul>
* </p><p>
@@ -947,7 +947,7 @@ public final class Display {
* The size is adjusted based on the current rotation of the display.
* </p><p>
* The real size may be smaller than the physical size of the screen when the
- * window manager is emulating a smaller display (using adb shell am display-size).
+ * window manager is emulating a smaller display (using adb shell wm size).
* </p>
*
* @param outSize Set to the real size of the display.
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 3d11dcbf14bf..0cec496fa264 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -562,12 +562,10 @@ public final class DisplayInfo implements Parcelable {
outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;
- width = (configuration != null
- && configuration.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED)
- ? (int)((configuration.screenWidthDp * outMetrics.density) + 0.5f) : width;
- height = (configuration != null
- && configuration.screenHeightDp != Configuration.SCREEN_HEIGHT_DP_UNDEFINED)
- ? (int)((configuration.screenHeightDp * outMetrics.density) + 0.5f) : height;
+ width = configuration != null && configuration.appBounds != null
+ ? configuration.appBounds.width() : width;
+ height = configuration != null && configuration.appBounds != null
+ ? configuration.appBounds.height() : height;
outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width;
outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index ae1ee42c8720..d25e5f04fad2 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -118,7 +118,7 @@ public class FocusFinder {
* @return the "effective" root of {@param focused}
*/
private ViewGroup getEffectiveRoot(ViewGroup root, View focused) {
- if (focused == null) {
+ if (focused == null || focused == root) {
return root;
}
ViewParent effective = focused.getParent();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 884283dee789..b12a7676dd7f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -25523,7 +25523,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* <p>
* The tooltip will be displayed:
* <ul>
- * <li>On long click, unless is not handled otherwise (by OnLongClickListener or a context
+ * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
* menu). </li>
* <li>On hover, after a brief delay since the pointer has stopped moving </li>
* </ul>
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 79b0420a77e3..958d76109a9e 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1018,9 +1018,20 @@ public final class InputMethodManager {
}
}
- /** @hide */
+ /**
+ * This method is still kept for a while until android.support.v7.widget.SearchView ver. 26.0
+ * is publicly released because previous implementations of that class had relied on this method
+ * via reflection.
+ *
+ * @deprecated This is a hidden API. You should never use this.
+ * @hide
+ */
+ @Deprecated
public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
try {
+ Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be removed "
+ + "soon. If you are using android.support.v7.widget.SearchView, please update "
+ + "to version 26.0 or newer version.");
mService.showSoftInput(mClient, flags, resultReceiver);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index c235ebd4720d..df65659dface 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -23,21 +23,15 @@ import android.app.usage.UsageStatsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
import android.content.pm.LabeledIntent;
-import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
-import android.content.pm.ShortcutInfo;
-import android.content.pm.ShortcutManager;
import android.database.DataSetObserver;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
@@ -362,7 +356,6 @@ public class ChooserActivity extends ResolverActivity {
mChooserListAdapter.addServiceResults(null, Lists.newArrayList(mCallerChooserTargets));
}
mChooserRowAdapter = new ChooserRowAdapter(mChooserListAdapter);
- mChooserRowAdapter.updateRowScales();
mChooserRowAdapter.registerDataSetObserver(new OffsetDataSetObserver(adapterView));
adapterView.setAdapter(mChooserRowAdapter);
if (listView != null) {
@@ -849,9 +842,7 @@ public class ChooserActivity extends ResolverActivity {
return false;
}
intent.setComponent(mChooserTarget.getComponentName());
- if (mChooserTarget.getIntentExtras() != null) {
- intent.putExtras(mChooserTarget.getIntentExtras());
- }
+ intent.putExtras(mChooserTarget.getIntentExtras());
// Important: we will ignore the target security checks in ActivityManager
// if and only if the ChooserTarget's target package is the same package
@@ -934,8 +925,6 @@ public class ChooserActivity extends ResolverActivity {
private static final int MAX_SERVICE_TARGETS = 8;
private static final int MAX_TARGETS_PER_SERVICE = 4;
- private boolean mAreChooserShortcutsRetrieved;
-
private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
private final List<TargetInfo> mCallerTargets = new ArrayList<>();
private boolean mShowServiceTargets;
@@ -1027,21 +1016,6 @@ public class ChooserActivity extends ResolverActivity {
if (mServiceTargets != null) {
pruneServiceTargets();
}
-
- if (DEBUG) Log.d(TAG, "Adding pushed chooser targets");
-
- if (!mAreChooserShortcutsRetrieved) {
- LauncherApps launcherApps = getLauncherApps();
- LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery();
- query.setIntent(getTargetIntent());
- query.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_CHOOSER);
- List<ShortcutInfo> shortcuts = launcherApps.getShortcuts(query,
- android.os.Process.myUserHandle());
- if (DEBUG) Log.d(TAG, "Adding " + shortcuts.size() + " chooser shortcuts");
- addShortcuts(shortcuts);
- mAreChooserShortcutsRetrieved = true;
- }
-
if (DEBUG) Log.d(TAG, "List built querying services");
queryTargetServices(this);
}
@@ -1067,7 +1041,6 @@ public class ChooserActivity extends ResolverActivity {
public int getServiceTargetCount() {
if (!mShowServiceTargets) {
- if (DEBUG) Log.d("TAG", "Hiding service targets");
return 0;
}
return Math.min(mServiceTargets.size(), MAX_SERVICE_TARGETS);
@@ -1159,71 +1132,6 @@ public class ChooserActivity extends ResolverActivity {
notifyDataSetChanged();
}
- // TODO: Pushed targets need to be scored correctly
- public void addShortcuts(List<ShortcutInfo> infos) {
- for (ShortcutInfo info : infos) {
- List<ChooserTarget> newTargets = new ArrayList<>();
- final ComponentName cn = info.getActivity();
- ActivityInfo ai;
- ResolveInfo ri = new ResolveInfo();
- if (cn != null) {
- try {
- ai = getPackageManager().getActivityInfo(cn, 0);
- ri.activityInfo = ai;
- UserManager userManager =
- (UserManager) getSystemService(Context.USER_SERVICE);
- ri.iconResourceId = ai.icon;
- ri.labelRes = ai.labelRes;
- ri.resolvePackageName = ai.packageName;
- ri.activityInfo.applicationInfo = new ApplicationInfo(
- ri.activityInfo.applicationInfo);
- ri.activityInfo.applicationInfo = ai.applicationInfo;
- ri.activityInfo.applicationInfo.uid = getUserId();
- } catch (PackageManager.NameNotFoundException ignored) {
- if (DEBUG) Log.d(TAG, "Package not found, skipping this shortcut");
- continue;
- }
- }
-
- DisplayResolveInfo resolveInfo = new DisplayResolveInfo(getTargetIntent(),
- ri,
- info.getShortLabel(),
- info.getLongLabel(),
- getTargetIntent());
-
- int bestMatch = 0;
- ComponentName bestComponent = null;
- for (int i = 0; i < info.getChooserIntentFilters().length; i++) {
- int newMatch = info.getChooserIntentFilters()[i]
- .match(getContentResolver(), getTargetIntent(), false, TAG);
- if (DEBUG) Log.d(TAG, "A match was found with value: " + newMatch);
- if (newMatch > bestMatch) {
- bestMatch = newMatch;
- bestComponent = info.getChooserComponentNames()[i];
- }
- }
- if (bestMatch == 0) {
- Log.e(TAG, "Unexpectedly, no match was found for the provided chooser intent");
- return;
- }
-
- Bundle extrasToAdd =
- info.getChooserExtras() == null ? null: new Bundle(info.getChooserExtras());
- if (DEBUG) Log.d(TAG, "Adding service target " + info.getShortLabel());
- newTargets.add(new ChooserTarget(
- info.getShortLabel(),
- info.getIcon(),
- 1,
- bestComponent,
- extrasToAdd));
- addServiceResults(resolveInfo, newTargets);
- }
- if (mChooserRowAdapter != null) {
- mChooserRowAdapter.updateRowScales();
- }
- setShowServiceTargets(true);
- }
-
/**
* Set to true to reveal all service targets at once.
*/
@@ -1338,7 +1246,37 @@ public class ChooserActivity extends ResolverActivity {
@Override
public void onChanged() {
super.onChanged();
- updateRowScales();
+ final int rcount = getServiceTargetRowCount();
+ if (mServiceTargetScale == null
+ || mServiceTargetScale.length != rcount) {
+ RowScale[] old = mServiceTargetScale;
+ int oldRCount = old != null ? old.length : 0;
+ mServiceTargetScale = new RowScale[rcount];
+ if (old != null && rcount > 0) {
+ System.arraycopy(old, 0, mServiceTargetScale, 0,
+ Math.min(old.length, rcount));
+ }
+
+ for (int i = rcount; i < oldRCount; i++) {
+ old[i].cancelAnimation();
+ }
+
+ for (int i = oldRCount; i < rcount; i++) {
+ final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
+ .setInterpolator(mInterpolator);
+ mServiceTargetScale[i] = rs;
+ }
+
+ // Start the animations in a separate loop.
+ // The process of starting animations will result in
+ // binding views to set up initial values, and we must
+ // have ALL of the new RowScale objects created above before
+ // we get started.
+ for (int i = oldRCount; i < rcount; i++) {
+ mServiceTargetScale[i].startAnimation();
+ }
+ }
+
notifyDataSetChanged();
}
@@ -1355,40 +1293,6 @@ public class ChooserActivity extends ResolverActivity {
});
}
- void updateRowScales() {
- final int rcount = getServiceTargetRowCount();
- if (mServiceTargetScale == null
- || mServiceTargetScale.length != rcount) {
- if (DEBUG) Log.d(TAG, "Row scales need adjusting to " + rcount + " rows.");
- RowScale[] old = mServiceTargetScale;
- int oldRCount = old != null ? old.length : 0;
- mServiceTargetScale = new RowScale[rcount];
- if (old != null && rcount > 0) {
- System.arraycopy(old, 0, mServiceTargetScale, 0,
- Math.min(old.length, rcount));
- }
-
- for (int i = rcount; i < oldRCount; i++) {
- old[i].cancelAnimation();
- }
-
- for (int i = oldRCount; i < rcount; i++) {
- final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
- .setInterpolator(mInterpolator);
- mServiceTargetScale[i] = rs;
- }
-
- // Start the animations in a separate loop.
- // The process of starting animations will result in
- // binding views to set up initial values, and we must
- // have ALL of the new RowScale objects created above before
- // we get started.
- for (int i = oldRCount; i < rcount; i++) {
- mServiceTargetScale[i].startAnimation();
- }
- }
- }
-
private float getRowScale(int rowPosition) {
final int start = getCallerTargetRowCount();
final int end = start + getServiceTargetRowCount();
@@ -1659,10 +1563,6 @@ public class ChooserActivity extends ResolverActivity {
}
}
- public LauncherApps getLauncherApps() {
- return (LauncherApps) getSystemService(Context.LAUNCHER_APPS_SERVICE);
- }
-
static class ServiceResultInfo {
public final DisplayResolveInfo originalTarget;
public final List<ChooserTarget> resultTargets;
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index 1abb59b006dd..a70209c705c0 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -74,6 +74,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
private final Rect mOldStableInsets = new Rect();
private final Rect mSystemInsets = new Rect();
private final Rect mStableInsets = new Rect();
+ private final Rect mTmpRect = new Rect();
public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds,
Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable,
@@ -370,12 +371,6 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
DisplayListCanvas canvas = mSystemBarBackgroundNode.start(width, height);
mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
final int topInset = DecorView.getColorViewTopInset(mStableInsets.top, mSystemInsets.top);
- final int bottomInset = DecorView.getColorViewBottomInset(stableInsets.bottom,
- systemInsets.bottom);
- final int rightInset = DecorView.getColorViewRightInset(stableInsets.right,
- systemInsets.right);
- final int leftInset = DecorView.getColorViewLeftInset(stableInsets.left,
- systemInsets.left);
if (mStatusBarColor != null) {
mStatusBarColor.setBounds(0, 0, left + width, topInset);
mStatusBarColor.draw(canvas);
@@ -385,14 +380,8 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
// don't want the navigation bar background be moving around when resizing in docked mode.
// However, we need it for the transitions into/out of docked mode.
if (mNavigationBarColor != null && fullscreen) {
- final int size = DecorView.getNavBarSize(bottomInset, rightInset, leftInset);
- if (DecorView.isNavBarToRightEdge(bottomInset, rightInset)) {
- mNavigationBarColor.setBounds(width - size, 0, width, height);
- } else if (DecorView.isNavBarToLeftEdge(bottomInset, leftInset)) {
- mNavigationBarColor.setBounds(0, 0, size, height);
- } else {
- mNavigationBarColor.setBounds(0, height - size, width, height);
- }
+ DecorView.getNavigationBarRect(width, height, stableInsets, systemInsets, mTmpRect);
+ mNavigationBarColor.setBounds(mTmpRect);
mNavigationBarColor.draw(canvas);
}
mSystemBarBackgroundNode.end(canvas);
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index a8e16c96acfa..653796dc39e7 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -119,6 +119,21 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
// The height of a window which has not in DIP.
private final static int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5;
+ public static final ColorViewAttributes STATUS_BAR_COLOR_VIEW_ATTRIBUTES =
+ new ColorViewAttributes(SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
+ Gravity.TOP, Gravity.LEFT, Gravity.RIGHT,
+ Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME,
+ com.android.internal.R.id.statusBarBackground,
+ FLAG_FULLSCREEN);
+
+ public static final ColorViewAttributes NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES =
+ new ColorViewAttributes(
+ SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
+ Gravity.BOTTOM, Gravity.RIGHT, Gravity.LEFT,
+ Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
+ com.android.internal.R.id.navigationBarBackground,
+ 0 /* hideWindowFlag */);
+
// Cludge to address b/22668382: Set the shadow size to the maximum so that the layer
// size calculation takes the shadow size into account. We set the elevation currently
// to max until the first layout command has been executed.
@@ -162,18 +177,10 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
// View added at runtime to draw under the navigation bar area
private View mNavigationGuard;
- private final ColorViewState mStatusColorViewState = new ColorViewState(
- SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
- Gravity.TOP, Gravity.LEFT, Gravity.RIGHT,
- Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.statusBarBackground,
- FLAG_FULLSCREEN);
- private final ColorViewState mNavigationColorViewState = new ColorViewState(
- SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
- Gravity.BOTTOM, Gravity.RIGHT, Gravity.LEFT,
- Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.navigationBarBackground,
- 0 /* hideWindowFlag */);
+ private final ColorViewState mStatusColorViewState =
+ new ColorViewState(STATUS_BAR_COLOR_VIEW_ATTRIBUTES);
+ private final ColorViewState mNavigationColorViewState =
+ new ColorViewState(NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES);
private final Interpolator mShowInterpolator;
private final Interpolator mHideInterpolator;
@@ -983,35 +990,50 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
return false;
}
- static int getColorViewTopInset(int stableTop, int systemTop) {
+ public static int getColorViewTopInset(int stableTop, int systemTop) {
return Math.min(stableTop, systemTop);
}
- static int getColorViewBottomInset(int stableBottom, int systemBottom) {
+ public static int getColorViewBottomInset(int stableBottom, int systemBottom) {
return Math.min(stableBottom, systemBottom);
}
- static int getColorViewRightInset(int stableRight, int systemRight) {
+ public static int getColorViewRightInset(int stableRight, int systemRight) {
return Math.min(stableRight, systemRight);
}
- static int getColorViewLeftInset(int stableLeft, int systemLeft) {
+ public static int getColorViewLeftInset(int stableLeft, int systemLeft) {
return Math.min(stableLeft, systemLeft);
}
- static boolean isNavBarToRightEdge(int bottomInset, int rightInset) {
+ public static boolean isNavBarToRightEdge(int bottomInset, int rightInset) {
return bottomInset == 0 && rightInset > 0;
}
- static boolean isNavBarToLeftEdge(int bottomInset, int leftInset) {
+ public static boolean isNavBarToLeftEdge(int bottomInset, int leftInset) {
return bottomInset == 0 && leftInset > 0;
}
- static int getNavBarSize(int bottomInset, int rightInset, int leftInset) {
+ public static int getNavBarSize(int bottomInset, int rightInset, int leftInset) {
return isNavBarToRightEdge(bottomInset, rightInset) ? rightInset
: isNavBarToLeftEdge(bottomInset, leftInset) ? leftInset : bottomInset;
}
+ public static void getNavigationBarRect(int canvasWidth, int canvasHeight, Rect stableInsets,
+ Rect contentInsets, Rect outRect) {
+ final int bottomInset = getColorViewBottomInset(stableInsets.bottom, contentInsets.bottom);
+ final int leftInset = getColorViewLeftInset(stableInsets.left, contentInsets.left);
+ final int rightInset = getColorViewLeftInset(stableInsets.right, contentInsets.right);
+ final int size = getNavBarSize(bottomInset, rightInset, leftInset);
+ if (isNavBarToRightEdge(bottomInset, rightInset)) {
+ outRect.set(canvasWidth - size, 0, canvasWidth, canvasHeight);
+ } else if (isNavBarToLeftEdge(bottomInset, leftInset)) {
+ outRect.set(0, 0, size, canvasHeight);
+ } else {
+ outRect.set(0, canvasHeight - size, canvasWidth, canvasHeight);
+ }
+ }
+
WindowInsets updateColorViews(WindowInsets insets, boolean animate) {
WindowManager.LayoutParams attrs = mWindow.getAttributes();
int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
@@ -1131,9 +1153,14 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
}
private int calculateStatusBarColor() {
- int flags = mWindow.getAttributes().flags;
- return (flags & FLAG_TRANSLUCENT_STATUS) != 0 ? mSemiTransparentStatusBarColor
- : (flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 ? mWindow.mStatusBarColor
+ return calculateStatusBarColor(mWindow.getAttributes().flags,
+ mSemiTransparentStatusBarColor, mWindow.mStatusBarColor);
+ }
+
+ public static int calculateStatusBarColor(int flags, int semiTransparentStatusBarColor,
+ int statusBarColor) {
+ return (flags & FLAG_TRANSLUCENT_STATUS) != 0 ? semiTransparentStatusBarColor
+ : (flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 ? statusBarColor
: Color.BLACK;
}
@@ -1160,13 +1187,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
int size, boolean verticalBar, boolean seascape, int sideMargin,
boolean animate, boolean force) {
- state.present = (sysUiVis & state.systemUiHideFlag) == 0
- && (mWindow.getAttributes().flags & state.hideWindowFlag) == 0
- && ((mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
- || force);
- boolean show = state.present
- && (color & Color.BLACK) != 0
- && ((mWindow.getAttributes().flags & state.translucentFlag) == 0 || force);
+ state.present = state.attributes.isPresent(sysUiVis, mWindow.getAttributes().flags, force);
+ boolean show = state.attributes.isVisible(state.present, color,
+ mWindow.getAttributes().flags, force);
boolean showView = show && !isResizing() && size > 0;
boolean visibilityChanged = false;
@@ -1175,15 +1198,15 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
int resolvedHeight = verticalBar ? LayoutParams.MATCH_PARENT : size;
int resolvedWidth = verticalBar ? size : LayoutParams.MATCH_PARENT;
int resolvedGravity = verticalBar
- ? (seascape ? state.seascapeGravity : state.horizontalGravity)
- : state.verticalGravity;
+ ? (seascape ? state.attributes.seascapeGravity : state.attributes.horizontalGravity)
+ : state.attributes.verticalGravity;
if (view == null) {
if (showView) {
state.view = view = new View(mContext);
view.setBackgroundColor(color);
- view.setTransitionName(state.transitionName);
- view.setId(state.id);
+ view.setTransitionName(state.attributes.transitionName);
+ view.setId(state.attributes.id);
visibilityChanged = true;
view.setVisibility(INVISIBLE);
state.targetVisibility = VISIBLE;
@@ -2269,6 +2292,15 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
boolean visible;
int color;
+ final ColorViewAttributes attributes;
+
+ ColorViewState(ColorViewAttributes attributes) {
+ this.attributes = attributes;
+ }
+ }
+
+ public static class ColorViewAttributes {
+
final int id;
final int systemUiHideFlag;
final int translucentFlag;
@@ -2278,9 +2310,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
final String transitionName;
final int hideWindowFlag;
- ColorViewState(int systemUiHideFlag,
- int translucentFlag, int verticalGravity, int horizontalGravity,
- int seascapeGravity, String transitionName, int id, int hideWindowFlag) {
+ private ColorViewAttributes(int systemUiHideFlag, int translucentFlag, int verticalGravity,
+ int horizontalGravity, int seascapeGravity, String transitionName, int id,
+ int hideWindowFlag) {
this.id = id;
this.systemUiHideFlag = systemUiHideFlag;
this.translucentFlag = translucentFlag;
@@ -2290,6 +2322,24 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
this.transitionName = transitionName;
this.hideWindowFlag = hideWindowFlag;
}
+
+ public boolean isPresent(int sysUiVis, int windowFlags, boolean force) {
+ return (sysUiVis & systemUiHideFlag) == 0
+ && (windowFlags & hideWindowFlag) == 0
+ && ((windowFlags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
+ || force);
+ }
+
+ public boolean isVisible(boolean present, int color, int windowFlags, boolean force) {
+ return present
+ && (color & Color.BLACK) != 0
+ && ((windowFlags & translucentFlag) == 0 || force);
+ }
+
+ public boolean isVisible(int sysUiVis, int color, int windowFlags, boolean force) {
+ final boolean present = isPresent(sysUiVis, windowFlags, force);
+ return isVisible(present, color, windowFlags, force);
+ }
}
/**
diff --git a/core/jni/android_hardware_UsbRequest.cpp b/core/jni/android_hardware_UsbRequest.cpp
index 4b7e0dd562b2..01fe078f6f16 100644
--- a/core/jni/android_hardware_UsbRequest.cpp
+++ b/core/jni/android_hardware_UsbRequest.cpp
@@ -167,7 +167,7 @@ android_hardware_UsbRequest_queue_direct(JNIEnv *env, jobject thiz,
}
static jboolean
-android_hardware_UsbRequest_enqueue(JNIEnv *env, jobject thiz, jobject buffer, jint offset,
+android_hardware_UsbRequest_queue(JNIEnv *env, jobject thiz, jobject buffer, jint offset,
jint length)
{
struct usb_request* request = get_request_from_object(env, thiz);
@@ -226,8 +226,8 @@ static const JNINativeMethod method_table[] = {
{"native_init", "(Landroid/hardware/usb/UsbDeviceConnection;IIII)Z",
(void *)android_hardware_UsbRequest_init},
{"native_close", "()V", (void *)android_hardware_UsbRequest_close},
- {"native_enqueue", "(Ljava/nio/ByteBuffer;II)Z",
- (void *)android_hardware_UsbRequest_enqueue},
+ {"native_queue", "(Ljava/nio/ByteBuffer;II)Z",
+ (void *)android_hardware_UsbRequest_queue},
{"native_queue_array", "([BIZ)Z", (void *)android_hardware_UsbRequest_queue_array},
{"native_dequeue_array", "([BIZ)I", (void *)android_hardware_UsbRequest_dequeue_array},
{"native_queue_direct", "(Ljava/nio/ByteBuffer;IZ)Z",
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 713287e4cd7a..5839fd50d79a 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -101,17 +101,7 @@ sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) {
return sur;
}
-jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
- const sp<IGraphicBufferProducer>& bufferProducer) {
- if (bufferProducer == NULL) {
- return NULL;
- }
-
- sp<Surface> surface(new Surface(bufferProducer, true));
- if (surface == NULL) {
- return NULL;
- }
-
+jobject android_view_Surface_createFromSurface(JNIEnv* env, const sp<Surface>& surface) {
jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
gSurfaceClassInfo.ctor, (jlong)surface.get());
if (surfaceObj == NULL) {
@@ -126,6 +116,16 @@ jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
return surfaceObj;
}
+jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
+ const sp<IGraphicBufferProducer>& bufferProducer) {
+ if (bufferProducer == NULL) {
+ return NULL;
+ }
+
+ sp<Surface> surface(new Surface(bufferProducer, true));
+ return android_view_Surface_createFromSurface(env, surface);
+}
+
int android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f) {
switch(f) {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 0ab27f2e0f8d..b95258bca49c 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -346,6 +346,11 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
return false;
}
+ // Handle force_mount_namespace with MOUNT_EXTERNAL_NONE.
+ if (mount_mode == MOUNT_EXTERNAL_NONE) {
+ return true;
+ }
+
if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
ALOGW("Failed to mount %s to /storage: %s", storageSource.string(), strerror(errno));
diff --git a/core/jni/include/android_runtime/android_view_Surface.h b/core/jni/include/android_runtime/android_view_Surface.h
index 3f1bdff81aef..2641ab8f0337 100644
--- a/core/jni/include/android_runtime/android_view_Surface.h
+++ b/core/jni/include/android_runtime/android_view_Surface.h
@@ -69,6 +69,10 @@ extern bool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj);
/* Gets the underlying Surface from a Surface Java object. */
extern sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj);
+/* Creates a Surface from an android::Surface. */
+extern jobject android_view_Surface_createFromSurface(JNIEnv* env,
+ const sp<Surface>& surface);
+
/* Creates a Surface from an IGraphicBufferProducer. */
extern jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 362794e81c55..e7a447c54aef 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -798,13 +798,13 @@
android:description="@string/permdesc_readPhoneState"
android:protectionLevel="dangerous" />
- <!-- Allows read access to the device's phone number. This is a subset of the capabilities
+ <!-- Allows read access to the device's phone number(s). This is a subset of the capabilities
granted by {@link #READ_PHONE_STATE} but is exposed to ephemeral applications.
<p>Protection level: dangerous-->
- <permission android:name="android.permission.READ_PHONE_NUMBER"
+ <permission android:name="android.permission.READ_PHONE_NUMBERS"
android:permissionGroup="android.permission-group.PHONE"
android:label="@string/permlab_readPhoneNumber"
- android:description="@string/permdesc_readPhoneNumber"
+ android:description="@string/permdesc_readPhoneNumbers"
android:protectionLevel="dangerous|ephemeral" />
<!-- Allows an application to initiate a phone call without going through
@@ -3346,7 +3346,8 @@
android:documentLaunchMode="never"
android:relinquishTaskIdentity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
- android:process=":ui">
+ android:process=":ui"
+ android:visibleToInstantApps="true">
<intent-filter>
<action android:name="android.intent.action.CHOOSER" />
<category android:name="android.intent.category.DEFAULT" />
@@ -3360,7 +3361,8 @@
android:documentLaunchMode="never"
android:relinquishTaskIdentity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
- android:process=":ui">
+ android:process=":ui"
+ android:visibleToInstantApps="true">
<intent-filter>
<action android:name="android.intent.action.CHOOSE_ACCESSIBILITY_BUTTON" />
<category android:name="android.intent.category.DEFAULT" />
@@ -3421,7 +3423,8 @@
android:exported="true"
android:theme="@style/Theme.DeviceDefault.Light.Dialog"
android:label="@string/choose_account_label"
- android:process=":ui">
+ android:process=":ui"
+ android:visibleToInstantApps="true">
</activity>
<activity android:name="android.accounts.ChooseTypeAndAccountActivity"
@@ -3429,14 +3432,16 @@
android:exported="true"
android:theme="@style/Theme.DeviceDefault.Light.Dialog"
android:label="@string/choose_account_label"
- android:process=":ui">
+ android:process=":ui"
+ android:visibleToInstantApps="true">
</activity>
<activity android:name="android.accounts.ChooseAccountTypeActivity"
android:excludeFromRecents="true"
android:theme="@style/Theme.DeviceDefault.Light.Dialog"
android:label="@string/choose_account_label"
- android:process=":ui">
+ android:process=":ui"
+ android:visibleToInstantApps="true">
</activity>
<activity android:name="android.accounts.CantAddAccountActivity"
@@ -3450,7 +3455,8 @@
android:excludeFromRecents="true"
android:exported="true"
android:theme="@style/Theme.DeviceDefault.Light.DialogWhenLarge"
- android:process=":ui">
+ android:process=":ui"
+ android:visibleToInstantApps="true">
</activity>
<activity android:name="android.content.SyncActivityTooManyDeletes"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 554f50c23daa..ee73b6983888 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8566,6 +8566,11 @@
<!-- @hide From Theme.colorBackground, used for the TaskDescription background
color. -->
<attr name="colorBackground" />
+ <!-- @hide From Theme.statusBarColor, used for the TaskDescription status bar color. -->
+ <attr name="statusBarColor"/>
+ <!-- @hide From Theme.navigationBarColor, used for the TaskDescription navigation bar
+ color. -->
+ <attr name="navigationBarColor"/>
</declare-styleable>
<declare-styleable name="Shortcut">
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index bcd8a8aeb7f7..85ecaff26b21 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2819,4 +2819,7 @@
density will be scaled accordingly to maintain aspect ratio. A value of 0 indicates no
constraint will be enforced. -->
<integer name="config_maxUiWidth">0</integer>
+
+ <!-- Whether the device supports quick settings and its associated APIs -->
+ <bool name="config_quickSettingsSupported">true</bool>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4afa8dcdfb4a..831cf89e0e97 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -20,10 +20,8 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Suffix added to a number to signify size in bytes. -->
<string name="byteShort">B</string>
- <!-- Suffix added to a number to signify size in kilobytes (1000 bytes).
- If you retain the Latin script for the localization, please use the lowercase
- 'k', as it signifies 1000 bytes as opposed to 1024 bytes. -->
- <string name="kilobyteShort">kB</string>
+ <!-- Suffix added to a number to signify size in kilobytes (1000 bytes). -->
+ <string name="kilobyteShort">KB</string>
<!-- Suffix added to a number to signify size in megabytes. -->
<string name="megabyteShort">MB</string>
<!-- Suffix added to a number to signify size in gigabytes. -->
@@ -1094,9 +1092,9 @@
order to improve the calling experience.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_readPhoneNumber">read phone number</string>
+ <string name="permlab_readPhoneNumbers">read phone numbers</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_readPhoneNumber">Allows the app to access the phone number of the device.</string>
+ <string name="permdesc_readPhoneNumbers">Allows the app to access the phone numbers of the device.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_wakeLock" product="tablet">prevent tablet from sleeping</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index dfd18e77a264..ae05a69da20d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2955,4 +2955,5 @@
<java-symbol type="string" name="etws_primary_default_message_test" />
<java-symbol type="string" name="etws_primary_default_message_others" />
+ <java-symbol type="bool" name="config_quickSettingsSupported" />
</resources>
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 3dfecc646169..1080a9fcfe71 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -16,17 +16,6 @@
package com.android.internal.app;
-import android.app.Instrumentation;
-import android.content.ComponentName;
-import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.LauncherApps;
-import android.content.pm.PackageManager;
-import android.content.pm.ShortcutInfo;
-import android.content.pm.ShortcutManager;
-import android.graphics.drawable.Icon;
-import android.os.SystemClock;
import com.android.internal.R;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
@@ -59,31 +48,25 @@ import static com.android.internal.app.ChooserWrapperActivity.sOverrides;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.isA;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
/**
* Chooser activity instrumentation tests
*/
@RunWith(AndroidJUnit4.class)
public class ChooserActivityTest {
- private Instrumentation instrumentation;
-
- @Before
- public void setUp() {
- instrumentation = InstrumentationRegistry.getInstrumentation();
- sOverrides.reset();
- }
-
@Rule
public ActivityTestRule<ChooserWrapperActivity> mActivityRule =
new ActivityTestRule<>(ChooserWrapperActivity.class, false,
false);
+ @Before
+ public void cleanOverrideData() {
+ sOverrides.reset();
+ }
+
@Test
public void customTitle() throws InterruptedException {
Intent sendIntent = createSendImageIntent();
@@ -252,6 +235,7 @@ public class ChooserActivityTest {
chosen[0] = targetInfo.getResolveInfo();
return true;
};
+
// Make a stable copy of the components as the original list may be modified
List<ResolvedComponentInfo> stableCopy =
createResolvedComponentsForTestWithOtherProfile(2);
@@ -340,32 +324,6 @@ public class ChooserActivityTest {
assertThat(chosen[0], is(toChoose));
}
- public void pushedChooserTarget() {
- ResolveInfo[] chosen = new ResolveInfo[1];
- sOverrides.onSafelyStartCallback = targetInfo -> {
- chosen[0] = targetInfo.getResolveInfo();
- return true;
- };
-
- setChooserShortcuts(1);
- List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
- when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
- Mockito.anyBoolean(),
- Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
-
- Intent sendIntent = createSendImageIntent();
- final ChooserWrapperActivity activity = mActivityRule
- .launchActivity(Intent.createChooser(sendIntent, null));
-
- waitForIdle();
-
- onView(withText("short chooser label 0"))
- .perform(click());
- waitForIdle();
- assertThat(chosen[0].resolvePackageName,
- is(ResolverDataProvider.createActivityInfo(0).packageName));
- }
-
private Intent createSendImageIntent() {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
@@ -413,48 +371,4 @@ public class ChooserActivityTest {
}
return packageStats.mChooserCounts.get(action).getOrDefault(annotation, 0);
}
-
- private void setChooserShortcuts(int numShortcuts) {
- ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
- for (int i = 0; i < numShortcuts; i++) {
- shortcuts.add(makeShortcut(i));
- }
- when(sOverrides.launcherApps.getShortcuts(
- Mockito.isA(LauncherApps.ShortcutQuery.class),
- Mockito.eq(UserHandle.SYSTEM)))
- .thenReturn(shortcuts);
- }
-
- private ShortcutInfo makeShortcut(int i) {
- try {
- IntentFilter filter = new IntentFilter(Intent.ACTION_SEND, "image/jpeg");
-
- ComponentName component = new ComponentName("foo.bar", "foo.bar" + ".MainActivity");
- ShortcutInfo.Builder b = new ShortcutInfo.Builder(instrumentation.getContext(), "" + i)
- .setActivity(component)
- .setShortLabel("short chooser label " + i)
- .setLongLabel("long chooser label" + i)
- .setRank(i)
- .setIntent(createSendImageIntent())
- .setIcon(Icon.createWithResource(instrumentation.getContext(),
- android.R.drawable.ic_menu_add))
- .addChooserIntentFilter(
- filter,
- component);
-
- sOverrides.createPackageManager = pm -> {
- final PackageManager spied = spy(pm);
- try {
- doAnswer(invocation -> ResolverDataProvider.createActivityInfo(i))
- .when(spied).getActivityInfo(
- Mockito.isA(ComponentName.class), Mockito.anyInt());
- } catch (Exception e) {
- // this is ok, just not found
- e.printStackTrace();
- }
- return spied;
- };
- return b.build();
- } catch (Exception e) {return null;}
- }
} \ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index 0dac2602740f..c446f3c79ea8 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -18,7 +18,6 @@ package com.android.internal.app;
import android.app.usage.UsageStatsManager;
import android.content.Context;
-import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import java.util.function.Function;
@@ -75,11 +74,6 @@ public class ChooserWrapperActivity extends ChooserActivity {
return super.getPackageManager();
}
- @Override
- public LauncherApps getLauncherApps() {
- return sOverrides.launcherApps;
- }
-
/**
* We cannot directly mock the activity created since instrumentation creates it.
* <p>
@@ -88,7 +82,6 @@ public class ChooserWrapperActivity extends ChooserActivity {
static class OverrideData {
@SuppressWarnings("Since15")
public Function<PackageManager, PackageManager> createPackageManager;
- public LauncherApps launcherApps;
public Function<TargetInfo, Boolean> onSafelyStartCallback;
public ResolverListController resolverListController;
public Boolean isVoiceInteraction;
@@ -97,7 +90,6 @@ public class ChooserWrapperActivity extends ChooserActivity {
onSafelyStartCallback = null;
isVoiceInteraction = null;
createPackageManager = null;
- launcherApps = mock(LauncherApps.class);
resolverListController = mock(ResolverListController.class);
}
}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 344f3c83ba6c..86ab3dc227f4 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -181,6 +181,9 @@
<allow-in-power-save package="com.android.cellbroadcastreceiver" />
<allow-in-power-save package="com.android.shell" />
+ <!-- STOPSHIP(b/36856786): Revert this once it is fixed properly -->
+ <allow-in-power-save package="com.google.android.apps.enterprise.dmagent" />
+
<!-- These are the packages that are white-listed to be able to run as system user -->
<system-user-whitelisted-app package="com.android.settings" />
diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java
index d69f67d138a1..218b857ce83c 100644
--- a/graphics/java/android/graphics/Color.java
+++ b/graphics/java/android/graphics/Color.java
@@ -289,7 +289,7 @@ import java.util.function.DoubleUnaryOperator;
* and <code>(1.0, 0.0, 0.0, 0.5)</code>.</p>
*/
@AnyThread
-public final class Color {
+public class Color {
@ColorInt public static final int BLACK = 0xFF000000;
@ColorInt public static final int DKGRAY = 0xFF444444;
@ColorInt public static final int GRAY = 0xFF888888;
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 7f579a2fd404..deafb6638ece 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -20,6 +20,7 @@ import android.annotation.CheckResult;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import java.io.PrintWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -170,6 +171,10 @@ public final class Rect implements Parcelable {
* or null if the string is not of that form.
*/
public static Rect unflattenFromString(String str) {
+ if (TextUtils.isEmpty(str)) {
+ return null;
+ }
+
Matcher matcher = UnflattenHelper.getMatcher(str);
if (!matcher.matches()) {
return null;
@@ -179,7 +184,7 @@ public final class Rect implements Parcelable {
Integer.parseInt(matcher.group(3)),
Integer.parseInt(matcher.group(4)));
}
-
+
/**
* Print short representation to given writer.
* @hide
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index c7796cdd4cc4..4adbf79d562c 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2540,6 +2540,44 @@ public class AudioManager {
/**
* @hide
+ * Notifies an application with a focus listener of gain or loss of audio focus.
+ * This method can only be used by owners of an {@link AudioPolicy} configured with
+ * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to true.
+ * @param afi the recipient of the focus change, that has previously requested audio focus, and
+ * that was received by the {@code AudioPolicy} through
+ * {@link AudioPolicy.AudioPolicyFocusListener#onAudioFocusRequest(AudioFocusInfo, int)}.
+ * @param focusChange one of focus gain types ({@link #AUDIOFOCUS_GAIN},
+ * {@link #AUDIOFOCUS_GAIN_TRANSIENT}, {@link #AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} or
+ * {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE})
+ * or one of the focus loss types ({@link AudioManager#AUDIOFOCUS_LOSS},
+ * {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT},
+ * or {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}).
+ * <br>For the focus gain, the change type should be the same as the app requested.
+ * @param ap a valid registered {@link AudioPolicy} configured as a focus policy.
+ * @return {@link #AUDIOFOCUS_REQUEST_GRANTED} if the dispatch was successfully sent, or
+ * {@link #AUDIOFOCUS_REQUEST_FAILED} if the focus client didn't have a listener, or
+ * if there was an error sending the request.
+ * @throws NullPointerException if the {@link AudioFocusInfo} or {@link AudioPolicy} are null.
+ */
+ @SystemApi
+ public int dispatchAudioFocusChange(@NonNull AudioFocusInfo afi, int focusChange,
+ @NonNull AudioPolicy ap) {
+ if (afi == null) {
+ throw new NullPointerException("Illegal null AudioFocusInfo");
+ }
+ if (ap == null) {
+ throw new NullPointerException("Illegal null AudioPolicy");
+ }
+ final IAudioService service = getService();
+ try {
+ return service.dispatchFocusChange(afi, focusChange, ap.cb());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
* Used internally by telephony package to abandon audio focus, typically after a call or
* when ringing ends and the call is rejected or not answered.
* Should match one or more calls to {@link #requestAudioFocusForCall(int, int)}.
@@ -2548,7 +2586,7 @@ public class AudioManager {
final IAudioService service = getService();
try {
service.abandonAudioFocus(null, AudioSystem.IN_VOICE_COMM_FOCUS_ID,
- null /*AudioAttributes, legacy behavior*/);
+ null /*AudioAttributes, legacy behavior*/, getContext().getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2579,7 +2617,7 @@ public class AudioManager {
final IAudioService service = getService();
try {
status = service.abandonAudioFocus(mAudioFocusDispatcher,
- getIdForAudioFocusListener(l), aa);
+ getIdForAudioFocusListener(l), aa, getContext().getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2787,7 +2825,7 @@ public class AudioManager {
final IAudioService service = getService();
try {
String regId = service.registerAudioPolicy(policy.getConfig(), policy.cb(),
- policy.hasFocusListener());
+ policy.hasFocusListener(), policy.isFocusPolicy());
if (regId == null) {
return ERROR;
} else {
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 58559843f1f9..884d41e59ada 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -20,6 +20,7 @@ import android.app.PendingIntent;
import android.bluetooth.BluetoothDevice;
import android.content.ComponentName;
import android.media.AudioAttributes;
+import android.media.AudioFocusInfo;
import android.media.AudioPlaybackConfiguration;
import android.media.AudioRecordingConfiguration;
import android.media.AudioRoutesInfo;
@@ -122,7 +123,8 @@ interface IAudioService {
IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
IAudioPolicyCallback pcb);
- int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, in AudioAttributes aa);
+ int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, in AudioAttributes aa,
+ in String callingPackageName);
void unregisterAudioFocusClient(String clientId);
@@ -164,7 +166,7 @@ interface IAudioService {
boolean isHdmiSystemAudioSupported();
String registerAudioPolicy(in AudioPolicyConfig policyConfig,
- in IAudioPolicyCallback pcb, boolean hasFocusListener);
+ in IAudioPolicyCallback pcb, boolean hasFocusListener, boolean isFocusPolicy);
oneway void unregisterAudioPolicyAsync(in IAudioPolicyCallback pcb);
@@ -196,5 +198,8 @@ interface IAudioService {
int getFocusRampTimeMs(in int focusGain, in AudioAttributes attr);
+ int dispatchFocusChange(in AudioFocusInfo afi, in int focusChange,
+ in IAudioPolicyCallback pcb);
+
// WARNING: read warning at top of file, it is recommended to add new methods at the end
}
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index cdc1d60fa789..4675e327ce25 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -746,14 +746,19 @@ public class MediaRecorder
}
/**
- * Sets the video encoding profile for recording. Call this method before prepare().
- * Prepare() may perform additional checks on the parameter to make sure whether the
- * specified profile and level are applicable, and sometimes the passed profile or
- * level will be discarded due to codec capablity or to ensure the video recording
- * can proceed smoothly based on the capabilities of the platform.
- * @hide
+ * Sets the desired video encoding profile and level for recording. The profile and level
+ * must be valid for the video encoder set by {@link #setVideoEncoder}. This method can
+ * called before or after {@link #setVideoEncoder} but it must be called before {@link #prepare}.
+ * {@code prepare()} may perform additional checks on the parameter to make sure that the specified
+ * profile and level are applicable, and sometimes the passed profile or level will be
+ * discarded due to codec capablity or to ensure the video recording can proceed smoothly
+ * based on the capabilities of the platform. <br>Application can also use the
+ * {@link MediaCodecInfo.CodecCapabilities#profileLevels} to query applicable combination of profile
+ * and level for the corresponding format. Note that the requested profile/level may not be supported by
+ * the codec that is actually being used by this MediaRecorder instance.
* @param profile declared in {@link MediaCodecInfo.CodecProfileLevel}.
* @param level declared in {@link MediaCodecInfo.CodecProfileLevel}.
+ * @throws IllegalArgumentException when an invalid profile or level value is used.
*/
public void setVideoEncodingProfileLevel(int profile, int level) {
if (profile <= 0) {
@@ -1281,3 +1286,4 @@ public class MediaRecorder
@Override
protected void finalize() { native_finalize(); }
}
+
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 423b4678441c..61d642f50179 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -68,6 +68,7 @@ public class AudioPolicy {
private int mStatus;
private String mRegistrationId;
private AudioPolicyStatusListener mStatusListener;
+ private boolean mIsFocusPolicy;
/**
* The behavior of a policy with regards to audio focus where it relies on the application
@@ -96,12 +97,14 @@ public class AudioPolicy {
public AudioPolicyConfig getConfig() { return mConfig; }
/** @hide */
public boolean hasFocusListener() { return mFocusListener != null; }
+ /** @hide */
+ public boolean isFocusPolicy() { return mIsFocusPolicy; }
/**
* The parameter is guaranteed non-null through the Builder
*/
private AudioPolicy(AudioPolicyConfig config, Context context, Looper looper,
- AudioPolicyFocusListener fl, AudioPolicyStatusListener sl) {
+ AudioPolicyFocusListener fl, AudioPolicyStatusListener sl, boolean isFocusPolicy) {
mConfig = config;
mStatus = POLICY_STATUS_UNREGISTERED;
mContext = context;
@@ -116,10 +119,12 @@ public class AudioPolicy {
}
mFocusListener = fl;
mStatusListener = sl;
+ mIsFocusPolicy = isFocusPolicy;
}
/**
- * Builder class for {@link AudioPolicy} objects
+ * Builder class for {@link AudioPolicy} objects.
+ * By default the policy to be created doesn't govern audio focus decisions.
*/
@SystemApi
public static class Builder {
@@ -128,6 +133,7 @@ public class AudioPolicy {
private Looper mLooper;
private AudioPolicyFocusListener mFocusListener;
private AudioPolicyStatusListener mStatusListener;
+ private boolean mIsFocusPolicy = false;
/**
* Constructs a new Builder with no audio mixes.
@@ -179,6 +185,21 @@ public class AudioPolicy {
}
/**
+ * Declares whether this policy will grant and deny audio focus through
+ * the {@link AudioPolicy.AudioPolicyStatusListener}.
+ * If set to {@code true}, it is mandatory to set an
+ * {@link AudioPolicy.AudioPolicyStatusListener} in order to successfully build
+ * an {@code AudioPolicy} instance.
+ * @param enforce true if the policy will govern audio focus decisions.
+ * @return the same Builder instance.
+ */
+ @SystemApi
+ public Builder setIsAudioFocusPolicy(boolean isFocusPolicy) {
+ mIsFocusPolicy = isFocusPolicy;
+ return this;
+ }
+
+ /**
* Sets the audio policy status listener.
* @param l a {@link AudioPolicy.AudioPolicyStatusListener}
*/
@@ -187,6 +208,14 @@ public class AudioPolicy {
mStatusListener = l;
}
+ /**
+ * Combines all of the attributes that have been set on this {@code Builder} and returns a
+ * new {@link AudioPolicy} object.
+ * @return a new {@code AudioPolicy} object.
+ * @throws IllegalStateException if there is no
+ * {@link AudioPolicy.AudioPolicyStatusListener} but the policy was configured
+ * as an audio focus policy with {@link #setIsAudioFocusPolicy(boolean)}.
+ */
@SystemApi
public AudioPolicy build() {
if (mStatusListener != null) {
@@ -195,8 +224,12 @@ public class AudioPolicy {
mix.mCallbackFlags |= AudioMix.CALLBACK_FLAG_NOTIFY_ACTIVITY;
}
}
+ if (mIsFocusPolicy && mFocusListener == null) {
+ throw new IllegalStateException("Cannot be a focus policy without "
+ + "an AudioPolicyFocusListener");
+ }
return new AudioPolicy(new AudioPolicyConfig(mMixes), mContext, mLooper,
- mFocusListener, mStatusListener);
+ mFocusListener, mStatusListener, mIsFocusPolicy);
}
}
@@ -402,6 +435,24 @@ public class AudioPolicy {
public static abstract class AudioPolicyFocusListener {
public void onAudioFocusGrant(AudioFocusInfo afi, int requestResult) {}
public void onAudioFocusLoss(AudioFocusInfo afi, boolean wasNotified) {}
+ /**
+ * Called whenever an application requests audio focus.
+ * Only ever called if the {@link AudioPolicy} was built with
+ * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to {@code true}.
+ * @param afi information about the focus request and the requester
+ * @param requestResult the result that was returned synchronously by the framework to the
+ * application, {@link #AUDIOFOCUS_REQUEST_FAILED},or
+ * {@link #AUDIOFOCUS_REQUEST_DELAYED}.
+ */
+ public void onAudioFocusRequest(AudioFocusInfo afi, int requestResult) {}
+ /**
+ * Called whenever an application abandons audio focus.
+ * Only ever called if the {@link AudioPolicy} was built with
+ * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to {@code true}.
+ * @param afi information about the focus request being abandoned and the original
+ * requester.
+ */
+ public void onAudioFocusAbandon(AudioFocusInfo afi) {}
}
private void onPolicyStatusChange() {
@@ -439,6 +490,22 @@ public class AudioPolicy {
}
}
+ public void notifyAudioFocusRequest(AudioFocusInfo afi, int requestResult) {
+ sendMsg(MSG_FOCUS_REQUEST, afi, requestResult);
+ if (DEBUG) {
+ Log.v(TAG, "notifyAudioFocusRequest: pack=" + afi.getPackageName() + " client="
+ + afi.getClientId() + "reqRes=" + requestResult);
+ }
+ }
+
+ public void notifyAudioFocusAbandon(AudioFocusInfo afi) {
+ sendMsg(MSG_FOCUS_ABANDON, afi, 0 /* ignored */);
+ if (DEBUG) {
+ Log.v(TAG, "notifyAudioFocusAbandon: pack=" + afi.getPackageName() + " client="
+ + afi.getClientId());
+ }
+ }
+
public void notifyMixStateUpdate(String regId, int state) {
for (AudioMix mix : mConfig.getMixes()) {
if (mix.getRegistration().equals(regId)) {
@@ -459,6 +526,8 @@ public class AudioPolicy {
private final static int MSG_FOCUS_GRANT = 1;
private final static int MSG_FOCUS_LOSS = 2;
private final static int MSG_MIX_STATE_UPDATE = 3;
+ private final static int MSG_FOCUS_REQUEST = 4;
+ private final static int MSG_FOCUS_ABANDON = 5;
private class EventHandler extends Handler {
public EventHandler(AudioPolicy ap, Looper looper) {
@@ -488,6 +557,20 @@ public class AudioPolicy {
mStatusListener.onMixStateUpdate((AudioMix) msg.obj);
}
break;
+ case MSG_FOCUS_REQUEST:
+ if (mFocusListener != null) {
+ mFocusListener.onAudioFocusRequest((AudioFocusInfo) msg.obj, msg.arg1);
+ } else { // should never be null, but don't crash
+ Log.e(TAG, "Invalid null focus listener for focus request event");
+ }
+ break;
+ case MSG_FOCUS_ABANDON:
+ if (mFocusListener != null) { // should never be null
+ mFocusListener.onAudioFocusAbandon((AudioFocusInfo) msg.obj);
+ } else { // should never be null, but don't crash
+ Log.e(TAG, "Invalid null focus listener for focus abandon event");
+ }
+ break;
default:
Log.e(TAG, "Unknown event " + msg.what);
}
diff --git a/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl b/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
index ad8af15b15f2..86abbb4dc8d9 100644
--- a/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
+++ b/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
@@ -22,9 +22,12 @@ import android.media.AudioFocusInfo;
*/
oneway interface IAudioPolicyCallback {
- // callbacks for audio focus
+ // callbacks for audio focus listening
void notifyAudioFocusGrant(in AudioFocusInfo afi, int requestResult);
void notifyAudioFocusLoss(in AudioFocusInfo afi, boolean wasNotified);
+ // callback for audio focus policy
+ void notifyAudioFocusRequest(in AudioFocusInfo afi, int requestResult);
+ void notifyAudioFocusAbandon(in AudioFocusInfo afi);
// callback for mix activity status update
void notifyMixStateUpdate(in String regId, int state);
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 06fc4bce3c76..d8c3eca300a3 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -16,6 +16,7 @@
package android.media.tv;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
@@ -840,7 +841,7 @@ public final class TvContract {
public interface BasePreviewProgramColumns extends BaseProgramColumns {
/** @hide */
- @StringDef({
+ @IntDef({
TYPE_MOVIE,
TYPE_TV_SERIES,
TYPE_TV_SEASON,
@@ -862,87 +863,87 @@ public final class TvContract {
*
* @see #COLUMN_TYPE
*/
- String TYPE_MOVIE = "TYPE_MOVIE";
+ int TYPE_MOVIE = 0;
/**
* The program type for TV series.
*
* @see #COLUMN_TYPE
*/
- String TYPE_TV_SERIES = "TYPE_TV_SERIES";
+ int TYPE_TV_SERIES = 1;
/**
* The program type for TV season.
*
* @see #COLUMN_TYPE
*/
- String TYPE_TV_SEASON = "TYPE_TV_SEASON";
+ int TYPE_TV_SEASON = 2;
/**
* The program type for TV episode.
*
* @see #COLUMN_TYPE
*/
- String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
+ int TYPE_TV_EPISODE = 3;
/**
* The program type for clip.
*
* @see #COLUMN_TYPE
*/
- String TYPE_CLIP = "TYPE_CLIP";
+ int TYPE_CLIP = 4;
/**
* The program type for event.
*
* @see #COLUMN_TYPE
*/
- String TYPE_EVENT = "TYPE_EVENT";
+ int TYPE_EVENT = 5;
/**
* The program type for channel.
*
* @see #COLUMN_TYPE
*/
- String TYPE_CHANNEL = "TYPE_CHANNEL";
+ int TYPE_CHANNEL = 6;
/**
* The program type for track.
*
* @see #COLUMN_TYPE
*/
- String TYPE_TRACK = "TYPE_TRACK";
+ int TYPE_TRACK = 7;
/**
* The program type for album.
*
* @see #COLUMN_TYPE
*/
- String TYPE_ALBUM = "TYPE_ALBUM";
+ int TYPE_ALBUM = 8;
/**
* The program type for artist.
*
* @see #COLUMN_TYPE
*/
- String TYPE_ARTIST = "TYPE_ARTIST";
+ int TYPE_ARTIST = 9;
/**
* The program type for playlist.
*
* @see #COLUMN_TYPE
*/
- String TYPE_PLAYLIST = "TYPE_PLAYLIST";
+ int TYPE_PLAYLIST = 10;
/**
* The program type for station.
*
* @see #COLUMN_TYPE
*/
- String TYPE_STATION = "TYPE_STATION";
+ int TYPE_STATION = 11;
/** @hide */
- @StringDef({
+ @IntDef({
ASPECT_RATIO_16_9,
ASPECT_RATIO_3_2,
ASPECT_RATIO_1_1,
@@ -957,7 +958,7 @@ public final class TvContract {
* @see #COLUMN_POSTER_ART_ASPECT_RATIO
* @see #COLUMN_THUMBNAIL_ASPECT_RATIO
*/
- String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
+ int ASPECT_RATIO_16_9 = 0;
/**
* The aspect ratio for 3:2.
@@ -965,7 +966,7 @@ public final class TvContract {
* @see #COLUMN_POSTER_ART_ASPECT_RATIO
* @see #COLUMN_THUMBNAIL_ASPECT_RATIO
*/
- String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
+ int ASPECT_RATIO_3_2 = 1;
/**
* The aspect ratio for 1:1.
@@ -973,7 +974,7 @@ public final class TvContract {
* @see #COLUMN_POSTER_ART_ASPECT_RATIO
* @see #COLUMN_THUMBNAIL_ASPECT_RATIO
*/
- String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
+ int ASPECT_RATIO_1_1 = 2;
/**
* The aspect ratio for 2:3.
@@ -981,10 +982,10 @@ public final class TvContract {
* @see #COLUMN_POSTER_ART_ASPECT_RATIO
* @see #COLUMN_THUMBNAIL_ASPECT_RATIO
*/
- String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
+ int ASPECT_RATIO_2_3 = 3;
/** @hide */
- @StringDef({
+ @IntDef({
AVAILABILITY_AVAILABLE,
AVAILABILITY_FREE_WITH_SUBSCRIPTION,
AVAILABILITY_PAID_CONTENT,
@@ -997,15 +998,14 @@ public final class TvContract {
*
* @see #COLUMN_AVAILABILITY
*/
- String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
+ int AVAILABILITY_AVAILABLE = 0;
/**
* The availability for "free with subscription".
*
* @see #COLUMN_AVAILABILITY
*/
- String AVAILABILITY_FREE_WITH_SUBSCRIPTION =
- "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
+ int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1;
/**
* The availability for "paid content, either to-own or rental
@@ -1013,72 +1013,72 @@ public final class TvContract {
*
* @see #COLUMN_AVAILABILITY
*/
- String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
+ int AVAILABILITY_PAID_CONTENT = 2;
/** @hide */
- @StringDef({
+ @IntDef({
+ INTERACTION_TYPE_VIEWS,
INTERACTION_TYPE_LISTENS,
INTERACTION_TYPE_FOLLOWERS,
INTERACTION_TYPE_FANS,
INTERACTION_TYPE_LIKES,
INTERACTION_TYPE_THUMBS,
- INTERACTION_TYPE_VIEWS,
INTERACTION_TYPE_VIEWERS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface InteractionType {}
/**
- * The interaction type for "listens".
+ * The interaction type for "views".
*
* @see #COLUMN_INTERACTION_TYPE
*/
- String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
+ int INTERACTION_TYPE_VIEWS = 0;
/**
- * The interaction type for "followers".
+ * The interaction type for "listens".
*
* @see #COLUMN_INTERACTION_TYPE
*/
- String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
+ int INTERACTION_TYPE_LISTENS = 1;
/**
- * The interaction type for "fans".
+ * The interaction type for "followers".
*
* @see #COLUMN_INTERACTION_TYPE
*/
- String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
+ int INTERACTION_TYPE_FOLLOWERS = 2;
/**
- * The interaction type for "likes".
+ * The interaction type for "fans".
*
* @see #COLUMN_INTERACTION_TYPE
*/
- String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
+ int INTERACTION_TYPE_FANS = 3;
/**
- * The interaction type for "thumbs".
+ * The interaction type for "likes".
*
* @see #COLUMN_INTERACTION_TYPE
*/
- String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
+ int INTERACTION_TYPE_LIKES = 4;
/**
- * The interaction type for "views".
+ * The interaction type for "thumbs".
*
* @see #COLUMN_INTERACTION_TYPE
*/
- String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
+ int INTERACTION_TYPE_THUMBS = 5;
/**
* The interaction type for "viewers".
*
* @see #COLUMN_INTERACTION_TYPE
*/
- String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
+ int INTERACTION_TYPE_VIEWERS = 6;
/** @hide */
- @StringDef({
+ @IntDef({
REVIEW_RATING_STYLE_STARS,
REVIEW_RATING_STYLE_THUMBS_UP_DOWN,
REVIEW_RATING_STYLE_PERCENTAGE,
@@ -1091,23 +1091,21 @@ public final class TvContract {
*
* @see #COLUMN_REVIEW_RATING_STYLE
*/
- String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
+ int REVIEW_RATING_STYLE_STARS = 0;
/**
* The review rating style for thumbs-up and thumbs-down rating.
*
* @see #COLUMN_REVIEW_RATING_STYLE
*/
- String REVIEW_RATING_STYLE_THUMBS_UP_DOWN =
- "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
+ int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1;
/**
* The review rating style for 0 to 100 point system.
*
* @see #COLUMN_REVIEW_RATING_STYLE
*/
- String REVIEW_RATING_STYLE_PERCENTAGE =
- "REVIEW_RATING_STYLE_PERCENTAGE";
+ int REVIEW_RATING_STYLE_PERCENTAGE = 2;
/**
* The type of this program content.
@@ -1129,7 +1127,7 @@ public final class TvContract {
* <p>This is a required field if the program is from a {@link Channels#TYPE_PREVIEW}
* channel.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
*/
String COLUMN_TYPE = "type";
@@ -1142,7 +1140,7 @@ public final class TvContract {
* {@link #ASPECT_RATIO_1_1}, and
* {@link #ASPECT_RATIO_2_3}.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
*/
String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
@@ -1155,7 +1153,7 @@ public final class TvContract {
* {@link #ASPECT_RATIO_1_1}, and
* {@link #ASPECT_RATIO_2_3}.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
*/
String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
@@ -1188,7 +1186,7 @@ public final class TvContract {
* {@link #AVAILABILITY_FREE_WITH_SUBSCRIPTION}, and
* {@link #AVAILABILITY_PAID_CONTENT}.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
*/
String COLUMN_AVAILABILITY = "availability";
@@ -1299,18 +1297,17 @@ public final class TvContract {
String COLUMN_DURATION_MILLIS = "duration_millis";
/**
- * The intent URI which is launched when the preview video is selected.
+ * The intent URI which is launched when the preview program is selected.
*
* <p>The URI is created using {@link Intent#toUri} with {@link Intent#URI_INTENT_SCHEME}
* and converted back to the original intent with {@link Intent#parseUri}. The intent is
- * launched when the user selects the preview video item.
+ * launched when the user selects the preview program item.
*
* <p>Can be empty.
*
* <p>Type: TEXT
*/
- String COLUMN_APP_LINK_INTENT_URI =
- "app_link_intent_uri";
+ String COLUMN_INTENT_URI = "intent_uri";
/**
* The flag indicating whether this program is transient or not.
@@ -1328,15 +1325,15 @@ public final class TvContract {
* The type of interaction for this TV program.
*
* <p> The value should match one of the followings:
+ * {@link #INTERACTION_TYPE_VIEWS},
* {@link #INTERACTION_TYPE_LISTENS},
* {@link #INTERACTION_TYPE_FOLLOWERS},
* {@link #INTERACTION_TYPE_FANS},
* {@link #INTERACTION_TYPE_LIKES},
- * {@link #INTERACTION_TYPE_THUMBS},
- * {@link #INTERACTION_TYPE_VIEWS}, and
+ * {@link #INTERACTION_TYPE_THUMBS}, and
* {@link #INTERACTION_TYPE_VIEWERS}.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
* @see #COLUMN_INTERACTION_COUNT
*/
String COLUMN_INTERACTION_TYPE = "interaction_type";
@@ -1364,7 +1361,7 @@ public final class TvContract {
* <p> The value should match one of the followings: {@link #REVIEW_RATING_STYLE_STARS},
* {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN}, and {@link #REVIEW_RATING_STYLE_PERCENTAGE}.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
* @see #COLUMN_REVIEW_RATING
*/
String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
@@ -2725,7 +2722,7 @@ public final class TvContract {
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
/** @hide */
- @StringDef({
+ @IntDef({
WATCH_NEXT_TYPE_CONTINUE,
WATCH_NEXT_TYPE_NEXT,
WATCH_NEXT_TYPE_NEW,
@@ -2740,7 +2737,7 @@ public final class TvContract {
*
* @see #COLUMN_WATCH_NEXT_TYPE
*/
- public static final String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
+ public static final int WATCH_NEXT_TYPE_CONTINUE = 0;
/**
* The watch next type for NEXT. Use this type when the user has watched one or more
@@ -2750,7 +2747,7 @@ public final class TvContract {
*
* @see #COLUMN_WATCH_NEXT_TYPE
*/
- public static final String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
+ public static final int WATCH_NEXT_TYPE_NEXT = 1;
/**
* The watch next type for NEW. Use this type when the user had watched all of the available
@@ -2760,7 +2757,7 @@ public final class TvContract {
*
* @see #COLUMN_WATCH_NEXT_TYPE
*/
- public static final String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
+ public static final int WATCH_NEXT_TYPE_NEW = 2;
/**
* The watch next type for WATCHLIST. Use this type when the user has elected to explicitly
@@ -2769,7 +2766,7 @@ public final class TvContract {
*
* @see #COLUMN_WATCH_NEXT_TYPE
*/
- public static final String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+ public static final int WATCH_NEXT_TYPE_WATCHLIST = 3;
/**
* The "watch next" type of this program content.
@@ -2782,7 +2779,7 @@ public final class TvContract {
*
* <p>This is a required field.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
*/
public static final String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index c7bed9bc1685..c82a1f6a646a 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -153,6 +153,7 @@ LIBANDROID {
ANativeWindow_acquire;
ANativeWindow_fromSurface;
ANativeWindow_fromSurfaceTexture; # introduced-arm=13 introduced-mips=13 introduced-x86=13
+ ANativeWindow_toSurface; # introduced=26
ANativeWindow_getFormat;
ANativeWindow_getHeight;
ANativeWindow_getWidth;
diff --git a/native/android/native_window_jni.cpp b/native/android/native_window_jni.cpp
index dc3040533974..859c550db94d 100644
--- a/native/android/native_window_jni.cpp
+++ b/native/android/native_window_jni.cpp
@@ -20,6 +20,7 @@
#include <android/native_window.h>
#include <system/window.h>
+#include <gui/Surface.h>
#include <utils/StrongPointer.h>
#include <android_runtime/android_view_Surface.h>
@@ -33,3 +34,11 @@ ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface) {
}
return win.get();
}
+
+jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) {
+ if (window == NULL) {
+ return NULL;
+ }
+ sp<Surface> surface = static_cast<Surface*>(window);
+ return android_view_Surface_createFromSurface(env, surface);
+}
diff --git a/packages/SettingsLib/res/values/attrs.xml b/packages/SettingsLib/res/values/attrs.xml
index 1f35d3e286e9..ea538fb320b1 100644
--- a/packages/SettingsLib/res/values/attrs.xml
+++ b/packages/SettingsLib/res/values/attrs.xml
@@ -36,6 +36,9 @@
<declare-styleable name="WifiEncryptionState">
<attr name="state_encrypted" format="boolean" />
</declare-styleable>
+ <declare-styleable name="WifiMeteredState">
+ <attr name="state_metered" format="boolean" />
+ </declare-styleable>
<declare-styleable name="WifiSavedState">
<attr name="state_saved" format="boolean" />
</declare-styleable>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index c2ce7c9fd5de..8833fb8cab53 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -1394,7 +1394,9 @@ public class ApplicationsState {
@Override
public boolean filterApp(AppEntry entry) {
- if ((entry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+ if (AppUtils.isInstant(entry.info)) {
+ return false;
+ } else if ((entry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
return true;
} else if ((entry.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
return true;
@@ -1407,6 +1409,23 @@ public class ApplicationsState {
}
};
+ /**
+ * Displays a combined list with "downloaded" and "visible in launcher" apps only.
+ */
+ public static final AppFilter FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT = new AppFilter() {
+
+ @Override
+ public void init() {
+ }
+
+ @Override
+ public boolean filterApp(AppEntry entry) {
+ return AppUtils.isInstant(entry.info)
+ || FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(entry);
+ }
+
+ };
+
public static final AppFilter FILTER_THIRD_PARTY = new AppFilter() {
@Override
public void init() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
index 69b45e5541b2..9ea7a4af8d12 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
@@ -71,14 +71,15 @@ public class BluetoothDiscoverableTimeoutReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
+ if (intent.getAction() == null || !intent.getAction().equals(INTENT_DISCOVERABLE_TIMEOUT)) {
+ return;
+ }
LocalBluetoothAdapter localBluetoothAdapter = LocalBluetoothAdapter.getInstance();
-
- if(localBluetoothAdapter != null &&
+ if(localBluetoothAdapter != null &&
localBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
Log.d(TAG, "Disable discoverable...");
-
localBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
- } else {
+ } else {
Log.e(TAG, "localBluetoothAdapter is NULL!!");
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index a3ae9269b1f7..abd4e294fecb 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -103,7 +103,7 @@ public class CachedBluetoothDeviceManager {
*/
public String getName(BluetoothDevice device) {
CachedBluetoothDevice cachedDevice = findDevice(device);
- if (cachedDevice != null) {
+ if (cachedDevice != null && cachedDevice.getName() != null) {
return cachedDevice.getName();
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
index 0f443d6791e3..61ca13d2819a 100755
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -63,7 +63,7 @@ public class BatteryMeterDrawableBase extends Drawable {
mPlusPaint;
private float mTextHeight, mWarningTextHeight;
private int mIconTint = Color.WHITE;
- private float mOldDarkIntensity = 0f;
+ private float mOldDarkIntensity = -1f;
private int mHeight;
private int mWidth;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index a9aaa05cb674..8f8167ee8187 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -44,6 +44,10 @@ public class AccessPointPreference extends Preference {
R.attr.state_encrypted
};
+ private static final int[] STATE_METERED = {
+ R.attr.state_metered
+ };
+
private static final int[] wifi_friction_attributes = { R.attr.wifi_friction };
private final StateListDrawable mFrictionSld;
@@ -179,6 +183,8 @@ public class AccessPointPreference extends Preference {
}
if (mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE) {
mFrictionSld.setState(STATE_SECURED);
+ } else if (mAccessPoint.getConfig() != null && mAccessPoint.getConfig().meteredHint) {
+ mFrictionSld.setState(STATE_METERED);
}
Drawable drawable = mFrictionSld.getCurrent();
frictionImageView.setImageDrawable(drawable);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 6f52dcace323..ec94841c7d0d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -26,7 +26,9 @@ public class WifiStatusTracker {
private final WifiManager mWifiManager;
public boolean enabled;
+ public int state;
public boolean connected;
+ public boolean connecting;
public String ssid;
public int rssi;
public int level;
@@ -39,11 +41,18 @@ public class WifiStatusTracker {
public void handleBroadcast(Intent intent) {
String action = intent.getAction();
if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+ state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+ WifiManager.WIFI_STATE_UNKNOWN);
+ enabled = state == WifiManager.WIFI_STATE_ENABLED;
+
+
enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
final NetworkInfo networkInfo = (NetworkInfo)
intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+ connecting = networkInfo != null && !networkInfo.isConnected()
+ && networkInfo.isConnectedOrConnecting();
connected = networkInfo != null && networkInfo.isConnected();
WifiInfo info = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO) != null
? (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO)
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
index e204a3a65c72..6a029f0be64d 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
@@ -110,6 +110,70 @@ public class ApplicationsStateTest {
}
@Test
+ public void testDownloadAndLauncherAndInstantAcceptsCorrectApps() {
+ // should include instant apps
+ mEntry.isHomeApp = false;
+ mEntry.hasLauncherEntry = false;
+ when(mEntry.info.isInstantApp()).thenReturn(true);
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+ .isTrue();
+
+ // should included updated system apps
+ when(mEntry.info.isInstantApp()).thenReturn(false);
+ mEntry.info.flags = ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+ .isTrue();
+
+ // should not include system apps other than the home app
+ mEntry.info.flags = ApplicationInfo.FLAG_SYSTEM;
+ mEntry.isHomeApp = false;
+ mEntry.hasLauncherEntry = false;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+ .isFalse();
+
+ // should include the home app
+ mEntry.isHomeApp = true;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+ .isTrue();
+
+ // should include any System app with a launcher entry
+ mEntry.isHomeApp = false;
+ mEntry.hasLauncherEntry = true;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+ .isTrue();
+ }
+
+ @Test
+ public void testDownloadAndLauncherAcceptsCorrectApps() {
+ mEntry.isHomeApp = false;
+ mEntry.hasLauncherEntry = false;
+
+ // should included updated system apps
+ when(mEntry.info.isInstantApp()).thenReturn(false);
+ mEntry.info.flags = ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(mEntry))
+ .isTrue();
+
+ // should not include system apps other than the home app
+ mEntry.info.flags = ApplicationInfo.FLAG_SYSTEM;
+ mEntry.isHomeApp = false;
+ mEntry.hasLauncherEntry = false;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(mEntry))
+ .isFalse();
+
+ // should include the home app
+ mEntry.isHomeApp = true;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(mEntry))
+ .isTrue();
+
+ // should include any System app with a launcher entry
+ mEntry.isHomeApp = false;
+ mEntry.hasLauncherEntry = true;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(mEntry))
+ .isTrue();
+ }
+
+ @Test
public void testInstantFilterAcceptsInstantApp() {
when(mEntry.info.isInstantApp()).thenReturn(true);
assertThat(ApplicationsState.FILTER_INSTANT.filterApp(mEntry)).isTrue();
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 635c96f23778..53c5b1b6b2bc 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -34,6 +34,7 @@ LOCAL_STATIC_ANDROID_LIBRARIES := \
android-support-v7-recyclerview \
android-support-v7-preference \
android-support-v7-appcompat \
+ android-support-v7-mediarouter \
android-support-v14-preference \
android-support-v17-leanback
diff --git a/packages/SystemUI/res/anim/ic_bluetooth_transient_group_1_animation.xml b/packages/SystemUI/res/anim/ic_bluetooth_transient_group_1_animation.xml
new file mode 100644
index 000000000000..26c6aa706cbf
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_bluetooth_transient_group_1_animation.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleX"
+ android:valueFrom="0.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleX"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleY"
+ android:valueFrom="0.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_bluetooth_transient_group_2_animation.xml b/packages/SystemUI/res/anim/ic_bluetooth_transient_group_2_animation.xml
new file mode 100644
index 000000000000..e1f8989b9a21
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_bluetooth_transient_group_2_animation.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleX"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@interpolator/ic_bluetooth_transient_animation_interpolator_0" />
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleY"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@interpolator/ic_bluetooth_transient_animation_interpolator_0" />
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_wifi_transient_wifi_1_animation.xml b/packages/SystemUI/res/anim/ic_signal_wifi_transient_wifi_1_animation.xml
new file mode 100644
index 000000000000..919a4ddd4f08
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_wifi_transient_wifi_1_animation.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="pathData"
+ android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="16"
+ android:propertyName="pathData"
+ android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 9.55569458008,-11.8414916992 9.55569458008,-11.8414916992 c 0.0,0.0 -3.32373046875,-3.83329772949 -9.59307861328,-3.7864074707 c -6.26933288574,0.046875 -9.61039733887,3.71441650391 -9.61039733887,3.71441650391 c 0.0,0.0 9.61378479004,11.913482666 9.61378479004,11.913482666 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="316"
+ android:propertyName="pathData"
+ android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 9.55569458008,-11.8414916992 9.55569458008,-11.8414916992 c 0.0,0.0 -3.32373046875,-3.83329772949 -9.59307861328,-3.7864074707 c -6.26933288574,0.046875 -9.61039733887,3.71441650391 -9.61039733887,3.71441650391 c 0.0,0.0 9.61378479004,11.913482666 9.61378479004,11.913482666 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 9.55569458008,-11.8414916992 9.55569458008,-11.8414916992 c 0.0,0.0 -3.32373046875,-3.83329772949 -9.59307861328,-3.7864074707 c -6.26933288574,0.046875 -9.61039733887,3.71441650391 -9.61039733887,3.71441650391 c 0.0,0.0 9.61378479004,11.913482666 9.61378479004,11.913482666 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="16"
+ android:propertyName="pathData"
+ android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 9.55569458008,-11.8414916992 9.55569458008,-11.8414916992 c 0.0,0.0 -3.32373046875,-3.83329772949 -9.59307861328,-3.7864074707 c -6.26933288574,0.046875 -9.61039733887,3.71441650391 -9.61039733887,3.71441650391 c 0.0,0.0 9.61378479004,11.913482666 9.61378479004,11.913482666 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 16.9385528564,-20.9904174805 16.9385528564,-20.9904174805 c -0.486480712891,-0.364868164062 -6.84008789062,-6.15798950195 -16.9654541016,-6.13645935059 c -10.1253662109,0.0215454101562 -16.4858551025,5.73852539062 -16.9723510742,6.10339355469 c 0.0,0.0 16.9652557373,21.0234832764 16.9652557373,21.0234832764 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="316"
+ android:propertyName="pathData"
+ android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 16.9385528564,-20.9904174805 16.9385528564,-20.9904174805 c -0.486480712891,-0.364868164062 -6.84008789062,-6.15798950195 -16.9654541016,-6.13645935059 c -10.1253662109,0.0215454101562 -16.4858551025,5.73852539062 -16.9723510742,6.10339355469 c 0.0,0.0 16.9652557373,21.0234832764 16.9652557373,21.0234832764 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 16.9385528564,-20.9904174805 16.9385528564,-20.9904174805 c -0.486480712891,-0.364868164062 -6.84008789062,-6.15798950195 -16.9654541016,-6.13645935059 c -10.1253662109,0.0215454101562 -16.4858551025,5.73852539062 -16.9723510742,6.10339355469 c 0.0,0.0 16.9652557373,21.0234832764 16.9652557373,21.0234832764 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="16"
+ android:propertyName="pathData"
+ android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 16.9385528564,-20.9904174805 16.9385528564,-20.9904174805 c -0.486480712891,-0.364868164062 -6.84008789062,-6.15798950195 -16.9654541016,-6.13645935059 c -10.1253662109,0.0215454101562 -16.4858551025,5.73852539062 -16.9723510742,6.10339355469 c 0.0,0.0 16.9652557373,21.0234832764 16.9652557373,21.0234832764 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="fillAlpha"
+ android:valueFrom="0.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="16"
+ android:propertyName="fillAlpha"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/drawable/ic_bluetooth_transient.xml b/packages/SystemUI/res/drawable/ic_bluetooth_transient.xml
new file mode 100644
index 000000000000..76026af392ec
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_bluetooth_transient.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="ic_bluetooth_transient"
+ android:width="48dp"
+ android:viewportWidth="48"
+ android:height="48dp"
+ android:viewportHeight="48" >
+ <group
+ android:name="ic_signal_wifi_4_bar_48px_outlines_"
+ android:translateX="21.9995"
+ android:translateY="25.73401" >
+ <group
+ android:name="ic_signal_wifi_4_bar_48px_outlines__pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <group
+ android:name="bluetooth"
+ android:translateX="22.08789"
+ android:translateY="18.72031" >
+ <group
+ android:name="bluetooth_pivot"
+ android:translateX="-22.08789"
+ android:translateY="-18.72031" >
+ <group
+ android:name="cross"
+ android:rotation="-1.88453" >
+ <path
+ android:name="extented_cross"
+ android:pathData="M 10.6188659668,6.56344604492 c 0.0,0.0 21.7386016846,23.1297454834 21.7386016846,23.1297454834"
+ android:strokeColor="#FFFFFFFF"
+ android:strokeWidth="4" />
+ </group>
+ <group
+ android:name="bluetooth_0"
+ android:translateX="23.38789"
+ android:translateY="18.72031" >
+ <path
+ android:name="b_shape_merged"
+ android:pathData="M 11.3999938965,-8.60000610352 c 0.0,0.0 -11.3999938965,-11.3999938965 -11.3999938965,-11.3999938965 c 0.0,0.0 -2.0,0.0 -2.0,0.0 c 0.0,0.0 0.0,15.1999969482 0.0,15.1999969482 c 0.0,0.0 -9.19999694824,-9.19999694824 -9.19999694824,-9.19999694824 c 0.0,0.0 -2.80000305176,2.80000305176 -2.80000305176,2.80000305176 c 0.0,0.0 11.1999969482,11.1999969482 11.1999969482,11.1999969482 c 0.0,0.0 -11.1999969482,11.1999969482 -11.1999969482,11.1999969482 c 0.0,0.0 2.80000305176,2.80000305176 2.80000305176,2.80000305176 c 0.0,0.0 9.19999694824,-9.19999694824 9.19999694824,-9.19999694824 c 0.0,0.0 0.0,15.1999969482 0.0,15.1999969482 c 0.0,0.0 2.0,0.0 2.0,0.0 c 0.0,0.0 11.3999938965,-11.3999938965 11.3999938965,-11.3999938965 c 0.0,0.0 -8.59999084473,-8.60000610352 -8.59999084473,-8.60000610352 c 0.0,0.0 8.59999084473,-8.60000610352 8.59999084473,-8.60000610352 Z M 2.0,-12.3000030518 c 0.0,0.0 3.80000305176,3.80000305176 3.80000305176,3.80000305176 c 0.0,0.0 -3.80000305176,3.69999694824 -3.80000305176,3.69999694824 c 0.0,0.0 0.0,-7.5 0.0,-7.5 Z M 5.80000305176,8.60000610352 c 0.0,0.0 -3.80000305176,3.69999694824 -3.80000305176,3.69999694824 c 0.0,0.0 0.0,-7.5 0.0,-7.5 c 0.0,0.0 3.80000305176,3.80000305176 3.80000305176,3.80000305176 Z"
+ android:fillColor="#FFFFFFFF" />
+ </group>
+ </group>
+ </group>
+ <group
+ android:name="dot_left"
+ android:translateX="20.16992"
+ android:translateY="18.64258" >
+ <group
+ android:name="dot_left_pivot"
+ android:translateX="-20.16992"
+ android:translateY="-18.64258" >
+ <group
+ android:name="group_1"
+ android:translateX="9.38789"
+ android:translateY="18.72031" >
+ <group
+ android:name="group_1_pivot"
+ android:translateX="-9.38789"
+ android:translateY="-18.72031" >
+ <path
+ android:name="dot_left_0"
+ android:pathData="M 13.3878936768,18.7203063965 c 0.0,0.0 -4.0,-4.0 -4.0,-4.0 c 0.0,0.0 -4.0,4.0 -4.0,4.0 c 0.0,0.0 4.0,4.0 4.0,4.0 c 0.0,0.0 4.0,-4.0 4.0,-4.0 Z"
+ android:fillColor="#FFFFFFFF" />
+ </group>
+ </group>
+ </group>
+ </group>
+ <group
+ android:name="dot_right"
+ android:translateX="26.16094"
+ android:translateY="18.60898" >
+ <group
+ android:name="dot_right_pivot"
+ android:translateX="-26.16094"
+ android:translateY="-18.60898" >
+ <group
+ android:name="group_2"
+ android:translateX="37.38789"
+ android:translateY="18.72031"
+ android:scaleX="0"
+ android:scaleY="0" >
+ <group
+ android:name="group_1_pivot_0"
+ android:translateX="-37.38789"
+ android:translateY="-18.72031" >
+ <path
+ android:name="dot_right_0"
+ android:pathData="M 37.3878936768,14.7203063965 c 0.0,0.0 -4.0,4.0 -4.0,4.0 c 0.0,0.0 4.0,4.0 4.0,4.0 c 0.0,0.0 4.0,-4.0 4.0,-4.0 c 0.0,0.0 -4.0,-4.0 -4.0,-4.0 Z"
+ android:fillColor="#FFFFFFFF" />
+ </group>
+ </group>
+ </group>
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_bluetooth_transient_animation.xml b/packages/SystemUI/res/drawable/ic_bluetooth_transient_animation.xml
new file mode 100644
index 000000000000..f7eb23c1c89d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_bluetooth_transient_animation.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_bluetooth_transient" >
+ <target
+ android:name="group_1"
+ android:animation="@anim/ic_bluetooth_transient_group_1_animation" />
+ <target
+ android:name="group_2"
+ android:animation="@anim/ic_bluetooth_transient_group_2_animation" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_wifi_transient.xml b/packages/SystemUI/res/drawable/ic_signal_wifi_transient.xml
new file mode 100644
index 000000000000..880e1bb075c7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_wifi_transient.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="ic_signal_wifi_transient"
+ android:width="48dp"
+ android:viewportWidth="48"
+ android:height="48dp"
+ android:viewportHeight="48" >
+ <group
+ android:name="ic_signal_wifi_4_bar_48px_2"
+ android:translateX="24.25"
+ android:translateY="25.73401" >
+ <group
+ android:name="ic_signal_wifi_4_bar_48px_2_pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <group
+ android:name="wifi_2"
+ android:translateX="23.481"
+ android:translateY="18.71151" >
+ <path
+ android:name="wifi"
+ android:pathData="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="0.5" />
+ </group>
+ <group
+ android:name="wifi_0"
+ android:translateX="23.481"
+ android:translateY="18.71151" >
+ <path
+ android:name="wifi_1"
+ android:pathData="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="0" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_wifi_transient_animation.xml b/packages/SystemUI/res/drawable/ic_signal_wifi_transient_animation.xml
new file mode 100644
index 000000000000..9f5aaebaf650
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_wifi_transient_animation.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_signal_wifi_transient" >
+ <target
+ android:name="wifi_1"
+ android:animation="@anim/ic_signal_wifi_transient_wifi_1_animation" />
+</animated-vector>
diff --git a/packages/SystemUI/res/interpolator/ic_bluetooth_transient_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_bluetooth_transient_animation_interpolator_0.xml
new file mode 100644
index 000000000000..c421f9e9e81c
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/ic_bluetooth_transient_animation_interpolator_0.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pathInterpolator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0.0,0.0 c 0.16666666667,0.0 0.83333333333,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
index 6bd79a4b4ae4..8078c4121424 100644
--- a/packages/SystemUI/res/layout/menu_ime.xml
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -27,6 +27,7 @@
android:layout_marginEnd="2dp"
android:scaleType="centerInside"
systemui:keyCode="82"
+ systemui:playSound="false"
android:visibility="invisible"
android:contentDescription="@string/accessibility_menu"
/>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index f405943811cf..008fcf0c62b4 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -20,6 +20,8 @@
<attr name="keyCode" format="integer" />
<!-- does this button generate longpress / repeat events? -->
<attr name="keyRepeat" format="boolean" />
+ <!-- Should this button play sound effects, default true -->
+ <attr name="playSound" format="boolean" />
<attr name="android:contentDescription" />
</declare-styleable>
<declare-styleable name="ToggleSliderView">
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ad39f5475554..a8cf3daec41e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1962,4 +1962,31 @@
<!-- Quick settings tile for toggling mobile data [CHAR LIMIT=20] -->
<string name="mobile_data">Mobile data</string>
+ <!-- Label for when wifi is off in QS detail panel [CHAR LIMIT=NONE] -->
+ <string name="wifi_is_off">Wi-Fi is off</string>
+
+ <!-- Label for when bluetooth is off in QS detail panel [CHAR LIMIT=NONE] -->
+ <string name="bt_is_off">Bluetooth is off</string>
+
+ <!-- Label for when Do not disturb is off in QS detail panel [CHAR LIMIT=NONE] -->
+ <string name="dnd_is_off">Do Not Disturb is off</string>
+
+ <!-- Prompt for when Do not disturb is on from automatic rule in QS [CHAR LIMIT=NONE] -->
+ <string name="qs_dnd_prompt_auto_rule">Do Not Disturb was turned on by an automatic rule (<xliff:g name="rule">%s</xliff:g>). Keep current settings?</string>
+
+ <!-- Prompt for when Do not disturb is on from app in QS [CHAR LIMIT=NONE] -->
+ <string name="qs_dnd_prompt_app">Do Not Disturb was turned on by an app (<xliff:g name="app">%s</xliff:g>). Keep current settings?</string>
+
+ <!-- Prompt for when Do not disturb is on from automatic rule or app in QS [CHAR LIMIT=NONE] -->
+ <string name="qs_dnd_prompt_auto_rule_app">Do Not Disturb was turned on by an automatic rule or app. Keep current settings?</string>
+
+ <!-- Description of Do Not Disturb option in QS that ends at the specified time[CHAR LIMIT=20] -->
+ <string name="qs_dnd_until">Until <xliff:g name="time">%s</xliff:g></string>
+
+ <!-- Do Not Disturb button to keep the current settings [CHAR LIMIT=20] -->
+ <string name="qs_dnd_keep">Keep</string>
+
+ <!-- Do Not Disturb button to change the current settings [CHAR LIMIT=20] -->
+ <string name="qs_dnd_replace">Replace</string>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 8c1062bf4cf4..d57e88cce351 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -98,6 +98,8 @@ public class BatteryMeterView extends LinearLayout implements
addView(mBatteryIconView, mlp);
updateShowPercent();
+ // Init to not dark at all.
+ onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
}
public void setForceShowPercent(boolean show) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 17228b9c876c..bcf1957109de 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -417,17 +417,17 @@ public class PipMenuActivity extends Activity {
}
private void updateDismissFraction(float fraction) {
- setDecorViewVisibility(true);
int alpha;
if (mMenuVisible) {
- mMenuContainer.setAlpha(1-fraction);
+ mMenuContainer.setAlpha(1 - fraction);
final float interpolatedAlpha =
MENU_BACKGROUND_ALPHA * (1.0f - fraction) + DISMISS_BACKGROUND_ALPHA * fraction;
- alpha = (int) (interpolatedAlpha*255);
+ alpha = (int) (interpolatedAlpha * 255);
} else {
- alpha = (int) (fraction*DISMISS_BACKGROUND_ALPHA*255);
+ alpha = (int) (fraction * DISMISS_BACKGROUND_ALPHA * 255);
}
mBackgroundDrawable.setAlpha(alpha);
+ setDecorViewVisibility(alpha > 0);
}
private void notifyRegisterInputConsumer() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index dd8cd2b3655f..ad290c388cb0 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -113,6 +113,7 @@ public class PipManager implements BasePipManager {
private IWindowManager mWindowManager;
private MediaSessionManager mMediaSessionManager;
private int mState = STATE_NO_PIP;
+ private int mResumeResizePinnedStackRunnable = STATE_NO_PIP;
private final Handler mHandler = new Handler();
private List<Listener> mListeners = new ArrayList<>();
private List<MediaListener> mMediaListeners = new ArrayList<>();
@@ -133,7 +134,7 @@ public class PipManager implements BasePipManager {
private final Runnable mResizePinnedStackRunnable = new Runnable() {
@Override
public void run() {
- resizePinnedStack(mState);
+ resizePinnedStack(mResumeResizePinnedStackRunnable);
}
};
private final Runnable mClosePipRunnable = new Runnable() {
@@ -364,16 +365,17 @@ public class PipManager implements BasePipManager {
void resizePinnedStack(int state) {
if (DEBUG) Log.d(TAG, "resizePinnedStack() state=" + state);
boolean wasStateNoPip = (mState == STATE_NO_PIP);
- mState = state;
+ mResumeResizePinnedStackRunnable = state;
for (int i = mListeners.size() - 1; i >= 0; --i) {
mListeners.get(i).onPipResizeAboutToStart();
}
if (mSuspendPipResizingReason != 0) {
- if (DEBUG) Log.d(TAG,
- "resizePinnedStack() deferring mSuspendPipResizingReason=" +
- mSuspendPipResizingReason);
+ if (DEBUG) Log.d(TAG, "resizePinnedStack() deferring"
+ + " mSuspendPipResizingReason=" + mSuspendPipResizingReason
+ + " mResumeResizePinnedStackRunnable=" + mResumeResizePinnedStackRunnable);
return;
}
+ mState = state;
switch (mState) {
case STATE_NO_PIP:
mCurrentPipBounds = null;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 4e4de15567d4..75e9d5ab063b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -114,7 +114,8 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
protected void handleUpdateState(BooleanState state, Object arg) {
final boolean enabled = mController.isBluetoothEnabled();
final boolean connected = mController.isBluetoothConnected();
- final boolean connecting = mController.isBluetoothConnecting();
+ state.isTransient = mController.isBluetoothConnecting()
+ || mController.getBluetoothState() == BluetoothAdapter.STATE_TURNING_ON;
state.dualTarget = true;
state.value = enabled;
if (enabled) {
@@ -124,8 +125,8 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
state.label = mController.getLastDeviceName();
state.contentDescription = mContext.getString(
R.string.accessibility_bluetooth_name, state.label);
- } else if (connecting) {
- state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_connecting);
+ } else if (state.isTransient) {
+ state.icon = ResourceIcon.get(R.drawable.ic_bluetooth_transient_animation);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_bluetooth_connecting);
state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 22b6a634cb9a..2725a329f6e0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -20,22 +20,29 @@ import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import android.service.quicksettings.Tile;
+import android.support.v7.app.MediaRouteChooserDialog;
+import android.support.v7.app.MediaRouteControllerDialog;
+import android.support.v7.media.MediaControlIntent;
+import android.support.v7.media.MediaRouteSelector;
import android.util.Log;
+import android.view.ContextThemeWrapper;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
+import android.view.WindowManager;
import android.widget.Button;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.R.style;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSHost;
-import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
@@ -109,7 +116,6 @@ public class CastTile extends QSTileImpl<BooleanState> {
if (mKeyguard.isSecure() && !mKeyguard.canSkipBouncer()) {
mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
showDetail(true);
- mHost.openPanels();
});
return;
}
@@ -117,6 +123,29 @@ public class CastTile extends QSTileImpl<BooleanState> {
}
@Override
+ public void showDetail(boolean show) {
+ mUiHandler.post(() -> {
+ Context context = new ContextThemeWrapper(mContext,
+ R.style.Theme_AppCompat_Light_Dialog_Alert);
+ if (mState.value) {
+ MediaRouteControllerDialog dialog = new MediaRouteControllerDialog(context);
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL);
+ dialog.show();
+ } else {
+ // Instead of showing detail, show standard media routing UI.
+ MediaRouteChooserDialog dialog = new MediaRouteChooserDialog(context);
+ MediaRouteSelector selector = new MediaRouteSelector.Builder()
+ .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
+ .build();
+ dialog.setRouteSelector(selector);
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL);
+ dialog.show();
+ }
+ mHost.collapsePanels();
+ });
+ }
+
+ @Override
public CharSequence getTileLabel() {
return mContext.getString(R.string.quick_settings_cast_title);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 04be7de644e3..9b3ee30a3ab0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -180,7 +180,7 @@ public class CellularTile extends QSTileImpl<SignalState> {
private final CallbackInfo mInfo = new CallbackInfo();
@Override
public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
- boolean activityIn, boolean activityOut, String description) {
+ boolean activityIn, boolean activityOut, String description, boolean isTransient) {
mInfo.wifiEnabled = enabled;
refreshState(mInfo);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 79b4c4a87596..7d2d210727ba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -157,7 +157,10 @@ public class WifiTile extends QSTileImpl<SignalState> {
state.activityOut = cb.enabled && cb.activityOut;
final StringBuffer minimalContentDescription = new StringBuffer();
final Resources r = mContext.getResources();
- if (!state.value) {
+ if (cb.isTransient) {
+ state.icon = ResourceIcon.get(R.drawable.ic_signal_wifi_transient_animation);
+ state.label = r.getString(R.string.quick_settings_wifi_label);
+ } else if (!state.value) {
state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_disabled);
state.label = r.getString(R.string.quick_settings_wifi_label);
} else if (wifiConnected) {
@@ -182,7 +185,7 @@ public class WifiTile extends QSTileImpl<SignalState> {
state.dualLabelContentDescription = r.getString(
R.string.accessibility_quick_settings_open_settings, getTileLabel());
state.expandedAccessibilityClassName = Switch.class.getName();
- state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+ state.state = state.value || cb.isTransient ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
}
@Override
@@ -226,6 +229,7 @@ public class WifiTile extends QSTileImpl<SignalState> {
boolean activityIn;
boolean activityOut;
String wifiSignalContentDescription;
+ boolean isTransient;
@Override
public String toString() {
@@ -237,6 +241,7 @@ public class WifiTile extends QSTileImpl<SignalState> {
.append(",activityIn=").append(activityIn)
.append(",activityOut=").append(activityOut)
.append(",wifiSignalContentDescription=").append(wifiSignalContentDescription)
+ .append(",isTransient=").append(isTransient)
.append(']').toString();
}
}
@@ -246,7 +251,7 @@ public class WifiTile extends QSTileImpl<SignalState> {
@Override
public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
- boolean activityIn, boolean activityOut, String description) {
+ boolean activityIn, boolean activityOut, String description, boolean isTransient) {
if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + enabled);
mInfo.enabled = enabled;
mInfo.connected = qsIcon.visible;
@@ -255,6 +260,7 @@ public class WifiTile extends QSTileImpl<SignalState> {
mInfo.activityIn = activityIn;
mInfo.activityOut = activityOut;
mInfo.wifiSignalContentDescription = qsIcon.contentDescription;
+ mInfo.isTransient = isTransient;
refreshState(mInfo);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 1c71da007fd0..3a43d304b1ca 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -355,9 +355,10 @@ public class SystemServicesProxy {
rti.firstActiveTime = rti.lastActiveTime = i;
if (i % 2 == 0) {
rti.taskDescription = new ActivityManager.TaskDescription(description,
- Bitmap.createBitmap(mDummyIcon), null,
- 0xFF000000 | (0xFFFFFF & new Random().nextInt()),
- 0xFF000000 | (0xFFFFFF & new Random().nextInt()));
+ Bitmap.createBitmap(mDummyIcon), null,
+ 0xFF000000 | (0xFFFFFF & new Random().nextInt()),
+ 0xFF000000 | (0xFFFFFF & new Random().nextInt()),
+ 0, 0);
} else {
rti.taskDescription = new ActivityManager.TaskDescription();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 67be99e5ccca..88711febe18d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -266,7 +266,7 @@ public class SignalClusterView extends LinearLayout implements NetworkController
@Override
public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
- boolean activityIn, boolean activityOut, String description) {
+ boolean activityIn, boolean activityOut, String description, boolean isTransient) {
mWifiVisible = statusIcon.visible && !mBlockWifi;
mWifiStrengthId = statusIcon.icon;
mWifiBadgeId = statusIcon.iconOverlay;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index c339da761fc9..a3ef91d95149 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -15,6 +15,7 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
+import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.util.ArraySet;
import android.view.Gravity;
@@ -22,6 +23,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.Dependency;
@@ -71,13 +73,18 @@ public interface StatusBarIconController {
}
@Override
- protected void onIconAdded(int index, String slot, boolean blocked, StatusBarIcon icon) {
- StatusBarIconView view = new StatusBarIconView(mContext, slot, null, blocked);
+ protected void onIconAdded(int index, String slot, boolean blocked,
+ StatusBarIcon icon) {
+ StatusBarIconView v = addIcon(index, slot, blocked, icon);
+ mDarkIconDispatcher.addDarkReceiver(v);
+ }
+
+ @Override
+ protected LayoutParams onCreateLayoutParams() {
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
lp.setMargins(mIconHPadding, 0, mIconHPadding, 0);
- mGroup.addView(view, index, lp);
- mDarkIconDispatcher.addDarkReceiver(view);
+ return lp;
}
@Override
@@ -116,11 +123,26 @@ public interface StatusBarIconController {
com.android.internal.R.dimen.status_bar_icon_size);
}
- protected void onIconAdded(int index, String slot, boolean blocked, StatusBarIcon icon) {
- StatusBarIconView view = new StatusBarIconView(mContext, slot, null, blocked);
+ protected void onIconAdded(int index, String slot, boolean blocked,
+ StatusBarIcon icon) {
+ addIcon(index, slot, blocked, icon);
+ }
+
+ protected StatusBarIconView addIcon(int index, String slot, boolean blocked,
+ StatusBarIcon icon) {
+ StatusBarIconView view = onCreateStatusBarIconView(slot, blocked);
view.set(icon);
- mGroup.addView(view, index, new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize));
+ mGroup.addView(view, index, onCreateLayoutParams());
+ return view;
+ }
+
+ @VisibleForTesting
+ protected StatusBarIconView onCreateStatusBarIconView(String slot, boolean blocked) {
+ return new StatusBarIconView(mContext, slot, null, blocked);
+ }
+
+ protected LinearLayout.LayoutParams onCreateLayoutParams() {
+ return new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
}
protected void destroy() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index 5ab99e9e5bce..a456786d712f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -109,13 +109,13 @@ public class CallbackHandler extends Handler implements EmergencyListener, Signa
@Override
public void setWifiIndicators(final boolean enabled, final IconState statusIcon,
final IconState qsIcon, final boolean activityIn, final boolean activityOut,
- final String description) {
+ final String description, boolean isTransient) {
post(new Runnable() {
@Override
public void run() {
for (SignalCallback callback : mSignalCallbacks) {
callback.setWifiIndicators(enabled, statusIcon, qsIcon, activityIn, activityOut,
- description);
+ description, isTransient);
}
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 882902ee3713..b5d22b1da288 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -49,6 +49,7 @@ import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK
public class KeyButtonView extends ImageView implements ButtonInterface {
+ private final boolean mPlaySounds;
private int mContentDescriptionRes;
private long mDownTime;
private int mCode;
@@ -90,6 +91,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
mCode = a.getInteger(R.styleable.KeyButtonView_keyCode, 0);
mSupportsLongpress = a.getBoolean(R.styleable.KeyButtonView_keyRepeat, true);
+ mPlaySounds = a.getBoolean(R.styleable.KeyButtonView_playSound, true);
TypedValue value = new TypedValue();
if (a.getValue(R.styleable.KeyButtonView_android_contentDescription, value)) {
@@ -241,8 +243,9 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
}
public void playSoundEffect(int soundConstant) {
+ if (!mPlaySounds) return;
mAudioManager.playSoundEffect(soundConstant, ActivityManager.getCurrentUser());
- };
+ }
public void sendEvent(int action, int flags) {
sendEvent(action, flags, SystemClock.uptimeMillis());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 565756017415..c02ce0ea6335 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -19,12 +19,10 @@ package com.android.systemui.statusbar.policy;
import android.content.Context;
import android.content.Intent;
import android.telephony.SubscriptionInfo;
-import android.view.View;
import com.android.settingslib.net.DataUsageController;
import com.android.settingslib.wifi.AccessPoint;
import com.android.systemui.DemoMode;
-import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import java.util.List;
@@ -48,7 +46,7 @@ public interface NetworkController extends CallbackController<SignalCallback>, D
public interface SignalCallback {
default void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
- boolean activityIn, boolean activityOut, String description) {}
+ boolean activityIn, boolean activityOut, String description, boolean isTransient) {}
default void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 12b70983dba3..2104cb1421aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -150,7 +150,7 @@ public class WifiSignalController extends
Utils.getWifiBadgeResource(mCurrentState.badgeEnum), contentDescription);
callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut,
- wifiDesc);
+ wifiDesc, mCurrentState.isTransient);
}
@Override
@@ -170,6 +170,9 @@ public class WifiSignalController extends
mWifiTracker.handleBroadcast(intent);
updateScoreCacheIfNecessary(previousNetworkKey);
+ mCurrentState.isTransient = mWifiTracker.state == WifiManager.WIFI_STATE_ENABLING
+ || mWifiTracker.state == WifiManager.WIFI_AP_STATE_DISABLING
+ || mWifiTracker.connecting;
mCurrentState.enabled = mWifiTracker.enabled;
mCurrentState.connected = mWifiTracker.connected;
mCurrentState.ssid = mWifiTracker.ssid;
@@ -252,6 +255,7 @@ public class WifiSignalController extends
static class WifiState extends SignalController.State {
String ssid;
int badgeEnum;
+ boolean isTransient;
@Override
public void copyFrom(State s) {
@@ -259,19 +263,23 @@ public class WifiSignalController extends
WifiState state = (WifiState) s;
ssid = state.ssid;
badgeEnum = state.badgeEnum;
+ isTransient = state.isTransient;
}
@Override
protected void toString(StringBuilder builder) {
super.toString(builder);
builder.append(',').append("ssid=").append(ssid);
+ builder.append(',').append("badgeEnum=").append(badgeEnum);
+ builder.append(',').append("isTransient=").append(isTransient);
}
@Override
public boolean equals(Object o) {
return super.equals(o)
&& Objects.equals(((WifiState) o).ssid, ssid)
- && (((WifiState) o).badgeEnum == badgeEnum);
+ && (((WifiState) o).badgeEnum == badgeEnum)
+ && (((WifiState) o).isTransient == isTransient);
}
}
}
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index ddd8d7b3002f..8eedf3145e61 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -41,6 +41,7 @@ LOCAL_STATIC_ANDROID_LIBRARIES := \
android-support-v7-recyclerview \
android-support-v7-preference \
android-support-v7-appcompat \
+ android-support-v7-mediarouter \
android-support-v14-preference \
android-support-v17-leanback
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
new file mode 100644
index 000000000000..ecae39a61c29
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
+import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.utils.leaks.LeakCheckedTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class StatusBarIconControllerTest extends LeakCheckedTest {
+
+ @Before
+ public void setup() {
+ injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
+ mDependency.injectMockDependency(DarkIconDispatcher.class);
+ }
+
+ @Test
+ public void testSetCalledOnAdd_IconManager() {
+ LinearLayout layout = new LinearLayout(mContext);
+ TestIconManager manager = new TestIconManager(layout);
+ StatusBarIcon icon = mock(StatusBarIcon.class);
+
+ manager.onIconAdded(0, "test_slot", false, icon);
+ verify(manager.mMock).set(eq(icon));
+ }
+
+ @Test
+ public void testSetCalledOnAdd_DarkIconManager() {
+ LinearLayout layout = new LinearLayout(mContext);
+ TestDarkIconManager manager = new TestDarkIconManager(layout);
+ StatusBarIcon icon = mock(StatusBarIcon.class);
+
+ manager.onIconAdded(0, "test_slot", false, icon);
+ verify(manager.mMock).set(eq(icon));
+ }
+
+ private static class TestDarkIconManager extends DarkIconManager {
+
+ private final StatusBarIconView mMock;
+
+ public TestDarkIconManager(LinearLayout group) {
+ super(group);
+ mMock = mock(StatusBarIconView.class);
+ }
+
+ @Override
+ protected StatusBarIconView onCreateStatusBarIconView(String slot, boolean blocked) {
+ return mMock;
+ }
+ }
+
+ private static class TestIconManager extends IconManager {
+
+ private final StatusBarIconView mMock;
+
+ public TestIconManager(ViewGroup group) {
+ super(group);
+ mMock = mock(StatusBarIconView.class);
+ }
+
+ @Override
+ protected StatusBarIconView onCreateStatusBarIconView(String slot, boolean blocked) {
+ return mMock;
+ }
+ }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
index b544d9df1292..3ed1681644f2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
@@ -79,7 +79,7 @@ public class CallbackHandlerTest {
boolean in = true;
boolean out = true;
String description = "Test";
- mHandler.setWifiIndicators(enabled, status, qs, in, out, description);
+ mHandler.setWifiIndicators(enabled, status, qs, in, out, description, true);
waitForCallbacks();
ArgumentCaptor<Boolean> enableArg = ArgumentCaptor.forClass(Boolean.class);
@@ -88,15 +88,17 @@ public class CallbackHandlerTest {
ArgumentCaptor<Boolean> inArg = ArgumentCaptor.forClass(Boolean.class);
ArgumentCaptor<Boolean> outArg = ArgumentCaptor.forClass(Boolean.class);
ArgumentCaptor<String> descArg = ArgumentCaptor.forClass(String.class);
+ ArgumentCaptor<Boolean> isTransient = ArgumentCaptor.forClass(Boolean.class);
Mockito.verify(mSignalCallback).setWifiIndicators(enableArg.capture(),
statusArg.capture(), qsArg.capture(), inArg.capture(), outArg.capture(),
- descArg.capture());
+ descArg.capture(), isTransient.capture());
assertEquals(enabled, (boolean) enableArg.getValue());
assertEquals(status, statusArg.getValue());
assertEquals(qs, qsArg.getValue());
assertEquals(in, (boolean) inArg.getValue());
assertEquals(out, (boolean) outArg.getValue());
assertEquals(description, descArg.getValue());
+ assertTrue(isTransient.getValue());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index efa232bb33af..483a8371b85b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -122,7 +122,7 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest {
ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators(
anyBoolean(), iconArg.capture(), any(), anyBoolean(), anyBoolean(),
- any());
+ any(), anyBoolean());
IconState iconState = iconArg.getValue();
assertEquals("Badged Wifi Resource is set",
@@ -269,7 +269,7 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest {
ArgumentCaptor<Boolean> outArg = ArgumentCaptor.forClass(Boolean.class);
Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators(
- anyBoolean(), any(), any(), inArg.capture(), outArg.capture(), any());
+ anyBoolean(), any(), any(), inArg.capture(), outArg.capture(), any(), anyBoolean());
assertEquals("WiFi data in, in quick settings", in, (boolean) inArg.getValue());
assertEquals("WiFi data out, in quick settings", out, (boolean) outArg.getValue());
}
@@ -282,7 +282,7 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest {
Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators(
enabledArg.capture(), any(), iconArg.capture(), anyBoolean(),
- anyBoolean(), descArg.capture());
+ anyBoolean(), descArg.capture(), anyBoolean());
IconState iconState = iconArg.getValue();
assertEquals("WiFi enabled, in quick settings", enabled, (boolean) enabledArg.getValue());
assertEquals("WiFi connected, in quick settings", connected, iconState.visible);
@@ -295,7 +295,7 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest {
Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators(
anyBoolean(), iconArg.capture(), any(), anyBoolean(), anyBoolean(),
- any());
+ any(), anyBoolean());
IconState iconState = iconArg.getValue();
assertEquals("WiFi visible, in status bar", visible, iconState.visible);
assertEquals("WiFi signal, in status bar", icon, iconState.icon);
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index da441f5eaff3..78bc01dc5389 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3188,21 +3188,21 @@ message MetricsEvent {
// ACTION: Logged when a provisioning session has completed
PROVISIONING_SESSION_COMPLETED = 735;
- // ACTION: An app requested the permission READ_PHONE_NUMBER
+ // ACTION: An app requested the permission READ_PHONE_NUMBERS
// PACKAGE: The package name of the app requesting the permission
- ACTION_PERMISSION_REQUEST_READ_PHONE_NUMBER = 736;
+ ACTION_PERMISSION_REQUEST_READ_PHONE_NUMBERS = 736;
- // ACTION: An app was granted the permission READ_PHONE_NUMBER
+ // ACTION: An app was granted the permission READ_PHONE_NUMBERS
// PACKAGE: The package name of the app that was granted the permission
- ACTION_PERMISSION_GRANT_READ_PHONE_NUMBER = 737;
+ ACTION_PERMISSION_GRANT_READ_PHONE_NUMBERS = 737;
- // ACTION: An app requested the permission READ_PHONE_NUMBER and the request was denied
+ // ACTION: An app requested the permission READ_PHONE_NUMBERS and the request was denied
// PACKAGE: The package name of the app requesting the permission
- ACTION_PERMISSION_DENIED_READ_PHONE_NUMBER = 738;
+ ACTION_PERMISSION_DENIED_READ_PHONE_NUMBERS = 738;
- // ACTION: The permission READ_PHONE_NUMBER was revoked for an app
+ // ACTION: The permission READ_PHONE_NUMBERS was revoked for an app
// PACKAGE: The package name of the app the permission was revoked for
- ACTION_PERMISSION_REVOKE_READ_PHONE_NUMBER = 739;
+ ACTION_PERMISSION_REVOKE_READ_PHONE_NUMBERS = 739;
// ACTION: QS Brightness Slider (with auto brightness disabled, and VR enabled)
// SUBTYPE: slider value
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 6b917b5298de..f6d91f44b2cf 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -153,6 +153,18 @@ message SystemMessage {
// Package: android
NOTE_SSL_CERT_INFO = 33;
+ // Warn the user they are approaching their data limit.
+ // Package: android
+ NOTE_NET_WARNING = 34;
+
+ // Warn the user they have reached their data limit.
+ // Package: android
+ NOTE_NET_LIMIT = 35;
+
+ // Warn the user they have exceeded their data limit.
+ // Package: android
+ NOTE_NET_LIMIT_SNOOZED = 36;
+
// ADD_NEW_IDS_ABOVE_THIS_LINE
// Legacy IDs with arbitrary values appear below
// Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 087c24866146..1968d2e925aa 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -585,17 +585,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
result = mEnabledServicesForFeedbackTempList;
result.clear();
List<Service> services = userState.mBoundServices;
- while (feedbackType != 0) {
- final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackType));
- feedbackType &= ~feedbackTypeBit;
- final int serviceCount = services.size();
- for (int i = 0; i < serviceCount; i++) {
- Service service = services.get(i);
- // Don't report the UIAutomation (fake service)
- if (!sFakeAccessibilityServiceComponentName.equals(service.mComponentName)
- && (service.mFeedbackType & feedbackTypeBit) != 0) {
- result.add(service.mAccessibilityServiceInfo);
- }
+ for (int serviceCount = services.size(), i = 0; i < serviceCount; ++i) {
+ Service service = services.get(i);
+ // Don't report the UIAutomation (fake service)
+ if (!sFakeAccessibilityServiceComponentName.equals(service.mComponentName)
+ && (service.mFeedbackType & feedbackType) != 0) {
+ result.add(service.mAccessibilityServiceInfo);
}
}
}
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index 3aba723b7e5f..20def0c5a4f8 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -156,7 +156,7 @@ final class ViewState {
}
// Then checks if the session has a response waiting authentication; if so, uses it instead.
final FillResponse currentResponse = mSession.getCurrentResponse();
- if (currentResponse.getAuthentication() != null) {
+ if (currentResponse != null && currentResponse.getAuthentication() != null) {
mListener.onFillReady(currentResponse, this.id, mCurrentValue);
}
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0e752ffdb5a5..25ac008fa586 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -29,13 +29,6 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
-import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
-import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
-import static android.net.NetworkPolicyManager.RULE_NONE;
-import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
-import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
-import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
-import static android.net.NetworkPolicyManager.uidRulesToString;
import android.annotation.Nullable;
import android.app.BroadcastOptions;
@@ -104,7 +97,6 @@ import android.security.Credentials;
import android.security.KeyStore;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
-import android.util.ArraySet;
import android.util.LocalLog;
import android.util.LocalLog.ReadOnlyLocalLog;
import android.util.Log;
@@ -130,6 +122,7 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils;
import com.android.internal.util.WakeupMessage;
import com.android.internal.util.XmlUtils;
+import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.DataConnectionStats;
import com.android.server.connectivity.KeepaliveTracker;
@@ -147,6 +140,7 @@ import com.android.server.connectivity.Tethering;
import com.android.server.connectivity.Vpn;
import com.android.server.net.BaseNetworkObserver;
import com.android.server.net.LockdownVpnTracker;
+import com.android.server.net.NetworkPolicyManagerInternal;
import com.google.android.collect.Lists;
@@ -221,18 +215,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
private boolean mLockdownEnabled;
private LockdownVpnTracker mLockdownTracker;
- /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */
- private Object mRulesLock = new Object();
- /** Currently active network rules by UID. */
- @GuardedBy("mRulesLock")
- private SparseIntArray mUidRules = new SparseIntArray();
- /** Set of ifaces that are costly. */
- @GuardedBy("mRulesLock")
- private ArraySet<String> mMeteredIfaces = new ArraySet<>();
- /** Flag indicating if background data is restricted. */
- @GuardedBy("mRulesLock")
- private boolean mRestrictBackground;
-
final private Context mContext;
private int mNetworkPreference;
// 0 is full bad, 100 is full good
@@ -246,6 +228,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private INetworkManagementService mNetd;
private INetworkStatsService mStatsService;
private INetworkPolicyManager mPolicyManager;
+ private NetworkPolicyManagerInternal mPolicyManagerInternal;
private String mCurrentTcpBufferSizes;
@@ -715,12 +698,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
mNetd = checkNotNull(netManager, "missing INetworkManagementService");
mStatsService = checkNotNull(statsService, "missing INetworkStatsService");
mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
+ mPolicyManagerInternal = checkNotNull(
+ LocalServices.getService(NetworkPolicyManagerInternal.class),
+ "missing NetworkPolicyManagerInternal");
+
mKeyStore = KeyStore.getInstance();
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
try {
- mPolicyManager.setConnectivityListener(mPolicyListener);
- mRestrictBackground = mPolicyManager.getRestrictBackground();
+ mPolicyManager.registerListener(mPolicyListener);
} catch (RemoteException e) {
// ouch, no rules updates means some processes may never get network
loge("unable to register INetworkPolicyListener" + e);
@@ -991,51 +977,22 @@ public class ConnectivityService extends IConnectivityManager.Stub
private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid,
boolean ignoreBlocked) {
// Networks aren't blocked when ignoring blocked status
- if (ignoreBlocked) return false;
+ if (ignoreBlocked) {
+ return false;
+ }
// Networks are never blocked for system services
- if (isSystem(uid)) return false;
-
- final boolean networkMetered;
- final int uidRules;
-
+ // TODO: consider moving this check to NetworkPolicyManagerInternal.isUidNetworkingBlocked.
+ if (isSystem(uid)) {
+ return false;
+ }
synchronized (mVpns) {
final Vpn vpn = mVpns.get(UserHandle.getUserId(uid));
if (vpn != null && vpn.isBlockingUid(uid)) {
return true;
}
}
-
final String iface = (lp == null ? "" : lp.getInterfaceName());
- synchronized (mRulesLock) {
- networkMetered = mMeteredIfaces.contains(iface);
- uidRules = mUidRules.get(uid, RULE_NONE);
- }
-
- boolean allowed = true;
- // Check Data Saver Mode first...
- if (networkMetered) {
- if ((uidRules & RULE_REJECT_METERED) != 0) {
- if (LOGD_RULES) Log.d(TAG, "uid " + uid + " is blacklisted");
- // Explicitly blacklisted.
- allowed = false;
- } else {
- allowed = !mRestrictBackground
- || (uidRules & RULE_ALLOW_METERED) != 0
- || (uidRules & RULE_TEMPORARY_ALLOW_METERED) != 0;
- if (LOGD_RULES) Log.d(TAG, "allowed status for uid " + uid + " when"
- + " mRestrictBackground=" + mRestrictBackground
- + ", whitelisted=" + ((uidRules & RULE_ALLOW_METERED) != 0)
- + ", tempWhitelist= + ((uidRules & RULE_TEMPORARY_ALLOW_METERED) != 0)"
- + ": " + allowed);
- }
- }
- // ...then power restrictions.
- if (allowed) {
- allowed = (uidRules & RULE_REJECT_ALL) == 0;
- if (LOGD_RULES) Log.d(TAG, "allowed status for uid " + uid + " when"
- + " rule is " + uidRulesToString(uidRules) + ": " + allowed);
- }
- return !allowed;
+ return mPolicyManagerInternal.isUidNetworkingBlocked(uid, iface);
}
private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) {
@@ -1481,67 +1438,24 @@ public class ConnectivityService extends IConnectivityManager.Stub
return true;
}
- private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
+ private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
@Override
public void onUidRulesChanged(int uid, int uidRules) {
- // caller is NPMS, since we only register with them
- if (LOGD_RULES) {
- log("onUidRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
- }
-
- synchronized (mRulesLock) {
- // skip update when we've already applied rules
- final int oldRules = mUidRules.get(uid, RULE_NONE);
- if (oldRules == uidRules) return;
-
- if (uidRules == RULE_NONE) {
- mUidRules.delete(uid);
- } else {
- mUidRules.put(uid, uidRules);
- }
- }
-
// TODO: notify UID when it has requested targeted updates
}
-
@Override
public void onMeteredIfacesChanged(String[] meteredIfaces) {
- // caller is NPMS, since we only register with them
- if (LOGD_RULES) {
- log("onMeteredIfacesChanged(ifaces=" + Arrays.toString(meteredIfaces) + ")");
- }
-
- synchronized (mRulesLock) {
- mMeteredIfaces.clear();
- for (String iface : meteredIfaces) {
- mMeteredIfaces.add(iface);
- }
- }
}
-
@Override
public void onRestrictBackgroundChanged(boolean restrictBackground) {
- // caller is NPMS, since we only register with them
- if (LOGD_RULES) {
- log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")");
- }
-
- synchronized (mRulesLock) {
- mRestrictBackground = restrictBackground;
- }
-
+ // TODO: relocate this specific callback in Tethering.
if (restrictBackground) {
log("onRestrictBackgroundChanged(true): disabling tethering");
mTethering.untetherAll();
}
}
-
@Override
public void onUidPoliciesChanged(int uid, int uidPolicies) {
- // caller is NPMS, since we only register with them
- if (LOGD_RULES) {
- log("onUidRulesChanged(uid=" + uid + ", uidPolicies=" + uidPolicies + ")");
- }
}
};
@@ -1976,33 +1890,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
pw.decreaseIndent();
pw.println();
- pw.println("Metered Interfaces:");
- pw.increaseIndent();
- for (String value : mMeteredIfaces) {
- pw.println(value);
- }
- pw.decreaseIndent();
- pw.println();
-
- pw.print("Restrict background: ");
- pw.println(mRestrictBackground);
- pw.println();
-
- pw.println("Status for known UIDs:");
- pw.increaseIndent();
- final int size = mUidRules.size();
- for (int i = 0; i < size; i++) {
- final int uid = mUidRules.keyAt(i);
- pw.print("UID=");
- pw.print(uid);
- final int uidRules = mUidRules.get(uid, RULE_NONE);
- pw.print(" rules=");
- pw.print(uidRulesToString(uidRules));
- pw.println();
- }
- pw.println();
- pw.decreaseIndent();
-
pw.println("Network Requests:");
pw.increaseIndent();
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
@@ -3437,6 +3324,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
Slog.e(TAG, s);
}
+ private static void loge(String s, Throwable t) {
+ Slog.e(TAG, s, t);
+ }
+
private static <T> T checkNotNull(T value, String message) {
if (value == null) {
throw new NullPointerException(message);
@@ -4197,20 +4088,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
final int uid = Binder.getCallingUid();
if (isSystem(uid)) {
+ // Exemption for system uid.
return;
}
- // if UID is restricted, don't allow them to bring up metered APNs
- if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED) == false) {
- final int uidRules;
- synchronized(mRulesLock) {
- uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
- }
- if (mRestrictBackground && (uidRules & RULE_ALLOW_METERED) == 0
- && (uidRules & RULE_TEMPORARY_ALLOW_METERED) == 0) {
- // we could silently fail or we can filter the available nets to only give
- // them those they have access to. Chose the more useful option.
- networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
- }
+ if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) {
+ // Policy already enforced.
+ return;
+ }
+ if (mPolicyManagerInternal.isUidRestrictedOnMeteredNetworks(uid)) {
+ // If UID is restricted, don't allow them to bring up metered APNs.
+ networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
}
}
diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
index 421d5a6ab964..c105b1244e74 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.app.ActivityThread;
import android.content.Context;
import android.os.IBinder;
import android.os.ServiceManager;
@@ -104,6 +105,16 @@ public abstract class SystemService {
}
/**
+ * Get the system UI context. This context is to be used for displaying UI. It is themable,
+ * which means resources can be overridden at runtime. Do not use to retrieve properties that
+ * configure the behavior of the device that is not UX related.
+ */
+ public final Context getUiContext() {
+ // This has already been set up by the time any SystemServices are created.
+ return ActivityThread.currentActivityThread().getSystemUiContext();
+ }
+
+ /**
* Returns true if the system is running in safe mode.
* TODO: we should define in which phase this becomes valid
*/
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 8b0665c6d312..4cbfb275fd32 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -398,7 +398,7 @@ public final class ActiveServices {
r.delayedStop = false;
r.fgRequired = fgRequired;
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
- service, neededGrants));
+ service, neededGrants, callingUid));
final ServiceMap smap = getServiceMapLocked(r.userId);
boolean addToStarting = false;
@@ -1140,7 +1140,7 @@ public final class ActiveServices {
// Service is already running, so we can immediately
// publish the connection.
try {
- c.conn.connected(s.name, b.intent.binder);
+ c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortName
+ " to connection " + c.conn.asBinder()
@@ -1194,7 +1194,7 @@ public final class ActiveServices {
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
try {
- c.conn.connected(r.name, service);
+ c.conn.connected(r.name, service, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + r.name +
" to connection " + c.conn.asBinder() +
@@ -1355,10 +1355,10 @@ public final class ActiveServices {
if (r == null) {
try {
// TODO: come back and remove this assumption to triage all services
- ResolveInfo rInfo = AppGlobals.getPackageManager().resolveService(service,
+ ResolveInfo rInfo = mAm.getPackageManagerInternalLocked().resolveService(service,
resolvedType, ActivityManagerService.STOCK_PM_FLAGS
| PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
- userId);
+ userId, callingUid);
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
@@ -1927,7 +1927,7 @@ public final class ActiveServices {
// be called.
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
- null, null));
+ null, null, 0));
}
sendServiceArgsLocked(r, execInFg, true);
@@ -1979,7 +1979,8 @@ public final class ActiveServices {
mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
si.getUriPermissionsLocked());
}
- // TODO b/34123112; Insert ephemeral grant here
+ mAm.grantEphemeralAccessLocked(r.userId, si.intent,
+ r.appInfo.uid, UserHandle.getAppId(si.callingId));
bumpServiceExecutingLocked(r, execInFg, "start");
if (!oomAdjusted) {
oomAdjusted = true;
@@ -2080,7 +2081,7 @@ public final class ActiveServices {
// being brought down. Mark it as dead.
cr.serviceDead = true;
try {
- cr.conn.connected(r.name, null);
+ cr.conn.connected(r.name, null, true);
} catch (Exception e) {
Slog.w(TAG, "Failure disconnecting service " + r.name +
" to connection " + c.get(i).conn.asBinder() +
@@ -2591,7 +2592,7 @@ public final class ActiveServices {
stopServiceLocked(sr);
} else {
sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
- sr.makeNextStartId(), baseIntent, null));
+ sr.makeNextStartId(), baseIntent, null, 0));
if (sr.app != null && sr.app.thread != null) {
// We always run in the foreground, since this is called as
// part of the "remove task" UI operation.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c27fa1b849a7..4c747a1c5433 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1350,7 +1350,13 @@ public class ActivityManagerService extends IActivityManager.Stub
@GuardedBy("this") boolean mLaunchWarningShown = false;
@GuardedBy("this") boolean mCheckedForSetup = false;
- Context mContext;
+ final Context mContext;
+
+ /**
+ * This Context is themable and meant for UI display (AlertDialogs, etc.). The theme can
+ * change at runtime. Use mContext for non-UI purposes.
+ */
+ final Context mUiContext;
/**
* The time at which we will allow normal application switches again,
@@ -1852,7 +1858,7 @@ public class ActivityManagerService extends IActivityManager.Stub
} break;
case SHOW_FACTORY_ERROR_UI_MSG: {
Dialog d = new FactoryErrorDialog(
- mContext, msg.getData().getCharSequence("msg"));
+ mUiContext, msg.getData().getCharSequence("msg"));
d.show();
ensureBootCompleted();
} break;
@@ -1863,7 +1869,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (!app.waitedForDebugger) {
Dialog d = new AppWaitingForDebuggerDialog(
ActivityManagerService.this,
- mContext, app);
+ mUiContext, app);
app.waitDialog = d;
app.waitedForDebugger = true;
d.show();
@@ -1878,24 +1884,24 @@ public class ActivityManagerService extends IActivityManager.Stub
} break;
case SHOW_UID_ERROR_UI_MSG: {
if (mShowDialogs) {
- AlertDialog d = new BaseErrorDialog(mContext);
+ AlertDialog d = new BaseErrorDialog(mUiContext);
d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
d.setCancelable(false);
- d.setTitle(mContext.getText(R.string.android_system_label));
- d.setMessage(mContext.getText(R.string.system_error_wipe_data));
- d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok),
+ d.setTitle(mUiContext.getText(R.string.android_system_label));
+ d.setMessage(mUiContext.getText(R.string.system_error_wipe_data));
+ d.setButton(DialogInterface.BUTTON_POSITIVE, mUiContext.getText(R.string.ok),
obtainMessage(DISMISS_DIALOG_UI_MSG, d));
d.show();
}
} break;
case SHOW_FINGERPRINT_ERROR_UI_MSG: {
if (mShowDialogs) {
- AlertDialog d = new BaseErrorDialog(mContext);
+ AlertDialog d = new BaseErrorDialog(mUiContext);
d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
d.setCancelable(false);
- d.setTitle(mContext.getText(R.string.android_system_label));
- d.setMessage(mContext.getText(R.string.system_error_manufacturer));
- d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok),
+ d.setTitle(mUiContext.getText(R.string.android_system_label));
+ d.setMessage(mUiContext.getText(R.string.system_error_manufacturer));
+ d.setButton(DialogInterface.BUTTON_POSITIVE, mUiContext.getText(R.string.ok),
obtainMessage(DISMISS_DIALOG_UI_MSG, d));
d.show();
}
@@ -1919,7 +1925,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (mode == ActivityManager.COMPAT_MODE_DISABLED
|| mode == ActivityManager.COMPAT_MODE_ENABLED) {
mCompatModeDialog = new CompatModeDialog(
- ActivityManagerService.this, mContext,
+ ActivityManagerService.this, mUiContext,
ar.info.applicationInfo);
mCompatModeDialog.show();
}
@@ -1939,7 +1945,7 @@ public class ActivityManagerService extends IActivityManager.Stub
ar.packageName)) {
// TODO(multi-display): Show dialog on appropriate display.
mUnsupportedDisplaySizeDialog = new UnsupportedDisplaySizeDialog(
- ActivityManagerService.this, mContext, ar.info.applicationInfo);
+ ActivityManagerService.this, mUiContext, ar.info.applicationInfo);
mUnsupportedDisplaySizeDialog.show();
}
}
@@ -2731,6 +2737,7 @@ public class ActivityManagerService extends IActivityManager.Stub
public ActivityManagerService(Injector injector) {
mInjector = injector;
mContext = mInjector.getContext();
+ mUiContext = null;
GL_ES_VERSION = 0;
mActivityStarter = null;
mAppErrors = null;
@@ -2762,8 +2769,10 @@ public class ActivityManagerService extends IActivityManager.Stub
LockGuard.installLock(this, LockGuard.INDEX_ACTIVITY);
mInjector = new Injector();
mContext = systemContext;
+
mFactoryTest = FactoryTest.getMode();
mSystemThread = ActivityThread.currentActivityThread();
+ mUiContext = mSystemThread.getSystemUiContext();
Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
@@ -2806,7 +2815,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mServices = new ActiveServices(this);
mProviderMap = new ProviderMap(this);
- mAppErrors = new AppErrors(mContext, this);
+ mAppErrors = new AppErrors(mUiContext, this);
// TODO: Move creation of battery stats service outside of activity manager service.
File dataDir = Environment.getDataDirectory();
@@ -2849,7 +2858,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mTempConfig.setToDefaults();
mTempConfig.setLocales(LocaleList.getDefault());
mConfigurationSeq = mTempConfig.seq = 1;
- mStackSupervisor = new ActivityStackSupervisor(this);
+ mStackSupervisor = createStackSupervisor();
mStackSupervisor.onConfigurationChanged(mTempConfig);
mKeyguardController = mStackSupervisor.mKeyguardController;
mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
@@ -2897,6 +2906,10 @@ public class ActivityManagerService extends IActivityManager.Stub
Watchdog.getInstance().addThread(mHandler);
}
+ protected ActivityStackSupervisor createStackSupervisor() {
+ return new ActivityStackSupervisor(this, mHandler.getLooper());
+ }
+
public void setSystemServiceManager(SystemServiceManager mgr) {
mSystemServiceManager = mgr;
}
@@ -3151,7 +3164,8 @@ public class ActivityManagerService extends IActivityManager.Stub
* {@link ActivityStack#setResumedActivityLocked} when an activity is resumed.
*/
void setResumedActivityUncheckLocked(ActivityRecord r, String reason) {
- if (r.task.isApplicationTask()) {
+ final TaskRecord task = r.getTask();
+ if (task.isApplicationTask()) {
if (mCurAppTimeTracker != r.appTimeTracker) {
// We are switching app tracking. Complete the current one.
if (mCurAppTimeTracker != null) {
@@ -3174,17 +3188,18 @@ public class ActivityManagerService extends IActivityManager.Stub
// TODO: VI Maybe r.task.voiceInteractor || r.voiceInteractor != null
// TODO: Probably not, because we don't want to resume voice on switching
// back to this activity
- if (r.task.voiceInteractor != null) {
- startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
+ if (task.voiceInteractor != null) {
+ startRunningVoiceLocked(task.voiceSession, r.info.applicationInfo.uid);
} else {
finishRunningVoiceLocked();
if (mLastResumedActivity != null) {
final IVoiceInteractionSession session;
- if (mLastResumedActivity.task != null
- && mLastResumedActivity.task.voiceSession != null) {
- session = mLastResumedActivity.task.voiceSession;
+ final TaskRecord lastResumedActivityTask = mLastResumedActivity.getTask();
+ if (lastResumedActivityTask != null
+ && lastResumedActivityTask.voiceSession != null) {
+ session = lastResumedActivityTask.voiceSession;
} else {
session = mLastResumedActivity.voiceSession;
}
@@ -3317,7 +3332,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final void showAskCompatModeDialogLocked(ActivityRecord r) {
Message msg = Message.obtain();
msg.what = SHOW_COMPAT_MODE_DIALOG_UI_MSG;
- msg.obj = r.task.askedCompatMode ? null : r;
+ msg.obj = r.getTask().askedCompatMode ? null : r;
mUiHandler.sendMessage(msg);
}
@@ -4723,7 +4738,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (ActivityRecord.forTokenLocked(callingActivity) != activity) {
throw new SecurityException("Only focused activity can call startVoiceInteraction");
}
- if (mRunningVoice != null || activity.task.voiceSession != null
+ if (mRunningVoice != null || activity.getTask().voiceSession != null
|| activity.voiceSession != null) {
Slog.w(TAG, "Already in a voice interaction, cannot start new voice interaction");
return;
@@ -5033,7 +5048,7 @@ public class ActivityManagerService extends IActivityManager.Stub
return true;
}
// Keep track of the root activity of the task before we finish it
- TaskRecord tr = r.task;
+ TaskRecord tr = r.getTask();
ActivityRecord rootR = tr.getRootActivity();
if (rootR == null) {
Slog.w(TAG, "Finishing task with all activities already finished");
@@ -5170,7 +5185,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// Do not allow task to finish if last task in lockTask mode. Launchable priv-apps
// can finish.
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
if (task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV &&
mStackSupervisor.isLastLockedTask(task) && task.getRootActivity() == r) {
mStackSupervisor.showLockTaskToast();
@@ -7834,7 +7849,7 @@ public class ActivityManagerService extends IActivityManager.Stub
return false;
}
// An activity is consider to be in multi-window mode if its task isn't fullscreen.
- return !r.task.mFullscreen;
+ return !r.getTask().mFullscreen;
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -9927,8 +9942,9 @@ public class ActivityManagerService extends IActivityManager.Stub
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r != null) {
r.setTaskDescription(td);
- r.task.updateTaskDescription();
- mTaskChangeNotificationController.notifyTaskDescriptionChanged(r.task.taskId, td);
+ final TaskRecord task = r.getTask();
+ task.updateTaskDescription();
+ mTaskChangeNotificationController.notifyTaskDescriptionChanged(task.taskId, td);
}
}
}
@@ -10378,8 +10394,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
if (DEBUG_STACK) Slog.d(TAG_STACK, "exitFreeformMode: " + r);
- r.task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT,
- ANIMATE, !DEFER_RESUME, "exitFreeformMode");
+ r.getTask().reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP,
+ REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME, "exitFreeformMode");
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -10760,7 +10776,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (r == null) {
return;
}
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
if (task != null) {
startLockTaskModeLocked(task);
}
@@ -10859,7 +10875,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (r == null) {
return;
}
- mStackSupervisor.showLockTaskEscapeMessageLocked(r.task);
+ mStackSupervisor.showLockTaskEscapeMessageLocked(r.getTask());
}
}
@@ -11516,6 +11532,9 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
checkTime(startTime, "getContentProviderImpl: done!");
+
+ grantEphemeralAccessLocked(userId, null /*intent*/,
+ cpi.applicationInfo.uid, UserHandle.getAppId(Binder.getCallingUid()));
}
// Wait for the provider to be published...
@@ -12291,13 +12310,17 @@ public class ActivityManagerService extends IActivityManager.Stub
mRecentTasks.notifyTaskPersisterLocked(task, flush);
}
- /** Notifies all listeners when the pinned stack animation starts. */
+ /**
+ * Notifies all listeners when the pinned stack animation starts.
+ */
@Override
public void notifyPinnedStackAnimationStarted() {
mTaskChangeNotificationController.notifyPinnedStackAnimationStarted();
}
- /** Notifies all listeners when the pinned stack animation ends. */
+ /**
+ * Notifies all listeners when the pinned stack animation ends.
+ */
@Override
public void notifyPinnedStackAnimationEnded() {
mTaskChangeNotificationController.notifyPinnedStackAnimationEnded();
@@ -13114,9 +13137,10 @@ public class ActivityManagerService extends IActivityManager.Stub
if (r == null) {
return false;
}
- int index = r.task.mActivities.lastIndexOf(r);
+ final TaskRecord task = r.getTask();
+ int index = task.mActivities.lastIndexOf(r);
if (index > 0) {
- ActivityRecord under = r.task.mActivities.get(index - 1);
+ ActivityRecord under = task.mActivities.get(index - 1);
under.returningOptions = ActivityOptions.fromBundle(options);
}
final boolean translucentChanged = r.changeWindowTranslucency(false);
@@ -13403,7 +13427,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (r == null) {
throw new IllegalArgumentException();
}
- return r.task.getTopActivity() == r;
+ return r.getTask().getTopActivity() == r;
}
}
@@ -15921,8 +15945,9 @@ public class ActivityManagerService extends IActivityManager.Stub
}
needSep = true;
synchronized (this) {
- if (lastTask != r.task) {
- lastTask = r.task;
+ final TaskRecord task = r.getTask();
+ if (lastTask != task) {
+ lastTask = task;
pw.print("TASK "); pw.print(lastTask.affinity);
pw.print(" id="); pw.print(lastTask.taskId);
pw.print(" userId="); pw.println(lastTask.userId);
@@ -17636,7 +17661,6 @@ public class ActivityManagerService extends IActivityManager.Stub
*/
private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
- Slog.d(TAG, "cleanUpApplicationRecord -- " + app.pid);
if (index >= 0) {
removeLruProcessLocked(app);
ProcessList.remove(app.pid);
@@ -19784,6 +19808,10 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ /**
+ * NOTE: For the pinned stack, this method is only called after the bounds animation has
+ * animated the stack to the fullscreen.
+ */
@Override
public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTasksToFullscreenStack()");
@@ -20551,8 +20579,9 @@ public class ActivityManagerService extends IActivityManager.Stub
app.cached = false;
app.empty = false;
foregroundActivities = true;
- if (r.task != null && minLayer > 0) {
- final int layer = r.task.mLayerRank;
+ final TaskRecord task = r.getTask();
+ if (task != null && minLayer > 0) {
+ final int layer = task.mLayerRank;
if (layer >= 0 && minLayer > layer) {
minLayer = layer;
}
@@ -23873,7 +23902,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final boolean updateFrameworkRes = packagesToUpdate.contains("android");
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
final ProcessRecord app = mLruProcesses.get(i);
- if (app.thread == null || app.pid == Process.myPid()) {
+ if (app.thread == null) {
continue;
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 47e11b117d38..3a2941467cb6 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -229,7 +229,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
private int theme; // resource identifier of activity's theme.
private int realTheme; // actual theme resource we will use, never 0.
private int windowFlags; // custom window flags for preview window.
- TaskRecord task; // the task this is in.
+ private TaskRecord task; // the task this is in.
private long createTime = System.currentTimeMillis();
long displayStartTime; // when we started launching this activity
long fullyDrawnStartTime; // when we started launching this activity
@@ -284,6 +284,10 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
boolean immersive; // immersive mode (don't interrupt if possible)
boolean forceNewConfig; // force re-create with new config next time
+ private boolean mInMultiWindowMode; // whether or not this activity is currently in multi-window
+ // mode (default false)
+ private boolean mInPictureInPictureMode; // whether or not this activity is currently in
+ // picture-in-picture mode (default false)
boolean supportsPictureInPictureWhilePausing; // This flag is set by the system to indicate
// that the activity can enter picture in picture while pausing (ie. only when another
// task is brought to front or started)
@@ -615,25 +619,51 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
}
}
- void scheduleMultiWindowModeChanged() {
+ void updateMultiWindowMode() {
if (task == null || task.getStack() == null || app == null || app.thread == null) {
return;
}
+
+ // An activity is considered to be in multi-window mode if its task isn't fullscreen.
+ final boolean inMultiWindowMode = !task.mFullscreen;
+ if (inMultiWindowMode != mInMultiWindowMode) {
+ mInMultiWindowMode = inMultiWindowMode;
+ scheduleMultiWindowModeChanged(getConfiguration());
+ }
+ }
+
+ private void scheduleMultiWindowModeChanged(Configuration overrideConfig) {
try {
- // An activity is considered to be in multi-window mode if its task isn't fullscreen.
- app.thread.scheduleMultiWindowModeChanged(appToken, !task.mFullscreen);
+ app.thread.scheduleMultiWindowModeChanged(appToken, mInMultiWindowMode,
+ overrideConfig);
} catch (Exception e) {
// If process died, I don't care.
}
}
- void schedulePictureInPictureModeChanged() {
+ void updatePictureInPictureMode(Rect targetStackBounds) {
if (task == null || task.getStack() == null || app == null || app.thread == null) {
return;
}
+
+ final boolean inPictureInPictureMode = (task.getStackId() == PINNED_STACK_ID) &&
+ (targetStackBounds != null);
+ if (inPictureInPictureMode != mInPictureInPictureMode) {
+ // Picture-in-picture mode changes also trigger a multi-window mode change as well, so
+ // update that here in order
+ mInPictureInPictureMode = inPictureInPictureMode;
+ mInMultiWindowMode = inPictureInPictureMode;
+ final Configuration newConfig = task.computeNewOverrideConfigurationForBounds(
+ targetStackBounds, null);
+ schedulePictureInPictureModeChanged(newConfig);
+ scheduleMultiWindowModeChanged(newConfig);
+ }
+ }
+
+ private void schedulePictureInPictureModeChanged(Configuration overrideConfig) {
try {
- app.thread.schedulePictureInPictureModeChanged(
- appToken, task.getStackId() == PINNED_STACK_ID);
+ app.thread.schedulePictureInPictureModeChanged(appToken, mInPictureInPictureMode,
+ overrideConfig);
} catch (Exception e) {
// If process died, no one cares.
}
@@ -656,9 +686,48 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
@Override
protected ConfigurationContainer getParent() {
+ return getTask();
+ }
+
+ TaskRecord getTask() {
return task;
}
+ /**
+ * Sets reference to the {@link TaskRecord} the {@link ActivityRecord} will treat as its parent.
+ * Note that this does not actually add the {@link ActivityRecord} as a {@link TaskRecord}
+ * children. However, this method will clean up references to this {@link ActivityRecord} in
+ * {@link ActivityStack}.
+ * @param task The new parent {@link TaskRecord}.
+ */
+ void setTask(TaskRecord task) {
+ setTask(task, false /*reparenting*/);
+ }
+
+ /**
+ * This method should only be called by {@link TaskRecord#removeActivity(ActivityRecord)}.
+ */
+ void setTask(TaskRecord task, boolean reparenting) {
+ // Do nothing if the {@link TaskRecord} is the same as the current {@link getTask}.
+ if (task != null && task == getTask()) {
+ return;
+ }
+
+ final ActivityStack stack = getStack();
+
+ // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this
+ // {@link ActivityRecord} from its current {@link ActivityStack}.
+ if (!reparenting && stack != null && (task == null || stack != task.getStack())) {
+ stack.onActivityRemovedFromStack(this);
+ }
+
+ this.task = task;
+
+ if (!reparenting) {
+ onParentChanged();
+ }
+ }
+
static class Token extends IApplicationToken.Stub {
private final WeakReference<ActivityRecord> weakActivity;
@@ -895,8 +964,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
// Must reparent first in window manager
mWindowContainerController.reparent(newTask.getWindowContainerController(), position);
- // Remove the activity from the old task and add it to the new task
- prevTask.removeActivity(this);
+ // Remove the activity from the old task and add it to the new task.
+ prevTask.removeActivity(this, true /*reparenting*/);
newTask.addActivityAtIndex(position, this);
}
@@ -2122,23 +2191,31 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
return true;
}
- /** Computes the override configuration for this activity */
+ /**
+ * Computes the bounds to fit the Activity within the bounds of the {@link Configuration}.
+ */
// TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
private void computeBounds(Rect outBounds) {
outBounds.setEmpty();
final float maxAspectRatio = info.maxAspectRatio;
final ActivityStack stack = getStack();
- if ((task != null && !task.mFullscreen) || maxAspectRatio == 0 || stack == null) {
+ if (task == null || stack == null || !task.mFullscreen || maxAspectRatio == 0) {
// We don't set override configuration if that activity task isn't fullscreen. I.e. the
// activity is in multi-window mode. Or, there isn't a max aspect ratio specified for
- // the activity.
+ // the activity. This is indicated by an empty {@link outBounds}.
return;
}
- stack.getDisplaySize(mTmpPoint);
- int maxActivityWidth = mTmpPoint.x;
- int maxActivityHeight = mTmpPoint.y;
- if (mTmpPoint.x < mTmpPoint.y) {
+ // We must base this on the parent configuration, because we set our override
+ // configuration's appBounds based on the result of this method. If we used our own
+ // configuration, it would be influenced by past invocations.
+ final Configuration configuration = getParent().getConfiguration();
+ final int containingAppWidth = configuration.appBounds.width();
+ final int containingAppHeight = configuration.appBounds.height();
+ int maxActivityWidth = containingAppWidth;
+ int maxActivityHeight = containingAppHeight;
+
+ if (containingAppWidth < containingAppHeight) {
// Width is the shorter side, so we use that to figure-out what the max. height should
// be given the aspect ratio.
maxActivityHeight = (int) ((maxActivityWidth * maxAspectRatio) + 0.5f);
@@ -2148,8 +2225,14 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
maxActivityWidth = (int) ((maxActivityHeight * maxAspectRatio) + 0.5f);
}
- if (mTmpPoint.x <= maxActivityWidth && mTmpPoint.y <= maxActivityHeight) {
+ if (containingAppWidth <= maxActivityWidth && containingAppHeight <= maxActivityHeight) {
// The display matches or is less than the activity aspect ratio, so nothing else to do.
+ // Return the existing bounds. If this method is running for the first time,
+ // {@link mBounds} will be empty (representing no override). If the method has run
+ // before, then effect of {@link mBounds} will already have been applied to the
+ // value returned from {@link getConfiguration}. Refer to
+ // {@link TaskRecord#computeOverrideConfiguration}.
+ outBounds.set(mBounds);
return;
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 498de63d11d8..f13b11e65a88 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -116,6 +116,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.Watchdog;
@@ -342,7 +343,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
private final Rect mTmpRect2 = new Rect();
/** Run all ActivityStacks through this */
- private final ActivityStackSupervisor mStackSupervisor;
+ protected final ActivityStackSupervisor mStackSupervisor;
private final LaunchingTaskPositioner mTaskPositioner;
@@ -725,7 +726,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (r == null) {
return null;
}
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
final ActivityStack stack = r.getStack();
if (stack != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
if (stack != this) Slog.w(TAG,
@@ -934,7 +935,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
+ taskIntent.getComponent().flattenToShortString()
- + "/aff=" + r.task.rootAffinity + " to new cls="
+ + "/aff=" + r.getTask().rootAffinity + " to new cls="
+ intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
// TODO Refactor to remove duplications. Check if logic can be simplified.
if (taskIntent != null && taskIntent.getComponent() != null &&
@@ -1049,8 +1050,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
void addRecentActivityLocked(ActivityRecord r) {
if (r != null) {
- mRecentTasks.addLocked(r.task);
- r.task.touchActiveTime();
+ final TaskRecord task = r.getTask();
+ mRecentTasks.addLocked(task);
+ task.touchActiveTime();
}
}
@@ -1226,11 +1228,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
|| (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
prev.state = ActivityState.PAUSING;
- prev.task.touchActiveTime();
+ prev.getTask().touchActiveTime();
clearLaunchTime(prev);
final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
if (mService.mHasRecents
- && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) {
+ && (next == null || next.noDisplay || next.getTask() != prev.getTask()
+ || uiSleeping)) {
prev.mUpdateTaskThumbnailWhenHidden = true;
}
stopFullyDrawnTraceIfNeeded();
@@ -1457,7 +1460,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Find the first visible activity above the passed activity and if it is translucent return it
// otherwise return null;
ActivityRecord findNextTranslucentActivity(ActivityRecord r) {
- TaskRecord task = r.task;
+ TaskRecord task = r.getTask();
if (task == null) {
return null;
}
@@ -1604,7 +1607,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Otherwise, the docked stack is always visible, except in the case where the top
// running activity task in the focus stack doesn't support any form of resizing but we
// show it for the home task even though it's not resizable.
- final TaskRecord task = r != null ? r.task : null;
+ final TaskRecord task = r != null ? r.getTask() : null;
return task == null || task.supportsSplitScreen() || task.isHomeTask() ? STACK_VISIBLE
: STACK_INVISIBLE;
}
@@ -2157,8 +2160,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
mResumedActivity = r;
r.state = ActivityState.RESUMED;
mService.setResumedActivityUncheckLocked(r, reason);
- r.task.touchActiveTime();
- mRecentTasks.addLocked(r.task);
+ final TaskRecord task = r.getTask();
+ task.touchActiveTime();
+ mRecentTasks.addLocked(task);
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
@@ -2207,8 +2211,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return false;
}
- final TaskRecord nextTask = next.task;
- final TaskRecord prevTask = prev != null ? prev.task : null;
+ final TaskRecord nextTask = next.getTask();
+ final TaskRecord prevTask = prev != null ? prev.getTask() : null;
if (prevTask != null && prevTask.getStack() == this &&
prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -2373,7 +2377,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
- mWindowManager.prepareAppTransition(prev.task == next.task
+ mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
? TRANSIT_ACTIVITY_CLOSE
: TRANSIT_TASK_CLOSE, false);
}
@@ -2385,7 +2389,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
- mWindowManager.prepareAppTransition(prev.task == next.task
+ mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
? TRANSIT_ACTIVITY_OPEN
: next.mLaunchTaskBehind
? TRANSIT_TASK_OPEN_BEHIND
@@ -2522,7 +2526,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
next.notifyAppResumed(next.stopped, allowSavedSurface);
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
- System.identityHashCode(next), next.task.taskId, next.shortComponentName);
+ System.identityHashCode(next), next.getTask().taskId,
+ next.shortComponentName);
next.sleeping = false;
mService.showUnsupportedZoomDialogIfNeededLocked(next);
@@ -2696,9 +2701,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return;
}
- // If the task was launched from the assistant stack, set the return type to assistant
final ActivityStack lastStack = mStackSupervisor.getLastStack();
- if (lastStack != null && lastStack.isAssistantStack()) {
+
+ // If there is no last task, do not set task to return to
+ if (lastStack == null) {
+ return;
+ }
+
+ // If the task was launched from the assistant stack, set the return type to assistant
+ if (lastStack.isAssistantStack()) {
task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
return;
}
@@ -2721,7 +2732,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
boolean newTask, boolean keepCurTransition, ActivityOptions options) {
- TaskRecord rTask = r.task;
+ TaskRecord rTask = r.getTask();
final int taskId = rTask.taskId;
// mLaunchTaskBehind tasks get placed at the back of the task stack.
if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
@@ -2740,7 +2751,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// All activities in task are finishing.
continue;
}
- if (task == r.task) {
+ if (task == rTask) {
// Here it is! Now, if this is not yet visible to the
// user, then just add it without starting; it will
// get started when the user navigates back to it.
@@ -2762,13 +2773,14 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// If we are not placing the new activity frontmost, we do not want to deliver the
// onUserLeaving callback to the actual frontmost activity
- if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
+ final TaskRecord activityTask = r.getTask();
+ if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
mStackSupervisor.mUserLeaving = false;
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"startActivity() behind front, mUserLeaving=false");
}
- task = r.task;
+ task = activityTask;
// Slot the activity into the history stack and proceed
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
@@ -2795,7 +2807,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
} else {
// If a new task is being launched, then mark the existing top activity as
// supporting picture-in-picture while pausing
- if (focusedTopActivity != null) {
+ if (focusedTopActivity != null &&
+ focusedTopActivity.getStack().getStackId() != PINNED_STACK_ID) {
focusedTopActivity.supportsPictureInPictureWhilePausing = true;
}
transit = TRANSIT_TASK_OPEN;
@@ -2829,11 +2842,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// "has the same starting icon" as the next one. This allows the
// window manager to keep the previous window it had previously
// created, if it still had one.
- ActivityRecord prev = r.task.topRunningActivityWithStartingWindowLocked();
+ TaskRecord prevTask = r.getTask();
+ ActivityRecord prev = prevTask.topRunningActivityWithStartingWindowLocked();
if (prev != null) {
// We don't want to reuse the previous starting preview if:
// (1) The current activity is in a different task.
- if (prev.task != r.task) {
+ if (prev.getTask() != prevTask) {
prev = null;
}
// (2) The current activity is already displayed.
@@ -2852,7 +2866,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
private boolean isTaskSwitch(ActivityRecord r,
ActivityRecord topFocusedActivity) {
- return topFocusedActivity != null && r.task != topFocusedActivity.task;
+ return topFocusedActivity != null && r.getTask() != topFocusedActivity.getTask();
}
/**
@@ -2919,20 +2933,20 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
!mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
mTaskHistory.get(0).mActivities.get(0) : null;
if (bottom != null && target.taskAffinity != null
- && target.taskAffinity.equals(bottom.task.affinity)) {
+ && target.taskAffinity.equals(bottom.getTask().affinity)) {
// If the activity currently at the bottom has the
// same task affinity as the one we are moving,
// then merge it into the same task.
- targetTask = bottom.task;
+ targetTask = bottom.getTask();
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
- + " out to bottom task " + bottom.task);
+ + " out to bottom task " + targetTask);
} else {
targetTask = createTaskRecord(
mStackSupervisor.getNextTaskIdForUserLocked(target.userId),
target.info, null, null, null, false, target.mActivityType);
targetTask.affinityIntent = target.intent;
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
- + " out to new task " + target.task);
+ + " out to new task " + targetTask);
}
boolean noOptions = canMoveOptions;
@@ -2954,7 +2968,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
"Removing activity " + p + " from task=" + task + " adding to task="
+ targetTask + " Callers=" + Debug.getCallers(4));
if (DEBUG_TASKS) Slog.v(TAG_TASKS,
- "Pushing next activity " + p + " out to target's task " + target.task);
+ "Pushing next activity " + p + " out to target's task " + target);
p.reparent(targetTask, 0 /* position - bottom */, "resetTargetTaskIfNeeded");
}
@@ -3125,13 +3139,13 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
boolean forceReset =
(newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
if (ACTIVITY_INACTIVE_RESET_TIME > 0
- && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
+ && taskTop.getTask().getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
if ((newActivity.info.flags & ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
forceReset = true;
}
}
- final TaskRecord task = taskTop.task;
+ final TaskRecord task = taskTop.getTask();
/** False until we evaluate the TaskRecord associated with taskTop. Switches to true
* for remaining tasks. Used for later tasks to reparent to task. */
@@ -3214,7 +3228,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// stack as long as there is a running activity.
return;
} else {
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
final boolean isAssistantOrOverAssistant = task.getStack().isAssistantStack() ||
task.isOverAssistantStack();
if (r.frontOfTask && task == topTask() &&
@@ -3373,10 +3387,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
Slog.w(TAG, " Force finishing activity "
+ r.intent.getComponent().flattenToShortString());
- int taskNdx = mTaskHistory.indexOf(r.task);
- int activityNdx = r.task.mActivities.indexOf(r);
+ finishedTask = r.getTask();
+ int taskNdx = mTaskHistory.indexOf(finishedTask);
+ final TaskRecord task = finishedTask;
+ int activityNdx = task.mActivities.indexOf(r);
finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false);
- finishedTask = r.task;
+ finishedTask = task;
// Also terminate any activities below it that aren't yet
// stopped, to avoid a situation where one will get
// re-start our crashing activity once it gets resumed again.
@@ -3446,7 +3462,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
final boolean finishActivityAffinityLocked(ActivityRecord r) {
- ArrayList<ActivityRecord> activities = r.task.mActivities;
+ ArrayList<ActivityRecord> activities = r.getTask().mActivities;
for (int index = activities.indexOf(r); index >= 0; --index) {
ActivityRecord cur = activities.get(index);
if (!Objects.equals(cur.taskAffinity, r.taskAffinity)) {
@@ -3511,7 +3527,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
mWindowManager.deferSurfaceLayout();
try {
r.makeFinishingLocked();
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
r.userId, System.identityHashCode(r),
task.taskId, r.shortComponentName, reason);
@@ -3700,23 +3716,24 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) {
// Basic case: for simple app-centric recents, we need to recreate
// the task if the affinity has changed.
- if (srec == null || srec.task.affinity == null ||
- !srec.task.affinity.equals(destAffinity)) {
+ if (srec == null || srec.getTask().affinity == null ||
+ !srec.getTask().affinity.equals(destAffinity)) {
return true;
}
// Document-centric case: an app may be split in to multiple documents;
// they need to re-create their task if this current activity is the root
// of a document, unless simply finishing it will return them to the the
// correct app behind.
- if (srec.frontOfTask && srec.task != null && srec.task.getBaseIntent() != null
- && srec.task.getBaseIntent().isDocument()) {
+ final TaskRecord task = srec.getTask();
+ if (srec.frontOfTask && task != null && task.getBaseIntent() != null
+ && task.getBaseIntent().isDocument()) {
// Okay, this activity is at the root of its task. What to do, what to do...
- if (srec.task.getTaskToReturnTo() != ActivityRecord.APPLICATION_ACTIVITY_TYPE) {
+ if (task.getTaskToReturnTo() != ActivityRecord.APPLICATION_ACTIVITY_TYPE) {
// Finishing won't return to an application, so we need to recreate.
return true;
}
// We now need to get the task below it to determine what to do.
- int taskIdx = mTaskHistory.indexOf(srec.task);
+ int taskIdx = mTaskHistory.indexOf(task);
if (taskIdx <= 0) {
Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec);
return false;
@@ -3726,7 +3743,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return true;
}
TaskRecord prevTask = mTaskHistory.get(taskIdx);
- if (!srec.task.affinity.equals(prevTask.affinity)) {
+ if (!task.affinity.equals(prevTask.affinity)) {
// These are different apps, so need to recreate.
return true;
}
@@ -3736,7 +3753,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
Intent resultData) {
- final TaskRecord task = srec.task;
+ final TaskRecord task = srec.getTask();
final ArrayList<ActivityRecord> activities = task.mActivities;
final int start = activities.indexOf(srec);
if (!mTaskHistory.contains(task) || (start < 0)) {
@@ -3815,6 +3832,22 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
Binder.restoreCallingIdentity(origId);
return foundParentInTask;
}
+
+ /**
+ * Remove any state associated with the {@link ActivityRecord}. This should be called whenever
+ * an activity moves away from the stack.
+ */
+ void onActivityRemovedFromStack(ActivityRecord r) {
+ if (mResumedActivity == r) {
+ mResumedActivity = null;
+ }
+ if (mPausingActivity == r) {
+ mPausingActivity = null;
+ }
+
+ removeTimeoutsForActivityLocked(r);
+ }
+
/**
* Perform the common clean-up of an activity record. This is called both
* as part of destroyActivityLocked() (when destroying the client-side
@@ -3825,12 +3858,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
* Note: Call before #removeActivityFromHistoryLocked.
*/
private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) {
- if (mResumedActivity == r) {
- mResumedActivity = null;
- }
- if (mPausingActivity == r) {
- mPausingActivity = null;
- }
+ onActivityRemovedFromStack(r);
r.deferRelaunchUntilPaused = false;
r.frozenBeforeDestroy = false;
@@ -3897,7 +3925,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r);
r.app = null;
r.removeWindowContainer();
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
final boolean lastActivity = task != null ? task.removeActivity(r) : false;
// If we are removing the last activity in the task, not including task overlay activities,
// then fall through into the block below to remove the entire task itself
@@ -4043,7 +4071,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
+ ", app=" + (r.app != null ? r.app.processName : "(null)"));
EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
r.userId, System.identityHashCode(r),
- r.task.taskId, r.shortComponentName, reason);
+ r.getTask().taskId, r.shortComponentName, reason);
boolean removedFromHistory = false;
@@ -4275,7 +4303,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
r.userId, System.identityHashCode(r),
- r.task.taskId, r.shortComponentName,
+ r.getTask().taskId, r.shortComponentName,
"proc died without state saved");
if (r.state == ActivityState.RESUMED) {
mService.updateUsageStats(r, false);
@@ -4403,7 +4431,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
// If a new task is moved to the front, then mark the existing top activity as supporting
// picture-in-picture while paused
- if (topActivity != null) {
+ if (topActivity != null && topActivity.getStack().getStackId() != PINNED_STACK_ID) {
topActivity.supportsPictureInPictureWhilePausing = true;
}
@@ -4529,7 +4557,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
}
- final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
+ final TaskRecord task = mResumedActivity != null ? mResumedActivity.getTask() : null;
if (prevIsHome || (task == tr && canGoHome) || (numTasks <= 1 && isOnHomeDisplay())) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
@@ -4570,7 +4598,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return;
}
- final TaskRecord startTask = start.task;
+ final TaskRecord startTask = start.getTask();
boolean behindFullscreen = false;
boolean updatedConfig = false;
@@ -4578,7 +4606,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final TaskRecord task = mTaskHistory.get(taskIndex);
final ArrayList<ActivityRecord> activities = task.mActivities;
int activityIndex =
- (start.task == task) ? activities.indexOf(start) : activities.size() - 1;
+ (start.getTask() == task) ? activities.indexOf(start) : activities.size() - 1;
for (; activityIndex >= 0; --activityIndex) {
final ActivityRecord r = activities.get(activityIndex);
updatedConfig |= r.ensureActivityConfigurationLocked(0 /* globalChanges */,
@@ -4739,7 +4767,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
|| filterByClasses.contains(r.realActivity.getClassName())))
|| (packageName == null && r.userId == userId);
if ((userId == UserHandle.USER_ALL || r.userId == userId)
- && (sameComponent || r.task == lastTask)
+ && (sameComponent || r.getTask() == lastTask)
&& (r.app == null || evenPersistent || !r.app.persistent)) {
if (!doit) {
if (r.finishing) {
@@ -4765,7 +4793,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
r.app = null;
}
- lastTask = r.task;
+ lastTask = r.getTask();
if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
true)) {
// r has been deleted from mActivities, accommodate.
@@ -4816,7 +4844,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (DEBUG_ALL) Slog.v(
TAG, r.intent.getComponent().flattenToShortString()
- + ": task=" + r.task);
+ + ": task=" + r.getTask());
}
RunningTaskInfo ci = new RunningTaskInfo();
@@ -4832,8 +4860,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
topTask = false;
}
- if (top.task != null) {
- ci.description = top.task.lastDescription;
+ if (top.getTask() != null) {
+ ci.description = top.getTask().lastDescription;
}
ci.numActivities = numActivities;
ci.numRunning = numRunning;
@@ -4982,9 +5010,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
task.removeWindowContainer();
}
- final ActivityRecord r = mResumedActivity;
- if (r != null && r.task == task) {
- mResumedActivity = null;
+ for (ActivityRecord record : task.mActivities) {
+ onActivityRemovedFromStack(record);
}
final int taskNdx = mTaskHistory.indexOf(task);
@@ -5074,7 +5101,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
void addTask(final TaskRecord task, final boolean toTop, String reason) {
- addTask(task, toTop ? MAX_VALUE : 0, reason);
+ addTask(task, toTop ? MAX_VALUE : 0, true /* schedulePictureInPictureModeChange */, reason);
if (toTop) {
// TODO: figure-out a way to remove this call.
mWindowContainerController.positionChildAtTop(task.getWindowContainerController(),
@@ -5084,7 +5111,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// TODO: This shouldn't allow automatic reparenting. Remove the call to preAddTask and deal
// with the fall-out...
- void addTask(final TaskRecord task, int position, String reason) {
+ void addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange,
+ String reason) {
// TODO: Is this remove really needed? Need to look into the call path for the other addTask
mTaskHistory.remove(task);
position = getAdjustedPositionForTask(task, position, null /* starting */);
@@ -5100,7 +5128,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
updateTaskMovement(task, toTop);
- postAddTask(task, prevStack);
+ postAddTask(task, prevStack, schedulePictureInPictureModeChange);
}
void positionChildAt(TaskRecord task, int index) {
@@ -5116,7 +5144,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity;
insertTaskAtPosition(task, index);
task.setStack(this);
- postAddTask(task, null /* prevStack */);
+ postAddTask(task, null /* prevStack */, true /* schedulePictureInPictureModeChange */);
if (wasResumed) {
if (mResumedActivity != null) {
@@ -5142,9 +5170,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return prevStack;
}
- private void postAddTask(TaskRecord task, ActivityStack prevStack) {
- if (prevStack != null) {
- mStackSupervisor.scheduleReportPictureInPictureModeChangedIfNeeded(task, prevStack);
+ /**
+ * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
+ * change. Callers may set this to false if they are explicitly scheduling PiP mode
+ * changes themselves, like during the PiP animation
+ */
+ private void postAddTask(TaskRecord task, ActivityStack prevStack,
+ boolean schedulePictureInPictureModeChange) {
+ if (schedulePictureInPictureModeChange && prevStack != null) {
+ mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, prevStack);
} else if (task.voiceSession != null) {
try {
task.voiceSession.taskStarted(task.intent, task.taskId);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index c65ca798a7b0..b72cd73e85cf 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -164,6 +164,7 @@ import android.view.Display;
import android.view.InputEvent;
import android.view.Surface;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -173,6 +174,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.wm.StackWindowController;
import com.android.server.wm.WindowManagerService;
import java.io.FileDescriptor;
@@ -371,6 +373,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
* application */
final ArrayList<ActivityRecord> mPipModeChangedActivities = new ArrayList<>();
+ /** The target stack bounds for the picture-in-picture mode changed that we need to report to
+ * the application */
+ Rect mPipModeChangedTargetStackBounds;
+
/** Used on user changes */
final ArrayList<UserState> mStartingUsers = new ArrayList<>();
@@ -549,9 +555,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
}
- public ActivityStackSupervisor(ActivityManagerService service) {
+ public ActivityStackSupervisor(ActivityManagerService service, Looper looper) {
mService = service;
- mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper());
+ mHandler = new ActivityStackSupervisorHandler(looper);
mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext);
mKeyguardController = new KeyguardController(service, this);
}
@@ -718,7 +724,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
if (prev != null) {
- prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
+ prev.getTask().setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
}
mHomeStack.moveHomeStackTaskToTop();
@@ -1310,7 +1316,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
mService.updateLruProcessLocked(app, true, null);
mService.updateOomAdjLocked();
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
@@ -2334,6 +2340,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ActivityStack fullscreenStack = getStack(FULLSCREEN_WORKSPACE_STACK_ID);
final boolean isFullscreenStackVisible = fullscreenStack != null &&
fullscreenStack.getStackVisibilityLocked(null) == STACK_VISIBLE;
+ // If we are moving from the pinned stack, then the animation takes care of updating
+ // the picture-in-picture mode.
+ final boolean schedulePictureInPictureModeChange = (fromStackId != PINNED_STACK_ID);
final ArrayList<TaskRecord> tasks = stack.getAllTasks();
final int size = tasks.size();
if (onTop) {
@@ -2352,6 +2361,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// Defer resume until all the tasks have been moved to the fullscreen stack
task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP,
REPARENT_MOVE_STACK_TO_FRONT, isTopTask /* animate */, DEFER_RESUME,
+ schedulePictureInPictureModeChange,
"moveTasksToFullscreenStack - onTop");
}
} else {
@@ -2361,8 +2371,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
? Math.max(fullscreenStack.getAllTasks().size() - 1, 0) : 0;
// Defer resume until all the tasks have been moved to the fullscreen stack
task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, position,
- REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE,
- DEFER_RESUME, "moveTasksToFullscreenStack - NOT_onTop");
+ REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE, DEFER_RESUME,
+ schedulePictureInPictureModeChange,
+ "moveTasksToFullscreenStack - NOT_onTop");
}
}
@@ -2506,9 +2517,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
fullscreenStack.getStackVisibilityLocked(null) == STACK_VISIBLE;
for (int i = 0; i < tasks.size(); i++) {
// Insert the task either at the top of the fullscreen stack if it is hidden,
- // or just under the top task if it is currently visible
- final int insertPosition = isFullscreenStackVisible
- ? Math.max(0, fullscreenStack.getChildCount() - 1)
+ // or to the bottom if it is currently visible
+ final int insertPosition = isFullscreenStackVisible ? 0
: fullscreenStack.getChildCount();
final TaskRecord task = tasks.get(i);
// Defer resume until we remove all the tasks
@@ -2614,7 +2624,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
for (int k = 0; k < proc.activities.size(); k++) {
- TaskRecord otherTask = proc.activities.get(k).task;
+ TaskRecord otherTask = proc.activities.get(k).getTask();
if (tr.taskId != otherTask.taskId && otherTask.inRecents) {
// Don't kill process(es) that has an activity in a different task that is
// also in recents.
@@ -2829,7 +2839,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
final PinnedActivityStack stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
try {
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
if (r == task.getStack().getVisibleBehindActivity()) {
// An activity can't be pinned and visible behind at the same time. Go ahead and
@@ -2856,9 +2866,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// was launched from home so home should be visible behind it.
moveHomeStackToFront(reason);
}
- // Defer resume until below
+ // Defer resume until below, and do not schedule PiP changes until we animate below
task.reparent(PINNED_STACK_ID, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
- DEFER_RESUME, reason);
+ DEFER_RESUME, false /* schedulePictureInPictureModeChange */, reason);
} else {
// There are multiple activities in the task and moving the top activity should
// reveal/leave the other activities in their original task.
@@ -2873,9 +2883,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
r.mActivityType);
r.reparent(newTask, MAX_VALUE, "moveActivityToStack");
- // Defer resume until below
+ // Defer resume until below, and do not schedule PiP changes until we animate below
newTask.reparent(PINNED_STACK_ID, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
- DEFER_RESUME, reason);
+ DEFER_RESUME, false /* schedulePictureInPictureModeChange */, reason);
}
// Reset the state that indicates it can enter PiP while pausing after we've moved it
@@ -2902,7 +2912,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return false;
}
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
final ActivityStack stack = r.getStack();
if (stack == null) {
Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: r="
@@ -3195,7 +3205,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// Called when WindowManager has finished animating the launchingBehind activity to the back.
private void handleLaunchTaskBehindCompleteLocked(ActivityRecord r) {
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
final ActivityStack stack = task.getStack();
r.mLaunchTaskBehind = false;
@@ -3208,7 +3218,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// task has been shown briefly
final ActivityRecord top = stack.topActivity();
if (top != null) {
- top.task.touchActiveTime();
+ top.getTask().touchActiveTime();
}
}
@@ -3307,17 +3317,19 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Not releasing in-use activity: " + r);
continue;
}
- if (r.task != null) {
- if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Collecting release task " + r.task
+
+ final TaskRecord task = r.getTask();
+ if (task != null) {
+ if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Collecting release task " + task
+ " from " + r);
if (firstTask == null) {
- firstTask = r.task;
- } else if (firstTask != r.task) {
+ firstTask = task;
+ } else if (firstTask != task) {
if (tasks == null) {
tasks = new ArraySet<>();
tasks.add(firstTask);
}
- tasks.add(r.task);
+ tasks.add(task);
}
}
}
@@ -3656,8 +3668,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
pw.println(header2);
header2 = null;
}
- if (lastTask != r.task) {
- lastTask = r.task;
+ if (lastTask != r.getTask()) {
+ lastTask = r.getTask();
pw.print(prefix);
pw.print(full ? "* " : " ");
pw.println(lastTask);
@@ -4072,7 +4084,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
}
final ActivityRecord r = topRunningActivityLocked();
- final TaskRecord task = r != null ? r.task : null;
+ final TaskRecord task = r != null ? r.getTask() : null;
if (mLockTaskModeTasks.isEmpty() && task != null
&& task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
// This task must have just been authorized.
@@ -4109,7 +4121,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
mActivityMetricsLogger.logWindowState();
}
- void scheduleReportMultiWindowModeChanged(TaskRecord task) {
+ void scheduleUpdateMultiWindowMode(TaskRecord task) {
for (int i = task.mActivities.size() - 1; i >= 0; i--) {
final ActivityRecord r = task.mActivities.get(i);
if (r.app != null && r.app.thread != null) {
@@ -4122,22 +4134,39 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
}
- void scheduleReportPictureInPictureModeChangedIfNeeded(TaskRecord task, ActivityStack prevStack) {
+ void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, ActivityStack prevStack) {
final ActivityStack stack = task.getStack();
if (prevStack == null || prevStack == stack
|| (prevStack.mStackId != PINNED_STACK_ID && stack.mStackId != PINNED_STACK_ID)) {
return;
}
- for (int i = task.mActivities.size() - 1; i >= 0; i--) {
- final ActivityRecord r = task.mActivities.get(i);
- if (r.app != null && r.app.thread != null) {
- mPipModeChangedActivities.add(r);
+ scheduleUpdatePictureInPictureModeIfNeeded(task, stack.mBounds, false /* immediate */);
+ }
+
+ void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, Rect targetStackBounds,
+ boolean immediate) {
+
+ if (immediate) {
+ mHandler.removeMessages(REPORT_PIP_MODE_CHANGED_MSG);
+ for (int i = task.mActivities.size() - 1; i >= 0; i--) {
+ final ActivityRecord r = task.mActivities.get(i);
+ if (r.app != null && r.app.thread != null) {
+ r.updatePictureInPictureMode(targetStackBounds);
+ }
}
- }
+ } else {
+ for (int i = task.mActivities.size() - 1; i >= 0; i--) {
+ final ActivityRecord r = task.mActivities.get(i);
+ if (r.app != null && r.app.thread != null) {
+ mPipModeChangedActivities.add(r);
+ }
+ }
+ mPipModeChangedTargetStackBounds = targetStackBounds;
- if (!mHandler.hasMessages(REPORT_PIP_MODE_CHANGED_MSG)) {
- mHandler.sendEmptyMessage(REPORT_PIP_MODE_CHANGED_MSG);
+ if (!mHandler.hasMessages(REPORT_PIP_MODE_CHANGED_MSG)) {
+ mHandler.sendEmptyMessage(REPORT_PIP_MODE_CHANGED_MSG);
+ }
}
}
@@ -4165,7 +4194,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
synchronized (mService) {
for (int i = mMultiWindowModeChangedActivities.size() - 1; i >= 0; i--) {
final ActivityRecord r = mMultiWindowModeChangedActivities.remove(i);
- r.scheduleMultiWindowModeChanged();
+ r.updateMultiWindowMode();
}
}
} break;
@@ -4173,7 +4202,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
synchronized (mService) {
for (int i = mPipModeChangedActivities.size() - 1; i >= 0; i--) {
final ActivityRecord r = mPipModeChangedActivities.remove(i);
- r.schedulePictureInPictureModeChanged();
+ r.updatePictureInPictureMode(mPipModeChangedTargetStackBounds);
}
}
} break;
@@ -4365,19 +4394,24 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
synchronized (mService) {
mStackId = stackId;
mActivityDisplay = activityDisplay;
- switch (mStackId) {
- case PINNED_STACK_ID:
- new PinnedActivityStack(this, mRecentTasks, onTop);
- break;
- default:
- new ActivityStack(this, mRecentTasks, onTop);
- break;
- }
mIdString = "ActivtyContainer{" + mStackId + "}";
+
+ createStack(stackId, onTop);
if (DEBUG_STACK) Slog.d(TAG_STACK, "Creating " + this);
}
}
+ protected void createStack(int stackId, boolean onTop) {
+ switch (stackId) {
+ case PINNED_STACK_ID:
+ new PinnedActivityStack(this, mRecentTasks, onTop);
+ break;
+ default:
+ new ActivityStack(this, mRecentTasks, onTop);
+ break;
+ }
+ }
+
/**
* Adds the stack to specified display. Also calls WindowManager to do the same from
* {@link ActivityStack#reparent(ActivityDisplay, boolean)}.
@@ -4901,7 +4935,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
mService.mActivityStarter.postStartActivityProcessing(task.getTopActivity(),
ActivityManager.START_TASK_TO_FRONT,
- sourceRecord != null ? sourceRecord.task.getStackId() : INVALID_STACK_ID,
+ sourceRecord != null ? sourceRecord.getTask().getStackId() : INVALID_STACK_ID,
sourceRecord, task.getStack());
return ActivityManager.START_TASK_TO_FRONT;
}
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index 547161ac4169..cafc4f0ecc96 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -188,10 +188,10 @@ class ActivityStartInterceptor {
}
ActivityRecord homeActivityRecord = mSupervisor.getHomeActivity();
- if (homeActivityRecord != null && homeActivityRecord.task != null) {
+ if (homeActivityRecord != null && homeActivityRecord.getTask() != null) {
// Showing credential confirmation activity in home task to avoid stopping multi-windowed
// mode after showing the full-screen credential confirmation activity.
- mActivityOptions.setLaunchTaskId(homeActivityRecord.task.taskId);
+ mActivityOptions.setLaunchTaskId(homeActivityRecord.getTask().taskId);
}
final UserInfo parent = mUserManager.getProfileParent(mUserId);
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 18e74080490d..b4085697f2da 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -79,7 +79,6 @@ import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
-import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
@@ -87,8 +86,6 @@ import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
-import static java.lang.Integer.MAX_VALUE;
-
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -335,7 +332,7 @@ class ActivityStarter {
}
if (err == ActivityManager.START_SUCCESS && sourceRecord != null
- && sourceRecord.task.voiceSession != null) {
+ && sourceRecord.getTask().voiceSession != null) {
// If this activity is being launched as part of a voice session, we need
// to ensure that it is safe to do so. If the upcoming activity will also
// be part of the voice session, we can only launch it if it has explicitly
@@ -575,7 +572,7 @@ class ActivityStarter {
// visibility instead of using this flag.
final boolean noDisplayActivityOverHome = sourceRecord != null
&& sourceRecord.noDisplay
- && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
+ && sourceRecord.getTask().getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
if (startedActivityStackId == DOCKED_STACK_ID
&& (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
@@ -625,7 +622,7 @@ class ActivityStarter {
FLAG_ACTIVITY_TASK_ON_HOME);
ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
: ActivityOptions.makeBasic());
- options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
+ options.setLaunchTaskId(mSupervisor.getHomeActivity().getTask().taskId);
mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
}
@@ -763,7 +760,7 @@ class ActivityStarter {
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
hist.packageName);
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
- hist.task.taskId);
+ hist.getTask().taskId);
}
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
aInfo.packageName);
@@ -967,8 +964,8 @@ class ActivityStarter {
// If we are not able to proceed, disassociate the activity from the task. Leaving an
// activity in an incomplete state can lead to issues, such as performing operations
// without a window container.
- if (result != START_SUCCESS && mStartActivity.task != null) {
- mStartActivity.task.removeActivity(mStartActivity);
+ if (result != START_SUCCESS && mStartActivity.getTask() != null) {
+ mStartActivity.getTask().removeActivity(mStartActivity);
}
mService.mWindowManager.continueSurfaceLayout();
}
@@ -1002,7 +999,7 @@ class ActivityStarter {
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
// still needs to be a lock task mode violation since the task gets cleared out and
// the device would otherwise leave the locked task.
- if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
+ if (mSupervisor.isLockTaskModeViolation(mReusedActivity.getTask(),
(mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
mSupervisor.showLockTaskToast();
@@ -1010,13 +1007,13 @@ class ActivityStarter {
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
- if (mStartActivity.task == null) {
- mStartActivity.task = mReusedActivity.task;
+ if (mStartActivity.getTask() == null) {
+ mStartActivity.setTask(mReusedActivity.getTask());
}
- if (mReusedActivity.task.intent == null) {
+ if (mReusedActivity.getTask().intent == null) {
// This task was started because of movement of the activity based on affinity...
// Now that we are actually launching it, we can assign the base intent.
- mReusedActivity.task.setIntent(mStartActivity);
+ mReusedActivity.getTask().setIntent(mStartActivity);
}
// This code path leads to delivering a new intent, we want to make sure we schedule it
@@ -1025,7 +1022,7 @@ class ActivityStarter {
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
|| mLaunchSingleInstance || mLaunchSingleTask) {
- final TaskRecord task = mReusedActivity.task;
+ final TaskRecord task = mReusedActivity.getTask();
// In this situation we want to remove all activities from the task up to the one
// being started. In most cases this means we are resetting the task to its initial
@@ -1037,17 +1034,17 @@ class ActivityStarter {
// the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
// task reference is needed in the call below to
// {@link setTargetStackAndMoveToFrontIfNeeded}.
- if (mReusedActivity.task == null) {
- mReusedActivity.task = task;
+ if (mReusedActivity.getTask() == null) {
+ mReusedActivity.setTask(task);
}
if (top != null) {
if (top.frontOfTask) {
// Activity aliases may mean we use different intents for the top activity,
// so make sure the task now has the identity of the new intent.
- top.task.setIntent(mStartActivity);
+ top.getTask().setIntent(mStartActivity);
}
- ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
+ ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
}
@@ -1098,7 +1095,7 @@ class ActivityStarter {
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask);
if (dontStart) {
- ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
+ ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
if (mDoResume) {
@@ -1116,14 +1113,14 @@ class ActivityStarter {
// Don't use mStartActivity.task to show the toast. We're not starting a new activity
// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
mSupervisor.handleNonResizableTaskIfNeeded(
- top.task, preferredLaunchStackId, topStack.mStackId);
+ top.getTask(), preferredLaunchStackId, topStack.mStackId);
return START_DELIVERED_TO_TOP;
}
boolean newTask = false;
final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
- ? mSourceRecord.task : null;
+ ? mSourceRecord.getTask() : null;
// Should this be considered a new task?
int result = START_SUCCESS;
@@ -1150,14 +1147,15 @@ class ActivityStarter {
mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
if (mSourceRecord != null) {
- mStartActivity.task.setTaskToReturnTo(mSourceRecord);
+ mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
}
if (newTask) {
EventLog.writeEvent(
- EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
+ EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
+ mStartActivity.getTask().taskId);
}
ActivityStack.logStartActivity(
- EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
+ EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
mTargetStack.mLastPausedActivity = null;
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
@@ -1165,7 +1163,8 @@ class ActivityStarter {
mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
mOptions);
if (mDoResume) {
- final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
+ final ActivityRecord topTaskActivity =
+ mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
@@ -1197,7 +1196,7 @@ class ActivityStarter {
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(
- mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
+ mStartActivity.getTask(), preferredLaunchStackId, mTargetStack.mStackId);
return START_SUCCESS;
}
@@ -1424,7 +1423,7 @@ class ActivityStarter {
+ "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
mNewTaskInfo = mSourceRecord.info;
- mNewTaskIntent = mSourceRecord.task.intent;
+ mNewTaskIntent = mSourceRecord.getTask().intent;
}
mSourceRecord = null;
mSourceStack = null;
@@ -1516,15 +1515,16 @@ class ActivityStarter {
ActivityRecord curTop = (focusStack == null)
? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
- if (curTop != null
- && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
+ final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
+ if (topTask != null
+ && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
&& !mAvoidMoveToFront) {
mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
- mSourceStack.topActivity().task == mSourceRecord.task)) {
+ mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {
// We really do want to push this one into the user's face, right now.
if (mLaunchTaskBehind && mSourceRecord != null) {
- intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
+ intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
}
mMovedOtherTask = true;
@@ -1539,13 +1539,13 @@ class ActivityStarter {
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
if (!willClearTask) {
final ActivityStack launchStack = getLaunchStack(
- mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
+ mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
+ final TaskRecord intentTask = intentActivity.getTask();
if (launchStack == null || launchStack == mTargetStack) {
// We only want to move to the front, if we aren't going to launch on a
// different stack. If we launch on a different stack, we will put the
// task on top there.
- mTargetStack.moveTaskToFrontLocked(
- intentActivity.task, mNoAnimation, mOptions,
+ mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
mMovedToFront = true;
} else if (launchStack.mStackId == DOCKED_STACK_ID
@@ -1553,7 +1553,7 @@ class ActivityStarter {
if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
// If we want to launch adjacent and mTargetStack is not the computed
// launch stack - move task to top of computed stack.
- intentActivity.task.reparent(launchStack.mStackId, ON_TOP,
+ intentTask.reparent(launchStack.mStackId, ON_TOP,
REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
"launchToSide");
} else {
@@ -1561,8 +1561,8 @@ class ActivityStarter {
// We choose to move task to front instead of launching it adjacent
// when specific stack was requested explicitly and it appeared to be
// adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
- mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
- mOptions, mStartActivity.appTimeTracker,
+ mTargetStack.moveTaskToFrontLocked(intentTask,
+ mNoAnimation, mOptions, mStartActivity.appTimeTracker,
"bringToFrontInsteadOfAdjacentLaunch");
}
mMovedToFront = true;
@@ -1570,7 +1570,7 @@ class ActivityStarter {
// Target and computed stacks are on different displays and we've
// found a matching task - move the existing instance to that display and
// move it to front.
- intentActivity.task.reparent(launchStack.mStackId, ON_TOP,
+ intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
"reparentToDisplay");
mMovedToFront = true;
@@ -1582,7 +1582,7 @@ class ActivityStarter {
intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
true /* taskSwitch */);
}
- updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
+ updateTaskReturnToType(intentActivity.getTask(), mLaunchFlags, focusStack);
}
}
if (!mMovedToFront && mDoResume) {
@@ -1591,7 +1591,7 @@ class ActivityStarter {
mTargetStack.moveToFront("intentActivityFound");
}
- mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
+ mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
mTargetStack.mStackId);
// If the caller has requested that the target task be reset, then do so.
@@ -1635,7 +1635,7 @@ class ActivityStarter {
// launching another activity.
// TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
// already launching one.
- final TaskRecord task = intentActivity.task;
+ final TaskRecord task = intentActivity.getTask();
task.performClearTaskLocked();
mReuseTask = task;
mReuseTask.setIntent(mStartActivity);
@@ -1646,7 +1646,7 @@ class ActivityStarter {
mMovedOtherTask = true;
} else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| mLaunchSingleInstance || mLaunchSingleTask) {
- ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
+ ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
mLaunchFlags);
if (top == null) {
// A special case: we need to start the activity because it is not currently
@@ -1655,11 +1655,11 @@ class ActivityStarter {
mAddingToTask = true;
// We are no longer placing the activity in the task we previously thought we were.
- mStartActivity.task = null;
+ mStartActivity.setTask(null);
// Now pretend like this activity is being started by the top of its task, so it
// is put in the right place.
mSourceRecord = intentActivity;
- final TaskRecord task = mSourceRecord.task;
+ final TaskRecord task = mSourceRecord.getTask();
if (task != null && task.getStack() == null) {
// Target stack got cleared when we all activities were removed above.
// Go ahead and reset it.
@@ -1669,7 +1669,7 @@ class ActivityStarter {
!mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
}
}
- } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
+ } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
// In this case the top activity on the task is the same as the one being launched,
// so we take that as a request to bring the task to the foreground. If the top
// activity in the task is the root activity, deliver this new intent to it if it
@@ -1677,13 +1677,13 @@ class ActivityStarter {
if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
&& intentActivity.realActivity.equals(mStartActivity.realActivity)) {
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
- intentActivity.task);
+ intentActivity.getTask());
if (intentActivity.frontOfTask) {
- intentActivity.task.setIntent(mStartActivity);
+ intentActivity.getTask().setIntent(mStartActivity);
}
intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
- } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
+ } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
// In this case we are launching the root activity of the task, but with a
// different intent. We should start a new instance on top.
mAddingToTask = true;
@@ -1696,13 +1696,13 @@ class ActivityStarter {
// current task.
mAddingToTask = true;
mSourceRecord = intentActivity;
- } else if (!intentActivity.task.rootWasReset) {
+ } else if (!intentActivity.getTask().rootWasReset) {
// In this case we are launching into an existing task that has not yet been started
// from its front door. The current task has been brought to the front. Ideally,
// we'd probably like to place this new task at the bottom of its stack, but that's
// a little hard to do with the current organization of the code so for now we'll
// just drop it.
- intentActivity.task.setIntent(mStartActivity);
+ intentActivity.getTask().setIntent(mStartActivity);
}
}
@@ -1736,11 +1736,11 @@ class ActivityStarter {
mService.resizeStack(
stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
} else {
- mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
+ mStartActivity.getTask().updateOverrideConfiguration(mLaunchBounds);
}
}
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
- + " in new task " + mStartActivity.task);
+ + " in new task " + mStartActivity.getTask());
} else {
addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
}
@@ -1749,7 +1749,7 @@ class ActivityStarter {
mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
}
- if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
+ if (mSupervisor.isLockTaskModeViolation(mStartActivity.getTask())) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
@@ -1758,7 +1758,7 @@ class ActivityStarter {
// If stack id is specified in activity options, usually it means that activity is
// launched not from currently focused stack (e.g. from SysUI or from shell) - in
// that case we check the target stack.
- updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
+ updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
}
if (mDoResume) {
@@ -1768,19 +1768,19 @@ class ActivityStarter {
}
private int setTaskFromSourceRecord() {
- if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
+ if (mSupervisor.isLockTaskModeViolation(mSourceRecord.getTask())) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
- final TaskRecord sourceTask = mSourceRecord.task;
+ final TaskRecord sourceTask = mSourceRecord.getTask();
final ActivityStack sourceStack = mSourceRecord.getStack();
// We only want to allow changing stack if the target task is not the top one,
// otherwise we would move the launching task to the other side, rather than show
// two side by side.
final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
if (moveStackAllowed) {
- mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
+ mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
mOptions);
}
@@ -1805,7 +1805,7 @@ class ActivityStarter {
ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
mKeepCurTransition = true;
if (top != null) {
- ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
+ ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
// For paranoia, make sure we have correctly resumed the top activity.
mTargetStack.mLastPausedActivity = null;
@@ -1821,7 +1821,7 @@ class ActivityStarter {
// stack if so.
final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
if (top != null) {
- final TaskRecord task = top.task;
+ final TaskRecord task = top.getTask();
task.moveActivityToFrontLocked(top);
top.updateOptionsLocked(mOptions);
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
@@ -1838,7 +1838,7 @@ class ActivityStarter {
// the same task as the one that is starting it.
addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
- + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
+ + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
return START_SUCCESS;
}
@@ -1861,7 +1861,7 @@ class ActivityStarter {
|| mLaunchSingleTop || mLaunchSingleTask) {
mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "inTaskToFront");
- ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
+ ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// 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!
@@ -1901,7 +1901,7 @@ class ActivityStarter {
addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
- + " in explicit task " + mStartActivity.task);
+ + " in explicit task " + mStartActivity.getTask());
return START_SUCCESS;
}
@@ -1913,17 +1913,17 @@ class ActivityStarter {
mTargetStack.moveToFront("addingToTopTask");
}
final ActivityRecord prev = mTargetStack.topActivity();
- final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
+ final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
mIntent, null, null, true, mStartActivity.mActivityType);
addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
mTargetStack.positionChildWindowContainerAtTop(task);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
- + " in new guessed " + mStartActivity.task);
+ + " in new guessed " + mStartActivity.getTask());
}
private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
- if (mStartActivity.task == null || mStartActivity.task == parent) {
+ if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
parent.addActivityToTop(mStartActivity);
} else {
mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
@@ -1973,7 +1973,7 @@ class ActivityStarter {
private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
int launchFlags, ActivityOptions aOptions) {
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
if (stack != null) {
return stack;
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 21c131c3616f..ba72dcf23c98 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -98,6 +98,7 @@ class AppErrors {
AppErrors(Context context, ActivityManagerService service) {
+ context.assertRuntimeOverlayThemable();
mService = service;
mContext = context;
}
diff --git a/services/core/java/com/android/server/am/BaseErrorDialog.java b/services/core/java/com/android/server/am/BaseErrorDialog.java
index 5f7f67a8a5e8..347a357aae04 100644
--- a/services/core/java/com/android/server/am/BaseErrorDialog.java
+++ b/services/core/java/com/android/server/am/BaseErrorDialog.java
@@ -34,6 +34,7 @@ class BaseErrorDialog extends AlertDialog {
public BaseErrorDialog(Context context) {
super(context, com.android.internal.R.style.Theme_Dialog_AppError);
+ context.assertRuntimeOverlayThemable();
getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
diff --git a/services/core/java/com/android/server/am/PersistentConnection.java b/services/core/java/com/android/server/am/PersistentConnection.java
new file mode 100644
index 000000000000..c34c097cb696
--- /dev/null
+++ b/services/core/java/com/android/server/am/PersistentConnection.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2017 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 android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.PrintWriter;
+
+/**
+ * Connects to a given service component on a given user.
+ *
+ * - Call {@link #connect()} to create a connection.
+ * - Call {@link #disconnect()} to disconnect. Make sure to disconnect when the user stops.
+ *
+ * Add onConnected/onDisconnected callbacks as needed.
+ */
+public abstract class PersistentConnection<T> {
+ private final Object mLock = new Object();
+
+ private final String mTag;
+ private final Context mContext;
+ private final Handler mHandler;
+ private final int mUserId;
+ private final ComponentName mComponentName;
+
+ @GuardedBy("mLock")
+ private boolean mStarted;
+
+ @GuardedBy("mLock")
+ private boolean mIsConnected;
+
+ @GuardedBy("mLock")
+ private T mService;
+
+ private final ServiceConnection mServiceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ synchronized (mLock) {
+ Slog.i(mTag, "Connected: " + mComponentName.flattenToShortString()
+ + " u" + mUserId);
+
+ mIsConnected = true;
+ mService = asInterface(service);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ synchronized (mLock) {
+ Slog.i(mTag, "Disconnected: " + mComponentName.flattenToShortString()
+ + " u" + mUserId);
+
+ cleanUpConnectionLocked();
+ }
+ }
+ };
+
+ public PersistentConnection(@NonNull String tag, @NonNull Context context,
+ @NonNull Handler handler, int userId, @NonNull ComponentName componentName) {
+ mTag = tag;
+ mContext = context;
+ mHandler = handler;
+ mUserId = userId;
+ mComponentName = componentName;
+ }
+
+ public final ComponentName getComponentName() {
+ return mComponentName;
+ }
+
+ /**
+ * @return whether connected.
+ */
+ public final boolean isConnected() {
+ synchronized (mLock) {
+ return mIsConnected;
+ }
+ }
+
+ /**
+ * @return the service binder interface.
+ */
+ public final T getServiceBinder() {
+ synchronized (mLock) {
+ return mService;
+ }
+ }
+
+ /**
+ * Connects to the service.
+ */
+ public final void connect() {
+ synchronized (mLock) {
+ if (mStarted) {
+ return;
+ }
+ mStarted = true;
+
+ final Intent service = new Intent().setComponent(mComponentName);
+
+ final boolean success = mContext.bindServiceAsUser(service, mServiceConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+ mHandler, UserHandle.of(mUserId));
+
+ if (!success) {
+ Slog.e(mTag, "Binding: " + service.getComponent() + " u" + mUserId
+ + " failed.");
+ }
+ }
+ }
+
+ private void cleanUpConnectionLocked() {
+ mIsConnected = false;
+ mService = null;
+ }
+
+ /**
+ * Disconnect from the service.
+ */
+ public final void disconnect() {
+ synchronized (mLock) {
+ if (!mStarted) {
+ return;
+ }
+ Slog.i(mTag, "Stopping: " + mComponentName.flattenToShortString() + " u" + mUserId);
+ mStarted = false;
+ mContext.unbindService(mServiceConnection);
+
+ cleanUpConnectionLocked();
+ }
+ }
+
+ /** Must be implemented by a subclass to convert an {@link IBinder} to a stub. */
+ protected abstract T asInterface(IBinder binder);
+
+ public void dump(String prefix, PrintWriter pw) {
+ synchronized (mLock) {
+ pw.print(prefix);
+ pw.print(mComponentName.flattenToShortString());
+ pw.print(mStarted ? " [started]" : " [not started]");
+ pw.print(mIsConnected ? " [connected]" : " [not connected]");
+ pw.println();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/PinnedActivityStack.java b/services/core/java/com/android/server/am/PinnedActivityStack.java
index 32d3082357a2..394e902ec27e 100644
--- a/services/core/java/com/android/server/am/PinnedActivityStack.java
+++ b/services/core/java/com/android/server/am/PinnedActivityStack.java
@@ -23,6 +23,7 @@ import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
import com.android.server.wm.PinnedStackWindowController;
import com.android.server.wm.StackWindowController;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -57,4 +58,18 @@ class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> {
boolean isBoundsAnimatingToFullscreen() {
return getWindowContainerController().isBoundsAnimatingToFullscreen();
}
+
+ @Override
+ public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {
+ // It is guaranteed that the activities requiring the update will be in the pinned stack at
+ // this point (either reparented before the animation into PiP, or before reparenting after
+ // the animation out of PiP)
+ synchronized(this) {
+ ArrayList<TaskRecord> tasks = getAllTasks();
+ for (int i = 0; i < tasks.size(); i++ ) {
+ mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(tasks.get(i),
+ targetStackBounds, true /* immediate */);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 40effff77166..0dc678813338 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -350,58 +350,58 @@ final class ProcessList {
String procState;
switch (curProcState) {
case ActivityManager.PROCESS_STATE_PERSISTENT:
- procState = "P ";
+ procState = "PER ";
break;
case ActivityManager.PROCESS_STATE_PERSISTENT_UI:
- procState = "PU";
+ procState = "PERU";
break;
case ActivityManager.PROCESS_STATE_TOP:
- procState = "T ";
+ procState = "TOP";
break;
case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
- procState = "SB";
+ procState = "BFGS";
break;
case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE:
- procState = "SF";
+ procState = "FGS ";
break;
case ActivityManager.PROCESS_STATE_TOP_SLEEPING:
- procState = "TS";
+ procState = "TPSL";
break;
case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
- procState = "IF";
+ procState = "IMPF";
break;
case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
- procState = "IB";
+ procState = "IMPB";
break;
case ActivityManager.PROCESS_STATE_BACKUP:
- procState = "BU";
+ procState = "BKUP";
break;
case ActivityManager.PROCESS_STATE_HEAVY_WEIGHT:
- procState = "HW";
+ procState = "HVY ";
break;
case ActivityManager.PROCESS_STATE_SERVICE:
- procState = "S ";
+ procState = "SVC ";
break;
case ActivityManager.PROCESS_STATE_RECEIVER:
- procState = "R ";
+ procState = "RCVR";
break;
case ActivityManager.PROCESS_STATE_HOME:
- procState = "HO";
+ procState = "HOME";
break;
case ActivityManager.PROCESS_STATE_LAST_ACTIVITY:
- procState = "LA";
+ procState = "LAST";
break;
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
- procState = "CA";
+ procState = "CAC ";
break;
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
- procState = "Ca";
+ procState = "CACC";
break;
case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
- procState = "CE";
+ procState = "CEM ";
break;
case ActivityManager.PROCESS_STATE_NONEXISTENT:
- procState = "N ";
+ procState = "NONE";
break;
default:
procState = "??";
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 2d2720458fbb..3c5c5fd0cfe4 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -287,7 +287,9 @@ final class ProcessRecord {
pw.print(" setSchedGroup="); pw.print(setSchedGroup);
pw.print(" systemNoUi="); pw.print(systemNoUi);
pw.print(" trimMemoryLevel="); pw.println(trimMemoryLevel);
- pw.print(prefix); pw.print("vrThreadTid="); pw.print(vrThreadTid);
+ if (vrThreadTid != 0) {
+ pw.print(prefix); pw.print("vrThreadTid="); pw.println(vrThreadTid);
+ }
pw.print(prefix); pw.print("curProcState="); pw.print(curProcState);
pw.print(" repProcState="); pw.print(repProcState);
pw.print(" pssProcState="); pw.print(pssProcState);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 44ebf50eb31a..b57f6c366f8f 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -124,6 +124,7 @@ final class ServiceRecord extends Binder {
final ServiceRecord sr;
final boolean taskRemoved;
final int id;
+ final int callingId;
final Intent intent;
final ActivityManagerService.NeededUriGrants neededGrants;
long deliveredTime;
@@ -134,12 +135,13 @@ final class ServiceRecord extends Binder {
String stringName; // caching of toString
StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id, Intent _intent,
- ActivityManagerService.NeededUriGrants _neededGrants) {
+ ActivityManagerService.NeededUriGrants _neededGrants, int _callingId) {
sr = _sr;
taskRemoved = _taskRemoved;
id = _id;
intent = _intent;
neededGrants = _neededGrants;
+ callingId = _callingId;
}
UriPermissionOwner getUriPermissionsLocked() {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index ce32f8413468..c7f20b9ff904 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -568,7 +568,27 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
boolean reparent(int preferredStackId, boolean toTop, @ReparentMoveStackMode int moveStackMode,
boolean animate, boolean deferResume, String reason) {
return reparent(preferredStackId, toTop ? MAX_VALUE : 0, moveStackMode, animate,
- deferResume, reason);
+ deferResume, true /* schedulePictureInPictureModeChange */, reason);
+ }
+
+ /**
+ * Convenience method to reparent a task to the top or bottom position of the stack, with
+ * an option to skip scheduling the picture-in-picture mode change.
+ */
+ boolean reparent(int preferredStackId, boolean toTop, @ReparentMoveStackMode int moveStackMode,
+ boolean animate, boolean deferResume, boolean schedulePictureInPictureModeChange,
+ String reason) {
+ return reparent(preferredStackId, toTop ? MAX_VALUE : 0, moveStackMode, animate,
+ deferResume, schedulePictureInPictureModeChange, reason);
+ }
+
+ /**
+ * Convenience method to reparent a task to a specific position of the stack.
+ */
+ boolean reparent(int preferredStackId, int position, @ReparentMoveStackMode int moveStackMode,
+ boolean animate, boolean deferResume, String reason) {
+ return reparent(preferredStackId, position, moveStackMode, animate, deferResume,
+ true /* schedulePictureInPictureModeChange */, reason);
}
/**
@@ -577,16 +597,20 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
* @param preferredStackId the stack id of the target stack to move this task
* @param position the position to place this task in the new stack
* @param animate whether or not we should wait for the new window created as a part of the
- * reparenting to be drawn and animated in
+ * reparenting to be drawn and animated in
* @param moveStackMode whether or not to move the stack to the front always, only if it was
- * previously focused & in front, or never
+ * previously focused & in front, or never
* @param deferResume whether or not to update the visibility of other tasks and stacks that may
- * have changed as a result of this reparenting
+ * have changed as a result of this reparenting
+ * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
+ * change. Callers may set this to false if they are explicitly scheduling PiP mode
+ * changes themselves, like during the PiP animation
* @param reason the caller of this reparenting
- * @return
+ * @return whether the task was reparented
*/
boolean reparent(int preferredStackId, int position, @ReparentMoveStackMode int moveStackMode,
- boolean animate, boolean deferResume, String reason) {
+ boolean animate, boolean deferResume, boolean schedulePictureInPictureModeChange,
+ String reason) {
final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
final WindowManagerService windowManager = mService.mWindowManager;
final ActivityStack sourceStack = getStack();
@@ -636,24 +660,14 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
// we are coming from in WM before we reparent because it became empty.
mWindowContainerController.reparent(toStack.getWindowContainerController(), position);
- // Reset the resumed activity on the previous stack
- if (wasResumed) {
- sourceStack.mResumedActivity = null;
- }
-
- // Reset the paused activity on the previous stack
- if (wasPaused) {
- sourceStack.mPausingActivity = null;
- sourceStack.removeTimeoutsForActivityLocked(r);
- }
-
// Move the task
sourceStack.removeTask(this, reason, REMOVE_TASK_MODE_MOVING);
- toStack.addTask(this, position, reason);
+ toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
- // TODO: Ensure that this is actually necessary here
- // Notify of picture-in-picture mode changes
- supervisor.scheduleReportPictureInPictureModeChangedIfNeeded(this, sourceStack);
+ if (schedulePictureInPictureModeChange) {
+ // Notify of picture-in-picture mode changes
+ supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
+ }
// TODO: Ensure that this is actually necessary here
// Notify the voice session if required
@@ -1187,14 +1201,13 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
* be in the current task or unparented to any task.
*/
void addActivityAtIndex(int index, ActivityRecord r) {
- if (r.task != null && r.task != this) {
+ TaskRecord task = r.getTask();
+ if (task != null && task != this) {
throw new IllegalArgumentException("Can not add r=" + " to task=" + this
- + " current parent=" + r.task);
+ + " current parent=" + task);
}
- // TODO(b/36505427): Maybe make task private to ActivityRecord so we can also do
- // onParentChanged() within the setter?
- r.task = this;
- r.onParentChanged();
+
+ r.setTask(this);
// Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
if (!mActivities.remove(r) && r.fullscreen) {
@@ -1249,15 +1262,21 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
}
/**
- * @return true if this was the last activity in the task
+ * Removes the specified activity from this task.
+ * @param r The {@link ActivityRecord} to remove.
+ * @return true if this was the last activity in the task.
*/
boolean removeActivity(ActivityRecord r) {
- if (r.task != this) {
+ return removeActivity(r, false /*reparenting*/);
+ }
+
+ boolean removeActivity(ActivityRecord r, boolean reparenting) {
+ if (r.getTask() != this) {
throw new IllegalArgumentException(
"Activity=" + r + " does not belong to task=" + this);
}
- r.task = null;
+ r.setTask(null /*task*/, reparenting);
if (mActivities.remove(r) && r.fullscreen) {
// Was previously in list.
@@ -1412,7 +1431,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
TaskThumbnail getTaskThumbnailLocked() {
if (mStack != null) {
final ActivityRecord resumedActivity = mStack.mResumedActivity;
- if (resumedActivity != null && resumedActivity.task == this) {
+ if (resumedActivity != null && resumedActivity.getTask() == this) {
final Bitmap thumbnail = resumedActivity.screenshotActivityLocked();
setLastThumbnailLocked(thumbnail);
}
@@ -1594,6 +1613,9 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
String iconFilename = null;
int colorPrimary = 0;
int colorBackground = 0;
+ int statusBarColor = 0;
+ int navigationBarColor = 0;
+ boolean topActivity = true;
for (--activityNdx; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = mActivities.get(activityNdx);
if (r.taskDescription != null) {
@@ -1606,13 +1628,16 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
if (colorPrimary == 0) {
colorPrimary = r.taskDescription.getPrimaryColor();
}
- if (colorBackground == 0) {
+ if (topActivity) {
colorBackground = r.taskDescription.getBackgroundColor();
+ statusBarColor = r.taskDescription.getStatusBarColor();
+ navigationBarColor = r.taskDescription.getNavigationBarColor();
}
}
+ topActivity = false;
}
lastTaskDescription = new TaskDescription(label, null, iconFilename, colorPrimary,
- colorBackground);
+ colorBackground, statusBarColor, navigationBarColor);
if (mWindowContainerController != null) {
mWindowContainerController.setTaskDescription(lastTaskDescription);
}
@@ -1928,7 +1953,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
task.updateOverrideConfiguration(bounds);
for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
- activities.get(activityNdx).task = task;
+ activities.get(activityNdx).setTask(task);
}
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
@@ -1979,6 +2004,25 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
}
/**
+ * @return a new Configuration for this Task, given the provided {@param bounds} and
+ * {@param insetBounds}.
+ */
+ Configuration computeNewOverrideConfigurationForBounds(Rect bounds, Rect insetBounds) {
+ // Compute a new override configuration for the given bounds, if fullscreen bounds
+ // (bounds == null), then leave the override config unset
+ final Configuration newOverrideConfig = new Configuration();
+ if (bounds != null) {
+ newOverrideConfig.setTo(getOverrideConfiguration());
+ mTmpRect.set(bounds);
+ adjustForMinimalTaskDimensions(mTmpRect);
+ computeOverrideConfiguration(newOverrideConfig, mTmpRect, insetBounds,
+ mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
+ }
+
+ return newOverrideConfig;
+ }
+
+ /**
* Update task's override configuration based on the bounds.
* @param bounds The bounds of the task.
* @return True if the override configuration was updated.
@@ -2027,7 +2071,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
onOverrideConfigurationChanged(newConfig);
if (mFullscreen != oldFullscreen) {
- mService.mStackSupervisor.scheduleReportMultiWindowModeChanged(this);
+ mService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
}
return !mTmpConfig.equals(newConfig);
@@ -2044,6 +2088,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
config.unset();
final Configuration parentConfig = getParent().getConfiguration();
+
final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
if (mStack != null) {
@@ -2052,11 +2097,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density,
config, parentConfig);
} else {
- // No stack, give some default values
- config.smallestScreenWidthDp =
- mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
- config.screenWidthDp = config.screenHeightDp = config.smallestScreenWidthDp;
- Slog.wtf(TAG, "Expected stack when calculating override config");
+ throw new IllegalArgumentException("Expected stack when calculating override config");
}
config.orientation = (config.screenWidthDp <= config.screenHeightDp)
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 70e56b09de13..c11f5316f769 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -55,6 +55,7 @@ import android.hardware.hdmi.HdmiTvClient;
import android.hardware.usb.UsbManager;
import android.media.AudioAttributes;
import android.media.AudioDevicePort;
+import android.media.AudioFocusInfo;
import android.media.AudioSystem;
import android.media.AudioFormat;
import android.media.AudioManager;
@@ -5634,8 +5635,9 @@ public class AudioService extends IAudioService.Stub
clientId, callingPackageName, flags);
}
- public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa) {
- return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa);
+ public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
+ String callingPackageName) {
+ return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName);
}
public void unregisterAudioFocusClient(String clientId) {
@@ -5650,6 +5652,7 @@ public class AudioService extends IAudioService.Stub
return mMediaFocusControl.getFocusRampTimeMs(focusGain, attr);
}
+ //==========================================================================================
private boolean readCameraSoundForced() {
return SystemProperties.getBoolean("audio.camerasound.force", false) ||
mContext.getResources().getBoolean(
@@ -6430,7 +6433,7 @@ public class AudioService extends IAudioService.Stub
// Audio policy management
//==========================================================================================
public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
- boolean hasFocusListener) {
+ boolean hasFocusListener, boolean isFocusPolicy) {
AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
if (DEBUG_AP) Log.d(TAG, "registerAudioPolicy for " + pcb.asBinder()
@@ -6452,7 +6455,8 @@ public class AudioService extends IAudioService.Stub
Slog.e(TAG, "Cannot re-register policy");
return null;
}
- AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener);
+ AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
+ isFocusPolicy);
pcb.asBinder().linkToDeath(app, 0/*flags*/);
regId = app.getRegistrationId();
mAudioPolicies.put(pcb.asBinder(), app);
@@ -6650,15 +6654,21 @@ public class AudioService extends IAudioService.Stub
* is handling ducking for audio focus.
*/
int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT;
+ boolean mIsFocusPolicy = false;
AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
- boolean hasFocusListener) {
+ boolean hasFocusListener, boolean isFocusPolicy) {
super(config);
setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
mPolicyCallback = token;
mHasFocusListener = hasFocusListener;
if (mHasFocusListener) {
mMediaFocusControl.addFocusFollower(mPolicyCallback);
+ // can only ever be true if there is a focus listener
+ if (isFocusPolicy) {
+ mIsFocusPolicy = true;
+ mMediaFocusControl.setFocusPolicy(mPolicyCallback);
+ }
}
connectMixes();
}
@@ -6676,6 +6686,9 @@ public class AudioService extends IAudioService.Stub
}
void release() {
+ if (mIsFocusPolicy) {
+ mMediaFocusControl.unsetFocusPolicy(mPolicyCallback);
+ }
if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
mMediaFocusControl.setDuckingInExtPolicyAvailable(false);
}
@@ -6690,6 +6703,22 @@ public class AudioService extends IAudioService.Stub
}
};
+ //======================
+ // Audio policy: focus
+ //======================
+ /** */
+ public int dispatchFocusChange(AudioFocusInfo afi, int focusChange, IAudioPolicyCallback pcb) {
+ synchronized (mAudioPolicies) {
+ if (!mAudioPolicies.containsKey(pcb.asBinder())) {
+ throw new IllegalStateException("Unregistered AudioPolicy for focus dispatch");
+ }
+ return mMediaFocusControl.dispatchFocusChange(afi, focusChange);
+ }
+ }
+
+ //======================
+ // misc
+ //======================
private HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
new HashMap<IBinder, AudioPolicyProxy>();
private int mAudioPolicyCounter = 0; // always accessed synchronized on mAudioPolicies
diff --git a/services/core/java/com/android/server/audio/FocusRequester.java b/services/core/java/com/android/server/audio/FocusRequester.java
index 5275c0524d54..bcaa29593304 100644
--- a/services/core/java/com/android/server/audio/FocusRequester.java
+++ b/services/core/java/com/android/server/audio/FocusRequester.java
@@ -33,7 +33,7 @@ import java.io.PrintWriter;
* @hide
* Class to handle all the information about a user of audio focus. The lifecycle of each
* instance is managed by android.media.MediaFocusControl, from its addition to the audio focus
- * stack to its release.
+ * stack, or the map of focus owners for an external focus policy, to its release.
*/
public class FocusRequester {
@@ -101,6 +101,21 @@ public class FocusRequester {
mFocusController = ctlr;
}
+ FocusRequester(AudioFocusInfo afi, IAudioFocusDispatcher afl,
+ IBinder source, AudioFocusDeathHandler hdlr, @NonNull MediaFocusControl ctlr) {
+ mAttributes = afi.getAttributes();
+ mClientId = afi.getClientId();
+ mPackageName = afi.getPackageName();
+ mCallingUid = afi.getClientUid();
+ mFocusGainRequest = afi.getGainRequest();
+ mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
+ mGrantFlags = afi.getFlags();
+
+ mFocusDispatcher = afl;
+ mSourceRef = source;
+ mDeathHandler = hdlr;
+ mFocusController = ctlr;
+ }
boolean hasSameClient(String otherClient) {
try {
@@ -118,6 +133,10 @@ public class FocusRequester {
return (mSourceRef != null) && mSourceRef.equals(ib);
}
+ boolean hasSameDispatcher(IAudioFocusDispatcher fd) {
+ return (mFocusDispatcher != null) && mFocusDispatcher.equals(fd);
+ }
+
boolean hasSamePackage(String pack) {
try {
return mPackageName.compareTo(pack) == 0;
@@ -369,6 +388,35 @@ public class FocusRequester {
}
}
+ int dispatchFocusChange(int focusChange) {
+ if (mFocusDispatcher == null) {
+ if (MediaFocusControl.DEBUG) { Log.v(TAG, "dispatchFocusChange: no focus dispatcher"); }
+ return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ }
+ if (focusChange == AudioManager.AUDIOFOCUS_NONE) {
+ if (MediaFocusControl.DEBUG) { Log.v(TAG, "dispatchFocusChange: AUDIOFOCUS_NONE"); }
+ return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ } else if ((focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
+ || focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
+ || focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
+ || focusChange == AudioManager.AUDIOFOCUS_GAIN)
+ && (mFocusGainRequest != focusChange)){
+ Log.w(TAG, "focus gain was requested with " + mFocusGainRequest
+ + ", dispatching " + focusChange);
+ } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
+ || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
+ || focusChange == AudioManager.AUDIOFOCUS_LOSS) {
+ mFocusLossReceived = focusChange;
+ }
+ try {
+ mFocusDispatcher.dispatchAudioFocusChange(focusChange, mClientId);
+ } catch (android.os.RemoteException e) {
+ Log.v(TAG, "dispatchFocusChange: error talking to focus listener", e);
+ return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ }
+ return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
+ }
+
AudioFocusInfo toAudioFocusInfo() {
return new AudioFocusInfo(mAttributes, mCallingUid, mClientId, mPackageName,
mFocusGainRequest, mFocusLossReceived, mGrantFlags);
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index b3f1548d4d92..821e78a27e33 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -16,6 +16,7 @@
package com.android.server.audio;
+import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.content.Context;
import android.media.AudioAttributes;
@@ -23,6 +24,7 @@ import android.media.AudioFocusInfo;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.IAudioFocusDispatcher;
+import android.media.audiopolicy.AudioPolicy;
import android.media.audiopolicy.IAudioPolicyCallback;
import android.os.Binder;
import android.os.IBinder;
@@ -32,7 +34,10 @@ import android.util.Log;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.Set;
import java.util.Stack;
import java.text.DateFormat;
@@ -43,6 +48,7 @@ import java.text.DateFormat;
public class MediaFocusControl implements PlayerFocusEnforcer {
private static final String TAG = "MediaFocusControl";
+ static final boolean DEBUG = false;
/**
* set to true so the framework enforces ducking itself, without communicating to apps
@@ -155,6 +161,13 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
while(stackIterator.hasNext()) {
stackIterator.next().dump(pw);
}
+ pw.println("\n");
+ if (mFocusPolicy == null) {
+ pw.println("No external focus policy\n");
+ } else {
+ pw.println("External focus policy: "+ mFocusPolicy + ", focus owners:\n");
+ dumpExtFocusPolicyFocusOwners(pw);
+ }
}
pw.println("\n");
pw.println(" Notify on duck: " + mNotifyFocusOwnerOnDuck + "\n");
@@ -234,6 +247,31 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
}
/**
+ * Helper function for external focus policy:
+ * Called synchronized on mAudioFocusLock
+ * Remove focus listeners from the list of potential focus owners for a particular client when
+ * it has died.
+ */
+ private void removeFocusEntryForExtPolicy(IBinder cb) {
+ if (mFocusOwnersForFocusPolicy.isEmpty()) {
+ return;
+ }
+ boolean released = false;
+ final Set<Entry<String, FocusRequester>> owners = mFocusOwnersForFocusPolicy.entrySet();
+ final Iterator<Entry<String, FocusRequester>> ownerIterator = owners.iterator();
+ while (ownerIterator.hasNext()) {
+ final Entry<String, FocusRequester> owner = ownerIterator.next();
+ final FocusRequester fr = owner.getValue();
+ if (fr.hasSameBinder(cb)) {
+ ownerIterator.remove();
+ fr.release();
+ notifyExtFocusPolicyFocusAbandon_syncAf(fr.toAudioFocusInfo());
+ break;
+ }
+ }
+ }
+
+ /**
* Helper function:
* Returns true if the system is in a state where the focus can be reevaluated, false otherwise.
* The implementation guarantees that a state where focus cannot be immediately reassigned
@@ -297,7 +335,11 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
public void binderDied() {
synchronized(mAudioFocusLock) {
- removeFocusStackEntryOnDeath(mCb);
+ if (mFocusPolicy != null) {
+ removeFocusEntryForExtPolicy(mCb);
+ } else {
+ removeFocusStackEntryOnDeath(mCb);
+ }
}
}
}
@@ -353,6 +395,34 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
}
}
+ private IAudioPolicyCallback mFocusPolicy = null;
+
+ // Since we don't have a stack of focus owners when using an external focus policy, we keep
+ // track of all the focus requesters in this map, with their clientId as the key. This is
+ // used both for focus dispatch and death handling
+ private HashMap<String, FocusRequester> mFocusOwnersForFocusPolicy =
+ new HashMap<String, FocusRequester>();
+
+ void setFocusPolicy(IAudioPolicyCallback policy) {
+ if (policy == null) {
+ return;
+ }
+ synchronized (mAudioFocusLock) {
+ mFocusPolicy = policy;
+ }
+ }
+
+ void unsetFocusPolicy(IAudioPolicyCallback policy) {
+ if (policy == null) {
+ return;
+ }
+ synchronized (mAudioFocusLock) {
+ if (mFocusPolicy == policy) {
+ mFocusPolicy = null;
+ }
+ }
+ }
+
/**
* @param pcb non null
*/
@@ -409,6 +479,100 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
}
}
+ /**
+ * Called synchronized on mAudioFocusLock
+ * @param afi
+ * @param requestResult
+ * @return true if the external audio focus policy (if any) is handling the focus request
+ */
+ boolean notifyExtFocusPolicyFocusRequest_syncAf(AudioFocusInfo afi, int requestResult,
+ IAudioFocusDispatcher fd, IBinder cb) {
+ if (mFocusPolicy == null) {
+ return false;
+ }
+ if (DEBUG) {
+ Log.v(TAG, "notifyExtFocusPolicyFocusRequest client="+afi.getClientId()
+ + " dispatcher=" + fd);
+ }
+ final FocusRequester existingFr = mFocusOwnersForFocusPolicy.get(afi.getClientId());
+ if (existingFr != null) {
+ if (!existingFr.hasSameDispatcher(fd)) {
+ existingFr.release();
+ final AudioFocusDeathHandler hdlr = new AudioFocusDeathHandler(cb);
+ mFocusOwnersForFocusPolicy.put(afi.getClientId(),
+ new FocusRequester(afi, fd, cb, hdlr, this));
+ }
+ } else if (requestResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED
+ || requestResult == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
+ // new focus (future) focus owner to keep track of
+ final AudioFocusDeathHandler hdlr = new AudioFocusDeathHandler(cb);
+ mFocusOwnersForFocusPolicy.put(afi.getClientId(),
+ new FocusRequester(afi, fd, cb, hdlr, this));
+ }
+ try {
+ //oneway
+ mFocusPolicy.notifyAudioFocusRequest(afi, requestResult);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Can't call notifyAudioFocusRequest() on IAudioPolicyCallback "
+ + mFocusPolicy.asBinder(), e);
+ }
+ return true;
+ }
+
+ /**
+ * Called synchronized on mAudioFocusLock
+ * @param afi
+ * @param requestResult
+ * @return true if the external audio focus policy (if any) is handling the focus request
+ */
+ boolean notifyExtFocusPolicyFocusAbandon_syncAf(AudioFocusInfo afi) {
+ if (mFocusPolicy == null) {
+ return false;
+ }
+ final FocusRequester fr = mFocusOwnersForFocusPolicy.remove(afi.getClientId());
+ if (fr != null) {
+ fr.release();
+ }
+ try {
+ //oneway
+ mFocusPolicy.notifyAudioFocusAbandon(afi);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Can't call notifyAudioFocusAbandon() on IAudioPolicyCallback "
+ + mFocusPolicy.asBinder(), e);
+ }
+ return true;
+ }
+
+ /** see AudioManager.dispatchFocusChange(AudioFocusInfo afi, int focusChange, AudioPolicy ap) */
+ int dispatchFocusChange(AudioFocusInfo afi, int focusChange) {
+ if (DEBUG) {
+ Log.v(TAG, "dispatchFocusChange " + focusChange + " to afi client="
+ + afi.getClientId());
+ }
+ synchronized (mAudioFocusLock) {
+ if (mFocusPolicy == null) {
+ if (DEBUG) { Log.v(TAG, "> failed: no focus policy" ); }
+ return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ }
+ final FocusRequester fr = mFocusOwnersForFocusPolicy.get(afi.getClientId());
+ if (fr == null) {
+ if (DEBUG) { Log.v(TAG, "> failed: no such focus requester known" ); }
+ return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ }
+ return fr.dispatchFocusChange(focusChange);
+ }
+ }
+
+ private void dumpExtFocusPolicyFocusOwners(PrintWriter pw) {
+ final Set<Entry<String, FocusRequester>> owners = mFocusOwnersForFocusPolicy.entrySet();
+ final Iterator<Entry<String, FocusRequester>> ownerIterator = owners.iterator();
+ while (ownerIterator.hasNext()) {
+ final Entry<String, FocusRequester> owner = ownerIterator.next();
+ final FocusRequester fr = owner.getValue();
+ fr.dump(pw);
+ }
+ }
+
protected int getCurrentAudioFocus() {
synchronized(mAudioFocusLock) {
if (mFocusStack.empty()) {
@@ -487,10 +651,23 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
& (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0);
if (enteringRingOrCall) { mRingOrCallActive = true; }
+ final AudioFocusInfo afiForExtPolicy;
+ if (mFocusPolicy != null) {
+ // construct AudioFocusInfo as it will be communicated to audio focus policy
+ afiForExtPolicy = new AudioFocusInfo(aa, Binder.getCallingUid(),
+ clientId, callingPackageName, focusChangeHint, 0 /*lossReceived*/,
+ flags);
+ } else {
+ afiForExtPolicy = null;
+ }
+
+ // handle delayed focus
boolean focusGrantDelayed = false;
if (!canReassignAudioFocus()) {
if ((flags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK) == 0) {
- return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ final int result = AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ notifyExtFocusPolicyFocusRequest_syncAf(afiForExtPolicy, result, fd, cb);
+ return result;
} else {
// request has AUDIOFOCUS_FLAG_DELAY_OK: focus can't be
// granted right now, so the requester will be inserted in the focus stack
@@ -499,6 +676,14 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
}
}
+ // external focus policy: delay request for focus gain?
+ final int resultWithExtPolicy = AudioManager.AUDIOFOCUS_REQUEST_DELAYED;
+ if (notifyExtFocusPolicyFocusRequest_syncAf(
+ afiForExtPolicy, resultWithExtPolicy, fd, cb)) {
+ // stop handling focus request here as it is handled by external audio focus policy
+ return resultWithExtPolicy;
+ }
+
// handle the potential premature death of the new holder of the focus
// (premature death == death before abandoning focus)
// Register for client death notification
@@ -569,7 +754,8 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
/**
* @see AudioManager#abandonAudioFocus(AudioManager.OnAudioFocusChangeListener, AudioAttributes)
* */
- protected int abandonAudioFocus(IAudioFocusDispatcher fl, String clientId, AudioAttributes aa) {
+ protected int abandonAudioFocus(IAudioFocusDispatcher fl, String clientId, AudioAttributes aa,
+ String callingPackageName) {
// AudioAttributes are currently ignored, to be used for zones
Log.i(TAG, " AudioFocus abandonAudioFocus() from uid/pid " + Binder.getCallingUid()
+ "/" + Binder.getCallingPid()
@@ -577,6 +763,16 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
try {
// this will take care of notifying the new focus owner if needed
synchronized(mAudioFocusLock) {
+ // external focus policy?
+ if (mFocusPolicy != null) {
+ final AudioFocusInfo afi = new AudioFocusInfo(aa, Binder.getCallingUid(),
+ clientId, callingPackageName, 0 /*gainRequest*/, 0 /*lossReceived*/,
+ 0 /*flags*/);
+ if (notifyExtFocusPolicyFocusAbandon_syncAf(afi)) {
+ return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
+ }
+ }
+
boolean exitingRingOrCall = mRingOrCallActive
& (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0);
if (exitingRingOrCall) { mRingOrCallActive = false; }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index a1a74377cf62..ddd918fdcc5d 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -339,6 +339,18 @@ public final class DisplayManagerService extends SystemService {
}
}
+ /**
+ * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
+ */
+ private void getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo) {
+ synchronized (mSyncRoot) {
+ final LogicalDisplay display = mLogicalDisplays.get(displayId);
+ if (display != null) {
+ display.getNonOverrideDisplayInfoLocked(outInfo);
+ }
+ }
+ }
+
private void performTraversalInTransactionFromWindowManagerInternal() {
synchronized (mSyncRoot) {
if (!mPendingTraversal) {
@@ -1663,6 +1675,11 @@ public final class DisplayManagerService extends SystemService {
}
@Override
+ public void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo) {
+ getNonOverrideDisplayInfoInternal(displayId, outInfo);
+ }
+
+ @Override
public void performTraversalInTransactionFromWindowManager() {
performTraversalInTransactionFromWindowManagerInternal();
}
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index a947b4106794..addad0b413a3 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -17,6 +17,7 @@
package com.android.server.display;
import android.graphics.Rect;
+import android.hardware.display.DisplayManagerInternal;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -62,7 +63,18 @@ final class LogicalDisplay {
private final int mDisplayId;
private final int mLayerStack;
- private DisplayInfo mOverrideDisplayInfo; // set by the window manager
+ /**
+ * Override information set by the window manager. Will be reported instead of {@link #mInfo}
+ * if not null.
+ * @see #setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo)
+ * @see #getDisplayInfoLocked()
+ */
+ private DisplayInfo mOverrideDisplayInfo;
+ /**
+ * Current display info. Initialized with {@link #mBaseDisplayInfo}. Set to {@code null} if
+ * needs to be updated.
+ * @see #getDisplayInfoLocked()
+ */
private DisplayInfo mInfo;
// The display device that this logical display is based on and which
@@ -142,6 +154,13 @@ final class LogicalDisplay {
}
/**
+ * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
+ */
+ void getNonOverrideDisplayInfoLocked(DisplayInfo outInfo) {
+ outInfo.copyFrom(mBaseDisplayInfo);
+ }
+
+ /**
* Sets overridden logical display information from the window manager.
* This method can be used to adjust application insets, rotation, and other
* properties that the window manager takes care of.
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 9e4432d25c0b..dc2ebb4451b2 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -27,4 +27,15 @@ public abstract class NetworkPolicyManagerInternal {
* Resets all policies associated with a given user.
*/
public abstract void resetUserState(int userId);
+
+ /**
+ * @return true if the given uid is restricted from doing networking on metered networks.
+ */
+ public abstract boolean isUidRestrictedOnMeteredNetworks(int uid);
+
+ /**
+ * @return true if networking is blocked on the given interface for the given uid according
+ * to current networking policies.
+ */
+ public abstract boolean isUidNetworkingBlocked(int uid, String ifname);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 8227753cc802..02e106e92aeb 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -178,6 +178,7 @@ import android.util.Xml;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.ArrayUtils;
@@ -213,6 +214,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Calendar;
+import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -246,8 +248,8 @@ import java.util.concurrent.TimeUnit;
*/
public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
static final String TAG = "NetworkPolicy";
- private static final boolean LOGD = false;
- private static final boolean LOGV = false;
+ private static final boolean LOGD = true; // UNDO
+ private static final boolean LOGV = true; // UNDO
private static final int VERSION_INIT = 1;
private static final int VERSION_ADDED_SNOOZE = 2;
@@ -269,11 +271,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
ActivityManager.isLowRamDeviceStatic() ? 50 : 200;
@VisibleForTesting
- public static final int TYPE_WARNING = 0x1;
+ public static final int TYPE_WARNING = SystemMessage.NOTE_NET_WARNING;
@VisibleForTesting
- public static final int TYPE_LIMIT = 0x2;
+ public static final int TYPE_LIMIT = SystemMessage.NOTE_NET_LIMIT;
@VisibleForTesting
- public static final int TYPE_LIMIT_SNOOZED = 0x3;
+ public static final int TYPE_LIMIT_SNOOZED = SystemMessage.NOTE_NET_LIMIT_SNOOZED;
private static final String TAG_POLICY_LIST = "policy-list";
private static final String TAG_NETWORK_POLICY = "network-policy";
@@ -420,15 +422,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/** Set of currently active {@link Notification} tags. */
@GuardedBy("mNetworkPoliciesSecondLock")
- private final ArraySet<String> mActiveNotifs = new ArraySet<String>();
+ private final ArraySet<NotificationId> mActiveNotifs = new ArraySet<>();
/** Foreground at UID granularity. */
@GuardedBy("mUidRulesFirstLock")
final SparseIntArray mUidState = new SparseIntArray();
- /** Higher priority listener before general event dispatch */
- private INetworkPolicyListener mConnectivityListener;
-
private final RemoteCallbackList<INetworkPolicyListener>
mListeners = new RemoteCallbackList<>();
@@ -1055,7 +1054,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (LOGV) Slog.v(TAG, "updateNotificationsNL()");
// keep track of previously active notifications
- final ArraySet<String> beforeNotifs = new ArraySet<String>(mActiveNotifs);
+ final ArraySet<NotificationId> beforeNotifs = new ArraySet<NotificationId>(mActiveNotifs);
mActiveNotifs.clear();
// TODO: when switching to kernel notifications, compute next future
@@ -1092,9 +1091,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// cancel stale notifications that we didn't renew above
for (int i = beforeNotifs.size()-1; i >= 0; i--) {
- final String tag = beforeNotifs.valueAt(i);
- if (!mActiveNotifs.contains(tag)) {
- cancelNotification(tag);
+ final NotificationId notificationId = beforeNotifs.valueAt(i);
+ if (!mActiveNotifs.contains(notificationId)) {
+ cancelNotification(notificationId);
}
}
}
@@ -1142,19 +1141,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
/**
- * Build unique tag that identifies an active {@link NetworkPolicy}
- * notification of a specific type, like {@link #TYPE_LIMIT}.
- */
- private String buildNotificationTag(NetworkPolicy policy, int type) {
- return TAG + ":" + policy.template.hashCode() + ":" + type;
- }
-
- /**
* Show notification for combined {@link NetworkPolicy} and specific type,
* like {@link #TYPE_LIMIT}. Okay to call multiple times.
*/
private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
- final String tag = buildNotificationTag(policy, type);
+ final NotificationId notificationId = new NotificationId(policy, type);
final Notification.Builder builder =
new Notification.Builder(mContext, SystemNotificationChannels.NETWORK_STATUS);
builder.setOnlyAlertOnce(true);
@@ -1262,25 +1253,26 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
try {
final String packageName = mContext.getPackageName();
final int[] idReceived = new int[1];
- if(!TextUtils.isEmpty(body)) {
+ if (!TextUtils.isEmpty(body)) {
builder.setStyle(new Notification.BigTextStyle()
.bigText(body));
}
mNotifManager.enqueueNotificationWithTag(
- packageName, packageName, tag, 0x0, builder.build(), idReceived,
- UserHandle.USER_ALL);
- mActiveNotifs.add(tag);
+ packageName, packageName, notificationId.getTag(), notificationId.getId(),
+ builder.build(), idReceived, UserHandle.USER_ALL);
+ mActiveNotifs.add(notificationId);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
}
- private void cancelNotification(String tag) {
+ private void cancelNotification(NotificationId notificationId) {
// TODO: move to NotificationManager once we can mock it
try {
final String packageName = mContext.getPackageName();
mNotifManager.cancelNotificationWithTag(
- packageName, tag, 0x0, UserHandle.USER_ALL);
+ packageName, notificationId.getTag(), notificationId.getId(),
+ UserHandle.USER_ALL);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
@@ -2242,15 +2234,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@Override
- public void setConnectivityListener(INetworkPolicyListener listener) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- if (mConnectivityListener != null) {
- throw new IllegalStateException("Connectivity listener already registered");
- }
- mConnectivityListener = listener;
- }
-
- @Override
public void registerListener(INetworkPolicyListener listener) {
// TODO: create permission for observing network policy
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
@@ -3561,7 +3544,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
case MSG_RULES_CHANGED: {
final int uid = msg.arg1;
final int uidRules = msg.arg2;
- dispatchUidRulesChanged(mConnectivityListener, uid, uidRules);
final int length = mListeners.beginBroadcast();
for (int i = 0; i < length; i++) {
final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
@@ -3572,7 +3554,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
case MSG_METERED_IFACES_CHANGED: {
final String[] meteredIfaces = (String[]) msg.obj;
- dispatchMeteredIfacesChanged(mConnectivityListener, meteredIfaces);
final int length = mListeners.beginBroadcast();
for (int i = 0; i < length; i++) {
final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
@@ -3603,7 +3584,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
case MSG_RESTRICT_BACKGROUND_CHANGED: {
final boolean restrictBackground = msg.arg1 != 0;
- dispatchRestrictBackgroundChanged(mConnectivityListener, restrictBackground);
final int length = mListeners.beginBroadcast();
for (int i = 0; i < length; i++) {
final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
@@ -3621,7 +3601,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final int policy = msg.arg2;
final Boolean notifyApp = (Boolean) msg.obj;
// First notify internal listeners...
- dispatchUidPoliciesChanged(mConnectivityListener, uid, policy);
final int length = mListeners.beginBroadcast();
for (int i = 0; i < length; i++) {
final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
@@ -4054,6 +4033,74 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
}
+
+ /**
+ * @return true if the given uid is restricted from doing networking on metered networks.
+ */
+ @Override
+ public boolean isUidRestrictedOnMeteredNetworks(int uid) {
+ final int uidRules;
+ final boolean isBackgroundRestricted;
+ synchronized (mUidRulesFirstLock) {
+ uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
+ isBackgroundRestricted = mRestrictBackground;
+ }
+ return isBackgroundRestricted
+ && !hasRule(uidRules, RULE_ALLOW_METERED)
+ && !hasRule(uidRules, RULE_TEMPORARY_ALLOW_METERED);
+ }
+
+ /**
+ * @return true if networking is blocked on the given interface for the given uid according
+ * to current networking policies.
+ */
+ @Override
+ public boolean isUidNetworkingBlocked(int uid, String ifname) {
+ final int uidRules;
+ final boolean isBackgroundRestricted;
+ final boolean isNetworkMetered;
+ synchronized (mUidRulesFirstLock) {
+ uidRules = mUidRules.get(uid, RULE_NONE);
+ isBackgroundRestricted = mRestrictBackground;
+ synchronized (mNetworkPoliciesSecondLock) {
+ isNetworkMetered = mMeteredIfaces.contains(ifname);
+ }
+ }
+ if (hasRule(uidRules, RULE_REJECT_ALL)) {
+ if (LOGV) logUidStatus(uid, "blocked by power restrictions");
+ return true;
+ }
+ if (!isNetworkMetered) {
+ if (LOGV) logUidStatus(uid, "allowed on unmetered network");
+ return false;
+ }
+ if (hasRule(uidRules, RULE_REJECT_METERED)) {
+ if (LOGV) logUidStatus(uid, "blacklisted on metered network");
+ return true;
+ }
+ if (hasRule(uidRules, RULE_ALLOW_METERED)) {
+ if (LOGV) logUidStatus(uid, "whitelisted on metered network");
+ return false;
+ }
+ if (hasRule(uidRules, RULE_TEMPORARY_ALLOW_METERED)) {
+ if (LOGV) logUidStatus(uid, "temporary whitelisted on metered network");
+ return false;
+ }
+ if (isBackgroundRestricted) {
+ if (LOGV) logUidStatus(uid, "blocked when background is restricted");
+ return true;
+ }
+ if (LOGV) logUidStatus(uid, "allowed by default");
+ return false;
+ }
+ }
+
+ private static boolean hasRule(int uidRules, int rule) {
+ return (uidRules & rule) != 0;
+ }
+
+ private static void logUidStatus(int uid, String descr) {
+ Slog.d(TAG, String.format("uid %d is %s", uid, descr));
}
/**
@@ -4125,4 +4172,43 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return next;
}
}
+
+ private class NotificationId {
+ private final String mTag;
+ private final int mId;
+
+ NotificationId(NetworkPolicy policy, int type) {
+ mTag = buildNotificationTag(policy, type);
+ mId = type;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof NotificationId)) return false;
+ NotificationId that = (NotificationId) o;
+ return Objects.equals(mTag, that.mTag);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mTag);
+ }
+
+ /**
+ * Build unique tag that identifies an active {@link NetworkPolicy}
+ * notification of a specific type, like {@link #TYPE_LIMIT}.
+ */
+ private String buildNotificationTag(NetworkPolicy policy, int type) {
+ return TAG + ":" + policy.template.hashCode() + ":" + type;
+ }
+
+ public String getTag() {
+ return mTag;
+ }
+
+ public int getId() {
+ return mId;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 73afaa089dd4..65aaee0f8ce8 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -282,7 +282,7 @@ public class RankingHelper implements RankingConfig {
for (int i = 0; i < size; i++) {
final NotificationChannel notificationChannel = r.channels.valueAt(i);
if (notificationChannel != null &&
- notificationChannel.getId() != NotificationChannel.DEFAULT_CHANNEL_ID) {
+ !notificationChannel.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
hasCreatedAChannel = true;
break;
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index e1426fdcf3ef..f79f6f40294c 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -242,18 +242,8 @@ public class LauncherAppsService extends SystemService {
try {
UserInfo callingUserInfo = mUm.getUserInfo(callingUserId);
if (callingUserInfo.isManagedProfile()) {
-
- // STOPSHIP Remove the whitelist.
- if ("com.google.android.talk".equals(callingPackage)
- || "com.google.android.quicksearchbox".equals(callingPackage)
- || "com.google.android.googlequicksearchbox".equals(callingPackage)
- ) {
- return false;
- }
- // STOPSHIP Change it to 'e'.
- Slog.wtfStack(TAG, message + " by " + callingPackage + " for another profile "
+ Slog.w(TAG, message + " by " + callingPackage + " for another profile "
+ targetUserId + " from " + callingUserId);
-
return false;
}
@@ -445,8 +435,8 @@ public class LauncherAppsService extends SystemService {
@Override
public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
- String packageName, List shortcutIds, ComponentName componentName, Intent intent,
- int flags, UserHandle targetUser) {
+ String packageName, List shortcutIds, ComponentName componentName, int flags,
+ UserHandle targetUser) {
ensureShortcutPermission(callingPackage);
if (!canAccessProfile(callingPackage, targetUser, "Cannot get shortcuts")
|| !isUserEnabled(targetUser)) {
@@ -457,17 +447,11 @@ public class LauncherAppsService extends SystemService {
"To query by shortcut ID, package name must also be set");
}
- if ((flags & ShortcutQuery.FLAG_MATCH_CHOOSER) == 0
- && intent != null) {
- throw new IllegalArgumentException("Supplied an intent in the query, but did "
- + "not request chooser targets");
- }
-
// TODO(b/29399275): Eclipse compiler requires explicit List<ShortcutInfo> cast below.
return new ParceledListSlice<>((List<ShortcutInfo>)
mShortcutServiceInternal.getShortcuts(getCallingUserId(),
callingPackage, changedSince, packageName, shortcutIds,
- componentName, intent, flags, targetUser.getIdentifier()));
+ componentName, flags, targetUser.getIdentifier()));
}
@Override
@@ -915,7 +899,6 @@ public class LauncherAppsService extends SystemService {
cookie.packageName,
/* changedSince= */ 0, packageName, /* shortcutIds=*/ null,
/* component= */ null,
- /* intent= */ null,
ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
| ShortcutQuery.FLAG_GET_ALL_KINDS
, userId);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0d9b052be7dd..d89b12e35215 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -569,7 +569,7 @@ public class PackageManagerService extends IPackageManager.Stub {
Manifest.permission.RECEIVE_MMS,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
- Manifest.permission.READ_PHONE_NUMBER,
+ Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.ANSWER_PHONE_CALLS);
@@ -2385,6 +2385,10 @@ public class PackageManagerService extends IPackageManager.Stub {
final VersionInfo ver = mSettings.getInternalVersion();
mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
+ if (mIsUpgrade) {
+ logCriticalInfo(Log.INFO,
+ "Upgrading from " + ver.fingerprint + " to " + Build.FINGERPRINT);
+ }
// when upgrading from pre-M, promote system app permissions from install to runtime
mPromoteSystemApps =
@@ -3036,13 +3040,14 @@ public class PackageManagerService extends IPackageManager.Stub {
return null;
}
+ final int callingUid = Binder.getCallingUid();
final int resolveFlags =
MATCH_DIRECT_BOOT_AWARE
| MATCH_DIRECT_BOOT_UNAWARE
| (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0);
final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE);
final List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null,
- resolveFlags, UserHandle.USER_SYSTEM);
+ resolveFlags, UserHandle.USER_SYSTEM, callingUid, false /*includeInstantApps*/);
final int N = resolvers.size();
if (N == 0) {
@@ -4021,12 +4026,12 @@ public class PackageManagerService extends IPackageManager.Stub {
* action and a {@code android.intent.category.BROWSABLE} category</li>
* </ul>
*/
- int updateFlagsForResolve(int flags, int userId, Intent intent, boolean includeInstantApp) {
+ int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid,
+ boolean includeInstantApps) {
// Safe mode means we shouldn't match any third-party components
if (mSafeMode) {
flags |= PackageManager.MATCH_SYSTEM_ONLY;
}
- final int callingUid = Binder.getCallingUid();
if (getInstantAppPackageName(callingUid) != null) {
// But, ephemeral apps see both ephemeral and exposed, non-ephemeral components
flags |= PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY;
@@ -4038,7 +4043,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|| callingUid == Process.SHELL_UID
|| callingUid == 0;
final boolean allowMatchInstant =
- (includeInstantApp
+ (includeInstantApps
&& Intent.ACTION_VIEW.equals(intent.getAction())
&& intent.hasCategory(Intent.CATEGORY_BROWSABLE)
&& hasWebURI(intent))
@@ -5588,22 +5593,23 @@ public class PackageManagerService extends IPackageManager.Stub {
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
return resolveIntentInternal(
- intent, resolvedType, flags, userId, false /*includeInstantApp*/);
+ intent, resolvedType, flags, userId, false /*includeInstantApps*/);
}
private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
- int flags, int userId, boolean includeInstantApp) {
+ int flags, int userId, boolean includeInstantApps) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
if (!sUserManager.exists(userId)) return null;
- flags = updateFlagsForResolve(flags, userId, intent, includeInstantApp);
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ final int callingUid = Binder.getCallingUid();
+ flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps);
+ enforceCrossUserPermission(callingUid, userId,
false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
- flags, userId, includeInstantApp);
+ flags, userId, includeInstantApps);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
final ResolveInfo bestChoice =
@@ -5623,9 +5629,11 @@ public class PackageManagerService extends IPackageManager.Stub {
if (!sUserManager.exists(userId)) {
return null;
}
+ final int callingUid = Binder.getCallingUid();
intent = updateIntentForResolve(intent);
final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
- final int flags = updateFlagsForResolve(0, userId, intent, false);
+ final int flags = updateFlagsForResolve(
+ 0, userId, intent, callingUid, false /*includeInstantApps*/);
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
userId);
synchronized (mPackages) {
@@ -5914,7 +5922,9 @@ public class PackageManagerService extends IPackageManager.Stub {
List<ResolveInfo> query, int priority, boolean always,
boolean removeMatches, boolean debug, int userId) {
if (!sUserManager.exists(userId)) return null;
- flags = updateFlagsForResolve(flags, userId, intent, false);
+ final int callingUid = Binder.getCallingUid();
+ flags = updateFlagsForResolve(
+ flags, userId, intent, callingUid, false /*includeInstantApps*/);
intent = updateIntentForResolve(intent);
// writer
synchronized (mPackages) {
@@ -6080,9 +6090,11 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (hasWebURI(intent)) {
// cross-profile app linking works only towards the parent.
+ final int callingUid = Binder.getCallingUid();
final UserInfo parent = getProfileParent(sourceUserId);
synchronized(mPackages) {
- int flags = updateFlagsForResolve(0, parent.id, intent, false);
+ int flags = updateFlagsForResolve(0, parent.id, intent, callingUid,
+ false /*includeInstantApps*/);
CrossProfileDomainInfo xpDomainInfo = getCrossProfileDomainPreferredLpr(
intent, resolvedType, flags, sourceUserId, parent.id);
return xpDomainInfo != null;
@@ -6149,11 +6161,12 @@ public class PackageManagerService extends IPackageManager.Stub {
}
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
- String resolvedType, int flags, int userId, boolean includeInstantApp) {
+ String resolvedType, int flags, int userId, boolean includeInstantApps) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- final String instantAppPkgName = getInstantAppPackageName(Binder.getCallingUid());
- flags = updateFlagsForResolve(flags, userId, intent, includeInstantApp);
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ final int callingUid = Binder.getCallingUid();
+ final String instantAppPkgName = getInstantAppPackageName(callingUid);
+ flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps);
+ enforceCrossUserPermission(callingUid, userId,
false /* requireFullPermission */, false /* checkShell */,
"query intent activities");
ComponentName comp = intent.getComponent();
@@ -6783,9 +6796,11 @@ public class PackageManagerService extends IPackageManager.Stub {
Intent[] specifics, String[] specificTypes, Intent intent,
String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- flags = updateFlagsForResolve(flags, userId, intent, false);
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
- false /* requireFullPermission */, false /* checkShell */,
+ final int callingUid = Binder.getCallingUid();
+ flags = updateFlagsForResolve(flags, userId, intent, callingUid,
+ false /*includeInstantApps*/);
+ enforceCrossUserPermission(callingUid, userId,
+ false /*requireFullPermission*/, false /*checkShell*/,
"query intent activity options");
final String resultsAction = intent.getAction();
@@ -6963,7 +6978,9 @@ public class PackageManagerService extends IPackageManager.Stub {
private @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- flags = updateFlagsForResolve(flags, userId, intent, false);
+ final int callingUid = Binder.getCallingUid();
+ flags = updateFlagsForResolve(flags, userId, intent, callingUid,
+ false /*includeInstantApps*/);
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -6999,9 +7016,17 @@ public class PackageManagerService extends IPackageManager.Stub {
@Override
public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ return resolveServiceInternal(
+ intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/);
+ }
+
+ private ResolveInfo resolveServiceInternal(Intent intent, String resolvedType, int flags,
+ int userId, int callingUid, boolean includeInstantApps) {
if (!sUserManager.exists(userId)) return null;
- flags = updateFlagsForResolve(flags, userId, intent, false);
- List<ResolveInfo> query = queryIntentServicesInternal(intent, resolvedType, flags, userId);
+ flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps);
+ List<ResolveInfo> query = queryIntentServicesInternal(
+ intent, resolvedType, flags, userId, callingUid, includeInstantApps);
if (query != null) {
if (query.size() >= 1) {
// If there is more than one service with the same priority,
@@ -7015,14 +7040,17 @@ public class PackageManagerService extends IPackageManager.Stub {
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentServices(Intent intent,
String resolvedType, int flags, int userId) {
- return new ParceledListSlice<>(
- queryIntentServicesInternal(intent, resolvedType, flags, userId));
+ final int callingUid = Binder.getCallingUid();
+ return new ParceledListSlice<>(queryIntentServicesInternal(
+ intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/));
}
private @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent,
- String resolvedType, int flags, int userId) {
+ String resolvedType, int flags, int userId, int callingUid,
+ boolean includeInstantApps) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- flags = updateFlagsForResolve(flags, userId, intent, false);
+ final String instantAppPkgName = getInstantAppPackageName(callingUid);
+ flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps);
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -7034,9 +7062,27 @@ public class PackageManagerService extends IPackageManager.Stub {
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
final ServiceInfo si = getServiceInfo(comp, flags, userId);
if (si != null) {
- final ResolveInfo ri = new ResolveInfo();
- ri.serviceInfo = si;
- list.add(ri);
+ // When specifying an explicit component, we prevent the service from being
+ // used when either 1) the service is in an instant application and the
+ // caller is not the same instant application or 2) the calling package is
+ // ephemeral and the activity is not visible to ephemeral applications.
+ final boolean matchVisibleToInstantAppOnly =
+ (flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+ final boolean isCallerInstantApp =
+ instantAppPkgName != null;
+ final boolean isTargetSameInstantApp =
+ comp.getPackageName().equals(instantAppPkgName);
+ final boolean isTargetHiddenFromInstantApp =
+ (si.flags & ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0;
+ final boolean blockResolution =
+ !isTargetSameInstantApp
+ && ((matchVisibleToInstantAppOnly && isCallerInstantApp
+ && isTargetHiddenFromInstantApp));
+ if (!blockResolution) {
+ final ResolveInfo ri = new ResolveInfo();
+ ri.serviceInfo = si;
+ list.add(ri);
+ }
}
return list;
}
@@ -7045,17 +7091,67 @@ public class PackageManagerService extends IPackageManager.Stub {
synchronized (mPackages) {
String pkgName = intent.getPackage();
if (pkgName == null) {
- return mServices.queryIntent(intent, resolvedType, flags, userId);
+ return applyPostServiceResolutionFilter(
+ mServices.queryIntent(intent, resolvedType, flags, userId),
+ instantAppPkgName);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
- return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
- userId);
+ return applyPostServiceResolutionFilter(
+ mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
+ userId),
+ instantAppPkgName);
}
return Collections.emptyList();
}
}
+ private List<ResolveInfo> applyPostServiceResolutionFilter(List<ResolveInfo> resolveInfos,
+ String instantAppPkgName) {
+ // TODO: When adding on-demand split support for non-instant apps, remove this check
+ // and always apply post filtering
+ if (instantAppPkgName == null) {
+ return resolveInfos;
+ }
+ for (int i = resolveInfos.size() - 1; i >= 0; i--) {
+ final ResolveInfo info = resolveInfos.get(i);
+ final boolean isEphemeralApp = info.serviceInfo.applicationInfo.isInstantApp();
+ // allow services that are defined in the provided package
+ if (isEphemeralApp && instantAppPkgName.equals(info.serviceInfo.packageName)) {
+ if (info.serviceInfo.splitName != null
+ && !ArrayUtils.contains(info.serviceInfo.applicationInfo.splitNames,
+ info.serviceInfo.splitName)) {
+ // requested service is defined in a split that hasn't been installed yet.
+ // add the installer to the resolve list
+ if (DEBUG_EPHEMERAL) {
+ Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
+ }
+ final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo);
+ installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
+ info.serviceInfo.packageName, info.serviceInfo.splitName,
+ info.serviceInfo.applicationInfo.versionCode);
+ // make sure this resolver is the default
+ installerInfo.isDefault = true;
+ installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
+ | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
+ // add a non-generic filter
+ installerInfo.filter = new IntentFilter();
+ // load resources from the correct package
+ installerInfo.resolvePackageName = info.getComponentInfo().packageName;
+ resolveInfos.set(i, installerInfo);
+ }
+ continue;
+ }
+ // allow services that have been explicitly exposed to ephemeral apps
+ if (!isEphemeralApp
+ && ((info.serviceInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0)) {
+ continue;
+ }
+ resolveInfos.remove(i);
+ }
+ return resolveInfos;
+ }
+
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentContentProviders(Intent intent,
String resolvedType, int flags, int userId) {
@@ -7066,7 +7162,9 @@ public class PackageManagerService extends IPackageManager.Stub {
private @NonNull List<ResolveInfo> queryIntentContentProvidersInternal(
Intent intent, String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- flags = updateFlagsForResolve(flags, userId, intent, false);
+ final int callingUid = Binder.getCallingUid();
+ flags = updateFlagsForResolve(flags, userId, intent, callingUid,
+ false /*includeInstantApps*/);
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -12401,11 +12499,29 @@ public class PackageManagerService extends IPackageManager.Stub {
if (ps == null) {
return null;
}
+ final PackageUserState userState = ps.readUserState(userId);
ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags,
- ps.readUserState(userId), userId);
+ userState, userId);
if (si == null) {
return null;
}
+ final boolean matchVisibleToInstantApp =
+ (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+ final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+ // throw out filters that aren't visible to ephemeral apps
+ if (matchVisibleToInstantApp
+ && !(info.isVisibleToInstantApp() || userState.instantApp)) {
+ return null;
+ }
+ // throw out ephemeral filters if we're not explicitly requesting them
+ if (!isInstantApp && userState.instantApp) {
+ return null;
+ }
+ // throw out instant app filters if updates are available; will trigger
+ // instant app resolution
+ if (userState.instantApp && ps.isUpdateAvailable()) {
+ return null;
+ }
final ResolveInfo res = new ResolveInfo();
res.serviceInfo = si;
if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
@@ -23135,10 +23251,18 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
}
}
+ @Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
return resolveIntentInternal(
- intent, resolvedType, flags, userId, true /*includeInstantApp*/);
+ intent, resolvedType, flags, userId, true /*includeInstantApps*/);
+ }
+
+ @Override
+ public ResolveInfo resolveService(Intent intent, String resolvedType,
+ int flags, int userId, int callingUid) {
+ return resolveServiceInternal(
+ intent, resolvedType, flags, userId, callingUid, true /*includeInstantApps*/);
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 8739089552e4..6fb056a48f7e 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3375,7 +3375,7 @@ final class Settings {
private void applyDefaultPreferredActivityLPw(PackageManagerService service,
Intent intent, int flags, ComponentName cn, String scheme, PatternMatcher ssp,
IntentFilter.AuthorityEntry auth, PatternMatcher path, int userId) {
- flags = service.updateFlagsForResolve(flags, userId, intent, false);
+ flags = service.updateFlagsForResolve(flags, userId, intent, Binder.getCallingUid(), false);
List<ResolveInfo> ri = service.mActivities.queryIntent(intent,
intent.getType(), flags, 0);
if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Queried " + intent
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 6f7e0de4b8ee..5035e6820be8 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -20,7 +20,6 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
@@ -32,7 +31,6 @@ import android.util.Log;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.pm.ShortcutService.ShortcutOperation;
@@ -70,9 +68,6 @@ class ShortcutPackage extends ShortcutPackageItem {
private static final String TAG_EXTRAS = "extras";
private static final String TAG_SHORTCUT = "shortcut";
private static final String TAG_CATEGORIES = "categories";
- private static final String TAG_CHOOSER_EXTRAS = "chooser-extras";
- private static final String TAG_CHOOSER_INTENT_FILTERS = "chooser-intent-filters";
- private static final String TAG_CHOOSER_COMPONENT_NAMES = "chooser-component-names";
private static final String ATTR_NAME = "name";
private static final String ATTR_CALL_COUNT = "call-count";
@@ -96,7 +91,6 @@ class ShortcutPackage extends ShortcutPackageItem {
private static final String ATTR_ICON_RES_ID = "icon-res";
private static final String ATTR_ICON_RES_NAME = "icon-resname";
private static final String ATTR_BITMAP_PATH = "bitmap-path";
- private static final String ATTR_COMPONENT_NAMES = "component-names";
private static final String NAME_CATEGORIES = "categories";
@@ -206,7 +200,7 @@ class ShortcutPackage extends ShortcutPackageItem {
if (shortcut != null) {
mShortcutUser.mService.removeIcon(getPackageUserId(), shortcut);
shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED
- | ShortcutInfo.FLAG_MANIFEST | ShortcutInfo.FLAG_CHOOSER);
+ | ShortcutInfo.FLAG_MANIFEST);
}
return shortcut;
}
@@ -232,7 +226,7 @@ class ShortcutPackage extends ShortcutPackageItem {
Preconditions.checkArgument(newShortcut.isEnabled(),
"add/setDynamicShortcuts() cannot publish disabled shortcuts");
- addCorrectDynamicFlags(newShortcut);
+ newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
@@ -256,17 +250,6 @@ class ShortcutPackage extends ShortcutPackageItem {
addShortcutInner(newShortcut);
}
- // TODO: Sample code & JavaDoc for ShortcutManager needs updating to reflect the fact that
- // Chooser shortcuts are not always dynamic.
- public void addCorrectDynamicFlags(@NonNull ShortcutInfo shortcut) {
- if (shortcut.getIntent() != null) {
- shortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
- }
- if (!ArrayUtils.isEmpty(shortcut.getChooserIntentFilters())) {
- shortcut.addFlags(ShortcutInfo.FLAG_CHOOSER);
- }
- }
-
/**
* Remove all shortcuts that aren't pinned nor dynamic.
*/
@@ -299,11 +282,11 @@ class ShortcutPackage extends ShortcutPackageItem {
boolean changed = false;
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
- if (si.isDynamic() || si.isChooser()) {
+ if (si.isDynamic()) {
changed = true;
si.setTimestamp(now);
- si.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_CHOOSER);
+ si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
si.setRank(0); // It may still be pinned, so clear the rank.
}
}
@@ -372,8 +355,7 @@ class ShortcutPackage extends ShortcutPackageItem {
if (oldShortcut.isPinned()) {
oldShortcut.setRank(0);
- oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST
- | ShortcutInfo.FLAG_CHOOSER);
+ oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
if (disable) {
oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
}
@@ -1133,8 +1115,8 @@ class ShortcutPackage extends ShortcutPackageItem {
// Don't adjust ranks for manifest shortcuts.
continue;
}
- // At this point, it must be dynamic or a chooser.
- if (!si.isDynamicOrChooser()) {
+ // At this point, it must be dynamic.
+ if (!si.isDynamic()) {
s.wtf("Non-dynamic shortcut found.");
continue;
}
@@ -1311,7 +1293,7 @@ class ShortcutPackage extends ShortcutPackageItem {
ShortcutService.writeAttr(out, ATTR_FLAGS,
si.getFlags() &
~(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES
- | ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_CHOOSER));
+ | ShortcutInfo.FLAG_DYNAMIC));
} else {
// When writing for backup, ranks shouldn't be saved, since shortcuts won't be restored
// as dynamic.
@@ -1334,36 +1316,15 @@ class ShortcutPackage extends ShortcutPackageItem {
}
final Intent[] intentsNoExtras = si.getIntentsNoExtras();
final PersistableBundle[] intentsExtras = si.getIntentPersistableExtrases();
- if (intentsNoExtras != null) {
- final int numIntents = intentsNoExtras.length;
- for (int i = 0; i < numIntents; i++) {
- out.startTag(null, TAG_INTENT);
- ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
- ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
- out.endTag(null, TAG_INTENT);
- }
- }
- ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
-
- ShortcutService.writeTagExtra(out, TAG_CHOOSER_EXTRAS, si.getChooserExtras());
-
- final IntentFilter[] intentFilters = si.getChooserIntentFilters();
- if (intentFilters != null) {
- for (int i = 0; i < intentFilters.length; i++) {
- out.startTag(null, TAG_CHOOSER_INTENT_FILTERS);
- intentFilters[i].writeToXml(out);
- out.endTag(null, TAG_CHOOSER_INTENT_FILTERS);
- }
+ final int numIntents = intentsNoExtras.length;
+ for (int i = 0; i < numIntents; i++) {
+ out.startTag(null, TAG_INTENT);
+ ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
+ ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
+ out.endTag(null, TAG_INTENT);
}
- final ComponentName[] componentNames = si.getChooserComponentNames();
- if (componentNames != null) {
- for (int i = 0; i < componentNames.length; i++) {
- out.startTag(null, TAG_CHOOSER_COMPONENT_NAMES);
- ShortcutService.writeAttr(out, ATTR_COMPONENT_NAMES, componentNames[i]);
- out.endTag(null, TAG_CHOOSER_COMPONENT_NAMES);
- }
- }
+ ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
out.endTag(null, TAG_SHORTCUT);
}
@@ -1436,9 +1397,6 @@ class ShortcutPackage extends ShortcutPackageItem {
String iconResName;
String bitmapPath;
ArraySet<String> categories = null;
- PersistableBundle chooserExtras;
- List<IntentFilter> chooserIntentFilters = new ArrayList<>();
- List<ComponentName> chooserComponentNames = new ArrayList<>();
id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
activityComponent = ShortcutService.parseComponentNameAttribute(parser,
@@ -1499,18 +1457,6 @@ class ShortcutPackage extends ShortcutPackageItem {
}
}
continue;
- case TAG_CHOOSER_EXTRAS:
- chooserExtras = PersistableBundle.restoreFromXml(parser);
- continue;
- case TAG_CHOOSER_COMPONENT_NAMES:
- chooserComponentNames.add(ShortcutService.parseComponentNameAttribute(parser,
- ATTR_ACTIVITY));
- continue;
- case TAG_CHOOSER_INTENT_FILTERS:
- IntentFilter toAdd = new IntentFilter();
- toAdd.readFromXml(parser);
- chooserIntentFilters.add(toAdd);
- continue;
}
throw ShortcutService.throwForInvalidTag(depth, tag);
}
@@ -1604,10 +1550,10 @@ class ShortcutPackage extends ShortcutPackageItem {
// Verify each shortcut's status.
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
- if (!(si.isDeclaredInManifest() || si.isDynamicOrChooser() || si.isPinned())) {
+ if (!(si.isDeclaredInManifest() || si.isDynamic() || si.isPinned())) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
- + " is not manifest, dynamic, chooser or pinned.");
+ + " is not manifest, dynamic or pinned.");
}
if (si.isDeclaredInManifest() && si.isDynamic()) {
failed = true;
@@ -1649,11 +1595,6 @@ class ShortcutPackage extends ShortcutPackageItem {
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " has a dummy target activity");
}
- if (si.getIntent() == null && !si.isChooser()) {
- failed = true;
- Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
- + " has a null intent, but is not a chooser");
- }
}
if (failed) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 9bf689527864..7c89e1ccb7c8 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -27,7 +27,6 @@ import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -65,7 +64,6 @@ import android.os.FileUtils;
import android.os.Handler;
import android.os.LocaleList;
import android.os.Looper;
-import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.Process;
@@ -1754,7 +1752,6 @@ public class ShortcutService extends IShortcutService.Stub {
ps.clearAllImplicitRanks();
assignImplicitRanks(newShortcuts);
- // TODO: Consider removing Chooser fields. If so, the FLAG_CHOOSER should be removed
for (int i = 0; i < size; i++) {
final ShortcutInfo source = newShortcuts.get(i);
fixUpIncomingShortcutInfo(source, /* forUpdate= */ true);
@@ -1794,13 +1791,6 @@ public class ShortcutService extends IShortcutService.Stub {
if (replacingIcon || source.hasStringResources()) {
fixUpShortcutResourceNamesAndValues(target);
}
-
- // While updating, we keep the dynamic flag as it previously was, but refresh the
- // chooser flag.
- // TODO: If we support clearing Chooser fields, we should also remove the flag.
- if (target.getChooserIntentFilters() != null) {
- target.addFlags(ShortcutInfo.FLAG_CHOOSER);
- }
}
// Lastly, adjust the ranks.
@@ -1864,7 +1854,6 @@ public class ShortcutService extends IShortcutService.Stub {
return true;
}
- // TODO: Ensure non-launchable shortcuts can not be pinned
@Override
public boolean requestPinShortcut(String packageName, ShortcutInfo shortcut,
IntentSender resultIntent, int userId) {
@@ -2020,7 +2009,7 @@ public class ShortcutService extends IShortcutService.Stub {
return getShortcutsWithQueryLocked(
packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
- ShortcutInfo::isDynamicOrChooser);
+ ShortcutInfo::isDynamic);
}
}
@@ -2213,14 +2202,6 @@ public class ShortcutService extends IShortcutService.Stub {
synchronized (mLock) {
throwIfUserLockedL(userId);
- // For the chooser, we just check is the system is calling.
- // STOPSHIP: We need to implement a new permission here rather than this terrible check.
- // The packageName check is to try to distinguish between when an actual
- // launcher is making the call, and when it's the system.
- if (isCallerSystem() && packageName.equals("android")) {
- return true;
- }
-
final ShortcutUser user = getUserShortcutsLocked(userId);
// Always trust the cached component.
@@ -2393,7 +2374,7 @@ public class ShortcutService extends IShortcutService.Stub {
public List<ShortcutInfo> getShortcuts(int launcherUserId,
@NonNull String callingPackage, long changedSince,
@Nullable String packageName, @Nullable List<String> shortcutIds,
- @Nullable ComponentName componentName, @Nullable Intent intent,
+ @Nullable ComponentName componentName,
int queryFlags, int userId) {
final ArrayList<ShortcutInfo> ret = new ArrayList<>();
@@ -2415,13 +2396,13 @@ public class ShortcutService extends IShortcutService.Stub {
if (packageName != null) {
getShortcutsInnerLocked(launcherUserId,
callingPackage, packageName, shortcutIds, changedSince,
- componentName, intent, queryFlags, userId, ret, cloneFlag);
+ componentName, queryFlags, userId, ret, cloneFlag);
} else {
final List<String> shortcutIdsF = shortcutIds;
getUserShortcutsLocked(userId).forAllPackages(p -> {
getShortcutsInnerLocked(launcherUserId,
callingPackage, p.getPackageName(), shortcutIdsF, changedSince,
- componentName, intent, queryFlags, userId, ret, cloneFlag);
+ componentName, queryFlags, userId, ret, cloneFlag);
});
}
}
@@ -2430,7 +2411,7 @@ public class ShortcutService extends IShortcutService.Stub {
private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage,
@Nullable String packageName, @Nullable List<String> shortcutIds, long changedSince,
- @Nullable ComponentName componentName, Intent intent, int queryFlags,
+ @Nullable ComponentName componentName, int queryFlags,
int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
final ArraySet<String> ids = shortcutIds == null ? null
: new ArraySet<>(shortcutIds);
@@ -2455,15 +2436,6 @@ public class ShortcutService extends IShortcutService.Stub {
return false;
}
}
- if (intent != null
- && !si.hasMatchingFilter(mContext.getContentResolver(), intent)) {
- return false;
- }
-
- if (((queryFlags & ShortcutQuery.FLAG_MATCH_CHOOSER) != 0)
- && si.isChooser()) {
- return true;
- }
if (((queryFlags & ShortcutQuery.FLAG_GET_DYNAMIC) != 0)
&& si.isDynamic()) {
return true;
@@ -3449,6 +3421,11 @@ public class ShortcutService extends IShortcutService.Stub {
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
+ dumpNoCheck(fd, pw, args);
+ }
+
+ @VisibleForTesting
+ void dumpNoCheck(FileDescriptor fd, PrintWriter pw, String[] args) {
boolean checkin = false;
boolean clear = false;
if (args != null) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b507df0b8447..7a315ab972e0 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5254,11 +5254,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- // Don't allow snapshots to influence SystemUI visibility flags.
- // TODO: Revisit this once SystemUI flags for snapshots are handled correctly
boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
- && attrs.type < FIRST_SYSTEM_WINDOW
- && (attrs.privateFlags & PRIVATE_FLAG_TASK_SNAPSHOT) == 0;
+ && attrs.type < FIRST_SYSTEM_WINDOW;
final int stackId = win.getStackId();
if (mTopFullscreenOpaqueWindowState == null && visible) {
if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 9c4e700c87d3..a60dae7c7914 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -2671,11 +2671,11 @@ public final class PowerManagerService extends SystemService
public void run() {
synchronized (this) {
if (haltMode == HALT_MODE_REBOOT_SAFE_MODE) {
- ShutdownThread.rebootSafeMode(mContext, confirm);
+ ShutdownThread.rebootSafeMode(getUiContext(), confirm);
} else if (haltMode == HALT_MODE_REBOOT) {
- ShutdownThread.reboot(mContext, reason, confirm);
+ ShutdownThread.reboot(getUiContext(), reason, confirm);
} else {
- ShutdownThread.shutdown(mContext, reason, confirm);
+ ShutdownThread.shutdown(getUiContext(), reason, confirm);
}
}
}
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 841e2a158c4f..864e83ef1f86 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -79,7 +79,7 @@ public final class ShutdownThread extends Thread {
private static final int SHUTDOWN_VIBRATE_MS = 500;
// state tracking
- private static Object sIsStartedGuard = new Object();
+ private static final Object sIsStartedGuard = new Object();
private static boolean sIsStarted = false;
private static boolean mReboot;
@@ -121,7 +121,8 @@ public final class ShutdownThread extends Thread {
* state etc. Must be called from a Looper thread in which its UI
* is shown.
*
- * @param context Context used to display the shutdown progress dialog.
+ * @param context Context used to display the shutdown progress dialog. This must be a context
+ * suitable for displaying UI (aka Themable).
* @param reason code to pass to android_reboot() (e.g. "userrequested"), or null.
* @param confirm true if user confirmation is needed before shutting down.
*/
@@ -132,7 +133,11 @@ public final class ShutdownThread extends Thread {
shutdownInner(context, confirm);
}
- static void shutdownInner(final Context context, boolean confirm) {
+ private static void shutdownInner(final Context context, boolean confirm) {
+ // ShutdownThread is called from many places, so best to verify here that the context passed
+ // in is themed.
+ context.assertRuntimeOverlayThemable();
+
// ensure that only one thread is trying to power down.
// any additional calls are just returned
synchronized (sIsStartedGuard) {
@@ -204,7 +209,8 @@ public final class ShutdownThread extends Thread {
* state etc. Must be called from a Looper thread in which its UI
* is shown.
*
- * @param context Context used to display the shutdown progress dialog.
+ * @param context Context used to display the shutdown progress dialog. This must be a context
+ * suitable for displaying UI (aka Themable).
* @param reason code to pass to the kernel (e.g. "recovery"), or null.
* @param confirm true if user confirmation is needed before shutting down.
*/
@@ -220,7 +226,8 @@ public final class ShutdownThread extends Thread {
* Request a reboot into safe mode. Must be called from a Looper thread in which its UI
* is shown.
*
- * @param context Context used to display the shutdown progress dialog.
+ * @param context Context used to display the shutdown progress dialog. This must be a context
+ * suitable for displaying UI (aka Themable).
* @param confirm true if user confirmation is needed before shutting down.
*/
public static void rebootSafeMode(final Context context, boolean confirm) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 212bd61dbc9a..218d21826d93 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -16,6 +16,7 @@
package com.android.server.statusbar;
+import android.app.ActivityThread;
import android.app.StatusBarManager;
import android.content.ComponentName;
import android.content.Context;
@@ -61,6 +62,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
private static final boolean SPEW = false;
private final Context mContext;
+
private final WindowManagerService mWindowManager;
private Handler mHandler = new Handler();
private NotificationDelegate mNotificationDelegate;
@@ -777,10 +779,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
long identity = Binder.clearCallingIdentity();
try {
mHandler.post(() -> {
+ // ShutdownThread displays UI, so give it a UI context.
+ Context uiContext = ActivityThread.currentActivityThread().getSystemUiContext();
if (safeMode) {
- ShutdownThread.rebootSafeMode(mContext, false);
+ ShutdownThread.rebootSafeMode(uiContext, false);
} else {
- ShutdownThread.reboot(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, false);
+ ShutdownThread.reboot(uiContext, PowerManager.SHUTDOWN_USER_REQUESTED, false);
}
});
} finally {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java b/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
index 963a5723b433..40bb4961a2bf 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
@@ -17,6 +17,8 @@ package com.android.server.statusbar;
import android.content.ComponentName;
import android.os.RemoteException;
import android.os.ShellCommand;
+import android.service.quicksettings.TileService;
+
import com.android.internal.statusbar.IStatusBarService;
import java.io.PrintWriter;
@@ -48,6 +50,10 @@ public class StatusBarShellCommand extends ShellCommand {
return runRemoveTile();
case "click-tile":
return runClickTile();
+ case "check-support":
+ final PrintWriter pw = getOutPrintWriter();
+ pw.println(String.valueOf(TileService.isQuickSettingsSupported()));
+ return 0;
default:
return handleDefaultCommands(cmd);
}
@@ -113,5 +119,8 @@ public class StatusBarShellCommand extends ShellCommand {
pw.println(" click-tile COMPONENT");
pw.println(" Click on a TileService of the specified component");
pw.println("");
+ pw.println(" check-support");
+ pw.println(" Check if this device supports QS + APIs");
+ pw.println("");
}
}
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 4b4be40880ee..2bc3c5f9abba 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -566,7 +566,7 @@ public class AppWindowContainerController
return false;
}
- mContainer.startingData = new SnapshotStartingData(mService, snapshot.getSnapshot());
+ mContainer.startingData = new SnapshotStartingData(mService, snapshot);
scheduleAddStartingWindow();
return true;
}
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 62414e50d0c6..9f0ed2100462 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static com.android.server.wm.AppTransition.DEFAULT_APP_TRANSITION_DURATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -32,7 +31,6 @@ import android.util.ArrayMap;
import android.util.Slog;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
import android.view.WindowManagerInternal;
/**
@@ -111,10 +109,15 @@ public class BoundsAnimationController {
private final boolean mMoveToFullScreen;
// True if this this animation was cancelled and will be replaced the another animation from
// the same {@link #AnimateBoundsUser} target.
- private boolean mWillReplace;
- // True to true if this animation replaced a previous animation of the same
+ private boolean mSkipAnimationEnd;
+ // True if this animation replaced a previous animation of the same
// {@link #AnimateBoundsUser} target.
- private final boolean mReplacement;
+ private final boolean mSkipAnimationStart;
+ // True if this animation is not replacing a previous animation, or if the previous
+ // animation is animating to a different fullscreen state than the current animation.
+ // We use this to ensure that we always provide a consistent set/order of callbacks when we
+ // transition to/from PiP.
+ private final boolean mAnimatingToNewFullscreenState;
// Depending on whether we are animating from
// a smaller to a larger size
@@ -122,13 +125,14 @@ public class BoundsAnimationController {
private final int mFrozenTaskHeight;
BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to, boolean moveToFullScreen,
- boolean replacement) {
+ boolean replacingExistingAnimation, boolean animatingToNewFullscreenState) {
super();
mTarget = target;
mFrom.set(from);
mTo.set(to);
mMoveToFullScreen = moveToFullScreen;
- mReplacement = replacement;
+ mSkipAnimationStart = replacingExistingAnimation;
+ mAnimatingToNewFullscreenState = animatingToNewFullscreenState;
addUpdateListener(this);
addListener(this);
@@ -145,11 +149,32 @@ public class BoundsAnimationController {
}
}
- boolean animatingToLargerSize() {
- if (mFrom.width() * mFrom.height() > mTo.width() * mTo.height()) {
- return false;
+ @Override
+ public void onAnimationStart(Animator animation) {
+ if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
+ + " mSkipAnimationStart=" + mSkipAnimationStart);
+ mFinishAnimationAfterTransition = false;
+ mTmpRect.set(mFrom.left, mFrom.top, mFrom.left + mFrozenTaskWidth,
+ mFrom.top + mFrozenTaskHeight);
+
+ // Ensure that we have prepared the target for animation before
+ // we trigger any size changes, so it can swap surfaces
+ // in to appropriate modes, or do as it wishes otherwise.
+ if (!mSkipAnimationStart) {
+ mTarget.onAnimationStart(mMoveToFullScreen);
+ }
+
+ // If we are animating to a new fullscreen state (either to/from fullscreen), then
+ // notify the target of the change with the new frozen task bounds
+ if (mAnimatingToNewFullscreenState) {
+ mTarget.updatePictureInPictureMode(mMoveToFullScreen ? null : mTo);
+ }
+
+ // Immediately update the task bounds if they have to become larger, but preserve
+ // the starting position so we don't jump at the beginning of the animation.
+ if (animatingToLargerSize()) {
+ mTarget.setPinnedStackSize(mFrom, mTmpRect);
}
- return true;
}
@Override
@@ -174,32 +199,11 @@ public class BoundsAnimationController {
}
}
-
- @Override
- public void onAnimationStart(Animator animation) {
- if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
- + " mReplacement=" + mReplacement);
- mFinishAnimationAfterTransition = false;
- // Ensure that we have prepared the target for animation before
- // we trigger any size changes, so it can swap surfaces
- // in to appropriate modes, or do as it wishes otherwise.
- if (!mReplacement) {
- mTarget.onAnimationStart(mMoveToFullScreen);
- }
-
- // Immediately update the task bounds if they have to become larger, but preserve
- // the starting position so we don't jump at the beginning of the animation.
- if (animatingToLargerSize()) {
- mTmpRect.set(mFrom.left, mFrom.top,
- mFrom.left + mFrozenTaskWidth, mFrom.top + mFrozenTaskHeight);
- mTarget.setPinnedStackSize(mFrom, mTmpRect);
- }
- }
-
@Override
public void onAnimationEnd(Animator animation) {
if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
- + " mMoveToFullScreen=" + mMoveToFullScreen + " mWillReplace=" + mWillReplace);
+ + " mMoveToFullScreen=" + mMoveToFullScreen
+ + " mSkipAnimationEnd=" + mSkipAnimationEnd);
// There could be another animation running. For example in the
// move to fullscreen case, recents will also be closing while the
@@ -214,7 +218,7 @@ public class BoundsAnimationController {
finishAnimation();
mTarget.setPinnedStackSize(mTo, null);
- if (mMoveToFullScreen && !mWillReplace) {
+ if (mMoveToFullScreen && !mSkipAnimationEnd) {
mTarget.moveToFullscreen();
}
}
@@ -226,20 +230,27 @@ public class BoundsAnimationController {
@Override
public void cancel() {
- mWillReplace = true;
+ mSkipAnimationEnd = true;
if (DEBUG) Slog.d(TAG, "cancel: willReplace mTarget=" + mTarget);
super.cancel();
}
/** Returns true if the animation target is the same as the input bounds. */
- public boolean isAnimatingTo(Rect bounds) {
+ boolean isAnimatingTo(Rect bounds) {
return mTo.equals(bounds);
}
+ private boolean animatingToLargerSize() {
+ if (mFrom.width() * mFrom.height() > mTo.width() * mTo.height()) {
+ return false;
+ }
+ return true;
+ }
+
private void finishAnimation() {
if (DEBUG) Slog.d(TAG, "finishAnimation: mTarget=" + mTarget
+ " callers" + Debug.getCallers(2));
- if (!mWillReplace) {
+ if (!mSkipAnimationEnd) {
mTarget.onAnimationEnd();
}
removeListener(this);
@@ -249,7 +260,7 @@ public class BoundsAnimationController {
@Override
public void onAnimationRepeat(Animator animation) {
-
+ // Do nothing
}
}
@@ -266,14 +277,27 @@ public class BoundsAnimationController {
boolean setSize(Rect bounds);
/**
* Behaves as setSize, but freezes the bounds of any tasks in the target at taskBounds,
- * to allow for more flexibility during resizing. Only
- * works for the pinned stack at the moment.
+ * to allow for more flexibility during resizing. Only works for the pinned stack at the
+ * moment.
*/
boolean setPinnedStackSize(Rect bounds, Rect taskBounds);
+ /**
+ * Callback for the target to inform it that the animation has started, so it can do some
+ * necessary preparation.
+ */
void onAnimationStart(boolean toFullscreen);
/**
+ * Callback for the target to inform it that the animation is going to a new fullscreen
+ * state and should update the picture-in-picture mode accordingly.
+ *
+ * @param targetStackBounds the target stack bounds we are animating to, can be null if
+ * we are animating to fullscreen
+ */
+ void updatePictureInPictureMode(Rect targetStackBounds);
+
+ /**
* Callback for the target to inform it that the animation has ended, so it can do some
* necessary cleanup.
*/
@@ -286,9 +310,12 @@ public class BoundsAnimationController {
boolean moveToFullscreen) {
final BoundsAnimator existing = mRunningAnimations.get(target);
final boolean replacing = existing != null;
+ final boolean animatingToNewFullscreenState = (existing == null) ||
+ (existing.mMoveToFullScreen != moveToFullscreen);
if (DEBUG) Slog.d(TAG, "animateBounds: target=" + target + " from=" + from + " to=" + to
- + " moveToFullscreen=" + moveToFullscreen + " replacing=" + replacing);
+ + " moveToFullscreen=" + moveToFullscreen + " replacing=" + replacing
+ + " animatingToNewFullscreenState=" + animatingToNewFullscreenState);
if (replacing) {
if (existing.isAnimatingTo(to)) {
@@ -300,8 +327,8 @@ public class BoundsAnimationController {
}
existing.cancel();
}
- final BoundsAnimator animator =
- new BoundsAnimator(target, from, to, moveToFullscreen, replacing);
+ final BoundsAnimator animator = new BoundsAnimator(target, from, to, moveToFullscreen,
+ replacing, animatingToNewFullscreenState);
mRunningAnimations.put(target, animator);
animator.setFloatValues(0f, 1f);
animator.setDuration((animationDuration != -1 ? animationDuration
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ae413e5eb9fd..4ebf1fcb7206 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -180,11 +180,23 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// Mapping from a token IBinder to a WindowToken object on this display.
private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
+ // Initial display metrics.
int mInitialDisplayWidth = 0;
int mInitialDisplayHeight = 0;
int mInitialDisplayDensity = 0;
+
+ /**
+ * Overridden display size. Initialized with {@link #mInitialDisplayWidth}
+ * and {@link #mInitialDisplayHeight}, but can be set via shell command "adb shell wm size".
+ * @see WindowManagerService#setForcedDisplaySize(int, int, int)
+ */
int mBaseDisplayWidth = 0;
int mBaseDisplayHeight = 0;
+ /**
+ * Overridden display density for current user. Initialized with {@link #mInitialDisplayDensity}
+ * but can be set from Settings or via shell command "adb shell wm density".
+ * @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int)
+ */
int mBaseDisplayDensity = 0;
boolean mDisplayScalingDisabled;
private final DisplayInfo mDisplayInfo = new DisplayInfo();
@@ -1134,6 +1146,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
config.screenHeightDp =
(int)(mService.mPolicy.getConfigDisplayHeight(dw, dh, displayInfo.rotation,
config.uiMode, mDisplayId) / mDisplayMetrics.density);
+
+ mService.mPolicy.getNonDecorInsetsLw(displayInfo.rotation, dw, dh, mTmpRect);
+ final int leftInset = mTmpRect.left;
+ final int topInset = mTmpRect.top;
+ // appBounds at the root level should mirror the app screen size.
+ config.setAppBounds(leftInset /*left*/, topInset /*top*/, leftInset + displayInfo.appWidth /*right*/,
+ topInset + displayInfo.appHeight /*bottom*/);
final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90
|| displayInfo.rotation == Surface.ROTATION_270);
@@ -1490,8 +1509,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
void updateDisplayInfo() {
+ // Check if display metrics changed and update base values if needed.
+ updateBaseDisplayMetricsIfNeeded();
+
mDisplay.getDisplayInfo(mDisplayInfo);
mDisplay.getMetrics(mDisplayMetrics);
+
for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
mTaskStackContainers.get(i).updateDisplayInfo(null);
}
@@ -1507,10 +1530,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
}
- mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
- mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
- mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
- mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
+ updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
+ mDisplayInfo.logicalDensityDpi);
+ mInitialDisplayWidth = mDisplayInfo.logicalWidth;
+ mInitialDisplayHeight = mDisplayInfo.logicalHeight;
+ mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
}
void getLogicalDisplayRect(Rect out) {
@@ -1540,6 +1564,42 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
}
+ /**
+ * If display metrics changed, overrides are not set and it's not just a rotation - update base
+ * values.
+ */
+ private void updateBaseDisplayMetricsIfNeeded() {
+ // Get real display metrics without overrides from WM.
+ mService.mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mDisplayInfo);
+ final int orientation = mDisplayInfo.rotation;
+ final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
+ final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth;
+ final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight;
+ final int newDensity = mDisplayInfo.logicalDensityDpi;
+
+ final boolean displayMetricsChanged = mInitialDisplayWidth != newWidth
+ || mInitialDisplayHeight != newHeight
+ || mInitialDisplayDensity != mDisplayInfo.logicalDensityDpi;
+
+ if (displayMetricsChanged) {
+ // Check if display size or density is forced.
+ final boolean isDisplaySizeForced = mBaseDisplayWidth != mInitialDisplayWidth
+ || mBaseDisplayHeight != mInitialDisplayHeight;
+ final boolean isDisplayDensityForced = mBaseDisplayDensity != mInitialDisplayDensity;
+
+ // If there is an override set for base values - use it, otherwise use new values.
+ updateBaseDisplayMetrics(isDisplaySizeForced ? mBaseDisplayWidth : newWidth,
+ isDisplaySizeForced ? mBaseDisplayHeight : newHeight,
+ isDisplayDensityForced ? mBaseDisplayDensity : newDensity);
+
+ // Real display metrics changed, so we should also update initial values.
+ mInitialDisplayWidth = newWidth;
+ mInitialDisplayHeight = newHeight;
+ mInitialDisplayDensity = newDensity;
+ mService.reconfigureDisplayLocked(this);
+ }
+ }
+
/** Sets the maximum width the screen resolution can be */
void setMaxUiWidth(int width) {
if (DEBUG_DISPLAY) {
@@ -2860,7 +2920,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (stack != null) {
stack.getBounds(frame);
}
- } else if (!mutableIncludeFullDisplay.value && !w.mIsWallpaper) {
+
+ // We want to screenshot with the exact bounds of the surface of the app. Thus,
+ // intersect it with the frame.
+ frame.intersect(w.mFrame);
+ }else if (!mutableIncludeFullDisplay.value && !w.mIsWallpaper) {
final Rect wf = w.mFrame;
final Rect cr = w.mContentInsets;
int left = wf.left + cr.left;
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 85eae0212373..e3002563a6fd 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -225,14 +225,25 @@ public class DockedStackDividerController implements DimLayerUser {
mService.mPolicy.getStableInsetsLw(rotation, dw, dh, mTmpRect);
config.unset();
config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
+
+ final int displayId = mDisplayContent.getDisplayId();
+ final int appWidth = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation,
+ baseConfig.uiMode, displayId);
+ final int appHeight = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation,
+ baseConfig.uiMode, displayId);
+ mService.mPolicy.getNonDecorInsetsLw(rotation, dw, dh, mTmpRect);
+ final int leftInset = mTmpRect.left;
+ final int topInset = mTmpRect.top;
+
+ config.setAppBounds(leftInset /*left*/, topInset /*top*/, leftInset + appWidth /*right*/,
+ topInset + appHeight /*bottom*/);
+
config.screenWidthDp = (int)
(mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, baseConfig.uiMode,
- mDisplayContent.getDisplayId()) /
- mDisplayContent.getDisplayMetrics().density);
+ displayId) / mDisplayContent.getDisplayMetrics().density);
config.screenHeightDp = (int)
(mService.mPolicy.getConfigDisplayHeight(dw, dh, rotation, baseConfig.uiMode,
- mDisplayContent.getDisplayId()) /
- mDisplayContent.getDisplayMetrics().density);
+ displayId) / mDisplayContent.getDisplayMetrics().density);
final Context rotationContext = mService.mContext.createConfigurationContext(config);
mSnapAlgorithmForRotation[rotation] = new DividerSnapAlgorithm(
rotationContext.getResources(), dw, dh, getContentWidth(),
diff --git a/services/core/java/com/android/server/wm/SnapshotStartingData.java b/services/core/java/com/android/server/wm/SnapshotStartingData.java
index e73d4d2559fb..35f35db5ada3 100644
--- a/services/core/java/com/android/server/wm/SnapshotStartingData.java
+++ b/services/core/java/com/android/server/wm/SnapshotStartingData.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import android.app.ActivityManager.TaskSnapshot;
import android.graphics.GraphicBuffer;
import android.view.WindowManagerPolicy.StartingSurface;
@@ -25,9 +26,9 @@ import android.view.WindowManagerPolicy.StartingSurface;
class SnapshotStartingData extends StartingData {
private final WindowManagerService mService;
- private final GraphicBuffer mSnapshot;
+ private final TaskSnapshot mSnapshot;
- SnapshotStartingData(WindowManagerService service, GraphicBuffer snapshot) {
+ SnapshotStartingData(WindowManagerService service, TaskSnapshot snapshot) {
super(service);
mService = service;
mSnapshot = snapshot;
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index 8186d30a55ff..635527e68ffe 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -270,6 +270,12 @@ public class StackWindowController
int width;
int height;
+
+ final Rect parentAppBounds = parentConfig.appBounds;
+
+ config.setAppBounds(!bounds.isEmpty() ? bounds : null);
+ boolean intersectParentBounds = false;
+
if (StackId.tasksAreFloating(mStackId)) {
// Floating tasks should not be resized to the screen's bounds.
@@ -280,6 +286,7 @@ public class StackWindowController
// the fullscreen stack, without intersecting it with the display bounds
stableBounds.inset(mTmpStableInsets);
nonDecorBounds.inset(mTmpNonDecorInsets);
+ intersectParentBounds = true;
}
width = (int) (stableBounds.width() / density);
height = (int) (stableBounds.height() / density);
@@ -299,6 +306,11 @@ public class StackWindowController
parentConfig.screenWidthDp);
height = Math.min((int) (stableBounds.height() / density),
parentConfig.screenHeightDp);
+ intersectParentBounds = true;
+ }
+
+ if (intersectParentBounds && config.appBounds != null) {
+ config.appBounds.intersect(parentAppBounds);
}
config.screenWidthDp = width;
@@ -350,6 +362,13 @@ public class StackWindowController
}
}
+ /** Calls directly into activity manager so window manager lock shouldn't held. */
+ public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {
+ if (mListener != null) {
+ mListener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
+ }
+ }
+
void requestResize(Rect bounds) {
mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
}
diff --git a/services/core/java/com/android/server/wm/StackWindowListener.java b/services/core/java/com/android/server/wm/StackWindowListener.java
index c763c175687f..a55f9dfa2d60 100644
--- a/services/core/java/com/android/server/wm/StackWindowListener.java
+++ b/services/core/java/com/android/server/wm/StackWindowListener.java
@@ -26,4 +26,10 @@ public interface StackWindowListener extends WindowContainerListener {
/** Called when the stack container would like its controller to resize. */
void requestResize(Rect bounds);
+
+ /**
+ * Called when the stack container pinned stack animation will change the picture-in-picture
+ * mode. This is a direct call into ActivityManager.
+ */
+ default void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 3ffb093ba386..b816d8199aa6 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -17,15 +17,14 @@
package com.android.server.wm;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static com.android.server.EventLogTags.WM_TASK_REMOVED;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -40,7 +39,6 @@ import android.view.DisplayInfo;
import android.view.Surface;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.EventLogTags;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index b8d0b8c096fe..48b01f40fc65 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -28,6 +28,7 @@ import android.app.ActivityManager.StackId;
import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Canvas;
import android.graphics.GraphicBuffer;
+import android.graphics.Rect;
import android.os.Environment;
import android.util.ArraySet;
import android.view.WindowManagerPolicy.StartingSurface;
@@ -152,7 +153,7 @@ class TaskSnapshotController {
* MANAGER LOCK WHEN CALLING THIS METHOD!
*/
StartingSurface createStartingSurface(AppWindowToken token,
- GraphicBuffer snapshot) {
+ TaskSnapshot snapshot) {
return TaskSnapshotSurface.create(mService, token, snapshot);
}
@@ -166,8 +167,17 @@ class TaskSnapshotController {
if (buffer == null) {
return null;
}
+ final WindowState mainWindow = top.findMainWindow();
return new TaskSnapshot(buffer, top.getConfiguration().orientation,
- top.findMainWindow().mStableInsets, false /* reduced */, 1f /* scale */);
+ minRect(mainWindow.mContentInsets, mainWindow.mStableInsets), false /* reduced */,
+ 1f /* scale */);
+ }
+
+ private Rect minRect(Rect rect1, Rect rect2) {
+ return new Rect(Math.min(rect1.left, rect2.left),
+ Math.min(rect1.top, rect2.top),
+ Math.min(rect1.right, rect2.right),
+ Math.min(rect1.bottom, rect2.bottom));
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 04403e2712c1..1591e480af4f 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -16,20 +16,35 @@
package com.android.server.wm;
-import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+import static android.graphics.Color.WHITE;
+import static android.graphics.Color.alpha;
+import static android.view.SurfaceControl.HIDDEN;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+import static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
+import static android.view.WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
+import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
+import static com.android.internal.policy.DecorView.getColorViewLeftInset;
+import static com.android.internal.policy.DecorView.getColorViewTopInset;
+import static com.android.internal.policy.DecorView.getNavigationBarRect;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.app.ActivityManager.TaskDescription;
-import android.graphics.Bitmap;
+import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.GraphicBuffer;
import android.graphics.Paint;
import android.graphics.Rect;
@@ -37,17 +52,22 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.MergedConfiguration;
import android.util.Slog;
import android.view.IWindowSession;
import android.view.Surface;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicy.StartingSurface;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.DecorView;
import com.android.internal.view.BaseIWindow;
/**
@@ -57,19 +77,57 @@ import com.android.internal.view.BaseIWindow;
*/
class TaskSnapshotSurface implements StartingSurface {
+ private static final long SIZE_MISMATCH_MINIMUM_TIME_MS = 450;
+
+ /**
+ * When creating the starting window, we use the exact same layout flags such that we end up
+ * with a window with the exact same dimensions etc. However, these flags are not used in layout
+ * and might cause other side effects so we exclude them.
+ */
+ private static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE
+ | FLAG_NOT_TOUCHABLE
+ | FLAG_NOT_TOUCH_MODAL
+ | FLAG_ALT_FOCUSABLE_IM
+ | FLAG_NOT_FOCUSABLE
+ | FLAG_HARDWARE_ACCELERATED
+ | FLAG_IGNORE_CHEEK_PRESSES
+ | FLAG_LOCAL_FOCUS_MODE
+ | FLAG_SLIPPERY
+ | FLAG_WATCH_OUTSIDE_TOUCH
+ | FLAG_SPLIT_TOUCH
+ | FLAG_SCALED
+ | FLAG_SECURE;
+
private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
private static final int MSG_REPORT_DRAW = 0;
private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
private final Window mWindow;
private final Surface mSurface;
+ private SurfaceControl mChildSurfaceControl;
private final IWindowSession mSession;
private final WindowManagerService mService;
+ private final Rect mTaskBounds;
+ private final Rect mStableInsets = new Rect();
+ private final Rect mContentInsets = new Rect();
+ private final Rect mFrame = new Rect();
+ private final TaskSnapshot mSnapshot;
+ private final CharSequence mTitle;
private boolean mHasDrawn;
private boolean mReportNextDraw;
- private Paint mFillBackgroundPaint = new Paint();
+ private long mShownTime;
+ private final Handler mHandler;
+ private final boolean mSizeMismatch;
+ private final Paint mBackgroundPaint = new Paint();
+ private final Paint mStatusBarPaint = new Paint();
+ private final Paint mNavigationBarPaint = new Paint();
+ private final int mStatusBarColor;
+ private final int mNavigationBarColor;
+ private final int mSysUiVis;
+ private final int mWindowFlags;
+ private final int mWindowPrivateFlags;
static TaskSnapshotSurface create(WindowManagerService service, AppWindowToken token,
- GraphicBuffer snapshot) {
+ TaskSnapshot snapshot) {
final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
final Window window = new Window();
@@ -78,32 +136,51 @@ class TaskSnapshotSurface implements StartingSurface {
final Surface surface = new Surface();
final Rect tmpRect = new Rect();
final Rect tmpFrame = new Rect();
+ final Rect taskBounds;
+ final Rect tmpContentInsets = new Rect();
+ final Rect tmpStableInsets = new Rect();
final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
- int fillBackgroundColor = Color.WHITE;
+ int backgroundColor = WHITE;
+ int statusBarColor = 0;
+ int navigationBarColor = 0;
+ final int sysUiVis;
+ final int windowFlags;
+ final int windowPrivateFlags;
synchronized (service.mWindowMap) {
+ final WindowState mainWindow = token.findMainWindow();
+ if (mainWindow == null) {
+ Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token="
+ + token);
+ return null;
+ }
+ sysUiVis = mainWindow.getSystemUiVisibility();
+ windowFlags = mainWindow.getAttrs().flags;
+ windowPrivateFlags = mainWindow.getAttrs().privateFlags;
+
layoutParams.type = TYPE_APPLICATION_STARTING;
- layoutParams.format = snapshot.getFormat();
- layoutParams.flags = FLAG_LAYOUT_INSET_DECOR
- | FLAG_LAYOUT_IN_SCREEN
+ layoutParams.format = snapshot.getSnapshot().getFormat();
+ layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
| FLAG_NOT_FOCUSABLE
- | FLAG_NOT_TOUCHABLE
- | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ | FLAG_NOT_TOUCHABLE;
layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT;
layoutParams.token = token.token;
layoutParams.width = LayoutParams.MATCH_PARENT;
layoutParams.height = LayoutParams.MATCH_PARENT;
-
- // TODO: Inherit behavior whether to draw behind status bar/nav bar.
- layoutParams.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ layoutParams.systemUiVisibility = sysUiVis;
final Task task = token.getTask();
if (task != null) {
- layoutParams.setTitle(String.format(TITLE_FORMAT,task.mTaskId));
+ layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
final TaskDescription taskDescription = task.getTaskDescription();
if (taskDescription != null) {
- fillBackgroundColor = taskDescription.getBackgroundColor();
+ backgroundColor = taskDescription.getBackgroundColor();
+ statusBarColor = taskDescription.getStatusBarColor();
+ navigationBarColor = taskDescription.getNavigationBarColor();
}
+ taskBounds = new Rect();
+ task.getBounds(taskBounds);
+ } else {
+ taskBounds = null;
}
}
try {
@@ -118,31 +195,57 @@ class TaskSnapshotSurface implements StartingSurface {
// Local call.
}
final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
- surface, fillBackgroundColor);
+ surface, snapshot, layoutParams.getTitle(), backgroundColor, statusBarColor,
+ navigationBarColor, sysUiVis, windowFlags, windowPrivateFlags, taskBounds);
window.setOuter(snapshotSurface);
try {
session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, tmpFrame,
- tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpMergedConfiguration,
- surface);
+ tmpRect, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect, tmpRect,
+ tmpMergedConfiguration, surface);
} catch (RemoteException e) {
// Local call.
}
- snapshotSurface.drawSnapshot(snapshot);
+ snapshotSurface.setFrames(tmpFrame, tmpContentInsets, tmpStableInsets);
+ snapshotSurface.drawSnapshot();
return snapshotSurface;
}
@VisibleForTesting
TaskSnapshotSurface(WindowManagerService service, Window window, Surface surface,
- int fillBackgroundColor) {
+ TaskSnapshot snapshot, CharSequence title, int backgroundColor, int statusBarColor,
+ int navigationBarColor, int sysUiVis, int windowFlags, int windowPrivateFlags,
+ Rect taskBounds) {
mService = service;
+ mHandler = new Handler(mService.mH.getLooper());
mSession = WindowManagerGlobal.getWindowSession();
mWindow = window;
mSurface = surface;
- mFillBackgroundPaint.setColor(fillBackgroundColor);
+ mSnapshot = snapshot;
+ mTitle = title;
+ mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
+ mTaskBounds = taskBounds;
+ mSysUiVis = sysUiVis;
+ mWindowFlags = windowFlags;
+ mWindowPrivateFlags = windowPrivateFlags;
+ mSizeMismatch = (mFrame.width() != snapshot.getSnapshot().getWidth()
+ || mFrame.height() != snapshot.getSnapshot().getHeight());
+ mStatusBarColor = DecorView.calculateStatusBarColor(windowFlags,
+ service.mContext.getColor(R.color.system_bar_background_semi_transparent),
+ statusBarColor);
+ mNavigationBarColor = navigationBarColor;
+ mStatusBarPaint.setColor(mStatusBarColor);
+ mNavigationBarPaint.setColor(navigationBarColor);
}
@Override
public void remove() {
+ synchronized (mService.mWindowMap) {
+ final long now = SystemClock.uptimeMillis();
+ if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS) {
+ mHandler.postAtTime(this::remove, mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS);
+ return;
+ }
+ }
try {
mSession.remove(mWindow);
} catch (RemoteException e) {
@@ -150,31 +253,149 @@ class TaskSnapshotSurface implements StartingSurface {
}
}
- private void drawSnapshot(GraphicBuffer snapshot) {
- mSurface.attachAndQueueBuffer(snapshot);
+ @VisibleForTesting
+ void setFrames(Rect frame, Rect contentInsets, Rect stableInsets) {
+ mFrame.set(frame);
+ mContentInsets.set(contentInsets);
+ mStableInsets.set(stableInsets);
+ }
+
+ private void drawSnapshot() {
+ final GraphicBuffer buffer = mSnapshot.getSnapshot();
+ if (mSizeMismatch) {
+ // The dimensions of the buffer and the window don't match, so attaching the buffer
+ // will fail. Better create a child window with the exact dimensions and fill the parent
+ // window with the background color!
+ drawSizeMismatchSnapshot(buffer);
+ } else {
+ drawSizeMatchSnapshot(buffer);
+ }
final boolean reportNextDraw;
synchronized (mService.mWindowMap) {
+ mShownTime = SystemClock.uptimeMillis();
mHasDrawn = true;
reportNextDraw = mReportNextDraw;
}
if (reportNextDraw) {
reportDrawn();
}
+ }
+
+ private void drawSizeMatchSnapshot(GraphicBuffer buffer) {
+ mSurface.attachAndQueueBuffer(buffer);
+ mSurface.release();
+ }
+
+ private void drawSizeMismatchSnapshot(GraphicBuffer buffer) {
+ final SurfaceSession session = new SurfaceSession(mSurface);
+
+ // Keep a reference to it such that it doesn't get destroyed when finalized.
+ mChildSurfaceControl = new SurfaceControl(session,
+ mTitle + " - task-snapshot-surface",
+ buffer.getWidth(), buffer.getHeight(), buffer.getFormat(), HIDDEN);
+ Surface surface = new Surface();
+ surface.copyFrom(mChildSurfaceControl);
+
+ // Clip off ugly navigation bar.
+ final Rect crop = calculateSnapshotCrop();
+ final Rect frame = calculateSnapshotFrame(crop);
+ SurfaceControl.openTransaction();
+ try {
+ // We can just show the surface here as it will still be hidden as the parent is
+ // still hidden.
+ mChildSurfaceControl.show();
+ mChildSurfaceControl.setWindowCrop(crop);
+ mChildSurfaceControl.setPosition(frame.left, frame.top);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ surface.attachAndQueueBuffer(buffer);
+ surface.release();
+
+ final Canvas c = mSurface.lockCanvas(null);
+ drawBackgroundAndBars(c, frame);
+ mSurface.unlockCanvasAndPost(c);
mSurface.release();
}
@VisibleForTesting
- void fillEmptyBackground(Canvas c, Bitmap b) {
- final boolean fillHorizontally = c.getWidth() > b.getWidth();
- final boolean fillVertically = c.getHeight() > b.getHeight();
+ Rect calculateSnapshotCrop() {
+ final Rect rect = new Rect();
+ rect.set(0, 0, mSnapshot.getSnapshot().getWidth(), mSnapshot.getSnapshot().getHeight());
+ final Rect insets = mSnapshot.getContentInsets();
+
+ // Let's remove all system decorations except the status bar, but only if the task is at the
+ // very top of the screen.
+ rect.inset(insets.left, mTaskBounds.top != 0 ? insets.top : 0, insets.right, insets.bottom);
+ return rect;
+ }
+
+ @VisibleForTesting
+ Rect calculateSnapshotFrame(Rect crop) {
+ final Rect frame = new Rect(crop);
+
+ // By default, offset it to to top/left corner
+ frame.offsetTo(-crop.left, -crop.top);
+
+ // However, we also need to make space for the navigation bar on the left side.
+ final int colorViewLeftInset = getColorViewLeftInset(mStableInsets.left,
+ mContentInsets.left);
+ frame.offset(colorViewLeftInset, 0);
+ return frame;
+ }
+
+ @VisibleForTesting
+ void drawBackgroundAndBars(Canvas c, Rect frame) {
+ final int statusBarHeight = getStatusBarColorViewHeight();
+ final boolean fillHorizontally = c.getWidth() > frame.right;
+ final boolean fillVertically = c.getHeight() > frame.bottom;
if (fillHorizontally) {
- c.drawRect(b.getWidth(), 0, c.getWidth(), fillVertically
- ? b.getHeight()
- : c.getHeight(),
- mFillBackgroundPaint);
+ c.drawRect(frame.right, alpha(mStatusBarColor) == 0xFF ? statusBarHeight : 0,
+ c.getWidth(), fillVertically
+ ? frame.bottom
+ : c.getHeight(),
+ mBackgroundPaint);
}
if (fillVertically) {
- c.drawRect(0, b.getHeight(), c.getWidth(), c.getHeight(), mFillBackgroundPaint);
+ c.drawRect(0, frame.bottom, c.getWidth(), c.getHeight(), mBackgroundPaint);
+ }
+ drawStatusBarBackground(c, frame, statusBarHeight);
+ drawNavigationBarBackground(c);
+ }
+
+ private int getStatusBarColorViewHeight() {
+ final boolean forceStatusBarBackground =
+ (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
+ if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mSysUiVis, mStatusBarColor, mWindowFlags, forceStatusBarBackground)) {
+ return getColorViewTopInset(mStableInsets.top, mContentInsets.top);
+ } else {
+ return 0;
+ }
+ }
+
+ private boolean isNavigationBarColorViewVisible() {
+ return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mSysUiVis, mNavigationBarColor, mWindowFlags, false /* force */);
+ }
+
+ @VisibleForTesting
+ void drawStatusBarBackground(Canvas c, Rect frame, int statusBarHeight) {
+ if (statusBarHeight > 0 && c.getWidth() > frame.right) {
+ final int rightInset = DecorView.getColorViewRightInset(mStableInsets.right,
+ mContentInsets.right);
+ c.drawRect(frame.right, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
+ }
+ }
+
+ @VisibleForTesting
+ void drawNavigationBarBackground(Canvas c) {
+ final Rect navigationBarRect = new Rect();
+ getNavigationBarRect(c.getWidth(), c.getHeight(), mStableInsets, mContentInsets,
+ navigationBarRect);
+ final boolean visible = isNavigationBarColorViewVisible();
+ if (visible && !navigationBarRect.isEmpty()) {
+ c.drawRect(navigationBarRect, mNavigationBarPaint);
}
}
@@ -211,10 +432,10 @@ class TaskSnapshotSurface implements StartingSurface {
}
};
- private static class Window extends BaseIWindow {
+ @VisibleForTesting
+ static class Window extends BaseIWindow {
private TaskSnapshotSurface mOuter;
-
public void setOuter(TaskSnapshotSurface outer) {
mOuter = outer;
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 8b5f5acc5c28..1a67ac73021d 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1483,6 +1483,14 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
}
@Override // AnimatesBounds
+ public void updatePictureInPictureMode(Rect targetStackBounds) {
+ final StackWindowController controller = getController();
+ if (controller != null) {
+ controller.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
+ }
+ }
+
+ @Override // AnimatesBounds
public void onAnimationEnd() {
synchronized (mService.mWindowMap) {
mBoundsAnimating = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 95fbbb89a649..f1796de2d342 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -102,6 +102,7 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityManagerInternal;
+import android.app.ActivityThread;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.content.BroadcastReceiver;
@@ -3196,19 +3197,25 @@ public class WindowManagerService extends IWindowManager.Stub
// Called by window manager policy. Not exposed externally.
@Override
public void shutdown(boolean confirm) {
- ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
+ // Pass in the UI context, since ShutdownThread requires it (to show UI).
+ ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
+ PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
}
// Called by window manager policy. Not exposed externally.
@Override
public void reboot(boolean confirm) {
- ShutdownThread.reboot(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
+ // Pass in the UI context, since ShutdownThread requires it (to show UI).
+ ShutdownThread.reboot(ActivityThread.currentActivityThread().getSystemUiContext(),
+ PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
}
// Called by window manager policy. Not exposed externally.
@Override
public void rebootSafeMode(boolean confirm) {
- ShutdownThread.rebootSafeMode(mContext, confirm);
+ // Pass in the UI context, since ShutdownThread requires it (to show UI).
+ ShutdownThread.rebootSafeMode(ActivityThread.currentActivityThread().getSystemUiContext(),
+ confirm);
}
public void setCurrentProfileIds(final int[] currentProfileIds) {
@@ -5312,8 +5319,8 @@ public class WindowManagerService extends IWindowManager.Stub
if (displayContent.mBaseDisplayWidth != width
|| displayContent.mBaseDisplayHeight != height) {
Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
- displayContent.mBaseDisplayWidth = width;
- displayContent.mBaseDisplayHeight = height;
+ displayContent.updateBaseDisplayMetrics(width, height,
+ displayContent.mBaseDisplayDensity);
}
} catch (NumberFormatException ex) {
}
@@ -5338,8 +5345,7 @@ public class WindowManagerService extends IWindowManager.Stub
// displayContent must not be null
private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
- displayContent.mBaseDisplayWidth = width;
- displayContent.mBaseDisplayHeight = height;
+ displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity);
reconfigureDisplayLocked(displayContent);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java
new file mode 100644
index 000000000000..97fa9d552142
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.devicepolicy;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.admin.DevicePolicyManager;
+import android.app.admin.IDeviceAdminService;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.BackgroundThread;
+import com.android.server.am.PersistentConnection;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * Manages connections to persistent services in owner packages.
+ */
+public class DeviceAdminServiceController {
+ static final String TAG = DevicePolicyManagerService.LOG_TAG;
+
+ static final boolean DEBUG = false; // DO NOT MERGE WITH TRUE.
+
+ final Object mLock = new Object();
+ final Context mContext;
+
+ private final DevicePolicyManagerService mService;
+ private final DevicePolicyManagerService.Injector mInjector;
+
+ private final Handler mHandler; // needed?
+
+ static void debug(String format, Object... args) {
+ if (!DEBUG) {
+ return;
+ }
+ Slog.d(TAG, String.format(format, args));
+ }
+
+ private class DevicePolicyServiceConnection
+ extends PersistentConnection<IDeviceAdminService> {
+ public DevicePolicyServiceConnection(int userId, @NonNull ComponentName componentName) {
+ super(TAG, mContext, mHandler, userId, componentName);
+ }
+
+ @Override
+ protected IDeviceAdminService asInterface(IBinder binder) {
+ return IDeviceAdminService.Stub.asInterface(binder);
+ }
+ }
+
+ /**
+ * User-ID -> {@link PersistentConnection}.
+ */
+ @GuardedBy("mLock")
+ private final SparseArray<DevicePolicyServiceConnection> mConnections = new SparseArray<>();
+
+ public DeviceAdminServiceController(DevicePolicyManagerService service) {
+ mService = service;
+ mInjector = service.mInjector;
+ mContext = mInjector.mContext;
+ mHandler = new Handler(BackgroundThread.get().getLooper());
+ }
+
+ /**
+ * Find a service that handles {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE}
+ * in a given package.
+ */
+ @Nullable
+ private ServiceInfo findService(@NonNull String packageName, int userId) {
+ final Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE);
+ intent.setPackage(packageName);
+
+ try {
+ final ParceledListSlice<ResolveInfo> pls = mInjector.getIPackageManager()
+ .queryIntentServices(intent, null, /* flags=*/ 0, userId);
+ if (pls == null) {
+ return null;
+ }
+ final List<ResolveInfo> list = pls.getList();
+ if (list.size() == 0) {
+ return null;
+ }
+ // Note if multiple services are found, that's an error, even if only one of them
+ // is exported.
+ if (list.size() > 1) {
+ Log.e(TAG, "More than one DeviceAdminService's found in package "
+ + packageName
+ + ". They'll all be ignored.");
+ return null;
+ }
+ final ServiceInfo si = list.get(0).serviceInfo;
+ if (si.exported) {
+ Log.e(TAG, "DeviceAdminService must not be exported: '"
+ + si.getComponentName().flattenToShortString()
+ + "' will be ignored.");
+ return null;
+ }
+ return si;
+ } catch (RemoteException e) {
+ }
+ return null;
+ }
+
+ /**
+ * Find a service that handles {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE}
+ * in an owner package and connect to it.
+ */
+ public void startServiceForOwner(@NonNull String packageName, int userId,
+ @NonNull String actionForLog) {
+ final long token = mInjector.binderClearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ final ServiceInfo service = findService(packageName, userId);
+ if (service == null) {
+ debug("Owner package %s on u%d has no service.",
+ packageName, userId);
+ disconnectServiceOnUserLocked(userId, actionForLog);
+ return;
+ }
+ // See if it's already running.
+ final PersistentConnection<IDeviceAdminService> existing =
+ mConnections.get(userId);
+ if (existing != null) {
+ if (existing.getComponentName().equals(service.getComponentName())) {
+ return;
+ }
+ disconnectServiceOnUserLocked(userId, actionForLog);
+ }
+
+ debug("Owner package %s on u%d has service %s for %s",
+ packageName, userId,
+ service.getComponentName().flattenToShortString(), actionForLog);
+
+ final DevicePolicyServiceConnection conn =
+ new DevicePolicyServiceConnection(
+ userId, service.getComponentName());
+ mConnections.put(userId, conn);
+ conn.connect();
+ }
+ } finally {
+ mInjector.binderRestoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Stop an owner service on a given user.
+ */
+ public void stopServiceForOwner(int userId, @NonNull String actionForLog) {
+ final long token = mInjector.binderClearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ disconnectServiceOnUserLocked(userId, actionForLog);
+ }
+ } finally {
+ mInjector.binderRestoreCallingIdentity(token);
+ }
+ }
+
+ private void disconnectServiceOnUserLocked(int userId, @NonNull String actionForLog) {
+ final DevicePolicyServiceConnection conn = mConnections.get(userId);
+ if (conn != null) {
+ debug("Stopping service for u%d if already running for %s.",
+ userId, actionForLog);
+ conn.disconnect();
+ mConnections.remove(userId);
+ }
+ }
+
+ public void dump(String prefix, PrintWriter pw) {
+ synchronized (mLock) {
+ if (mConnections.size() == 0) {
+ return;
+ }
+ pw.println();
+ pw.print(prefix); pw.println("Owner Services:");
+ for (int i = 0; i < mConnections.size(); i++) {
+ final int userId = mConnections.keyAt(i);
+ pw.print(prefix); pw.print(" "); pw.print("User: "); pw.println(userId);
+
+ final DevicePolicyServiceConnection con = mConnections.valueAt(i);
+ con.dump(prefix + " ", pw);
+ }
+ }
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6f49324bfc56..bfa1b9988b2f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -140,7 +140,6 @@ import android.os.storage.StorageManager;
import android.provider.ContactsContract.QuickContact;
import android.provider.ContactsInternal;
import android.provider.Settings;
-import android.security.Credentials;
import android.security.IKeyChainAliasCallback;
import android.security.IKeyChainService;
import android.security.KeyChain;
@@ -194,7 +193,6 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
-import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -365,6 +363,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final UserManagerInternal mUserManagerInternal;
final TelephonyManager mTelephonyManager;
private final LockPatternUtils mLockPatternUtils;
+ private final DeviceAdminServiceController mDeviceAdminServiceController;
/**
* Contains (package-user) pairs to remove. An entry (p, u) implies that removal of package p
@@ -459,7 +458,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public void onStartUser(int userHandle) {
- mService.onStartUser(userHandle);
+ mService.handleStartUser(userHandle);
+ }
+
+ @Override
+ public void onUnlockUser(int userHandle) {
+ mService.handleUnlockUser(userHandle);
+ }
+
+ @Override
+ public void onStopUser(int userHandle) {
+ mService.handleStopUser(userHandle);
}
}
@@ -1420,7 +1429,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- private void handlePackagesChanged(String packageName, int userHandle) {
+ private void handlePackagesChanged(@Nullable String packageName, int userHandle) {
boolean removedAdmin = false;
if (VERBOSE_LOG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
DevicePolicyData policy = getUserData(userHandle);
@@ -1434,9 +1443,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (packageName == null || packageName.equals(adminPackage)) {
if (mIPackageManager.getPackageInfo(adminPackage, 0, userHandle) == null
|| mIPackageManager.getReceiverInfo(aa.info.getComponent(),
- PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- userHandle) == null) {
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+ userHandle) == null) {
removedAdmin = true;
policy.mAdminList.remove(i);
policy.mAdminMap.remove(aa.info.getComponent());
@@ -1461,6 +1470,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
+ // If it's an owner package, we may need to refresh the bound connection.
+ final ComponentName owner = getOwnerComponent(userHandle);
+ if ((packageName != null) && (owner != null)
+ && (owner.getPackageName().equals(packageName))) {
+ startOwnerService(userHandle, "package-broadcast");
+ }
+
// Persist updates if the removed package was an admin or delegate.
if (removedAdmin || removedDelegate) {
saveSettingsLocked(policy.mUserHandle);
@@ -1791,6 +1807,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Needed when mHasFeature == false, because it controls the certificate warning text.
mCertificateMonitor = new CertificateMonitor(this, mInjector, mBackgroundHandler);
+ mDeviceAdminServiceController = new DeviceAdminServiceController(this);
+
if (!mHasFeature) {
// Skip the rest of the initialization
return;
@@ -2943,7 +2961,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
loadOwners();
cleanUpOldUsers();
ensureUnknownSourcesRestrictionForProfileOwners();
- onStartUser(UserHandle.USER_SYSTEM);
+ handleStartUser(UserHandle.USER_SYSTEM);
// Register an observer for watching for user setup complete and settings changes.
mSetupContentObserver.register();
@@ -2990,10 +3008,32 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- private void onStartUser(int userId) {
+ void handleStartUser(int userId) {
updateScreenCaptureDisabledInWindowManager(userId,
getScreenCaptureDisabled(null, userId));
pushUserRestrictions(userId);
+
+ startOwnerService(userId, "start-user");
+ }
+
+ void handleUnlockUser(int userId) {
+ startOwnerService(userId, "unlock-user");
+ }
+
+ void handleStopUser(int userId) {
+ stopOwnerService(userId, "stop-user");
+ }
+
+ private void startOwnerService(int userId, String actionForLog) {
+ final ComponentName owner = getOwnerComponent(userId);
+ if (owner != null) {
+ mDeviceAdminServiceController.startServiceForOwner(
+ owner.getPackageName(), userId, actionForLog);
+ }
+ }
+
+ private void stopOwnerService(int userId, String actionForLog) {
+ mDeviceAdminServiceController.stopServiceForOwner(userId, actionForLog);
}
private void cleanUpOldUsers() {
@@ -5078,7 +5118,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* @param callerPackage the name of the calling package. Required if {@code who} is
* {@code null}.
* @param reqPolicy the policy used in the API whose access permission is being checked.
- * @param scoppe the delegation scope corresponding to the API being checked.
+ * @param scope the delegation scope corresponding to the API being checked.
* @throws SecurityException if {@code who} is given and is not an owner for {@code reqPolicy};
* or when {@code who} is {@code null} and {@code callerPackage} is not a delegate
* of {@code scope}.
@@ -6460,6 +6500,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
+ mDeviceAdminServiceController.startServiceForOwner(
+ admin.getPackageName(), userId, "set-device-owner");
+
Slog.i(LOG_TAG, "Device owner set: " + admin + " on user " + userId);
return true;
}
@@ -6615,6 +6658,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private void clearDeviceOwnerLocked(ActiveAdmin admin, int userId) {
+ mDeviceAdminServiceController.stopServiceForOwner(userId, "clear-device-owner");
+
if (admin != null) {
admin.disableCamera = false;
admin.userRestrictions = null;
@@ -6692,6 +6737,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
+ mDeviceAdminServiceController.startServiceForOwner(
+ who.getPackageName(), userHandle, "set-profile-owner");
return true;
}
}
@@ -6723,6 +6770,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
public void clearProfileOwnerLocked(ActiveAdmin admin, int userId) {
+ mDeviceAdminServiceController.stopServiceForOwner(userId, "clear-profile-owner");
+
if (admin != null) {
admin.disableCamera = false;
admin.userRestrictions = null;
@@ -7275,6 +7324,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
pw.println("Current Device Policy Manager state:");
mOwners.dump(" ", pw);
+ mDeviceAdminServiceController.dump(" ", pw);
int userCount = mUserData.size();
for (int u = 0; u < userCount; u++) {
DevicePolicyData policy = getUserData(mUserData.keyAt(u));
@@ -9624,6 +9674,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return null;
}
+ /**
+ * Return device owner or profile owner set on a given user.
+ */
+ private @Nullable ComponentName getOwnerComponent(int userId) {
+ synchronized (this) {
+ if (mOwners.getDeviceOwnerUserId() == userId) {
+ return mOwners.getDeviceOwnerComponent();
+ }
+ if (mOwners.hasProfileOwner(userId)) {
+ return mOwners.getProfileOwnerComponent(userId);
+ }
+ }
+ return null;
+ }
+
private int checkManagedUserProvisioningPreCondition(int callingUserId) {
if (!hasFeatureManagedUsers()) {
return CODE_MANAGED_USERS_NOT_SUPPORTED;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index da49eb37ebec..412cf81eb5a5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -475,6 +475,9 @@ public final class SystemServer {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
+
+ final Context systemUiContext = activityThread.getSystemUiContext();
+ systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
new file mode 100644
index 000000000000..54ecab3af542
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2017 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 static org.junit.Assert.assertTrue;
+
+import android.content.ComponentName;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link ActivityRecord} class.
+ *
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.am.ActivityRecordTests
+ */
+@MediumTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class ActivityRecordTests extends ActivityTestsBase {
+ private final ComponentName testActivityComponent =
+ ComponentName.unflattenFromString("com.foo/.BarActivity");
+ @Test
+ public void testStackCleanupOnClearingTask() throws Exception {
+ final ActivityManagerService service = createActivityManagerService();
+ final TestActivityStack testStack = new ActivityStackBuilder(service).build();
+ final TaskRecord task = createTask(service, testActivityComponent, testStack);
+ final ActivityRecord record = createActivity(service, testActivityComponent, task);
+
+ record.setTask(null);
+ assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+ }
+
+ @Test
+ public void testStackCleanupOnActivityRemoval() throws Exception {
+ final ActivityManagerService service = createActivityManagerService();
+ final TestActivityStack testStack = new ActivityStackBuilder(service).build();
+ final TaskRecord task = createTask(service, testActivityComponent, testStack);
+ final ActivityRecord record = createActivity(service, testActivityComponent, task);
+
+ task.removeActivity(record);
+ assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+ }
+
+ @Test
+ public void testStackCleanupOnTaskRemoval() throws Exception {
+ final ActivityManagerService service = createActivityManagerService();
+ final TestActivityStack testStack = new ActivityStackBuilder(service).build();
+ final TaskRecord task = createTask(service, testActivityComponent, testStack);
+ final ActivityRecord record = createActivity(service, testActivityComponent, task);
+
+ testStack.removeTask(task, null /*reason*/, ActivityStack.REMOVE_TASK_MODE_MOVING);
+ assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+ }
+
+ @Test
+ public void testNoCleanupMovingActivityInSameStack() throws Exception {
+ final ActivityManagerService service = createActivityManagerService();
+ final TestActivityStack testStack = new ActivityStackBuilder(service).build();
+ final TaskRecord oldTask = createTask(service, testActivityComponent, testStack);
+ final ActivityRecord record = createActivity(service, testActivityComponent, oldTask);
+ final TaskRecord newTask = createTask(service, testActivityComponent, testStack);
+
+ record.reparent(newTask, 0, null /*reason*/);
+ assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 0);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
new file mode 100644
index 000000000000..c5cc2ff22abd
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2017 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 static org.mockito.Mockito.mock;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.test.InstrumentationRegistry;
+import com.android.server.AttributeCache;
+import com.android.server.wm.AppWindowContainerController;
+import com.android.server.wm.StackWindowController;
+
+import com.android.server.wm.WindowManagerService;
+import com.android.server.wm.WindowTestUtils;
+import org.junit.Before;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * A base class to handle common operations in activity related unit tests.
+ */
+public class ActivityTestsBase {
+ private final Context mContext = InstrumentationRegistry.getContext();
+ private static boolean sLooperPrepared;
+ private Handler mHandler;
+
+ // Grabbing an instance of {@link WindowManagerService} creates it if not present so this must
+ // be called at before any tests.
+ private final WindowManagerService mWms = WindowTestUtils.getWindowManagerService(mContext);
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ if (!sLooperPrepared) {
+ sLooperPrepared = true;
+ Looper.prepare();
+ }
+ }
+
+ protected ActivityManagerService createActivityManagerService() {
+ return new TestActivityManagerService(mContext);
+ }
+
+ protected static TestActivityStack createActivityStack(ActivityManagerService service,
+ int stackId, int displayId, boolean onTop) {
+ if (service.mStackSupervisor instanceof TestActivityStackSupervisor) {
+ final TestActivityStack stack = ((TestActivityStackSupervisor) service.mStackSupervisor)
+ .createTestStack(stackId, onTop);
+ return stack;
+ }
+
+ return null;
+ }
+
+ protected static ActivityRecord createActivity(ActivityManagerService service,
+ ComponentName component, TaskRecord task) {
+ Intent intent = new Intent();
+ intent.setComponent(component);
+ final ActivityInfo aInfo = new ActivityInfo();
+ aInfo.applicationInfo = new ApplicationInfo();
+ aInfo.applicationInfo.packageName = component.getPackageName();
+ AttributeCache.init(service.mContext);
+ final ActivityRecord activity = new ActivityRecord(service, null /* caller */,
+ 0 /* launchedFromPid */, 0, null, intent, null,
+ aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
+ 0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
+ service.mStackSupervisor, null /* container */, null /* options */,
+ null /* sourceRecord */);
+ activity.mWindowContainerController = mock(AppWindowContainerController.class);
+
+ if (task != null) {
+ task.addActivityToTop(activity);
+ }
+
+ return activity;
+ }
+
+ protected static TaskRecord createTask(ActivityManagerService service,
+ ComponentName component, ActivityStack stack) {
+ final ActivityInfo aInfo = new ActivityInfo();
+ aInfo.applicationInfo = new ApplicationInfo();
+ aInfo.applicationInfo.packageName = component.getPackageName();
+
+ Intent intent = new Intent();
+ intent.setComponent(component);
+
+ final TaskRecord task = new TaskRecord(service, 0, aInfo, intent /*intent*/,
+ null /*_taskDescription*/, null /*thumbnailInfo*/);
+ stack.addTask(task, true, "creating test task");
+ task.setStack(stack);
+ task.createWindowContainer(true, true);
+
+ return task;
+ }
+
+ /**
+ * An {@link ActivityManagerService} subclass which provides a test
+ * {@link ActivityStackSupervisor}.
+ */
+ protected static class TestActivityManagerService extends ActivityManagerService {
+ public TestActivityManagerService(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected ActivityStackSupervisor createStackSupervisor() {
+ return new TestActivityStackSupervisor(this, new Handler().getLooper());
+ }
+ }
+
+ /**
+ * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
+ * setup not available in the test environment. Also specifies an injector for
+ */
+ protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
+ public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
+ super(service, looper);
+ }
+
+ // Invoked during {@link ActivityStack} creation.
+ @Override
+ void updateUIDsPresentOnDisplay() {
+ }
+
+ public TestActivityStack createTestStack(int stackId, boolean onTop) {
+ final ActivityDisplay display = new ActivityDisplay();
+ final TestActivityContainer container =
+ new TestActivityContainer(stackId, display, onTop);
+ return container.getStack();
+ }
+
+ private class TestActivityContainer extends ActivityContainer {
+ private TestActivityStack mStack;
+ TestActivityContainer(int stackId, ActivityDisplay activityDisplay, boolean onTop) {
+ super(stackId, activityDisplay, onTop);
+ }
+
+ @Override
+ protected void createStack(int stackId, boolean onTop) {
+ mStack = new TestActivityStack(this, null /*recentTasks*/, onTop);
+ }
+
+ public TestActivityStack getStack() {
+ return mStack;
+ }
+ }
+ }
+
+ /**
+ * Override of {@link ActivityStack} that tracks test metrics, such as the number of times a
+ * method is called. Note that its functionality depends on the implementations of the
+ * construction arguments.
+ */
+ protected static class TestActivityStack<T extends StackWindowController>
+ extends ActivityStack<T> {
+ private int mOnActivityRemovedFromStackCount = 0;
+ private T mContainerController;
+ TestActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer,
+ RecentTasks recentTasks, boolean onTop) {
+ super(activityContainer, recentTasks, onTop);
+ }
+
+ @Override
+ void onActivityRemovedFromStack(ActivityRecord r) {
+ mOnActivityRemovedFromStackCount++;
+ super.onActivityRemovedFromStack(r);
+ }
+
+ // Returns the number of times {@link #onActivityRemovedFromStack} has been called
+ public int onActivityRemovedFromStackInvocationCount() {
+ return mOnActivityRemovedFromStackCount;
+ }
+
+ @Override
+ protected T createStackWindowController(int displayId, boolean onTop,
+ Rect outBounds) {
+ mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController();
+ return mContainerController;
+ }
+
+ @Override
+ T getWindowContainerController() {
+ return mContainerController;
+ }
+ }
+
+ protected static class ActivityStackBuilder {
+ private boolean mOnTop = true;
+ private int mStackId = 0;
+ private int mDisplayId = 1;
+
+ private final ActivityManagerService mService;
+
+ public ActivityStackBuilder(ActivityManagerService ams) {
+ mService = ams;
+ }
+
+ public ActivityStackBuilder setOnTop(boolean onTop) {
+ mOnTop = onTop;
+ return this;
+ }
+
+ public ActivityStackBuilder setStackId(int id) {
+ mStackId = id;
+ return this;
+ }
+
+ public ActivityStackBuilder setDisplayId(int id) {
+ mDisplayId = id;
+ return this;
+ }
+
+ public TestActivityStack build() {
+ return createActivityStack(mService, mStackId, mDisplayId, mOnTop);
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 0f51c49bfaba..d281e5aed3cc 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -36,7 +36,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
@@ -1276,7 +1275,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
try {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final PrintWriter pw = new PrintWriter(out);
- mService.dump(/* fd */ null, pw, args);
+ mService.dumpNoCheck(/* fd */ null, pw, args);
pw.close();
return out.toString();
@@ -1345,23 +1344,20 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected ShortcutInfo makeShortcut(String id) {
return makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
}
@Deprecated // Title was renamed to short label.
protected ShortcutInfo makeShortcutWithTitle(String id, String title) {
return makeShortcut(
id, title, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
}
protected ShortcutInfo makeShortcutWithShortLabel(String id, String shortLabel) {
return makeShortcut(
id, shortLabel, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
}
/**
@@ -1370,8 +1366,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected ShortcutInfo makeShortcutWithTimestamp(String id, long timestamp) {
final ShortcutInfo s = makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
s.setTimestamp(timestamp);
return s;
}
@@ -1383,8 +1378,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
ComponentName activity) {
final ShortcutInfo s = makeShortcut(
id, "Title-" + id, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
s.setTimestamp(timestamp);
return s;
}
@@ -1395,27 +1389,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
return makeShortcut(
id, "Title-" + id, /* activity =*/ null, icon,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
- }
-
- protected ShortcutInfo makeChooserShortcut(String id, int i, boolean includeIntent) {
- List<IntentFilter> filters = new ArrayList<>();
- List<ComponentName> componentNames = new ArrayList<>();
- for(int j = 0; j < i; j++) {
- final IntentFilter filter = new IntentFilter();
- filter.addAction("view");
- filters.add(filter);
-
- componentNames.add(new ComponentName("xxxx", "yy" + i));
- }
- Intent intent = null;
- if (includeIntent) {
- intent = makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class);
- }
- return makeShortcut(
- id, "Title-" + id, /* activity =*/ null, /* icon */ null,
- intent, /* rank =*/ 0, filters, componentNames);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
}
protected ShortcutInfo makePackageShortcut(String packageName, String id) {
@@ -1424,8 +1398,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
setCaller(packageName);
ShortcutInfo s = makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
setCaller(origCaller); // restore the caller
return s;
@@ -1449,52 +1422,39 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected ShortcutInfo makeShortcutWithActivity(String id, ComponentName activity) {
return makeShortcut(
id, "Title-" + id, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
}
protected ShortcutInfo makeShortcutWithIntent(String id, Intent intent) {
return makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- intent, /* rank =*/ 0, /* chooserFilters =*/ null,
- /* chooserComponentNames =*/ null);
-
+ intent, /* rank =*/ 0);
}
protected ShortcutInfo makeShortcutWithActivityAndTitle(String id, ComponentName activity,
String title) {
return makeShortcut(
id, title, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
}
protected ShortcutInfo makeShortcutWithActivityAndRank(String id, ComponentName activity,
int rank) {
return makeShortcut(
id, "Title-" + id, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank,
- /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank);
}
/**
* Make a shortcut with details.
*/
protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity,
- Icon icon, Intent intent, int rank, @Nullable List<IntentFilter> chooserFilters,
- @Nullable List<ComponentName> chooserComponentNames) {
+ Icon icon, Intent intent, int rank) {
final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id)
.setActivity(new ComponentName(mClientContext.getPackageName(), "main"))
.setShortLabel(title)
- .setRank(rank);
- if (intent != null) {
- b.setIntent(intent);
- }
- if (chooserFilters != null) {
- for (int i = 0; i < chooserFilters.size(); i++) {
- b.addChooserIntentFilter(chooserFilters.get(i), chooserComponentNames.get(i));
- }
- }
+ .setRank(rank)
+ .setIntent(intent);
if (icon != null) {
b.setIcon(icon);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index dd0871ae49e0..9861aa177135 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -17,7 +17,6 @@ package com.android.server.pm;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.anyOrNull;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.anyStringOrNull;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllChooser;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDisabled;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamic;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamicOrPinned;
@@ -58,7 +57,6 @@ import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -261,9 +259,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 10);
final ShortcutInfo si2 = makeShortcut(
"shortcut2",
@@ -271,18 +267,14 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 12);
final ShortcutInfo si3 = makeShortcut(
"shortcut3",
"Title 3",
/* activity */ null,
icon3,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 13,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 13);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2, si3)));
assertShortcutIds(assertAllNotKeyFieldsOnly(
@@ -993,10 +985,8 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
makeShortcut("s2"),
makeShortcut("s3"),
makeShortcut("s4"),
- makeShortcut("s5"),
- makeChooserShortcut("s6", 2, true),
- makeChooserShortcut("s7", 2, true),
- makeChooserShortcut("s8", 1, true))));
+ makeShortcut("s5")
+ )));
});
runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
@@ -1004,13 +994,11 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
makeShortcut("s2"),
makeShortcut("s3"),
makeShortcut("s4"),
- makeShortcut("s5"),
- makeChooserShortcut("s6", 2, true),
- makeChooserShortcut("s7", 2, true),
- makeChooserShortcut("s8", 1, true))));
+ makeShortcut("s5")
+ )));
});
runWithCaller(LAUNCHER_1, UserHandle.USER_SYSTEM, () -> {
- mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3", "s6"),
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3"),
getCallingUser());
mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s4", "s5"),
getCallingUser());
@@ -1023,20 +1011,19 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mManager.removeDynamicShortcuts(list("s1"));
mManager.removeDynamicShortcuts(list("s3"));
mManager.removeDynamicShortcuts(list("s5"));
- mManager.removeDynamicShortcuts(list("s7"));
});
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s3", "s4", "s5", "s6", "s7", "s8");
+ "s3", "s4", "s5");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
- "s2", "s3", "s6");
+ "s2", "s3");
});
runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s2", "s4", "s6", "s8");
+ "s2", "s4");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
"s4", "s5");
@@ -1073,10 +1060,10 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s3", "s4", "s5", "s6", "s7", "s8");
+ "s3", "s4", "s5");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
- "s2", "s3", "s6");
+ "s2", "s3");
ShortcutInfo s = getCallerShortcut("s2");
assertTrue(s.hasIconResource());
@@ -1092,7 +1079,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s2", "s4", "s6", "s8");
+ "s2", "s4");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
"s4", "s5");
@@ -1189,46 +1176,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void testUpdateShortcuts_chooser() {
- runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
- assertTrue(mManager.setDynamicShortcuts(list(
- makeShortcut("s1"),
- makeChooserShortcut("s2", 2, false),
- makeChooserShortcut("s3", 2, false)
- )));
-
- assertFalse(getCallerShortcut("s1").isChooser());
- assertTrue(getCallerShortcut("s2").isChooser());
- assertTrue(getCallerShortcut("s3").isChooser());
-
- ShortcutInfo s = getCallerShortcut("s1");
- assertNull(s.getChooserIntentFilters());
- assertNull(s.getChooserComponentNames());
-
- assertTrue(getCallerShortcut("s1").isDynamic());
- assertFalse(getCallerShortcut("s2").isDynamic());
- assertFalse(getCallerShortcut("s3").isDynamic());
-
-
- // Replace 2 with a chooser shortcut
- mManager.updateShortcuts(list(makeChooserShortcut("s1", 2, true)));
-
- s = getCallerShortcut("s1");
- assertEquals(2, s.getChooserIntentFilters().length);
- assertEquals(2, s.getChooserComponentNames().length);
-
- assertShortcutIds(assertAllChooser(
- mManager.getDynamicShortcuts()),
- "s1", "s2", "s3");
-
- assertTrue(getCallerShortcut("s1").isDynamic());
- assertFalse(getCallerShortcut("s2").isDynamic());
- assertFalse(getCallerShortcut("s3").isDynamic());
- });
- }
-
-
- // === Test for launcher side APIs ===
+ // === Test for launcher side APIs ===
public void testGetShortcuts() {
@@ -1539,17 +1487,15 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/* icon =*/ null,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10, /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 10);
final ShortcutInfo s1_2 = makeShortcut(
- "s2", "Title 2",
+ "s2",
+ "Title 2",
/* activity */ null,
/* icon =*/ null,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 12);
assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
dumpsysOnLogcat();
@@ -1562,9 +1508,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/* icon =*/ null,
makeIntent(Intent.ACTION_ANSWER, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 10);
assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
dumpsysOnLogcat();
@@ -2733,12 +2677,10 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
final ShortcutInfo s1_2 = makeShortcut(
"s2",
"Title 2",
- /* activity */ null,
- /* icon =*/ null,
+ /* activity */ null,
+ /* icon =*/ null,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* rank */ 12,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* rank */ 12);
final ShortcutInfo s1_3 = makeShortcut("s3");
@@ -2753,9 +2695,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/* icon =*/ null,
makeIntent(Intent.ACTION_ANSWER, ShortcutActivity.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 10);
assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
});
@@ -3175,9 +3115,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 10);
final ShortcutInfo si2 = makeShortcut(
"s2",
@@ -3185,9 +3123,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 12);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
@@ -3205,8 +3141,8 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
makeComponent(ShortcutActivity.class),
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
- "key1", "val1", "nest", makeBundle("key", 123)), /* weight */ 10,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ "key1", "val1", "nest", makeBundle("key", 123)),
+ /* weight */ 10);
final ShortcutInfo si2 = makeShortcut(
"s2",
@@ -3214,8 +3150,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12, /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 12);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
@@ -3237,8 +3172,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10, /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 10);
final ShortcutInfo si2 = makeShortcut(
"s2",
@@ -3246,8 +3180,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12, /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 12);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
@@ -6884,12 +6817,10 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mManager.setDynamicShortcuts(list(
makeShortcut("ms1", "title1",
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
- /* icon */ null, new Intent("action1"), /* rank */ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null),
+ /* icon */ null, new Intent("action1"), /* rank */ 0),
makeShortcut("ms2", "title2",
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
- /* icon */ null, new Intent("action1"), /* rank */ 0, /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null)));
+ /* icon */ null, new Intent("action1"), /* rank */ 0)));
});
runWithCaller(LAUNCHER_1, USER_0, () -> {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 7c5eb07f0a78..9880caa11f85 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -34,7 +34,6 @@ import android.Manifest.permission;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
@@ -93,6 +92,11 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertExpectException(
RuntimeException.class,
+ "intents cannot contain null",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(null));
+
+ assertExpectException(
+ RuntimeException.class,
"action must be set",
() -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
@@ -137,19 +141,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
"disabledMessage cannot be empty",
() -> new ShortcutInfo.Builder(getTestContext(), "id").setDisabledMessage(""));
-
- assertExpectException(
- RuntimeException.class,
- "component name cannot be null",
- () -> new ShortcutInfo.Builder(getTestContext(), "id")
- .addChooserIntentFilter(new IntentFilter(Intent.ACTION_SEND), null));
-
- assertExpectException(
- RuntimeException.class,
- "intent filter cannot be null",
- () -> new ShortcutInfo.Builder(getTestContext(), "id")
- .addChooserIntentFilter(null, new ComponentName("xxx", "s")));
-
assertExpectException(NullPointerException.class, "action must be set",
() -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
@@ -248,10 +239,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
- IntentFilter chooserFilter = new IntentFilter();
- chooserFilter.addAction(Intent.ACTION_VIEW);
- PersistableBundle pb2 = new PersistableBundle();
- pb2.putInt("l", 1);
si = new ShortcutInfo.Builder(getTestContext())
.setId("id")
@@ -264,8 +251,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setRank(123)
.setExtras(pb)
- .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
- .setChooserExtras(pb2)
.build();
si.addFlags(ShortcutInfo.FLAG_PINNED);
si.setBitmapPath("abc");
@@ -296,12 +281,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(null, si.getTextResName());
assertEquals(0, si.getDisabledMessageResourceId());
assertEquals(null, si.getDisabledMessageResName());
-
- assertEquals(1, si.getChooserIntentFilters().length);
- assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
- assertEquals(1, si.getChooserComponentNames().length);
- assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
- assertEquals(1, si.getChooserExtras().getInt("l"));
}
public void testShortcutInfoParcel_resId() {
@@ -310,10 +289,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
- IntentFilter chooserFilter = new IntentFilter();
- chooserFilter.addAction(Intent.ACTION_VIEW);
- PersistableBundle pb2 = new PersistableBundle();
- pb2.putInt("l", 1);
si = new ShortcutInfo.Builder(getTestContext())
.setId("id")
@@ -326,8 +301,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setRank(123)
.setExtras(pb)
- .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
- .setChooserExtras(pb2)
.build();
si.addFlags(ShortcutInfo.FLAG_PINNED);
si.setBitmapPath("abc");
@@ -364,11 +337,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
- IntentFilter chooserFilter = new IntentFilter();
- chooserFilter.addAction(Intent.ACTION_VIEW);
- PersistableBundle pb2 = new PersistableBundle();
- pb2.putInt("l", 1);
-
ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivity(new ComponentName("a", "b"))
@@ -380,8 +348,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
- .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
- .setChooserExtras(pb2)
.build();
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
@@ -411,12 +377,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(456, si.getIconResourceId());
assertEquals("string/r456", si.getIconResName());
- assertEquals(1, si.getChooserIntentFilters().length);
- assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
- assertEquals(1, si.getChooserComponentNames().length);
- assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
- assertEquals(1, si.getChooserExtras().getInt("l"));
-
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
assertEquals(mClientContext.getPackageName(), si.getPackage());
@@ -484,10 +444,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
- IntentFilter chooserFilter = new IntentFilter();
- chooserFilter.addAction(Intent.ACTION_VIEW);
- PersistableBundle pb2 = new PersistableBundle();
- pb2.putInt("l", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivity(new ComponentName("a", "b"))
@@ -499,8 +455,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
- .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
- .setChooserExtras(pb2)
.build();
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
@@ -533,12 +487,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(456, si.getIconResourceId());
assertEquals("string/r456", si.getIconResName());
- assertEquals(1, si.getChooserIntentFilters().length);
- assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
- assertEquals(1, si.getChooserComponentNames().length);
- assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
- assertEquals(1, si.getChooserExtras().getInt("l"));
-
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
assertEquals(mClientContext.getPackageName(), si.getPackage());
@@ -654,10 +602,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
public void testShortcutInfoCopyNonNullFieldsFrom() throws InterruptedException {
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
- IntentFilter chooserFilter = new IntentFilter();
- chooserFilter.addAction(Intent.ACTION_VIEW);
- PersistableBundle pb2 = new PersistableBundle();
- pb2.putInt("l", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
.setId("id")
.setActivity(new ComponentName("a", "b"))
@@ -769,12 +713,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(999, si.getRank());
- PersistableBundle pb3 = new PersistableBundle();
- pb3.putInt("x", 99);
+ PersistableBundle pb2 = new PersistableBundle();
+ pb2.putInt("x", 99);
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
- .setExtras(pb3).build());
+ .setExtras(pb2).build());
assertEquals("text", si.getText());
assertEquals(99, si.getExtras().getInt("x"));
}
@@ -2096,16 +2040,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(expected, dumpCheckin());
}
- public void testDumpsysNoPermission() {
- assertExpectException(SecurityException.class, "android.permission.DUMP",
- () -> mService.dump(null, new PrintWriter(new StringWriter()), null));
-
- // System can call it without the permission.
- runWithSystemUid(() -> {
- mService.dump(null, new PrintWriter(new StringWriter()), null);
- });
- }
-
/**
* Make sure the legacy file format that only supported a single intent per shortcut
* can still be read.
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppBoundsTests.java b/services/tests/servicestests/src/com/android/server/wm/AppBoundsTests.java
new file mode 100644
index 000000000000..f68e06afff9a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/AppBoundsTests.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2017 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.app.ActivityManager;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Debug;
+import android.view.DisplayInfo;
+import org.junit.Test;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test class to exercise logic related to {@link android.content.res.Configuration#appBounds}.
+ *
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.wm.AppBoundsTests
+ */
+@SmallTest
+@Presubmit
+@org.junit.runner.RunWith(AndroidJUnit4.class)
+public class AppBoundsTests extends WindowTestsBase {
+ private Rect mParentBounds;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mParentBounds = new Rect(10 /*left*/, 30 /*top*/, 80 /*right*/, 60 /*bottom*/);
+ }
+
+ /**
+ * Ensures the configuration app bounds at the root level match the app dimensions.
+ */
+ @Test
+ public void testRootConfigurationBounds() throws Exception {
+ final DisplayInfo info = sDisplayContent.getDisplayInfo();
+ info.appWidth = 1024;
+ info.appHeight = 768;
+
+ final Configuration config = sWm.computeNewConfiguration(sDisplayContent.getDisplayId());
+ // The bounds should always be positioned in the top left.
+ assertEquals(config.appBounds.left, 0);
+ assertEquals(config.appBounds.top, 0);
+
+ // The bounds should equal the defined app width and height
+ assertEquals(config.appBounds.width(), info.appWidth);
+ assertEquals(config.appBounds.height(), info.appHeight);
+ }
+
+ /**
+ * Ensures that bounds are clipped to their parent.
+ */
+ @Test
+ public void testBoundsClipping() throws Exception {
+ final Rect shiftedBounds = new Rect(mParentBounds);
+ shiftedBounds.offset(10, 10);
+ final Rect expectedBounds = new Rect(mParentBounds);
+ expectedBounds.intersect(shiftedBounds);
+ testStackBoundsConfiguration(null /*stackId*/, mParentBounds, shiftedBounds,
+ expectedBounds);
+ }
+
+ /**
+ * Ensures that empty bounds are not propagated to the configuration.
+ */
+ @Test
+ public void testEmptyBounds() throws Exception {
+ final Rect emptyBounds = new Rect();
+ testStackBoundsConfiguration(null /*stackId*/, mParentBounds, emptyBounds,
+ null /*ExpectedBounds*/);
+ }
+
+ /**
+ * Ensures that bounds on freeform stacks are not clipped.
+ */
+ @Test
+ public void testFreeFormBounds() throws Exception {
+ final Rect freeFormBounds = new Rect(mParentBounds);
+ freeFormBounds.offset(10, 10);
+ testStackBoundsConfiguration(ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID,
+ mParentBounds, freeFormBounds, freeFormBounds);
+ }
+
+ /**
+ * Ensures that fully contained bounds are not clipped.
+ */
+ @Test
+ public void testContainedBounds() throws Exception {
+ final Rect insetBounds = new Rect(mParentBounds);
+ insetBounds.inset(5, 5, 5, 5);
+ testStackBoundsConfiguration(null /*stackId*/, mParentBounds, insetBounds, insetBounds);
+ }
+
+ /**
+ * Ensures that full screen free form bounds are clipped
+ */
+ @Test
+ public void testFullScreenFreeFormBounds() throws Exception {
+ final Rect fullScreenBounds = new Rect(0, 0, sDisplayInfo.logicalWidth,
+ sDisplayInfo.logicalHeight);
+ testStackBoundsConfiguration(null /*stackId*/, mParentBounds, fullScreenBounds,
+ mParentBounds);
+ }
+
+
+ private void testStackBoundsConfiguration(Integer stackId, Rect parentBounds, Rect bounds,
+ Rect expectedConfigBounds) {
+ final StackWindowController stackController = stackId != null ?
+ createStackControllerOnStackOnDisplay(stackId, sDisplayContent)
+ : createStackControllerOnDisplay(sDisplayContent);
+
+ final Configuration parentConfig = sDisplayContent.getConfiguration();
+ parentConfig.setAppBounds(parentBounds);
+
+ final Configuration config = new Configuration();
+ stackController.adjustConfigurationForBounds(bounds, null /*insetBounds*/,
+ new Rect() /*nonDecorBounds*/, new Rect() /*stableBounds*/, false /*overrideWidth*/,
+ false /*overrideHeight*/, sDisplayInfo.logicalDensityDpi, config, parentConfig);
+ // Assert that both expected and actual are null or are equal to each other
+
+ assertTrue((expectedConfigBounds == null && config.appBounds == null)
+ || expectedConfigBounds.equals(config.appBounds));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index 2ccaefc4512e..25004de60676 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -44,7 +44,8 @@ public class AppWindowContainerControllerTests extends WindowTestsBase {
@Test
public void testRemoveContainer() throws Exception {
- final TestAppWindowContainerController controller = createAppWindowController();
+ final WindowTestUtils.TestAppWindowContainerController controller =
+ createAppWindowController();
// Assert token was added to display.
assertNotNull(sDisplayContent.getWindowToken(controller.mToken.asBinder()));
@@ -61,7 +62,8 @@ public class AppWindowContainerControllerTests extends WindowTestsBase {
@Test
public void testSetOrientation() throws Exception {
- final TestAppWindowContainerController controller = createAppWindowController();
+ final WindowTestUtils.TestAppWindowContainerController controller =
+ createAppWindowController();
// Assert orientation is unspecified to start.
assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, controller.getOrientation());
@@ -92,7 +94,8 @@ public class AppWindowContainerControllerTests extends WindowTestsBase {
@Test
public void testCreateRemoveStartingWindow() throws Exception {
- final TestAppWindowContainerController controller = createAppWindowController();
+ final WindowTestUtils.TestAppWindowContainerController controller =
+ createAppWindowController();
controller.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
waitUntilHandlerIdle();
@@ -105,8 +108,10 @@ public class AppWindowContainerControllerTests extends WindowTestsBase {
@Test
public void testTransferStartingWindow() throws Exception {
- final TestAppWindowContainerController controller1 = createAppWindowController();
- final TestAppWindowContainerController controller2 = createAppWindowController();
+ final WindowTestUtils.TestAppWindowContainerController controller1 =
+ createAppWindowController();
+ final WindowTestUtils.TestAppWindowContainerController controller2 =
+ createAppWindowController();
controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
waitUntilHandlerIdle();
@@ -120,8 +125,10 @@ public class AppWindowContainerControllerTests extends WindowTestsBase {
@Test
public void testTransferStartingWindowWhileCreating() throws Exception {
- final TestAppWindowContainerController controller1 = createAppWindowController();
- final TestAppWindowContainerController controller2 = createAppWindowController();
+ final WindowTestUtils.TestAppWindowContainerController controller1 =
+ createAppWindowController();
+ final WindowTestUtils.TestAppWindowContainerController controller2 =
+ createAppWindowController();
sPolicy.setRunnableWhenAddingSplashScreen(() -> {
// Surprise, ...! Transfer window in the middle of the creation flow.
@@ -140,16 +147,16 @@ public class AppWindowContainerControllerTests extends WindowTestsBase {
public void testReparent() throws Exception {
final StackWindowController stackController =
createStackControllerOnDisplay(sDisplayContent);
- final TestTaskWindowContainerController taskController1 =
- new TestTaskWindowContainerController(stackController);
- final TestAppWindowContainerController appWindowController1 = createAppWindowController(
- taskController1);
- final TestTaskWindowContainerController taskController2 =
- new TestTaskWindowContainerController(stackController);
- final TestAppWindowContainerController appWindowController2 = createAppWindowController(
- taskController2);
- final TestTaskWindowContainerController taskController3 =
- new TestTaskWindowContainerController(stackController);
+ final WindowTestUtils.TestTaskWindowContainerController taskController1 =
+ new WindowTestUtils.TestTaskWindowContainerController(stackController);
+ final WindowTestUtils.TestAppWindowContainerController appWindowController1 =
+ createAppWindowController(taskController1);
+ final WindowTestUtils.TestTaskWindowContainerController taskController2 =
+ new WindowTestUtils.TestTaskWindowContainerController(stackController);
+ final WindowTestUtils.TestAppWindowContainerController appWindowController2 =
+ createAppWindowController(taskController2);
+ final WindowTestUtils.TestTaskWindowContainerController taskController3 =
+ new WindowTestUtils.TestTaskWindowContainerController(stackController);
try {
appWindowController1.reparent(taskController1, 0);
@@ -169,16 +176,18 @@ public class AppWindowContainerControllerTests extends WindowTestsBase {
// Reparent the app window and ensure that it is moved
appWindowController1.reparent(taskController2, 0);
assertEquals(taskController2.mContainer, appWindowController1.mContainer.getParent());
- assertEquals(0, ((TestAppWindowToken) appWindowController1.mContainer).positionInParent());
- assertEquals(1, ((TestAppWindowToken) appWindowController2.mContainer).positionInParent());
+ assertEquals(0, ((WindowTestUtils.TestAppWindowToken) appWindowController1.mContainer)
+ .positionInParent());
+ assertEquals(1, ((WindowTestUtils.TestAppWindowToken) appWindowController2.mContainer)
+ .positionInParent());
}
- private TestAppWindowContainerController createAppWindowController() {
- return createAppWindowController(new TestTaskWindowContainerController());
+ private WindowTestUtils.TestAppWindowContainerController createAppWindowController() {
+ return createAppWindowController(new WindowTestUtils.TestTaskWindowContainerController());
}
- private TestAppWindowContainerController createAppWindowController(
- TestTaskWindowContainerController taskController) {
- return new TestAppWindowContainerController(taskController);
+ private WindowTestUtils.TestAppWindowContainerController createAppWindowController(
+ WindowTestUtils.TestTaskWindowContainerController taskController) {
+ return new WindowTestUtils.TestAppWindowContainerController(taskController);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index 2003b91bcfad..7a7ca3f4000a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -51,7 +51,8 @@ public class AppWindowTokenTests extends WindowTestsBase {
@Test
public void testAddWindow_Order() throws Exception {
- final TestAppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ final WindowTestUtils.TestAppWindowToken token =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
assertEquals(0, token.getWindowsCount());
@@ -78,7 +79,8 @@ public class AppWindowTokenTests extends WindowTestsBase {
@Test
public void testFindMainWindow() throws Exception {
- final TestAppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ final WindowTestUtils.TestAppWindowToken token =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
assertNull(token.findMainWindow());
@@ -102,12 +104,13 @@ public class AppWindowTokenTests extends WindowTestsBase {
// Create an app window with token on a display.
final TaskStack stack = createTaskStackOnDisplay(sDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final TestAppWindowToken appWindowToken = new TestAppWindowToken(sDisplayContent);
+ final WindowTestUtils.TestAppWindowToken appWindowToken =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
task.addChild(appWindowToken, 0);
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
TYPE_BASE_APPLICATION);
attrs.setTitle("AppWindow");
- final TestWindowState appWindow = new TestWindowState(attrs, appWindowToken);
+ final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, appWindowToken);
appWindowToken.addWindow(appWindow);
// Set initial orientation and update.
@@ -137,12 +140,13 @@ public class AppWindowTokenTests extends WindowTestsBase {
final DisplayContent defaultDisplayContent = sWm.getDefaultDisplayContentLocked();
final TaskStack stack = createTaskStackOnDisplay(defaultDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final TestAppWindowToken appWindowToken = new TestAppWindowToken(defaultDisplayContent);
+ final WindowTestUtils.TestAppWindowToken appWindowToken =
+ new WindowTestUtils.TestAppWindowToken(defaultDisplayContent);
task.addChild(appWindowToken, 0);
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
TYPE_BASE_APPLICATION);
attrs.setTitle("AppWindow");
- final TestWindowState appWindow = new TestWindowState(attrs, appWindowToken);
+ final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, appWindowToken);
appWindowToken.addWindow(appWindow);
// Set initial orientation and update.
@@ -165,7 +169,8 @@ public class AppWindowTokenTests extends WindowTestsBase {
@Test
public void testGetOrientation() throws Exception {
- final TestAppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ final WindowTestUtils.TestAppWindowToken token =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
token.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
token.setFillsParent(false);
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 1729ceec0005..d7d365e72480 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -175,7 +175,7 @@ public class DisplayContentTests extends WindowTestsBase {
assertEquals(dc, stack.getDisplayContent());
final Task task = createTaskInStack(stack, 0 /* userId */);
- final TestAppWindowToken token = new TestAppWindowToken(dc);
+ final WindowTestUtils.TestAppWindowToken token = new WindowTestUtils.TestAppWindowToken(dc);
task.addChild(token, 0);
assertEquals(dc, task.getDisplayContent());
assertEquals(dc, token.getDisplayContent());
@@ -213,10 +213,10 @@ public class DisplayContentTests extends WindowTestsBase {
*/
@Test
public void testDefaultDisplayOverrideConfigUpdate() throws Exception {
- final Configuration currentOverrideConfig = sDisplayContent.getOverrideConfiguration();
+ final Configuration currentConfig = sDisplayContent.getConfiguration();
// Create new, slightly changed override configuration and apply it to the display.
- final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
+ final Configuration newOverrideConfig = new Configuration(currentConfig);
newOverrideConfig.densityDpi += 120;
newOverrideConfig.fontScale += 0.3;
@@ -228,10 +228,10 @@ public class DisplayContentTests extends WindowTestsBase {
assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
// Return back to original values.
- sWm.setNewDisplayOverrideConfiguration(currentOverrideConfig, DEFAULT_DISPLAY);
+ sWm.setNewDisplayOverrideConfiguration(currentConfig, DEFAULT_DISPLAY);
globalConfig = sWm.mRoot.getConfiguration();
- assertEquals(currentOverrideConfig.densityDpi, globalConfig.densityDpi);
- assertEquals(currentOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
+ assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
+ assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
index b0eba0b99567..13098f64bfac 100644
--- a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
@@ -16,12 +16,7 @@
package com.android.server.wm;
-import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
-
import android.graphics.Rect;
-import android.hardware.display.DisplayManagerGlobal;
-import android.view.Display;
-import android.view.DisplayInfo;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -48,8 +43,8 @@ public class StackWindowControllerTests extends WindowTestsBase {
public void testRemoveContainer() throws Exception {
final StackWindowController stackController =
createStackControllerOnDisplay(sDisplayContent);
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController(stackController);
+ final WindowTestUtils.TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController(stackController);
final TaskStack stack = stackController.mContainer;
final Task task = taskController.mContainer;
@@ -68,11 +63,11 @@ public class StackWindowControllerTests extends WindowTestsBase {
public void testRemoveContainer_deferRemoval() throws Exception {
final StackWindowController stackController =
createStackControllerOnDisplay(sDisplayContent);
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController(stackController);
+ final WindowTestUtils.TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController(stackController);
final TaskStack stack = stackController.mContainer;
- final TestTask task = (TestTask) taskController.mContainer;
+ final WindowTestUtils.TestTask task = (WindowTestUtils.TestTask) taskController.mContainer;
// Stack removal is deferred if one of its child is animating.
task.setLocalIsAnimating(true);
@@ -96,9 +91,9 @@ public class StackWindowControllerTests extends WindowTestsBase {
final StackWindowController stack1Controller =
createStackControllerOnDisplay(sDisplayContent);
final TaskStack stack1 = stack1Controller.mContainer;
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController(stack1Controller);
- final TestTask task1 = (TestTask) taskController.mContainer;
+ final WindowTestUtils.TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController(stack1Controller);
+ final WindowTestUtils.TestTask task1 = (WindowTestUtils.TestTask) taskController.mContainer;
task1.mOnDisplayChangedCalled = false;
// Create second display and put second stack on it.
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index aab75ee1699b..717ddf26eb2f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -16,6 +16,9 @@
package com.android.server.wm;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
@@ -24,15 +27,19 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
+import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.GraphicBuffer;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import android.view.Surface;
+
+import com.android.server.wm.TaskSnapshotSurface.Window;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -48,59 +55,174 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
private TaskSnapshotSurface mSurface;
- @Before
- public void setUp() {
- mSurface = new TaskSnapshotSurface(null, null, null, Color.WHITE);
+ private void setupSurface(int width, int height, Rect contentInsets, int sysuiVis,
+ int windowFlags, Rect taskBounds) {
+ final GraphicBuffer buffer = GraphicBuffer.create(width, height, PixelFormat.RGBA_8888,
+ GraphicBuffer.USAGE_SW_READ_NEVER | GraphicBuffer.USAGE_SW_WRITE_NEVER);
+ final TaskSnapshot snapshot = new TaskSnapshot(buffer,
+ ORIENTATION_PORTRAIT, contentInsets, false, 1.0f);
+ mSurface = new TaskSnapshotSurface(sWm, new Window(), new Surface(), snapshot, "Test",
+ Color.WHITE, Color.RED, Color.BLUE, sysuiVis, windowFlags, 0, taskBounds);
+ }
+
+ private void setupSurface(int width, int height) {
+ setupSurface(width, height, new Rect(), 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, width, height));
}
@Test
public void fillEmptyBackground_fillHorizontally() throws Exception {
+ setupSurface(200, 100);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(200);
when(mockCanvas.getHeight()).thenReturn(100);
- final Bitmap b = Bitmap.createBitmap(100, 200, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 200));
verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
}
@Test
public void fillEmptyBackground_fillVertically() throws Exception {
+ setupSurface(100, 200);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(200);
- final Bitmap b = Bitmap.createBitmap(200, 100, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 100));
verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(100.0f), eq(200.0f), any());
}
@Test
public void fillEmptyBackground_fillBoth() throws Exception {
+ setupSurface(200, 200);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(200);
when(mockCanvas.getHeight()).thenReturn(200);
- final Bitmap b = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(200.0f), eq(200.0f), any());
}
@Test
public void fillEmptyBackground_dontFill_sameSize() throws Exception {
+ setupSurface(100, 100);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- final Bitmap b = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
}
@Test
public void fillEmptyBackground_dontFill_bitmapLarger() throws Exception {
+ setupSurface(100, 100);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 200));
+ verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop() {
+ setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 0, 100, 100));
+ assertEquals(new Rect(0, 0, 100, 90), mSurface.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop_taskNotOnTop() {
+ setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 50, 100, 100));
+ assertEquals(new Rect(0, 10, 100, 90), mSurface.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop_navBarLeft() {
+ setupSurface(100, 100, new Rect(10, 10, 0, 0), 0, 0, new Rect(0, 0, 100, 100));
+ assertEquals(new Rect(10, 0, 100, 100), mSurface.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop_navBarRight() {
+ setupSurface(100, 100, new Rect(0, 10, 10, 0), 0, 0, new Rect(0, 0, 100, 100));
+ assertEquals(new Rect(0, 0, 90, 100), mSurface.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotFrame() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 0, 10);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ assertEquals(new Rect(0, -10, 100, 70),
+ mSurface.calculateSnapshotFrame(new Rect(0, 10, 100, 90)));
+ }
+
+ @Test
+ public void testCalculateSnapshotFrame_navBarLeft() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(10, 10, 0, 0);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ assertEquals(new Rect(0, -10, 90, 80),
+ mSurface.calculateSnapshotFrame(new Rect(10, 10, 100, 100)));
+ }
+
+ @Test
+ public void testDrawStatusBarBackground() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 10, 0);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- final Bitmap b = Bitmap.createBitmap(200, 200, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 50, 100), 10);
+ verify(mockCanvas).drawRect(eq(50.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
+ }
+
+ @Test
+ public void testDrawStatusBarBackground_nope() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 10, 0);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 100, 100), 10);
verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
}
+
+ @Test
+ public void testDrawNavigationBarBackground() {
+ final Rect insets = new Rect(0, 10, 0, 10);
+ setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, 100, 100));
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawNavigationBarBackground(mockCanvas);
+ verify(mockCanvas).drawRect(eq(new Rect(0, 90, 100, 100)), any());
+ }
+
+ @Test
+ public void testDrawNavigationBarBackground_left() {
+ final Rect insets = new Rect(10, 10, 0, 0);
+ setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, 100, 100));
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawNavigationBarBackground(mockCanvas);
+ verify(mockCanvas).drawRect(eq(new Rect(0, 0, 10, 100)), any());
+ }
+
+ @Test
+ public void testDrawNavigationBarBackground_right() {
+ final Rect insets = new Rect(0, 10, 10, 0);
+ setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, 100, 100));
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawNavigationBarBackground(mockCanvas);
+ verify(mockCanvas).drawRect(eq(new Rect(90, 0, 100, 100)), any());
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
index 462bd68dc420..82ea2313e8d7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -56,7 +56,7 @@ public class TaskStackContainersTests extends WindowTestsBase {
// Stack should contain visible app window to be considered visible.
final Task pinnedTask = createTaskInStack(mPinnedStack, 0 /* userId */);
assertFalse(mPinnedStack.isVisible());
- final TestAppWindowToken pinnedApp = new TestAppWindowToken(sDisplayContent);
+ final WindowTestUtils.TestAppWindowToken pinnedApp = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
pinnedTask.addChild(pinnedApp, 0 /* addPos */);
assertTrue(mPinnedStack.isVisible());
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
index 9dbd8a617eec..267e5f77e709 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
@@ -16,9 +16,6 @@
package com.android.server.wm;
-import android.content.pm.ActivityInfo;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -67,12 +64,14 @@ public class TaskStackTests extends WindowTestsBase {
public void testClosingAppDifferentStackOrientation() throws Exception {
final TaskStack stack = createTaskStackOnDisplay(sDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- TestAppWindowToken appWindowToken1 = new TestAppWindowToken(sDisplayContent);
+ WindowTestUtils.TestAppWindowToken appWindowToken1 =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
task1.addChild(appWindowToken1, 0);
appWindowToken1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
final Task task2 = createTaskInStack(stack, 1 /* userId */);
- TestAppWindowToken appWindowToken2 = new TestAppWindowToken(sDisplayContent);
+ WindowTestUtils.TestAppWindowToken appWindowToken2 =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
task2.addChild(appWindowToken2, 0);
appWindowToken2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
@@ -85,12 +84,14 @@ public class TaskStackTests extends WindowTestsBase {
public void testMoveTaskToBackDifferentStackOrientation() throws Exception {
final TaskStack stack = createTaskStackOnDisplay(sDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- TestAppWindowToken appWindowToken1 = new TestAppWindowToken(sDisplayContent);
+ WindowTestUtils.TestAppWindowToken appWindowToken1 =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
task1.addChild(appWindowToken1, 0);
appWindowToken1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
final Task task2 = createTaskInStack(stack, 1 /* userId */);
- TestAppWindowToken appWindowToken2 = new TestAppWindowToken(sDisplayContent);
+ WindowTestUtils.TestAppWindowToken appWindowToken2 =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
task2.addChild(appWindowToken2, 0);
appWindowToken2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
index f79908e906c7..1819c56735eb 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
@@ -16,14 +16,9 @@
package com.android.server.wm;
-import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
-
-import android.hardware.display.DisplayManagerGlobal;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.Display;
-import android.view.DisplayInfo;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -45,10 +40,10 @@ public class TaskWindowContainerControllerTests extends WindowTestsBase {
@Test
public void testRemoveContainer() throws Exception {
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController();
- final TestAppWindowContainerController appController =
- new TestAppWindowContainerController(taskController);
+ final WindowTestUtils.TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController();
+ final WindowTestUtils.TestAppWindowContainerController appController =
+ new WindowTestUtils.TestAppWindowContainerController(taskController);
taskController.removeContainer();
// Assert that the container was removed.
@@ -58,12 +53,12 @@ public class TaskWindowContainerControllerTests extends WindowTestsBase {
@Test
public void testRemoveContainer_deferRemoval() throws Exception {
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController();
- final TestAppWindowContainerController appController =
- new TestAppWindowContainerController(taskController);
+ final WindowTestUtils.TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController();
+ final WindowTestUtils.TestAppWindowContainerController appController =
+ new WindowTestUtils.TestAppWindowContainerController(taskController);
- final TestTask task = (TestTask) taskController.mContainer;
+ final WindowTestUtils.TestTask task = (WindowTestUtils.TestTask) taskController.mContainer;
final AppWindowToken app = appController.mContainer;
task.mShouldDeferRemoval = true;
@@ -85,12 +80,12 @@ public class TaskWindowContainerControllerTests extends WindowTestsBase {
public void testReparent() throws Exception {
final StackWindowController stackController1 =
createStackControllerOnDisplay(sDisplayContent);
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController(stackController1);
+ final WindowTestUtils.TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController(stackController1);
final StackWindowController stackController2 =
createStackControllerOnDisplay(sDisplayContent);
- final TestTaskWindowContainerController taskController2 =
- new TestTaskWindowContainerController(stackController2);
+ final WindowTestUtils.TestTaskWindowContainerController taskController2 =
+ new WindowTestUtils.TestTaskWindowContainerController(stackController2);
boolean gotException = false;
try {
@@ -114,8 +109,8 @@ public class TaskWindowContainerControllerTests extends WindowTestsBase {
taskController.reparent(stackController2, 0);
assertEquals(stackController2.mContainer, taskController.mContainer.getParent());
- assertEquals(0, ((TestTask) taskController.mContainer).positionInParent());
- assertEquals(1, ((TestTask) taskController2.mContainer).positionInParent());
+ assertEquals(0, ((WindowTestUtils.TestTask) taskController.mContainer).positionInParent());
+ assertEquals(1, ((WindowTestUtils.TestTask) taskController2.mContainer).positionInParent());
}
@Test
@@ -124,9 +119,9 @@ public class TaskWindowContainerControllerTests extends WindowTestsBase {
final StackWindowController stack1Controller =
createStackControllerOnDisplay(sDisplayContent);
final TaskStack stack1 = stack1Controller.mContainer;
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController(stack1Controller);
- final TestTask task1 = (TestTask) taskController.mContainer;
+ final WindowTestUtils.TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController(stack1Controller);
+ final WindowTestUtils.TestTask task1 = (WindowTestUtils.TestTask) taskController.mContainer;
task1.mOnDisplayChangedCalled = false;
assertEquals(sDisplayContent, stack1.getDisplayContent());
@@ -134,9 +129,10 @@ public class TaskWindowContainerControllerTests extends WindowTestsBase {
final DisplayContent dc = createNewDisplay();
final StackWindowController stack2Controller = createStackControllerOnDisplay(dc);
final TaskStack stack2 = stack2Controller.mContainer;
- final TestTaskWindowContainerController taskController2 =
- new TestTaskWindowContainerController(stack2Controller);
- final TestTask task2 = (TestTask) taskController2.mContainer;
+ final WindowTestUtils.TestTaskWindowContainerController taskController2 =
+ new WindowTestUtils.TestTaskWindowContainerController(stack2Controller);
+ final WindowTestUtils.TestTask task2 =
+ (WindowTestUtils.TestTask) taskController2.mContainer;
// Reparent and check state
taskController.reparent(stack2Controller, 0);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 0b72a21ca30d..fbeda0a9191c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
+import android.content.pm.ActivityInfo;
import android.os.PowerSaveState;
import org.mockito.invocation.InvocationOnMock;
@@ -449,9 +450,8 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
}
@Override
- public boolean rotationHasCompatibleMetricsLw(int orientation,
- int rotation) {
- return false;
+ public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
+ return true;
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index cf8af6716d34..0eaf5bc3e940 100644
--- a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -46,7 +46,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testFlow() throws Exception {
- final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ final AppWindowToken token = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
sWm.mUnknownAppVisibilityController.notifyLaunched(token);
sWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token);
sWm.mUnknownAppVisibilityController.notifyRelayouted(token);
@@ -58,8 +58,8 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testMultiple() throws Exception {
- final AppWindowToken token1 = new TestAppWindowToken(sDisplayContent);
- final AppWindowToken token2 = new TestAppWindowToken(sDisplayContent);
+ final AppWindowToken token1 = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
+ final AppWindowToken token2 = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
sWm.mUnknownAppVisibilityController.notifyLaunched(token1);
sWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token1);
sWm.mUnknownAppVisibilityController.notifyLaunched(token2);
@@ -74,7 +74,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testClear() throws Exception {
- final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ final AppWindowToken token = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
sWm.mUnknownAppVisibilityController.notifyLaunched(token);
sWm.mUnknownAppVisibilityController.clear();;
assertTrue(sWm.mUnknownAppVisibilityController.allResolved());
@@ -82,7 +82,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testAppRemoved() throws Exception {
- final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ final AppWindowToken token = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
sWm.mUnknownAppVisibilityController.notifyLaunched(token);
sWm.mUnknownAppVisibilityController.appRemoved(token);
assertTrue(sWm.mUnknownAppVisibilityController.allResolved());
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index 1b1984dba8f4..a2aa058ac063 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -102,7 +102,7 @@ public class WindowFrameTests extends WindowTestsBase {
// Just any non zero value.
sWm.mSystemDecorLayer = 10000;
- mWindowToken = new TestAppWindowToken(sWm.getDefaultDisplayContentLocked());
+ mWindowToken = new WindowTestUtils.TestAppWindowToken(sWm.getDefaultDisplayContentLocked());
mStubStack = new TaskStack(sWm, 0);
}
@@ -250,37 +250,57 @@ public class WindowFrameTests extends WindowTestsBase {
@Test
public void testLayoutNonfullscreenTask() {
- final Rect taskBounds = new Rect(300, 300, 700, 700);
+ final DisplayInfo displayInfo = sWm.getDefaultDisplayContentLocked().getDisplayInfo();
+ final int logicalWidth = displayInfo.logicalWidth;
+ final int logicalHeight = displayInfo.logicalHeight;
+
+ final int taskLeft = logicalWidth / 4;
+ final int taskTop = logicalHeight / 4;
+ final int taskRight = logicalWidth / 4 * 3;
+ final int taskBottom = logicalHeight / 4 * 3;
+ final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
TaskWithBounds task = new TaskWithBounds(taskBounds);
task.mFullscreenForTest = false;
WindowState w = createWindow(task, FILL_PARENT, FILL_PARENT);
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
- final Rect pf = new Rect(0, 0, 1000, 1000);
+ final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, null);
// For non fullscreen tasks the containing frame is based off the
// task bounds not the parent frame.
- assertRect(w.mFrame, 300, 300, 700, 700);
- assertRect(w.getContentFrameLw(), 300, 300, 700, 700);
+ assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
+ assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight, taskBottom);
assertRect(w.mContentInsets, 0, 0, 0, 0);
- pf.set(0, 0, 1000, 1000);
+ pf.set(0, 0, logicalWidth, logicalHeight);
// We still produce insets against the containing frame the same way.
- final Rect cf = new Rect(0, 0, 500, 500);
+ final int cfRight = logicalWidth / 2;
+ final int cfBottom = logicalHeight / 2;
+ final Rect cf = new Rect(0, 0, cfRight, cfBottom);
w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null);
- assertRect(w.mFrame, 300, 300, 700, 700);
- assertRect(w.getContentFrameLw(), 300, 300, 500, 500);
- assertRect(w.mContentInsets, 0, 0, 200, 200);
-
- pf.set(0, 0, 1000, 1000);
+ assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
+ int contentInsetRight = taskRight - cfRight;
+ int contentInsetBottom = taskBottom - cfBottom;
+ assertRect(w.mContentInsets, 0, 0, contentInsetRight, contentInsetBottom);
+ assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight - contentInsetRight,
+ taskBottom - contentInsetBottom);
+
+ pf.set(0, 0, logicalWidth, logicalHeight);
// However if we set temp inset bounds, the insets will be computed
// as if our window was laid out there, but it will be laid out according to
// the task bounds.
- task.mInsetBounds.set(200, 200, 600, 600);
+ final int insetLeft = logicalWidth / 5;
+ final int insetTop = logicalHeight / 5;
+ final int insetRight = insetLeft + (taskRight - taskLeft);
+ final int insetBottom = insetTop + (taskBottom - taskTop);
+ task.mInsetBounds.set(insetLeft, insetTop, insetRight, insetBottom);
w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null);
- assertRect(w.mFrame, 300, 300, 700, 700);
- assertRect(w.getContentFrameLw(), 300, 300, 600, 600);
- assertRect(w.mContentInsets, 0, 0, 100, 100);
+ assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
+ contentInsetRight = insetRight - cfRight;
+ contentInsetBottom = insetBottom - cfBottom;
+ assertRect(w.mContentInsets, 0, 0, contentInsetRight, contentInsetBottom);
+ assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight - contentInsetRight,
+ taskBottom - contentInsetBottom);
}
@Test
@@ -289,13 +309,16 @@ public class WindowFrameTests extends WindowTestsBase {
new TaskWithBounds(null), FILL_PARENT, FILL_PARENT);
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
- final Rect pf = new Rect(0, 0, 1000, 1000);
+ final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo();
+ final int logicalWidth = displayInfo.logicalWidth;
+ final int logicalHeight = displayInfo.logicalHeight;
+ final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
final Rect df = pf;
final Rect of = df;
final Rect cf = new Rect(pf);
// Produce some insets
- cf.top += 50;
- cf.bottom -= 100;
+ cf.top += displayInfo.logicalWidth / 10;
+ cf.bottom -= displayInfo.logicalWidth / 5;
final Rect vf = cf;
final Rect sf = vf;
// We use a decor content frame with insets to produce cropping.
@@ -308,35 +331,34 @@ public class WindowFrameTests extends WindowTestsBase {
// If we were above system decor we wouldnt' get any cropping though
w.mLayer = sWm.mSystemDecorLayer + 1;
w.calculatePolicyCrop(policyCrop);
- assertRect(policyCrop, 0, 0, 1000, 1000);
+ assertRect(policyCrop, 0, 0, logicalWidth, logicalHeight);
w.mLayer = 1;
dcf.setEmpty();
// Likewise with no decor frame we would get no crop
w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null);
w.calculatePolicyCrop(policyCrop);
- assertRect(policyCrop, 0, 0, 1000, 1000);
+ assertRect(policyCrop, 0, 0, logicalWidth, logicalHeight);
// Now we set up a window which doesn't fill the entire decor frame.
// Normally it would be cropped to it's frame but in the case of docked resizing
// we need to account for the fact the windows surface will be made
// fullscreen and thus also make the crop fullscreen.
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
- w.mAttrs.width = 500;
- w.mAttrs.height = 500;
- w.mRequestedWidth = 500;
- w.mRequestedHeight = 500;
+ w.mAttrs.width = logicalWidth / 2;
+ w.mAttrs.height = logicalHeight / 2;
+ w.mRequestedWidth = logicalWidth / 2;
+ w.mRequestedHeight = logicalHeight / 2;
w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf);
w.calculatePolicyCrop(policyCrop);
// Normally the crop is shrunk from the decor frame
// to the computed window frame.
- assertRect(policyCrop, 0, 0, 500, 500);
+ assertRect(policyCrop, 0, 0, logicalWidth / 2, logicalHeight / 2);
w.mDockedResizingForTest = true;
w.calculatePolicyCrop(policyCrop);
// But if we are docked resizing it won't be, however we will still be
// shrunk to the decor frame and the display.
- final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo();
assertRect(policyCrop, 0, 0,
Math.min(pf.width(), displayInfo.logicalWidth),
Math.min(pf.height(), displayInfo.logicalHeight));
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
new file mode 100644
index 000000000000..3a443575332e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2017 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.app.ActivityManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Binder;
+import android.os.IBinder;
+import android.view.IApplicationToken;
+import android.view.IWindow;
+import android.view.WindowManager;
+
+import static android.app.AppOpsManager.OP_NONE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.res.Configuration.EMPTY;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
+import static org.mockito.Mockito.mock;
+
+/**
+ * A collection of static functions that can be referenced by other test packages to provide access
+ * to WindowManager related test functionality.
+ */
+public class WindowTestUtils {
+ public static int sNextTaskId = 0;
+
+ /**
+ * Retrieves an instance of {@link WindowManagerService}, creating it if necessary.
+ */
+ public static WindowManagerService getWindowManagerService(Context context) {
+ return TestWindowManagerPolicy.getWindowManagerService(context);
+ }
+
+ /**
+ * Creates a mock instance of {@link StackWindowController}.
+ */
+ public static StackWindowController createMockStackWindowContainerController() {
+ StackWindowController controller = mock(StackWindowController.class);
+ controller.mContainer = mock(TestTaskStack.class);
+ return controller;
+ }
+
+ /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
+ public static Task createTaskInStack(WindowManagerService service, TaskStack stack,
+ int userId) {
+ final Task newTask = new Task(WindowTestUtils.sNextTaskId++, stack, userId, service, null,
+ EMPTY, 0, false,
+ false, new ActivityManager.TaskDescription(), null);
+ stack.addTask(newTask, POSITION_TOP);
+ return newTask;
+ }
+
+ /**
+ * An extension of {@link TestTaskStack}, which overrides package scoped methods that would not
+ * normally be mocked out.
+ */
+ public static class TestTaskStack extends TaskStack {
+ TestTaskStack(WindowManagerService service, int stackId) {
+ super(service, stackId);
+ }
+
+ @Override
+ void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) {
+ // Do nothing.
+ }
+ }
+
+ /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
+ public static class TestAppWindowToken extends AppWindowToken {
+
+ TestAppWindowToken(DisplayContent dc) {
+ super(WindowTestsBase.sWm, null, false, dc, true /* fillsParent */,
+ null /* overrideConfig */, null /* bounds */);
+ }
+
+ TestAppWindowToken(WindowManagerService service, IApplicationToken token,
+ boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
+ boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
+ int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
+ boolean alwaysFocusable, AppWindowContainerController controller,
+ Configuration overrideConfig, Rect bounds) {
+ super(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen,
+ showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges,
+ launchTaskBehind, alwaysFocusable, controller, overrideConfig, bounds);
+ }
+
+ int getWindowsCount() {
+ return mChildren.size();
+ }
+
+ boolean hasWindow(WindowState w) {
+ return mChildren.contains(w);
+ }
+
+ WindowState getFirstChild() {
+ return mChildren.getFirst();
+ }
+
+ WindowState getLastChild() {
+ return mChildren.getLast();
+ }
+
+ int positionInParent() {
+ return getParent().mChildren.indexOf(this);
+ }
+ }
+
+ /* Used so we can gain access to some protected members of the {@link WindowToken} class */
+ public static class TestWindowToken extends WindowToken {
+ int adj = 0;
+
+ TestWindowToken(int type, DisplayContent dc) {
+ this(type, dc, false /* persistOnEmpty */);
+ }
+
+ TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
+ super(WindowTestsBase.sWm, mock(IBinder.class), type, persistOnEmpty, dc,
+ false /* ownerCanManageAppTokens */);
+ }
+
+ int getWindowsCount() {
+ return mChildren.size();
+ }
+
+ boolean hasWindow(WindowState w) {
+ return mChildren.contains(w);
+ }
+
+ @Override
+ int getAnimLayerAdjustment() {
+ return adj;
+ }
+ }
+
+ /* Used so we can gain access to some protected members of the {@link Task} class */
+ public static class TestTask extends Task {
+ boolean mShouldDeferRemoval = false;
+ boolean mOnDisplayChangedCalled = false;
+ private boolean mUseLocalIsAnimating = false;
+ private boolean mIsAnimating = false;
+
+ TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
+ Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
+ boolean homeTask, TaskWindowContainerController controller) {
+ super(taskId, stack, userId, service, bounds, overrideConfig, resizeMode,
+ supportsPictureInPicture, homeTask, new ActivityManager.TaskDescription(),
+ controller);
+ }
+
+ boolean shouldDeferRemoval() {
+ return mShouldDeferRemoval;
+ }
+
+ int positionInParent() {
+ return getParent().mChildren.indexOf(this);
+ }
+
+ @Override
+ void onDisplayChanged(DisplayContent dc) {
+ super.onDisplayChanged(dc);
+ mOnDisplayChangedCalled = true;
+ }
+
+ @Override
+ boolean isAnimating() {
+ return mUseLocalIsAnimating ? mIsAnimating : super.isAnimating();
+ }
+
+ void setLocalIsAnimating(boolean isAnimating) {
+ mUseLocalIsAnimating = true;
+ mIsAnimating = isAnimating;
+ }
+ }
+
+ /**
+ * Used so we can gain access to some protected members of {@link TaskWindowContainerController}
+ * class.
+ */
+ public static class TestTaskWindowContainerController extends TaskWindowContainerController {
+
+ TestTaskWindowContainerController() {
+ this(WindowTestsBase.createStackControllerOnDisplay(WindowTestsBase.sDisplayContent));
+ }
+
+ TestTaskWindowContainerController(StackWindowController stackController) {
+ super(sNextTaskId++, new TaskWindowContainerListener() {
+ @Override
+ public void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
+
+ }
+
+ @Override
+ public void requestResize(Rect bounds, int resizeMode) {
+
+ }
+ }, stackController, 0 /* userId */, null /* bounds */,
+ EMPTY /* overrideConfig*/, RESIZE_MODE_UNRESIZEABLE,
+ false /* supportsPictureInPicture */, false /* homeTask*/, true /* toTop*/,
+ true /* showForAllUsers */, new ActivityManager.TaskDescription(), WindowTestsBase.sWm);
+ }
+
+ @Override
+ TestTask createTask(int taskId, TaskStack stack, int userId, Rect bounds,
+ Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
+ boolean homeTask, ActivityManager.TaskDescription taskDescription) {
+ return new TestTask(taskId, stack, userId, mService, bounds, overrideConfig, resizeMode,
+ supportsPictureInPicture, homeTask, this);
+ }
+ }
+
+ public static class TestAppWindowContainerController extends AppWindowContainerController {
+
+ final IApplicationToken mToken;
+
+ TestAppWindowContainerController(TestTaskWindowContainerController taskController) {
+ this(taskController, new TestIApplicationToken());
+ }
+
+ TestAppWindowContainerController(TestTaskWindowContainerController taskController,
+ IApplicationToken token) {
+ super(taskController, token, null /* listener */, 0 /* index */,
+ SCREEN_ORIENTATION_UNSPECIFIED, true /* fullscreen */,
+ true /* showForAllUsers */, 0 /* configChanges */, false /* voiceInteraction */,
+ false /* launchTaskBehind */, false /* alwaysFocusable */,
+ 0 /* targetSdkVersion */, 0 /* rotationAnimationHint */,
+ 0 /* inputDispatchingTimeoutNanos */, WindowTestsBase.sWm, null /* overrideConfig */,
+ null /* bounds */);
+ mToken = token;
+ }
+
+ @Override
+ AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
+ boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
+ boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
+ int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
+ boolean alwaysFocusable, AppWindowContainerController controller,
+ Configuration overrideConfig, Rect bounds) {
+ return new TestAppWindowToken(service, token, voiceInteraction, dc,
+ inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
+ orientation,
+ rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
+ controller, overrideConfig, bounds);
+ }
+
+ AppWindowToken getAppWindowToken() {
+ return (AppWindowToken) WindowTestsBase.sDisplayContent.getWindowToken(mToken.asBinder());
+ }
+ }
+
+ public static class TestIApplicationToken implements IApplicationToken {
+
+ private final Binder mBinder = new Binder();
+ @Override
+ public IBinder asBinder() {
+ return mBinder;
+ }
+ }
+
+ /** Used to track resize reports. */
+ public static class TestWindowState extends WindowState {
+ boolean resizeReported;
+
+ TestWindowState(WindowManagerService service, Session session, IWindow window,
+ WindowManager.LayoutParams attrs, WindowToken token) {
+ super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0,
+ false /* ownerCanAddInternalSystemWindow */);
+ }
+
+ @Override
+ void reportResized() {
+ super.reportResized();
+ resizeReported = true;
+ }
+
+ @Override
+ public boolean isGoneForLayoutLw() {
+ return false;
+ }
+
+ @Override
+ void updateResizingWindowIfNeeded() {
+ // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
+ // the system that it can actually update the window.
+ boolean hadSurface = mHasSurface;
+ mHasSurface = true;
+
+ super.updateResizingWindowIfNeeded();
+
+ mHasSurface = hadSurface;
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index a9d930f5c893..eaf4ac4baf4f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -19,21 +19,16 @@ package com.android.server.wm;
import static android.view.View.VISIBLE;
import android.app.ActivityManager.TaskDescription;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
-import android.os.Binder;
import android.view.Display;
import android.view.DisplayInfo;
-import android.view.IApplicationToken;
import org.junit.Assert;
import org.junit.After;
import org.junit.Before;
import org.mockito.MockitoAnnotations;
-import android.app.ActivityManager.TaskSnapshot;
import android.content.Context;
-import android.os.IBinder;
import android.support.test.InstrumentationRegistry;
import android.view.IWindow;
import android.view.WindowManager;
@@ -41,10 +36,6 @@ import android.view.WindowManager;
import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.AppOpsManager.OP_NONE;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.content.res.Configuration.EMPTY;
-import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
@@ -58,7 +49,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static org.mockito.Mockito.mock;
import com.android.server.AttributeCache;
@@ -78,8 +68,7 @@ class WindowTestsBase {
// make sure we don't collide with any existing display. If we run into no other display, the
// added display should be treated as default. This cannot be the default display
private static int sNextDisplayId = Display.DEFAULT_DISPLAY + 1;
- static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
- private static int sNextTaskId = 0;
+ private static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
private static boolean sOneTimeSetupDone = false;
static DisplayContent sDisplayContent;
@@ -184,14 +173,14 @@ class WindowTestsBase {
private static WindowToken createWindowToken(DisplayContent dc, int stackId, int type) {
if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) {
- return new TestWindowToken(type, dc);
+ return new WindowTestUtils.TestWindowToken(type, dc);
}
final TaskStack stack = stackId == INVALID_STACK_ID
? createTaskStackOnDisplay(dc)
: createStackControllerOnStackOnDisplay(stackId, dc).mContainer;
final Task task = createTaskInStack(stack, 0 /* userId */);
- final TestAppWindowToken token = new TestAppWindowToken(dc);
+ final WindowTestUtils.TestAppWindowToken token = new WindowTestUtils.TestAppWindowToken(dc);
task.addChild(token, 0);
return token;
}
@@ -209,7 +198,7 @@ class WindowTestsBase {
}
WindowState createAppWindow(Task task, int type, String name) {
- final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ final AppWindowToken token = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
task.addChild(token, 0);
return createWindow(null, type, token, name);
}
@@ -260,10 +249,7 @@ class WindowTestsBase {
/** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
static Task createTaskInStack(TaskStack stack, int userId) {
- final Task newTask = new Task(sNextTaskId++, stack, userId, sWm, null, EMPTY, 0, false,
- false, new TaskDescription(), null);
- stack.addTask(newTask, POSITION_TOP);
- return newTask;
+ return WindowTestUtils.createTaskInStack(sWm, stack, userId);
}
/** Creates a {@link DisplayContent} and adds it to the system. */
@@ -274,227 +260,10 @@ class WindowTestsBase {
return new DisplayContent(display, sWm, sLayersController, new WallpaperController(sWm));
}
- /* Used so we can gain access to some protected members of the {@link WindowToken} class */
- static class TestWindowToken extends WindowToken {
- int adj = 0;
-
- TestWindowToken(int type, DisplayContent dc) {
- this(type, dc, false /* persistOnEmpty */);
- }
-
- TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
- super(sWm, mock(IBinder.class), type, persistOnEmpty, dc,
- false /* ownerCanManageAppTokens */);
- }
-
- int getWindowsCount() {
- return mChildren.size();
- }
-
- boolean hasWindow(WindowState w) {
- return mChildren.contains(w);
- }
-
- @Override
- int getAnimLayerAdjustment() {
- return adj;
- }
- }
-
- /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
- static class TestAppWindowToken extends AppWindowToken {
-
- TestAppWindowToken(DisplayContent dc) {
- super(sWm, null, false, dc, true /* fillsParent */, null /* overrideConfig */,
- null /* bounds */);
- }
-
- TestAppWindowToken(WindowManagerService service, IApplicationToken token,
- boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
- boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
- int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
- boolean alwaysFocusable, AppWindowContainerController controller,
- Configuration overrideConfig, Rect bounds) {
- super(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen,
- showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges,
- launchTaskBehind, alwaysFocusable, controller, overrideConfig, bounds);
- }
-
- int getWindowsCount() {
- return mChildren.size();
- }
-
- boolean hasWindow(WindowState w) {
- return mChildren.contains(w);
- }
-
- WindowState getFirstChild() {
- return mChildren.getFirst();
- }
-
- WindowState getLastChild() {
- return mChildren.getLast();
- }
-
- int positionInParent() {
- return getParent().mChildren.indexOf(this);
- }
- }
-
- /* Used so we can gain access to some protected members of the {@link Task} class */
- class TestTask extends Task {
-
- boolean mShouldDeferRemoval = false;
- boolean mOnDisplayChangedCalled = false;
- private boolean mUseLocalIsAnimating = false;
- private boolean mIsAnimating = false;
-
- TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
- Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
- boolean homeTask, TaskWindowContainerController controller) {
- super(taskId, stack, userId, service, bounds, overrideConfig, resizeMode,
- supportsPictureInPicture, homeTask, new TaskDescription(), controller);
- }
-
- boolean shouldDeferRemoval() {
- return mShouldDeferRemoval;
- }
-
- int positionInParent() {
- return getParent().mChildren.indexOf(this);
- }
-
- @Override
- void onDisplayChanged(DisplayContent dc) {
- super.onDisplayChanged(dc);
- mOnDisplayChangedCalled = true;
- }
-
- @Override
- boolean isAnimating() {
- return mUseLocalIsAnimating ? mIsAnimating : super.isAnimating();
- }
-
- void setLocalIsAnimating(boolean isAnimating) {
- mUseLocalIsAnimating = true;
- mIsAnimating = isAnimating;
- }
- }
-
- /**
- * Used so we can gain access to some protected members of {@link TaskWindowContainerController}
- * class.
- */
- class TestTaskWindowContainerController extends TaskWindowContainerController {
-
- TestTaskWindowContainerController() {
- this(createStackControllerOnDisplay(sDisplayContent));
- }
-
- TestTaskWindowContainerController(StackWindowController stackController) {
- super(sNextTaskId++, new TaskWindowContainerListener() {
- @Override
- public void onSnapshotChanged(TaskSnapshot snapshot) {
-
- }
-
- @Override
- public void requestResize(Rect bounds, int resizeMode) {
-
- }
- }, stackController, 0 /* userId */, null /* bounds */,
- EMPTY /* overrideConfig*/, RESIZE_MODE_UNRESIZEABLE,
- false /* supportsPictureInPicture */, false /* homeTask*/, true /* toTop*/,
- true /* showForAllUsers */, new TaskDescription(), sWm);
- }
-
- @Override
- TestTask createTask(int taskId, TaskStack stack, int userId, Rect bounds,
- Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
- boolean homeTask, TaskDescription taskDescription) {
- return new TestTask(taskId, stack, userId, mService, bounds, overrideConfig, resizeMode,
- supportsPictureInPicture, homeTask, this);
- }
- }
-
- class TestAppWindowContainerController extends AppWindowContainerController {
-
- final IApplicationToken mToken;
-
- TestAppWindowContainerController(TestTaskWindowContainerController taskController) {
- this(taskController, new TestIApplicationToken());
- }
-
- TestAppWindowContainerController(TestTaskWindowContainerController taskController,
- IApplicationToken token) {
- super(taskController, token, null /* listener */, 0 /* index */,
- SCREEN_ORIENTATION_UNSPECIFIED, true /* fullscreen */,
- true /* showForAllUsers */, 0 /* configChanges */, false /* voiceInteraction */,
- false /* launchTaskBehind */, false /* alwaysFocusable */,
- 0 /* targetSdkVersion */, 0 /* rotationAnimationHint */,
- 0 /* inputDispatchingTimeoutNanos */, sWm, null /* overrideConfig */,
- null /* bounds */);
- mToken = token;
- }
-
- @Override
- AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
- boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
- boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
- int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
- boolean alwaysFocusable, AppWindowContainerController controller,
- Configuration overrideConfig, Rect bounds) {
- return new TestAppWindowToken(service, token, voiceInteraction, dc,
- inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
- orientation,
- rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
- controller, overrideConfig, bounds);
- }
-
- AppWindowToken getAppWindowToken() {
- return (AppWindowToken) sDisplayContent.getWindowToken(mToken.asBinder());
- }
+ /** Creates a {@link com.android.server.wm.WindowTestUtils.TestWindowState} */
+ WindowTestUtils.TestWindowState createWindowState(WindowManager.LayoutParams attrs,
+ WindowToken token) {
+ return new WindowTestUtils.TestWindowState(sWm, sMockSession, sIWindow, attrs, token);
}
- class TestIApplicationToken implements IApplicationToken {
-
- private final Binder mBinder = new Binder();
- @Override
- public IBinder asBinder() {
- return mBinder;
- }
- }
-
- /** Used to track resize reports. */
- class TestWindowState extends WindowState {
- boolean resizeReported;
-
- TestWindowState(WindowManager.LayoutParams attrs, WindowToken token) {
- super(sWm, sMockSession, sIWindow, token, null, OP_NONE, 0, attrs, 0, 0,
- false /* ownerCanAddInternalSystemWindow */);
- }
-
- @Override
- void reportResized() {
- super.reportResized();
- resizeReported = true;
- }
-
- @Override
- public boolean isGoneForLayoutLw() {
- return false;
- }
-
- @Override
- void updateResizingWindowIfNeeded() {
- // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
- // the system that it can actually update the window.
- boolean hadSurface = mHasSurface;
- mHasSurface = true;
-
- super.updateResizingWindowIfNeeded();
-
- mHasSurface = hadSurface;
- }
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
index babb6d9db31f..4f7ad41050f1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
@@ -46,7 +46,8 @@ public class WindowTokenTests extends WindowTestsBase {
@Test
public void testAddWindow() throws Exception {
- final TestWindowToken token = new TestWindowToken(0, sDisplayContent);
+ final WindowTestUtils.TestWindowToken token =
+ new WindowTestUtils.TestWindowToken(0, sDisplayContent);
assertEquals(0, token.getWindowsCount());
@@ -76,7 +77,7 @@ public class WindowTokenTests extends WindowTestsBase {
@Test
public void testChildRemoval() throws Exception {
final DisplayContent dc = sDisplayContent;
- final TestWindowToken token = new TestWindowToken(0, dc);
+ final WindowTestUtils.TestWindowToken token = new WindowTestUtils.TestWindowToken(0, dc);
assertEquals(token, dc.getWindowToken(token.token));
@@ -95,7 +96,8 @@ public class WindowTokenTests extends WindowTestsBase {
@Test
public void testAdjustAnimLayer() throws Exception {
- final TestWindowToken token = new TestWindowToken(0, sDisplayContent);
+ final WindowTestUtils.TestWindowToken token =
+ new WindowTestUtils.TestWindowToken(0, sDisplayContent);
final WindowState window1 = createWindow(null, TYPE_APPLICATION, token, "window1");
final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token, "window11");
final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token, "window12");
@@ -135,8 +137,9 @@ public class WindowTokenTests extends WindowTestsBase {
*/
@Test
public void testTokenRemovalProcess() throws Exception {
- final TestWindowToken token =
- new TestWindowToken(TYPE_TOAST, sDisplayContent, true /* persistOnEmpty */);
+ final WindowTestUtils.TestWindowToken token =
+ new WindowTestUtils.TestWindowToken(TYPE_TOAST, sDisplayContent,
+ true /* persistOnEmpty */);
// Verify that the token is on the display
assertNotNull(sDisplayContent.getWindowToken(token.token));
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index c34293347814..922f08da643f 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -512,13 +512,6 @@ public class ShortcutManagerTestUtils {
return actualShortcuts;
}
- public static List<ShortcutInfo> assertAllChooser(List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertTrue("ID " + s.getId(), s.isChooser());
- }
- return actualShortcuts;
- }
-
public static List<ShortcutInfo> assertAllPinned(List<ShortcutInfo> actualShortcuts) {
for (ShortcutInfo s : actualShortcuts) {
assertTrue("ID " + s.getId(), s.isPinned());
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index 7b8ebd44e629..01e36f57d1be 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -1039,18 +1039,34 @@ class UsbProfileGroupSettingsManager {
* Start the appropriate package when an device/accessory got attached.
*
* @param intent The intent to start the package
- * @param matches The available resolutions of the intent
+ * @param rawMatches The available resolutions of the intent
* @param defaultActivity The default activity for the device (if set)
* @param device The device if a device was attached
* @param accessory The accessory if a device was attached
*/
- private void resolveActivity(@NonNull Intent intent, @NonNull ArrayList<ResolveInfo> matches,
+ private void resolveActivity(@NonNull Intent intent, @NonNull ArrayList<ResolveInfo> rawMatches,
@Nullable ActivityInfo defaultActivity, @Nullable UsbDevice device,
@Nullable UsbAccessory accessory) {
- int count = matches.size();
+ final int numRawMatches = rawMatches.size();
+
+ // The raw matches contain the activities that can be started but also the intents to switch
+ // between the profiles
+ int numParentActivityMatches = 0;
+ int numNonParentActivityMatches = 0;
+ for (int i = 0; i < numRawMatches; i++) {
+ final ResolveInfo rawMatch = rawMatches.get(i);
+ if (!rawMatch.getComponentInfo().name.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
+ if (UserHandle.getUserHandleForUid(
+ rawMatch.activityInfo.applicationInfo.uid).equals(mParentUser)) {
+ numParentActivityMatches++;
+ } else {
+ numNonParentActivityMatches++;
+ }
+ }
+ }
// don't show the resolver activity if there are no choices available
- if (count == 0) {
+ if (numParentActivityMatches + numNonParentActivityMatches == 0) {
if (accessory != null) {
String uri = accessory.getUri();
if (uri != null && uri.length() > 0) {
@@ -1073,6 +1089,21 @@ class UsbProfileGroupSettingsManager {
return;
}
+ // If only one profile has activity matches, we need to remove all switch intents
+ ArrayList<ResolveInfo> matches;
+ if (numParentActivityMatches == 0 || numNonParentActivityMatches == 0) {
+ matches = new ArrayList<>(numParentActivityMatches + numNonParentActivityMatches);
+
+ for (int i = 0; i < numRawMatches; i++) {
+ ResolveInfo rawMatch = rawMatches.get(i);
+ if (!rawMatch.getComponentInfo().name.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
+ matches.add(rawMatch);
+ }
+ }
+ } else {
+ matches = rawMatches;
+ }
+
if (defaultActivity != null) {
UsbUserSettingsManager defaultRIUserSettings = mSettingsManager.getSettingsForUser(
UserHandle.getUserId(defaultActivity.applicationInfo.uid));
@@ -1101,7 +1132,7 @@ class UsbProfileGroupSettingsManager {
resolverIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
UserHandle user;
- if (count == 1) {
+ if (matches.size() == 1) {
ResolveInfo rInfo = matches.get(0);
// start UsbConfirmActivity if there is only one choice
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 201f3ad5dce7..81f660047c6b 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1178,6 +1178,7 @@ public class SubscriptionManager {
public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId) {
if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+ intent.putExtra(Intent.EXTRA_SUBSCRIPTION_INDEX, subId);
intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
//FIXME this is using phoneId and slotIndex interchangeably
//Eventually, this should be removed as it is not the slot id
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 26c9430408e8..8357a2b535a4 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -877,19 +877,16 @@ public class TelephonyManager {
/**
* USSD return code success.
- * @hide
*/
public static final int USSD_RETURN_SUCCESS = 100;
/**
* USSD return code for failure case.
- * @hide
*/
public static final int USSD_RETURN_FAILURE = -1;
/**
* USSD return code for failure case.
- * @hide
*/
public static final int USSD_ERROR_SERVICE_UNAVAIL = -2;
@@ -2395,7 +2392,7 @@ public class TelephonyManager {
* OR
* {@link android.Manifest.permission#READ_SMS}
* OR
- * {@link android.Manifest.permission#READ_PHONE_NUMBER}
+ * {@link android.Manifest.permission#READ_PHONE_NUMBERS}
* <p>
* The default SMS app can also use this.
*/
@@ -2412,7 +2409,7 @@ public class TelephonyManager {
* OR
* {@link android.Manifest.permission#READ_SMS}
* OR
- * {@link android.Manifest.permission#READ_PHONE_NUMBER}
+ * {@link android.Manifest.permission#READ_PHONE_NUMBERS}
* <p>
* The default SMS app can also use this.
*
@@ -5113,16 +5110,32 @@ public class TelephonyManager {
return new int[0];
}
- public static abstract class OnReceiveUssdResponseCallback {
+ /* The caller of {@link #sendUssdRequest(String, UssdResponseCallback, Handler} provides
+ * once the network returns a USSD message or if there is failure.
+ * Either {@link #onReceiveUssdResponse(TelephonyManager, String, CharSequence} or
+ * {@link #onReceiveUssdResponseFailed(TelephonyManager, String, int} will be called.
+ */
+ public static abstract class UssdResponseCallback {
/**
- ** Called when USSD has succeeded.
+ * Called when USSD has succeeded. The calling app can choose to either display the message
+ * or interpret the message.
+ * @param telephonyManager the TelephonyManager the callback is registered to.
+ * @param request the ussd code sent to the network.
+ * @param response the response from the network.
**/
- public void onReceiveUssdResponse(String request, CharSequence response) {};
+ public void onReceiveUssdResponse(final TelephonyManager telephonyManager,
+ String request, CharSequence response) {};
/**
- ** Called when USSD has failed.
+ * Called when USSD has failed.
+ * @param telephonyManager the TelephonyManager the callback is registered to
+ * @param request the ussd code.
+ * @param failureCode failure code, should be either of
+ * {@link TelephonyManager#USSD_RETURN_FAILURE} or
+ * {@link TelephonyManager#USSD_ERROR_SERVICE_UNAVAIL}.
**/
- public void onReceiveUssdResponseFailed(String request, int failureCode) {};
+ public void onReceiveUssdResponseFailed(final TelephonyManager telephonyManager,
+ String request, int failureCode) {};
}
/**
@@ -5134,13 +5147,14 @@ public class TelephonyManager {
* {@link android.Manifest.permission#CALL_PHONE}
* @param ussdRequest the USSD command to be executed.
* @param callback called by the framework to inform the caller of the result of executing the
- * USSD request (see {@link OnReceiveUssdResponseCallback}).
+ * USSD request (see {@link UssdResponseCallback}).
* @param handler the {@link Handler} to run the request on.
*/
@RequiresPermission(android.Manifest.permission.CALL_PHONE)
public void sendUssdRequest(String ussdRequest,
- final OnReceiveUssdResponseCallback callback, Handler handler) {
- checkNotNull(callback, "OnReceiveUssdResponseCallback cannot be null.");
+ final UssdResponseCallback callback, Handler handler) {
+ checkNotNull(callback, "UssdResponseCallback cannot be null.");
+ final TelephonyManager telephonyManager = this;
ResultReceiver wrappedCallback = new ResultReceiver(handler) {
@Override
@@ -5150,10 +5164,11 @@ public class TelephonyManager {
UssdResponse response = ussdResponse.getParcelable(USSD_RESPONSE);
if (resultCode == USSD_RETURN_SUCCESS) {
- callback.onReceiveUssdResponse(response.getUssdRequest(),
+ callback.onReceiveUssdResponse(telephonyManager, response.getUssdRequest(),
response.getReturnMessage());
} else {
- callback.onReceiveUssdResponseFailed(response.getUssdRequest(), resultCode);
+ callback.onReceiveUssdResponseFailed(telephonyManager,
+ response.getUssdRequest(), resultCode);
}
}
};
@@ -5172,11 +5187,13 @@ public class TelephonyManager {
}
}
- /*
- * @return true, if the device is currently on a technology (e.g. UMTS or LTE) which can support
- * voice and data simultaneously. This can change based on location or network condition.
- */
- public boolean isConcurrentVoiceAndDataAllowed() {
+ /**
+ * Whether the device is currently on a technology (e.g. UMTS or LTE) which can support
+ * voice and data simultaneously. This can change based on location or network condition.
+ *
+ * @return {@code true} if simultaneous voice and data supported, and {@code false} otherwise.
+ */
+ public boolean isConcurrentVoiceAndDataSupported() {
try {
ITelephony telephony = getITelephony();
return (telephony == null ? false : telephony.isConcurrentVoiceAndDataAllowed(mSubId));
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 73ee25ad5bcf..b4c531e99a95 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -334,9 +334,11 @@ public class TelephonyIntents {
* <ul>
* <li><em>subscription</em> - A int, the current default subscription.</li>
* </ul>
+ * @deprecated Use {@link Intent#ACTION_DEFAULT_SUBSCRIPTION_CHANGED}
*/
+ @Deprecated
public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED
- = "android.intent.action.ACTION_DEFAULT_SUBSCRIPTION_CHANGED";
+ = Intent.ACTION_DEFAULT_SUBSCRIPTION_CHANGED;
/**
* Broadcast Action: The default data subscription has changed. This has the following
@@ -364,9 +366,11 @@ public class TelephonyIntents {
* <ul>
* <li><em>subscription</em> - A int, the current sms default subscription.</li>
* </ul>
+ * @deprecated Use {@link Intent#ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED}
*/
+ @Deprecated
public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED
- = "android.intent.action.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED";
+ = Intent.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED;
/*
* Broadcast Action: An attempt to set phone radio type and access technology has changed.
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 04443a53527c..c562cb95ee31 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -80,6 +80,7 @@ import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
import com.android.server.net.NetworkPinner;
+import com.android.server.net.NetworkPolicyManagerInternal;
import java.net.InetAddress;
import java.util.ArrayList;
@@ -713,6 +714,9 @@ public class ConnectivityServiceTest extends AndroidTestCase {
}
mServiceContext = new MockContext(getContext());
+ LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
+ LocalServices.addService(
+ NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
mService = new WrappedConnectivityService(mServiceContext,
mock(INetworkManagementService.class),
mock(INetworkStatsService.class),
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTestBase.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTestBase.java
index 00dddeed3e8c..8739b7fade9a 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTestBase.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTestBase.java
@@ -311,7 +311,6 @@ public class RenderTestBase {
sFrameworkRepo = null;
sProjectResources = null;
sLogger = null;
- sBridge.dispose();
sBridge = null;
TestUtils.gc();
@@ -329,7 +328,6 @@ public class RenderTestBase {
RenderSession session = sBridge.createSession(params);
try {
-
if (frameTimeNanos != -1) {
session.setElapsedFrameTimeNanos(frameTimeNanos);
}
@@ -338,11 +336,13 @@ public class RenderTestBase {
getLogger().error(session.getResult().getException(),
session.getResult().getErrorMessage());
}
- // Render the session with a timeout of 50s.
- Result renderResult = session.render(50000);
- if (!renderResult.isSuccess()) {
- getLogger().error(session.getResult().getException(),
- session.getResult().getErrorMessage());
+ else {
+ // Render the session with a timeout of 50s.
+ Result renderResult = session.render(50000);
+ if (!renderResult.isSuccess()) {
+ getLogger().error(session.getResult().getException(),
+ session.getResult().getErrorMessage());
+ }
}
return RenderResult.getFromSession(session);