From c85dfa3da5e35a04f501bcd5f5b7f99ded8bfbf4 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Mon, 10 Apr 2023 14:30:46 +0800 Subject: [PATCH 1/4] DSU enhancement (1/N) * System image is not required This allows the client to install a new data partition without supplying new system images. This is handy to simulate the condition of factory reset. Bug: 277691885 Test: adb shell am start-activity \ -n com.android.dynsystem/com.android.dynsystem.VerificationActivity \ -a android.os.image.action.START_INSTALL \ --el KEY_USERDATA_SIZE 2147483648 Change-Id: I0580b9b608221f4a07d7f8456de0cdd2f300578b --- packages/DynamicSystemInstallationService/AndroidManifest.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/DynamicSystemInstallationService/AndroidManifest.xml b/packages/DynamicSystemInstallationService/AndroidManifest.xml index 1765348292220..cd404385d5a0c 100644 --- a/packages/DynamicSystemInstallationService/AndroidManifest.xml +++ b/packages/DynamicSystemInstallationService/AndroidManifest.xml @@ -39,6 +39,10 @@ + + + + Date: Mon, 10 Apr 2023 14:51:37 +0800 Subject: [PATCH 2/4] DSU enhancement (2/N) * Expose KEY_ENABLE_WHEN_COMPLETED This will streamline the UI flow where the device will reboot immediately when the installation is done. Bug: 277691885 Test: adb shell am start-activity \ -n com.android.dynsystem/com.android.dynsystem.VerificationActivity \ -a android.os.image.action.START_INSTALL \ --el KEY_USERDATA_SIZE 2147483648 \ --ez KEY_ENABLE_WHEN_COMPLETED true Change-Id: I63cfd66647ac0cfc312ef329d18aba89b93aa990 --- core/java/android/os/image/DynamicSystemClient.java | 6 ++++++ .../android/dynsystem/DynamicSystemInstallationService.java | 3 +-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java index 5aa4e27fc2f3d..01ae65c8ff286 100644 --- a/core/java/android/os/image/DynamicSystemClient.java +++ b/core/java/android/os/image/DynamicSystemClient.java @@ -217,6 +217,12 @@ public class DynamicSystemClient { */ public static final String KEY_USERDATA_SIZE = "KEY_USERDATA_SIZE"; + /** + * Intent key: Whether to enable DynamicSystem immediately after installation is done. + * Note this will reboot the device automatically. + * @hide + */ + public static final String KEY_ENABLE_WHEN_COMPLETED = "KEY_ENABLE_WHEN_COMPLETED"; private static class IncomingHandler extends Handler { private final WeakReference mWeakClient; diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java index 55626844594de..60653d3e25377 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java @@ -27,6 +27,7 @@ import static android.os.image.DynamicSystemClient.CAUSE_ERROR_IO; import static android.os.image.DynamicSystemClient.CAUSE_INSTALL_CANCELLED; import static android.os.image.DynamicSystemClient.CAUSE_INSTALL_COMPLETED; import static android.os.image.DynamicSystemClient.CAUSE_NOT_SPECIFIED; +import static android.os.image.DynamicSystemClient.KEY_ENABLE_WHEN_COMPLETED; import static android.os.image.DynamicSystemClient.STATUS_IN_PROGRESS; import static android.os.image.DynamicSystemClient.STATUS_IN_USE; import static android.os.image.DynamicSystemClient.STATUS_NOT_STARTED; @@ -77,8 +78,6 @@ public class DynamicSystemInstallationService extends Service private static final String TAG = "DynamicSystemInstallationService"; - // TODO (b/131866826): This is currently for test only. Will move this to System API. - static final String KEY_ENABLE_WHEN_COMPLETED = "KEY_ENABLE_WHEN_COMPLETED"; static final String KEY_DSU_SLOT = "KEY_DSU_SLOT"; static final String DEFAULT_DSU_SLOT = "dsu"; static final String KEY_PUBKEY = "KEY_PUBKEY"; From d4bf2448f64a32ae4a9d068c05d24be1ecb479f8 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Mon, 10 Apr 2023 15:10:02 +0800 Subject: [PATCH 3/4] DSU enhancement (3/N) * Expose KEY_ONE_SHOT This allows the device to stay in DynamicSystem mode across reboots until the user decides to exit DSU mode Bug: 277691885 Test: adb shell am start-activity \ -n com.android.dynsystem/com.android.dynsystem.VerificationActivity \ -a android.os.image.action.START_INSTALL \ --el KEY_USERDATA_SIZE 2147483648 \ --ez KEY_ENABLE_WHEN_COMPLETED true \ --ez KEY_ONE_SHOT false Change-Id: I8057ebb7af866f9da3ad7836615866642ff93ddb --- core/java/android/os/image/DynamicSystemClient.java | 7 +++++++ .../dynsystem/DynamicSystemInstallationService.java | 7 +++++-- .../src/com/android/dynsystem/InstallationAsyncTask.java | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java index 01ae65c8ff286..ffe633172c562 100644 --- a/core/java/android/os/image/DynamicSystemClient.java +++ b/core/java/android/os/image/DynamicSystemClient.java @@ -224,6 +224,13 @@ public class DynamicSystemClient { */ public static final String KEY_ENABLE_WHEN_COMPLETED = "KEY_ENABLE_WHEN_COMPLETED"; + /** + * Intent key: Whether to leave DynamicSystem on device reboot. + * False indicates a sticky mode where device stays in DynamicSystem across reboots. + * @hide + */ + public static final String KEY_ONE_SHOT = "KEY_ONE_SHOT"; + private static class IncomingHandler extends Handler { private final WeakReference mWeakClient; diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java index 60653d3e25377..be031ba332fe4 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java @@ -28,6 +28,7 @@ import static android.os.image.DynamicSystemClient.CAUSE_INSTALL_CANCELLED; import static android.os.image.DynamicSystemClient.CAUSE_INSTALL_COMPLETED; import static android.os.image.DynamicSystemClient.CAUSE_NOT_SPECIFIED; import static android.os.image.DynamicSystemClient.KEY_ENABLE_WHEN_COMPLETED; +import static android.os.image.DynamicSystemClient.KEY_ONE_SHOT; import static android.os.image.DynamicSystemClient.STATUS_IN_PROGRESS; import static android.os.image.DynamicSystemClient.STATUS_IN_USE; import static android.os.image.DynamicSystemClient.STATUS_NOT_STARTED; @@ -171,6 +172,7 @@ public class DynamicSystemInstallationService extends Service // This is for testing only now private boolean mEnableWhenCompleted; + private boolean mOneShot; private InstallationAsyncTask.Progress mInstallTaskProgress; private InstallationAsyncTask mInstallTask; @@ -317,6 +319,7 @@ public class DynamicSystemInstallationService extends Service long systemSize = intent.getLongExtra(DynamicSystemClient.KEY_SYSTEM_SIZE, 0); long userdataSize = intent.getLongExtra(DynamicSystemClient.KEY_USERDATA_SIZE, 0); mEnableWhenCompleted = intent.getBooleanExtra(KEY_ENABLE_WHEN_COMPLETED, false); + mOneShot = intent.getBooleanExtra(KEY_ONE_SHOT, true); String dsuSlot = intent.getStringExtra(KEY_DSU_SLOT); String publicKey = intent.getStringExtra(KEY_PUBKEY); @@ -383,9 +386,9 @@ public class DynamicSystemInstallationService extends Service boolean enabled = false; if (mInstallTask != null && mInstallTask.isCompleted()) { - enabled = mInstallTask.commit(); + enabled = mInstallTask.commit(mOneShot); } else if (isDynamicSystemInstalled()) { - enabled = mDynSystem.setEnable(true, true); + enabled = mDynSystem.setEnable(true, mOneShot); } else { Log.e(TAG, "Trying to reboot to AOT while there is no complete installation"); return; diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java index a41399fb0d0d1..42b620abe734e 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java @@ -803,7 +803,7 @@ class InstallationAsyncTask extends AsyncTask { return mIsCompleted; } - boolean commit() { - return mDynSystem.setEnable(true, true); + boolean commit(boolean oneShot) { + return mDynSystem.setEnable(true, oneShot); } } From e5dff82b537ab65f96f3db90d354ba15717ee20e Mon Sep 17 00:00:00 2001 From: JW Wang Date: Mon, 10 Apr 2023 15:34:59 +0800 Subject: [PATCH 4/4] DSU enhancement (4/N) * Support hiding notification This allows the client to provide customized UI to enter/exit DSU without using the notifications from the status bar. Bug: 277691885 Test: adb shell am start-service --user 0 \ -n com.android.dynsystem/com.android.dynsystem.DynamicSystemInstallationService \ -a android.os.image.action.HIDE_NOTIFICATION Change-Id: I3f51e6caf0d3b336a71b6154d644f89624cd9491 --- .../android/os/image/DynamicSystemClient.java | 7 +++++ .../DynamicSystemInstallationService.java | 26 ++++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java index ffe633172c562..d5b0ecc3f2185 100644 --- a/core/java/android/os/image/DynamicSystemClient.java +++ b/core/java/android/os/image/DynamicSystemClient.java @@ -202,6 +202,13 @@ public class DynamicSystemClient { public static final String ACTION_NOTIFY_IF_IN_USE = "android.os.image.action.NOTIFY_IF_IN_USE"; + /** + * Intent action: hide notifications about the status of {@code DynamicSystem}. + * @hide + */ + public static final String ACTION_HIDE_NOTIFICATION = + "android.os.image.action.HIDE_NOTIFICATION"; + /* * Intent Keys */ diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java index be031ba332fe4..5e42f705cf4ba 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java @@ -19,6 +19,7 @@ package com.android.dynsystem; import static android.os.AsyncTask.Status.FINISHED; import static android.os.AsyncTask.Status.PENDING; import static android.os.AsyncTask.Status.RUNNING; +import static android.os.image.DynamicSystemClient.ACTION_HIDE_NOTIFICATION; import static android.os.image.DynamicSystemClient.ACTION_NOTIFY_IF_IN_USE; import static android.os.image.DynamicSystemClient.ACTION_START_INSTALL; import static android.os.image.DynamicSystemClient.CAUSE_ERROR_EXCEPTION; @@ -173,6 +174,7 @@ public class DynamicSystemInstallationService extends Service // This is for testing only now private boolean mEnableWhenCompleted; private boolean mOneShot; + private boolean mHideNotification; private InstallationAsyncTask.Progress mInstallTaskProgress; private InstallationAsyncTask mInstallTask; @@ -230,6 +232,8 @@ public class DynamicSystemInstallationService extends Service executeRebootToNormalCommand(); } else if (ACTION_NOTIFY_IF_IN_USE.equals(action)) { executeNotifyIfInUseCommand(); + } else if (ACTION_HIDE_NOTIFICATION.equals(action)) { + executeHideNotificationCommand(); } return Service.START_NOT_STICKY; @@ -441,12 +445,16 @@ public class DynamicSystemInstallationService extends Service private void executeNotifyIfInUseCommand() { switch (getStatus()) { case STATUS_IN_USE: - startForeground(NOTIFICATION_ID, - buildNotification(STATUS_IN_USE, CAUSE_NOT_SPECIFIED)); + if (!mHideNotification) { + startForeground(NOTIFICATION_ID, + buildNotification(STATUS_IN_USE, CAUSE_NOT_SPECIFIED)); + } break; case STATUS_READY: - startForeground(NOTIFICATION_ID, - buildNotification(STATUS_READY, CAUSE_NOT_SPECIFIED)); + if (!mHideNotification) { + startForeground(NOTIFICATION_ID, + buildNotification(STATUS_READY, CAUSE_NOT_SPECIFIED)); + } break; case STATUS_IN_PROGRESS: break; @@ -456,6 +464,16 @@ public class DynamicSystemInstallationService extends Service } } + private void executeHideNotificationCommand() { + mHideNotification = true; + switch (getStatus()) { + case STATUS_IN_USE: + case STATUS_READY: + stopForeground(STOP_FOREGROUND_REMOVE); + break; + } + } + private void resetTaskAndStop() { resetTaskAndStop(/* removeNotification= */ false); }