summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.txt10
-rw-r--r--api/system-current.txt52
-rw-r--r--api/test-current.txt10
-rw-r--r--core/java/android/app/ActivityManager.java22
-rw-r--r--core/java/android/app/IActivityManager.aidl1
-rw-r--r--core/java/android/app/ITaskStackListener.aidl5
-rw-r--r--core/java/android/app/Notification.java2
-rw-r--r--core/java/android/app/TaskStackListener.java4
-rw-r--r--core/java/android/app/backup/BackupManagerMonitor.java102
-rw-r--r--core/java/android/content/ContentResolver.java50
-rw-r--r--core/java/android/os/Build.java2
-rw-r--r--core/java/android/provider/DocumentsContract.java3
-rw-r--r--core/java/android/service/autofill/AutoFillService.java44
-rw-r--r--core/java/android/service/autofill/FillResponse.java6
-rw-r--r--core/java/android/service/autofill/IAutoFillService.aidl4
-rw-r--r--core/java/android/service/autofill/IAutoFillServiceConnection.aidl26
-rw-r--r--core/java/android/service/autofill/SaveInfo.java56
-rw-r--r--core/java/android/view/NotificationHeaderView.java13
-rw-r--r--core/java/android/view/SurfaceControl.java17
-rw-r--r--core/java/android/view/SurfaceSession.java5
-rw-r--r--core/java/android/view/SurfaceView.java451
-rw-r--r--core/java/android/view/ViewRootImpl.java10
-rw-r--r--core/java/com/android/internal/view/SurfaceCallbackHelper.java21
-rw-r--r--core/jni/android_view_RenderNode.cpp8
-rw-r--r--core/jni/android_view_SurfaceControl.cpp28
-rw-r--r--core/jni/android_view_SurfaceSession.cpp11
-rw-r--r--core/jni/android_view_ThreadedRenderer.cpp4
-rw-r--r--core/jni/fd_utils.cpp59
-rw-r--r--libs/hwui/TreeInfo.h2
-rw-r--r--media/java/android/media/tv/TvView.java4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/applications/PermissionsSummaryHelper.java80
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java98
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemBars.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java29
-rw-r--r--services/autofill/java/com/android/server/autofill/AutoFillManagerService.java23
-rw-r--r--services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java29
-rw-r--r--services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java47
-rw-r--r--services/autofill/java/com/android/server/autofill/RemoteFillService.java22
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java13
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/SaveUi.java17
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java280
-rw-r--r--services/backup/java/com/android/server/backup/TransportManager.java31
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java7
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java124
-rw-r--r--services/core/java/com/android/server/am/ActivityRecord.java9
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java39
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java242
-rw-r--r--services/core/java/com/android/server/am/ActivityStarter.java29
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java50
-rw-r--r--services/core/java/com/android/server/am/BroadcastStats.java36
-rw-r--r--services/core/java/com/android/server/am/TaskChangeNotificationController.java17
-rw-r--r--services/core/java/com/android/server/am/TaskRecord.java175
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java72
-rw-r--r--services/core/java/com/android/server/wm/Task.java3
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java20
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java15
-rw-r--r--tools/aapt2/flatten/XmlFlattener_test.cpp4
-rw-r--r--tools/aapt2/util/Util.h3
-rw-r--r--tools/aapt2/xml/XmlDom.cpp50
-rw-r--r--tools/aapt2/xml/XmlDom_test.cpp19
76 files changed, 1921 insertions, 933 deletions
diff --git a/Android.mk b/Android.mk
index f544620b993f..f318a5a754c1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -265,6 +265,7 @@ LOCAL_SRC_FILES += \
core/java/android/security/IKeystoreService.aidl \
core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl \
core/java/android/service/autofill/IAutoFillService.aidl \
+ core/java/android/service/autofill/IAutoFillServiceConnection.aidl \
core/java/android/service/autofill/IFillCallback.aidl \
core/java/android/service/autofill/ISaveCallback.aidl \
core/java/android/service/carrier/ICarrierService.aidl \
diff --git a/api/current.txt b/api/current.txt
index cf6c925a6efe..8857abc21b64 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3911,8 +3911,9 @@ package android.app {
method public void readFromParcel(android.os.Parcel);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.ActivityManager.RunningAppProcessInfo> CREATOR;
- field public static final int IMPORTANCE_BACKGROUND = 400; // 0x190
- field public static final int IMPORTANCE_EMPTY = 500; // 0x1f4
+ field public static final deprecated int IMPORTANCE_BACKGROUND = 400; // 0x190
+ field public static final int IMPORTANCE_CACHED = 400; // 0x190
+ field public static final deprecated int IMPORTANCE_EMPTY = 500; // 0x1f4
field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
@@ -8450,8 +8451,10 @@ package android.content {
field public static final java.lang.String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*";
field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
+ field public static final java.lang.String EXTRA_HONORED_ARGS = "android.content.extra.HONORED_ARGS";
field public static final java.lang.String EXTRA_REFRESH_SUPPORTED = "android.content.extra.REFRESH_SUPPORTED";
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
+ field public static final java.lang.String EXTRA_TOTAL_SIZE = "android.content.extra.TOTAL_SIZE";
field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
field public static final java.lang.String QUERY_ARG_LIMIT = "android:query-page-limit";
@@ -8462,7 +8465,6 @@ package android.content {
field public static final java.lang.String QUERY_ARG_SQL_SELECTION = "android:query-sql-selection";
field public static final java.lang.String QUERY_ARG_SQL_SELECTION_ARGS = "android:query-sql-selection-args";
field public static final java.lang.String QUERY_ARG_SQL_SORT_ORDER = "android:query-sql-sort-order";
- field public static final java.lang.String QUERY_RESULT_SIZE = "android:query-result-size";
field public static final int QUERY_SORT_DIRECTION_ASCENDING = 0; // 0x0
field public static final int QUERY_SORT_DIRECTION_DESCENDING = 1; // 0x1
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
@@ -36471,6 +36473,7 @@ package android.service.autofill {
public abstract class AutoFillService extends android.app.Service {
ctor public AutoFillService();
+ method public final void disableSelf();
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
@@ -36533,6 +36536,7 @@ package android.service.autofill {
method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
method public android.service.autofill.SaveInfo build();
method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+ method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
}
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 7ef4db8d894b..557b54bea987 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4049,8 +4049,9 @@ package android.app {
method public void readFromParcel(android.os.Parcel);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.ActivityManager.RunningAppProcessInfo> CREATOR;
- field public static final int IMPORTANCE_BACKGROUND = 400; // 0x190
- field public static final int IMPORTANCE_EMPTY = 500; // 0x1f4
+ field public static final deprecated int IMPORTANCE_BACKGROUND = 400; // 0x190
+ field public static final int IMPORTANCE_CACHED = 400; // 0x190
+ field public static final deprecated int IMPORTANCE_EMPTY = 500; // 0x1f4
field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
@@ -6946,26 +6947,64 @@ package android.app.backup {
public class BackupManagerMonitor {
ctor public BackupManagerMonitor();
method public void onEvent(android.os.Bundle);
+ field public static final java.lang.String EXTRA_LOG_CANCEL_ALL = "android.app.backup.extra.LOG_CANCEL_ALL";
field public static final java.lang.String EXTRA_LOG_EVENT_CATEGORY = "android.app.backup.extra.LOG_EVENT_CATEGORY";
field public static final java.lang.String EXTRA_LOG_EVENT_ID = "android.app.backup.extra.LOG_EVENT_ID";
field public static final java.lang.String EXTRA_LOG_EVENT_PACKAGE_NAME = "android.app.backup.extra.LOG_EVENT_PACKAGE_NAME";
field public static final java.lang.String EXTRA_LOG_EVENT_PACKAGE_VERSION = "android.app.backup.extra.LOG_EVENT_PACKAGE_VERSION";
+ field public static final java.lang.String EXTRA_LOG_EXCEPTION_FULL_BACKUP = "android.app.backup.extra.LOG_EXCEPTION_FULL_BACKUP";
+ field public static final java.lang.String EXTRA_LOG_ILLEGAL_KEY = "android.app.backup.extra.LOG_ILLEGAL_KEY";
+ field public static final java.lang.String EXTRA_LOG_MANIFEST_PACKAGE_NAME = "android.app.backup.extra.LOG_MANIFEST_PACKAGE_NAME";
field public static final java.lang.String EXTRA_LOG_OLD_VERSION = "android.app.backup.extra.LOG_OLD_VERSION";
+ field public static final java.lang.String EXTRA_LOG_POLICY_ALLOW_APKS = "android.app.backup.extra.LOG_POLICY_ALLOW_APKS";
+ field public static final java.lang.String EXTRA_LOG_PREFLIGHT_ERROR = "android.app.backup.extra.LOG_PREFLIGHT_ERROR";
+ field public static final java.lang.String EXTRA_LOG_RESTORE_ANYWAY = "android.app.backup.extra.LOG_RESTORE_ANYWAY";
+ field public static final java.lang.String EXTRA_LOG_RESTORE_VERSION = "android.app.backup.extra.LOG_RESTORE_VERSION";
+ field public static final java.lang.String EXTRA_LOG_WIDGET_PACKAGE_NAME = "android.app.backup.extra.LOG_WIDGET_PACKAGE_NAME";
field public static final int LOG_EVENT_CATEGORY_AGENT = 2; // 0x2
field public static final int LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY = 3; // 0x3
field public static final int LOG_EVENT_CATEGORY_TRANSPORT = 1; // 0x1
+ field public static final int LOG_EVENT_ID_APK_NOT_INSTALLED = 40; // 0x28
field public static final int LOG_EVENT_ID_APP_HAS_NO_AGENT = 28; // 0x1c
+ field public static final int LOG_EVENT_ID_BACKUP_DISABLED = 13; // 0xd
+ field public static final int LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK = 41; // 0x29
field public static final int LOG_EVENT_ID_CANT_FIND_AGENT = 30; // 0x1e
- field public static final int LOG_EVENT_ID_FULL_BACKUP_TIMEOUT = 4; // 0x4
+ field public static final int LOG_EVENT_ID_CORRUPT_MANIFEST = 46; // 0x2e
+ field public static final int LOG_EVENT_ID_DEVICE_NOT_PROVISIONED = 14; // 0xe
+ field public static final int LOG_EVENT_ID_ERROR_PREFLIGHT = 16; // 0x10
+ field public static final int LOG_EVENT_ID_EXCEPTION_FULL_BACKUP = 19; // 0x13
+ field public static final int LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE = 43; // 0x2b
+ field public static final int LOG_EVENT_ID_FULL_BACKUP_CANCEL = 4; // 0x4
+ field public static final int LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE = 39; // 0x27
+ field public static final int LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH = 37; // 0x25
field public static final int LOG_EVENT_ID_FULL_RESTORE_TIMEOUT = 45; // 0x2d
- field public static final int LOG_EVENT_ID_KEY_VALUE_BACKUP_TIMEOUT = 21; // 0x15
+ field public static final int LOG_EVENT_ID_ILLEGAL_KEY = 5; // 0x5
+ field public static final int LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL = 21; // 0x15
field public static final int LOG_EVENT_ID_KEY_VALUE_RESTORE_TIMEOUT = 31; // 0x1f
+ field public static final int LOG_EVENT_ID_LOST_TRANSPORT = 25; // 0x19
+ field public static final int LOG_EVENT_ID_MISSING_SIGNATURE = 42; // 0x2a
+ field public static final int LOG_EVENT_ID_NO_DATA_TO_SEND = 7; // 0x7
field public static final int LOG_EVENT_ID_NO_PACKAGES = 49; // 0x31
+ field public static final int LOG_EVENT_ID_NO_PM_METADATA_RECEIVED = 23; // 0x17
field public static final int LOG_EVENT_ID_NO_RESTORE_METADATA_AVAILABLE = 22; // 0x16
+ field public static final int LOG_EVENT_ID_PACKAGE_INELIGIBLE = 9; // 0x9
+ field public static final int LOG_EVENT_ID_PACKAGE_KEY_VALUE_PARTICIPANT = 10; // 0xa
field public static final int LOG_EVENT_ID_PACKAGE_NOT_FOUND = 12; // 0xc
field public static final int LOG_EVENT_ID_PACKAGE_NOT_PRESENT = 26; // 0x1a
+ field public static final int LOG_EVENT_ID_PACKAGE_STOPPED = 11; // 0xb
field public static final int LOG_EVENT_ID_PACKAGE_TRANSPORT_NOT_PRESENT = 15; // 0xf
+ field public static final int LOG_EVENT_ID_PM_AGENT_HAS_NO_METADATA = 24; // 0x18
+ field public static final int LOG_EVENT_ID_QUOTA_HIT_PREFLIGHT = 18; // 0x12
+ field public static final int LOG_EVENT_ID_RESTORE_ANY_VERSION = 34; // 0x22
+ field public static final int LOG_EVENT_ID_RESTORE_VERSION_HIGHER = 27; // 0x1b
+ field public static final int LOG_EVENT_ID_SIGNATURE_MISMATCH = 29; // 0x1d
+ field public static final int LOG_EVENT_ID_SYSTEM_APP_NO_AGENT = 38; // 0x26
+ field public static final int LOG_EVENT_ID_TRANSPORT_IS_NULL = 50; // 0x32
+ field public static final int LOG_EVENT_ID_UNKNOWN_VERSION = 44; // 0x2c
+ field public static final int LOG_EVENT_ID_VERSIONS_MATCH = 35; // 0x23
field public static final int LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER = 36; // 0x24
+ field public static final int LOG_EVENT_ID_WIDGET_METADATA_MISMATCH = 47; // 0x2f
+ field public static final int LOG_EVENT_ID_WIDGET_UNKNOWN_VERSION = 48; // 0x30
}
public abstract class BackupObserver {
@@ -8902,8 +8941,10 @@ package android.content {
field public static final java.lang.String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*";
field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
+ field public static final java.lang.String EXTRA_HONORED_ARGS = "android.content.extra.HONORED_ARGS";
field public static final java.lang.String EXTRA_REFRESH_SUPPORTED = "android.content.extra.REFRESH_SUPPORTED";
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
+ field public static final java.lang.String EXTRA_TOTAL_SIZE = "android.content.extra.TOTAL_SIZE";
field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
field public static final java.lang.String QUERY_ARG_LIMIT = "android:query-page-limit";
@@ -8914,7 +8955,6 @@ package android.content {
field public static final java.lang.String QUERY_ARG_SQL_SELECTION = "android:query-sql-selection";
field public static final java.lang.String QUERY_ARG_SQL_SELECTION_ARGS = "android:query-sql-selection-args";
field public static final java.lang.String QUERY_ARG_SQL_SORT_ORDER = "android:query-sql-sort-order";
- field public static final java.lang.String QUERY_RESULT_SIZE = "android:query-result-size";
field public static final int QUERY_SORT_DIRECTION_ASCENDING = 0; // 0x0
field public static final int QUERY_SORT_DIRECTION_DESCENDING = 1; // 0x1
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
@@ -39394,6 +39434,7 @@ package android.service.autofill {
public abstract class AutoFillService extends android.app.Service {
ctor public AutoFillService();
+ method public final void disableSelf();
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
@@ -39456,6 +39497,7 @@ package android.service.autofill {
method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
method public android.service.autofill.SaveInfo build();
method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+ method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
}
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 5e4911c39e39..e542ee4f3b5d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3920,8 +3920,9 @@ package android.app {
method public void readFromParcel(android.os.Parcel);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.ActivityManager.RunningAppProcessInfo> CREATOR;
- field public static final int IMPORTANCE_BACKGROUND = 400; // 0x190
- field public static final int IMPORTANCE_EMPTY = 500; // 0x1f4
+ field public static final deprecated int IMPORTANCE_BACKGROUND = 400; // 0x190
+ field public static final int IMPORTANCE_CACHED = 400; // 0x190
+ field public static final deprecated int IMPORTANCE_EMPTY = 500; // 0x1f4
field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
@@ -8477,8 +8478,10 @@ package android.content {
field public static final java.lang.String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*";
field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
+ field public static final java.lang.String EXTRA_HONORED_ARGS = "android.content.extra.HONORED_ARGS";
field public static final java.lang.String EXTRA_REFRESH_SUPPORTED = "android.content.extra.REFRESH_SUPPORTED";
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
+ field public static final java.lang.String EXTRA_TOTAL_SIZE = "android.content.extra.TOTAL_SIZE";
field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
field public static final java.lang.String QUERY_ARG_LIMIT = "android:query-page-limit";
@@ -8489,7 +8492,6 @@ package android.content {
field public static final java.lang.String QUERY_ARG_SQL_SELECTION = "android:query-sql-selection";
field public static final java.lang.String QUERY_ARG_SQL_SELECTION_ARGS = "android:query-sql-selection-args";
field public static final java.lang.String QUERY_ARG_SQL_SORT_ORDER = "android:query-sql-sort-order";
- field public static final java.lang.String QUERY_RESULT_SIZE = "android:query-result-size";
field public static final int QUERY_SORT_DIRECTION_ASCENDING = 0; // 0x0
field public static final int QUERY_SORT_DIRECTION_DESCENDING = 1; // 0x1
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
@@ -36610,6 +36612,7 @@ package android.service.autofill {
public abstract class AutoFillService extends android.app.Service {
ctor public AutoFillService();
+ method public final void disableSelf();
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
@@ -36672,6 +36675,7 @@ package android.service.autofill {
method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
method public android.service.autofill.SaveInfo build();
method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+ method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
}
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index fda99660ff74..cae37c6d3762 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3024,14 +3024,22 @@ public class ActivityManager {
/**
* Constant for {@link #importance}: This process process contains
- * background code that is expendable.
+ * cached code that is expendable, not actively running any app components
+ * we care about.
*/
- public static final int IMPORTANCE_BACKGROUND = 400;
+ public static final int IMPORTANCE_CACHED = 400;
+
+ /**
+ * @deprecated Renamed to {@link #IMPORTANCE_CACHED}.
+ */
+ public static final int IMPORTANCE_BACKGROUND = IMPORTANCE_CACHED;
/**
* Constant for {@link #importance}: This process is empty of any
* actively running code.
+ * @deprecated This value is no longer reported, use {@link #IMPORTANCE_CACHED} instead.
*/
+ @Deprecated
public static final int IMPORTANCE_EMPTY = 500;
/**
@@ -3044,7 +3052,7 @@ public class ActivityManager {
if (procState == PROCESS_STATE_NONEXISTENT) {
return IMPORTANCE_GONE;
} else if (procState >= PROCESS_STATE_HOME) {
- return IMPORTANCE_BACKGROUND;
+ return IMPORTANCE_CACHED;
} else if (procState >= PROCESS_STATE_SERVICE) {
return IMPORTANCE_SERVICE;
} else if (procState > PROCESS_STATE_HEAVY_WEIGHT) {
@@ -3066,7 +3074,7 @@ public class ActivityManager {
public static int importanceToProcState(int importance) {
if (importance == IMPORTANCE_GONE) {
return PROCESS_STATE_NONEXISTENT;
- } else if (importance >= IMPORTANCE_BACKGROUND) {
+ } else if (importance >= IMPORTANCE_CACHED) {
return PROCESS_STATE_HOME;
} else if (importance >= IMPORTANCE_SERVICE) {
return PROCESS_STATE_SERVICE;
@@ -3088,8 +3096,8 @@ public class ActivityManager {
/**
* The relative importance level that the system places on this
* process. May be one of {@link #IMPORTANCE_FOREGROUND},
- * {@link #IMPORTANCE_VISIBLE}, {@link #IMPORTANCE_SERVICE},
- * {@link #IMPORTANCE_BACKGROUND}, or {@link #IMPORTANCE_EMPTY}. These
+ * {@link #IMPORTANCE_VISIBLE}, {@link #IMPORTANCE_SERVICE}, or
+ * {@link #IMPORTANCE_CACHED}. These
* constants are numbered so that "more important" values are always
* smaller than "less important" values.
*/
@@ -3101,7 +3109,7 @@ public class ActivityManager {
* utility of processes within a category. This number means nothing
* except that a smaller values are more recently used (and thus
* more important). Currently an LRU value is only maintained for
- * the {@link #IMPORTANCE_BACKGROUND} category, though others may
+ * the {@link #IMPORTANCE_CACHED} category, though others may
* be maintained in the future.
*/
public int lru;
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 853833054746..dad2061e004f 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -522,6 +522,7 @@ interface IActivityManager {
void startLocalVoiceInteraction(in IBinder token, in Bundle options);
void stopLocalVoiceInteraction(in IBinder token);
boolean supportsLocalVoiceInteraction();
+ void notifyPinnedStackAnimationStarted();
void notifyPinnedStackAnimationEnded();
void removeStack(int stackId);
void makePackageIdle(String packageName, int userId);
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 983435024a9b..d8d4bb906fba 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -38,6 +38,11 @@ oneway interface ITaskStackListener {
void onPinnedActivityRestartAttempt(String launchedFromPackage);
/**
+ * Called whenever the pinned stack is starting animating a resize.
+ */
+ void onPinnedStackAnimationStarted();
+
+ /**
* Called whenever the pinned stack is done animating a resize.
*/
void onPinnedStackAnimationEnded();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 34a45dd626e2..3fc459e33594 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4177,7 +4177,7 @@ public class Notification implements Parcelable
}
RemoteViews header = makeNotificationHeader();
-
+ header.setBoolean(R.id.notification_header, "setAcceptAllTouches", true);
if (summary != null) {
mN.extras.putCharSequence(EXTRA_SUB_TEXT, summary);
} else {
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 5a0845f02b29..7a569fc322a6 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -39,6 +39,10 @@ public abstract class TaskStackListener extends ITaskStackListener.Stub {
}
@Override
+ public void onPinnedStackAnimationStarted() throws RemoteException {
+ }
+
+ @Override
public void onPinnedStackAnimationEnded() throws RemoteException {
}
diff --git a/core/java/android/app/backup/BackupManagerMonitor.java b/core/java/android/app/backup/BackupManagerMonitor.java
index d2a623e0b13a..ebad16e0bc3d 100644
--- a/core/java/android/app/backup/BackupManagerMonitor.java
+++ b/core/java/android/app/backup/BackupManagerMonitor.java
@@ -54,26 +54,118 @@ public class BackupManagerMonitor {
public static final String EXTRA_LOG_EVENT_CATEGORY =
"android.app.backup.extra.LOG_EVENT_CATEGORY";
+
+ /**
+ * boolean: when we have an event with id LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL we record if
+ * the call was to cancel backup of all packages
+ */
+ public static final String EXTRA_LOG_CANCEL_ALL = "android.app.backup.extra.LOG_CANCEL_ALL";
+
+ /**
+ * string: when we have an event with id LOG_EVENT_ID_ILLEGAL_KEY we send the key that was used
+ * by the app
+ */
+ public static final String EXTRA_LOG_ILLEGAL_KEY = "android.app.backup.extra.LOG_ILLEGAL_KEY";
+
+ /**
+ * long: when we have an event with id LOG_EVENT_ID_ERROR_PREFLIGHT we send the error code that
+ * was returned by the transport during preflight
+ */
+ public static final String EXTRA_LOG_PREFLIGHT_ERROR =
+ "android.app.backup.extra.LOG_PREFLIGHT_ERROR";
+
+ /**
+ * string: when we have an event with id LOG_EVENT_ID_EXCEPTION_FULL_BACKUP we send the
+ * exception's stacktrace
+ */
+ public static final String EXTRA_LOG_EXCEPTION_FULL_BACKUP =
+ "android.app.backup.extra.LOG_EXCEPTION_FULL_BACKUP";
+
+ /**
+ * int: when we have an event with id LOG_EVENT_ID_RESTORE_VERSION_HIGHER we send the
+ * restore package version
+ */
+ public static final String EXTRA_LOG_RESTORE_VERSION =
+ "android.app.backup.extra.LOG_RESTORE_VERSION";
+
+ /**
+ * boolean: when we have an event with id LOG_EVENT_ID_RESTORE_VERSION_HIGHER we record if
+ * ApplicationInfo.FLAG_RESTORE_ANY_VERSION flag is set
+ */
+ public static final String EXTRA_LOG_RESTORE_ANYWAY =
+ "android.app.backup.extra.LOG_RESTORE_ANYWAY";
+
+
+ /**
+ * boolean: when we have an event with id LOG_EVENT_ID_APK_NOT_INSTALLED we record if
+ * the policy allows to install apks provided with the dataset
+ */
+ public static final String EXTRA_LOG_POLICY_ALLOW_APKS =
+ "android.app.backup.extra.LOG_POLICY_ALLOW_APKS";
+
+
+ /**
+ * string: when we have an event with id LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE we record the
+ * package name provided in the restore manifest
+ */
+ public static final String EXTRA_LOG_MANIFEST_PACKAGE_NAME =
+ "android.app.backup.extra.LOG_MANIFEST_PACKAGE_NAME";
+
+ /**
+ * string: when we have an event with id LOG_EVENT_ID_WIDGET_METADATA_MISMATCH we record the
+ * package name provided in the widget metadata
+ */
+ public static final String EXTRA_LOG_WIDGET_PACKAGE_NAME =
+ "android.app.backup.extra.LOG_WIDGET_PACKAGE_NAME";
+
/**
- * string: when we have event of id LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER we send the version
+ * int: when we have event of id LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER we send the version
* of the backup.
*/
- public static final String EXTRA_LOG_OLD_VERSION =
- "android.app.backup.extra.LOG_OLD_VERSION";
+ public static final String EXTRA_LOG_OLD_VERSION = "android.app.backup.extra.LOG_OLD_VERSION";
// TODO complete this list with all log messages. And document properly.
- public static final int LOG_EVENT_ID_FULL_BACKUP_TIMEOUT = 4;
+ public static final int LOG_EVENT_ID_FULL_BACKUP_CANCEL = 4;
+ public static final int LOG_EVENT_ID_ILLEGAL_KEY = 5;
+ public static final int LOG_EVENT_ID_NO_DATA_TO_SEND = 7;
+ public static final int LOG_EVENT_ID_PACKAGE_INELIGIBLE = 9;
+ public static final int LOG_EVENT_ID_PACKAGE_KEY_VALUE_PARTICIPANT = 10;
+ public static final int LOG_EVENT_ID_PACKAGE_STOPPED = 11;
public static final int LOG_EVENT_ID_PACKAGE_NOT_FOUND = 12;
+ public static final int LOG_EVENT_ID_BACKUP_DISABLED = 13;
+ public static final int LOG_EVENT_ID_DEVICE_NOT_PROVISIONED = 14;
public static final int LOG_EVENT_ID_PACKAGE_TRANSPORT_NOT_PRESENT = 15;
- public static final int LOG_EVENT_ID_KEY_VALUE_BACKUP_TIMEOUT = 21;
+ public static final int LOG_EVENT_ID_ERROR_PREFLIGHT = 16;
+ public static final int LOG_EVENT_ID_QUOTA_HIT_PREFLIGHT = 18;
+ public static final int LOG_EVENT_ID_EXCEPTION_FULL_BACKUP = 19;
+ public static final int LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL = 21;
public static final int LOG_EVENT_ID_NO_RESTORE_METADATA_AVAILABLE = 22;
+ public static final int LOG_EVENT_ID_NO_PM_METADATA_RECEIVED = 23;
+ public static final int LOG_EVENT_ID_PM_AGENT_HAS_NO_METADATA = 24;
+ public static final int LOG_EVENT_ID_LOST_TRANSPORT = 25;
public static final int LOG_EVENT_ID_PACKAGE_NOT_PRESENT = 26;
+ public static final int LOG_EVENT_ID_RESTORE_VERSION_HIGHER = 27;
public static final int LOG_EVENT_ID_APP_HAS_NO_AGENT = 28;
+ public static final int LOG_EVENT_ID_SIGNATURE_MISMATCH = 29;
public static final int LOG_EVENT_ID_CANT_FIND_AGENT = 30;
public static final int LOG_EVENT_ID_KEY_VALUE_RESTORE_TIMEOUT = 31;
+ public static final int LOG_EVENT_ID_RESTORE_ANY_VERSION = 34;
+ public static final int LOG_EVENT_ID_VERSIONS_MATCH = 35;
public static final int LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER = 36;
+ public static final int LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH = 37;
+ public static final int LOG_EVENT_ID_SYSTEM_APP_NO_AGENT = 38;
+ public static final int LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE = 39;
+ public static final int LOG_EVENT_ID_APK_NOT_INSTALLED = 40;
+ public static final int LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK = 41;
+ public static final int LOG_EVENT_ID_MISSING_SIGNATURE = 42;
+ public static final int LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE = 43;
+ public static final int LOG_EVENT_ID_UNKNOWN_VERSION = 44;
public static final int LOG_EVENT_ID_FULL_RESTORE_TIMEOUT = 45;
+ public static final int LOG_EVENT_ID_CORRUPT_MANIFEST = 46;
+ public static final int LOG_EVENT_ID_WIDGET_METADATA_MISMATCH = 47;
+ public static final int LOG_EVENT_ID_WIDGET_UNKNOWN_VERSION = 48;
public static final int LOG_EVENT_ID_NO_PACKAGES = 49;
+ public static final int LOG_EVENT_ID_TRANSPORT_IS_NULL = 50;
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 9958a79ea3ee..5579c9aed925 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -307,6 +307,18 @@ public abstract class ContentResolver {
*/
public static final String QUERY_ARG_SORT_COLLATION = "android:query-sort-collation";
+ /**
+ * Allows provider to report back to client which keys were honored.
+ *
+ * Key identifying a {@code String[]} containing all QUERY_ARG_SORT* arguments
+ * honored by the provider. Include this in {@link Cursor} extras {@link Bundle}
+ * when any QUERY_ARG_SORT* value was honored during the preparation of the
+ * results {@link Cursor}.
+ *
+ * @see #QUERY_ARG_SORT_COLUMNS, #QUERY_ARG_SORT_DIRECTION, #QUERY_ARG_SORT_COLLATION.
+ */
+ public static final String EXTRA_HONORED_ARGS = "android.content.extra.HONORED_ARGS";
+
/** @hide */
@IntDef(flag = false, value = {
QUERY_SORT_DIRECTION_ASCENDING,
@@ -354,8 +366,9 @@ public abstract class ContentResolver {
public static final String QUERY_ARG_LIMIT = "android:query-page-limit";
/**
- * Added to {@link Cursor} extras {@link Bundle} to indicate size of the
- * full, un-offset, un-limited recordset.
+ * Added to {@link Cursor} extras {@link Bundle} to indicate total size of
+ * recordset when paging is active. Providers must include this when
+ * implementing paging support.
*
* <p>When full size of the recordset is unknown a provider may return -1
* to indicate this.
@@ -364,7 +377,7 @@ public abstract class ContentResolver {
* send content change notification once (if) full recordset size becomes
* known.
*/
- public static final String QUERY_RESULT_SIZE = "android:query-result-size";
+ public static final String EXTRA_TOTAL_SIZE = "android.content.extra.TOTAL_SIZE";
/**
* This is the Android platform's base MIME type for a content: URI
@@ -704,6 +717,13 @@ public abstract class ContentResolver {
* <li>Provide an explicit projection, to prevent reading data from storage
* that aren't going to be used.
*
+ * Provider must identify which QUERY_ARG_SORT* arguments were honored during
+ * the preparation of the result set by including the respective argument keys
+ * in the {@link Cursor} extras {@link Bundle}. See {@link #EXTRA_HONORED_ARGS}
+ * for details.
+ *
+ * @see #QUERY_ARG_SORT_COLUMNS, #QUERY_ARG_SORT_DIRECTION, #QUERY_ARG_SORT_COLLATION.
+ *
* @param uri The URI, using the content:// scheme, for the content to
* retrieve.
* @param projection A list of which columns to return. Passing null will
@@ -3037,17 +3057,19 @@ public abstract class ContentResolver {
query += " COLLATE NOCASE";
}
- switch (queryArgs.getInt(
- QUERY_ARG_SORT_DIRECTION, Integer.MIN_VALUE)) {
- case QUERY_SORT_DIRECTION_ASCENDING:
- query += " ASC";
- break;
- case QUERY_SORT_DIRECTION_DESCENDING:
- query += " DESC";
- break;
- default:
- throw new IllegalArgumentException("Unsupported sort direction value."
- + " See ContentResolver documentation for details.");
+ int sortDir = queryArgs.getInt(QUERY_ARG_SORT_DIRECTION, Integer.MIN_VALUE);
+ if (sortDir != Integer.MIN_VALUE) {
+ switch (sortDir) {
+ case QUERY_SORT_DIRECTION_ASCENDING:
+ query += " ASC";
+ break;
+ case QUERY_SORT_DIRECTION_DESCENDING:
+ query += " DESC";
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported sort direction value."
+ + " See ContentResolver documentation for details.");
+ }
}
return query;
}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 817cb5bb9add..0610499dbce4 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -275,7 +275,7 @@ public class Build {
* Magic version number for a current development build, which has
* not yet turned into an official release.
*/
- public static final int CUR_DEVELOPMENT = 10000;
+ public static final int CUR_DEVELOPMENT = VMRuntime.SDK_VERSION_CUR_DEVELOPMENT;
/**
* October 2008: The original, first, version of Android. Yay!
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 71a0349bce54..33b59038c106 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -119,6 +119,9 @@ public final class DocumentsContract {
* <p>Location should specify a document URI or a tree URI with document ID. If
* this URI identifies a non-directory, document navigator will attempt to use the parent
* of the document as the initial location.
+ *
+ * <p>The initial location is system specific if this extra is missing or document navigator
+ * failed to locate the desired initial location.
*/
public static final String EXTRA_INITIAL_URI = "android.provider.extra.INITIAL_URI";
diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java
index 4099f59ec9ef..3c211eb972e7 100644
--- a/core/java/android/service/autofill/AutoFillService.java
+++ b/core/java/android/service/autofill/AutoFillService.java
@@ -15,9 +15,12 @@
*/
package android.service.autofill;
+import android.accessibilityservice.IAccessibilityServiceConnection;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Message;
import android.os.RemoteException;
+import android.view.accessibility.AccessibilityInteractionClient;
import com.android.internal.os.HandlerCaller;
import android.annotation.SdkConstant;
import android.app.Activity;
@@ -79,6 +82,15 @@ public abstract class AutoFillService extends Service {
private final IAutoFillService mInterface = new IAutoFillService.Stub() {
@Override
+ public void onInit(IAutoFillServiceConnection connection) {
+ if (connection != null) {
+ mHandlerCaller.obtainMessageO(MSG_CONNECT, connection).sendToTarget();
+ } else {
+ mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget();
+ }
+ }
+
+ @Override
public void onFillRequest(AssistStructure structure, Bundle extras,
IFillCallback callback) {
ICancellationSignal transport = CancellationSignal.createTransport();
@@ -98,21 +110,12 @@ public abstract class AutoFillService extends Service {
mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure,
extras, callback).sendToTarget();
}
-
- @Override
- public void onConnected() {
- mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_CONNECT));
- }
-
- @Override
- public void onDisconnected() {
- mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_DISCONNECT));
- }
};
private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
switch (msg.what) {
case MSG_CONNECT: {
+ mConnection = (IAutoFillServiceConnection) msg.obj;
onConnected();
break;
} case MSG_ON_FILL_REQUEST: {
@@ -136,6 +139,7 @@ public abstract class AutoFillService extends Service {
break;
} case MSG_DISCONNECT: {
onDisconnected();
+ mConnection = null;
break;
} default: {
Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
@@ -145,6 +149,8 @@ public abstract class AutoFillService extends Service {
private HandlerCaller mHandlerCaller;
+ private IAutoFillServiceConnection mConnection;
+
/**
* {@inheritDoc}
*
@@ -223,4 +229,22 @@ public abstract class AutoFillService extends Service {
public void onDisconnected() {
//TODO(b/33197203): is not called anymore, fix it!
}
+
+ /**
+ * Disables the service. After calling this method, the service will
+ * be disabled and settings will show that it is turned off.
+ *
+ * <p>You should call this method only after a call to {@link #onConnected()}
+ * and before the corresponding call to {@link #onDisconnected()}. In other words
+ * you can disable your service only while the system is connected to it.</p>
+ */
+ public final void disableSelf() {
+ if (mConnection != null) {
+ try {
+ mConnection.disableSelf();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ }
}
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index ba75c8bee039..ef551ad29623 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -171,7 +171,7 @@ public final class FillResponse implements Parcelable {
if (false) {
// TODO(b/33197203, 35727295): this is how mSaveInfo will be set once we don't support
- // FillResponse.setSavableIds()
+ // FillResponse.addSavableIds()
mSaveInfo = builder.mSaveInfo;
if (mSaveInfo != null) {
mSaveInfo.addSavableIds(mDatasets);
@@ -181,11 +181,11 @@ public final class FillResponse implements Parcelable {
}
}
} else {
- // Temporary workaround to support FillResponse.setSavableIds()
+ // Temporary workaround to support FillResponse.addSavableIds()
SaveInfo saveInfo = builder.mSaveInfoBuilder != null ? builder.mSaveInfoBuilder.build()
: builder.mSaveInfo;
- // Handle the the case where service didn't call setSavableIds() because it would
+ // Handle the the case where service didn't call addSavableIds() because it would
// contain just the ids from the datasets.
if (saveInfo == null && mDatasets != null) {
saveInfo = new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_GENERIC).build();
diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl
index fa1ea65e30b0..80685d87a788 100644
--- a/core/java/android/service/autofill/IAutoFillService.aidl
+++ b/core/java/android/service/autofill/IAutoFillService.aidl
@@ -18,6 +18,7 @@ package android.service.autofill;
import android.app.assist.AssistStructure;
import android.os.Bundle;
+import android.service.autofill.IAutoFillServiceConnection;
import android.service.autofill.IFillCallback;
import android.service.autofill.ISaveCallback;
import com.android.internal.os.IResultReceiver;
@@ -28,10 +29,9 @@ import com.android.internal.os.IResultReceiver;
* @hide
*/
oneway interface IAutoFillService {
+ void onInit(in IAutoFillServiceConnection connection);
void onFillRequest(in AssistStructure structure, in Bundle extras,
in IFillCallback callback);
void onSaveRequest(in AssistStructure structure, in Bundle extras,
in ISaveCallback callback);
- void onConnected();
- void onDisconnected();
}
diff --git a/core/java/android/service/autofill/IAutoFillServiceConnection.aidl b/core/java/android/service/autofill/IAutoFillServiceConnection.aidl
new file mode 100644
index 000000000000..cf73a10ca58c
--- /dev/null
+++ b/core/java/android/service/autofill/IAutoFillServiceConnection.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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.service.autofill;
+
+/**
+ * Interface from an auto fill service to the system.
+ *
+ * @hide
+ */
+interface IAutoFillServiceConnection {
+ void disableSelf();
+}
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 096f28b60687..a8f9aeedb6b9 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -21,6 +21,7 @@ import static android.view.autofill.Helper.DEBUG;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.IntentSender;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -72,6 +73,8 @@ public final class SaveInfo implements Parcelable {
public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3;
private final @SaveDataType int mType;
+ private CharSequence mNegativeActionTitle;
+ private IntentSender mNegativeActionListener;
private ArraySet<AutoFillId> mSavableIds;
private final CharSequence mDescription;
@@ -88,11 +91,23 @@ public final class SaveInfo implements Parcelable {
private SaveInfo(Builder builder) {
mType = builder.mType;
+ mNegativeActionTitle = builder.mNegativeActionTitle;
+ mNegativeActionListener = builder.mNegativeActionListener;
mSavableIds = builder.mSavableIds;
mDescription = builder.mDescription;
}
/** @hide */
+ public @Nullable CharSequence getNegativeActionTitle() {
+ return mNegativeActionTitle;
+ }
+
+ /** @hide */
+ public @Nullable IntentSender getNegativeActionListener() {
+ return mNegativeActionListener;
+ }
+
+ /** @hide */
public @Nullable ArraySet<AutoFillId> getSavableIds() {
return mSavableIds;
}
@@ -132,6 +147,8 @@ public final class SaveInfo implements Parcelable {
public static final class Builder {
private final @SaveDataType int mType;
+ private CharSequence mNegativeActionTitle;
+ private IntentSender mNegativeActionListener;
private ArraySet<AutoFillId> mSavableIds;
private CharSequence mDescription;
private boolean mDestroyed;
@@ -195,6 +212,42 @@ public final class SaveInfo implements Parcelable {
}
/**
+ * Sets the title and listener for the negative save action.
+ *
+ * <p>This allows a fill-provider to customize the text and be
+ * notified when the user selects the negative action in the save
+ * UI. Note that selecting the negative action regardless of its text
+ * and listener being customized would dismiss the save UI and if a
+ * custom listener intent is provided then this intent will be
+ * started.</p>
+ *
+ * <p>This customization could be useful for providing additional
+ * semantics to the negative action. For example, a fill-provider
+ * can use this mechanism to add a "Disable" function or a "More info"
+ * function, etc. Note that the save action is exclusively controlled
+ * by the platform to ensure user consent is collected to release
+ * data from the filled app to the fill-provider.</p>
+ *
+ * @param title The action title.
+ * @param listener The action listener.
+ * @return This builder.
+ *
+ * @throws IllegalArgumentException If the title and the listener
+ * are not both either null or non-null.
+ */
+ public @NonNull Builder setNegativeAction(@Nullable CharSequence title,
+ @Nullable IntentSender listener) {
+ throwIfDestroyed();
+ if (title == null ^ listener == null) {
+ throw new IllegalArgumentException("title and listener"
+ + " must be both non-null or null");
+ }
+ mNegativeActionTitle = title;
+ mNegativeActionListener = listener;
+ return this;
+ }
+
+ /**
* Builds a new {@link SaveInfo} instance.
*/
public SaveInfo build() {
@@ -235,6 +288,8 @@ public final class SaveInfo implements Parcelable {
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mType);
+ parcel.writeCharSequence(mNegativeActionTitle);
+ parcel.writeParcelable(mNegativeActionListener, flags);
parcel.writeTypedArraySet(mSavableIds, flags);
parcel.writeCharSequence(mDescription);
}
@@ -246,6 +301,7 @@ public final class SaveInfo implements Parcelable {
// the system obeys the contract of the builder to avoid attacks
// using specially crafted parcels.
final Builder builder = new Builder(parcel.readInt());
+ builder.setNegativeAction(parcel.readCharSequence(), parcel.readParcelable(null));
final ArraySet<AutoFillId> savableIds = parcel.readTypedArraySet(null);
final int savableIdsCount = (savableIds != null) ? savableIds.size() : 0;
for (int i = 0; i < savableIdsCount; i++) {
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index c3d3f3918ccf..16d46666732d 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -94,6 +94,7 @@ public class NotificationHeaderView extends ViewGroup {
}
}
};
+ private boolean mAcceptAllTouches;
public NotificationHeaderView(Context context) {
this(context, null);
@@ -374,6 +375,8 @@ public class NotificationHeaderView extends ViewGroup {
case MotionEvent.ACTION_DOWN:
mTrackGesture = false;
if (isInside(x, y)) {
+ mDownX = x;
+ mDownY = y;
mTrackGesture = true;
return true;
}
@@ -396,11 +399,12 @@ public class NotificationHeaderView extends ViewGroup {
}
private boolean isInside(float x, float y) {
+ if (mAcceptAllTouches) {
+ return true;
+ }
for (int i = 0; i < mTouchRects.size(); i++) {
Rect r = mTouchRects.get(i);
if (r.contains((int) x, (int) y)) {
- mDownX = x;
- mDownY = y;
return true;
}
}
@@ -433,4 +437,9 @@ public class NotificationHeaderView extends ViewGroup {
}
return mTouchListener.isInside(x, y);
}
+
+ @RemotableViewMethod
+ public void setAcceptAllTouches(boolean acceptAllTouches) {
+ mAcceptAllTouches = acceptAllTouches;
+ }
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 0ac16c1fa023..b718696b2202 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -95,11 +95,6 @@ public class SurfaceControl {
IBinder displayToken, int mode);
private static native void nativeDeferTransactionUntil(long nativeObject,
IBinder handle, long frame);
- private static native void nativeDeferTransactionUntilSurface(long nativeObject,
- long surfaceObject, long frame);
- private static native void nativeReparentChildren(long nativeObject,
- IBinder handle);
- private static native void nativeSeverChildren(long nativeObject);
private static native void nativeSetOverrideScalingMode(long nativeObject,
int scalingMode);
private static native IBinder nativeGetHandle(long nativeObject);
@@ -426,18 +421,6 @@ public class SurfaceControl {
nativeDeferTransactionUntil(mNativeObject, handle, frame);
}
- public void deferTransactionUntil(Surface barrier, long frame) {
- nativeDeferTransactionUntilSurface(mNativeObject, barrier.mNativeObject, frame);
- }
-
- public void reparentChildren(IBinder newParentHandle) {
- nativeReparentChildren(mNativeObject, newParentHandle);
- }
-
- public void detachChildren() {
- nativeSeverChildren(mNativeObject);
- }
-
public void setOverrideScalingMode(int scalingMode) {
checkNotReleased();
nativeSetOverrideScalingMode(mNativeObject, scalingMode);
diff --git a/core/java/android/view/SurfaceSession.java b/core/java/android/view/SurfaceSession.java
index b5912bc1e1c8..3cf5af484625 100644
--- a/core/java/android/view/SurfaceSession.java
+++ b/core/java/android/view/SurfaceSession.java
@@ -27,7 +27,6 @@ public final class SurfaceSession {
private long mNativeClient; // SurfaceComposerClient*
private static native long nativeCreate();
- private static native long nativeCreateScoped(long surfacePtr);
private static native void nativeDestroy(long ptr);
private static native void nativeKill(long ptr);
@@ -36,10 +35,6 @@ public final class SurfaceSession {
mNativeClient = nativeCreate();
}
- public SurfaceSession(Surface root) {
- mNativeClient = nativeCreateScoped(root.mNativeObject);
- }
-
/* no user serviceable parts here ... */
@Override
protected void finalize() throws Throwable {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 61b12475d542..d2577d48c3d1 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -16,10 +16,6 @@
package android.view;
-import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_SUBLAYER;
-import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_OVERLAY_SUBLAYER;
-import static android.view.WindowManagerPolicy.APPLICATION_PANEL_SUBLAYER;
-
import android.content.Context;
import android.content.res.CompatibilityInfo.Translator;
import android.content.res.Configuration;
@@ -30,12 +26,16 @@ import android.graphics.Rect;
import android.graphics.Region;
import android.os.Handler;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
+import com.android.internal.view.BaseIWindow;
import com.android.internal.view.SurfaceCallbackHelper;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;
@@ -92,8 +92,8 @@ import java.util.concurrent.locks.ReentrantLock;
* positioned asynchronously.</p>
*/
public class SurfaceView extends View {
- private static final String TAG = "SurfaceView";
- private static final boolean DEBUG = false;
+ static private final String TAG = "SurfaceView";
+ static private final boolean DEBUG = false;
final ArrayList<SurfaceHolder.Callback> mCallbacks
= new ArrayList<SurfaceHolder.Callback>();
@@ -102,23 +102,28 @@ public class SurfaceView extends View {
final ReentrantLock mSurfaceLock = new ReentrantLock();
final Surface mSurface = new Surface(); // Current surface in use
+ final Surface mNewSurface = new Surface(); // New surface we are switching to
boolean mDrawingStopped = true;
- // We use this to track if the application has produced a frame
- // in to the Surface. Up until that point, we should be careful not to punch
- // holes.
- boolean mDrawFinished = false;
-
- final Rect mScreenRect = new Rect();
- SurfaceSession mSurfaceSession;
- SurfaceControl mSurfaceControl;
+ final WindowManager.LayoutParams mLayout
+ = new WindowManager.LayoutParams();
+ IWindowSession mSession;
+ MyWindow mWindow;
+ final Rect mVisibleInsets = new Rect();
+ final Rect mWinFrame = new Rect();
+ final Rect mOverscanInsets = new Rect();
+ final Rect mContentInsets = new Rect();
+ final Rect mStableInsets = new Rect();
+ final Rect mOutsets = new Rect();
+ final Rect mBackdropFrame = new Rect();
final Rect mTmpRect = new Rect();
final Configuration mConfiguration = new Configuration();
static final int KEEP_SCREEN_ON_MSG = 1;
- static final int DRAW_FINISHED_MSG = 2;
+ static final int GET_NEW_SURFACE_MSG = 2;
+ static final int UPDATE_WINDOW_MSG = 3;
- int mSubLayer = APPLICATION_MEDIA_SUBLAYER;
+ int mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
boolean mIsCreating = false;
private volatile boolean mRtHandlingPositionUpdates = false;
@@ -130,9 +135,11 @@ public class SurfaceView extends View {
case KEEP_SCREEN_ON_MSG: {
setKeepScreenOn(msg.arg1 != 0);
} break;
- case DRAW_FINISHED_MSG: {
- mDrawFinished = true;
- invalidate();
+ case GET_NEW_SURFACE_MSG: {
+ handleGetNewSurface();
+ } break;
+ case UPDATE_WINDOW_MSG: {
+ updateWindow();
} break;
}
}
@@ -142,7 +149,7 @@ public class SurfaceView extends View {
= new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
- updateSurface();
+ updateWindow();
}
};
@@ -152,14 +159,13 @@ public class SurfaceView extends View {
public boolean onPreDraw() {
// reposition ourselves where the surface is
mHaveFrame = getWidth() > 0 && getHeight() > 0;
- updateSurface();
+ updateWindow();
return true;
}
};
boolean mRequestedVisible = false;
boolean mWindowVisibility = false;
- boolean mLastWindowVisibility = false;
boolean mViewVisibility = false;
int mRequestedWidth = -1;
int mRequestedHeight = -1;
@@ -175,17 +181,19 @@ public class SurfaceView extends View {
boolean mVisible = false;
int mWindowSpaceLeft = -1;
int mWindowSpaceTop = -1;
- int mSurfaceWidth = -1;
- int mSurfaceHeight = -1;
+ int mWindowSpaceWidth = -1;
+ int mWindowSpaceHeight = -1;
int mFormat = -1;
final Rect mSurfaceFrame = new Rect();
int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
+ boolean mUpdateWindowNeeded;
+ boolean mReportDrawNeeded;
private Translator mTranslator;
+ private int mWindowInsetLeft;
+ private int mWindowInsetTop;
private boolean mGlobalListenersAdded;
- private int mSurfaceFlags = SurfaceControl.HIDDEN;
-
public SurfaceView(Context context) {
this(context, null);
}
@@ -219,8 +227,11 @@ public class SurfaceView extends View {
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mParent.requestTransparentRegion(this);
+ mSession = getWindowSession();
+ mLayout.token = getWindowToken();
+ mLayout.setTitle("SurfaceView - " + getViewRootImpl().getTitle());
+ mLayout.packageName = mContext.getOpPackageName();
mViewVisibility = getVisibility() == VISIBLE;
- mRequestedVisible = mViewVisibility && mWindowVisibility;
if (!mGlobalListenersAdded) {
ViewTreeObserver observer = getViewTreeObserver();
@@ -235,7 +246,7 @@ public class SurfaceView extends View {
super.onWindowVisibilityChanged(visibility);
mWindowVisibility = visibility == VISIBLE;
mRequestedVisible = mWindowVisibility && mViewVisibility;
- updateSurface();
+ updateWindow();
}
@Override
@@ -253,7 +264,7 @@ public class SurfaceView extends View {
requestLayout();
}
mRequestedVisible = newRequestedVisible;
- updateSurface();
+ updateWindow();
}
@Override
@@ -266,14 +277,19 @@ public class SurfaceView extends View {
}
mRequestedVisible = false;
-
- updateSurface();
- if (mSurfaceControl != null) {
- mSurfaceControl.destroy();
+ updateWindow();
+ mHaveFrame = false;
+ if (mWindow != null) {
+ try {
+ mSession.remove(mWindow);
+ } catch (RemoteException ex) {
+ // Not much we can do here...
+ }
+ mWindow = null;
}
- mSurfaceControl = null;
+ mSession = null;
+ mLayout.token = null;
- mHaveFrame = false;
super.onDetachedFromWindow();
}
@@ -292,13 +308,13 @@ public class SurfaceView extends View {
@Override
protected boolean setFrame(int left, int top, int right, int bottom) {
boolean result = super.setFrame(left, top, right, bottom);
- updateSurface();
+ updateWindow();
return result;
}
@Override
public boolean gatherTransparentRegion(Region region) {
- if (isAboveParent()) {
+ if (mWindowType == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
return super.gatherTransparentRegion(region);
}
@@ -325,7 +341,7 @@ public class SurfaceView extends View {
@Override
public void draw(Canvas canvas) {
- if (mDrawFinished && !isAboveParent()) {
+ if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
// draw() is not called when SKIP_DRAW is set
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
// punch a whole in the view-hierarchy below us
@@ -337,8 +353,8 @@ public class SurfaceView extends View {
@Override
protected void dispatchDraw(Canvas canvas) {
- if (mDrawFinished && !isAboveParent()) {
- // draw() is not called when SKIP_DRAW is set
+ if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+ // if SKIP_DRAW is cleared, draw() has already punched a hole
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
// punch a whole in the view-hierarchy below us
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
@@ -359,8 +375,9 @@ public class SurfaceView extends View {
* <p>Calling this overrides any previous call to {@link #setZOrderOnTop}.
*/
public void setZOrderMediaOverlay(boolean isMediaOverlay) {
- mSubLayer = isMediaOverlay
- ? APPLICATION_MEDIA_OVERLAY_SUBLAYER : APPLICATION_MEDIA_SUBLAYER;
+ mWindowType = isMediaOverlay
+ ? WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY
+ : WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
}
/**
@@ -378,9 +395,12 @@ public class SurfaceView extends View {
*/
public void setZOrderOnTop(boolean onTop) {
if (onTop) {
- mSubLayer = APPLICATION_PANEL_SUBLAYER;
+ mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+ // ensures the surface is placed below the IME
+ mLayout.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
} else {
- mSubLayer = APPLICATION_MEDIA_SUBLAYER;
+ mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+ mLayout.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
}
}
@@ -398,32 +418,31 @@ public class SurfaceView extends View {
*/
public void setSecure(boolean isSecure) {
if (isSecure) {
- mSurfaceFlags |= SurfaceControl.SECURE;
+ mLayout.flags |= WindowManager.LayoutParams.FLAG_SECURE;
} else {
- mSurfaceFlags &= ~SurfaceControl.SECURE;
+ mLayout.flags &= ~WindowManager.LayoutParams.FLAG_SECURE;
}
}
- private Rect getParentSurfaceInsets() {
- final ViewRootImpl root = getViewRootImpl();
- if (root == null) {
- return null;
- } else {
- return root.mWindowAttributes.surfaceInsets;
- }
+ /**
+ * Hack to allow special layering of windows. The type is one of the
+ * types in WindowManager.LayoutParams. This is a hack so:
+ * @hide
+ */
+ public void setWindowType(int type) {
+ mWindowType = type;
}
/** @hide */
- protected void updateSurface() {
+ protected void updateWindow() {
if (!mHaveFrame) {
return;
}
ViewRootImpl viewRoot = getViewRootImpl();
- if (viewRoot == null || viewRoot.mSurface == null || !viewRoot.mSurface.isValid()) {
- return;
+ if (viewRoot != null) {
+ mTranslator = viewRoot.mTranslator;
}
- mTranslator = viewRoot.mTranslator;
if (mTranslator != null) {
mSurface.setCompatibilityTranslator(mTranslator);
}
@@ -433,15 +452,17 @@ public class SurfaceView extends View {
int myHeight = mRequestedHeight;
if (myHeight <= 0) myHeight = getHeight();
+ final boolean creating = mWindow == null;
final boolean formatChanged = mFormat != mRequestedFormat;
- final boolean creating = (mSurfaceControl == null || formatChanged)
- && mRequestedVisible;
- final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight;
+ final boolean sizeChanged = mWindowSpaceWidth != myWidth || mWindowSpaceHeight != myHeight;
final boolean visibleChanged = mVisible != mRequestedVisible;
- final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility;
+ final boolean layoutSizeChanged = getWidth() != mLayout.width
+ || getHeight() != mLayout.height;
+
boolean redrawNeeded = false;
- if (creating || formatChanged || sizeChanged || visibleChanged || windowVisibleChanged) {
+ if (creating || formatChanged || sizeChanged || visibleChanged
+ || mUpdateWindowNeeded || mReportDrawNeeded) {
getLocationInWindow(mLocation);
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
@@ -455,77 +476,93 @@ public class SurfaceView extends View {
final boolean visible = mVisible = mRequestedVisible;
mWindowSpaceLeft = mLocation[0];
mWindowSpaceTop = mLocation[1];
- mSurfaceWidth = myWidth;
- mSurfaceHeight = myHeight;
+ mWindowSpaceWidth = myWidth;
+ mWindowSpaceHeight = myHeight;
mFormat = mRequestedFormat;
- mLastWindowVisibility = mWindowVisibility;
- mScreenRect.left = mWindowSpaceLeft;
- mScreenRect.top = mWindowSpaceTop;
- mScreenRect.right = mWindowSpaceLeft + getWidth();
- mScreenRect.bottom = mWindowSpaceTop + getHeight();
+ // Scaling/Translate window's layout here because mLayout is not used elsewhere.
+
+ // Places the window relative
+ mLayout.x = mWindowSpaceLeft;
+ mLayout.y = mWindowSpaceTop;
+ mLayout.width = getWidth();
+ mLayout.height = getHeight();
if (mTranslator != null) {
- mTranslator.translateRectInAppWindowToScreen(mScreenRect);
+ mTranslator.translateLayoutParamsInAppWindowToScreen(mLayout);
}
- final Rect surfaceInsets = getParentSurfaceInsets();
- mScreenRect.offset(surfaceInsets.left, surfaceInsets.top);
+ mLayout.format = mRequestedFormat;
+ mLayout.flags |=WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
+ | WindowManager.LayoutParams.FLAG_SCALED
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ ;
+ if (!creating && !sizeChanged) {
+ mLayout.privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY;
+ } else {
+ mLayout.privateFlags &=
+ ~WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY;
+ }
- if (creating) {
- mSurfaceSession = new SurfaceSession(viewRoot.mSurface);
- mSurfaceControl = new SurfaceControl(mSurfaceSession,
- "SurfaceView - " + viewRoot.getTitle().toString(),
- mSurfaceWidth, mSurfaceHeight, mFormat,
- mSurfaceFlags);
+ if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) {
+ mLayout.privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
+ }
+ mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
+ | WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
+
+ if (mWindow == null) {
+ Display display = getDisplay();
+ mWindow = new MyWindow(this);
+ mLayout.type = mWindowType;
+ mLayout.gravity = Gravity.START|Gravity.TOP;
+ mSession.addToDisplayWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,
+ mVisible ? VISIBLE : GONE, display.getDisplayId(), mContentInsets,
+ mStableInsets);
}
- boolean realSizeChanged = false;
+ boolean realSizeChanged;
+ boolean reportDrawNeeded;
+
+ int relayoutResult;
mSurfaceLock.lock();
try {
+ mUpdateWindowNeeded = false;
+ reportDrawNeeded = mReportDrawNeeded;
+ mReportDrawNeeded = false;
mDrawingStopped = !visible;
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+ "Cur surface: " + mSurface);
- SurfaceControl.openTransaction();
- try {
- mSurfaceControl.setLayer(mSubLayer);
- if (mViewVisibility) {
- mSurfaceControl.show();
- } else {
- mSurfaceControl.hide();
- }
-
- // While creating the surface, we will set it's initial
- // geometry. Outside of that though, we should generally
- // leave it to the RenderThread.
- if (creating || !mRtHandlingPositionUpdates) {
- mSurfaceControl.setPosition(mScreenRect.left, mScreenRect.top);
- mSurfaceControl.setMatrix(mScreenRect.width() / (float) mSurfaceWidth,
- 0.0f, 0.0f,
- mScreenRect.height() / (float) mSurfaceHeight);
- }
- if (sizeChanged) {
- mSurfaceControl.setSize(mSurfaceWidth, mSurfaceHeight);
- }
- } finally {
- SurfaceControl.closeTransaction();
+ relayoutResult = mSession.relayout(
+ mWindow, mWindow.mSeq, mLayout, mWindowSpaceWidth, mWindowSpaceHeight,
+ visible ? VISIBLE : GONE,
+ WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
+ mWinFrame, mOverscanInsets, mContentInsets,
+ mVisibleInsets, mStableInsets, mOutsets, mBackdropFrame,
+ mConfiguration, mNewSurface);
+ if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
+ reportDrawNeeded = true;
}
- if (sizeChanged || creating) {
- redrawNeeded = true;
- }
+ if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+ + "New surface: " + mNewSurface
+ + ", vis=" + visible + ", frame=" + mWinFrame);
mSurfaceFrame.left = 0;
mSurfaceFrame.top = 0;
if (mTranslator == null) {
- mSurfaceFrame.right = mSurfaceWidth;
- mSurfaceFrame.bottom = mSurfaceHeight;
+ mSurfaceFrame.right = mWinFrame.width();
+ mSurfaceFrame.bottom = mWinFrame.height();
} else {
float appInvertedScale = mTranslator.applicationInvertedScale;
- mSurfaceFrame.right = (int) (mSurfaceWidth * appInvertedScale + 0.5f);
- mSurfaceFrame.bottom = (int) (mSurfaceHeight * appInvertedScale + 0.5f);
+ mSurfaceFrame.right = (int) (mWinFrame.width() * appInvertedScale + 0.5f);
+ mSurfaceFrame.bottom = (int) (mWinFrame.height() * appInvertedScale + 0.5f);
}
final int surfaceWidth = mSurfaceFrame.right;
@@ -539,11 +576,12 @@ public class SurfaceView extends View {
}
try {
- redrawNeeded |= visible && !mDrawFinished;
+ redrawNeeded |= creating | reportDrawNeeded;
SurfaceHolder.Callback callbacks[] = null;
- final boolean surfaceChanged = creating;
+ final boolean surfaceChanged = (relayoutResult
+ & WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED) != 0;
if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
mSurfaceCreated = false;
if (mSurface.isValid()) {
@@ -570,10 +608,7 @@ public class SurfaceView extends View {
}
}
- if (creating) {
- mSurface.copyFrom(mSurfaceControl);
- }
-
+ mSurface.transferFrom(mNewSurface);
if (visible && mSurface.isValid()) {
if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {
mSurfaceCreated = true;
@@ -606,55 +641,53 @@ public class SurfaceView extends View {
callbacks = getSurfaceCallbacks();
}
SurfaceCallbackHelper sch =
- new SurfaceCallbackHelper(this::onDrawFinished);
+ new SurfaceCallbackHelper(mSession, mWindow);
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
}
}
} finally {
mIsCreating = false;
- if (mSurfaceControl != null && !mSurfaceCreated) {
- mSurfaceControl.destroy();
- mSurfaceControl = null;
- }
+ mSession.performDeferredDestroy(mWindow);
}
- } catch (Exception ex) {
+ } catch (RemoteException ex) {
Log.e(TAG, "Exception from relayout", ex);
}
if (DEBUG) Log.v(
- TAG, "Layout: x=" + mScreenRect.left + " y=" + mScreenRect.top
- + " w=" + mScreenRect.width() + " h=" + mScreenRect.height()
- + ", frame=" + mSurfaceFrame);
+ TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
+ " w=" + mLayout.width + " h=" + mLayout.height +
+ ", frame=" + mSurfaceFrame);
} else {
// Calculate the window position in case RT loses the window
// and we need to fallback to a UI-thread driven position update
- getLocationInSurface(mLocation);
+ getLocationInWindow(mLocation);
final boolean positionChanged = mWindowSpaceLeft != mLocation[0]
|| mWindowSpaceTop != mLocation[1];
- final boolean layoutSizeChanged = getWidth() != mScreenRect.width()
- || getHeight() != mScreenRect.height();
if (positionChanged || layoutSizeChanged) { // Only the position has changed
mWindowSpaceLeft = mLocation[0];
mWindowSpaceTop = mLocation[1];
- // For our size changed check, we keep mScreenRect.width() and mScreenRect.height()
+ // For our size changed check, we keep mLayout.width and mLayout.height
// in view local space.
- mLocation[0] = getWidth();
- mLocation[1] = getHeight();
+ mLocation[0] = mLayout.width = getWidth();
+ mLocation[1] = mLayout.height = getHeight();
+
+ transformFromViewToWindowSpace(mLocation);
- mScreenRect.set(mWindowSpaceLeft, mWindowSpaceTop,
+ mTmpRect.set(mWindowSpaceLeft, mWindowSpaceTop,
mLocation[0], mLocation[1]);
if (mTranslator != null) {
- mTranslator.translateRectInAppWindowToScreen(mScreenRect);
+ mTranslator.translateRectInAppWindowToScreen(mTmpRect);
}
if (!isHardwareAccelerated() || !mRtHandlingPositionUpdates) {
try {
- if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition UI, " +
+ if (DEBUG) Log.d(TAG, String.format("%d updateWindowPosition UI, " +
"postion = [%d, %d, %d, %d]", System.identityHashCode(this),
- mScreenRect.left, mScreenRect.top,
- mScreenRect.right, mScreenRect.bottom));
- setParentSpaceRectangle(mScreenRect, -1);
- } catch (Exception ex) {
+ mTmpRect.left, mTmpRect.top,
+ mTmpRect.right, mTmpRect.bottom));
+ mSession.repositionChild(mWindow, mTmpRect.left, mTmpRect.top,
+ mTmpRect.right, mTmpRect.bottom, -1, mTmpRect);
+ } catch (RemoteException ex) {
Log.e(TAG, "Exception from relayout", ex);
}
}
@@ -662,43 +695,20 @@ public class SurfaceView extends View {
}
}
- private void onDrawFinished() {
- if (DEBUG) {
- Log.i(TAG, System.identityHashCode(this) + " "
- + "finishedDrawing");
- }
- mHandler.sendEmptyMessage(DRAW_FINISHED_MSG);
- }
-
- private void setParentSpaceRectangle(Rect position, long frameNumber) {
- ViewRootImpl viewRoot = getViewRootImpl();
-
- SurfaceControl.openTransaction();
- try {
- if (frameNumber > 0) {
- mSurfaceControl.deferTransactionUntil(viewRoot.mSurface, frameNumber);
- }
- mSurfaceControl.setPosition(position.left, position.top);
- mSurfaceControl.setMatrix(position.width() / (float) mSurfaceWidth,
- 0.0f, 0.0f,
- position.height() / (float) mSurfaceHeight);
- } finally {
- SurfaceControl.closeTransaction();
- }
- }
-
private Rect mRTLastReportedPosition = new Rect();
/**
* Called by native by a Rendering Worker thread to update the window position
* @hide
*/
- public final void updateSurfacePosition_renderWorker(long frameNumber,
+ public final void updateWindowPosition_renderWorker(long frameNumber,
int left, int top, int right, int bottom) {
- if (mSurfaceControl == null) {
+ IWindowSession session = mSession;
+ MyWindow window = mWindow;
+ if (session == null || window == null) {
+ // Guess we got detached, that sucks
return;
}
-
// TODO: This is teensy bit racey in that a brand new SurfaceView moving on
// its 2nd frame if RenderThread is running slowly could potentially see
// this as false, enter the branch, get pre-empted, then this comes along
@@ -716,29 +726,35 @@ public class SurfaceView extends View {
}
try {
if (DEBUG) {
- Log.d(TAG, String.format("%d updateSurfacePosition RenderWorker, frameNr = %d, " +
+ Log.d(TAG, String.format("%d updateWindowPosition RenderWorker, frameNr = %d, " +
"postion = [%d, %d, %d, %d]", System.identityHashCode(this),
frameNumber, left, top, right, bottom));
}
- mRTLastReportedPosition.set(left, top, right, bottom);
- setParentSpaceRectangle(mRTLastReportedPosition, frameNumber);
+ // Just using mRTLastReportedPosition as a dummy rect here
+ session.repositionChild(window, left, top, right, bottom,
+ frameNumber,
+ mRTLastReportedPosition);
// Now overwrite mRTLastReportedPosition with our values
- } catch (Exception ex) {
+ mRTLastReportedPosition.set(left, top, right, bottom);
+ } catch (RemoteException ex) {
Log.e(TAG, "Exception from repositionChild", ex);
}
}
/**
- * Called by native on RenderThread to notify that the view is no longer in the
+ * Called by native on RenderThread to notify that the window is no longer in the
* draw tree. UI thread is blocked at this point.
* @hide
*/
- public final void surfacePositionLost_uiRtSync(long frameNumber) {
+ public final void windowPositionLost_uiRtSync(long frameNumber) {
if (DEBUG) {
Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
System.identityHashCode(this), frameNumber));
}
- if (mSurfaceControl == null) {
+ IWindowSession session = mSession;
+ MyWindow window = mWindow;
+ if (session == null || window == null) {
+ // We got detached prior to receiving this, abort
return;
}
if (mRtHandlingPositionUpdates) {
@@ -747,14 +763,19 @@ public class SurfaceView extends View {
// safely access other member variables at this time.
// So do what the UI thread would have done if RT wasn't handling position
// updates.
- if (!mScreenRect.isEmpty() && !mScreenRect.equals(mRTLastReportedPosition)) {
+ mTmpRect.set(mLayout.x, mLayout.y,
+ mLayout.x + mLayout.width,
+ mLayout.y + mLayout.height);
+
+ if (!mTmpRect.isEmpty() && !mTmpRect.equals(mRTLastReportedPosition)) {
try {
- if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition, " +
+ if (DEBUG) Log.d(TAG, String.format("%d updateWindowPosition, " +
"postion = [%d, %d, %d, %d]", System.identityHashCode(this),
- mScreenRect.left, mScreenRect.top,
- mScreenRect.right, mScreenRect.bottom));
- setParentSpaceRectangle(mScreenRect, frameNumber);
- } catch (Exception ex) {
+ mTmpRect.left, mTmpRect.top,
+ mTmpRect.right, mTmpRect.bottom));
+ session.repositionChild(window, mTmpRect.left, mTmpRect.top,
+ mTmpRect.right, mTmpRect.bottom, frameNumber, mWinFrame);
+ } catch (RemoteException ex) {
Log.e(TAG, "Exception from relayout", ex);
}
}
@@ -771,6 +792,10 @@ public class SurfaceView extends View {
return callbacks;
}
+ void handleGetNewSurface() {
+ updateWindow();
+ }
+
/**
* Check to see if the surface has fixed size dimensions or if the surface's
* dimensions are dimensions are dependent on its current layout.
@@ -782,8 +807,65 @@ public class SurfaceView extends View {
return (mRequestedWidth != -1 || mRequestedHeight != -1);
}
- private boolean isAboveParent() {
- return mSubLayer >= 0;
+ private static class MyWindow extends BaseIWindow {
+ private final WeakReference<SurfaceView> mSurfaceView;
+
+ public MyWindow(SurfaceView surfaceView) {
+ mSurfaceView = new WeakReference<SurfaceView>(surfaceView);
+ }
+
+ @Override
+ public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
+ Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
+ Configuration newConfig, Rect backDropRect, boolean forceLayout,
+ boolean alwaysConsumeNavBar, int displayId) {
+ SurfaceView surfaceView = mSurfaceView.get();
+ if (surfaceView != null) {
+ if (DEBUG) Log.v(TAG, surfaceView + " got resized: w=" + frame.width()
+ + " h=" + frame.height() + ", cur w=" + mCurWidth + " h=" + mCurHeight);
+ surfaceView.mSurfaceLock.lock();
+ try {
+ if (reportDraw) {
+ surfaceView.mUpdateWindowNeeded = true;
+ surfaceView.mReportDrawNeeded = true;
+ surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
+ } else if (surfaceView.mWinFrame.width() != frame.width()
+ || surfaceView.mWinFrame.height() != frame.height()
+ || forceLayout) {
+ surfaceView.mUpdateWindowNeeded = true;
+ surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
+ }
+ } finally {
+ surfaceView.mSurfaceLock.unlock();
+ }
+ }
+ }
+
+ @Override
+ public void dispatchAppVisibility(boolean visible) {
+ // The point of SurfaceView is to let the app control the surface.
+ }
+
+ @Override
+ public void dispatchGetNewSurface() {
+ SurfaceView surfaceView = mSurfaceView.get();
+ if (surfaceView != null) {
+ Message msg = surfaceView.mHandler.obtainMessage(GET_NEW_SURFACE_MSG);
+ surfaceView.mHandler.sendMessage(msg);
+ }
+ }
+
+ @Override
+ public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
+ Log.w("SurfaceView", "Unexpected focus in surface: focus=" + hasFocus + ", touchEnabled=" + touchEnabled);
+ }
+
+ @Override
+ public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
+ }
+
+ int mCurWidth = -1;
+ int mCurHeight = -1;
}
private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
@@ -831,14 +913,15 @@ public class SurfaceView extends View {
@Override
public void setFormat(int format) {
+
// for backward compatibility reason, OPAQUE always
// means 565 for SurfaceView
if (format == PixelFormat.OPAQUE)
format = PixelFormat.RGB_565;
mRequestedFormat = format;
- if (mSurfaceControl != null) {
- updateSurface();
+ if (mWindow != null) {
+ updateWindow();
}
}
@@ -899,10 +982,10 @@ public class SurfaceView extends View {
mSurfaceLock.lock();
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Locking canvas... stopped="
- + mDrawingStopped + ", surfaceControl=" + mSurfaceControl);
+ + mDrawingStopped + ", win=" + mWindow);
Canvas c = null;
- if (!mDrawingStopped && mSurfaceControl != null) {
+ if (!mDrawingStopped && mWindow != null) {
try {
if (hardware) {
c = mSurface.lockHardwareCanvas();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f9863b0a6761..20d960fff661 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2632,14 +2632,6 @@ public final class ViewRootImpl implements ViewParent,
}
}
- private void onDrawFinished() {
- try {
- mWindowSession.finishDrawing(mWindow);
- } catch (RemoteException e) {
- // Have fun!
- }
- }
-
private void performDraw() {
if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
return;
@@ -2690,7 +2682,7 @@ public final class ViewRootImpl implements ViewParent,
}
if (mSurfaceHolder != null && mSurface.isValid()) {
- SurfaceCallbackHelper sch = new SurfaceCallbackHelper(this::onDrawFinished);
+ SurfaceCallbackHelper sch = new SurfaceCallbackHelper(mWindowSession, mWindow);
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
diff --git a/core/java/com/android/internal/view/SurfaceCallbackHelper.java b/core/java/com/android/internal/view/SurfaceCallbackHelper.java
index 507b673ec279..5b6a82cf1c43 100644
--- a/core/java/com/android/internal/view/SurfaceCallbackHelper.java
+++ b/core/java/com/android/internal/view/SurfaceCallbackHelper.java
@@ -17,11 +17,14 @@
package com.android.internal.view;
import android.os.RemoteException;
+import android.view.IWindow;
+import android.view.IWindowSession;
import android.view.Surface;
import android.view.SurfaceHolder;
public class SurfaceCallbackHelper {
- Runnable mRunnable;
+ IWindowSession mSession;
+ IWindow.Stub mWindow;
int mFinishDrawingCollected = 0;
int mFinishDrawingExpected = 0;
@@ -34,18 +37,26 @@ public class SurfaceCallbackHelper {
if (mFinishDrawingCollected < mFinishDrawingExpected) {
return;
}
- mRunnable.run();
+ try {
+ mSession.finishDrawing(mWindow);
+ } catch (RemoteException e) {
+ }
}
}
};
- public SurfaceCallbackHelper(Runnable callbacksCollected) {
- mRunnable = callbacksCollected;
+ public SurfaceCallbackHelper(IWindowSession session,
+ IWindow.Stub window) {
+ mSession = session;
+ mWindow = window;
}
public void dispatchSurfaceRedrawNeededAsync(SurfaceHolder holder, SurfaceHolder.Callback callbacks[]) {
if (callbacks == null || callbacks.length == 0) {
- mRunnable.run();
+ try {
+ mSession.finishDrawing(mWindow);
+ } catch (RemoteException e) {
+ }
return;
}
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 6e8c93132562..f221392f16bd 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -452,6 +452,10 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
const RenderProperties& props = node.properties();
uirenderer::Rect bounds(props.getWidth(), props.getHeight());
transform.mapRect(bounds);
+ bounds.left -= info.windowInsetLeft;
+ bounds.right -= info.windowInsetLeft;
+ bounds.top -= info.windowInsetTop;
+ bounds.bottom -= info.windowInsetTop;
if (CC_LIKELY(transform.isPureTranslate())) {
// snap/round the computed bounds, so they match the rounding behavior
@@ -623,9 +627,9 @@ static const JNINativeMethod gMethods[] = {
int register_android_view_RenderNode(JNIEnv* env) {
jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
- "updateSurfacePosition_renderWorker", "(JIIII)V");
+ "updateWindowPosition_renderWorker", "(JIIII)V");
gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz,
- "surfacePositionLost_uiRtSync", "(J)V");
+ "windowPositionLost_uiRtSync", "(J)V");
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index be86f5c6b8ab..a81901df9a1b 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -693,6 +693,7 @@ static jboolean nativeGetAnimationFrameStats(JNIEnv* env, jclass clazz, jobject
return JNI_TRUE;
}
+
static void nativeDeferTransactionUntil(JNIEnv* env, jclass clazz, jlong nativeObject,
jobject handleObject, jlong frameNumber) {
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
@@ -701,27 +702,6 @@ static void nativeDeferTransactionUntil(JNIEnv* env, jclass clazz, jlong nativeO
ctrl->deferTransactionUntil(handle, frameNumber);
}
-static void nativeDeferTransactionUntilSurface(JNIEnv* env, jclass clazz, jlong nativeObject,
- jobject surfaceObject, jlong frameNumber) {
- auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- sp<Surface> barrier = reinterpret_cast<Surface *>(surfaceObject);
-
- ctrl->deferTransactionUntil(barrier, frameNumber);
-}
-
-static void nativeReparentChildren(JNIEnv* env, jclass clazz, jlong nativeObject,
- jobject newParentObject) {
- auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- sp<IBinder> handle = ibinderForJavaObject(env, newParentObject);
-
- ctrl->reparentChildren(handle);
-}
-
-static void nativeSeverChildren(JNIEnv* env, jclass clazz, jlong nativeObject) {
- auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- ctrl->detachChildren();
-}
-
static void nativeSetOverrideScalingMode(JNIEnv* env, jclass clazz, jlong nativeObject,
jint scalingMode) {
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
@@ -844,12 +824,6 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetDisplayPowerMode },
{"nativeDeferTransactionUntil", "(JLandroid/os/IBinder;J)V",
(void*)nativeDeferTransactionUntil },
- {"nativeDeferTransactionUntilSurface", "(JJJ)V",
- (void*)nativeDeferTransactionUntilSurface },
- {"nativeReparentChildren", "(JLandroid/os/IBinder;)V",
- (void*)nativeReparentChildren } ,
- {"nativeSeverChildren", "(J)V",
- (void*)nativeSeverChildren } ,
{"nativeSetOverrideScalingMode", "(JI)V",
(void*)nativeSetOverrideScalingMode },
{"nativeGetHandle", "(J)Landroid/os/IBinder;",
diff --git a/core/jni/android_view_SurfaceSession.cpp b/core/jni/android_view_SurfaceSession.cpp
index 508d89795569..dad6958560c0 100644
--- a/core/jni/android_view_SurfaceSession.cpp
+++ b/core/jni/android_view_SurfaceSession.cpp
@@ -24,7 +24,6 @@
#include <utils/RefBase.h>
#include <gui/SurfaceComposerClient.h>
-#include <gui/Surface.h>
namespace android {
@@ -46,13 +45,6 @@ static jlong nativeCreate(JNIEnv* env, jclass clazz) {
return reinterpret_cast<jlong>(client);
}
-static jlong nativeCreateScoped(JNIEnv* env, jclass clazz, jlong surfaceObject) {
- Surface *parent = reinterpret_cast<Surface*>(surfaceObject);
- SurfaceComposerClient* client = new SurfaceComposerClient(parent->getIGraphicBufferProducer());
- client->incStrong((void*)nativeCreate);
- return reinterpret_cast<jlong>(client);
-}
-
static void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
SurfaceComposerClient* client = reinterpret_cast<SurfaceComposerClient*>(ptr);
client->decStrong((void*)nativeCreate);
@@ -63,12 +55,11 @@ static void nativeKill(JNIEnv* env, jclass clazz, jlong ptr) {
client->dispose();
}
+
static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeCreate", "()J",
(void*)nativeCreate },
- { "nativeCreateScoped", "(J)J",
- (void*)nativeCreateScoped },
{ "nativeDestroy", "(J)V",
(void*)nativeDestroy },
{ "nativeKill", "(J)V",
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 99edf6ef944e..37eae48a7a11 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -178,9 +178,13 @@ public:
}
}
// TODO: This is hacky
+ info.windowInsetLeft = -stagingProperties().getLeft();
+ info.windowInsetTop = -stagingProperties().getTop();
info.updateWindowPositions = true;
RenderNode::prepareTree(info);
info.updateWindowPositions = false;
+ info.windowInsetLeft = 0;
+ info.windowInsetTop = 0;
info.errorHandler = nullptr;
}
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 59a536b1b001..9660de4dbba4 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -26,8 +26,8 @@
#include <sys/un.h>
#include <unistd.h>
+#include <android-base/logging.h>
#include <android-base/strings.h>
-#include <cutils/log.h>
// Static whitelist of open paths that the zygote is allowed to keep open.
static const char* kPathWhitelist[] = {
@@ -137,7 +137,7 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) {
// This should never happen; the zygote should always have the right set
// of permissions required to stat all its open files.
if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
- ALOGE("Unable to stat fd %d : %s", fd, strerror(errno));
+ PLOG(ERROR) << "Unable to stat fd " << fd;
return NULL;
}
@@ -150,7 +150,8 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) {
}
if (!whitelist->IsAllowed(socket_name)) {
- ALOGE("Socket name not whitelisted : %s (fd=%d)", socket_name.c_str(), fd);
+ LOG(ERROR) << "Socket name not whitelisted : " << socket_name
+ << " (fd=" << fd << ")";
return NULL;
}
@@ -168,7 +169,7 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) {
// with the child process across forks but those should have been closed
// before we got to this point.
if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
- ALOGE("Unsupported st_mode %d", f_stat.st_mode);
+ LOG(ERROR) << "Unsupported st_mode " << f_stat.st_mode;
return NULL;
}
@@ -178,7 +179,7 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) {
}
if (!whitelist->IsAllowed(file_path)) {
- ALOGE("Not whitelisted : %s", file_path.c_str());
+ LOG(ERROR) << "Not whitelisted : " << file_path;
return NULL;
}
@@ -187,7 +188,7 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) {
// there won't be any races.
const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
if (fd_flags == -1) {
- ALOGE("Failed fcntl(%d, F_GETFD) : %s", fd, strerror(errno));
+ PLOG(ERROR) << "Failed fcntl(" << fd << ", F_GETFD)";
return NULL;
}
@@ -205,7 +206,7 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) {
// their presence and pass them in to open().
int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
if (fs_flags == -1) {
- ALOGE("Failed fcntl(%d, F_GETFL) : %s", fd, strerror(errno));
+ PLOG(ERROR) << "Failed fcntl(" << fd << ", F_GETFL)";
return NULL;
}
@@ -224,6 +225,7 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) {
bool FileDescriptorInfo::Restat() const {
struct stat f_stat;
if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
+ PLOG(ERROR) << "Unable to restat fd " << fd;
return false;
}
@@ -241,31 +243,31 @@ bool FileDescriptorInfo::ReopenOrDetach() const {
const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));
if (new_fd == -1) {
- ALOGE("Failed open(%s, %d) : %s", file_path.c_str(), open_flags, strerror(errno));
+ PLOG(ERROR) << "Failed open(" << file_path << ", " << open_flags << ")";
return false;
}
if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
close(new_fd);
- ALOGE("Failed fcntl(%d, F_SETFD, %x) : %s", new_fd, fd_flags, strerror(errno));
+ PLOG(ERROR) << "Failed fcntl(" << new_fd << ", F_SETFD, " << fd_flags << ")";
return false;
}
if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
close(new_fd);
- ALOGE("Failed fcntl(%d, F_SETFL, %x) : %s", new_fd, fs_flags, strerror(errno));
+ PLOG(ERROR) << "Failed fcntl(" << new_fd << ", F_SETFL, " << fs_flags << ")";
return false;
}
if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
close(new_fd);
- ALOGE("Failed lseek64(%d, SEEK_SET) : %s", new_fd, strerror(errno));
+ PLOG(ERROR) << "Failed lseek64(" << new_fd << ", SEEK_SET)";
return false;
}
if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) {
close(new_fd);
- ALOGE("Failed dup2(%d, %d) : %s", fd, new_fd, strerror(errno));
+ PLOG(ERROR) << "Failed dup2(" << fd << ", " << new_fd << ")";
return false;
}
@@ -312,7 +314,10 @@ bool FileDescriptorInfo::Readlink(const int fd, std::string* result) {
// ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here.
char buf[4096];
ssize_t len = readlink(path, buf, sizeof(buf));
- if (len == -1) return false;
+ if (len == -1) {
+ PLOG(ERROR) << "Readlink on " << fd << " failed.";
+ return false;
+ }
result->assign(buf, len);
return true;
@@ -325,12 +330,12 @@ bool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) {
socklen_t addr_len = sizeof(ss);
if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) {
- ALOGE("Failed getsockname(%d) : %s", fd, strerror(errno));
+ PLOG(ERROR) << "Failed getsockname(" << fd << ")";
return false;
}
if (addr->sa_family != AF_UNIX) {
- ALOGE("Unsupported socket (fd=%d) with family %d", fd, addr->sa_family);
+ LOG(ERROR) << "Unsupported socket (fd=" << fd << ") with family " << addr->sa_family;
return false;
}
@@ -339,13 +344,13 @@ bool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) {
size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path);
// This is an unnamed local socket, we do not accept it.
if (path_len == 0) {
- ALOGE("Unsupported AF_UNIX socket (fd=%d) with empty path.", fd);
+ LOG(ERROR) << "Unsupported AF_UNIX socket (fd=" << fd << ") with empty path.";
return false;
}
// This is a local socket with an abstract address, we do not accept it.
if (unix_addr->sun_path[0] == '\0') {
- ALOGE("Unsupported AF_UNIX socket (fd=%d) with abstract address.", fd);
+ LOG(ERROR) << "Unsupported AF_UNIX socket (fd=" << fd << ") with abstract address.";
return false;
}
@@ -363,17 +368,17 @@ bool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) {
bool FileDescriptorInfo::DetachSocket() const {
const int dev_null_fd = open("/dev/null", O_RDWR);
if (dev_null_fd < 0) {
- ALOGE("Failed to open /dev/null : %s", strerror(errno));
+ PLOG(ERROR) << "Failed to open /dev/null";
return false;
}
if (dup2(dev_null_fd, fd) == -1) {
- ALOGE("Failed dup2 on socket descriptor %d : %s", fd, strerror(errno));
+ PLOG(ERROR) << "Failed dup2 on socket descriptor " << fd;
return false;
}
if (close(dev_null_fd) == -1) {
- ALOGE("Failed close(%d) : %s", dev_null_fd, strerror(errno));
+ PLOG(ERROR) << "Failed close(" << dev_null_fd << ")";
return false;
}
@@ -384,7 +389,7 @@ bool FileDescriptorInfo::DetachSocket() const {
FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore) {
DIR* d = opendir(kFdPath);
if (d == NULL) {
- ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
+ PLOG(ERROR) << "Unable to open directory " << std::string(kFdPath);
return NULL;
}
int dir_fd = dirfd(d);
@@ -397,14 +402,14 @@ FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_
continue;
}
if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
- ALOGI("Ignoring open file descriptor %d", fd);
+ LOG(INFO) << "Ignoring open file descriptor " << fd;
continue;
}
FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd);
if (info == NULL) {
if (closedir(d) == -1) {
- ALOGE("Unable to close directory : %s", strerror(errno));
+ PLOG(ERROR) << "Unable to close directory";
}
return NULL;
}
@@ -412,7 +417,7 @@ FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_
}
if (closedir(d) == -1) {
- ALOGE("Unable to close directory : %s", strerror(errno));
+ PLOG(ERROR) << "Unable to close directory";
return NULL;
}
return new FileDescriptorTable(open_fd_map);
@@ -424,7 +429,7 @@ bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore) {
// First get the list of open descriptors.
DIR* d = opendir(kFdPath);
if (d == NULL) {
- ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
+ PLOG(ERROR) << "Unable to open directory " << std::string(kFdPath);
return false;
}
@@ -436,7 +441,7 @@ bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore) {
continue;
}
if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
- ALOGI("Ignoring open file descriptor %d", fd);
+ LOG(INFO) << "Ignoring open file descriptor " << fd;
continue;
}
@@ -444,7 +449,7 @@ bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore) {
}
if (closedir(d) == -1) {
- ALOGE("Unable to close directory : %s", strerror(errno));
+ PLOG(ERROR) << "Unable to close directory";
return false;
}
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index e39614b6a5ea..c6fbe2bd55de 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -91,6 +91,8 @@ public:
LayerUpdateQueue* layerUpdateQueue = nullptr;
ErrorHandler* errorHandler = nullptr;
+ int32_t windowInsetLeft = 0;
+ int32_t windowInsetTop = 0;
bool updateWindowPositions = false;
struct Out {
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index e5af35711311..aee9d38e0a27 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -776,8 +776,8 @@ public class TvView extends ViewGroup {
mSurface = null;
mSurfaceView = new SurfaceView(getContext(), mAttrs, mDefStyleAttr) {
@Override
- protected void updateSurface() {
- super.updateSurface();
+ protected void updateWindow() {
+ super.updateWindow();
relayoutSessionOverlayView();
}};
// The surface view's content should be treated as secure all the time.
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/PermissionsSummaryHelper.java b/packages/SettingsLib/src/com/android/settingslib/applications/PermissionsSummaryHelper.java
new file mode 100644
index 000000000000..ec8e9561ea83
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/PermissionsSummaryHelper.java
@@ -0,0 +1,80 @@
+/*
+ * 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.settingslib.applications;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.pm.permission.RuntimePermissionPresentationInfo;
+import android.content.pm.permission.RuntimePermissionPresenter;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class PermissionsSummaryHelper {
+
+ public static void getPermissionSummary(Context context, String pkg,
+ final PermissionsResultCallback callback) {
+ final RuntimePermissionPresenter presenter =
+ RuntimePermissionPresenter.getInstance(context);
+ presenter.getAppPermissions(pkg, new RuntimePermissionPresenter.OnResultCallback() {
+ @Override
+ public void onGetAppPermissions(
+ @NonNull List<RuntimePermissionPresentationInfo> permissions) {
+ final int permissionCount = permissions.size();
+
+ int grantedStandardCount = 0;
+ int grantedAdditionalCount = 0;
+ int requestedCount = 0;
+ List<CharSequence> grantedStandardLabels = new ArrayList<>();
+
+ for (int i = 0; i < permissionCount; i++) {
+ RuntimePermissionPresentationInfo permission = permissions.get(i);
+ requestedCount++;
+ if (permission.isGranted()) {
+ if (permission.isStandard()) {
+ grantedStandardLabels.add(permission.getLabel());
+ grantedStandardCount++;
+ } else {
+ grantedAdditionalCount++;
+ }
+ }
+ }
+
+ Collator collator = Collator.getInstance();
+ collator.setStrength(Collator.PRIMARY);
+ Collections.sort(grantedStandardLabels, collator);
+
+ callback.onPermissionSummaryResult(grantedStandardCount, requestedCount,
+ grantedAdditionalCount, grantedStandardLabels);
+ }
+ }, null);
+ }
+
+ public static abstract class PermissionsResultCallback {
+ public void onAppWithPermissionsCountsResult(int standardGrantedPermissionAppCount,
+ int standardUsedPermissionAppCount) {
+ /* do nothing - stub */
+ }
+
+ public void onPermissionSummaryResult(int standardGrantedPermissionCount,
+ int requestedPermissionCount, int additionalGrantedPermissionCount,
+ List<CharSequence> grantedGroupLabels) {
+ /* do nothing - stub */
+ }
+ }
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 56ae618883b9..de79d3f98c32 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -143,6 +143,8 @@ final class SettingsState {
@GuardedBy("sLock")
private static Signature sSystemSignature;
+ private final Object mWriteLock = new Object();
+
private final Object mLock;
private final Handler mHandler;
@@ -551,62 +553,66 @@ final class SettingsState {
}
private void doWriteState() {
- if (DEBUG_PERSISTENCE) {
- Slog.i(LOG_TAG, "[PERSIST START]");
- }
-
- AtomicFile destination = new AtomicFile(mStatePersistFile);
+ synchronized (mWriteLock) {
+ if (DEBUG_PERSISTENCE) {
+ Slog.i(LOG_TAG, "[PERSIST START]");
+ }
- final int version;
- final ArrayMap<String, Setting> settings;
+ AtomicFile destination = new AtomicFile(mStatePersistFile);
- synchronized (mLock) {
- version = mVersion;
- settings = new ArrayMap<>(mSettings);
- mDirty = false;
- mWriteScheduled = false;
- }
+ final int version;
+ final ArrayMap<String, Setting> settings;
- FileOutputStream out = null;
- try {
- out = destination.startWrite();
+ synchronized (mLock) {
+ version = mVersion;
+ settings = new ArrayMap<>(mSettings);
+ mDirty = false;
+ mWriteScheduled = false;
+ }
- XmlSerializer serializer = Xml.newSerializer();
- serializer.setOutput(out, StandardCharsets.UTF_8.name());
- serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
- serializer.startDocument(null, true);
- serializer.startTag(null, TAG_SETTINGS);
- serializer.attribute(null, ATTR_VERSION, String.valueOf(version));
+ FileOutputStream out = null;
+ try {
+ out = destination.startWrite();
+
+ XmlSerializer serializer = Xml.newSerializer();
+ serializer.setOutput(out, StandardCharsets.UTF_8.name());
+ serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
+ true);
+ serializer.startDocument(null, true);
+ serializer.startTag(null, TAG_SETTINGS);
+ serializer.attribute(null, ATTR_VERSION, String.valueOf(version));
+
+ final int settingCount = settings.size();
+ for (int i = 0; i < settingCount; i++) {
+ Setting setting = settings.valueAt(i);
+
+ writeSingleSetting(mVersion, serializer, setting.getId(), setting.getName(),
+ setting.getValue(), setting.getDefaultValue(), setting.getPackageName(),
+ setting.getTag(), setting.isDefaultFromSystem());
+
+ if (DEBUG_PERSISTENCE) {
+ Slog.i(LOG_TAG, "[PERSISTED]" + setting.getName() + "="
+ + setting.getValue());
+ }
+ }
- final int settingCount = settings.size();
- for (int i = 0; i < settingCount; i++) {
- Setting setting = settings.valueAt(i);
+ serializer.endTag(null, TAG_SETTINGS);
+ serializer.endDocument();
+ destination.finishWrite(out);
- writeSingleSetting(mVersion, serializer, setting.getId(), setting.getName(),
- setting.getValue(), setting.getDefaultValue(), setting.getPackageName(),
- setting.getTag(), setting.isDefaultFromSystem());
+ synchronized (mLock) {
+ addHistoricalOperationLocked(HISTORICAL_OPERATION_PERSIST, null);
+ }
if (DEBUG_PERSISTENCE) {
- Slog.i(LOG_TAG, "[PERSISTED]" + setting.getName() + "=" + setting.getValue());
+ Slog.i(LOG_TAG, "[PERSIST END]");
}
+ } catch (Throwable t) {
+ Slog.wtf(LOG_TAG, "Failed to write settings, restoring backup", t);
+ destination.failWrite(out);
+ } finally {
+ IoUtils.closeQuietly(out);
}
-
- serializer.endTag(null, TAG_SETTINGS);
- serializer.endDocument();
- destination.finishWrite(out);
-
- synchronized (mLock) {
- addHistoricalOperationLocked(HISTORICAL_OPERATION_PERSIST, null);
- }
-
- if (DEBUG_PERSISTENCE) {
- Slog.i(LOG_TAG, "[PERSIST END]");
- }
- } catch (Throwable t) {
- Slog.wtf(LOG_TAG, "Failed to write settings, restoring backup", t);
- destination.failWrite(out);
- } finally {
- IoUtils.closeQuietly(out);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemBars.java b/packages/SystemUI/src/com/android/systemui/SystemBars.java
index 6623cabe4bd7..b5093b3ce52a 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemBars.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemBars.java
@@ -43,13 +43,6 @@ public class SystemBars extends SystemUI {
}
@Override
- protected void onConfigurationChanged(Configuration newConfig) {
- if (mStatusBar != null) {
- mStatusBar.onConfigurationChanged(newConfig);
- }
- }
-
- @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mStatusBar != null) {
mStatusBar.dump(fd, pw, args);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index ae402efabc7f..e7256d14de77 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -71,8 +71,15 @@ public class PipManager implements BasePipManager {
}
@Override
+ public void onPinnedStackAnimationStarted() {
+ // Disable touches while the animation is running
+ mTouchHandler.setTouchEnabled(false);
+ }
+
+ @Override
public void onPinnedStackAnimationEnded() {
- // TODO(winsonc): Disable touch interaction with the PiP until the animation ends
+ // Re-enable touches after the animation completes
+ mTouchHandler.setTouchEnabled(true);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index d832810e4812..4100b66b07b6 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -181,6 +181,10 @@ public class PipTouchHandler {
registerInputConsumer();
}
+ public void setTouchEnabled(boolean enabled) {
+ mTouchState.setAllowTouches(enabled);
+ }
+
public void onActivityPinned() {
// Reset some states once we are pinned
if (mIsTappingThrough) {
@@ -294,6 +298,7 @@ public class PipTouchHandler {
// Fall through to clean up
}
case MotionEvent.ACTION_CANCEL: {
+ mTouchState.reset();
break;
}
}
@@ -418,6 +423,10 @@ public class PipTouchHandler {
@Override
public void onDown(PipTouchState touchState) {
+ if (!touchState.isUserInteracting()) {
+ return;
+ }
+
if (ENABLE_DRAG_TO_DISMISS) {
mDismissViewController.createDismissTarget();
mHandler.postDelayed(mShowDismissAffordance, SHOW_DISMISS_AFFORDANCE_DELAY);
@@ -426,6 +435,10 @@ public class PipTouchHandler {
@Override
boolean onMove(PipTouchState touchState) {
+ if (!touchState.isUserInteracting()) {
+ return false;
+ }
+
if (touchState.startedDragging()) {
mSavedSnapFraction = -1f;
}
@@ -458,6 +471,10 @@ public class PipTouchHandler {
@Override
public boolean onUp(PipTouchState touchState) {
+ if (!touchState.isUserInteracting()) {
+ return false;
+ }
+
try {
if (ENABLE_DRAG_TO_DISMISS) {
mHandler.removeCallbacks(mShowDismissAffordance);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
index 702ad0af0447..a317dc32ba45 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
@@ -37,6 +37,7 @@ public class PipTouchState {
private final PointF mLastTouch = new PointF();
private final PointF mLastDelta = new PointF();
private final PointF mVelocity = new PointF();
+ private boolean mAllowTouches = true;
private boolean mIsUserInteracting = false;
private boolean mIsDragging = false;
private boolean mStartedDragging = false;
@@ -48,23 +49,41 @@ public class PipTouchState {
}
/**
+ * Resets this state.
+ */
+ public void reset() {
+ mAllowDraggingOffscreen = false;
+ mIsDragging = false;
+ mStartedDragging = false;
+ mIsUserInteracting = false;
+ }
+
+ /**
* Processess a given touch event and updates the state.
*/
public void onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
+ if (!mAllowTouches) {
+ return;
+ }
+
// Initialize the velocity tracker
initOrResetVelocityTracker();
+
mActivePointerId = ev.getPointerId(0);
mLastTouch.set(ev.getX(), ev.getY());
mDownTouch.set(mLastTouch);
- mIsDragging = false;
- mStartedDragging = false;
mAllowDraggingOffscreen = true;
mIsUserInteracting = true;
break;
}
case MotionEvent.ACTION_MOVE: {
+ // Skip event if we did not start processing this touch gesture
+ if (!mIsUserInteracting) {
+ break;
+ }
+
// Update the velocity tracker
mVelocityTracker.addMovement(ev);
int pointerIndex = ev.findPointerIndex(mActivePointerId);
@@ -86,6 +105,11 @@ public class PipTouchState {
break;
}
case MotionEvent.ACTION_POINTER_UP: {
+ // Skip event if we did not start processing this touch gesture
+ if (!mIsUserInteracting) {
+ break;
+ }
+
// Update the velocity tracker
mVelocityTracker.addMovement(ev);
@@ -100,6 +124,11 @@ public class PipTouchState {
break;
}
case MotionEvent.ACTION_UP: {
+ // Skip event if we did not start processing this touch gesture
+ if (!mIsUserInteracting) {
+ break;
+ }
+
// Update the velocity tracker
mVelocityTracker.addMovement(ev);
mVelocityTracker.computeCurrentVelocity(1000,
@@ -112,7 +141,6 @@ public class PipTouchState {
// Fall through to clean up
}
case MotionEvent.ACTION_CANCEL: {
- mIsUserInteracting = false;
recycleVelocityTracker();
break;
}
@@ -171,6 +199,19 @@ public class PipTouchState {
}
/**
+ * Sets whether touching is currently allowed.
+ */
+ public void setAllowTouches(boolean allowTouches) {
+ mAllowTouches = allowTouches;
+
+ // If the user happens to touch down before this is sent from the system during a transition
+ // then block any additional handling by resetting the state now
+ if (mIsUserInteracting) {
+ reset();
+ }
+ }
+
+ /**
* Disallows dragging offscreen for the duration of the current gesture.
*/
public void setDisallowDraggingOffscreen() {
@@ -202,6 +243,7 @@ public class PipTouchState {
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
+ pw.println(innerPrefix + "mAllowTouches=" + mAllowTouches);
pw.println(innerPrefix + "mDownTouch=" + mDownTouch);
pw.println(innerPrefix + "mDownDelta=" + mDownDelta);
pw.println(innerPrefix + "mLastTouch=" + mLastTouch);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index b28b0e70ceb5..a76299d07626 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -288,7 +288,7 @@ public class CustomTile extends QSTile<QSTile.State> implements TileChangeListen
drawable = mTile.getIcon().loadDrawable(mContext);
} catch (Exception e) {
Log.w(TAG, "Invalid icon, forcing into unavailable state");
- tileState = Tile.STATE_UNAVAILABLE;
+ state.state = Tile.STATE_UNAVAILABLE;
drawable = mDefaultIcon.loadDrawable(mContext);
}
state.icon = new DrawableIcon(drawable);
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 cda902b6fb69..1042356042f8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -154,6 +154,7 @@ public class SystemServicesProxy {
public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
public void onActivityPinned() { }
public void onPinnedActivityRestartAttempt(String launchedFromPackage) { }
+ public void onPinnedStackAnimationStarted() { }
public void onPinnedStackAnimationEnded() { }
public void onActivityForcedResizable(String packageName, int taskId) { }
public void onActivityDismissingDockedStack() { }
@@ -206,6 +207,12 @@ public class SystemServicesProxy {
}
@Override
+ public void onPinnedStackAnimationStarted() throws RemoteException {
+ mHandler.removeMessages(H.ON_PINNED_STACK_ANIMATION_STARTED);
+ mHandler.sendEmptyMessage(H.ON_PINNED_STACK_ANIMATION_STARTED);
+ }
+
+ @Override
public void onPinnedStackAnimationEnded() throws RemoteException {
mHandler.removeMessages(H.ON_PINNED_STACK_ANIMATION_ENDED);
mHandler.sendEmptyMessage(H.ON_PINNED_STACK_ANIMATION_ENDED);
@@ -1219,6 +1226,7 @@ public class SystemServicesProxy {
private static final int ON_ACTIVITY_FORCED_RESIZABLE = 6;
private static final int ON_ACTIVITY_DISMISSING_DOCKED_STACK = 7;
private static final int ON_TASK_PROFILE_LOCKED = 8;
+ private static final int ON_PINNED_STACK_ANIMATION_STARTED = 9;
@Override
public void handleMessage(Message msg) {
@@ -1248,6 +1256,12 @@ public class SystemServicesProxy {
}
break;
}
+ case ON_PINNED_STACK_ANIMATION_STARTED: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onPinnedStackAnimationStarted();
+ }
+ break;
+ }
case ON_PINNED_STACK_ANIMATION_ENDED: {
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
mTaskStackListeners.get(i).onPinnedStackAnimationEnded();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 36ed551ec4bc..8da17fa76bd7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -41,7 +41,8 @@ import com.android.systemui.statusbar.stack.ViewState;
* A notification shelf view that is placed inside the notification scroller. It manages the
* overflow icons that don't fit into the regular list anymore.
*/
-public class NotificationShelf extends ActivatableNotificationView {
+public class NotificationShelf extends ActivatableNotificationView implements
+ View.OnLayoutChangeListener {
public static final boolean SHOW_AMBIENT_ICONS = true;
private static final boolean USE_ANIMATIONS_WHEN_OPENING =
@@ -494,6 +495,10 @@ public class NotificationShelf extends ActivatableNotificationView {
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
+ updateRelativeOffset();
+ }
+
+ private void updateRelativeOffset() {
mCollapsedIcons.getLocationOnScreen(mTmp);
mRelativeOffset = mTmp[0];
getLocationOnScreen(mTmp);
@@ -560,6 +565,7 @@ public class NotificationShelf extends ActivatableNotificationView {
public void setCollapsedIcons(NotificationIconContainer collapsedIcons) {
mCollapsedIcons = collapsedIcons;
+ mCollapsedIcons.addOnLayoutChangeListener(this);
}
public void setStatusBarState(int statusBarState) {
@@ -595,6 +601,12 @@ public class NotificationShelf extends ActivatableNotificationView {
}
}
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
+ int oldTop, int oldRight, int oldBottom) {
+ updateRelativeOffset();
+ }
+
private class ShelfState extends ExpandableViewState {
private float openedAmount;
private boolean hasItemsInStableShelf;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index aec9a4b421ae..110170194294 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -612,8 +612,10 @@ public class StatusBarIconView extends AnimatedImageView {
}
public void setIconAppearAmount(float iconAppearAmount) {
- mIconAppearAmount = iconAppearAmount;
- invalidate();
+ if (mIconAppearAmount != iconAppearAmount) {
+ mIconAppearAmount = iconAppearAmount;
+ invalidate();
+ }
}
public float getIconAppearAmount() {
@@ -625,8 +627,10 @@ public class StatusBarIconView extends AnimatedImageView {
}
public void setDotAppearAmount(float dotAppearAmount) {
- mDotAppearAmount = dotAppearAmount;
- invalidate();
+ if (mDotAppearAmount != dotAppearAmount) {
+ mDotAppearAmount = dotAppearAmount;
+ invalidate();
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index 1f56c563bef7..6cd3eae366e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -153,7 +153,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
}
private boolean shouldHideNotificationIcons() {
- return !mStatusBar.isClosed() && mStatusBarComponent.shouldHideNotificationIcons();
+ return !mStatusBar.isClosed() && mStatusBarComponent.hideStatusBarIconsWhenExpanded();
}
public void hideSystemIconArea(boolean animate) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 707997d5be45..45812042412c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -79,7 +79,9 @@ public class NotificationIconAreaController implements DarkReceiver {
for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
View child = mNotificationIcons.getChildAt(i);
child.setLayoutParams(params);
- child = mShelfIcons.getChildAt(i);
+ }
+ for (int i = 0; i < mShelfIcons.getChildCount(); i++) {
+ View child = mShelfIcons.getChildAt(i);
child.setLayoutParams(params);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 468fb57069ee..e6d3168693a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -26,7 +26,6 @@ import android.app.StatusBarManager;
import android.content.Context;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
@@ -47,7 +46,6 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.DejankUtils;
-import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -179,7 +177,7 @@ public class NotificationPanelView extends PanelView implements
private boolean mKeyguardStatusViewAnimating;
private ValueAnimator mQsSizeChangeAnimator;
- private boolean mShadeEmpty;
+ private boolean mShowEmptyShadeView;
private boolean mQsScrimEnabled = true;
private boolean mLastAnnouncementWasQuickSettings;
@@ -211,11 +209,12 @@ public class NotificationPanelView extends PanelView implements
}
};
private NotificationGroupManager mGroupManager;
- private boolean mOpening;
+ private boolean mShowIconsWhenExpanded;
private int mIndicationBottomPadding;
private boolean mIsFullWidth;
private boolean mDark;
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
+ private boolean mNoVisibleNotifications = true;
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -1518,7 +1517,7 @@ public class NotificationPanelView extends PanelView implements
// it in expanded QS state as well so we don't run into troubles when fading the view in/out
// and expanding/collapsing the whole panel from/to quick settings.
if (mNotificationStackScroller.getNotGoneChildCount() == 0
- && mShadeEmpty) {
+ && mShowEmptyShadeView) {
notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight();
}
int maxQsHeight = mQsMaxExpansionHeight;
@@ -2118,15 +2117,15 @@ public class NotificationPanelView extends PanelView implements
return mDozing;
}
- public void setShadeEmpty(boolean shadeEmpty) {
- mShadeEmpty = shadeEmpty;
+ public void showEmptyShadeView(boolean emptyShadeViewVisible) {
+ mShowEmptyShadeView = emptyShadeViewVisible;
updateEmptyShadeView();
}
private void updateEmptyShadeView() {
// Hide "No notifications" in QS.
- mNotificationStackScroller.updateEmptyShadeView(mShadeEmpty && !mQsExpanded);
+ mNotificationStackScroller.updateEmptyShadeView(mShowEmptyShadeView && !mQsExpanded);
}
public void setQsScrimEnabled(boolean qsScrimEnabled) {
@@ -2306,7 +2305,7 @@ public class NotificationPanelView extends PanelView implements
}
mNotificationStackScroller.setExpandedHeight(expandedHeight);
updateKeyguardBottomAreaAlpha();
- setOpening(isFullWidth() && expandedHeight < getOpeningHeight());
+ updateStatusBarIcons();
}
/**
@@ -2317,13 +2316,21 @@ public class NotificationPanelView extends PanelView implements
return mIsFullWidth;
}
- private void setOpening(boolean opening) {
- if (opening != mOpening) {
- mOpening = opening;
+ private void updateStatusBarIcons() {
+ boolean showIconsWhenExpanded = isFullWidth() && getExpandedHeight() < getOpeningHeight();
+ if (showIconsWhenExpanded && mNoVisibleNotifications && isOnKeyguard()) {
+ showIconsWhenExpanded = false;
+ }
+ if (showIconsWhenExpanded != mShowIconsWhenExpanded) {
+ mShowIconsWhenExpanded = showIconsWhenExpanded;
mStatusBar.recomputeDisableFlags(false);
}
}
+ private boolean isOnKeyguard() {
+ return mStatusBar.getBarState() == StatusBarState.KEYGUARD;
+ }
+
public void setPanelScrimMinFraction(float minFraction) {
mBar.panelScrimMinFractionChanged(minFraction);
}
@@ -2426,12 +2433,8 @@ public class NotificationPanelView extends PanelView implements
mGroupManager = groupManager;
}
- public boolean shouldHideNotificationIcons() {
- return !isFullWidth() || (!mOpening && !isFullyCollapsed());
- }
-
- public boolean shouldAnimateIconHiding() {
- return !isFullWidth();
+ public boolean hideStatusBarIconsWhenExpanded() {
+ return !isFullWidth() || !mShowIconsWhenExpanded;
}
private final FragmentListener mFragmentListener = new FragmentListener() {
@@ -2473,4 +2476,8 @@ public class NotificationPanelView extends PanelView implements
mKeyguardStatusView.setDark(dark);
positionClockAndNotifications();
}
+
+ public void setNoVisibleNotifications(boolean noNotifications) {
+ mNoVisibleNotifications = noNotifications;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 9e93ed3c813f..bb6c8f2e1e73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone;
import android.app.ActivityManager;
-import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.ActivityManager.StackId;
import android.app.ActivityManager.StackInfo;
import android.app.AlarmManager;
@@ -25,8 +24,6 @@ import android.app.AlarmManager.AlarmClockInfo;
import android.app.AppGlobals;
import android.app.Notification;
import android.app.Notification.Action;
-import android.app.Notification.BigTextStyle;
-import android.app.Notification.Style;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.SynchronousUserSwitchObserver;
@@ -37,7 +34,6 @@ import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.graphics.drawable.Icon;
import android.media.AudioManager;
@@ -51,7 +47,6 @@ import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.notification.StatusBarNotification;
import android.telecom.TelecomManager;
-import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
@@ -61,11 +56,9 @@ import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.R.string;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.RotationLockTile;
-import com.android.systemui.recents.Recents;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
import com.android.systemui.statusbar.CommandQueue;
@@ -87,9 +80,6 @@ import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.NotificationChannels;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* This class contains all of the policy about which icons are installed in the status
* bar at boot time. It goes through the normal API for icons, even though it probably
@@ -137,8 +127,6 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
private boolean mVolumeVisible;
private boolean mCurrentUserSetup;
- private int mZen;
-
private boolean mManagedProfileFocused = false;
private boolean mManagedProfileIconVisible = false;
private boolean mManagedProfileInQuietMode = false;
@@ -275,14 +263,14 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
@Override
public void onZenChanged(int zen) {
- mZen = zen;
updateVolumeZen();
}
private void updateAlarm() {
final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
- final boolean zenNone = mZen == Global.ZEN_MODE_NO_INTERRUPTIONS;
+ int zen = mZenController.getZen();
+ final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS;
mIconController.setIcon(mSlotAlarmClock, zenNone ? R.drawable.stat_sys_alarm_dim
: R.drawable.stat_sys_alarm, null);
mIconController.setIconVisibility(mSlotAlarmClock, mCurrentUserSetup && hasAlarm);
@@ -323,17 +311,18 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
boolean volumeVisible = false;
int volumeIconId = 0;
String volumeDescription = null;
+ int zen = mZenController.getZen();
if (DndTile.isVisible(mContext) || DndTile.isCombinedIcon(mContext)) {
- zenVisible = mZen != Global.ZEN_MODE_OFF;
- zenIconId = mZen == Global.ZEN_MODE_NO_INTERRUPTIONS
+ zenVisible = zen != Global.ZEN_MODE_OFF;
+ zenIconId = zen == Global.ZEN_MODE_NO_INTERRUPTIONS
? R.drawable.stat_sys_dnd_total_silence : R.drawable.stat_sys_dnd;
zenDescription = mContext.getString(R.string.quick_settings_dnd_label);
- } else if (mZen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
+ } else if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
zenVisible = true;
zenIconId = R.drawable.stat_sys_zen_none;
zenDescription = mContext.getString(R.string.interruption_level_none);
- } else if (mZen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
+ } else if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
zenVisible = true;
zenIconId = R.drawable.stat_sys_zen_important;
zenDescription = mContext.getString(R.string.interruption_level_priority);
@@ -344,7 +333,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
volumeVisible = true;
volumeIconId = R.drawable.stat_sys_ringer_silent;
volumeDescription = mContext.getString(R.string.accessibility_ringer_silent);
- } else if (mZen != Global.ZEN_MODE_NO_INTERRUPTIONS && mZen != Global.ZEN_MODE_ALARMS &&
+ } else if (zen != Global.ZEN_MODE_NO_INTERRUPTIONS && zen != Global.ZEN_MODE_ALARMS &&
audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
volumeVisible = true;
volumeIconId = R.drawable.stat_sys_ringer_vibrate;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 53d2d735b14e..c90d493f54ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -172,7 +172,6 @@ import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.InflationException;
-import com.android.systemui.statusbar.notification.NotificationInflater;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
@@ -717,7 +716,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private LogMaker mStatusBarStateLog;
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
private NotificationIconAreaController mNotificationIconAreaController;
- private ConfigurationListener mDensityChangeListener;
+ private ConfigurationListener mConfigurationListener;
private InflationExceptionHandler mInflationExceptionHandler = this::handleInflationException;
private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
@@ -945,13 +944,18 @@ public class StatusBar extends SystemUI implements DemoMode,
Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this);
- mDensityChangeListener = new ConfigurationListener() {
+ mConfigurationListener = new ConfigurationListener() {
+ @Override
+ public void onConfigChanged(Configuration newConfig) {
+ StatusBar.this.onConfigurationChanged(newConfig);
+ }
+
@Override
public void onDensityOrFontScaleChanged() {
StatusBar.this.onDensityOrFontScaleChanged();
}
};
- Dependency.get(ConfigurationController.class).addCallback(mDensityChangeListener);
+ Dependency.get(ConfigurationController.class).addCallback(mConfigurationListener);
}
protected void createIconController() {
@@ -2034,10 +2038,10 @@ public class StatusBar extends SystemUI implements DemoMode,
}
private void updateEmptyShadeView() {
- boolean showEmptyShade =
+ boolean showEmptyShadeView =
mState != StatusBarState.KEYGUARD &&
mNotificationData.getActiveNotifications().size() == 0;
- mNotificationPanel.setShadeEmpty(showEmptyShade);
+ mNotificationPanel.showEmptyShadeView(showEmptyShadeView);
}
private void updateSpeedBumpIndex() {
@@ -2720,8 +2724,8 @@ public class StatusBar extends SystemUI implements DemoMode,
return mLaunchTransitionFadingAway;
}
- public boolean shouldHideNotificationIcons() {
- return mNotificationPanel.shouldHideNotificationIcons();
+ public boolean hideStatusBarIconsWhenExpanded() {
+ return mNotificationPanel.hideStatusBarIconsWhenExpanded();
}
/**
@@ -2963,7 +2967,7 @@ public class StatusBar extends SystemUI implements DemoMode,
runPostCollapseRunnables();
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
showBouncerIfKeyguard();
- recomputeDisableFlags(shouldAnimatIconHiding() /* animate */);
+ recomputeDisableFlags(mNotificationPanel.hideStatusBarIconsWhenExpanded() /* animate */);
// Trimming will happen later if Keyguard is showing - doing it here might cause a jank in
// the bouncer appear animation.
@@ -2972,10 +2976,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- private boolean shouldAnimatIconHiding() {
- return mNotificationPanel.shouldAnimateIconHiding();
- }
-
public boolean interceptTouchEvent(MotionEvent event) {
if (DEBUG_GESTURES) {
if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
@@ -3910,7 +3910,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(null);
mDeviceProvisionedController.removeCallback(mUserSetupObserver);
- Dependency.get(ConfigurationController.class).removeCallback(mDensityChangeListener);
+ Dependency.get(ConfigurationController.class).removeCallback(mConfigurationListener);
}
private boolean mDemoModeAllowed;
@@ -6570,6 +6570,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
}
+ mNotificationPanel.setNoVisibleNotifications(visibleNotifications == 0);
mStackScroller.changeViewPosition(mDismissView, mStackScroller.getChildCount() - 1);
mStackScroller.changeViewPosition(mEmptyShadeView, mStackScroller.getChildCount() - 2);
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
index 7a85d4e9b62e..8947b7d99eef 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
@@ -186,6 +186,29 @@ public final class AutoFillManagerService extends SystemService {
}
// Called by Shell command.
+ void destroySessions(int userId, IResultReceiver receiver) {
+ Slog.i(TAG, "destroySessions() for userId " + userId);
+ mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
+
+ synchronized (mLock) {
+ if (userId != UserHandle.USER_ALL) {
+ mServicesCache.get(userId).destroySessionsLocked();
+ } else {
+ final int size = mServicesCache.size();
+ for (int i = 0; i < size; i++) {
+ mServicesCache.valueAt(i).destroySessionsLocked();
+ }
+ }
+ }
+
+ try {
+ receiver.send(0, new Bundle());
+ } catch (RemoteException e) {
+ // Just ignore it...
+ }
+ }
+
+ // Called by Shell command.
void listSessions(int userId, IResultReceiver receiver) {
Slog.i(TAG, "listSessions() for userId " + userId);
mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index bfc6e836c3b0..5e852f1738f1 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -59,7 +59,6 @@ import android.service.autofill.IAutoFillService;
import android.service.autofill.SaveInfo;
import android.text.TextUtils;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.LocalLog;
import android.util.PrintWriterPrinter;
import android.util.Slog;
@@ -405,6 +404,12 @@ final class AutoFillManagerServiceImpl {
}
}
+ void destroySessionsLocked() {
+ for (Session session : mSessions.values()) {
+ session.removeSelf();
+ }
+ }
+
void listSessionsLocked(ArrayList<String> output) {
for (IBinder activityToken : mSessions.keySet()) {
output.add((mInfo != null ? mInfo.getServiceInfo().getComponentName()
@@ -666,6 +671,28 @@ final class AutoFillManagerServiceImpl {
// FillServiceCallbacks
@Override
+ public void onDisableSelf() {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final String autoFillService = Settings.Secure.getStringForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.AUTO_FILL_SERVICE, mUserId);
+ if (mInfo.getServiceInfo().getComponentName().equals(
+ ComponentName.unflattenFromString(autoFillService))) {
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Settings.Secure.AUTO_FILL_SERVICE, null, mUserId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ synchronized (mLock) {
+ destroyLocked();
+ mSessions.remove(this);
+ }
+ }
+
+ // FillServiceCallbacks
+ @Override
public void onServiceDied(RemoteFillService service) {
// TODO(b/33197203): implement
}
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
index cfa4a1d0a107..76eed2ac2639 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
@@ -20,7 +20,6 @@ import static com.android.server.autofill.AutoFillManagerService.RECEIVER_BUNDLE
import android.app.ActivityManager;
import android.os.Bundle;
-import android.os.RemoteException;
import android.os.ShellCommand;
import android.os.UserHandle;
@@ -50,6 +49,8 @@ public final class AutoFillManagerServiceShellCommand extends ShellCommand {
return requestSave();
case "list":
return requestList(pw);
+ case "destroy":
+ return requestDestroy(pw);
case "reset":
return requestReset();
default:
@@ -67,6 +68,9 @@ public final class AutoFillManagerServiceShellCommand extends ShellCommand {
pw.println(" list sessions [--user USER_ID]");
pw.println(" List all pending sessions.");
pw.println("");
+ pw.println(" destroy sessions [--user USER_ID]");
+ pw.println(" Destroy all pending sessions.");
+ pw.println("");
pw.println(" save [--user USER_ID]");
pw.println(" Request provider to save contents of the top activity. ");
pw.println("");
@@ -82,30 +86,55 @@ public final class AutoFillManagerServiceShellCommand extends ShellCommand {
return 0;
}
- private int requestList(PrintWriter pw) {
- final String type = getNextArgRequired();
- if (!type.equals("sessions")) {
- pw.println("Error: invalid list type");
+ private int requestDestroy(PrintWriter pw) {
+ if (!isNextArgSessions(pw)) {
return -1;
-
}
+
final int userId = getUserIdFromArgsOrAllUsers();
final CountDownLatch latch = new CountDownLatch(1);
final IResultReceiver receiver = new IResultReceiver.Stub() {
+ @Override
+ public void send(int resultCode, Bundle resultData) {
+ latch.countDown();
+ }
+ };
+ return requestSessionCommon(pw, latch, () -> mService.destroySessions(userId, receiver));
+ }
+ private int requestList(PrintWriter pw) {
+ if (!isNextArgSessions(pw)) {
+ return -1;
+ }
+
+ final int userId = getUserIdFromArgsOrAllUsers();
+ final CountDownLatch latch = new CountDownLatch(1);
+ final IResultReceiver receiver = new IResultReceiver.Stub() {
@Override
- public void send(int resultCode, Bundle resultData) throws RemoteException {
+ public void send(int resultCode, Bundle resultData) {
final ArrayList<String> sessions = resultData
.getStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS);
-
for (String session : sessions) {
pw.println(session);
}
latch.countDown();
}
};
+ return requestSessionCommon(pw, latch, () -> mService.listSessions(userId, receiver));
+ }
+
+ private boolean isNextArgSessions(PrintWriter pw) {
+ final String type = getNextArgRequired();
+ if (!type.equals("sessions")) {
+ pw.println("Error: invalid list type");
+ return false;
+ }
+ return true;
+ }
- mService.listSessions(userId, receiver);
+ private int requestSessionCommon(PrintWriter pw, CountDownLatch latch,
+ Runnable command) {
+ command.run();
try {
final boolean received = latch.await(5, TimeUnit.SECONDS);
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index c469718780c0..04eeb324ddf6 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -33,6 +33,7 @@ import android.os.UserHandle;
import android.service.autofill.AutoFillService;
import android.service.autofill.FillResponse;
import android.service.autofill.IAutoFillService;
+import android.service.autofill.IAutoFillServiceConnection;
import android.service.autofill.IFillCallback;
import android.service.autofill.ISaveCallback;
import android.text.format.DateUtils;
@@ -57,7 +58,7 @@ final class RemoteFillService implements DeathRecipient {
private static final boolean DEBUG = Helper.DEBUG;
// How long after the last interaction with the service we would unbind
- private static final long TIMEOUT_IDLE_BIND_MILLIS = 5 * DateUtils.MINUTE_IN_MILLIS;
+ private static final long TIMEOUT_IDLE_BIND_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS;
private final Context mContext;
@@ -91,6 +92,7 @@ final class RemoteFillService implements DeathRecipient {
void onSaveRequestSuccess();
void onSaveRequestFailure(CharSequence message);
void onServiceDied(RemoteFillService service);
+ void onDisableSelf();
}
public RemoteFillService(Context context, ComponentName componentName,
@@ -197,6 +199,10 @@ final class RemoteFillService implements DeathRecipient {
}
}
+ private void handleDisableSelf() {
+ mCallbacks.onDisableSelf();
+ }
+
private boolean isBound() {
return mAutoFillService != null;
}
@@ -239,7 +245,7 @@ final class RemoteFillService implements DeathRecipient {
// Need to double check if it's null, since it could be set on onServiceDisconnected()
if (mAutoFillService != null) {
try {
- mAutoFillService.onDisconnected();
+ mAutoFillService.onInit(null);
} catch (Exception e) {
Slog.w(LOG_TAG, "Exception calling onDisconnected(): " + e);
}
@@ -321,7 +327,12 @@ final class RemoteFillService implements DeathRecipient {
// Need to double check if it's null, since it could be set on
// onServiceDisconnected()
if (mAutoFillService != null) {
- mAutoFillService.onConnected();
+ mAutoFillService.onInit(new IAutoFillServiceConnection.Stub() {
+ @Override
+ public void disableSelf() {
+ mHandler.obtainMessage(MyHandler.MSG_ON_DISABLE_SELF).sendToTarget();
+ }
+ });
}
} catch (RemoteException e) {
Slog.w(LOG_TAG, "Exception calling onConnected(): " + e);
@@ -347,6 +358,7 @@ final class RemoteFillService implements DeathRecipient {
public static final int MSG_BINDER_DIED = 2;
public static final int MSG_UNBIND = 3;
public static final int MSG_ON_PENDING_REQUEST = 4;
+ public static final int MSG_ON_DISABLE_SELF = 5;
public MyHandler(Context context) {
// Cannot use lambda - doesn't compile
@@ -374,6 +386,10 @@ final class RemoteFillService implements DeathRecipient {
case MSG_ON_PENDING_REQUEST: {
handlePendingRequest((PendingRequest) message.obj);
} break;
+
+ case MSG_ON_DISABLE_SELF: {
+ handleDisableSelf();
+ } break;
}
}
}, false);
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 949a80c7bfdc..0da36c8936c8 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -26,6 +26,7 @@ import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
import android.service.autofill.SaveInfo;
import android.text.TextUtils;
+import android.util.Slog;
import android.view.autofill.AutoFillId;
import android.widget.Toast;
@@ -41,6 +42,8 @@ import java.io.PrintWriter;
* managing saving of user edits.
*/
public final class AutoFillUI {
+ private static final String TAG = "AutoFillUI";
+
private final Handler mHandler = UiThread.getHandler();
private final @NonNull Context mContext;
@@ -191,9 +194,17 @@ public final class AutoFillUI {
}
@Override
- public void onCancel() {
+ public void onCancel(IntentSender listener) {
// TODO(b/33197203): add MetricsLogger call
hideSaveUiUiThread();
+ if (listener != null) {
+ try {
+ listener.sendIntent(mContext, 0, null, null, null);
+ } catch (IntentSender.SendIntentException e) {
+ Slog.e(TAG, "Error starting negative action listener: "
+ + listener, e);
+ }
+ }
}
});
});
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index afe93c7d6e06..d443dc34f949 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -19,6 +19,7 @@ package com.android.server.autofill.ui;
import android.annotation.NonNull;
import android.app.Dialog;
import android.content.Context;
+import android.content.IntentSender;
import android.os.Handler;
import android.service.autofill.SaveInfo;
import android.text.format.DateUtils;
@@ -38,7 +39,7 @@ import com.android.server.UiThread;
final class SaveUi {
public interface OnSaveListener {
void onSave();
- void onCancel();
+ void onCancel(IntentSender listener);
}
private static final long LIFETIME_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS;
@@ -87,14 +88,20 @@ final class SaveUi {
subTitleView.setVisibility(View.VISIBLE);
}
- final View noButton = view.findViewById(R.id.autofill_save_no);
- noButton.setOnClickListener((v) -> mListener.onCancel());
+ final TextView noButton = view.findViewById(R.id.autofill_save_no);
+ if (info.getNegativeActionTitle() != null) {
+ noButton.setText(info.getNegativeActionTitle());
+ noButton.setOnClickListener((v) -> mListener.onCancel(
+ info.getNegativeActionListener()));
+ } else {
+ noButton.setOnClickListener((v) -> mListener.onCancel(null));
+ }
final View yesButton = view.findViewById(R.id.autofill_save_yes);
yesButton.setOnClickListener((v) -> mListener.onSave());
final View closeButton = view.findViewById(R.id.autofill_save_close);
- closeButton.setOnClickListener((v) -> mListener.onCancel());
+ closeButton.setOnClickListener((v) -> mListener.onCancel(null));
mDialog = new Dialog(context, R.style.Theme_Material_Panel);
mDialog.setContentView(view);
@@ -112,7 +119,7 @@ final class SaveUi {
mDialog.show();
- mHandler.postDelayed(() -> mListener.onCancel(), LIFETIME_MILLIS);
+ mHandler.postDelayed(() -> mListener.onCancel(null), LIFETIME_MILLIS);
}
void destroy() {
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 4f8b8af49518..2d947a4dfca1 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -16,9 +16,23 @@
package com.android.server.backup;
-import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER;
-import static android.app.backup.BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_OLD_VERSION;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_POLICY_ALLOW_APKS;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_MANIFEST_PACKAGE_NAME;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_SYSTEM_APP_NO_AGENT;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_APK_NOT_INSTALLED;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_MISSING_SIGNATURE;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_RESTORE_ANY_VERSION;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSIONS_MATCH;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
import android.app.ActivityManager;
@@ -2374,6 +2388,8 @@ public class BackupManagerService {
IBackupTransport transport = mTransportManager.getCurrentTransportBinder();
if (transport == null) {
sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
+ monitor = monitorEvent(monitor, BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL,
+ null, BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null);
return BackupManager.ERROR_TRANSPORT_ABORTED;
}
@@ -3338,6 +3354,14 @@ public class BackupManagerService {
addBackupTrace("illegal key " + key + " from " + pkgName);
EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, pkgName,
"bad key");
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_ILLEGAL_KEY,
+ mCurrentPackage,
+ BackupManagerMonitor
+ .LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ putMonitoringExtra(null,
+ BackupManagerMonitor.EXTRA_LOG_ILLEGAL_KEY,
+ key));
mBackupHandler.removeMessages(MSG_BACKUP_OPERATION_TIMEOUT);
sendBackupOnPackageResult(mObserver, pkgName,
BackupManager.ERROR_AGENT_FAILURE);
@@ -3407,6 +3431,11 @@ public class BackupManagerService {
if (MORE_DEBUG) Slog.i(TAG,
"no backup data written; not calling transport");
addBackupTrace("no data to send");
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_NO_DATA_TO_SEND,
+ mCurrentPackage,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ null);
}
if (mStatus == BackupTransport.TRANSPORT_OK) {
@@ -3502,8 +3531,10 @@ public class BackupManagerService {
Slog.e(TAG, "Cancel backing up " + mCurrentPackage.packageName);
EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, mCurrentPackage.packageName);
mMonitor = monitorEvent(mMonitor,
- BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_TIMEOUT,
- mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
+ BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL,
+ mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
+ putMonitoringExtra(null, BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL,
+ mCancelAll));
addBackupTrace(
"cancel of " + mCurrentPackage.packageName + ", cancelAll=" + cancelAll);
errorCleanup();
@@ -4593,6 +4624,11 @@ public class BackupManagerService {
if (MORE_DEBUG) {
Slog.d(TAG, "Ignoring ineligible package " + pkg);
}
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_INELIGIBLE,
+ mCurrentPackage,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ null);
sendBackupOnPackageResult(mBackupObserver, pkg,
BackupManager.ERROR_BACKUP_NOT_ALLOWED);
continue;
@@ -4603,6 +4639,11 @@ public class BackupManagerService {
Slog.d(TAG, "Ignoring full-data backup of key/value participant "
+ pkg);
}
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_KEY_VALUE_PARTICIPANT,
+ mCurrentPackage,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ null);
sendBackupOnPackageResult(mBackupObserver, pkg,
BackupManager.ERROR_BACKUP_NOT_ALLOWED);
continue;
@@ -4613,6 +4654,11 @@ public class BackupManagerService {
if (MORE_DEBUG) {
Slog.d(TAG, "Ignoring stopped package " + pkg);
}
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_STOPPED,
+ mCurrentPackage,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ null);
sendBackupOnPackageResult(mBackupObserver, pkg,
BackupManager.ERROR_BACKUP_NOT_ALLOWED);
continue;
@@ -4620,7 +4666,7 @@ public class BackupManagerService {
mPackages.add(info);
} catch (NameNotFoundException e) {
Slog.i(TAG, "Requested package " + pkg + " not found; ignoring");
- monitor = monitorEvent(monitor,
+ mMonitor = monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_FOUND,
mCurrentPackage,
BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
@@ -4696,9 +4742,17 @@ public class BackupManagerService {
if (!mEnabled || !mProvisioned) {
// Backups are globally disabled, so don't proceed.
if (DEBUG) {
- Slog.i(TAG, "full backup requested but e=" + mEnabled
- + " p=" + mProvisioned + "; ignoring");
+ Slog.i(TAG, "full backup requested but enabled=" + mEnabled
+ + " provisioned=" + mProvisioned + "; ignoring");
+ }
+ int monitoringEvent;
+ if (!mEnabled) {
+ monitoringEvent = BackupManagerMonitor.LOG_EVENT_ID_BACKUP_DISABLED;
+ } else {
+ monitoringEvent = BackupManagerMonitor.LOG_EVENT_ID_DEVICE_NOT_PROVISIONED;
}
+ mMonitor = monitorEvent(mMonitor, monitoringEvent, null,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
mUpdateSchedule = false;
backupRunStatus = BackupManager.ERROR_BACKUP_NOT_ALLOWED;
return;
@@ -4722,7 +4776,8 @@ public class BackupManagerService {
PackageInfo currentPackage = mPackages.get(i);
String packageName = currentPackage.packageName;
if (DEBUG) {
- Slog.i(TAG, "Initiating full-data transport backup of " + packageName);
+ Slog.i(TAG, "Initiating full-data transport backup of " + packageName
+ + " token: " + mCurrentOpToken);
}
EventLog.writeEvent(EventLogTags.FULL_BACKUP_PACKAGE, packageName);
@@ -4781,6 +4836,13 @@ public class BackupManagerService {
+ packageName + ": " + preflightResult
+ ", not running backup.");
}
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_ERROR_PREFLIGHT,
+ mCurrentPackage,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ putMonitoringExtra(null,
+ BackupManagerMonitor.EXTRA_LOG_PREFLIGHT_ERROR,
+ preflightResult));
backupPackageStatus = (int) preflightResult;
} else {
int nRead = 0;
@@ -4808,6 +4870,11 @@ public class BackupManagerService {
if (backupPackageStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
Slog.w(TAG, "Package hit quota limit in-flight " + packageName
+ ": " + totalRead + " of " + quota);
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_QUOTA_HIT_PREFLIGHT,
+ mCurrentPackage,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT,
+ null);
mBackupRunner.sendQuotaExceeded(totalRead, quota);
}
}
@@ -4942,6 +5009,14 @@ public class BackupManagerService {
} catch (Exception e) {
backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED;
Slog.w(TAG, "Exception trying full transport backup", e);
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_EXCEPTION_FULL_BACKUP,
+ mCurrentPackage,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ putMonitoringExtra(null,
+ BackupManagerMonitor.EXTRA_LOG_EXCEPTION_FULL_BACKUP,
+ Log.getStackTraceString(e)));
+
} finally {
if (mCancelAll) {
@@ -5221,7 +5296,7 @@ public class BackupManagerService {
}
mMonitor = monitorEvent(mMonitor,
- BackupManagerMonitor.LOG_EVENT_ID_FULL_BACKUP_TIMEOUT,
+ BackupManagerMonitor.LOG_EVENT_ID_FULL_BACKUP_CANCEL,
mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
mIsCancelled = true;
// Cancel tasks spun off by this task.
@@ -6309,9 +6384,29 @@ public class BackupManagerService {
} else {
Slog.w(TAG, "Metadata mismatch: package " + info.packageName
+ " but widget data for " + pkg);
+
+ Bundle monitoringExtras = putMonitoringExtra(null,
+ EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
+ monitoringExtras = putMonitoringExtra(monitoringExtras,
+ BackupManagerMonitor.EXTRA_LOG_WIDGET_PACKAGE_NAME, pkg);
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_WIDGET_METADATA_MISMATCH,
+ null,
+ LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ monitoringExtras);
}
} else {
Slog.w(TAG, "Unsupported metadata version " + version);
+
+ Bundle monitoringExtras = putMonitoringExtra(null, EXTRA_LOG_EVENT_PACKAGE_NAME,
+ info.packageName);
+ monitoringExtras = putMonitoringExtra(monitoringExtras,
+ EXTRA_LOG_EVENT_PACKAGE_VERSION, version);
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_WIDGET_UNKNOWN_VERSION,
+ null,
+ LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ monitoringExtras);
}
}
@@ -6386,10 +6481,20 @@ public class BackupManagerService {
if ((pkgInfo.applicationInfo.flags
& ApplicationInfo.FLAG_RESTORE_ANY_VERSION) != 0) {
Slog.i(TAG, "Package has restoreAnyVersion; taking data");
+ mMonitor = monitorEvent(mMonitor,
+ LOG_EVENT_ID_RESTORE_ANY_VERSION,
+ pkgInfo,
+ LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ null);
policy = RestorePolicy.ACCEPT;
} else if (pkgInfo.versionCode >= version) {
Slog.i(TAG, "Sig + version match; taking data");
policy = RestorePolicy.ACCEPT;
+ mMonitor = monitorEvent(mMonitor,
+ LOG_EVENT_ID_VERSIONS_MATCH,
+ pkgInfo,
+ LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ null);
} else {
// The data is from a newer version of the app than
// is presently installed. That means we can only
@@ -6403,30 +6508,43 @@ public class BackupManagerService {
} else {
Slog.i(TAG, "Data requires newer version "
+ version + "; ignoring");
- ArrayList<Pair<String, String>> list =
- new ArrayList<>();
- list.add(new Pair<String, String>(
- EXTRA_LOG_OLD_VERSION,
- Integer.toString(version)));
mMonitor = monitorEvent(mMonitor,
LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER,
pkgInfo,
LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
- list);
+ putMonitoringExtra(null,
+ EXTRA_LOG_OLD_VERSION,
+ version));
+
policy = RestorePolicy.IGNORE;
}
}
} else {
Slog.w(TAG, "Restore manifest signatures do not match "
+ "installed application for " + info.packageName);
+ mMonitor = monitorEvent(mMonitor,
+ LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH,
+ pkgInfo,
+ LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ null);
}
} else {
Slog.w(TAG, "Package " + info.packageName
+ " is system level with no agent");
+ mMonitor = monitorEvent(mMonitor,
+ LOG_EVENT_ID_SYSTEM_APP_NO_AGENT,
+ pkgInfo,
+ LOG_EVENT_CATEGORY_AGENT,
+ null);
}
} else {
if (DEBUG) Slog.i(TAG, "Restore manifest from "
+ info.packageName + " but allowBackup=false");
+ mMonitor = monitorEvent(mMonitor,
+ LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE,
+ pkgInfo,
+ LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ null);
}
} catch (NameNotFoundException e) {
// Okay, the target app isn't installed. We can process
@@ -6439,26 +6557,71 @@ public class BackupManagerService {
} else {
policy = RestorePolicy.IGNORE;
}
+ Bundle monitoringExtras = putMonitoringExtra(null,
+ EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
+ monitoringExtras = putMonitoringExtra(monitoringExtras,
+ EXTRA_LOG_POLICY_ALLOW_APKS, mAllowApks);
+ mMonitor = monitorEvent(mMonitor,
+ LOG_EVENT_ID_APK_NOT_INSTALLED,
+ null,
+ LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ monitoringExtras);
}
if (policy == RestorePolicy.ACCEPT_IF_APK && !hasApk) {
Slog.i(TAG, "Cannot restore package " + info.packageName
+ " without the matching .apk");
+ mMonitor = monitorEvent(mMonitor,
+ LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK,
+ null,
+ LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ putMonitoringExtra(null,
+ EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName));
}
} else {
Slog.i(TAG, "Missing signature on backed-up package "
+ info.packageName);
+ mMonitor = monitorEvent(mMonitor,
+ LOG_EVENT_ID_MISSING_SIGNATURE,
+ null,
+ LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ putMonitoringExtra(null,
+ EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName));
}
} else {
Slog.i(TAG, "Expected package " + info.packageName
+ " but restore manifest claims " + manifestPackage);
+ Bundle monitoringExtras = putMonitoringExtra(null,
+ EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
+ monitoringExtras = putMonitoringExtra(monitoringExtras,
+ EXTRA_LOG_MANIFEST_PACKAGE_NAME, manifestPackage);
+ mMonitor = monitorEvent(mMonitor,
+ LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE,
+ null,
+ LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ monitoringExtras);
}
} else {
Slog.i(TAG, "Unknown restore manifest version " + version
+ " for package " + info.packageName);
+ Bundle monitoringExtras = putMonitoringExtra(null,
+ EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
+ monitoringExtras = putMonitoringExtra(monitoringExtras,
+ EXTRA_LOG_EVENT_PACKAGE_VERSION, version);
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_UNKNOWN_VERSION,
+ null,
+ LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ monitoringExtras);
+
}
} catch (NumberFormatException e) {
Slog.w(TAG, "Corrupt restore manifest for package " + info.packageName);
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_CORRUPT_MANIFEST,
+ null,
+ LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ putMonitoringExtra(null, EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName));
} catch (IllegalArgumentException e) {
Slog.w(TAG, e.getMessage());
}
@@ -8557,7 +8720,12 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
return;
}
if (!PACKAGE_MANAGER_SENTINEL.equals(desc.getPackageName())) {
- Slog.e(TAG, "Required metadata but got " + desc.getPackageName());
+ Slog.e(TAG, "Required package metadata but got "
+ + desc.getPackageName());
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_NO_PM_METADATA_RECEIVED,
+ mCurrentPackage,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
mStatus = BackupTransport.TRANSPORT_ERROR;
executeNextState(UnifiedRestoreState.FINAL);
return;
@@ -8585,7 +8753,11 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// signature/version verification etc, so we simply do not proceed with
// the restore operation.
if (!mPmAgent.hasMetadata()) {
- Slog.e(TAG, "No restore metadata available, so not restoring");
+ Slog.e(TAG, "PM agent has no metadata, so not restoring");
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_PM_AGENT_HAS_NO_METADATA,
+ mCurrentPackage,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
PACKAGE_MANAGER_SENTINEL,
"Package manager restore metadata missing");
@@ -8601,6 +8773,10 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
} catch (Exception e) {
// If we lost the transport at any time, halt
Slog.e(TAG, "Unable to contact transport for restore: " + e.getMessage());
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_LOST_TRANSPORT,
+ null,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null);
mStatus = BackupTransport.TRANSPORT_ERROR;
mBackupHandler.removeMessages(MSG_BACKUP_RESTORE_STEP, this);
executeNextState(UnifiedRestoreState.FINAL);
@@ -8670,17 +8846,37 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// handle this case, we do not attempt the restore.
if ((mCurrentPackage.applicationInfo.flags
& ApplicationInfo.FLAG_RESTORE_ANY_VERSION) == 0) {
- String message = "Version " + metaInfo.versionCode
+ String message = "Source version " + metaInfo.versionCode
+ " > installed version " + mCurrentPackage.versionCode;
Slog.w(TAG, "Package " + pkgName + ": " + message);
+ Bundle monitoringExtras = putMonitoringExtra(null,
+ BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION,
+ metaInfo.versionCode);
+ monitoringExtras = putMonitoringExtra(monitoringExtras,
+ BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, false);
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER,
+ mCurrentPackage,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ monitoringExtras);
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
pkgName, message);
nextState = UnifiedRestoreState.RUNNING_QUEUE;
return;
} else {
- if (DEBUG) Slog.v(TAG, "Version " + metaInfo.versionCode
- + " > installed " + mCurrentPackage.versionCode
+ if (DEBUG) Slog.v(TAG, "Source version " + metaInfo.versionCode
+ + " > installed version " + mCurrentPackage.versionCode
+ " but restoreAnyVersion");
+ Bundle monitoringExtras = putMonitoringExtra(null,
+ BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION,
+ metaInfo.versionCode);
+ monitoringExtras = putMonitoringExtra(monitoringExtras,
+ BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, true);
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER,
+ mCurrentPackage,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ monitoringExtras);
}
}
@@ -8739,6 +8935,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
Metadata metaInfo = mPmAgent.getRestoredMetadata(packageName);
if (!BackupUtils.signaturesMatch(metaInfo.sigHashes, mCurrentPackage)) {
Slog.w(TAG, "Signature mismatch restoring " + packageName);
+ mMonitor = monitorEvent(mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_SIGNATURE_MISMATCH, mCurrentPackage,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
"Signature mismatch");
executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
@@ -11035,23 +11234,54 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
}
}
+ private Bundle putMonitoringExtra(Bundle extras, String key, String value) {
+ if (extras == null) {
+ extras = new Bundle();
+ }
+ extras.putString(key, value);
+ return extras;
+ }
+
+ private Bundle putMonitoringExtra(Bundle extras, String key, int value) {
+ if (extras == null) {
+ extras = new Bundle();
+ }
+ extras.putInt(key, value);
+ return extras;
+ }
+
+ private Bundle putMonitoringExtra(Bundle extras, String key, long value) {
+ if (extras == null) {
+ extras = new Bundle();
+ }
+ extras.putLong(key, value);
+ return extras;
+ }
+
+
+ private Bundle putMonitoringExtra(Bundle extras, String key, boolean value) {
+ if (extras == null) {
+ extras = new Bundle();
+ }
+ extras.putBoolean(key, value);
+ return extras;
+ }
+
private static IBackupManagerMonitor monitorEvent(IBackupManagerMonitor monitor, int id,
- PackageInfo pkg, int category, ArrayList<Pair<String, String>> extras) {
+ PackageInfo pkg, int category, Bundle extras) {
if (monitor != null) {
try {
Bundle bundle = new Bundle();
bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID, id);
bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY, category);
if (pkg != null) {
- bundle.putString(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME,
+ bundle.putString(EXTRA_LOG_EVENT_PACKAGE_NAME,
pkg.packageName);
bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION,
pkg.versionCode);
}
if (extras != null) {
- for (Pair<String,String> pair : extras) {
- bundle.putString(pair.first, pair.second);
- }
+ bundle.putAll(extras);
}
monitor.onEvent(bundle);
return monitor;
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index b9dbe13af7c8..619ddb16ee9b 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -41,6 +41,7 @@ import com.android.internal.backup.IBackupTransport;
import com.android.server.EventLogTags;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -103,13 +104,18 @@ class TransportManager {
// been removed from mBoundTransports because onServiceDisconnected would already been
// called on TransportConnection objects.
synchronized (mTransportLock) {
- for (ComponentName transport : mValidTransports.keySet()) {
- if (transport.getPackageName().equals(packageName)) {
- TransportConnection removed = mValidTransports.remove(transport);
- if (removed != null) {
- mContext.unbindService(removed);
- log_verbose("Package removed, Removing transport: " +
- transport.flattenToShortString());
+ Iterator<Map.Entry<ComponentName, TransportConnection>> iter =
+ mValidTransports.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry<ComponentName, TransportConnection> validTransport = iter.next();
+ ComponentName componentName = validTransport.getKey();
+ if (componentName.getPackageName().equals(packageName)) {
+ TransportConnection transportConnection = validTransport.getValue();
+ iter.remove();
+ if (transportConnection != null) {
+ mContext.unbindService(transportConnection);
+ log_verbose("Package removed, removing transport: "
+ + componentName.flattenToShortString());
}
}
}
@@ -278,15 +284,16 @@ class TransportManager {
}
private void tryBindTransport(ServiceInfo transport) {
- Slog.d(TAG, "Binding to transport: " + transport.getComponentName().flattenToShortString());
+ final ComponentName transportComponentName = transport.getComponentName();
+ Slog.d(TAG, "Binding to transport: " + transportComponentName.flattenToShortString());
// TODO: b/22388012 (Multi user backup and restore)
- TransportConnection connection = new TransportConnection(transport.getComponentName());
- if (bindToTransport(transport.getComponentName(), connection)) {
+ TransportConnection connection = new TransportConnection(transportComponentName);
+ if (bindToTransport(transportComponentName, connection)) {
synchronized (mTransportLock) {
- mValidTransports.put(transport.getComponentName(), connection);
+ mValidTransports.put(transportComponentName, connection);
}
} else {
- Slog.w(TAG, "Couldn't bind to transport " + transport.getComponentName());
+ Slog.w(TAG, "Couldn't bind to transport " + transportComponentName);
}
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 5ffb7385fcc3..0d438cb0f87a 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -99,6 +99,7 @@ class AlarmManagerService extends SystemService {
static final boolean DEBUG_VALIDATE = localLOGV || false;
static final boolean DEBUG_ALARM_CLOCK = localLOGV || false;
static final boolean DEBUG_LISTENER_CALLBACK = localLOGV || false;
+ static final boolean DEBUG_WAKELOCK = localLOGV || false;
static final boolean RECORD_ALARMS_IN_HISTORY = true;
static final boolean RECORD_DEVICE_IDLE_ALARMS = false;
static final int ALARM_EVENT = 1;
@@ -2934,6 +2935,9 @@ class AlarmManagerService extends SystemService {
updateStatsLocked(inflight);
}
mBroadcastRefCount--;
+ if (DEBUG_WAKELOCK) {
+ Slog.d(TAG, "mBroadcastRefCount -> " + mBroadcastRefCount);
+ }
if (mBroadcastRefCount == 0) {
mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0).sendToTarget();
mWakeLock.release();
@@ -3074,6 +3078,9 @@ class AlarmManagerService extends SystemService {
}
// The alarm is now in flight; now arrange wakelock and stats tracking
+ if (DEBUG_WAKELOCK) {
+ Slog.d(TAG, "mBroadcastRefCount -> " + (mBroadcastRefCount + 1));
+ }
if (mBroadcastRefCount == 0) {
setWakelockWorkSource(alarm.operation, alarm.workSource,
alarm.type, alarm.statsTag, (alarm.operation == null) ? alarm.uid : -1,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 88ceb6fa4109..54ee5dc43034 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -135,6 +135,8 @@ import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
+import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
+import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_RELAUNCH;
import static com.android.server.wm.AppTransition.TRANSIT_NONE;
@@ -144,6 +146,8 @@ import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_FRONT;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
+import static java.lang.Integer.MAX_VALUE;
+
import android.Manifest;
import android.Manifest.permission;
import android.annotation.NonNull;
@@ -4157,13 +4161,9 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
for (int i=mLruProcesses.size()-1; i>=0; i--) {
final ProcessRecord proc = mLruProcesses.get(i);
- if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT
- || procState > proc.setProcState) {
- if (proc.pkgList.containsKey(packageName)) {
- procState = proc.setProcState;
- break;
- }
- if (proc.pkgDeps != null && proc.pkgDeps.contains(packageName)) {
+ if (procState > proc.setProcState) {
+ if (proc.pkgList.containsKey(packageName) ||
+ (proc.pkgDeps != null && proc.pkgDeps.contains(packageName))) {
procState = proc.setProcState;
}
}
@@ -9812,14 +9812,19 @@ public class ActivityManagerService extends IActivityManager.Stub
} else if (bounds != null && stackId != FREEFORM_WORKSPACE_STACK_ID ) {
stackId = FREEFORM_WORKSPACE_STACK_ID;
}
+
+ // Reparent the task to the right stack if necessary
boolean preserveWindow = (resizeMode & RESIZE_MODE_PRESERVE_WINDOW) != 0;
if (stackId != task.getStackId()) {
- mStackSupervisor.moveTaskToStackUncheckedLocked(task, stackId, ON_TOP,
- !FORCE_FOCUS, "resizeTask");
+ // Defer resume until the task is resized below
+ task.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE,
+ DEFER_RESUME, "resizeTask");
preserveWindow = false;
}
- task.resize(bounds, resizeMode, preserveWindow, false /* deferResume */);
+ // After reparenting (which only resizes the task to the stack bounds), resize the
+ // task to the actual bounds provided
+ task.resize(bounds, resizeMode, preserveWindow, !DEFER_RESUME);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -10198,14 +10203,16 @@ public class ActivityManagerService extends IActivityManager.Stub
throw new IllegalArgumentException(
"exitFreeformMode: No activity record matching token=" + token);
}
- final ActivityStack stack = r.getStackLocked(token);
+
+ final ActivityStack stack = r.getStack();
if (stack == null || stack.mStackId != FREEFORM_WORKSPACE_STACK_ID) {
throw new IllegalStateException(
"exitFreeformMode: You can only go fullscreen from freeform.");
}
+
if (DEBUG_STACK) Slog.d(TAG_STACK, "exitFreeformMode: " + r);
- mStackSupervisor.moveTaskToStackLocked(r.task.taskId, FULLSCREEN_WORKSPACE_STACK_ID,
- ON_TOP, !FORCE_FOCUS, "exitFreeformMode", ANIMATE);
+ r.task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT,
+ ANIMATE, !DEFER_RESUME, "exitFreeformMode");
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -10222,15 +10229,22 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
long ident = Binder.clearCallingIdentity();
try {
+ final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+ if (task == null) {
+ Slog.w(TAG, "moveTaskToStack: No task for id=" + taskId);
+ return;
+ }
+
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
+ " to stackId=" + stackId + " toTop=" + toTop);
if (stackId == DOCKED_STACK_ID) {
mWindowManager.setDockedStackCreateState(DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
null /* initialBounds */);
}
- boolean result = mStackSupervisor.moveTaskToStackLocked(taskId, stackId, toTop,
- !FORCE_FOCUS, "moveTaskToStack", ANIMATE);
- if (result && stackId == DOCKED_STACK_ID) {
+
+ final boolean successful = task.reparent(stackId, toTop,
+ REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME, "moveTaskToStack");
+ if (successful && stackId == DOCKED_STACK_ID) {
// If task moved to docked stack - show recents if needed.
mWindowManager.showRecentApps(false /* fromHome */);
}
@@ -10262,22 +10276,23 @@ public class ActivityManagerService extends IActivityManager.Stub
// TODO: App transition
mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_RELAUNCH, false);
- // Defer the resume so resume/pausing while moving stacks is dangerous.
- mStackSupervisor.moveTaskToStackLocked(topTask.taskId, DOCKED_STACK_ID,
- false /* toTop */, !FORCE_FOCUS, "swapDockedAndFullscreenStack",
- ANIMATE, true /* deferResume */);
+ // Defer the resume until we move all the docked tasks to the fullscreen stack below
+ topTask.reparent(DOCKED_STACK_ID, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE,
+ DEFER_RESUME, "swapDockedAndFullscreenStack - DOCKED_STACK");
final int size = tasks.size();
for (int i = 0; i < size; i++) {
final int id = tasks.get(i).taskId;
if (id == topTask.taskId) {
continue;
}
- mStackSupervisor.moveTaskToStackLocked(id,
- FULLSCREEN_WORKSPACE_STACK_ID, true /* toTop */, !FORCE_FOCUS,
- "swapDockedAndFullscreenStack", ANIMATE, true /* deferResume */);
+
+ // Defer the resume until after all the tasks have been moved
+ tasks.get(i).reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP,
+ REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, DEFER_RESUME,
+ "swapDockedAndFullscreenStack - FULLSCREEN_STACK");
}
- // Because we deferred the resume, to avoid conflicts with stack switches while
+ // Because we deferred the resume to avoid conflicts with stack switches while
// resuming, we need to do it after all the tasks are moved.
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mStackSupervisor.resumeFocusedStackTopActivityLocked();
@@ -10310,12 +10325,20 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
long ident = Binder.clearCallingIdentity();
try {
+ final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+ if (task == null) {
+ Slog.w(TAG, "moveTaskToDockedStack: No task for id=" + taskId);
+ return false;
+ }
+
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToDockedStack: moving task=" + taskId
+ " to createMode=" + createMode + " toTop=" + toTop);
mWindowManager.setDockedStackCreateState(createMode, initialBounds);
- final boolean moved = mStackSupervisor.moveTaskToStackLocked(
- taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS, "moveTaskToDockedStack",
- animate, DEFER_RESUME);
+
+ // Defer resuming until we move the home stack to the front below
+ final boolean moved = task.reparent(DOCKED_STACK_ID, toTop,
+ REPARENT_KEEP_STACK_AT_FRONT, animate, DEFER_RESUME,
+ "moveTaskToDockedStack");
if (moved) {
if (moveHomeStackFront) {
mStackSupervisor.moveHomeStackToFront("moveTaskToDockedStack");
@@ -10449,7 +10472,8 @@ public class ActivityManagerService extends IActivityManager.Stub
stack.positionChildAt(task, position);
} else {
// Reparent to new stack.
- task.reparent(stackId, position, "positionTaskInStack");
+ task.reparent(stackId, position, REPARENT_LEAVE_STACK_IN_PLACE,
+ !ANIMATE, !DEFER_RESUME, "positionTaskInStack");
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -12087,6 +12111,12 @@ public class ActivityManagerService extends IActivityManager.Stub
mRecentTasks.notifyTaskPersisterLocked(task, flush);
}
+ /** Notifies all listeners when the pinned stack animation starts. */
+ @Override
+ public void notifyPinnedStackAnimationStarted() {
+ mTaskChangeNotificationController.notifyPinnedStackAnimationStarted();
+ }
+
/** Notifies all listeners when the pinned stack animation ends. */
@Override
public void notifyPinnedStackAnimationEnded() {
@@ -18853,7 +18883,9 @@ public class ActivityManagerService extends IActivityManager.Stub
appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,
resultExtras, ordered, sticky, false, userId);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
- final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
+ final boolean replaced = replacePending
+ && (queue.replaceParallelBroadcastLocked(r) != null);
+ // Note: We assume resultTo is null for non-ordered broadcasts.
if (!replaced) {
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
@@ -18952,8 +18984,25 @@ public class ActivityManagerService extends IActivityManager.Stub
if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
"Enqueueing broadcast " + r.intent.getAction());
- boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
- if (!replaced) {
+ final BroadcastRecord oldRecord =
+ replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
+ if (oldRecord != null) {
+ // Replaced, fire the result-to receiver.
+ if (oldRecord.resultTo != null) {
+ final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
+ try {
+ oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
+ oldRecord.intent,
+ Activity.RESULT_CANCELED, null, null,
+ false, false, oldRecord.userId);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failure ["
+ + queue.mQueueName + "] sending broadcast result of "
+ + intent, e);
+
+ }
+ }
+ } else {
queue.enqueueOrderedBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
@@ -18970,8 +19019,7 @@ public class ActivityManagerService extends IActivityManager.Stub
return ActivityManager.BROADCAST_SUCCESS;
}
- final void addBroadcastStatLocked(String action, String srcPackage, int receiveCount,
- int skipCount, long dispatchTime) {
+ final void rotateBroadcastStatsIfNeededLocked() {
final long now = SystemClock.elapsedRealtime();
if (mCurBroadcastStats == null ||
(mCurBroadcastStats.mStartRealtime +(24*60*60*1000) < now)) {
@@ -18982,9 +19030,19 @@ public class ActivityManagerService extends IActivityManager.Stub
}
mCurBroadcastStats = new BroadcastStats();
}
+ }
+
+ final void addBroadcastStatLocked(String action, String srcPackage, int receiveCount,
+ int skipCount, long dispatchTime) {
+ rotateBroadcastStatsIfNeededLocked();
mCurBroadcastStats.addBroadcast(action, srcPackage, receiveCount, skipCount, dispatchTime);
}
+ final void addBackgroundCheckViolationLocked(String action, String targetPackage) {
+ rotateBroadcastStatsIfNeededLocked();
+ mCurBroadcastStats.addBackgroundCheckViolation(action, targetPackage);
+ }
+
final Intent verifyBroadcastLocked(Intent intent) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors() == true) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 10055c8d98f7..c79ed2af29aa 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -797,6 +797,15 @@ final class ActivityRecord implements AppWindowContainerListener {
+ " is already the parent of r=" + this);
}
+ // TODO: Ensure that we do not directly reparent activities across stacks, as that may leave
+ // the stacks in strange states. For now, we should use Task.reparent() to ensure that
+ // the stack is left in an OK state.
+ if (prevTask != null && newTask != null && prevTask.getStack() != newTask.getStack()) {
+ throw new IllegalArgumentException(reason + ": task=" + newTask
+ + " is in a different stack (" + newTask.getStackId() + ") than the parent of"
+ + " r=" + this + " (" + prevTask.getStackId() + ")");
+ }
+
// Must reparent first in window manager
mWindowContainerController.reparent(newTask.getWindowContainerController(), position);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 827a41e776d8..5d4bff97b1b1 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -5077,45 +5077,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
moveToFront(reason);
}
- /**
- * Moves the input activity from its current stack to this one.
- * NOTE: The current task of the activity isn't moved to this stack. Instead a new task is
- * created on this stack which the activity is added to.
- * */
- void moveActivityToStack(ActivityRecord r) {
- final ActivityStack prevStack = r.getStack();
- if (prevStack.mStackId == mStackId) {
- // You are already in the right stack silly...
- return;
- }
-
- final boolean wasFocused = mStackSupervisor.isFocusedStack(prevStack)
- && (mStackSupervisor.topRunningActivityLocked() == r);
- final boolean wasResumed = wasFocused && (prevStack.mResumedActivity == r);
- final boolean wasPaused = prevStack.mPausingActivity == r;
-
- // Create a new task for the activity to be parented in
- final TaskRecord task = createTaskRecord(
- mStackSupervisor.getNextTaskIdForUserLocked(r.userId),
- r.info, r.intent, null, null, true, r.mActivityType);
- // This is a new task, so reparenting it to position 0 will move it to the top
- r.reparent(task, 0 /* position */, "moveActivityToStack");
-
- // Notify the task actiivties if it was moved to/from a pinned stack
- mStackSupervisor.scheduleReportPictureInPictureModeChangedIfNeeded(task, prevStack);
-
- // Resume the activity if necessary after it has moved
- moveToFrontAndResumeStateIfNeeded(r, wasFocused, wasResumed, wasPaused,
- "moveActivityToStack");
- if (wasResumed) {
- prevStack.mResumedActivity = null;
- }
- if (wasPaused) {
- prevStack.mPausingActivity = null;
- prevStack.removeTimeoutsForActivityLocked(r);
- }
- }
-
public int getStackId() {
return mStackId;
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index d3ad0572d556..6e138a161e1c 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -89,6 +89,9 @@ import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
+import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
+import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
+import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS;
import static java.lang.Integer.MAX_VALUE;
@@ -1992,8 +1995,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
stackId = task.getLaunchStackId();
}
if (stackId != currentStack.mStackId) {
- currentStack = moveTaskToStackUncheckedLocked(task, stackId, ON_TOP,
- !FORCE_FOCUS, reason);
+ task.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
+ DEFER_RESUME, "findTaskToMoveToFrontLocked");
stackId = currentStack.mStackId;
// moveTaskToStackUncheckedLocked() should already placed the task on top,
// still need moveTaskToFrontLocked() below for any transition settings.
@@ -2278,6 +2281,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
if (onTop) {
for (int i = 0; i < size; i++) {
final TaskRecord task = tasks.get(i);
+ final boolean isTopTask = i == (size - 1);
if (fromStackId == PINNED_STACK_ID) {
// Update the return-to to reflect where the pinned stack task was moved
// from so that we retain the stack that was previously visible if the
@@ -2287,22 +2291,25 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
MetricsLogger.action(mService.mContext,
MetricsEvent.ACTION_PICTURE_IN_PICTURE_EXPANDED_TO_FULLSCREEN);
}
- moveTaskToStackLocked(tasks.get(i).taskId,
- FULLSCREEN_WORKSPACE_STACK_ID, onTop, onTop /*forceFocus*/,
- "moveTasksToFullscreenStack - onTop", ANIMATE, DEFER_RESUME);
+ // 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,
+ "moveTasksToFullscreenStack - onTop");
}
-
- ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
- resumeFocusedStackTopActivityLocked();
} else {
for (int i = 0; i < size; i++) {
final TaskRecord task = tasks.get(i);
- final int position = fullscreenStack != null ?
- Math.max(fullscreenStack.getAllTasks().size() - 1, 0) : 0;
+ final int position = fullscreenStack != null
+ ? 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,
- "moveTasksToFullscreenStack - NOT_onTop");
+ REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE,
+ DEFER_RESUME, "moveTasksToFullscreenStack - NOT_onTop");
}
}
+
+ ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
+ resumeFocusedStackTopActivityLocked();
} finally {
mAllowDockedStackResize = true;
mWindowManager.continueSurfaceLayout();
@@ -2445,14 +2452,16 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
? Math.max(0, fullscreenStack.getChildCount() - 1)
: fullscreenStack.getChildCount();
final TaskRecord task = tasks.get(i);
- task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, insertPosition, "removeStack");
+ // Defer resume until we remove all the tasks
+ task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, insertPosition,
+ REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE, DEFER_RESUME, "removeStack");
}
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
resumeFocusedStackTopActivityLocked();
} else {
// If there is no fullscreen stack, then create the stack and move all the tasks
// onto the stack
- moveTasksToFullscreenStackLocked(PINNED_STACK_ID, false /* onTop */);
+ moveTasksToFullscreenStackLocked(PINNED_STACK_ID, !ON_TOP);
}
} else {
for (int i = tasks.size() - 1; i >= 0; i--) {
@@ -2657,168 +2666,52 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
/**
- * Moves the specified task record to the input stack id.
- * WARNING: This method performs an unchecked/raw move of the task and
- * can leave the system in an unstable state if used incorrectly.
- * Use {@link #moveTaskToStackLocked} to perform safe task movement to a stack.
- * @param task Task to move.
- * @param stackId Id of stack to move task to.
- * @param toTop True if the task should be placed at the top of the stack.
- * @param forceFocus if focus should be moved to the new stack
- * @param reason Reason the task is been moved.
- * @return The stack the task was moved to.
+ * Returns the reparent target stack, creating the stack if necessary. This call also enforces
+ * the various checks on tasks that are going to be reparented from one stack to another.
*/
- ActivityStack moveTaskToStackUncheckedLocked(TaskRecord task, int stackId, boolean toTop,
- boolean forceFocus, String reason) {
-
- if (StackId.isMultiWindowStack(stackId) && !mService.mSupportsMultiWindow) {
- throw new IllegalStateException("moveTaskToStackUncheckedLocked: Device doesn't "
- + "support multi-window task=" + task + " to stackId=" + stackId);
- }
-
- final ActivityRecord r = task.topRunningActivityLocked();
+ ActivityStack getReparentTargetStack(TaskRecord task, int stackId, boolean toTop) {
final ActivityStack prevStack = task.getStack();
- final boolean wasFocused = isFocusedStack(prevStack) && (topRunningActivityLocked() == r);
- final boolean wasResumed = prevStack.mResumedActivity == r;
- final boolean wasPaused = prevStack.mPausingActivity == r;
- // In some cases the focused stack isn't the front stack. E.g. pinned stack.
- // Whenever we are moving the top activity from the front stack we want to make sure to move
- // the stack to the front.
- final boolean wasFront = isFrontStackOnDisplay(prevStack)
- && (prevStack.topRunningActivityLocked() == r);
-
- if (stackId == DOCKED_STACK_ID && !task.isResizeable()) {
- // We don't allow moving a unresizeable task to the docked stack since the docked
- // stack is used for split-screen mode and will cause things like the docked divider to
- // show up. We instead leave the task in its current stack or move it to the fullscreen
- // stack if it isn't currently in a stack.
- stackId = (prevStack != null) ? prevStack.mStackId : FULLSCREEN_WORKSPACE_STACK_ID;
- Slog.w(TAG, "Can not move unresizeable task=" + task
- + " to docked stack. Moving to stackId=" + stackId + " instead.");
- }
- // Temporarily disable resizeablility of task we are moving. We don't want it to be resized
- // if a docked stack is created below which will lead to the stack we are moving from and
- // its resizeable tasks being resized.
- task.mTemporarilyUnresizable = true;
- final ActivityStack stack = getStack(stackId, CREATE_IF_NEEDED, toTop);
- task.mTemporarilyUnresizable = false;
- task.reparent(stack.mStackId, toTop ? MAX_VALUE : 0, reason);
-
- // Reset the resumed activity on the previous stack
- if (wasResumed) {
- prevStack.mResumedActivity = null;
- }
- // Reset the paused activity on the previous stack
- if (wasPaused) {
- prevStack.mPausingActivity = null;
- prevStack.removeTimeoutsForActivityLocked(r);
- }
-
- // If the task had focus before (or we're requested to move focus),
- // move focus to the new stack by moving the stack to the front.
- stack.moveToFrontAndResumeStateIfNeeded(r, forceFocus || wasFocused || wasFront, wasResumed,
- wasPaused, reason);
-
- return stack;
- }
-
- boolean moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
- String reason, boolean animate) {
- return moveTaskToStackLocked(taskId, stackId, toTop, forceFocus, reason, animate,
- false /* deferResume */);
- }
-
- boolean moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
- String reason, boolean animate, boolean deferResume) {
- final TaskRecord task = anyTaskForIdLocked(taskId);
- if (task == null) {
- Slog.w(TAG, "moveTaskToStack: no task for id=" + taskId);
- return false;
+ // Check that we aren't reparenting to the same stack that the task is already in
+ if (prevStack != null && prevStack.mStackId == stackId) {
+ Slog.w(TAG, "Can not reparent to same stack, task=" + task
+ + " already in stackId=" + stackId);
+ return prevStack;
}
- final ActivityStack currentStack = task.getStack();
- if (currentStack != null && currentStack.mStackId == stackId) {
- // You are already in the right stack silly...
- Slog.i(TAG, "moveTaskToStack: taskId=" + taskId + " already in stackId=" + stackId);
- return true;
+ // Ensure that we aren't trying to move into a multi-window stack without multi-window
+ // support
+ if (StackId.isMultiWindowStack(stackId) && !mService.mSupportsMultiWindow) {
+ throw new IllegalArgumentException("Device doesn't support multi-window, can not"
+ + " reparent task=" + task + " to stackId=" + stackId);
}
+ // Ensure that we aren't trying to move into a freeform stack without freeform
+ // support
if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
- throw new IllegalArgumentException("moveTaskToStack:"
- + "Attempt to move task " + taskId + " to unsupported freeform stack");
+ throw new IllegalArgumentException("Device doesn't support freeform, can not reparent"
+ + " task=" + task);
}
- final ActivityRecord topActivity = task.getTopActivity();
- final int sourceStackId = task.getStackId();
- final boolean mightReplaceWindow =
- StackId.replaceWindowsOnTaskMove(sourceStackId, stackId) && topActivity != null;
- if (mightReplaceWindow) {
- // We are about to relaunch the activity because its configuration changed due to
- // being maximized, i.e. size change. The activity will first remove the old window
- // and then add a new one. This call will tell window manager about this, so it can
- // preserve the old window until the new one is drawn. This prevents having a gap
- // between the removal and addition, in which no window is visible. We also want the
- // entrance of the new window to be properly animated.
- // Note here we always set the replacing window first, as the flags might be needed
- // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
- mWindowManager.setWillReplaceWindow(topActivity.appToken, animate);
+ // We don't allow moving a unresizeable task to the docked stack since the docked stack is
+ // used for split-screen mode and will cause things like the docked divider to show up. We
+ // instead leave the task in its current stack or move it to the fullscreen stack if it
+ // isn't currently in a stack.
+ if (stackId == DOCKED_STACK_ID && !task.isResizeable()) {
+ stackId = (prevStack != null) ? prevStack.mStackId : FULLSCREEN_WORKSPACE_STACK_ID;
+ Slog.w(TAG, "Can not move unresizeable task=" + task + " to docked stack."
+ + " Moving to stackId=" + stackId + " instead.");
}
- mWindowManager.deferSurfaceLayout();
- final int preferredLaunchStackId = stackId;
- boolean kept = true;
+ // Temporarily disable resizeablility of the task as we don't want it to be resized if, for
+ // example, a docked stack is created which will lead to the stack we are moving from being
+ // resized and and its resizeable tasks being resized.
try {
- final ActivityStack stack = moveTaskToStackUncheckedLocked(
- task, stackId, toTop, forceFocus, reason + " moveTaskToStack");
- stackId = stack.mStackId;
-
- if (!animate) {
- stack.mNoAnimActivities.add(topActivity);
- }
-
- // We might trigger a configuration change. Save the current task bounds for freezing.
- // TODO: Should this call be moved inside the resize method in WM?
- stack.prepareFreezingTaskBounds();
-
- // Make sure the task has the appropriate bounds/size for the stack it is in.
- if (stackId == FULLSCREEN_WORKSPACE_STACK_ID
- && !Objects.equals(task.mBounds, stack.mBounds)) {
- kept = task.resize(stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
- deferResume);
- } else if (stackId == FREEFORM_WORKSPACE_STACK_ID) {
- Rect bounds = task.getLaunchBounds();
- if (bounds == null) {
- stack.layoutTaskInStack(task, null);
- bounds = task.mBounds;
- }
- kept = task.resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
- } else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) {
- kept = task.resize(stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
- deferResume);
- }
+ task.mTemporarilyUnresizable = true;
+ return getStack(stackId, CREATE_IF_NEEDED, toTop);
} finally {
- mWindowManager.continueSurfaceLayout();
+ task.mTemporarilyUnresizable = false;
}
-
- if (mightReplaceWindow) {
- // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
- // window), we need to clear the replace window settings. Otherwise, we schedule a
- // timeout to remove the old window if the replacing window is not coming in time.
- mWindowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
- }
-
- if (!deferResume) {
-
- // The task might have already been running and its visibility needs to be synchronized with
- // the visibility of the stack / windows.
- ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
- resumeFocusedStackTopActivityLocked();
- }
-
- handleNonResizableTaskIfNeeded(task, preferredLaunchStackId, stackId);
-
- return (preferredLaunchStackId == stackId);
}
boolean moveTopStackActivityToPinnedStackLocked(int stackId, Rect bounds) {
@@ -2849,8 +2742,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void moveActivityToPinnedStackLocked(ActivityRecord r, String reason, Rect bounds,
boolean moveHomeStackToFront) {
-
mWindowManager.deferSurfaceLayout();
+
// Need to make sure the pinned stack exist so we can resize it below...
final PinnedActivityStack stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
@@ -2882,12 +2775,26 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// was launched from home so home should be visible behind it.
moveHomeStackToFront(reason);
}
- moveTaskToStackLocked(
- task.taskId, PINNED_STACK_ID, ON_TOP, FORCE_FOCUS, reason, !ANIMATE);
+ // Defer resume until below
+ task.reparent(PINNED_STACK_ID, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
+ DEFER_RESUME, reason);
} else {
// There are multiple activities in the task and moving the top activity should
- // reveal/leave the other activities in their original task
- stack.moveActivityToStack(r);
+ // reveal/leave the other activities in their original task.
+
+ // Currently, we don't support reparenting activities across tasks in two different
+ // stacks, so instead, just create a new task in the same stack, reparent the
+ // activity into that task, and then reparent the whole task to the new stack. This
+ // ensures that all the necessary work to migrate states in the old and new stacks
+ // is also done.
+ final TaskRecord newTask = task.getStack().createTaskRecord(
+ getNextTaskIdForUserLocked(r.userId), r.info, r.intent, null, null, true,
+ r.mActivityType);
+ r.reparent(newTask, MAX_VALUE, "moveActivityToStack");
+
+ // Defer resume until below
+ newTask.reparent(PINNED_STACK_ID, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
+ DEFER_RESUME, reason);
}
// Reset the state that indicates it can enter PiP while pausing after we've moved it
@@ -4880,9 +4787,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
if (launchStackId != INVALID_STACK_ID) {
if (task.getStackId() != launchStackId) {
- moveTaskToStackLocked(
- taskId, launchStackId, ON_TOP, FORCE_FOCUS, "startActivityFromRecents",
- ANIMATE);
+ task.reparent(launchStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, ANIMATE,
+ DEFER_RESUME, "startActivityFromRecents");
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 857241afa0a8..b9ae4fd4f7b3 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -77,11 +77,16 @@ import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
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;
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;
@@ -1489,9 +1494,9 @@ 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.
- mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
- launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
- ANIMATE);
+ intentActivity.task.reparent(launchStack.mStackId, ON_TOP,
+ REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
+ "launchToSide");
} else {
// TODO: This should be reevaluated in MW v2.
// We choose to move task to front instead of launching it adjacent
@@ -1556,9 +1561,13 @@ class ActivityStarter {
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
// The caller has requested to completely replace any existing task with its new
// activity. Well that should not be too hard...
- intentActivity.task.performClearTaskLocked();
- intentActivity.task.setIntent(mStartActivity);
+ // Note: we must persist the {@link TaskRecord} first as intentActivity could be
+ // removed from calling performClearTaskLocked (For example, if it is being brought out
+ // of history or if it is finished immediately), thus disassociating the task.
mReuseTask = intentActivity.task;
+ mReuseTask.performClearTaskLocked();
+ mReuseTask.setIntent(mStartActivity);
+
// When we clear the task - focus will be adjusted, which will bring another task
// to top before we launch the activity we need. This will temporary swap their
// mTaskToReturnTo values and we don't want to overwrite them accidentally.
@@ -1706,8 +1715,8 @@ class ActivityStarter {
if (mTargetStack == null) {
mTargetStack = sourceStack;
} else if (mTargetStack != sourceStack) {
- mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
- ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
+ sourceTask.reparent(mTargetStack.mStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
+ !ANIMATE, DEFER_RESUME, "launchToSide");
}
final TaskRecord topTask = mTargetStack.topTask();
@@ -1773,9 +1782,9 @@ class ActivityStarter {
mInTask.updateOverrideConfiguration(mLaunchBounds);
int stackId = mInTask.getLaunchStackId();
if (stackId != mInTask.getStackId()) {
- final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(mInTask,
- stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
- stackId = stack.mStackId;
+ mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
+ DEFER_RESUME, "inTaskToFront");
+ stackId = mInTask.getStackId();
}
if (StackId.resizeStackWithLaunchBounds(stackId)) {
mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 68253c78c78c..c9d19cb31832 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -239,33 +239,37 @@ public final class BroadcastQueue {
}
}
- public final boolean replaceParallelBroadcastLocked(BroadcastRecord r) {
- final Intent intent = r.intent;
- for (int i = mParallelBroadcasts.size() - 1; i >= 0; i--) {
- final Intent curIntent = mParallelBroadcasts.get(i).intent;
- if (intent.filterEquals(curIntent)) {
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
- "***** DROPPING PARALLEL ["
- + mQueueName + "]: " + intent);
- mParallelBroadcasts.set(i, r);
- return true;
- }
- }
- return false;
+ /**
+ * Find the same intent from queued parallel broadcast, replace with a new one and return
+ * the old one.
+ */
+ public final BroadcastRecord replaceParallelBroadcastLocked(BroadcastRecord r) {
+ return replaceBroadcastLocked(mParallelBroadcasts, r, "PARALLEL");
}
- public final boolean replaceOrderedBroadcastLocked(BroadcastRecord r) {
+ /**
+ * Find the same intent from queued ordered broadcast, replace with a new one and return
+ * the old one.
+ */
+ public final BroadcastRecord replaceOrderedBroadcastLocked(BroadcastRecord r) {
+ return replaceBroadcastLocked(mOrderedBroadcasts, r, "ORDERED");
+ }
+
+ private BroadcastRecord replaceBroadcastLocked(ArrayList<BroadcastRecord> queue,
+ BroadcastRecord r, String typeForLogging) {
final Intent intent = r.intent;
- for (int i = mOrderedBroadcasts.size() - 1; i > 0; i--) {
- if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
- "***** DROPPING ORDERED ["
- + mQueueName + "]: " + intent);
- mOrderedBroadcasts.set(i, r);
- return true;
+ for (int i = queue.size() - 1; i > 0; i--) {
+ final BroadcastRecord old = queue.get(i);
+ if (old.userId == r.userId && intent.filterEquals(old.intent)) {
+ if (DEBUG_BROADCAST) {
+ Slog.v(TAG_BROADCAST, "***** DROPPING "
+ + typeForLogging + " [" + mQueueName + "]: " + intent);
+ }
+ queue.set(i, r);
+ return old;
}
}
- return false;
+ return null;
}
private final void processCurBroadcastLocked(BroadcastRecord r,
@@ -1191,6 +1195,8 @@ public final class BroadcastQueue {
&& r.intent.getPackage() == null
&& ((r.intent.getFlags()
& Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0))) {
+ mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
+ component.getPackageName());
Slog.w(TAG, "Background execution not allowed: receiving "
+ r.intent + " to "
+ component.flattenToShortString());
diff --git a/services/core/java/com/android/server/am/BroadcastStats.java b/services/core/java/com/android/server/am/BroadcastStats.java
index fdbaada49091..fd2458222a89 100644
--- a/services/core/java/com/android/server/am/BroadcastStats.java
+++ b/services/core/java/com/android/server/am/BroadcastStats.java
@@ -47,6 +47,7 @@ public final class BroadcastStats {
static final class ActionEntry {
final String mAction;
final ArrayMap<String, PackageEntry> mPackages = new ArrayMap<>();
+ final ArrayMap<String, ViolationEntry> mBackgroundCheckViolations = new ArrayMap<>();
int mReceiveCount;
int mSkipCount;
long mTotalDispatchTime;
@@ -61,6 +62,10 @@ public final class BroadcastStats {
int mSendCount;
}
+ static final class ViolationEntry {
+ int mCount;
+ }
+
public BroadcastStats() {
mStartRealtime = SystemClock.elapsedRealtime();
mStartUptime = SystemClock.uptimeMillis();
@@ -87,6 +92,20 @@ public final class BroadcastStats {
pe.mSendCount++;
}
+ public void addBackgroundCheckViolation(String action, String targetPackage) {
+ ActionEntry ae = mActions.get(action);
+ if (ae == null) {
+ ae = new ActionEntry(action);
+ mActions.put(action, ae);
+ }
+ ViolationEntry ve = ae.mBackgroundCheckViolations.get(targetPackage);
+ if (ve == null) {
+ ve = new ViolationEntry();
+ ae.mBackgroundCheckViolations.put(targetPackage, ve);
+ }
+ ve.mCount++;
+ }
+
public boolean dumpStats(PrintWriter pw, String prefix, String dumpPackage) {
boolean printedSomething = false;
ArrayList<ActionEntry> actions = new ArrayList<>(mActions.size());
@@ -123,6 +142,15 @@ public final class BroadcastStats {
pw.print(pe.mSendCount);
pw.println(" times");
}
+ for (int j=ae.mBackgroundCheckViolations.size()-1; j>=0; j--) {
+ pw.print(prefix);
+ pw.print(" Bg Check Violation ");
+ pw.print(ae.mBackgroundCheckViolations.keyAt(j));
+ pw.print(": ");
+ ViolationEntry ve = ae.mBackgroundCheckViolations.valueAt(j);
+ pw.print(ve.mCount);
+ pw.println(" times");
+ }
}
return printedSomething;
}
@@ -158,6 +186,14 @@ public final class BroadcastStats {
pw.print(pe.mSendCount);
pw.println();
}
+ for (int j=ae.mBackgroundCheckViolations.size()-1; j>=0; j--) {
+ pw.print("v,");
+ pw.print(ae.mBackgroundCheckViolations.keyAt(j));
+ ViolationEntry ve = ae.mBackgroundCheckViolations.valueAt(j);
+ pw.print(",");
+ pw.print(ve.mCount);
+ pw.println();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
index 9dfc7cd84f40..9a98bc6ec6f8 100644
--- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
@@ -46,6 +46,7 @@ class TaskChangeNotificationController {
static final int NOTIFY_TASK_REMOVAL_STARTED_LISTENERS = 13;
static final int NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG = 14;
static final int NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG = 15;
+ static final int NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG = 16;
// Delay in notifying task stack change listeners (in millis)
static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
@@ -100,6 +101,10 @@ class TaskChangeNotificationController {
l.onPinnedActivityRestartAttempt((String) m.obj);
};
+ private final TaskStackConsumer mNotifyPinnedStackAnimationStarted = (l, m) -> {
+ l.onPinnedStackAnimationStarted();
+ };
+
private final TaskStackConsumer mNotifyPinnedStackAnimationEnded = (l, m) -> {
l.onPinnedStackAnimationEnded();
};
@@ -166,6 +171,9 @@ class TaskChangeNotificationController {
case NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG:
forAllRemoteListeners(mNotifyPinnedActivityRestartAttempt, msg);
break;
+ case NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG:
+ forAllRemoteListeners(mNotifyPinnedStackAnimationStarted, msg);
+ break;
case NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG:
forAllRemoteListeners(mNotifyPinnedStackAnimationEnded, msg);
break;
@@ -276,6 +284,15 @@ class TaskChangeNotificationController {
msg.sendToTarget();
}
+ /** Notifies all listeners when the pinned stack animation starts. */
+ void notifyPinnedStackAnimationStarted() {
+ mHandler.removeMessages(NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG);
+ final Message msg =
+ mHandler.obtainMessage(NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG);
+ forAllLocalListeners(mNotifyPinnedStackAnimationStarted, msg);
+ msg.sendToTarget();
+ }
+
/** Notifies all listeners when the pinned stack animation ends. */
void notifyPinnedStackAnimationEnded() {
mHandler.removeMessages(NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG);
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 241042452fb1..3f33f41e03f6 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
@@ -54,6 +55,7 @@ import com.android.server.wm.AppWindowContainerController;
import com.android.server.wm.StackWindowController;
import com.android.server.wm.TaskWindowContainerController;
import com.android.server.wm.TaskWindowContainerListener;
+import com.android.server.wm.WindowManagerService;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -62,10 +64,13 @@ import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Objects;
import static android.app.ActivityManager.RESIZE_MODE_FORCED;
+import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
@@ -107,9 +112,10 @@ import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
-import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
+import static java.lang.Integer.MAX_VALUE;
+
final class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
@@ -160,6 +166,24 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
static final int INVALID_TASK_ID = -1;
private static final int INVALID_MIN_SIZE = -1;
+ /**
+ * The modes to control how the stack is moved to the front when calling
+ * {@link TaskRecord#reparent}.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ REPARENT_MOVE_STACK_TO_FRONT,
+ REPARENT_KEEP_STACK_AT_FRONT,
+ REPARENT_LEAVE_STACK_IN_PLACE
+ })
+ public @interface ReparentMoveStackMode {}
+ // Moves the stack to the front if it was not at the front
+ public static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
+ // Only moves the stack to the front if it was focused or front most already
+ public static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
+ // Do not move the stack as a part of reparenting
+ public static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
+
final int taskId; // Unique identifier for this task.
String affinity; // The affinity name for this task, or null; may change identity.
String rootAffinity; // Initial base affinity, or null; does not change from initial root.
@@ -537,36 +561,159 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
mWindowContainerController.getBounds(bounds);
}
- // TODO: Should we be doing all the stuff in ASS.moveTaskToStackLocked?
- void reparent(int stackId, int position, String reason) {
- mService.mWindowManager.deferSurfaceLayout();
+ /**
+ * Convenience method to reparent a task to the top or bottom position of the stack.
+ */
+ 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);
+ }
+
+ /**
+ * Reparents the task into a preferred stack, creating it if necessary.
+ *
+ * @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
+ * @param moveStackMode whether or not to move the stack to the front always, only if it was
+ * 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
+ * @param reason the caller of this reparenting
+ * @return
+ */
+ boolean reparent(int preferredStackId, int position, @ReparentMoveStackMode int moveStackMode,
+ boolean animate, boolean deferResume, String reason) {
+ final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
+ final WindowManagerService windowManager = mService.mWindowManager;
+ final ActivityStack sourceStack = getStack();
+ final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStackId,
+ position == MAX_VALUE);
+ if (toStack == sourceStack) {
+ return false;
+ }
+
+ final int sourceStackId = getStackId();
+ final int stackId = toStack.getStackId();
+ final ActivityRecord topActivity = getTopActivity();
+ final boolean mightReplaceWindow = StackId.replaceWindowsOnTaskMove(sourceStackId, stackId)
+ && topActivity != null;
+ if (mightReplaceWindow) {
+ // We are about to relaunch the activity because its configuration changed due to
+ // being maximized, i.e. size change. The activity will first remove the old window
+ // and then add a new one. This call will tell window manager about this, so it can
+ // preserve the old window until the new one is drawn. This prevents having a gap
+ // between the removal and addition, in which no window is visible. We also want the
+ // entrance of the new window to be properly animated.
+ // Note here we always set the replacing window first, as the flags might be needed
+ // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
+ windowManager.setWillReplaceWindow(topActivity.appToken, animate);
+ }
+
+ windowManager.deferSurfaceLayout();
+ boolean kept = true;
try {
- final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
- final ActivityStack newStack = supervisor.getStack(stackId,
- CREATE_IF_NEEDED, false /* toTop */);
+ final ActivityRecord r = topRunningActivityLocked();
+ final boolean wasFocused = supervisor.isFocusedStack(sourceStack)
+ && (topRunningActivityLocked() == r);
+ final boolean wasResumed = sourceStack.mResumedActivity == r;
+ final boolean wasPaused = sourceStack.mPausingActivity == r;
+
+ // In some cases the focused stack isn't the front stack. E.g. pinned stack.
+ // Whenever we are moving the top activity from the front stack we want to make sure to
+ // move the stack to the front.
+ final boolean wasFront = supervisor.isFrontStackOnDisplay(sourceStack)
+ && (sourceStack.topRunningActivityLocked() == r);
+
// Adjust the position for the new parent stack as needed.
- position = newStack.getAdjustedPositionForTask(this, position, null /* starting */);
+ position = toStack.getAdjustedPositionForTask(this, position, null /* starting */);
// Must reparent first in window manager to avoid a situation where AM can delete the
// we are coming from in WM before we reparent because it became empty.
- mWindowContainerController.reparent(newStack.getWindowContainerController(), position);
+ mWindowContainerController.reparent(toStack.getWindowContainerController(), position);
- final ActivityStack prevStack = mStack;
- prevStack.removeTask(this, reason, REMOVE_TASK_MODE_MOVING);
- newStack.addTask(this, position, reason);
+ // 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);
+ }
- supervisor.scheduleReportPictureInPictureModeChangedIfNeeded(this, prevStack);
+ // Move the task
+ sourceStack.removeTask(this, reason, REMOVE_TASK_MODE_MOVING);
+ toStack.addTask(this, position, reason);
+ // TODO: Ensure that this is actually necessary here
+ // Notify of picture-in-picture mode changes
+ supervisor.scheduleReportPictureInPictureModeChangedIfNeeded(this, sourceStack);
+
+ // TODO: Ensure that this is actually necessary here
+ // Notify the voice session if required
if (voiceSession != null) {
try {
voiceSession.taskStarted(intent, taskId);
} catch (RemoteException e) {
}
}
+
+ // If the task had focus before (or we're requested to move focus), move focus to the
+ // new stack by moving the stack to the front.
+ final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
+ || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
+ toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed, wasPaused,
+ reason);
+ if (!animate) {
+ toStack.mNoAnimActivities.add(topActivity);
+ }
+
+ // We might trigger a configuration change. Save the current task bounds for freezing.
+ // TODO: Should this call be moved inside the resize method in WM?
+ toStack.prepareFreezingTaskBounds();
+
+ // Make sure the task has the appropriate bounds/size for the stack it is in.
+ if (stackId == FULLSCREEN_WORKSPACE_STACK_ID
+ && !Objects.equals(mBounds, toStack.mBounds)) {
+ kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
+ deferResume);
+ } else if (stackId == FREEFORM_WORKSPACE_STACK_ID) {
+ Rect bounds = getLaunchBounds();
+ if (bounds == null) {
+ toStack.layoutTaskInStack(this, null);
+ bounds = mBounds;
+ }
+ kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
+ } else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) {
+ kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
+ deferResume);
+ }
} finally {
- mService.mWindowManager.continueSurfaceLayout();
+ windowManager.continueSurfaceLayout();
+ }
+
+ if (mightReplaceWindow) {
+ // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
+ // window), we need to clear the replace window settings. Otherwise, we schedule a
+ // timeout to remove the old window if the replacing window is not coming in time.
+ windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
}
+
+ if (!deferResume) {
+ // The task might have already been running and its visibility needs to be synchronized
+ // with the visibility of the stack / windows.
+ supervisor.ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
+ supervisor.resumeFocusedStackTopActivityLocked();
+ }
+
+ supervisor.handleNonResizableTaskIfNeeded(this, preferredStackId, stackId);
+
+ return (preferredStackId == stackId);
}
void cancelWindowTransition() {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 994f38d5a94a..647adbf960a5 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -84,8 +84,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
final boolean mVoiceInteraction;
- // TODO: Use getParent instead?
- private Task mTask;
/** @see WindowContainer#fillsParent() */
private boolean mFillsParent;
boolean layoutConfigChanges;
@@ -411,7 +409,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
}
boolean windowsAreFocusable() {
- return StackId.canReceiveKeys(mTask.mStack.mStackId) || mAlwaysFocusable;
+ return StackId.canReceiveKeys(getTask().mStack.mStackId) || mAlwaysFocusable;
}
AppWindowContainerController getController() {
@@ -467,7 +465,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
getController().removeStartingWindow();
}
- final TaskStack stack = mTask.mStack;
+ final TaskStack stack = getTask().mStack;
if (delayed && !isEmpty()) {
// set the token aside because it has an active animation to be finished
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
@@ -667,20 +665,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
}
Task getTask() {
- return mTask;
- }
-
- /**
- * Sets the associated task, cleaning up dependencies when unset.
- */
- void setTask(Task task) {
- // Note: the following code assumes that the previous task's stack is the same as the
- // new task's stack.
- if (!mReparenting && mTask != null && mTask.mStack != null) {
- mTask.mStack.mExitingAppTokens.remove(this);
- }
-
- mTask = task;
+ return (Task) getParent();
}
@Override
@@ -690,10 +675,15 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
// When the associated task is {@code null}, the {@link AppWindowToken} can no longer
// access visual elements like the {@link DisplayContent}. We must remove any associations
// such as animations.
- if (!mReparenting && mTask == null) {
- // It is possible we have been marked as a closing app earlier. We must remove ourselves
- // from this list so we do not participate in any future animations.
- mService.mClosingApps.remove(this);
+ if (!mReparenting) {
+ final Task task = getTask();
+ if (task == null) {
+ // It is possible we have been marked as a closing app earlier. We must remove ourselves
+ // from this list so we do not participate in any future animations.
+ mService.mClosingApps.remove(this);
+ } else if (task.mStack != null) {
+ task.mStack.mExitingAppTokens.remove(this);
+ }
}
}
@@ -795,16 +785,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
if (canFreezeBounds()) {
freezeBounds();
}
-
- // In the process of tearing down before relaunching, the app will
- // try and clean up it's child surfaces. We need to prevent this from
- // happening, so we sever the children, transfering their ownership
- // from the client it-self to the parent surface (owned by us).
- for (int i = mChildren.size() - 1; i >= 0; i--) {
- final WindowState w = mChildren.get(i);
- w.mWinAnimator.detachChildren();
- }
-
mPendingRelaunchCount++;
}
@@ -895,19 +875,20 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
}
void reparent(Task task, int position) {
- if (task == mTask) {
+ final Task currentTask = getTask();
+ if (task == currentTask) {
throw new IllegalArgumentException(
- "window token=" + this + " already child of task=" + mTask);
+ "window token=" + this + " already child of task=" + currentTask);
}
- if (mTask.mStack != task.mStack) {
+ if (currentTask.mStack != task.mStack) {
throw new IllegalArgumentException(
- "window token=" + this + " current task=" + mTask
+ "window token=" + this + " current task=" + currentTask
+ " belongs to a different stack than " + task);
}
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
- + " from task=" + mTask);
+ + " from task=" + currentTask);
final DisplayContent prevDisplayContent = getDisplayContent();
mReparenting = true;
@@ -927,9 +908,11 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
}
private boolean canFreezeBounds() {
+ final Task task = getTask();
+
// For freeform windows, we can't freeze the bounds at the moment because this would make
// the resizing unresponsive.
- return mTask != null && !mTask.inFreeformWorkspace();
+ return task != null && !task.inFreeformWorkspace();
}
/**
@@ -939,16 +922,17 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
* with a queue.
*/
private void freezeBounds() {
- mFrozenBounds.offer(new Rect(mTask.mPreparedFrozenBounds));
+ final Task task = getTask();
+ mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
- if (mTask.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
+ if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
// We didn't call prepareFreezingBounds on the task, so use the current value.
- mFrozenMergedConfig.offer(new Configuration(mTask.getConfiguration()));
+ mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
} else {
- mFrozenMergedConfig.offer(new Configuration(mTask.mPreparedFrozenMergedConfig));
+ mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
}
// Calling unset() to make it equal to Configuration.EMPTY.
- mTask.mPreparedFrozenMergedConfig.unset();
+ task.mPreparedFrozenMergedConfig.unset();
}
/**
@@ -1473,7 +1457,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
if (appToken != null) {
pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
}
- pw.print(prefix); pw.print("task="); pw.println(mTask);
+ pw.print(prefix); pw.print("task="); pw.println(getTask());
pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
pw.print(" mOrientation="); pw.println(mOrientation);
pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 07eb88dc9ad7..99c085ffe19f 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -133,7 +133,6 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
void addChild(AppWindowToken wtoken, int position) {
position = getAdjustedAddPosition(position);
super.addChild(wtoken, position);
- wtoken.setTask(this);
mDeferRemoval = false;
}
@@ -244,8 +243,6 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
removeIfPossible();
}
}
-
- token.setTask(null /*task*/);
}
void setSendingToBottom(boolean toBottom) {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 6cc2efb78526..7588b71dced7 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1439,6 +1439,14 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
mBoundsAnimating = true;
mBoundsAnimatingToFullscreen = toFullscreen;
}
+
+ if (mStackId == PINNED_STACK_ID) {
+ try {
+ mService.mActivityManager.notifyPinnedStackAnimationStarted();
+ } catch (RemoteException e) {
+ // I don't believe you...
+ }
+ }
}
@Override // AnimatesBounds
@@ -1448,6 +1456,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
mBoundsAnimationTarget.setEmpty();
mService.requestTraversal();
}
+
if (mStackId == PINNED_STACK_ID) {
try {
mService.mActivityManager.notifyPinnedStackAnimationEnded();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index eb3a2d15a855..e339329b56d4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2199,15 +2199,6 @@ public class WindowManagerService extends IWindowManager.Stub
if (mAccessibilityController != null && win.getDisplayId() == DEFAULT_DISPLAY) {
mAccessibilityController.onWindowTransitionLocked(win, transit);
}
-
- // When we start the exit animation we take the Surface from the client
- // so it will stop perturbing it. We need to likewise takeaway the SurfaceFlinger
- // side child surfaces, so they will remain preserved in their current state
- // (rather than be cleaned up immediately by the app code).
- SurfaceControl.openTransaction();
- winAnimator.detachChildren();
- SurfaceControl.closeTransaction();
-
return focusMayChange;
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 48060686a1de..6d572d78b9d7 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1532,13 +1532,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return changed;
}
- // Next up we will notify the client that it's visibility has changed.
- // We need to prevent it from destroying child surfaces until
- // the animation has finished.
- if (!visible && isVisibleNow()) {
- mWinAnimator.detachChildren();
- }
-
if (visible != isVisibleNow()) {
if (!runningAppAnimation) {
final AccessibilityController accessibilityController =
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 4b7133836db8..98598e1654dc 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -566,20 +566,6 @@ class WindowStateAnimator {
if (!mDestroyPreservedSurfaceUponRedraw) {
return;
}
- if (mSurfaceController != null) {
- if (mPendingDestroySurface != null) {
- // If we are preserving a surface but we aren't relaunching that means
- // we are just doing an in-place switch. In that case any SurfaceFlinger side
- // child layers need to be reparented to the new surface to make this
- // transparent to the app.
- if (mWin.mAppToken == null || mWin.mAppToken.isRelaunching() == false) {
- SurfaceControl.openTransaction();
- mPendingDestroySurface.reparentChildrenInTransaction(mSurfaceController);
- SurfaceControl.closeTransaction();
- }
- }
- }
-
destroyDeferredSurfaceLocked();
mDestroyPreservedSurfaceUponRedraw = false;
}
@@ -1979,10 +1965,4 @@ class WindowStateAnimator {
}
return mForceScaleUntilResize;
}
-
- void detachChildren() {
- if (mSurfaceController != null) {
- mSurfaceController.detachChildren();
- }
- }
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index f7d3343831bf..f8e74284fafd 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -135,20 +135,6 @@ class WindowSurfaceController {
}
}
- void reparentChildrenInTransaction(WindowSurfaceController other) {
- if (SHOW_TRANSACTIONS) Slog.i(TAG, "REPARENT from: " + this + " to: " + other);
- if ((mSurfaceControl != null) && (other.mSurfaceControl != null)) {
- mSurfaceControl.reparentChildren(other.getHandle());
- }
- }
-
- void detachChildren() {
- if (SHOW_TRANSACTIONS) Slog.i(TAG, "SEVER CHILDREN");
- if (mSurfaceControl != null) {
- mSurfaceControl.detachChildren();
- }
- }
-
void hideInTransaction(String reason) {
if (SHOW_TRANSACTIONS) logSurface("HIDE ( " + reason + " )", null);
mHiddenForOtherReasons = true;
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 440362d5c1b4..18c48b71270d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -158,21 +158,6 @@ class WindowTestsBase {
return win;
}
- /**
- * Creates a window for a task on a the given {@param stackId}.
- */
- private WindowState createStackWindow(int stackId, String name) {
- final StackWindowController stackController = createStackControllerOnStackOnDisplay(stackId,
- sDisplayContent);
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController(stackController);
- TestAppWindowToken appWinToken = new TestAppWindowToken(sDisplayContent);
- appWinToken.setTask(taskController.mContainer);
- final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, name);
- win.mAppToken = appWinToken;
- return win;
- }
-
/** Asserts that the first entry is greater than the second entry. */
void assertGreaterThan(int first, int second) throws Exception {
Assert.assertTrue("Excepted " + first + " to be greater than " + second, first > second);
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index ffc2de141860..ec3d75e354c7 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -76,7 +76,7 @@ TEST_F(XmlFlattenerTest, FlattenXmlWithNoCompiledAttributes) {
<View xmlns:test="http://com.test"
attr="hey">
<Layout test:hello="hi" />
- <Layout>Some text</Layout>
+ <Layout>Some text\\</Layout>
</View>)EOF");
android::ResXMLTree tree;
@@ -128,7 +128,7 @@ TEST_F(XmlFlattenerTest, FlattenXmlWithNoCompiledAttributes) {
ASSERT_EQ(tree.next(), android::ResXMLTree::TEXT);
const char16_t* text = tree.getText(&len);
- EXPECT_EQ(StringPiece16(text, len), u"Some text");
+ EXPECT_EQ(StringPiece16(text, len), u"Some text\\");
ASSERT_EQ(tree.next(), android::ResXMLTree::END_TAG);
ASSERT_EQ(tree.getElementNamespace(&len), nullptr);
diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h
index f8fa80ed7d66..7210d21f64ab 100644
--- a/tools/aapt2/util/Util.h
+++ b/tools/aapt2/util/Util.h
@@ -164,6 +164,7 @@ class StringBuilder {
StringBuilder& Append(const android::StringPiece& str);
const std::string& ToString() const;
const std::string& Error() const;
+ bool IsEmpty() const;
// When building StyledStrings, we need UTF-16 indices into the string,
// which is what the Java layer expects when dealing with java
@@ -185,6 +186,8 @@ inline const std::string& StringBuilder::ToString() const { return str_; }
inline const std::string& StringBuilder::Error() const { return error_; }
+inline bool StringBuilder::IsEmpty() const { return str_.empty(); }
+
inline size_t StringBuilder::Utf16Len() const { return utf16_len_; }
inline StringBuilder::operator bool() const { return error_.empty(); }
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index fab2f19fc0ac..d9ea1bcf3766 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -18,7 +18,6 @@
#include <expat.h>
-#include <cassert>
#include <memory>
#include <stack>
#include <string>
@@ -41,6 +40,8 @@ struct Stack {
std::unique_ptr<xml::Node> root;
std::stack<xml::Node*> node_stack;
std::string pending_comment;
+ std::unique_ptr<xml::Text> last_text_node;
+ util::StringBuilder pending_text;
};
/**
@@ -62,6 +63,19 @@ static void SplitName(const char* name, std::string* out_ns,
}
}
+static void FinishPendingText(Stack* stack) {
+ if (stack->last_text_node != nullptr) {
+ if (!stack->pending_text.IsEmpty()) {
+ stack->last_text_node->text = stack->pending_text.ToString();
+ stack->pending_text = {};
+ stack->node_stack.top()->AppendChild(std::move(stack->last_text_node));
+ } else {
+ // Drop an empty text node.
+ stack->last_text_node = nullptr;
+ }
+ }
+}
+
static void AddToStack(Stack* stack, XML_Parser parser,
std::unique_ptr<Node> node) {
node->line_number = XML_GetCurrentLineNumber(parser);
@@ -83,6 +97,7 @@ static void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix,
const char* uri) {
XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
+ FinishPendingText(stack);
std::unique_ptr<Namespace> ns = util::make_unique<Namespace>();
if (prefix) {
@@ -99,6 +114,7 @@ static void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix,
static void XMLCALL EndNamespaceHandler(void* user_data, const char* prefix) {
XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
+ FinishPendingText(stack);
CHECK(!stack->node_stack.empty());
stack->node_stack.pop();
@@ -113,6 +129,7 @@ static void XMLCALL StartElementHandler(void* user_data, const char* name,
const char** attrs) {
XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
+ FinishPendingText(stack);
std::unique_ptr<Element> el = util::make_unique<Element>();
SplitName(name, &el->namespace_uri, &el->name);
@@ -120,7 +137,9 @@ static void XMLCALL StartElementHandler(void* user_data, const char* name,
while (*attrs) {
Attribute attribute;
SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
- attribute.value = *attrs++;
+ util::StringBuilder builder;
+ builder.Append(*attrs++);
+ attribute.value = builder.ToString();
// Insert in sorted order.
auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(),
@@ -135,41 +154,38 @@ static void XMLCALL StartElementHandler(void* user_data, const char* name,
static void XMLCALL EndElementHandler(void* user_data, const char* name) {
XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
+ FinishPendingText(stack);
CHECK(!stack->node_stack.empty());
// stack->nodeStack.top()->comment = std::move(stack->pendingComment);
stack->node_stack.pop();
}
-static void XMLCALL CharacterDataHandler(void* user_data, const char* s,
- int len) {
+static void XMLCALL CharacterDataHandler(void* user_data, const char* s, int len) {
XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
- if (!s || len <= 0) {
+ const StringPiece str(s, len);
+ if (str.empty()) {
return;
}
// See if we can just append the text to a previous text node.
- if (!stack->node_stack.empty()) {
- Node* currentParent = stack->node_stack.top();
- if (!currentParent->children.empty()) {
- Node* last_child = currentParent->children.back().get();
- if (Text* text = NodeCast<Text>(last_child)) {
- text->text.append(s, len);
- return;
- }
- }
+ if (stack->last_text_node != nullptr) {
+ stack->pending_text.Append(str);
+ return;
}
- std::unique_ptr<Text> text = util::make_unique<Text>();
- text->text.assign(s, len);
- AddToStack(stack, parser, std::move(text));
+ stack->last_text_node = util::make_unique<Text>();
+ stack->last_text_node->line_number = XML_GetCurrentLineNumber(parser);
+ stack->last_text_node->column_number = XML_GetCurrentColumnNumber(parser);
+ stack->pending_text.Append(str);
}
static void XMLCALL CommentDataHandler(void* user_data, const char* comment) {
XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
+ FinishPendingText(stack);
if (!stack->pending_comment.empty()) {
stack->pending_comment += '\n';
diff --git a/tools/aapt2/xml/XmlDom_test.cpp b/tools/aapt2/xml/XmlDom_test.cpp
index a414afe92fc0..0fc3cec66666 100644
--- a/tools/aapt2/xml/XmlDom_test.cpp
+++ b/tools/aapt2/xml/XmlDom_test.cpp
@@ -49,4 +49,23 @@ TEST(XmlDomTest, Inflate) {
EXPECT_EQ(ns->namespace_prefix, "android");
}
+TEST(XmlDomTest, HandleEscapes) {
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
+ R"EOF(<shortcode pattern="\\d{5}">\\d{5}</shortcode>)EOF");
+
+ xml::Element* el = xml::FindRootElement(doc->root.get());
+ ASSERT_NE(nullptr, el);
+
+ xml::Attribute* attr = el->FindAttribute({}, "pattern");
+ ASSERT_NE(nullptr, attr);
+
+ EXPECT_EQ("\\d{5}", attr->value);
+
+ ASSERT_EQ(1u, el->children.size());
+
+ xml::Text* text = xml::NodeCast<xml::Text>(el->children[0].get());
+ ASSERT_NE(nullptr, text);
+ EXPECT_EQ("\\d{5}", text->text);
+}
+
} // namespace aapt