summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.txt7
-rw-r--r--api/system-current.txt49
-rw-r--r--api/test-current.txt7
-rw-r--r--core/java/android/app/ActivityManager.java22
-rw-r--r--core/java/android/app/backup/BackupManagerMonitor.java102
-rw-r--r--core/java/android/os/Build.java2
-rw-r--r--core/java/android/os/SystemProperties.java30
-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/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/FrameBuilder.cpp2
-rw-r--r--libs/hwui/LayerUpdateQueue.h3
-rw-r--r--libs/hwui/TreeInfo.h2
-rw-r--r--libs/hwui/pipeline/skia/RenderNodeDrawable.cpp4
-rw-r--r--libs/hwui/pipeline/skia/SkiaDisplayList.cpp12
-rw-r--r--libs/hwui/pipeline/skia/SkiaDisplayList.h26
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.cpp2
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp9
-rw-r--r--libs/hwui/tests/unit/LayerUpdateQueueTests.cpp8
-rw-r--r--libs/hwui/tests/unit/RenderNodeDrawableTests.cpp4
-rw-r--r--libs/hwui/tests/unit/RenderNodeTests.cpp2
-rw-r--r--libs/hwui/tests/unit/SkiaDisplayListTests.cpp25
-rw-r--r--media/java/android/media/MediaCodec.java48
-rw-r--r--media/java/android/media/MediaExtractor.java27
-rw-r--r--media/java/android/media/MediaPlayer.java58
-rw-r--r--media/java/android/media/tv/TvView.java4
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java98
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java (renamed from packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java)35
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java4
-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.java105
-rw-r--r--services/core/java/com/android/server/am/ActivityRecord.java54
-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.java21
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java48
-rw-r--r--services/core/java/com/android/server/am/TaskRecord.java175
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java4
-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/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--telephony/java/android/telephony/TelephonyManager.java5
-rw-r--r--wifi/java/android/net/wifi/hotspot2/pps/Credential.java17
68 files changed, 1708 insertions, 954 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..6e054fc5f240 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
@@ -36471,6 +36472,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 +36535,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..cfcc40a618cd 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 {
@@ -39394,6 +39433,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 +39496,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..478a3ed42444 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
@@ -36610,6 +36611,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 +36674,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/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/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/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 78820b537606..b525193c1b9c 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -35,7 +35,6 @@ public class SystemProperties {
private static final String TAG = "SystemProperties";
private static final boolean TRACK_KEY_ACCESS = false;
- public static final int PROP_NAME_MAX = 31;
public static final int PROP_VALUE_MAX = 91;
private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();
@@ -82,12 +81,8 @@ public class SystemProperties {
/**
* Get the value for the given key.
* @return an empty string if the key isn't found
- * @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static String get(String key) {
- if (key.length() > PROP_NAME_MAX) {
- throw newKeyTooLargeException(key);
- }
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get(key);
}
@@ -95,12 +90,8 @@ public class SystemProperties {
/**
* Get the value for the given key.
* @return if the key isn't found, return def if it isn't null, or an empty string otherwise
- * @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static String get(String key, String def) {
- if (key.length() > PROP_NAME_MAX) {
- throw newKeyTooLargeException(key);
- }
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get(key, def);
}
@@ -111,12 +102,8 @@ public class SystemProperties {
* @param def a default value to return
* @return the key parsed as an integer, or def if the key isn't found or
* cannot be parsed
- * @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static int getInt(String key, int def) {
- if (key.length() > PROP_NAME_MAX) {
- throw newKeyTooLargeException(key);
- }
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get_int(key, def);
}
@@ -127,12 +114,8 @@ public class SystemProperties {
* @param def a default value to return
* @return the key parsed as a long, or def if the key isn't found or
* cannot be parsed
- * @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static long getLong(String key, long def) {
- if (key.length() > PROP_NAME_MAX) {
- throw newKeyTooLargeException(key);
- }
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get_long(key, def);
}
@@ -148,25 +131,17 @@ public class SystemProperties {
* @param def a default value to return
* @return the key parsed as a boolean, or def if the key isn't found or is
* not able to be parsed as a boolean.
- * @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static boolean getBoolean(String key, boolean def) {
- if (key.length() > PROP_NAME_MAX) {
- throw newKeyTooLargeException(key);
- }
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get_boolean(key, def);
}
/**
* Set the value for the given key.
- * @throws IllegalArgumentException if the key exceeds 32 characters
* @throws IllegalArgumentException if the value exceeds 92 characters
*/
public static void set(String key, String val) {
- if (key.length() > PROP_NAME_MAX) {
- throw newKeyTooLargeException(key);
- }
if (val != null && val.length() > PROP_VALUE_MAX) {
throw newValueTooLargeException(key, val);
}
@@ -196,11 +171,6 @@ public class SystemProperties {
}
}
- private static IllegalArgumentException newKeyTooLargeException(String key) {
- return new IllegalArgumentException("system property key '" + key + "' is longer than "
- + PROP_NAME_MAX + " characters");
- }
-
private static IllegalArgumentException newValueTooLargeException(String key, String value) {
return new IllegalArgumentException("value of system property '" + key + "' is longer than "
+ PROP_VALUE_MAX + " characters: " + value);
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/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/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 35ff635930ab..1b57e290c198 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -78,7 +78,7 @@ void FrameBuilder::deferLayers(const LayerUpdateQueue& layers) {
// Render all layers to be updated, in order. Defer in reverse order, so that they'll be
// updated in the order they're passed in (mLayerBuilders are issued to Renderer in reverse)
for (int i = layers.entries().size() - 1; i >= 0; i--) {
- RenderNode* layerNode = layers.entries()[i].renderNode;
+ RenderNode* layerNode = layers.entries()[i].renderNode.get();
// only schedule repaint if node still on layer - possible it may have been
// removed during a dropped frame, but layers may still remain scheduled so
// as not to lose info on what portion is damaged
diff --git a/libs/hwui/LayerUpdateQueue.h b/libs/hwui/LayerUpdateQueue.h
index 5b1a8543dd0d..38f3596d70df 100644
--- a/libs/hwui/LayerUpdateQueue.h
+++ b/libs/hwui/LayerUpdateQueue.h
@@ -19,6 +19,7 @@
#include "Rect.h"
#include "utils/Macros.h"
+#include <utils/StrongPointer.h>
#include <vector>
#include <unordered_map>
@@ -35,7 +36,7 @@ public:
Entry(RenderNode* renderNode, const Rect& damage)
: renderNode(renderNode)
, damage(damage) {}
- RenderNode* renderNode;
+ sp<RenderNode> renderNode;
Rect damage;
};
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/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 117395bfc75c..39f11b8e6bfe 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -197,12 +197,12 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const {
if (needsLayer) {
canvas->saveLayer(bounds, &paint);
}
- canvas->drawDrawable(displayList->mDrawable.get());
+ displayList->draw(canvas);
if (needsLayer) {
canvas->restore();
}
} else {
- canvas->drawDrawable(displayList->mDrawable.get());
+ displayList->draw(canvas);
}
}
}
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index b4babcb9564e..496f7babd3cc 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -27,10 +27,6 @@ namespace android {
namespace uirenderer {
namespace skiapipeline {
-SkiaDisplayList::SkiaDisplayList(SkRect bounds) : mDrawable(SkLiteDL::New(bounds)) {
- SkASSERT(projectionReceiveIndex == -1);
-}
-
void SkiaDisplayList::syncContents() {
for (auto& functor : mChildFunctors) {
functor.syncFunctor();
@@ -41,7 +37,7 @@ void SkiaDisplayList::syncContents() {
}
bool SkiaDisplayList::reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) {
- reset(SkRect::MakeEmpty());
+ reset();
node->attachAvailableList(this);
return true;
}
@@ -102,10 +98,10 @@ bool SkiaDisplayList::prepareListAndChildren(TreeObserver& observer, TreeInfo& i
return isDirty;
}
-void SkiaDisplayList::reset(SkRect bounds) {
+void SkiaDisplayList::reset() {
mProjectionReceiver = nullptr;
- mDrawable->reset(bounds);
+ mDisplayList.reset();
mMutableImages.clear();
mVectorDrawables.clear();
@@ -119,7 +115,7 @@ void SkiaDisplayList::reset(SkRect bounds) {
void SkiaDisplayList::output(std::ostream& output, uint32_t level) {
DumpOpsCanvas canvas(output, level, *this);
- mDrawable->draw(&canvas, nullptr);
+ mDisplayList.draw(&canvas);
}
}; // namespace skiapipeline
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 439b999380ac..6ee5922f9cd6 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -22,7 +22,7 @@
#include <deque>
#include <SkLiteDL.h>
-#include <SkPictureRecorder.h>
+#include <SkLiteRecorder.h>
namespace android {
namespace uirenderer {
@@ -39,22 +39,22 @@ namespace skiapipeline {
*/
class SkiaDisplayList : public DisplayList {
public:
- SkiaDisplayList(SkRect bounds);
+ SkiaDisplayList() { SkASSERT(projectionReceiveIndex == -1); }
virtual ~SkiaDisplayList() {
/* Given that we are using a LinearStdAllocator to store some of the
* SkDrawable contents we must ensure that any other object that is
* holding a reference to those drawables is destroyed prior to their
* deletion.
*/
- mDrawable.reset();
+ mDisplayList.reset();
}
/**
* This resets the DisplayList so that it behaves as if the object were newly
- * constructed with the provided bounds. The reuse avoids any overhead
- * associated with destroying the SkLiteDL as well as the deques and vectors.
+ * constructed. The reuse avoids any overhead associated with destroying
+ * the SkLiteDL as well as the deques and vectors.
*/
- void reset(SkRect bounds);
+ void reset();
/**
* Use the linear allocator to create any SkDrawables needed by the display
@@ -72,7 +72,7 @@ public:
/**
* Returns true if the DisplayList does not have any recorded content
*/
- bool isEmpty() const override { return mDrawable->empty(); }
+ bool isEmpty() const override { return mDisplayList.empty(); }
/**
* Returns true if this list directly contains a GLFunctor drawing command.
@@ -126,18 +126,24 @@ public:
*/
inline bool containsProjectionReceiver() const { return mProjectionReceiver; }
+ void attachRecorder(SkLiteRecorder* recorder, const SkIRect& bounds) {
+ recorder->reset(&mDisplayList, bounds);
+ }
+
+ void draw(SkCanvas* canvas) { mDisplayList.draw(canvas); }
+
void output(std::ostream& output, uint32_t level) override;
/**
* We use std::deque here because (1) we need to iterate through these
- * elements and (2) mDrawable holds pointers to the elements, so they cannot
- * relocate.
+ * elements and (2) mDisplayList holds pointers to the elements, so they
+ * cannot relocate.
*/
std::deque<RenderNodeDrawable> mChildNodes;
std::deque<GLFunctorDrawable> mChildFunctors;
std::vector<SkImage*> mMutableImages;
std::vector<VectorDrawableRoot*> mVectorDrawables;
- sk_sp<SkLiteDL> mDrawable;
+ SkLiteDL mDisplayList;
//mProjectionReceiver points to a child node (stored in mChildNodes) that is as a projection
//receiver. It is set at record time and used at both prepare and draw tree traversals to
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 430d6bea70c1..11dc1f4c2161 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -80,7 +80,7 @@ void SkiaPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry
void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) {
// Render all layers that need to be updated, in order.
for (size_t i = 0; i < layers.entries().size(); i++) {
- RenderNode* layerNode = layers.entries()[i].renderNode;
+ RenderNode* layerNode = layers.entries()[i].renderNode.get();
// only schedule repaint if node still on layer - possible it may have been
// removed during a dropped frame, but layers may still remain scheduled so
// as not to lose info on what portion is damaged
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index dbe0296eae24..559d268b71f7 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -39,14 +39,11 @@ void SkiaRecordingCanvas::initDisplayList(uirenderer::RenderNode* renderNode, in
if (renderNode) {
mDisplayList = renderNode->detachAvailableList();
}
- SkRect bounds = SkRect::MakeWH(width, height);
- if (mDisplayList) {
- mDisplayList->reset(bounds);
- } else {
- mDisplayList.reset(new SkiaDisplayList(bounds));
+ if (!mDisplayList) {
+ mDisplayList.reset(new SkiaDisplayList());
}
- mRecorder.reset(mDisplayList->mDrawable.get());
+ mDisplayList->attachRecorder(&mRecorder, SkIRect::MakeWH(width, height));
SkiaCanvas::reset(&mRecorder);
}
diff --git a/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp b/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
index 4db1cb935902..91c7514e271e 100644
--- a/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
+++ b/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
@@ -48,11 +48,11 @@ TEST(LayerUpdateQueue, enqueueSimple) {
EXPECT_EQ(3u, queue.entries().size());
- EXPECT_EQ(a.get(), queue.entries()[0].renderNode);
+ EXPECT_EQ(a.get(), queue.entries()[0].renderNode.get());
EXPECT_EQ(Rect(25, 25, 75, 75), queue.entries()[0].damage);
- EXPECT_EQ(b.get(), queue.entries()[1].renderNode);
+ EXPECT_EQ(b.get(), queue.entries()[1].renderNode.get());
EXPECT_EQ(Rect(100, 100, 200, 200), queue.entries()[1].damage); // clipped to bounds
- EXPECT_EQ(c.get(), queue.entries()[2].renderNode);
+ EXPECT_EQ(c.get(), queue.entries()[2].renderNode.get());
EXPECT_EQ(Rect(0, 0, 1, 1), queue.entries()[2].damage); // rounded out
}
@@ -65,7 +65,7 @@ TEST(LayerUpdateQueue, enqueueUnion) {
EXPECT_EQ(1u, queue.entries().size());
- EXPECT_EQ(a.get(), queue.entries()[0].renderNode);
+ EXPECT_EQ(a.get(), queue.entries()[0].renderNode.get());
EXPECT_EQ(Rect(10, 10, 40, 40), queue.entries()[0].damage);
}
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index f21b3f7ec334..cbea501e3df3 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -44,9 +44,9 @@ TEST(RenderNodeDrawable, create) {
canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
});
- auto skLiteDL = SkLiteDL::New(SkRect::MakeWH(1, 1));
+ SkLiteDL skLiteDL;
SkLiteRecorder canvas;
- canvas.reset(skLiteDL.get());
+ canvas.reset(&skLiteDL, SkIRect::MakeWH(1, 1));
canvas.translate(100, 100);
RenderNodeDrawable drawable(rootNode.get(), &canvas);
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index 2925243d9f1c..eda4a9de49ae 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -331,7 +331,7 @@ RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
// damage rect.
EXPECT_TRUE(rootNode->getDisplayList()->hasVectorDrawables());
EXPECT_FALSE(info.layerUpdateQueue->entries().empty());
- EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode);
+ EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode.get());
EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
canvasContext->destroy();
}
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index be460bf6bdfe..dd8f4b4ec8cc 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -30,16 +30,13 @@ using namespace android::uirenderer::renderthread;
using namespace android::uirenderer::skiapipeline;
TEST(SkiaDisplayList, create) {
- SkRect bounds = SkRect::MakeWH(200, 200);
- SkiaDisplayList skiaDL(bounds);
+ SkiaDisplayList skiaDL;
ASSERT_TRUE(skiaDL.isEmpty());
ASSERT_FALSE(skiaDL.mProjectionReceiver);
- ASSERT_EQ(skiaDL.mDrawable->getBounds(), bounds);
}
TEST(SkiaDisplayList, reset) {
- SkRect bounds = SkRect::MakeWH(200, 200);
- SkiaDisplayList skiaDL(bounds);
+ SkiaDisplayList skiaDL;
SkCanvas dummyCanvas;
RenderNodeDrawable drawable(nullptr, &dummyCanvas);
@@ -47,10 +44,9 @@ TEST(SkiaDisplayList, reset) {
skiaDL.mChildFunctors.emplace_back(nullptr, nullptr, &dummyCanvas);
skiaDL.mMutableImages.push_back(nullptr);
skiaDL.mVectorDrawables.push_back(nullptr);
- skiaDL.mDrawable->drawAnnotation(bounds, "testAnnotation", nullptr);
+ skiaDL.mDisplayList.drawAnnotation(SkRect::MakeWH(200, 200), "testAnnotation", nullptr);
skiaDL.mProjectionReceiver = &drawable;
- ASSERT_EQ(skiaDL.mDrawable->getBounds(), bounds);
ASSERT_FALSE(skiaDL.mChildNodes.empty());
ASSERT_FALSE(skiaDL.mChildFunctors.empty());
ASSERT_FALSE(skiaDL.mMutableImages.empty());
@@ -58,10 +54,8 @@ TEST(SkiaDisplayList, reset) {
ASSERT_FALSE(skiaDL.isEmpty());
ASSERT_TRUE(skiaDL.mProjectionReceiver);
- bounds = SkRect::MakeWH(100, 100);
- skiaDL.reset(bounds);
+ skiaDL.reset();
- ASSERT_EQ(skiaDL.mDrawable->getBounds(), bounds);
ASSERT_TRUE(skiaDL.mChildNodes.empty());
ASSERT_TRUE(skiaDL.mChildFunctors.empty());
ASSERT_TRUE(skiaDL.mMutableImages.empty());
@@ -79,7 +73,7 @@ TEST(SkiaDisplayList, reuseDisplayList) {
ASSERT_EQ(availableList.get(), nullptr);
// attach a displayList for reuse
- SkiaDisplayList skiaDL(SkRect::MakeWH(200, 200));
+ SkiaDisplayList skiaDL;
ASSERT_TRUE(skiaDL.reuseDisplayList(renderNode.get(), nullptr));
// detach the list that you just attempted to reuse
@@ -93,13 +87,13 @@ TEST(SkiaDisplayList, reuseDisplayList) {
}
TEST(SkiaDisplayList, syncContexts) {
- SkRect bounds = SkRect::MakeWH(200, 200);
- SkiaDisplayList skiaDL(bounds);
+ SkiaDisplayList skiaDL;
SkCanvas dummyCanvas;
TestUtils::MockFunctor functor;
skiaDL.mChildFunctors.emplace_back(&functor, nullptr, &dummyCanvas);
+ SkRect bounds = SkRect::MakeWH(200, 200);
VectorDrawableRoot vectorDrawable(new VectorDrawable::Group());
vectorDrawable.mutateStagingProperties()->setBounds(bounds);
skiaDL.mVectorDrawables.push_back(&vectorDrawable);
@@ -127,7 +121,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren) {
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
- SkiaDisplayList skiaDL(SkRect::MakeWH(200, 200));
+ SkiaDisplayList skiaDL;
// prepare with a clean VD
VectorDrawableRoot cleanVD(new VectorDrawable::Group());
@@ -170,8 +164,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren) {
}
TEST(SkiaDisplayList, updateChildren) {
- SkRect bounds = SkRect::MakeWH(200, 200);
- SkiaDisplayList skiaDL(bounds);
+ SkiaDisplayList skiaDL;
sp<RenderNode> renderNode = new RenderNode();
SkCanvas dummyCanvas;
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 1ca96583112e..d26412789f39 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -3188,9 +3188,55 @@ final public class MediaCodec {
/**
* Returns Analytics/Metrics data about the current content being
*
- * @return a Bundle containint the set of attributes and values available
+ * @return a Bundle containing the set of attributes and values available
* for the media being handled by this instance of MediaCodec
*
+ * <table style="width: 0%">
+ * <thead>
+ * <tr>
+ * <th>Key</th>
+ * <th>Type</th>
+ * <th>Description</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>{@code "codec"}</td>
+ * <td>String</td>
+ * <td>Identifies the particular codec in use</td>
+ * </tr><tr>
+ * <td>{@code "mime"}</td>
+ * <td>String</td>
+ * <td>Mime type of the media being encoded/decoded</td>
+ * </tr><tr>
+ * <td>{@code "mode"}</td>
+ * <td>String</td>
+ * <td>"Audio" or "Video"</td>
+ * </tr><tr>
+ * <td>{@code "secure"}</td>
+ * <td>Integer</td>
+ * <td>Indicates whether the code is operating on secure content and
+ * may also use capabilities in android.media.MediaCrypto</td>
+ * </tr><tr>
+ * <td>{@code "height"}</td>
+ * <td>Integer</td>
+ * <td>Height (pixels); valid only when mode=video</td>
+ * </tr><tr>
+ * <td>{@code "width"}</td>
+ * <td>Integer</td>
+ * <td>Width (pixels); valid only when mode=video</td>
+ * </tr><tr>
+ * <td>{@code "rotation"}</td>
+ * <td>Integer</td>
+ * <td>rotation (degrees) to orient the video onto the target surface;
+ * valid only when mode=video. Note there may be additional
+ * rotations applied when the surface is mapped to the screen.</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * Additional fields specific to individual codecs will also appear in
+ * the return value.
*/
public native Bundle getMetrics();
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 01ae36ffccfe..b9e409d17748 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -656,6 +656,33 @@ final public class MediaExtractor {
* @return the set of keys and values available for the media being
* handled by this instance of MediaExtractor
*
+ * <table style="width: 0%">
+ * <thead>
+ * <tr>
+ * <th>Key</th>
+ * <th>Type</th>
+ * <th>Description</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>{@code "fmt"}</td>
+ * <td>String</td>
+ * <td>The container format (which determines the handler)</td>
+ * </tr><tr>
+ * <td>{@code "mime"}</td>
+ * <td>String</td>
+ * <td>Mime type of the container.</td>
+ * </tr><tr>
+ * <td>{@code "ntrk"}</td>
+ * <td>Integer</td>
+ * <td>Number of tracks in the container</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * Additional fields specific to individual codecs will also appear in
+ * the return value.
*/
public native Bundle getMetrics();
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index fb37f9f62d14..b85c91119384 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1498,6 +1498,64 @@ public class MediaPlayer extends PlayerBase
*
* @return the a map of attributes and values available for this video
* player or null if no metrics are available.
+ *
+ * <table style="width: 0%">
+ * <thead>
+ * <tr>
+ * <th>Key</th>
+ * <th>Type</th>
+ * <th>Description</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>{@code "video/codec"}</td>
+ * <td>String</td>
+ * <td>Identifies the video codec in use</td>
+ * </tr><tr>
+ * <td>{@code "video/mime"}</td>
+ * <td>String</td>
+ * <td>Mime type of the video being encoded/decoded</td>
+ * </tr><tr>
+ * <td>{@code "audio/codec"}</td>
+ * <td>String</td>
+ * <td>Identifies the audio codec in use</td>
+ * </tr><tr>
+ * <td>{@code "audio/mime"}</td>
+ * <td>String</td>
+ * <td>Mime type of the audio being encoded/decoded</td>
+ * </tr><tr>
+ * <td>{@code "ht"}</td>
+ * <td>Integer</td>
+ * <td>Height (pixels); valid only when mode=video</td>
+ * </tr><tr>
+ * <td>{@code "wid"}</td>
+ * <td>Integer</td>
+ * <td>Width (pixels); valid only when mode=video</td>
+ * </tr><tr>
+ * <td>{@code "frame"}</td>
+ * <td>Integer</td>
+ * <td>Number of decoded video frames sent to the display</td>
+ * </tr><tr>
+ * <td>{@code "dropped"}</td>
+ * <td>Integer</td>
+ * <td>Number of decoded video frames that were not sent to display.
+ * These frames were dropped by the player.</td>
+ * </tr><tr>
+ * <td>{@code "durationMs"}</td>
+ * <td>Integer</td>
+ * <td>The length of the media being played (in ms), e.g. "This video lasts for 30000 milliseconds". </td>
+ * </tr><tr>
+ * <td>{@code "playingMs"}</td>
+ * <td>Integer</td>
+ * <td>The time the media has been played (in ms). If you watch a
+ * 30 second twice through, this will report 60000 ms.</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * Additional fields specific to individual codecs will also appear in
+ * the return value.
*/
public native Bundle getMetrics();
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/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/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index f7bfc1e6d4fc..62aa4660bc56 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -23,16 +23,18 @@ import android.service.quicksettings.Tile;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.RelativeSizeSpan;
+import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.widget.Button;
import android.widget.Checkable;
import android.widget.ImageView;
+import android.widget.Switch;
import android.widget.TextView;
+
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.BatteryInfo;
import com.android.settingslib.graph.BatteryMeterDrawableBase;
@@ -43,9 +45,8 @@ import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.BatteryController;
-import java.text.NumberFormat;
-
-public class BatteryTile extends QSTile<QSTile.State> implements BatteryController.BatteryStateChangeCallback {
+public class BatterySaverTile extends QSTile<QSTile.BooleanState> implements
+ BatteryController.BatteryStateChangeCallback {
private final BatteryController mBatteryController;
private final BatteryDetail mBatteryDetail = new BatteryDetail();
@@ -56,19 +57,14 @@ public class BatteryTile extends QSTile<QSTile.State> implements BatteryControll
private boolean mDetailShown;
private boolean mPluggedIn;
- public BatteryTile(Host host) {
+ public BatterySaverTile(Host host) {
super(host);
mBatteryController = Dependency.get(BatteryController.class);
}
@Override
- public State newTileState() {
- return new QSTile.State();
- }
-
- @Override
- public DetailAdapter getDetailAdapter() {
- return mBatteryDetail;
+ public BooleanState newTileState() {
+ return new BooleanState();
}
@Override
@@ -109,22 +105,15 @@ public class BatteryTile extends QSTile<QSTile.State> implements BatteryControll
}
@Override
- protected void handleUpdateState(State state, Object arg) {
- int level = (arg != null) ? (Integer) arg : mLevel;
- String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
-
+ protected void handleUpdateState(BooleanState state, Object arg) {
state.state = mCharging ? Tile.STATE_UNAVAILABLE
: mPowerSave ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
state.icon = ResourceIcon.get(R.drawable.ic_qs_battery_saver);
state.label = mContext.getString(R.string.battery_detail_switch_title);
- state.contentDescription = mContext.getString(R.string.accessibility_quick_settings_battery,
- percentage) + "," +
- (mPowerSave ? mContext.getString(R.string.battery_saver_notification_title)
- : mCharging ? mContext.getString(R.string.expanded_header_battery_charging)
- : "")
- + "," + mContext.getString(R.string.accessibility_battery_details);
+ state.contentDescription = state.label;
+ state.value = mPowerSave;
state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
- = Button.class.getName();
+ = Switch.class.getName();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index a1022c4757a5..de002372c442 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -37,7 +37,7 @@ import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.external.TileLifecycleManager;
import com.android.systemui.qs.external.TileServices;
import com.android.systemui.qs.tiles.AirplaneModeTile;
-import com.android.systemui.qs.tiles.BatteryTile;
+import com.android.systemui.qs.tiles.BatterySaverTile;
import com.android.systemui.qs.tiles.BluetoothTile;
import com.android.systemui.qs.tiles.CastTile;
import com.android.systemui.qs.tiles.CellularTile;
@@ -273,7 +273,7 @@ public class QSTileHost implements QSTile.Host, Tunable {
else if (tileSpec.equals("cast")) return new CastTile(this);
else if (tileSpec.equals("hotspot")) return new HotspotTile(this);
else if (tileSpec.equals("user")) return new UserTile(this);
- else if (tileSpec.equals("battery")) return new BatteryTile(this);
+ else if (tileSpec.equals("battery")) return new BatterySaverTile(this);
else if (tileSpec.equals("saver")) return new DataSaverTile(this);
else if (tileSpec.equals("night")) return new NightDisplayTile(this);
else if (tileSpec.equals("nfc")) return new NfcTile(this);
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..e9e73cc20510 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);
@@ -18853,7 +18877,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 +18978,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();
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index fa7dd28eb856..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);
@@ -2019,12 +2028,6 @@ final class ActivityRecord implements AppWindowContainerListener {
// Okay we now are going to make this activity have the new config.
// But then we need to figure out how it needs to deal with that.
-
- // Find changes between last reported merged configuration and the current one. This is used
- // to decide whether to relaunch an activity or just report a configuration change.
- final int changes = getTaskConfigurationChanges(mTmpConfig1);
-
- // Update last reported values.
final Configuration newGlobalConfig = service.getGlobalConfiguration();
final Configuration newTaskMergedOverrideConfig = task.getMergedOverrideConfiguration();
mTmpConfig1.setTo(mLastReportedConfiguration);
@@ -2032,6 +2035,9 @@ final class ActivityRecord implements AppWindowContainerListener {
mLastReportedConfiguration.setTo(newGlobalConfig);
mLastReportedOverrideConfiguration.setTo(newTaskMergedOverrideConfig);
+ int taskChanges = getTaskConfigurationChanges(this, newTaskMergedOverrideConfig,
+ mTmpConfig2);
+ final int changes = mTmpConfig1.diff(newGlobalConfig) | taskChanges;
if (changes == 0 && !forceNewConfig) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Configuration no differences in " + this);
@@ -2046,7 +2052,8 @@ final class ActivityRecord implements AppWindowContainerListener {
}
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
- "Configuration changes for " + this + ", allChanges="
+ "Configuration changes for " + this + " ; taskChanges="
+ + Configuration.configurationDiffToString(taskChanges) + ", allChanges="
+ Configuration.configurationDiffToString(changes));
// If the activity isn't currently running, just leave the new configuration and it will
@@ -2144,27 +2151,40 @@ final class ActivityRecord implements AppWindowContainerListener {
return (changes&(~configChanged)) != 0;
}
- private int getTaskConfigurationChanges(Configuration newTaskConfig) {
+ private static int getTaskConfigurationChanges(ActivityRecord record, Configuration taskConfig,
+ Configuration oldTaskOverride) {
+ // If we went from full-screen to non-full-screen, make sure to use the correct
+ // configuration task diff, so the diff stays as small as possible.
+ if (Configuration.EMPTY.equals(oldTaskOverride)
+ && !Configuration.EMPTY.equals(taskConfig)) {
+ oldTaskOverride = record.task.extractOverrideConfig(record.mLastReportedConfiguration);
+ }
+
+ // Conversely, do the same when going the other direction.
+ if (Configuration.EMPTY.equals(taskConfig)
+ && !Configuration.EMPTY.equals(oldTaskOverride)) {
+ taskConfig = record.task.extractOverrideConfig(record.mLastReportedConfiguration);
+ }
+
// Determine what has changed. May be nothing, if this is a config that has come back from
// the app after going idle. In that case we just want to leave the official config object
// now in the activity and do nothing else.
- final Configuration oldTaskConfig = task.getConfiguration();
- int taskChanges = oldTaskConfig.diff(newTaskConfig, true /* skipUndefined */);
+ int taskChanges = oldTaskOverride.diff(taskConfig, true /* skipUndefined */);
// We don't want to use size changes if they don't cross boundaries that are important to
// the app.
if ((taskChanges & CONFIG_SCREEN_SIZE) != 0) {
- final boolean crosses = crossesHorizontalSizeThreshold(oldTaskConfig.screenWidthDp,
- newTaskConfig.screenWidthDp)
- || crossesVerticalSizeThreshold(oldTaskConfig.screenHeightDp,
- newTaskConfig.screenHeightDp);
+ final boolean crosses = record.crossesHorizontalSizeThreshold(
+ oldTaskOverride.screenWidthDp, taskConfig.screenWidthDp)
+ || record.crossesVerticalSizeThreshold(
+ oldTaskOverride.screenHeightDp, taskConfig.screenHeightDp);
if (!crosses) {
taskChanges &= ~CONFIG_SCREEN_SIZE;
}
}
if ((taskChanges & CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
- final int oldSmallest = oldTaskConfig.smallestScreenWidthDp;
- final int newSmallest = newTaskConfig.smallestScreenWidthDp;
- if (!crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
+ final int oldSmallest = oldTaskOverride.smallestScreenWidthDp;
+ final int newSmallest = taskConfig.smallestScreenWidthDp;
+ if (!record.crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
taskChanges &= ~CONFIG_SMALLEST_SCREEN_SIZE;
}
}
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 94656c4eb2e3..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
@@ -1710,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();
@@ -1777,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..75b5929b0c65 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,
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/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
index 9c9a6711c581..0634dac8de4e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
@@ -80,9 +80,7 @@ public class PackageManagerServiceCompilerMapping {
try {
// Check that the system property name is legal.
String sysPropName = getSystemPropertyName(reason);
- if (sysPropName == null ||
- sysPropName.isEmpty() ||
- sysPropName.length() > SystemProperties.PROP_NAME_MAX) {
+ if (sysPropName == null || sysPropName.isEmpty()) {
throw new IllegalStateException("Reason system property name \"" +
sysPropName +"\" for reason " + REASON_STRINGS[reason]);
}
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/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/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 6d465f713215..932c276de720 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -4041,9 +4041,8 @@ public class TelephonyManager {
}
}
- if (property.length() > SystemProperties.PROP_NAME_MAX
- || propVal.length() > SystemProperties.PROP_VALUE_MAX) {
- Rlog.d(TAG, "setTelephonyProperty: property to long phoneId=" + phoneId +
+ if (propVal.length() > SystemProperties.PROP_VALUE_MAX) {
+ Rlog.d(TAG, "setTelephonyProperty: property too long phoneId=" + phoneId +
" property=" + property + " value: " + value + " propVal=" + propVal);
return;
}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index 620759df8f1d..23888411c1b2 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -122,12 +122,22 @@ public final class Credential implements Parcelable {
private static final int MAX_PASSWORD_BYTES = 255;
/**
+ * Supported authentication methods.
+ * @hide
+ */
+ public static final String AUTH_METHOD_PAP = "PAP";
+ /** @hide */
+ public static final String AUTH_METHOD_MSCHAP = "MS-CHAP";
+ /** @hide */
+ public static final String AUTH_METHOD_MSCHAPV2 = "MS-CHAP-V2";
+
+ /**
* Supported Non-EAP inner methods. Refer to
* Credential/UsernamePassword/EAPMethod/InnerEAPType in Hotspot 2.0 Release 2 Technical
* Specification Section 9.1 for more info.
*/
- private static final Set<String> SUPPORTED_AUTH =
- new HashSet<String>(Arrays.asList("PAP", "CHAP", "MS-CHAP", "MS-CHAP-V2"));
+ private static final Set<String> SUPPORTED_AUTH = new HashSet<String>(
+ Arrays.asList(AUTH_METHOD_PAP, AUTH_METHOD_MSCHAP, AUTH_METHOD_MSCHAPV2));
/**
* Username of the credential.
@@ -348,8 +358,9 @@ public final class Credential implements Parcelable {
public static final class CertificateCredential implements Parcelable {
/**
* Supported certificate types.
+ * @hide
*/
- private static final String CERT_TYPE_X509V3 = "x509v3";
+ public static final String CERT_TYPE_X509V3 = "x509v3";
/**
* Certificate SHA-256 fingerprint length.