Loading packages/DynamicSystemInstallationService/Android.bp +8 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,9 @@ android_app { defaults: ["platform_app_defaults"], srcs: ["src/**/*.java"], static_libs: [ "DynamicSystemInstallationService-logtags", ], resource_dirs: ["res"], certificate: "platform", Loading @@ -32,3 +35,8 @@ android_app { enabled: false, }, } java_library { name: "DynamicSystemInstallationService-logtags", srcs: ["src/**/*.logtags"], } packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +71 −25 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import android.os.RemoteException; import android.os.image.DynamicSystemClient; import android.os.image.DynamicSystemManager; import android.text.TextUtils; import android.util.EventLog; import android.util.Log; import android.widget.Toast; Loading Loading @@ -103,6 +104,36 @@ public class DynamicSystemInstallationService extends Service private static final String NOTIFICATION_CHANNEL_ID = "com.android.dynsystem"; private static final int NOTIFICATION_ID = 1; /* * Event log tags */ 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; protected static void logEventProgressUpdate( String partition, long installedSize, long partitionSize, int partitionNumber, int totalPartitionNumber) { EventLog.writeEvent( EVENT_DSU_PROGRESS_UPDATE, partition, installedSize, partitionSize, partitionNumber, totalPartitionNumber); } protected static void logEventComplete() { EventLog.writeEvent(EVENT_DSU_INSTALL_COMPLETE); } protected static void logEventFailed(String cause) { EventLog.writeEvent(EVENT_DSU_INSTALL_FAILED, cause); } /* * IPC */ Loading Loading @@ -132,15 +163,10 @@ public class DynamicSystemInstallationService extends Service private DynamicSystemManager mDynSystem; private NotificationManager mNM; private int mNumInstalledPartitions; private String mCurrentPartitionName; private long mCurrentPartitionSize; private long mCurrentPartitionInstalledSize; // This is for testing only now private boolean mEnableWhenCompleted; private InstallationAsyncTask.Progress mInstallTaskProgress; private InstallationAsyncTask mInstallTask; Loading Loading @@ -203,17 +229,21 @@ public class DynamicSystemInstallationService extends Service @Override public void onProgressUpdate(InstallationAsyncTask.Progress progress) { mCurrentPartitionName = progress.partitionName; mCurrentPartitionSize = progress.partitionSize; mCurrentPartitionInstalledSize = progress.installedSize; mNumInstalledPartitions = progress.numInstalledPartitions; logEventProgressUpdate( progress.partitionName, progress.installedSize, progress.partitionSize, progress.partitionNumber, progress.totalPartitionNumber); mInstallTaskProgress = progress; postStatus(STATUS_IN_PROGRESS, CAUSE_NOT_SPECIFIED, null); } @Override public void onResult(int result, Throwable detail) { if (result == RESULT_OK) { logEventComplete(); postStatus(STATUS_READY, CAUSE_INSTALL_COMPLETED, null); // For testing: enable DSU and restart the device when install completed Loading @@ -223,6 +253,12 @@ public class DynamicSystemInstallationService extends Service return; } if (result == RESULT_CANCELLED) { logEventFailed("Dynamic System installation task is canceled by the user."); } else { logEventFailed("error: " + detail); } boolean removeNotification = false; switch (result) { case RESULT_CANCELLED: Loading Loading @@ -251,16 +287,20 @@ public class DynamicSystemInstallationService extends Service private void executeInstallCommand(Intent intent) { if (!verifyRequest(intent)) { Log.e(TAG, "Verification failed. Did you use VerificationActivity?"); logEventFailed("VerificationActivity"); return; } if (mInstallTask != null) { Log.e(TAG, "There is already an installation task running"); logEventFailed("There is already an ongoing installation task."); return; } if (isInDynamicSystem()) { Log.e(TAG, "We are already running in DynamicSystem"); logEventFailed( "Cannot start a Dynamic System installation task within a Dynamic System."); return; } Loading Loading @@ -445,19 +485,22 @@ public class DynamicSystemInstallationService extends Service case STATUS_IN_PROGRESS: builder.setContentText(getString(R.string.notification_install_inprogress)); if (mInstallTaskProgress != null) { int max = 1024; int progress = 0; int currentMax = max >> (mNumInstalledPartitions + 1); int currentMax = max >> mInstallTaskProgress.partitionNumber; progress = max - currentMax * 2; long currentProgress = (mCurrentPartitionInstalledSize >> 20) * currentMax / Math.max(mCurrentPartitionSize >> 20, 1); long currentProgress = (mInstallTaskProgress.installedSize >> 20) * currentMax / Math.max(mInstallTaskProgress.partitionSize >> 20, 1); progress += (int) currentProgress; builder.setProgress(max, progress, false); } builder.addAction(new Notification.Action.Builder( null, getString(R.string.notification_action_cancel), createPendingIntent(ACTION_CANCEL_INSTALL)).build()); Loading Loading @@ -563,13 +606,13 @@ public class DynamicSystemInstallationService extends Service StringBuilder msg = new StringBuilder(); msg.append("status: " + statusString + ", cause: " + causeString); if (status == STATUS_IN_PROGRESS) { if (status == STATUS_IN_PROGRESS && mInstallTaskProgress != null) { msg.append( String.format( ", partition name: %s, progress: %d/%d", mCurrentPartitionName, mCurrentPartitionInstalledSize, mCurrentPartitionSize)); mInstallTaskProgress.partitionName, mInstallTaskProgress.installedSize, mInstallTaskProgress.partitionSize)); } if (detail != null) { msg.append(", detail: " + detail); Loading @@ -594,7 +637,10 @@ public class DynamicSystemInstallationService extends Service Bundle bundle = new Bundle(); // TODO: send more info to the clients bundle.putLong(DynamicSystemClient.KEY_INSTALLED_SIZE, mCurrentPartitionInstalledSize); if (mInstallTaskProgress != null) { bundle.putLong( DynamicSystemClient.KEY_INSTALLED_SIZE, mInstallTaskProgress.installedSize); } if (detail != null) { bundle.putSerializable(DynamicSystemClient.KEY_EXCEPTION_DETAIL, Loading packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags 0 → 100644 +7 −0 Original line number Diff line number Diff line # See system/logging/logcat/event.logtags for a description of the format of this file. option java_package com.android.dynsystem 120000 dsu_progress_update (partition|3),(installed_size|2|5),(partition_size|2|5),(partition_number|1|5),(total_partition_number|1|5) 120001 dsu_install_complete 120002 dsu_install_failed (cause|3) packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java +90 −37 Original line number Diff line number Diff line Loading @@ -44,7 +44,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Progress, Throwable> { class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { private static final String TAG = "InstallationAsyncTask"; Loading Loading @@ -106,14 +106,22 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog static class Progress { public final String partitionName; public final long installedSize; public final long partitionSize; public final int numInstalledPartitions; public long installedSize; Progress(String partitionName, long partitionSize, int numInstalledPartitions) { public final int partitionNumber; public final int totalPartitionNumber; Progress( String partitionName, long installedSize, long partitionSize, int partitionNumber, int totalPartitionNumber) { this.partitionName = partitionName; this.installedSize = installedSize; this.partitionSize = partitionSize; this.numInstalledPartitions = numInstalledPartitions; this.partitionNumber = partitionNumber; this.totalPartitionNumber = totalPartitionNumber; } } Loading @@ -139,7 +147,10 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog private boolean mIsZip; private boolean mIsCompleted; private int mNumInstalledPartitions; private String mPartitionName; private long mPartitionSize; private int mPartitionNumber; private int mTotalPartitionNumber; private InputStream mStream; private ZipFile mZipFile; Loading Loading @@ -175,11 +186,15 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog protected Throwable doInBackground(String... voids) { Log.d(TAG, "Start doInBackground(), URL: " + mUrl); final boolean wantScratchPartition = Build.IS_DEBUGGABLE; try { // call DynamicSystemManager to cleanup stuff mDynSystem.remove(); verifyAndPrepare(); if (wantScratchPartition) { ++mTotalPartitionNumber; } mDynSystem.startInstallation(mDsuSlot); Loading @@ -198,7 +213,7 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog return null; } if (Build.IS_DEBUGGABLE) { if (wantScratchPartition) { // If host is debuggable, then install a scratch partition so that we can do // adb remount in the guest system. try { Loading Loading @@ -262,9 +277,14 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } @Override protected void onProgressUpdate(Progress... values) { Progress progress = values[0]; mListener.onProgressUpdate(progress); protected void onProgressUpdate(Long... installedSize) { mListener.onProgressUpdate( new Progress( mPartitionName, installedSize[0], mPartitionSize, mPartitionNumber, mTotalPartitionNumber)); } private void verifyAndPrepare() throws Exception { Loading @@ -281,12 +301,16 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog throw new UnsupportedFormatException( String.format(Locale.US, "Unsupported file format: %s", mUrl)); } // At least two partitions, {system, userdata} mTotalPartitionNumber = 2; if (mIsNetworkUrl) { mStream = new URL(mUrl).openStream(); } else if (URLUtil.isFileUrl(mUrl)) { if (mIsZip) { mZipFile = new ZipFile(new File(new URL(mUrl).toURI())); // {*.img in zip} + {userdata} mTotalPartitionNumber = calculateNumberOfImagesInLocalZip(mZipFile) + 1; } else { mStream = new URL(mUrl).openStream(); } Loading Loading @@ -333,9 +357,13 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } }; thread.start(); Progress progress = new Progress(partitionName, partitionSize, mNumInstalledPartitions++); mPartitionName = partitionName; mPartitionSize = partitionSize; ++mPartitionNumber; publishProgress(/* installedSize = */ 0L); long prevInstalledSize = 0; thread.start(); while (thread.isAlive()) { if (isCancelled()) { return; Loading @@ -343,9 +371,9 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog final long installedSize = mDynSystem.getInstallationProgress().bytes_processed; if (installedSize > progress.installedSize + MIN_PROGRESS_TO_PUBLISH) { progress.installedSize = installedSize; publishProgress(progress); if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) { publishProgress(installedSize); prevInstalledSize = installedSize; } try { Loading Loading @@ -392,14 +420,42 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog installImage("system", mSystemSize, new GZIPInputStream(mStream)); } private boolean shouldInstallEntry(String name) { if (!name.endsWith(".img")) { return false; } String partitionName = name.substring(0, name.length() - 4); if (UNSUPPORTED_PARTITIONS.contains(partitionName)) { return false; } return true; } private int calculateNumberOfImagesInLocalZip(ZipFile zipFile) { int total = 0; Enumeration<? extends ZipEntry> entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); if (shouldInstallEntry(entry.getName())) { ++total; } } return total; } private void installStreamingZipUpdate() throws IOException, ImageValidationException { Log.d(TAG, "To install a streaming ZIP update"); ZipInputStream zis = new ZipInputStream(mStream); ZipEntry zipEntry = null; ZipEntry entry = null; while ((zipEntry = zis.getNextEntry()) != null) { installImageFromAnEntry(zipEntry, zis); while ((entry = zis.getNextEntry()) != null) { String name = entry.getName(); if (shouldInstallEntry(name)) { installImageFromAnEntry(entry, zis); } else { Log.d(TAG, name + " installation is not supported, skip it."); } if (isCancelled()) { break; Loading @@ -414,7 +470,12 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); String name = entry.getName(); if (shouldInstallEntry(name)) { installImageFromAnEntry(entry, mZipFile.getInputStream(entry)); } else { Log.d(TAG, name + " installation is not supported, skip it."); } if (isCancelled()) { break; Loading @@ -422,28 +483,16 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } } private boolean installImageFromAnEntry(ZipEntry entry, InputStream is) private void installImageFromAnEntry(ZipEntry entry, InputStream is) throws IOException, ImageValidationException { String name = entry.getName(); Log.d(TAG, "ZipEntry: " + name); if (!name.endsWith(".img")) { return false; } String partitionName = name.substring(0, name.length() - 4); if (UNSUPPORTED_PARTITIONS.contains(partitionName)) { Log.d(TAG, name + " installation is not supported, skip it."); return false; } long uncompressedSize = entry.getSize(); installImage(partitionName, uncompressedSize, is); return true; } private void installImage(String partitionName, long uncompressedSize, InputStream is) Loading Loading @@ -497,8 +546,12 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog mInstallationSession.setAshmem(pfd, READ_BUFFER_SIZE); Progress progress = new Progress(partitionName, partitionSize, mNumInstalledPartitions++); mPartitionName = partitionName; mPartitionSize = partitionSize; ++mPartitionNumber; publishProgress(/* installedSize = */ 0L); long prevInstalledSize = 0; long installedSize = 0; byte[] bytes = new byte[READ_BUFFER_SIZE]; int numBytesRead; Loading @@ -516,9 +569,9 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog installedSize += numBytesRead; if (installedSize > progress.installedSize + MIN_PROGRESS_TO_PUBLISH) { progress.installedSize = installedSize; publishProgress(progress); if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) { publishProgress(installedSize); prevInstalledSize = installedSize; } } Loading Loading
packages/DynamicSystemInstallationService/Android.bp +8 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,9 @@ android_app { defaults: ["platform_app_defaults"], srcs: ["src/**/*.java"], static_libs: [ "DynamicSystemInstallationService-logtags", ], resource_dirs: ["res"], certificate: "platform", Loading @@ -32,3 +35,8 @@ android_app { enabled: false, }, } java_library { name: "DynamicSystemInstallationService-logtags", srcs: ["src/**/*.logtags"], }
packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +71 −25 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import android.os.RemoteException; import android.os.image.DynamicSystemClient; import android.os.image.DynamicSystemManager; import android.text.TextUtils; import android.util.EventLog; import android.util.Log; import android.widget.Toast; Loading Loading @@ -103,6 +104,36 @@ public class DynamicSystemInstallationService extends Service private static final String NOTIFICATION_CHANNEL_ID = "com.android.dynsystem"; private static final int NOTIFICATION_ID = 1; /* * Event log tags */ 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; protected static void logEventProgressUpdate( String partition, long installedSize, long partitionSize, int partitionNumber, int totalPartitionNumber) { EventLog.writeEvent( EVENT_DSU_PROGRESS_UPDATE, partition, installedSize, partitionSize, partitionNumber, totalPartitionNumber); } protected static void logEventComplete() { EventLog.writeEvent(EVENT_DSU_INSTALL_COMPLETE); } protected static void logEventFailed(String cause) { EventLog.writeEvent(EVENT_DSU_INSTALL_FAILED, cause); } /* * IPC */ Loading Loading @@ -132,15 +163,10 @@ public class DynamicSystemInstallationService extends Service private DynamicSystemManager mDynSystem; private NotificationManager mNM; private int mNumInstalledPartitions; private String mCurrentPartitionName; private long mCurrentPartitionSize; private long mCurrentPartitionInstalledSize; // This is for testing only now private boolean mEnableWhenCompleted; private InstallationAsyncTask.Progress mInstallTaskProgress; private InstallationAsyncTask mInstallTask; Loading Loading @@ -203,17 +229,21 @@ public class DynamicSystemInstallationService extends Service @Override public void onProgressUpdate(InstallationAsyncTask.Progress progress) { mCurrentPartitionName = progress.partitionName; mCurrentPartitionSize = progress.partitionSize; mCurrentPartitionInstalledSize = progress.installedSize; mNumInstalledPartitions = progress.numInstalledPartitions; logEventProgressUpdate( progress.partitionName, progress.installedSize, progress.partitionSize, progress.partitionNumber, progress.totalPartitionNumber); mInstallTaskProgress = progress; postStatus(STATUS_IN_PROGRESS, CAUSE_NOT_SPECIFIED, null); } @Override public void onResult(int result, Throwable detail) { if (result == RESULT_OK) { logEventComplete(); postStatus(STATUS_READY, CAUSE_INSTALL_COMPLETED, null); // For testing: enable DSU and restart the device when install completed Loading @@ -223,6 +253,12 @@ public class DynamicSystemInstallationService extends Service return; } if (result == RESULT_CANCELLED) { logEventFailed("Dynamic System installation task is canceled by the user."); } else { logEventFailed("error: " + detail); } boolean removeNotification = false; switch (result) { case RESULT_CANCELLED: Loading Loading @@ -251,16 +287,20 @@ public class DynamicSystemInstallationService extends Service private void executeInstallCommand(Intent intent) { if (!verifyRequest(intent)) { Log.e(TAG, "Verification failed. Did you use VerificationActivity?"); logEventFailed("VerificationActivity"); return; } if (mInstallTask != null) { Log.e(TAG, "There is already an installation task running"); logEventFailed("There is already an ongoing installation task."); return; } if (isInDynamicSystem()) { Log.e(TAG, "We are already running in DynamicSystem"); logEventFailed( "Cannot start a Dynamic System installation task within a Dynamic System."); return; } Loading Loading @@ -445,19 +485,22 @@ public class DynamicSystemInstallationService extends Service case STATUS_IN_PROGRESS: builder.setContentText(getString(R.string.notification_install_inprogress)); if (mInstallTaskProgress != null) { int max = 1024; int progress = 0; int currentMax = max >> (mNumInstalledPartitions + 1); int currentMax = max >> mInstallTaskProgress.partitionNumber; progress = max - currentMax * 2; long currentProgress = (mCurrentPartitionInstalledSize >> 20) * currentMax / Math.max(mCurrentPartitionSize >> 20, 1); long currentProgress = (mInstallTaskProgress.installedSize >> 20) * currentMax / Math.max(mInstallTaskProgress.partitionSize >> 20, 1); progress += (int) currentProgress; builder.setProgress(max, progress, false); } builder.addAction(new Notification.Action.Builder( null, getString(R.string.notification_action_cancel), createPendingIntent(ACTION_CANCEL_INSTALL)).build()); Loading Loading @@ -563,13 +606,13 @@ public class DynamicSystemInstallationService extends Service StringBuilder msg = new StringBuilder(); msg.append("status: " + statusString + ", cause: " + causeString); if (status == STATUS_IN_PROGRESS) { if (status == STATUS_IN_PROGRESS && mInstallTaskProgress != null) { msg.append( String.format( ", partition name: %s, progress: %d/%d", mCurrentPartitionName, mCurrentPartitionInstalledSize, mCurrentPartitionSize)); mInstallTaskProgress.partitionName, mInstallTaskProgress.installedSize, mInstallTaskProgress.partitionSize)); } if (detail != null) { msg.append(", detail: " + detail); Loading @@ -594,7 +637,10 @@ public class DynamicSystemInstallationService extends Service Bundle bundle = new Bundle(); // TODO: send more info to the clients bundle.putLong(DynamicSystemClient.KEY_INSTALLED_SIZE, mCurrentPartitionInstalledSize); if (mInstallTaskProgress != null) { bundle.putLong( DynamicSystemClient.KEY_INSTALLED_SIZE, mInstallTaskProgress.installedSize); } if (detail != null) { bundle.putSerializable(DynamicSystemClient.KEY_EXCEPTION_DETAIL, Loading
packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags 0 → 100644 +7 −0 Original line number Diff line number Diff line # See system/logging/logcat/event.logtags for a description of the format of this file. option java_package com.android.dynsystem 120000 dsu_progress_update (partition|3),(installed_size|2|5),(partition_size|2|5),(partition_number|1|5),(total_partition_number|1|5) 120001 dsu_install_complete 120002 dsu_install_failed (cause|3)
packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java +90 −37 Original line number Diff line number Diff line Loading @@ -44,7 +44,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Progress, Throwable> { class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { private static final String TAG = "InstallationAsyncTask"; Loading Loading @@ -106,14 +106,22 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog static class Progress { public final String partitionName; public final long installedSize; public final long partitionSize; public final int numInstalledPartitions; public long installedSize; Progress(String partitionName, long partitionSize, int numInstalledPartitions) { public final int partitionNumber; public final int totalPartitionNumber; Progress( String partitionName, long installedSize, long partitionSize, int partitionNumber, int totalPartitionNumber) { this.partitionName = partitionName; this.installedSize = installedSize; this.partitionSize = partitionSize; this.numInstalledPartitions = numInstalledPartitions; this.partitionNumber = partitionNumber; this.totalPartitionNumber = totalPartitionNumber; } } Loading @@ -139,7 +147,10 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog private boolean mIsZip; private boolean mIsCompleted; private int mNumInstalledPartitions; private String mPartitionName; private long mPartitionSize; private int mPartitionNumber; private int mTotalPartitionNumber; private InputStream mStream; private ZipFile mZipFile; Loading Loading @@ -175,11 +186,15 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog protected Throwable doInBackground(String... voids) { Log.d(TAG, "Start doInBackground(), URL: " + mUrl); final boolean wantScratchPartition = Build.IS_DEBUGGABLE; try { // call DynamicSystemManager to cleanup stuff mDynSystem.remove(); verifyAndPrepare(); if (wantScratchPartition) { ++mTotalPartitionNumber; } mDynSystem.startInstallation(mDsuSlot); Loading @@ -198,7 +213,7 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog return null; } if (Build.IS_DEBUGGABLE) { if (wantScratchPartition) { // If host is debuggable, then install a scratch partition so that we can do // adb remount in the guest system. try { Loading Loading @@ -262,9 +277,14 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } @Override protected void onProgressUpdate(Progress... values) { Progress progress = values[0]; mListener.onProgressUpdate(progress); protected void onProgressUpdate(Long... installedSize) { mListener.onProgressUpdate( new Progress( mPartitionName, installedSize[0], mPartitionSize, mPartitionNumber, mTotalPartitionNumber)); } private void verifyAndPrepare() throws Exception { Loading @@ -281,12 +301,16 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog throw new UnsupportedFormatException( String.format(Locale.US, "Unsupported file format: %s", mUrl)); } // At least two partitions, {system, userdata} mTotalPartitionNumber = 2; if (mIsNetworkUrl) { mStream = new URL(mUrl).openStream(); } else if (URLUtil.isFileUrl(mUrl)) { if (mIsZip) { mZipFile = new ZipFile(new File(new URL(mUrl).toURI())); // {*.img in zip} + {userdata} mTotalPartitionNumber = calculateNumberOfImagesInLocalZip(mZipFile) + 1; } else { mStream = new URL(mUrl).openStream(); } Loading Loading @@ -333,9 +357,13 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } }; thread.start(); Progress progress = new Progress(partitionName, partitionSize, mNumInstalledPartitions++); mPartitionName = partitionName; mPartitionSize = partitionSize; ++mPartitionNumber; publishProgress(/* installedSize = */ 0L); long prevInstalledSize = 0; thread.start(); while (thread.isAlive()) { if (isCancelled()) { return; Loading @@ -343,9 +371,9 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog final long installedSize = mDynSystem.getInstallationProgress().bytes_processed; if (installedSize > progress.installedSize + MIN_PROGRESS_TO_PUBLISH) { progress.installedSize = installedSize; publishProgress(progress); if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) { publishProgress(installedSize); prevInstalledSize = installedSize; } try { Loading Loading @@ -392,14 +420,42 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog installImage("system", mSystemSize, new GZIPInputStream(mStream)); } private boolean shouldInstallEntry(String name) { if (!name.endsWith(".img")) { return false; } String partitionName = name.substring(0, name.length() - 4); if (UNSUPPORTED_PARTITIONS.contains(partitionName)) { return false; } return true; } private int calculateNumberOfImagesInLocalZip(ZipFile zipFile) { int total = 0; Enumeration<? extends ZipEntry> entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); if (shouldInstallEntry(entry.getName())) { ++total; } } return total; } private void installStreamingZipUpdate() throws IOException, ImageValidationException { Log.d(TAG, "To install a streaming ZIP update"); ZipInputStream zis = new ZipInputStream(mStream); ZipEntry zipEntry = null; ZipEntry entry = null; while ((zipEntry = zis.getNextEntry()) != null) { installImageFromAnEntry(zipEntry, zis); while ((entry = zis.getNextEntry()) != null) { String name = entry.getName(); if (shouldInstallEntry(name)) { installImageFromAnEntry(entry, zis); } else { Log.d(TAG, name + " installation is not supported, skip it."); } if (isCancelled()) { break; Loading @@ -414,7 +470,12 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); String name = entry.getName(); if (shouldInstallEntry(name)) { installImageFromAnEntry(entry, mZipFile.getInputStream(entry)); } else { Log.d(TAG, name + " installation is not supported, skip it."); } if (isCancelled()) { break; Loading @@ -422,28 +483,16 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } } private boolean installImageFromAnEntry(ZipEntry entry, InputStream is) private void installImageFromAnEntry(ZipEntry entry, InputStream is) throws IOException, ImageValidationException { String name = entry.getName(); Log.d(TAG, "ZipEntry: " + name); if (!name.endsWith(".img")) { return false; } String partitionName = name.substring(0, name.length() - 4); if (UNSUPPORTED_PARTITIONS.contains(partitionName)) { Log.d(TAG, name + " installation is not supported, skip it."); return false; } long uncompressedSize = entry.getSize(); installImage(partitionName, uncompressedSize, is); return true; } private void installImage(String partitionName, long uncompressedSize, InputStream is) Loading Loading @@ -497,8 +546,12 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog mInstallationSession.setAshmem(pfd, READ_BUFFER_SIZE); Progress progress = new Progress(partitionName, partitionSize, mNumInstalledPartitions++); mPartitionName = partitionName; mPartitionSize = partitionSize; ++mPartitionNumber; publishProgress(/* installedSize = */ 0L); long prevInstalledSize = 0; long installedSize = 0; byte[] bytes = new byte[READ_BUFFER_SIZE]; int numBytesRead; Loading @@ -516,9 +569,9 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog installedSize += numBytesRead; if (installedSize > progress.installedSize + MIN_PROGRESS_TO_PUBLISH) { progress.installedSize = installedSize; publishProgress(progress); if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) { publishProgress(installedSize); prevInstalledSize = installedSize; } } Loading