Loading core/java/android/os/image/DynamicSystemManager.java +11 −7 Original line number Diff line number Diff line Loading @@ -16,13 +16,16 @@ package android.os.image; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.content.Context; import android.gsi.AvbPublicKey; import android.gsi.GsiProgress; import android.gsi.IGsiService; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Pair; /** * The DynamicSystemManager offers a mechanism to use a new system image temporarily. After the Loading Loading @@ -138,17 +141,18 @@ public class DynamicSystemManager { * @param name The DSU partition name * @param size Size of the DSU image in bytes * @param readOnly True if the partition is read only, e.g. system. * @return {@code true} if the call succeeds. {@code false} either the device does not contain * enough space or a DynamicSystem is currently in use where the {@link #isInUse} would be * true. * @return {@code Integer} an IGsiService.INSTALL_* status code. {@link Session} an installation * session object if successful, otherwise {@code null}. */ @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public Session createPartition(String name, long size, boolean readOnly) { public @NonNull Pair<Integer, Session> createPartition( String name, long size, boolean readOnly) { try { if (mService.createPartition(name, size, readOnly)) { return new Session(); int status = mService.createPartition(name, size, readOnly); if (status == IGsiService.INSTALL_OK) { return new Pair<>(status, new Session()); } else { return null; return new Pair<>(status, null); } } catch (RemoteException e) { throw new RuntimeException(e.toString()); Loading core/java/android/os/image/IDynamicSystemService.aidl +2 −2 Original line number Diff line number Diff line Loading @@ -35,10 +35,10 @@ interface IDynamicSystemService * @param name The DSU partition name * @param size Size of the DSU image in bytes * @param readOnly True if this partition is readOnly * @return true if the call succeeds * @return IGsiService.INSTALL_* status code */ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") boolean createPartition(@utf8InCpp String name, long size, boolean readOnly); int createPartition(@utf8InCpp String name, long size, boolean readOnly); /** * Complete the current partition installation. Loading packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +7 −0 Original line number Diff line number Diff line Loading @@ -110,6 +110,7 @@ public class DynamicSystemInstallationService extends Service private static final int EVENT_DSU_PROGRESS_UPDATE = 120000; private static final int EVENT_DSU_INSTALL_COMPLETE = 120001; private static final int EVENT_DSU_INSTALL_FAILED = 120002; private static final int EVENT_DSU_INSTALL_INSUFFICIENT_SPACE = 120003; protected static void logEventProgressUpdate( String partitionName, Loading @@ -136,6 +137,10 @@ public class DynamicSystemInstallationService extends Service EventLog.writeEvent(EVENT_DSU_INSTALL_FAILED, cause); } protected static void logEventInsufficientSpace() { EventLog.writeEvent(EVENT_DSU_INSTALL_INSUFFICIENT_SPACE); } /* * IPC */ Loading Loading @@ -258,6 +263,8 @@ public class DynamicSystemInstallationService extends Service if (result == RESULT_CANCELLED) { logEventFailed("Dynamic System installation task is canceled by the user."); } else if (detail instanceof InstallationAsyncTask.InsufficientSpaceException) { logEventInsufficientSpace(); } else { logEventFailed("error: " + detail); } Loading packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags +1 −0 Original line number Diff line number Diff line Loading @@ -5,3 +5,4 @@ option java_package com.android.dynsystem 120000 dsu_progress_update (partition_name|3),(installed_bytes|2|5),(total_bytes|2|5),(partition_number|1|5),(total_partition_number|1|5),(total_progress_percentage|1|5) 120001 dsu_install_complete 120002 dsu_install_failed (cause|3) 120003 dsu_install_insufficient_space packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java +67 −26 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.dynsystem; import android.content.Context; import android.gsi.AvbPublicKey; import android.gsi.IGsiService; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; Loading @@ -27,6 +28,7 @@ import android.os.SystemProperties; import android.os.image.DynamicSystemManager; import android.service.persistentdata.PersistentDataBlockManager; import android.util.Log; import android.util.Pair; import android.util.Range; import android.webkit.URLUtil; Loading Loading @@ -106,8 +108,15 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { } } static class InsufficientSpaceException extends IOException { InsufficientSpaceException(String message) { super(message); } } /** UNSET means the installation is not completed */ static final int RESULT_UNSET = 0; static final int RESULT_OK = 1; static final int RESULT_CANCELLED = 2; static final int RESULT_ERROR_IO = 3; Loading Loading @@ -157,6 +166,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { private final boolean mIsNetworkUrl; private final boolean mIsDeviceBootloaderUnlocked; private final boolean mWantScratchPartition; private int mCreatePartitionStatus; private DynamicSystemManager.Session mInstallationSession; private KeyRevocationList mKeyRevocationList; Loading Loading @@ -435,12 +445,17 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { throws IOException { Log.d(TAG, "Creating writable partition: " + partitionName + ", size: " + partitionSize); Thread thread = new Thread() { mCreatePartitionStatus = 0; mInstallationSession = null; Thread thread = new Thread() { @Override public void run() { mInstallationSession = Pair<Integer, DynamicSystemManager.Session> result = mDynSystem.createPartition( partitionName, partitionSize, /* readOnly = */ false); mCreatePartitionStatus = result.first; mInstallationSession = result.second; } }; Loading Loading @@ -468,20 +483,29 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { } } if (prevInstalledSize != partitionSize) { publishProgress(partitionSize); } if (mInstallationSession == null) { if (mCreatePartitionStatus == IGsiService.INSTALL_ERROR_NO_SPACE || mCreatePartitionStatus == IGsiService.INSTALL_ERROR_FILE_SYSTEM_CLUTTERED) { throw new InsufficientSpaceException( "Failed to create " + partitionName + " partition: storage media has insufficient free space"); } else { throw new IOException( "Failed to start installation with requested size: " + partitionSize); } } // Reset installation session and verify that installation completes successfully. mInstallationSession = null; if (!mDynSystem.closePartition()) { throw new IOException("Failed to complete partition installation: " + partitionName); } // Ensure a 100% mark is published. if (prevInstalledSize != partitionSize) { publishProgress(partitionSize); } } private void installScratch() throws IOException { Loading Loading @@ -606,10 +630,19 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { throw new IOException("Cannot get raw size for " + partitionName); } Thread thread = new Thread(() -> { mInstallationSession = mDynSystem.createPartition(partitionName, partitionSize, true); }); mCreatePartitionStatus = 0; mInstallationSession = null; Thread thread = new Thread() { @Override public void run() { Pair<Integer, DynamicSystemManager.Session> result = mDynSystem.createPartition( partitionName, partitionSize, /* readOnly = */ true); mCreatePartitionStatus = result.first; mInstallationSession = result.second; } }; Log.d(TAG, "Start creating partition: " + partitionName); thread.start(); Loading @@ -627,9 +660,17 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { } if (mInstallationSession == null) { if (mCreatePartitionStatus == IGsiService.INSTALL_ERROR_NO_SPACE || mCreatePartitionStatus == IGsiService.INSTALL_ERROR_FILE_SYSTEM_CLUTTERED) { throw new InsufficientSpaceException( "Failed to create " + partitionName + " partition: storage media has insufficient free space"); } else { throw new IOException( "Failed to start installation with requested size: " + partitionSize); } } Log.d(TAG, "Start installing: " + partitionName); Loading Loading @@ -688,11 +729,6 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { installedSize += numBytesRead; } // Ensure a 100% mark is published. if (prevInstalledSize != partitionSize) { publishProgress(partitionSize); } AvbPublicKey avbPublicKey = new AvbPublicKey(); if (!mInstallationSession.getAvbPublicKey(avbPublicKey)) { imageValidationThrowOrWarning(new PublicKeyException("getAvbPublicKey() failed")); Loading @@ -708,6 +744,11 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { if (!mDynSystem.closePartition()) { throw new IOException("Failed to complete partition installation: " + partitionName); } // Ensure a 100% mark is published. if (prevInstalledSize != partitionSize) { publishProgress(partitionSize); } } private static String toHexString(byte[] bytes) { Loading Loading
core/java/android/os/image/DynamicSystemManager.java +11 −7 Original line number Diff line number Diff line Loading @@ -16,13 +16,16 @@ package android.os.image; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.content.Context; import android.gsi.AvbPublicKey; import android.gsi.GsiProgress; import android.gsi.IGsiService; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Pair; /** * The DynamicSystemManager offers a mechanism to use a new system image temporarily. After the Loading Loading @@ -138,17 +141,18 @@ public class DynamicSystemManager { * @param name The DSU partition name * @param size Size of the DSU image in bytes * @param readOnly True if the partition is read only, e.g. system. * @return {@code true} if the call succeeds. {@code false} either the device does not contain * enough space or a DynamicSystem is currently in use where the {@link #isInUse} would be * true. * @return {@code Integer} an IGsiService.INSTALL_* status code. {@link Session} an installation * session object if successful, otherwise {@code null}. */ @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public Session createPartition(String name, long size, boolean readOnly) { public @NonNull Pair<Integer, Session> createPartition( String name, long size, boolean readOnly) { try { if (mService.createPartition(name, size, readOnly)) { return new Session(); int status = mService.createPartition(name, size, readOnly); if (status == IGsiService.INSTALL_OK) { return new Pair<>(status, new Session()); } else { return null; return new Pair<>(status, null); } } catch (RemoteException e) { throw new RuntimeException(e.toString()); Loading
core/java/android/os/image/IDynamicSystemService.aidl +2 −2 Original line number Diff line number Diff line Loading @@ -35,10 +35,10 @@ interface IDynamicSystemService * @param name The DSU partition name * @param size Size of the DSU image in bytes * @param readOnly True if this partition is readOnly * @return true if the call succeeds * @return IGsiService.INSTALL_* status code */ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") boolean createPartition(@utf8InCpp String name, long size, boolean readOnly); int createPartition(@utf8InCpp String name, long size, boolean readOnly); /** * Complete the current partition installation. Loading
packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +7 −0 Original line number Diff line number Diff line Loading @@ -110,6 +110,7 @@ public class DynamicSystemInstallationService extends Service private static final int EVENT_DSU_PROGRESS_UPDATE = 120000; private static final int EVENT_DSU_INSTALL_COMPLETE = 120001; private static final int EVENT_DSU_INSTALL_FAILED = 120002; private static final int EVENT_DSU_INSTALL_INSUFFICIENT_SPACE = 120003; protected static void logEventProgressUpdate( String partitionName, Loading @@ -136,6 +137,10 @@ public class DynamicSystemInstallationService extends Service EventLog.writeEvent(EVENT_DSU_INSTALL_FAILED, cause); } protected static void logEventInsufficientSpace() { EventLog.writeEvent(EVENT_DSU_INSTALL_INSUFFICIENT_SPACE); } /* * IPC */ Loading Loading @@ -258,6 +263,8 @@ public class DynamicSystemInstallationService extends Service if (result == RESULT_CANCELLED) { logEventFailed("Dynamic System installation task is canceled by the user."); } else if (detail instanceof InstallationAsyncTask.InsufficientSpaceException) { logEventInsufficientSpace(); } else { logEventFailed("error: " + detail); } Loading
packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags +1 −0 Original line number Diff line number Diff line Loading @@ -5,3 +5,4 @@ option java_package com.android.dynsystem 120000 dsu_progress_update (partition_name|3),(installed_bytes|2|5),(total_bytes|2|5),(partition_number|1|5),(total_partition_number|1|5),(total_progress_percentage|1|5) 120001 dsu_install_complete 120002 dsu_install_failed (cause|3) 120003 dsu_install_insufficient_space
packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java +67 −26 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.dynsystem; import android.content.Context; import android.gsi.AvbPublicKey; import android.gsi.IGsiService; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; Loading @@ -27,6 +28,7 @@ import android.os.SystemProperties; import android.os.image.DynamicSystemManager; import android.service.persistentdata.PersistentDataBlockManager; import android.util.Log; import android.util.Pair; import android.util.Range; import android.webkit.URLUtil; Loading Loading @@ -106,8 +108,15 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { } } static class InsufficientSpaceException extends IOException { InsufficientSpaceException(String message) { super(message); } } /** UNSET means the installation is not completed */ static final int RESULT_UNSET = 0; static final int RESULT_OK = 1; static final int RESULT_CANCELLED = 2; static final int RESULT_ERROR_IO = 3; Loading Loading @@ -157,6 +166,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { private final boolean mIsNetworkUrl; private final boolean mIsDeviceBootloaderUnlocked; private final boolean mWantScratchPartition; private int mCreatePartitionStatus; private DynamicSystemManager.Session mInstallationSession; private KeyRevocationList mKeyRevocationList; Loading Loading @@ -435,12 +445,17 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { throws IOException { Log.d(TAG, "Creating writable partition: " + partitionName + ", size: " + partitionSize); Thread thread = new Thread() { mCreatePartitionStatus = 0; mInstallationSession = null; Thread thread = new Thread() { @Override public void run() { mInstallationSession = Pair<Integer, DynamicSystemManager.Session> result = mDynSystem.createPartition( partitionName, partitionSize, /* readOnly = */ false); mCreatePartitionStatus = result.first; mInstallationSession = result.second; } }; Loading Loading @@ -468,20 +483,29 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { } } if (prevInstalledSize != partitionSize) { publishProgress(partitionSize); } if (mInstallationSession == null) { if (mCreatePartitionStatus == IGsiService.INSTALL_ERROR_NO_SPACE || mCreatePartitionStatus == IGsiService.INSTALL_ERROR_FILE_SYSTEM_CLUTTERED) { throw new InsufficientSpaceException( "Failed to create " + partitionName + " partition: storage media has insufficient free space"); } else { throw new IOException( "Failed to start installation with requested size: " + partitionSize); } } // Reset installation session and verify that installation completes successfully. mInstallationSession = null; if (!mDynSystem.closePartition()) { throw new IOException("Failed to complete partition installation: " + partitionName); } // Ensure a 100% mark is published. if (prevInstalledSize != partitionSize) { publishProgress(partitionSize); } } private void installScratch() throws IOException { Loading Loading @@ -606,10 +630,19 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { throw new IOException("Cannot get raw size for " + partitionName); } Thread thread = new Thread(() -> { mInstallationSession = mDynSystem.createPartition(partitionName, partitionSize, true); }); mCreatePartitionStatus = 0; mInstallationSession = null; Thread thread = new Thread() { @Override public void run() { Pair<Integer, DynamicSystemManager.Session> result = mDynSystem.createPartition( partitionName, partitionSize, /* readOnly = */ true); mCreatePartitionStatus = result.first; mInstallationSession = result.second; } }; Log.d(TAG, "Start creating partition: " + partitionName); thread.start(); Loading @@ -627,9 +660,17 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { } if (mInstallationSession == null) { if (mCreatePartitionStatus == IGsiService.INSTALL_ERROR_NO_SPACE || mCreatePartitionStatus == IGsiService.INSTALL_ERROR_FILE_SYSTEM_CLUTTERED) { throw new InsufficientSpaceException( "Failed to create " + partitionName + " partition: storage media has insufficient free space"); } else { throw new IOException( "Failed to start installation with requested size: " + partitionSize); } } Log.d(TAG, "Start installing: " + partitionName); Loading Loading @@ -688,11 +729,6 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { installedSize += numBytesRead; } // Ensure a 100% mark is published. if (prevInstalledSize != partitionSize) { publishProgress(partitionSize); } AvbPublicKey avbPublicKey = new AvbPublicKey(); if (!mInstallationSession.getAvbPublicKey(avbPublicKey)) { imageValidationThrowOrWarning(new PublicKeyException("getAvbPublicKey() failed")); Loading @@ -708,6 +744,11 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { if (!mDynSystem.closePartition()) { throw new IOException("Failed to complete partition installation: " + partitionName); } // Ensure a 100% mark is published. if (prevInstalledSize != partitionSize) { publishProgress(partitionSize); } } private static String toHexString(byte[] bytes) { Loading