From c44ee158b9f92b6381c221b7539371b5f73011ba Mon Sep 17 00:00:00 2001 From: Howard Chen Date: Fri, 2 Aug 2019 17:54:49 +0800 Subject: [PATCH 1/2] Clean up usage on deprecated GSID methods change: Add a oneShot argument to setEnable remove: commit() and replace it with enableGsi rename: removeGsiInstall -> removeGsi rename: disableGsiInstall -> disableGsi Bug: 138969329 Test: adb shell am start-activity \ -n com.android.dynsystem/com.android.dynsystem.VerificationActivity \ -a android.os.image.action.START_INSTALL \ -d file:///storage/emulated/0/Download/system.raw.gz \ --el KEY_SYSTEM_SIZE $(du -b system.raw|cut -f1) \ --el KEY_USERDATA_SIZE 8589934592 Change-Id: I680013c8b1181599f0b858222bd92e31c5f085fd Merged-In: I680013c8b1181599f0b858222bd92e31c5f085fd --- .../android/os/image/DynamicSystemManager.java | 6 +++--- .../android/os/image/IDynamicSystemService.aidl | 10 +++------- .../DynamicSystemInstallationService.java | 2 +- .../com/android/server/DynamicSystemService.java | 15 ++++----------- 4 files changed, 11 insertions(+), 22 deletions(-) diff --git a/core/java/android/os/image/DynamicSystemManager.java b/core/java/android/os/image/DynamicSystemManager.java index cec19457dd07e..e4f88c52889fe 100644 --- a/core/java/android/os/image/DynamicSystemManager.java +++ b/core/java/android/os/image/DynamicSystemManager.java @@ -76,7 +76,7 @@ public class DynamicSystemManager { @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean commit() { try { - return mService.commit(); + return mService.setEnable(true, true); } catch (RemoteException e) { throw new RuntimeException(e.toString()); } @@ -188,9 +188,9 @@ public class DynamicSystemManager { * @return {@code true} if the call succeeds. {@code false} if there is no installed image. */ @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) - public boolean setEnable(boolean enable) { + public boolean setEnable(boolean enable, boolean oneShot) { try { - return mService.setEnable(enable); + return mService.setEnable(enable, oneShot); } catch (RemoteException e) { throw new RuntimeException(e.toString()); } diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl index a34daca86ce58..2f4ab2d2420de 100644 --- a/core/java/android/os/image/IDynamicSystemService.aidl +++ b/core/java/android/os/image/IDynamicSystemService.aidl @@ -72,9 +72,11 @@ interface IDynamicSystemService /** * Enable or disable DynamicSystem. * + * @param oneShot If true, the GSI will boot once and then disable itself. + * * @return true if the call succeeds */ - boolean setEnable(boolean enable); + boolean setEnable(boolean enable, boolean oneShot); /** * Write a chunk of the DynamicSystem system image @@ -83,10 +85,4 @@ interface IDynamicSystemService */ boolean write(in byte[] buf); - /** - * Finish write and make device to boot into the it after reboot. - * - * @return true if the call succeeds - */ - boolean commit(); } diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java index e731b45010a45..142078e1b77cc 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java @@ -291,7 +291,7 @@ public class DynamicSystemInstallationService extends Service if (mInstallTask != null && mInstallTask.getResult() == RESULT_OK) { enabled = mInstallTask.commit(); } else if (isDynamicSystemInstalled()) { - enabled = mDynSystem.setEnable(true); + enabled = mDynSystem.setEnable(true, true); } else { Log.e(TAG, "Trying to reboot to AOT while there is no complete installation"); return; diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java index 173d5b053309c..e53141229e91b 100644 --- a/services/core/java/com/android/server/DynamicSystemService.java +++ b/services/core/java/com/android/server/DynamicSystemService.java @@ -181,18 +181,16 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements @Override public boolean remove() throws RemoteException { - return getGsiService().removeGsiInstall(); + return getGsiService().removeGsi(); } @Override - public boolean setEnable(boolean enable) throws RemoteException { + public boolean setEnable(boolean enable, boolean oneShot) throws RemoteException { IGsiService gsiService = getGsiService(); if (enable) { - final int status = gsiService.getGsiBootStatus(); - final boolean singleBoot = (status == IGsiService.BOOT_STATUS_SINGLE_BOOT); - return gsiService.setGsiBootable(singleBoot) == 0; + return gsiService.enableGsi(oneShot) == 0; } else { - return gsiService.disableGsiInstall(); + return gsiService.disableGsi(); } } @@ -200,9 +198,4 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements public boolean write(byte[] buf) throws RemoteException { return getGsiService().commitGsiChunkFromMemory(buf); } - - @Override - public boolean commit() throws RemoteException { - return getGsiService().setGsiBootable(true) == 0; - } } From ae615b32cddb2b7c259bc552842991ac72f9a062 Mon Sep 17 00:00:00 2001 From: Howard Chen Date: Mon, 5 Aug 2019 16:56:12 +0800 Subject: [PATCH 2/2] Use Ashmem to reduce buffer copies Use android.os.MemoryFile to allocate Ashmem and use gsid.setAshmem and gsid.commitGsiChunkFromAshmem to submit data. Bug: 138976291 Test: adb shell am start-activity \ -n com.android.dynsystem/com.android.dynsystem.VerificationActivity \ -a android.os.image.action.START_INSTALL \ -d file:///storage/emulated/0/Download/system.raw.gz \ --el KEY_SYSTEM_SIZE $(du -b system.raw|cut -f1) \ --el KEY_USERDATA_SIZE 8589934592 Change-Id: I6df718a8cc3f4e5835c9d20d0bf5bf8bb0daee22 Merged-In: I6df718a8cc3f4e5835c9d20d0bf5bf8bb0daee22 --- .../os/image/DynamicSystemManager.java | 28 +++++++++++++++---- .../os/image/IDynamicSystemService.aidl | 16 +++++++++-- .../dynsystem/InstallationAsyncTask.java | 23 +++++++-------- .../android/server/DynamicSystemService.java | 18 ++++++++++-- 4 files changed, 62 insertions(+), 23 deletions(-) diff --git a/core/java/android/os/image/DynamicSystemManager.java b/core/java/android/os/image/DynamicSystemManager.java index e4f88c52889fe..77fd946f7ccbe 100644 --- a/core/java/android/os/image/DynamicSystemManager.java +++ b/core/java/android/os/image/DynamicSystemManager.java @@ -20,6 +20,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.content.Context; import android.gsi.GsiProgress; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; /** @@ -52,21 +53,38 @@ public class DynamicSystemManager { /** The DynamicSystemManager.Session represents a started session for the installation. */ public class Session { private Session() {} + /** - * Write a chunk of the DynamicSystem system image + * Set the file descriptor that points to a ashmem which will be used + * to fetch data during the submitFromAshmem. * - * @return {@code true} if the call succeeds. {@code false} if there is any native runtime - * error. + * @param ashmem fd that points to a ashmem + * @param size size of the ashmem file */ @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) - public boolean write(byte[] buf) { + public boolean setAshmem(ParcelFileDescriptor ashmem, long size) { try { - return mService.write(buf); + return mService.setAshmem(ashmem, size); } catch (RemoteException e) { throw new RuntimeException(e.toString()); } } + /** + * Submit bytes to the DSU partition from the ashmem previously set with + * setAshmem. + * + * @param size Number of bytes + * @return true on success, false otherwise. + */ + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) + public boolean submitFromAshmem(int size) { + try { + return mService.submitFromAshmem(size); + } catch (RemoteException e) { + throw new RuntimeException(e.toString()); + } + } /** * Finish write and make device to boot into the it after reboot. * diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl index 2f4ab2d2420de..a6de170b5ce5c 100644 --- a/core/java/android/os/image/IDynamicSystemService.aidl +++ b/core/java/android/os/image/IDynamicSystemService.aidl @@ -79,10 +79,20 @@ interface IDynamicSystemService boolean setEnable(boolean enable, boolean oneShot); /** - * Write a chunk of the DynamicSystem system image + * Set the file descriptor that points to a ashmem which will be used + * to fetch data during the submitFromAshmem. * - * @return true if the call succeeds + * @param fd fd that points to a ashmem + * @param size size of the ashmem file */ - boolean write(in byte[] buf); + boolean setAshmem(in ParcelFileDescriptor fd, long size); + /** + * Submit bytes to the DSU partition from the ashmem previously set with + * setAshmem. + * + * @param bytes number of bytes that can be read from stream. + * @return true on success, false otherwise. + */ + boolean submitFromAshmem(long bytes); } diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java index 077f7ecd3e46b..cf286bdbde968 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java @@ -20,6 +20,8 @@ import android.content.Context; import android.gsi.GsiProgress; import android.net.Uri; import android.os.AsyncTask; +import android.os.MemoryFile; +import android.os.ParcelFileDescriptor; import android.os.image.DynamicSystemManager; import android.util.Log; import android.webkit.URLUtil; @@ -28,11 +30,9 @@ import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; -import java.util.Arrays; import java.util.Locale; import java.util.zip.GZIPInputStream; - class InstallationAsyncTask extends AsyncTask { private static final String TAG = "InstallationAsyncTask"; @@ -125,28 +125,26 @@ class InstallationAsyncTask extends AsyncTask { Thread.sleep(10); } - if (mInstallationSession == null) { - throw new IOException("Failed to start installation with requested size: " - + (mSystemSize + mUserdataSize)); + throw new IOException( + "Failed to start installation with requested size: " + + (mSystemSize + mUserdataSize)); } installedSize = mUserdataSize; + MemoryFile memoryFile = new MemoryFile("dsu", READ_BUFFER_SIZE); byte[] bytes = new byte[READ_BUFFER_SIZE]; - + mInstallationSession.setAshmem( + new ParcelFileDescriptor(memoryFile.getFileDescriptor()), READ_BUFFER_SIZE); int numBytesRead; - Log.d(TAG, "Start installation loop"); while ((numBytesRead = mStream.read(bytes, 0, READ_BUFFER_SIZE)) != -1) { + memoryFile.writeBytes(bytes, 0, 0, numBytesRead); if (isCancelled()) { break; } - - byte[] writeBuffer = numBytesRead == READ_BUFFER_SIZE - ? bytes : Arrays.copyOf(bytes, numBytesRead); - - if (!mInstallationSession.write(writeBuffer)) { + if (!mInstallationSession.submitFromAshmem(numBytesRead)) { throw new IOException("Failed write() to DynamicSystem"); } @@ -157,7 +155,6 @@ class InstallationAsyncTask extends AsyncTask { reportedInstalledSize = installedSize; } } - return null; } catch (Exception e) { diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java index e53141229e91b..18009e1914823 100644 --- a/services/core/java/com/android/server/DynamicSystemService.java +++ b/services/core/java/com/android/server/DynamicSystemService.java @@ -25,6 +25,7 @@ import android.gsi.IGsid; import android.os.Environment; import android.os.IBinder; import android.os.IBinder.DeathRecipient; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; @@ -195,7 +196,20 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements } @Override - public boolean write(byte[] buf) throws RemoteException { - return getGsiService().commitGsiChunkFromMemory(buf); + public boolean setAshmem(ParcelFileDescriptor ashmem, long size) { + try { + return getGsiService().setGsiAshmem(ashmem, size); + } catch (RemoteException e) { + throw new RuntimeException(e.toString()); + } + } + + @Override + public boolean submitFromAshmem(long size) { + try { + return getGsiService().commitGsiChunkFromAshmem(size); + } catch (RemoteException e) { + throw new RuntimeException(e.toString()); + } } }