Loading core/java/android/content/pm/IPackageInstallerSession.aidl +3 −1 Original line number Diff line number Diff line Loading @@ -39,6 +39,9 @@ interface IPackageInstallerSession { void transfer(in String packageName, in IntentSender statusReceiver); void abandon(); void addFile(String name, long lengthBytes, in byte[] metadata); void removeFile(String name); boolean isMultiPackage(); int[] getChildSessionIds(); void addChildSessionId(in int sessionId); Loading @@ -46,5 +49,4 @@ interface IPackageInstallerSession { int getParentSessionId(); boolean isStaged(); void addFile(in String name, long size, in byte[] metadata); } core/java/android/content/pm/PackageInstaller.java +75 −23 Original line number Diff line number Diff line Loading @@ -230,6 +230,15 @@ public class PackageInstaller { /** {@hide} */ public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK"; /** * Streaming installation pending. * Caller should make sure DataLoader is able to prepare image and reinitiate the operation. * * @see #EXTRA_SESSION_ID * {@hide} */ public static final int STATUS_PENDING_STREAMING = -2; /** * User action is currently required to proceed. You can launch the intent * activity described by {@link Intent#EXTRA_INTENT} to involve the user and Loading Loading @@ -1059,13 +1068,56 @@ public class PackageInstaller { } } /** * Adds a file to session. On commit this file will be pulled from dataLoader. * * @param name arbitrary, unique name of your choosing to identify the * APK being written. You can open a file again for * additional writes (such as after a reboot) by using the * same name. This name is only meaningful within the context * of a single install session. * @param lengthBytes total size of the file being written. * The system may clear various caches as needed to allocate * this space. * @param metadata additional info use by dataLoader to pull data for the file. * @throws SecurityException if called after the session has been * sealed or abandoned * @throws IllegalStateException if called for non-callback session * {@hide} */ public void addFile(@NonNull String name, long lengthBytes, @NonNull byte[] metadata) { try { mSession.addFile(name, lengthBytes, metadata); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Removes a file. * * @param name name of a file, e.g. split. * @throws SecurityException if called after the session has been * sealed or abandoned * @throws IllegalStateException if called for non-callback session * {@hide} */ public void removeFile(@NonNull String name) { try { mSession.removeFile(name); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Attempt to commit everything staged in this session. This may require * user intervention, and so it may not happen immediately. The final * result of the commit will be reported through the given callback. * <p> * Once this method is called, the session is sealed and no additional * mutations may be performed on the session. If the device reboots * Once this method is called, the session is sealed and no additional mutations may be * performed on the session. In case of device reboot or data loader transient failure * before the session has been finalized, you may commit the session again. * <p> * If the installer is the device owner or the affiliated profile owner, there will be no Loading Loading @@ -1219,27 +1271,6 @@ public class PackageInstaller { } } /** * Configure files for an installation session. * * Currently only for Incremental installation session. Once this method is called, * the files and their paths, as specified in the parameters, will be created and properly * configured in the Incremental File System. * * TODO(b/136132412): update this and InstallationFile class with latest API design. * * @throws IllegalStateException if {@link SessionParams#incrementalParams} is null. * * @hide */ public void addFile(@NonNull String name, long size, @NonNull byte[] metadata) { try { mSession.addFile(name, size, metadata); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Release this session object. You can open the session again if it * hasn't been finalized. Loading Loading @@ -1429,6 +1460,9 @@ public class PackageInstaller { public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST; /** {@hide} */ public IncrementalDataLoaderParams incrementalParams; /** TODO(b/146080380): add a class name to make it fully compatible with ComponentName. * {@hide} */ public String dataLoaderPackageName; /** * Construct parameters for a new package install session. Loading Loading @@ -1468,6 +1502,7 @@ public class PackageInstaller { incrementalParams = new IncrementalDataLoaderParams( dataLoaderParamsParcel); } dataLoaderPackageName = source.readString(); } /** {@hide} */ Loading @@ -1492,6 +1527,7 @@ public class PackageInstaller { ret.isStaged = isStaged; ret.requiredInstalledVersionCode = requiredInstalledVersionCode; ret.incrementalParams = incrementalParams; ret.dataLoaderPackageName = dataLoaderPackageName; return ret; } Loading Loading @@ -1831,6 +1867,20 @@ public class PackageInstaller { this.incrementalParams = incrementalParams; } /** * Set the data provider params for the session. * This also switches installation into callback mode and disallow direct writes into * staging folder. * TODO(b/146080380): unify dataprovider params with Incremental. * * @param dataLoaderPackageName name of the dataLoader package * {@hide} */ @RequiresPermission(Manifest.permission.INSTALL_PACKAGES) public void setDataLoaderPackageName(String dataLoaderPackageName) { this.dataLoaderPackageName = dataLoaderPackageName; } /** {@hide} */ public void dump(IndentingPrintWriter pw) { pw.printPair("mode", mode); Loading @@ -1851,6 +1901,7 @@ public class PackageInstaller { pw.printPair("isMultiPackage", isMultiPackage); pw.printPair("isStaged", isStaged); pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode); pw.printPair("dataLoaderPackageName", dataLoaderPackageName); pw.println(); } Loading Loading @@ -1885,6 +1936,7 @@ public class PackageInstaller { } else { dest.writeParcelable(null, flags); } dest.writeString(dataLoaderPackageName); } public static final Parcelable.Creator<SessionParams> Loading services/core/java/com/android/server/pm/PackageInstallerService.java +19 −3 Original line number Diff line number Diff line Loading @@ -637,7 +637,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this, mInstallThread.getLooper(), mStagingManager, sessionId, userId, callingUid, installSource, params, createdMillis, stageDir, stageCid, false, false, false, null, SessionInfo.INVALID_ID, stageDir, stageCid, null, false, false, false, null, SessionInfo.INVALID_ID, false, false, false, SessionInfo.STAGED_SESSION_NO_ERROR, ""); synchronized (mSessions) { Loading Loading @@ -1014,12 +1014,28 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } } static void sendPendingStreaming(Context context, IntentSender target, int sessionId, Throwable cause) { final Intent intent = new Intent(); intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId); intent.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_STREAMING); if (cause != null && !TextUtils.isEmpty(cause.getMessage())) { intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, "Staging Image Not Ready [" + cause.getMessage() + "]"); } else { intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, "Staging Image Not Ready"); } try { target.sendIntent(context, 0, intent, null, null); } catch (SendIntentException ignored) { } } static void sendOnUserActionRequired(Context context, IntentSender target, int sessionId, Intent intent) { final Intent fillIn = new Intent(); fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId); fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_USER_ACTION); fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_USER_ACTION); fillIn.putExtra(Intent.EXTRA_INTENT, intent); try { target.sendIntent(context, 0, fillIn, null, null); Loading services/core/java/com/android/server/pm/PackageInstallerSession.java +309 −47 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/pm/PackageManagerShellCommand.java +58 −10 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; Loading @@ -135,6 +136,8 @@ class PackageManagerShellCommand extends ShellCommand { private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/"; private static final int DEFAULT_WAIT_MS = 60 * 1000; private static final String PM_SHELL_DATALOADER = "com.android.pm.dataloader"; final IPackageManager mInterface; final IPermissionManager mPermissionManager; final private WeakHashMap<String, Resources> mResourceCache = Loading Loading @@ -175,6 +178,8 @@ class PackageManagerShellCommand extends ShellCommand { return runQueryIntentReceivers(); case "install": return runInstall(); case "install-streaming": return runStreamingInstall(); case "install-abandon": case "install-destroy": return runInstallAbandon(); Loading Loading @@ -1152,9 +1157,21 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } private int runStreamingInstall() throws RemoteException { final InstallParams params = makeInstallParams(); if (TextUtils.isEmpty(params.sessionParams.dataLoaderPackageName)) { params.sessionParams.setDataLoaderPackageName(PM_SHELL_DATALOADER); } return doRunInstall(params); } private int runInstall() throws RemoteException { return doRunInstall(makeInstallParams()); } private int doRunInstall(final InstallParams params) throws RemoteException { final PrintWriter pw = getOutPrintWriter(); final InstallParams params = makeInstallParams(); final boolean streaming = !TextUtils.isEmpty(params.sessionParams.dataLoaderPackageName); ArrayList<String> inPaths = getRemainingArgs(); if (inPaths.isEmpty()) { Loading @@ -1181,19 +1198,32 @@ class PackageManagerShellCommand extends ShellCommand { return 1; } if (!streaming) { setParamsSize(params, inPaths); } final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId); boolean abandonSession = true; try { for (String inPath : inPaths) { String splitName = hasSplits ? (new File(inPath)).getName() if (streaming) { String name = new File(inPath).getName(); byte[] metadata = inPath.getBytes(StandardCharsets.UTF_8); if (doAddFile(sessionId, name, params.sessionParams.sizeBytes, metadata, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; } } else { String splitName = hasSplits ? new File(inPath).getName() : "base." + (isApex ? "apex" : "apk"); if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, splitName, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; } } } if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; Loading Loading @@ -2927,11 +2957,32 @@ class PackageManagerShellCommand extends ShellCommand { return sessionId; } private int doAddFile(int sessionId, String name, long sizeBytes, byte[] metadata, boolean logSuccess) throws RemoteException { PackageInstaller.Session session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); try { session.addFile(name, sizeBytes, metadata); if (logSuccess) { getOutPrintWriter().println("Success"); } return 0; } finally { IoUtils.closeQuietly(session); } } private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName, boolean logSuccess) throws RemoteException { PackageInstaller.Session session = null; try { session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); final PrintWriter pw = getOutPrintWriter(); final ParcelFileDescriptor fd; if (STDIN_PATH.equals(inPath)) { fd = ParcelFileDescriptor.dup(getInFileDescriptor()); Loading @@ -2953,8 +3004,6 @@ class PackageManagerShellCommand extends ShellCommand { return 1; } session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); session.write(splitName, 0, sizeBytes, fd); if (logSuccess) { Loading Loading @@ -3000,7 +3049,6 @@ class PackageManagerShellCommand extends ShellCommand { try { session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); for (String splitName : splitNames) { session.removeSplit(splitName); } Loading Loading
core/java/android/content/pm/IPackageInstallerSession.aidl +3 −1 Original line number Diff line number Diff line Loading @@ -39,6 +39,9 @@ interface IPackageInstallerSession { void transfer(in String packageName, in IntentSender statusReceiver); void abandon(); void addFile(String name, long lengthBytes, in byte[] metadata); void removeFile(String name); boolean isMultiPackage(); int[] getChildSessionIds(); void addChildSessionId(in int sessionId); Loading @@ -46,5 +49,4 @@ interface IPackageInstallerSession { int getParentSessionId(); boolean isStaged(); void addFile(in String name, long size, in byte[] metadata); }
core/java/android/content/pm/PackageInstaller.java +75 −23 Original line number Diff line number Diff line Loading @@ -230,6 +230,15 @@ public class PackageInstaller { /** {@hide} */ public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK"; /** * Streaming installation pending. * Caller should make sure DataLoader is able to prepare image and reinitiate the operation. * * @see #EXTRA_SESSION_ID * {@hide} */ public static final int STATUS_PENDING_STREAMING = -2; /** * User action is currently required to proceed. You can launch the intent * activity described by {@link Intent#EXTRA_INTENT} to involve the user and Loading Loading @@ -1059,13 +1068,56 @@ public class PackageInstaller { } } /** * Adds a file to session. On commit this file will be pulled from dataLoader. * * @param name arbitrary, unique name of your choosing to identify the * APK being written. You can open a file again for * additional writes (such as after a reboot) by using the * same name. This name is only meaningful within the context * of a single install session. * @param lengthBytes total size of the file being written. * The system may clear various caches as needed to allocate * this space. * @param metadata additional info use by dataLoader to pull data for the file. * @throws SecurityException if called after the session has been * sealed or abandoned * @throws IllegalStateException if called for non-callback session * {@hide} */ public void addFile(@NonNull String name, long lengthBytes, @NonNull byte[] metadata) { try { mSession.addFile(name, lengthBytes, metadata); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Removes a file. * * @param name name of a file, e.g. split. * @throws SecurityException if called after the session has been * sealed or abandoned * @throws IllegalStateException if called for non-callback session * {@hide} */ public void removeFile(@NonNull String name) { try { mSession.removeFile(name); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Attempt to commit everything staged in this session. This may require * user intervention, and so it may not happen immediately. The final * result of the commit will be reported through the given callback. * <p> * Once this method is called, the session is sealed and no additional * mutations may be performed on the session. If the device reboots * Once this method is called, the session is sealed and no additional mutations may be * performed on the session. In case of device reboot or data loader transient failure * before the session has been finalized, you may commit the session again. * <p> * If the installer is the device owner or the affiliated profile owner, there will be no Loading Loading @@ -1219,27 +1271,6 @@ public class PackageInstaller { } } /** * Configure files for an installation session. * * Currently only for Incremental installation session. Once this method is called, * the files and their paths, as specified in the parameters, will be created and properly * configured in the Incremental File System. * * TODO(b/136132412): update this and InstallationFile class with latest API design. * * @throws IllegalStateException if {@link SessionParams#incrementalParams} is null. * * @hide */ public void addFile(@NonNull String name, long size, @NonNull byte[] metadata) { try { mSession.addFile(name, size, metadata); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Release this session object. You can open the session again if it * hasn't been finalized. Loading Loading @@ -1429,6 +1460,9 @@ public class PackageInstaller { public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST; /** {@hide} */ public IncrementalDataLoaderParams incrementalParams; /** TODO(b/146080380): add a class name to make it fully compatible with ComponentName. * {@hide} */ public String dataLoaderPackageName; /** * Construct parameters for a new package install session. Loading Loading @@ -1468,6 +1502,7 @@ public class PackageInstaller { incrementalParams = new IncrementalDataLoaderParams( dataLoaderParamsParcel); } dataLoaderPackageName = source.readString(); } /** {@hide} */ Loading @@ -1492,6 +1527,7 @@ public class PackageInstaller { ret.isStaged = isStaged; ret.requiredInstalledVersionCode = requiredInstalledVersionCode; ret.incrementalParams = incrementalParams; ret.dataLoaderPackageName = dataLoaderPackageName; return ret; } Loading Loading @@ -1831,6 +1867,20 @@ public class PackageInstaller { this.incrementalParams = incrementalParams; } /** * Set the data provider params for the session. * This also switches installation into callback mode and disallow direct writes into * staging folder. * TODO(b/146080380): unify dataprovider params with Incremental. * * @param dataLoaderPackageName name of the dataLoader package * {@hide} */ @RequiresPermission(Manifest.permission.INSTALL_PACKAGES) public void setDataLoaderPackageName(String dataLoaderPackageName) { this.dataLoaderPackageName = dataLoaderPackageName; } /** {@hide} */ public void dump(IndentingPrintWriter pw) { pw.printPair("mode", mode); Loading @@ -1851,6 +1901,7 @@ public class PackageInstaller { pw.printPair("isMultiPackage", isMultiPackage); pw.printPair("isStaged", isStaged); pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode); pw.printPair("dataLoaderPackageName", dataLoaderPackageName); pw.println(); } Loading Loading @@ -1885,6 +1936,7 @@ public class PackageInstaller { } else { dest.writeParcelable(null, flags); } dest.writeString(dataLoaderPackageName); } public static final Parcelable.Creator<SessionParams> Loading
services/core/java/com/android/server/pm/PackageInstallerService.java +19 −3 Original line number Diff line number Diff line Loading @@ -637,7 +637,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this, mInstallThread.getLooper(), mStagingManager, sessionId, userId, callingUid, installSource, params, createdMillis, stageDir, stageCid, false, false, false, null, SessionInfo.INVALID_ID, stageDir, stageCid, null, false, false, false, null, SessionInfo.INVALID_ID, false, false, false, SessionInfo.STAGED_SESSION_NO_ERROR, ""); synchronized (mSessions) { Loading Loading @@ -1014,12 +1014,28 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } } static void sendPendingStreaming(Context context, IntentSender target, int sessionId, Throwable cause) { final Intent intent = new Intent(); intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId); intent.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_STREAMING); if (cause != null && !TextUtils.isEmpty(cause.getMessage())) { intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, "Staging Image Not Ready [" + cause.getMessage() + "]"); } else { intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, "Staging Image Not Ready"); } try { target.sendIntent(context, 0, intent, null, null); } catch (SendIntentException ignored) { } } static void sendOnUserActionRequired(Context context, IntentSender target, int sessionId, Intent intent) { final Intent fillIn = new Intent(); fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId); fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_USER_ACTION); fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_USER_ACTION); fillIn.putExtra(Intent.EXTRA_INTENT, intent); try { target.sendIntent(context, 0, fillIn, null, null); Loading
services/core/java/com/android/server/pm/PackageInstallerSession.java +309 −47 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/pm/PackageManagerShellCommand.java +58 −10 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; Loading @@ -135,6 +136,8 @@ class PackageManagerShellCommand extends ShellCommand { private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/"; private static final int DEFAULT_WAIT_MS = 60 * 1000; private static final String PM_SHELL_DATALOADER = "com.android.pm.dataloader"; final IPackageManager mInterface; final IPermissionManager mPermissionManager; final private WeakHashMap<String, Resources> mResourceCache = Loading Loading @@ -175,6 +178,8 @@ class PackageManagerShellCommand extends ShellCommand { return runQueryIntentReceivers(); case "install": return runInstall(); case "install-streaming": return runStreamingInstall(); case "install-abandon": case "install-destroy": return runInstallAbandon(); Loading Loading @@ -1152,9 +1157,21 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } private int runStreamingInstall() throws RemoteException { final InstallParams params = makeInstallParams(); if (TextUtils.isEmpty(params.sessionParams.dataLoaderPackageName)) { params.sessionParams.setDataLoaderPackageName(PM_SHELL_DATALOADER); } return doRunInstall(params); } private int runInstall() throws RemoteException { return doRunInstall(makeInstallParams()); } private int doRunInstall(final InstallParams params) throws RemoteException { final PrintWriter pw = getOutPrintWriter(); final InstallParams params = makeInstallParams(); final boolean streaming = !TextUtils.isEmpty(params.sessionParams.dataLoaderPackageName); ArrayList<String> inPaths = getRemainingArgs(); if (inPaths.isEmpty()) { Loading @@ -1181,19 +1198,32 @@ class PackageManagerShellCommand extends ShellCommand { return 1; } if (!streaming) { setParamsSize(params, inPaths); } final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId); boolean abandonSession = true; try { for (String inPath : inPaths) { String splitName = hasSplits ? (new File(inPath)).getName() if (streaming) { String name = new File(inPath).getName(); byte[] metadata = inPath.getBytes(StandardCharsets.UTF_8); if (doAddFile(sessionId, name, params.sessionParams.sizeBytes, metadata, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; } } else { String splitName = hasSplits ? new File(inPath).getName() : "base." + (isApex ? "apex" : "apk"); if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, splitName, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; } } } if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; Loading Loading @@ -2927,11 +2957,32 @@ class PackageManagerShellCommand extends ShellCommand { return sessionId; } private int doAddFile(int sessionId, String name, long sizeBytes, byte[] metadata, boolean logSuccess) throws RemoteException { PackageInstaller.Session session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); try { session.addFile(name, sizeBytes, metadata); if (logSuccess) { getOutPrintWriter().println("Success"); } return 0; } finally { IoUtils.closeQuietly(session); } } private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName, boolean logSuccess) throws RemoteException { PackageInstaller.Session session = null; try { session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); final PrintWriter pw = getOutPrintWriter(); final ParcelFileDescriptor fd; if (STDIN_PATH.equals(inPath)) { fd = ParcelFileDescriptor.dup(getInFileDescriptor()); Loading @@ -2953,8 +3004,6 @@ class PackageManagerShellCommand extends ShellCommand { return 1; } session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); session.write(splitName, 0, sizeBytes, fd); if (logSuccess) { Loading Loading @@ -3000,7 +3049,6 @@ class PackageManagerShellCommand extends ShellCommand { try { session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); for (String splitName : splitNames) { session.removeSplit(splitName); } Loading