• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.content.pm;
18 
19 import android.Manifest;
20 import android.annotation.CurrentTimeMillisLong;
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.RequiresPermission;
25 import android.annotation.SdkConstant;
26 import android.annotation.SdkConstant.SdkConstantType;
27 import android.annotation.SystemApi;
28 import android.annotation.TestApi;
29 import android.annotation.UnsupportedAppUsage;
30 import android.app.ActivityManager;
31 import android.app.AppGlobals;
32 import android.content.Intent;
33 import android.content.IntentSender;
34 import android.content.pm.PackageManager.DeleteFlags;
35 import android.content.pm.PackageManager.InstallReason;
36 import android.graphics.Bitmap;
37 import android.net.Uri;
38 import android.os.Build;
39 import android.os.FileBridge;
40 import android.os.Handler;
41 import android.os.HandlerExecutor;
42 import android.os.Parcel;
43 import android.os.ParcelFileDescriptor;
44 import android.os.Parcelable;
45 import android.os.ParcelableException;
46 import android.os.RemoteException;
47 import android.os.SystemProperties;
48 import android.os.UserHandle;
49 import android.system.ErrnoException;
50 import android.system.Os;
51 import android.util.ArraySet;
52 import android.util.ExceptionUtils;
53 
54 import com.android.internal.util.IndentingPrintWriter;
55 import com.android.internal.util.Preconditions;
56 import com.android.internal.util.function.pooled.PooledLambda;
57 
58 import java.io.Closeable;
59 import java.io.IOException;
60 import java.io.InputStream;
61 import java.io.OutputStream;
62 import java.lang.annotation.Retention;
63 import java.lang.annotation.RetentionPolicy;
64 import java.security.MessageDigest;
65 import java.util.ArrayList;
66 import java.util.Collections;
67 import java.util.Iterator;
68 import java.util.List;
69 import java.util.Set;
70 import java.util.concurrent.Executor;
71 
72 /**
73  * Offers the ability to install, upgrade, and remove applications on the
74  * device. This includes support for apps packaged either as a single
75  * "monolithic" APK, or apps packaged as multiple "split" APKs.
76  * <p>
77  * An app is delivered for installation through a
78  * {@link PackageInstaller.Session}, which any app can create. Once the session
79  * is created, the installer can stream one or more APKs into place until it
80  * decides to either commit or destroy the session. Committing may require user
81  * intervention to complete the installation, unless the caller falls into one of the
82  * following categories, in which case the installation will complete automatically.
83  * <ul>
84  * <li>the device owner
85  * <li>the affiliated profile owner
86  * </ul>
87  * <p>
88  * Sessions can install brand new apps, upgrade existing apps, or add new splits
89  * into an existing app.
90  * <p>
91  * Apps packaged as multiple split APKs always consist of a single "base" APK
92  * (with a {@code null} split name) and zero or more "split" APKs (with unique
93  * split names). Any subset of these APKs can be installed together, as long as
94  * the following constraints are met:
95  * <ul>
96  * <li>All APKs must have the exact same package name, version code, and signing
97  * certificates.
98  * <li>All APKs must have unique split names.
99  * <li>All installations must contain a single base APK.
100  * </ul>
101  * <p>
102  * The ApiDemos project contains examples of using this API:
103  * <code>ApiDemos/src/com/example/android/apis/content/InstallApk*.java</code>.
104  * <p>
105  * On Android Q or above, an app installed notification will be posted
106  * by system after a new app is installed.
107  * To customize installer's notification icon, you should declare the following in the manifest
108  * &lt;application> as follows: </p>
109  * <pre>
110  * &lt;meta-data android:name="com.android.packageinstaller.notification.smallIcon"
111  * android:resource="@drawable/installer_notification_icon"/>
112  * </pre>
113  * <pre>
114  * &lt;meta-data android:name="com.android.packageinstaller.notification.color"
115  * android:resource="@color/installer_notification_color"/>
116  * </pre>
117  */
118 public class PackageInstaller {
119     private static final String TAG = "PackageInstaller";
120 
121     /** {@hide} */
122     public static final boolean ENABLE_REVOCABLE_FD =
123             SystemProperties.getBoolean("fw.revocable_fd", false);
124 
125     /**
126      * Activity Action: Show details about a particular install session. This
127      * may surface actions such as pause, resume, or cancel.
128      * <p>
129      * This should always be scoped to the installer package that owns the
130      * session. Clients should use {@link SessionInfo#createDetailsIntent()} to
131      * build this intent correctly.
132      * <p>
133      * In some cases, a matching Activity may not exist, so ensure you safeguard
134      * against this.
135      * <p>
136      * The session to show details for is defined in {@link #EXTRA_SESSION_ID}.
137      */
138     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
139     public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
140 
141     /**
142      * Broadcast Action: Explicit broadcast sent to the last known default launcher when a session
143      * for a new install is committed. For managed profile, this is sent to the default launcher
144      * of the primary profile.
145      * <p>
146      * The associated session is defined in {@link #EXTRA_SESSION} and the user for which this
147      * session was created in {@link Intent#EXTRA_USER}.
148      */
149     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
150     public static final String ACTION_SESSION_COMMITTED =
151             "android.content.pm.action.SESSION_COMMITTED";
152 
153     /**
154      * Broadcast Action: Send information about a staged install session when its state is updated.
155      * <p>
156      * The associated session information is defined in {@link #EXTRA_SESSION}.
157      */
158     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
159     public static final String ACTION_SESSION_UPDATED =
160             "android.content.pm.action.SESSION_UPDATED";
161 
162     /** {@hide} */
163     public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL";
164 
165     /**
166      * An integer session ID that an operation is working with.
167      *
168      * @see Intent#getIntExtra(String, int)
169      */
170     public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
171 
172     /**
173      * {@link SessionInfo} that an operation is working with.
174      *
175      * @see Intent#getParcelableExtra(String)
176      */
177     public static final String EXTRA_SESSION = "android.content.pm.extra.SESSION";
178 
179     /**
180      * Package name that an operation is working with.
181      *
182      * @see Intent#getStringExtra(String)
183      */
184     public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
185 
186     /**
187      * Current status of an operation. Will be one of
188      * {@link #STATUS_PENDING_USER_ACTION}, {@link #STATUS_SUCCESS},
189      * {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED},
190      * {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT},
191      * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID}, or
192      * {@link #STATUS_FAILURE_STORAGE}.
193      * <p>
194      * More information about a status may be available through additional
195      * extras; see the individual status documentation for details.
196      *
197      * @see Intent#getIntExtra(String, int)
198      */
199     public static final String EXTRA_STATUS = "android.content.pm.extra.STATUS";
200 
201     /**
202      * Detailed string representation of the status, including raw details that
203      * are useful for debugging.
204      *
205      * @see Intent#getStringExtra(String)
206      */
207     public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
208 
209     /**
210      * Another package name relevant to a status. This is typically the package
211      * responsible for causing an operation failure.
212      *
213      * @see Intent#getStringExtra(String)
214      */
215     public static final String
216             EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
217 
218     /**
219      * Storage path relevant to a status.
220      *
221      * @see Intent#getStringExtra(String)
222      */
223     public static final String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH";
224 
225     /** {@hide} */
226     @Deprecated
227     public static final String EXTRA_PACKAGE_NAMES = "android.content.pm.extra.PACKAGE_NAMES";
228 
229     /** {@hide} */
230     public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS";
231     /** {@hide} */
232     public static final String EXTRA_LEGACY_BUNDLE = "android.content.pm.extra.LEGACY_BUNDLE";
233     /** {@hide} */
234     public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK";
235 
236     /**
237      * User action is currently required to proceed. You can launch the intent
238      * activity described by {@link Intent#EXTRA_INTENT} to involve the user and
239      * continue.
240      * <p>
241      * You may choose to immediately launch the intent if the user is actively
242      * using your app. Otherwise, you should use a notification to guide the
243      * user back into your app before launching.
244      *
245      * @see Intent#getParcelableExtra(String)
246      */
247     public static final int STATUS_PENDING_USER_ACTION = -1;
248 
249     /**
250      * The operation succeeded.
251      */
252     public static final int STATUS_SUCCESS = 0;
253 
254     /**
255      * The operation failed in a generic way. The system will always try to
256      * provide a more specific failure reason, but in some rare cases this may
257      * be delivered.
258      *
259      * @see #EXTRA_STATUS_MESSAGE
260      */
261     public static final int STATUS_FAILURE = 1;
262 
263     /**
264      * The operation failed because it was blocked. For example, a device policy
265      * may be blocking the operation, a package verifier may have blocked the
266      * operation, or the app may be required for core system operation.
267      * <p>
268      * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
269      * specific package blocking the install.
270      *
271      * @see #EXTRA_STATUS_MESSAGE
272      * @see #EXTRA_OTHER_PACKAGE_NAME
273      */
274     public static final int STATUS_FAILURE_BLOCKED = 2;
275 
276     /**
277      * The operation failed because it was actively aborted. For example, the
278      * user actively declined requested permissions, or the session was
279      * abandoned.
280      *
281      * @see #EXTRA_STATUS_MESSAGE
282      */
283     public static final int STATUS_FAILURE_ABORTED = 3;
284 
285     /**
286      * The operation failed because one or more of the APKs was invalid. For
287      * example, they might be malformed, corrupt, incorrectly signed,
288      * mismatched, etc.
289      *
290      * @see #EXTRA_STATUS_MESSAGE
291      */
292     public static final int STATUS_FAILURE_INVALID = 4;
293 
294     /**
295      * The operation failed because it conflicts (or is inconsistent with) with
296      * another package already installed on the device. For example, an existing
297      * permission, incompatible certificates, etc. The user may be able to
298      * uninstall another app to fix the issue.
299      * <p>
300      * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
301      * specific package identified as the cause of the conflict.
302      *
303      * @see #EXTRA_STATUS_MESSAGE
304      * @see #EXTRA_OTHER_PACKAGE_NAME
305      */
306     public static final int STATUS_FAILURE_CONFLICT = 5;
307 
308     /**
309      * The operation failed because of storage issues. For example, the device
310      * may be running low on space, or external media may be unavailable. The
311      * user may be able to help free space or insert different external media.
312      * <p>
313      * The result may also contain {@link #EXTRA_STORAGE_PATH} with the path to
314      * the storage device that caused the failure.
315      *
316      * @see #EXTRA_STATUS_MESSAGE
317      * @see #EXTRA_STORAGE_PATH
318      */
319     public static final int STATUS_FAILURE_STORAGE = 6;
320 
321     /**
322      * The operation failed because it is fundamentally incompatible with this
323      * device. For example, the app may require a hardware feature that doesn't
324      * exist, it may be missing native code for the ABIs supported by the
325      * device, or it requires a newer SDK version, etc.
326      *
327      * @see #EXTRA_STATUS_MESSAGE
328      */
329     public static final int STATUS_FAILURE_INCOMPATIBLE = 7;
330 
331     private final IPackageInstaller mInstaller;
332     private final int mUserId;
333     private final String mInstallerPackageName;
334 
335     private final ArrayList<SessionCallbackDelegate> mDelegates = new ArrayList<>();
336 
337     /** {@hide} */
PackageInstaller(IPackageInstaller installer, String installerPackageName, int userId)338     public PackageInstaller(IPackageInstaller installer,
339             String installerPackageName, int userId) {
340         mInstaller = installer;
341         mInstallerPackageName = installerPackageName;
342         mUserId = userId;
343     }
344 
345     /**
346      * Create a new session using the given parameters, returning a unique ID
347      * that represents the session. Once created, the session can be opened
348      * multiple times across multiple device boots.
349      * <p>
350      * The system may automatically destroy sessions that have not been
351      * finalized (either committed or abandoned) within a reasonable period of
352      * time, typically on the order of a day.
353      *
354      * @throws IOException if parameters were unsatisfiable, such as lack of
355      *             disk space or unavailable media.
356      * @throws SecurityException when installation services are unavailable,
357      *             such as when called from a restricted user.
358      * @throws IllegalArgumentException when {@link SessionParams} is invalid.
359      * @return positive, non-zero unique ID that represents the created session.
360      *         This ID remains consistent across device reboots until the
361      *         session is finalized. IDs are not reused during a given boot.
362      */
createSession(@onNull SessionParams params)363     public int createSession(@NonNull SessionParams params) throws IOException {
364         try {
365             final String installerPackage;
366             if (params.installerPackageName == null) {
367                 installerPackage = mInstallerPackageName;
368             } else {
369                 installerPackage = params.installerPackageName;
370             }
371 
372             return mInstaller.createSession(params, installerPackage, mUserId);
373         } catch (RuntimeException e) {
374             ExceptionUtils.maybeUnwrapIOException(e);
375             throw e;
376         } catch (RemoteException e) {
377             throw e.rethrowFromSystemServer();
378         }
379     }
380 
381     /**
382      * Open an existing session to actively perform work. To succeed, the caller
383      * must be the owner of the install session.
384      *
385      * @throws IOException if parameters were unsatisfiable, such as lack of
386      *             disk space or unavailable media.
387      * @throws SecurityException when the caller does not own the session, or
388      *             the session is invalid.
389      */
openSession(int sessionId)390     public @NonNull Session openSession(int sessionId) throws IOException {
391         try {
392             try {
393                 return new Session(mInstaller.openSession(sessionId));
394             } catch (RemoteException e) {
395                 throw e.rethrowFromSystemServer();
396             }
397         } catch (RuntimeException e) {
398             ExceptionUtils.maybeUnwrapIOException(e);
399             throw e;
400         }
401     }
402 
403     /**
404      * Update the icon representing the app being installed in a specific
405      * session. This should be roughly
406      * {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions.
407      *
408      * @throws SecurityException when the caller does not own the session, or
409      *             the session is invalid.
410      */
updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon)411     public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) {
412         try {
413             mInstaller.updateSessionAppIcon(sessionId, appIcon);
414         } catch (RemoteException e) {
415             throw e.rethrowFromSystemServer();
416         }
417     }
418 
419     /**
420      * Update the label representing the app being installed in a specific
421      * session.
422      *
423      * @throws SecurityException when the caller does not own the session, or
424      *             the session is invalid.
425      */
updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel)426     public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) {
427         try {
428             final String val = (appLabel != null) ? appLabel.toString() : null;
429             mInstaller.updateSessionAppLabel(sessionId, val);
430         } catch (RemoteException e) {
431             throw e.rethrowFromSystemServer();
432         }
433     }
434 
435     /**
436      * Completely abandon the given session, destroying all staged data and
437      * rendering it invalid. Abandoned sessions will be reported to
438      * {@link SessionCallback} listeners as failures. This is equivalent to
439      * opening the session and calling {@link Session#abandon()}.
440      *
441      * @throws SecurityException when the caller does not own the session, or
442      *             the session is invalid.
443      */
abandonSession(int sessionId)444     public void abandonSession(int sessionId) {
445         try {
446             mInstaller.abandonSession(sessionId);
447         } catch (RemoteException e) {
448             throw e.rethrowFromSystemServer();
449         }
450     }
451 
452     /**
453      * Return details for a specific session. No special permissions are
454      * required to retrieve these details.
455      *
456      * @return details for the requested session, or {@code null} if the session
457      *         does not exist.
458      */
getSessionInfo(int sessionId)459     public @Nullable SessionInfo getSessionInfo(int sessionId) {
460         try {
461             return mInstaller.getSessionInfo(sessionId);
462         } catch (RemoteException e) {
463             throw e.rethrowFromSystemServer();
464         }
465     }
466 
467     /**
468      * Return list of all known install sessions, regardless of the installer.
469      */
getAllSessions()470     public @NonNull List<SessionInfo> getAllSessions() {
471         try {
472             return mInstaller.getAllSessions(mUserId).getList();
473         } catch (RemoteException e) {
474             throw e.rethrowFromSystemServer();
475         }
476     }
477 
478     /**
479      * Return list of all known install sessions owned by the calling app.
480      */
getMySessions()481     public @NonNull List<SessionInfo> getMySessions() {
482         try {
483             return mInstaller.getMySessions(mInstallerPackageName, mUserId).getList();
484         } catch (RemoteException e) {
485             throw e.rethrowFromSystemServer();
486         }
487     }
488 
489     /**
490      * Return list of all staged install sessions.
491      */
getStagedSessions()492     public @NonNull List<SessionInfo> getStagedSessions() {
493         try {
494             // TODO: limit this to the mUserId?
495             return mInstaller.getStagedSessions().getList();
496         } catch (RemoteException e) {
497             throw e.rethrowFromSystemServer();
498         }
499     }
500 
501     /**
502      * Returns an active staged session, or {@code null} if there is none.
503      *
504      * <p>Staged session is active iff:
505      * <ul>
506      *     <li>It is committed, i.e. {@link SessionInfo#isCommitted()} is {@code true}, and
507      *     <li>it is not applied, i.e. {@link SessionInfo#isStagedSessionApplied()} is {@code
508      *     false}, and
509      *     <li>it is not failed, i.e. {@link SessionInfo#isStagedSessionFailed()} is {@code false}.
510      * </ul>
511      *
512      * <p>In case of a multi-apk session, reasoning above is applied to the parent session, since
513      * that is the one that should been {@link Session#commit committed}.
514      */
getActiveStagedSession()515     public @Nullable SessionInfo getActiveStagedSession() {
516         final List<SessionInfo> stagedSessions = getStagedSessions();
517         for (SessionInfo s : stagedSessions) {
518             if (s.isStagedSessionApplied() || s.isStagedSessionFailed()) {
519                 // Finalized session.
520                 continue;
521             }
522             if (s.getParentSessionId() != SessionInfo.INVALID_ID) {
523                 // Child session.
524                 continue;
525             }
526             if (s.isCommitted()) {
527                 return s;
528             }
529         }
530         return null;
531     }
532 
533     /**
534      * Uninstall the given package, removing it completely from the device. This
535      * method is available to:
536      * <ul>
537      * <li>the current "installer of record" for the package
538      * <li>the device owner
539      * <li>the affiliated profile owner
540      * </ul>
541      *
542      * @param packageName The package to uninstall.
543      * @param statusReceiver Where to deliver the result.
544      *
545      * @see android.app.admin.DevicePolicyManager
546      */
547     @RequiresPermission(anyOf = {
548             Manifest.permission.DELETE_PACKAGES,
549             Manifest.permission.REQUEST_DELETE_PACKAGES})
uninstall(@onNull String packageName, @NonNull IntentSender statusReceiver)550     public void uninstall(@NonNull String packageName, @NonNull IntentSender statusReceiver) {
551         uninstall(packageName, 0 /*flags*/, statusReceiver);
552     }
553 
554     /**
555      * Uninstall the given package, removing it completely from the device. This
556      * method is only available to the current "installer of record" for the
557      * package.
558      *
559      * @param packageName The package to uninstall.
560      * @param flags Flags for uninstall.
561      * @param statusReceiver Where to deliver the result.
562      *
563      * @hide
564      */
uninstall(@onNull String packageName, @DeleteFlags int flags, @NonNull IntentSender statusReceiver)565     public void uninstall(@NonNull String packageName, @DeleteFlags int flags,
566             @NonNull IntentSender statusReceiver) {
567         uninstall(new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
568                 flags, statusReceiver);
569     }
570 
571     /**
572      * Uninstall the given package with a specific version code, removing it
573      * completely from the device. If the version code of the package
574      * does not match the one passed in the versioned package argument this
575      * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to
576      * uninstall the latest version of the package.
577      * <p>
578      * This method is available to:
579      * <ul>
580      * <li>the current "installer of record" for the package
581      * <li>the device owner
582      * <li>the affiliated profile owner
583      * </ul>
584      *
585      * @param versionedPackage The versioned package to uninstall.
586      * @param statusReceiver Where to deliver the result.
587      *
588      * @see android.app.admin.DevicePolicyManager
589      */
590     @RequiresPermission(anyOf = {
591             Manifest.permission.DELETE_PACKAGES,
592             Manifest.permission.REQUEST_DELETE_PACKAGES})
uninstall(@onNull VersionedPackage versionedPackage, @NonNull IntentSender statusReceiver)593     public void uninstall(@NonNull VersionedPackage versionedPackage,
594             @NonNull IntentSender statusReceiver) {
595         uninstall(versionedPackage, 0 /*flags*/, statusReceiver);
596     }
597 
598     /**
599      * Uninstall the given package with a specific version code, removing it
600      * completely from the device. This method is only available to the current
601      * "installer of record" for the package. If the version code of the package
602      * does not match the one passed in the versioned package argument this
603      * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to
604      * uninstall the latest version of the package.
605      *
606      * @param versionedPackage The versioned package to uninstall.
607      * @param flags Flags for uninstall.
608      * @param statusReceiver Where to deliver the result.
609      *
610      * @hide
611      */
612     @RequiresPermission(anyOf = {
613             Manifest.permission.DELETE_PACKAGES,
614             Manifest.permission.REQUEST_DELETE_PACKAGES})
uninstall(@onNull VersionedPackage versionedPackage, @DeleteFlags int flags, @NonNull IntentSender statusReceiver)615     public void uninstall(@NonNull VersionedPackage versionedPackage, @DeleteFlags int flags,
616             @NonNull IntentSender statusReceiver) {
617         Preconditions.checkNotNull(versionedPackage, "versionedPackage cannot be null");
618         try {
619             mInstaller.uninstall(versionedPackage, mInstallerPackageName,
620                     flags, statusReceiver, mUserId);
621         } catch (RemoteException e) {
622             throw e.rethrowFromSystemServer();
623         }
624     }
625 
626     /**
627      * Install the given package, which already exists on the device, for the user for which this
628      * installer was created.
629      *
630      * <p>This will
631      * {@link PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set) whitelist
632      * all restricted permissions}.
633      *
634      * @param packageName The package to install.
635      * @param installReason Reason for install.
636      * @param statusReceiver Where to deliver the result.
637      */
638     @RequiresPermission(allOf = {
639             Manifest.permission.INSTALL_PACKAGES,
640             Manifest.permission.INSTALL_EXISTING_PACKAGES})
installExistingPackage(@onNull String packageName, @InstallReason int installReason, @Nullable IntentSender statusReceiver)641     public void installExistingPackage(@NonNull String packageName,
642             @InstallReason int installReason,
643             @Nullable IntentSender statusReceiver) {
644         Preconditions.checkNotNull(packageName, "packageName cannot be null");
645         try {
646             mInstaller.installExistingPackage(packageName,
647                     PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS, installReason,
648                     statusReceiver, mUserId, null);
649         } catch (RemoteException e) {
650             throw e.rethrowFromSystemServer();
651         }
652     }
653 
654 
655     /** {@hide} */
656     @SystemApi
657     @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
setPermissionsResult(int sessionId, boolean accepted)658     public void setPermissionsResult(int sessionId, boolean accepted) {
659         try {
660             mInstaller.setPermissionsResult(sessionId, accepted);
661         } catch (RemoteException e) {
662             throw e.rethrowFromSystemServer();
663         }
664     }
665 
666     /**
667      * Events for observing session lifecycle.
668      * <p>
669      * A typical session lifecycle looks like this:
670      * <ul>
671      * <li>An installer creates a session to indicate pending app delivery. All
672      * install details are available at this point.
673      * <li>The installer opens the session to deliver APK data. Note that a
674      * session may be opened and closed multiple times as network connectivity
675      * changes. The installer may deliver periodic progress updates.
676      * <li>The installer commits or abandons the session, resulting in the
677      * session being finished.
678      * </ul>
679      */
680     public static abstract class SessionCallback {
681         /**
682          * New session has been created. Details about the session can be
683          * obtained from {@link PackageInstaller#getSessionInfo(int)}.
684          */
onCreated(int sessionId)685         public abstract void onCreated(int sessionId);
686 
687         /**
688          * Badging details for an existing session has changed. For example, the
689          * app icon or label has been updated.
690          */
onBadgingChanged(int sessionId)691         public abstract void onBadgingChanged(int sessionId);
692 
693         /**
694          * Active state for session has been changed.
695          * <p>
696          * A session is considered active whenever there is ongoing forward
697          * progress being made, such as the installer holding an open
698          * {@link Session} instance while streaming data into place, or the
699          * system optimizing code as the result of
700          * {@link Session#commit(IntentSender)}.
701          * <p>
702          * If the installer closes the {@link Session} without committing, the
703          * session is considered inactive until the installer opens the session
704          * again.
705          */
onActiveChanged(int sessionId, boolean active)706         public abstract void onActiveChanged(int sessionId, boolean active);
707 
708         /**
709          * Progress for given session has been updated.
710          * <p>
711          * Note that this progress may not directly correspond to the value
712          * reported by
713          * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
714          * system may carve out a portion of the overall progress to represent
715          * its own internal installation work.
716          */
onProgressChanged(int sessionId, float progress)717         public abstract void onProgressChanged(int sessionId, float progress);
718 
719         /**
720          * Session has completely finished, either with success or failure.
721          */
onFinished(int sessionId, boolean success)722         public abstract void onFinished(int sessionId, boolean success);
723     }
724 
725     /** {@hide} */
726     static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub {
727         private static final int MSG_SESSION_CREATED = 1;
728         private static final int MSG_SESSION_BADGING_CHANGED = 2;
729         private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
730         private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
731         private static final int MSG_SESSION_FINISHED = 5;
732 
733         final SessionCallback mCallback;
734         final Executor mExecutor;
735 
SessionCallbackDelegate(SessionCallback callback, Executor executor)736         SessionCallbackDelegate(SessionCallback callback, Executor executor) {
737             mCallback = callback;
738             mExecutor = executor;
739         }
740 
741         @Override
onSessionCreated(int sessionId)742         public void onSessionCreated(int sessionId) {
743             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onCreated, mCallback,
744                     sessionId).recycleOnUse());
745         }
746 
747         @Override
onSessionBadgingChanged(int sessionId)748         public void onSessionBadgingChanged(int sessionId) {
749             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onBadgingChanged,
750                     mCallback, sessionId).recycleOnUse());
751         }
752 
753         @Override
onSessionActiveChanged(int sessionId, boolean active)754         public void onSessionActiveChanged(int sessionId, boolean active) {
755             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onActiveChanged,
756                     mCallback, sessionId, active).recycleOnUse());
757         }
758 
759         @Override
onSessionProgressChanged(int sessionId, float progress)760         public void onSessionProgressChanged(int sessionId, float progress) {
761             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onProgressChanged,
762                     mCallback, sessionId, progress).recycleOnUse());
763         }
764 
765         @Override
onSessionFinished(int sessionId, boolean success)766         public void onSessionFinished(int sessionId, boolean success) {
767             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onFinished,
768                     mCallback, sessionId, success).recycleOnUse());
769         }
770     }
771 
772     /** {@hide} */
773     @Deprecated
addSessionCallback(@onNull SessionCallback callback)774     public void addSessionCallback(@NonNull SessionCallback callback) {
775         registerSessionCallback(callback);
776     }
777 
778     /**
779      * Register to watch for session lifecycle events. No special permissions
780      * are required to watch for these events.
781      */
registerSessionCallback(@onNull SessionCallback callback)782     public void registerSessionCallback(@NonNull SessionCallback callback) {
783         registerSessionCallback(callback, new Handler());
784     }
785 
786     /** {@hide} */
787     @Deprecated
addSessionCallback(@onNull SessionCallback callback, @NonNull Handler handler)788     public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
789         registerSessionCallback(callback, handler);
790     }
791 
792     /**
793      * Register to watch for session lifecycle events. No special permissions
794      * are required to watch for these events.
795      *
796      * @param handler to dispatch callback events through, otherwise uses
797      *            calling thread.
798      */
registerSessionCallback(@onNull SessionCallback callback, @NonNull Handler handler)799     public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
800         synchronized (mDelegates) {
801             final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
802                     new HandlerExecutor(handler));
803             try {
804                 mInstaller.registerCallback(delegate, mUserId);
805             } catch (RemoteException e) {
806                 throw e.rethrowFromSystemServer();
807             }
808             mDelegates.add(delegate);
809         }
810     }
811 
812     /** {@hide} */
813     @Deprecated
removeSessionCallback(@onNull SessionCallback callback)814     public void removeSessionCallback(@NonNull SessionCallback callback) {
815         unregisterSessionCallback(callback);
816     }
817 
818     /**
819      * Unregister a previously registered callback.
820      */
unregisterSessionCallback(@onNull SessionCallback callback)821     public void unregisterSessionCallback(@NonNull SessionCallback callback) {
822         synchronized (mDelegates) {
823             for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
824                 final SessionCallbackDelegate delegate = i.next();
825                 if (delegate.mCallback == callback) {
826                     try {
827                         mInstaller.unregisterCallback(delegate);
828                     } catch (RemoteException e) {
829                         throw e.rethrowFromSystemServer();
830                     }
831                     i.remove();
832                 }
833             }
834         }
835     }
836 
837     /**
838      * An installation that is being actively staged. For an install to succeed,
839      * all existing and new packages must have identical package names, version
840      * codes, and signing certificates.
841      * <p>
842      * A session may contain any number of split packages. If the application
843      * does not yet exist, this session must include a base package.
844      * <p>
845      * If an APK included in this session is already defined by the existing
846      * installation (for example, the same split name), the APK in this session
847      * will replace the existing APK.
848      * <p>
849      * In such a case that multiple packages need to be committed simultaneously,
850      * multiple sessions can be referenced by a single multi-package session.
851      * This session is created with no package name and calling
852      * {@link SessionParams#setMultiPackage()}. The individual session IDs can be
853      * added with {@link #addChildSessionId(int)} and commit of the multi-package
854      * session will result in all child sessions being committed atomically.
855      */
856     public static class Session implements Closeable {
857         /** {@hide} */
858         protected final IPackageInstallerSession mSession;
859 
860         /** {@hide} */
Session(IPackageInstallerSession session)861         public Session(IPackageInstallerSession session) {
862             mSession = session;
863         }
864 
865         /** {@hide} */
866         @Deprecated
setProgress(float progress)867         public void setProgress(float progress) {
868             setStagingProgress(progress);
869         }
870 
871         /**
872          * Set current progress of staging this session. Valid values are
873          * anywhere between 0 and 1.
874          * <p>
875          * Note that this progress may not directly correspond to the value
876          * reported by {@link SessionCallback#onProgressChanged(int, float)}, as
877          * the system may carve out a portion of the overall progress to
878          * represent its own internal installation work.
879          */
setStagingProgress(float progress)880         public void setStagingProgress(float progress) {
881             try {
882                 mSession.setClientProgress(progress);
883             } catch (RemoteException e) {
884                 throw e.rethrowFromSystemServer();
885             }
886         }
887 
888         /** {@hide} */
889         @UnsupportedAppUsage
addProgress(float progress)890         public void addProgress(float progress) {
891             try {
892                 mSession.addClientProgress(progress);
893             } catch (RemoteException e) {
894                 throw e.rethrowFromSystemServer();
895             }
896         }
897 
898         /**
899          * Open a stream to write an APK file into the session.
900          * <p>
901          * The returned stream will start writing data at the requested offset
902          * in the underlying file, which can be used to resume a partially
903          * written file. If a valid file length is specified, the system will
904          * preallocate the underlying disk space to optimize placement on disk.
905          * It's strongly recommended to provide a valid file length when known.
906          * <p>
907          * You can write data into the returned stream, optionally call
908          * {@link #fsync(OutputStream)} as needed to ensure bytes have been
909          * persisted to disk, and then close when finished. All streams must be
910          * closed before calling {@link #commit(IntentSender)}.
911          *
912          * @param name arbitrary, unique name of your choosing to identify the
913          *            APK being written. You can open a file again for
914          *            additional writes (such as after a reboot) by using the
915          *            same name. This name is only meaningful within the context
916          *            of a single install session.
917          * @param offsetBytes offset into the file to begin writing at, or 0 to
918          *            start at the beginning of the file.
919          * @param lengthBytes total size of the file being written, used to
920          *            preallocate the underlying disk space, or -1 if unknown.
921          *            The system may clear various caches as needed to allocate
922          *            this space.
923          * @throws IOException if trouble opening the file for writing, such as
924          *             lack of disk space or unavailable media.
925          * @throws SecurityException if called after the session has been
926          *             sealed or abandoned
927          */
openWrite(@onNull String name, long offsetBytes, long lengthBytes)928         public @NonNull OutputStream openWrite(@NonNull String name, long offsetBytes,
929                 long lengthBytes) throws IOException {
930             try {
931                 if (ENABLE_REVOCABLE_FD) {
932                     return new ParcelFileDescriptor.AutoCloseOutputStream(
933                             mSession.openWrite(name, offsetBytes, lengthBytes));
934                 } else {
935                     final ParcelFileDescriptor clientSocket = mSession.openWrite(name,
936                             offsetBytes, lengthBytes);
937                     return new FileBridge.FileBridgeOutputStream(clientSocket);
938                 }
939             } catch (RuntimeException e) {
940                 ExceptionUtils.maybeUnwrapIOException(e);
941                 throw e;
942             } catch (RemoteException e) {
943                 throw e.rethrowFromSystemServer();
944             }
945         }
946 
947         /** {@hide} */
write(@onNull String name, long offsetBytes, long lengthBytes, @NonNull ParcelFileDescriptor fd)948         public void write(@NonNull String name, long offsetBytes, long lengthBytes,
949                 @NonNull ParcelFileDescriptor fd) throws IOException {
950             try {
951                 mSession.write(name, offsetBytes, lengthBytes, fd);
952             } catch (RuntimeException e) {
953                 ExceptionUtils.maybeUnwrapIOException(e);
954                 throw e;
955             } catch (RemoteException e) {
956                 throw e.rethrowFromSystemServer();
957             }
958         }
959 
960         /**
961          * Ensure that any outstanding data for given stream has been committed
962          * to disk. This is only valid for streams returned from
963          * {@link #openWrite(String, long, long)}.
964          */
fsync(@onNull OutputStream out)965         public void fsync(@NonNull OutputStream out) throws IOException {
966             if (ENABLE_REVOCABLE_FD) {
967                 if (out instanceof ParcelFileDescriptor.AutoCloseOutputStream) {
968                     try {
969                         Os.fsync(((ParcelFileDescriptor.AutoCloseOutputStream) out).getFD());
970                     } catch (ErrnoException e) {
971                         throw e.rethrowAsIOException();
972                     }
973                 } else {
974                     throw new IllegalArgumentException("Unrecognized stream");
975                 }
976             } else {
977                 if (out instanceof FileBridge.FileBridgeOutputStream) {
978                     ((FileBridge.FileBridgeOutputStream) out).fsync();
979                 } else {
980                     throw new IllegalArgumentException("Unrecognized stream");
981                 }
982             }
983         }
984 
985         /**
986          * Return all APK names contained in this session.
987          * <p>
988          * This returns all names which have been previously written through
989          * {@link #openWrite(String, long, long)} as part of this session.
990          *
991          * @throws SecurityException if called after the session has been
992          *             committed or abandoned.
993          */
getNames()994         public @NonNull String[] getNames() throws IOException {
995             try {
996                 return mSession.getNames();
997             } catch (RuntimeException e) {
998                 ExceptionUtils.maybeUnwrapIOException(e);
999                 throw e;
1000             } catch (RemoteException e) {
1001                 throw e.rethrowFromSystemServer();
1002             }
1003         }
1004 
1005         /**
1006          * Open a stream to read an APK file from the session.
1007          * <p>
1008          * This is only valid for names which have been previously written
1009          * through {@link #openWrite(String, long, long)} as part of this
1010          * session. For example, this stream may be used to calculate a
1011          * {@link MessageDigest} of a written APK before committing.
1012          *
1013          * @throws SecurityException if called after the session has been
1014          *             committed or abandoned.
1015          */
openRead(@onNull String name)1016         public @NonNull InputStream openRead(@NonNull String name) throws IOException {
1017             try {
1018                 final ParcelFileDescriptor pfd = mSession.openRead(name);
1019                 return new ParcelFileDescriptor.AutoCloseInputStream(pfd);
1020             } catch (RuntimeException e) {
1021                 ExceptionUtils.maybeUnwrapIOException(e);
1022                 throw e;
1023             } catch (RemoteException e) {
1024                 throw e.rethrowFromSystemServer();
1025             }
1026         }
1027 
1028         /**
1029          * Removes a split.
1030          * <p>
1031          * Split removals occur prior to adding new APKs. If upgrading a feature
1032          * split, it is not expected nor desirable to remove the split prior to
1033          * upgrading.
1034          * <p>
1035          * When split removal is bundled with new APKs, the packageName must be
1036          * identical.
1037          */
removeSplit(@onNull String splitName)1038         public void removeSplit(@NonNull String splitName) throws IOException {
1039             try {
1040                 mSession.removeSplit(splitName);
1041             } catch (RuntimeException e) {
1042                 ExceptionUtils.maybeUnwrapIOException(e);
1043                 throw e;
1044             } catch (RemoteException e) {
1045                 throw e.rethrowFromSystemServer();
1046             }
1047         }
1048 
1049         /**
1050          * Attempt to commit everything staged in this session. This may require
1051          * user intervention, and so it may not happen immediately. The final
1052          * result of the commit will be reported through the given callback.
1053          * <p>
1054          * Once this method is called, the session is sealed and no additional
1055          * mutations may be performed on the session. If the device reboots
1056          * before the session has been finalized, you may commit the session again.
1057          * <p>
1058          * If the installer is the device owner or the affiliated profile owner, there will be no
1059          * user intervention.
1060          *
1061          * @param statusReceiver Called when the state of the session changes. Intents
1062          *                       sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
1063          *                       individual status codes on how to handle them.
1064          *
1065          * @throws SecurityException if streams opened through
1066          *             {@link #openWrite(String, long, long)} are still open.
1067          *
1068          * @see android.app.admin.DevicePolicyManager
1069          */
commit(@onNull IntentSender statusReceiver)1070         public void commit(@NonNull IntentSender statusReceiver) {
1071             try {
1072                 mSession.commit(statusReceiver, false);
1073             } catch (RemoteException e) {
1074                 throw e.rethrowFromSystemServer();
1075             }
1076         }
1077 
1078         /**
1079          * Attempt to commit a session that has been {@link #transfer(String) transferred}.
1080          *
1081          * <p>If the device reboots before the session has been finalized, you may commit the
1082          * session again.
1083          *
1084          * <p>The caller of this method is responsible to ensure the safety of the session. As the
1085          * session was created by another - usually less trusted - app, it is paramount that before
1086          * committing <u>all</u> public and system {@link SessionInfo properties of the session}
1087          * and <u>all</u> {@link #openRead(String) APKs} are verified by the caller. It might happen
1088          * that new properties are added to the session with a new API revision. In this case the
1089          * callers need to be updated.
1090          *
1091          * @param statusReceiver Called when the state of the session changes. Intents
1092          *                       sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
1093          *                       individual status codes on how to handle them.
1094          *
1095          * @hide
1096          */
1097         @SystemApi
1098         @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
commitTransferred(@onNull IntentSender statusReceiver)1099         public void commitTransferred(@NonNull IntentSender statusReceiver) {
1100             try {
1101                 mSession.commit(statusReceiver, true);
1102             } catch (RemoteException e) {
1103                 throw e.rethrowFromSystemServer();
1104             }
1105         }
1106 
1107         /**
1108          * Transfer the session to a new owner.
1109          * <p>
1110          * Only sessions that update the installing app can be transferred.
1111          * <p>
1112          * After the transfer to a package with a different uid all method calls on the session
1113          * will cause {@link SecurityException}s.
1114          * <p>
1115          * Once this method is called, the session is sealed and no additional mutations beside
1116          * committing it may be performed on the session.
1117          *
1118          * @param packageName The package of the new owner. Needs to hold the INSTALL_PACKAGES
1119          *                    permission.
1120          *
1121          * @throws PackageManager.NameNotFoundException if the new owner could not be found.
1122          * @throws SecurityException if called after the session has been committed or abandoned.
1123          * @throws SecurityException if the session does not update the original installer
1124          * @throws SecurityException if streams opened through
1125          *                           {@link #openWrite(String, long, long) are still open.
1126          */
transfer(@onNull String packageName)1127         public void transfer(@NonNull String packageName)
1128                 throws PackageManager.NameNotFoundException {
1129             Preconditions.checkNotNull(packageName);
1130 
1131             try {
1132                 mSession.transfer(packageName);
1133             } catch (ParcelableException e) {
1134                 e.maybeRethrow(PackageManager.NameNotFoundException.class);
1135                 throw new RuntimeException(e);
1136             } catch (RemoteException e) {
1137                 throw e.rethrowFromSystemServer();
1138             }
1139         }
1140 
1141         /**
1142          * Release this session object. You can open the session again if it
1143          * hasn't been finalized.
1144          */
1145         @Override
close()1146         public void close() {
1147             try {
1148                 mSession.close();
1149             } catch (RemoteException e) {
1150                 throw e.rethrowFromSystemServer();
1151             }
1152         }
1153 
1154         /**
1155          * Completely abandon this session, destroying all staged data and
1156          * rendering it invalid. Abandoned sessions will be reported to
1157          * {@link SessionCallback} listeners as failures. This is equivalent to
1158          * opening the session and calling {@link Session#abandon()}.
1159          */
abandon()1160         public void abandon() {
1161             try {
1162                 mSession.abandon();
1163             } catch (RemoteException e) {
1164                 throw e.rethrowFromSystemServer();
1165             }
1166         }
1167 
1168         /**
1169          * @return {@code true} if this session will commit more than one package when it is
1170          * committed.
1171          */
isMultiPackage()1172         public boolean isMultiPackage() {
1173             try {
1174                 return mSession.isMultiPackage();
1175             } catch (RemoteException e) {
1176                 throw e.rethrowFromSystemServer();
1177             }
1178         }
1179 
1180         /**
1181          * @return {@code true} if this session will be staged and applied at next reboot.
1182          */
isStaged()1183         public boolean isStaged() {
1184             try {
1185                 return mSession.isStaged();
1186             } catch (RemoteException e) {
1187                 throw e.rethrowFromSystemServer();
1188             }
1189         }
1190 
1191         /**
1192          * @return the session ID of the multi-package session that this belongs to or
1193          * {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session.
1194          */
getParentSessionId()1195         public int getParentSessionId() {
1196             try {
1197                 return mSession.getParentSessionId();
1198             } catch (RemoteException e) {
1199                 throw e.rethrowFromSystemServer();
1200             }
1201         }
1202 
1203         /**
1204          * @return the set of session IDs that will be committed atomically when this session is
1205          * committed if this is a multi-package session or null if none exist.
1206          */
1207         @NonNull
getChildSessionIds()1208         public int[] getChildSessionIds() {
1209             try {
1210                 return mSession.getChildSessionIds();
1211             } catch (RemoteException e) {
1212                 throw e.rethrowFromSystemServer();
1213             }
1214         }
1215 
1216         /**
1217          * Adds a session ID to the set of sessions that will be committed atomically
1218          * when this session is committed.
1219          *
1220          * <p>If the parent is staged or has rollback enabled, all children must have
1221          * the same properties.
1222          *
1223          * @param sessionId the session ID to add to this multi-package session.
1224          */
addChildSessionId(int sessionId)1225         public void addChildSessionId(int sessionId) {
1226             try {
1227                 mSession.addChildSessionId(sessionId);
1228             } catch (RemoteException e) {
1229                 e.rethrowFromSystemServer();
1230             }
1231         }
1232 
1233         /**
1234          * Removes a session ID from the set of sessions that will be committed
1235          * atomically when this session is committed.
1236          *
1237          * @param sessionId the session ID to remove from this multi-package session.
1238          */
removeChildSessionId(int sessionId)1239         public void removeChildSessionId(int sessionId) {
1240             try {
1241                 mSession.removeChildSessionId(sessionId);
1242             } catch (RemoteException e) {
1243                 e.rethrowFromSystemServer();
1244             }
1245         }
1246     }
1247 
1248     /**
1249      * Parameters for creating a new {@link PackageInstaller.Session}.
1250      */
1251     public static class SessionParams implements Parcelable {
1252 
1253         /** {@hide} */
1254         public static final int MODE_INVALID = -1;
1255 
1256         /**
1257          * Mode for an install session whose staged APKs should fully replace any
1258          * existing APKs for the target app.
1259          */
1260         public static final int MODE_FULL_INSTALL = 1;
1261 
1262         /**
1263          * Mode for an install session that should inherit any existing APKs for the
1264          * target app, unless they have been explicitly overridden (based on split
1265          * name) by the session. For example, this can be used to add one or more
1266          * split APKs to an existing installation.
1267          * <p>
1268          * If there are no existing APKs for the target app, this behaves like
1269          * {@link #MODE_FULL_INSTALL}.
1270          */
1271         public static final int MODE_INHERIT_EXISTING = 2;
1272 
1273         /**
1274          * Special constant to refer to all restricted permissions.
1275          */
1276         public static final @NonNull Set<String> RESTRICTED_PERMISSIONS_ALL = new ArraySet<>();
1277 
1278         /** {@hide} */
1279         public static final int UID_UNKNOWN = -1;
1280 
1281         /** {@hide} */
1282         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1283         public int mode = MODE_INVALID;
1284         /** {@hide} */
1285         @UnsupportedAppUsage
1286         public int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
1287         /** {@hide} */
1288         public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
1289         /** {@hide} */
1290         public @InstallReason int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
1291         /** {@hide} */
1292         @UnsupportedAppUsage
1293         public long sizeBytes = -1;
1294         /** {@hide} */
1295         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1296         public String appPackageName;
1297         /** {@hide} */
1298         @UnsupportedAppUsage
1299         public Bitmap appIcon;
1300         /** {@hide} */
1301         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1302         public String appLabel;
1303         /** {@hide} */
1304         public long appIconLastModified = -1;
1305         /** {@hide} */
1306         public Uri originatingUri;
1307         /** {@hide} */
1308         @UnsupportedAppUsage
1309         public int originatingUid = UID_UNKNOWN;
1310         /** {@hide} */
1311         public Uri referrerUri;
1312         /** {@hide} */
1313         public String abiOverride;
1314         /** {@hide} */
1315         public String volumeUuid;
1316         /** {@hide} */
1317         public String[] grantedRuntimePermissions;
1318         /** {@hide} */
1319         public List<String> whitelistedRestrictedPermissions;
1320         /** {@hide} */
1321         public String installerPackageName;
1322         /** {@hide} */
1323         public boolean isMultiPackage;
1324         /** {@hide} */
1325         public boolean isStaged;
1326         /** {@hide} */
1327         public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST;
1328 
1329         /**
1330          * Construct parameters for a new package install session.
1331          *
1332          * @param mode one of {@link #MODE_FULL_INSTALL} or
1333          *            {@link #MODE_INHERIT_EXISTING} describing how the session
1334          *            should interact with an existing app.
1335          */
SessionParams(int mode)1336         public SessionParams(int mode) {
1337             this.mode = mode;
1338         }
1339 
1340         /** {@hide} */
SessionParams(Parcel source)1341         public SessionParams(Parcel source) {
1342             mode = source.readInt();
1343             installFlags = source.readInt();
1344             installLocation = source.readInt();
1345             installReason = source.readInt();
1346             sizeBytes = source.readLong();
1347             appPackageName = source.readString();
1348             appIcon = source.readParcelable(null);
1349             appLabel = source.readString();
1350             originatingUri = source.readParcelable(null);
1351             originatingUid = source.readInt();
1352             referrerUri = source.readParcelable(null);
1353             abiOverride = source.readString();
1354             volumeUuid = source.readString();
1355             grantedRuntimePermissions = source.readStringArray();
1356             whitelistedRestrictedPermissions = source.createStringArrayList();
1357             installerPackageName = source.readString();
1358             isMultiPackage = source.readBoolean();
1359             isStaged = source.readBoolean();
1360             requiredInstalledVersionCode = source.readLong();
1361         }
1362 
1363         /** {@hide} */
copy()1364         public SessionParams copy() {
1365             SessionParams ret = new SessionParams(mode);
1366             ret.installFlags = installFlags;
1367             ret.installLocation = installLocation;
1368             ret.installReason = installReason;
1369             ret.sizeBytes = sizeBytes;
1370             ret.appPackageName = appPackageName;
1371             ret.appIcon = appIcon;  // not a copy.
1372             ret.appLabel = appLabel;
1373             ret.originatingUri = originatingUri;  // not a copy, but immutable.
1374             ret.originatingUid = originatingUid;
1375             ret.referrerUri = referrerUri;  // not a copy, but immutable.
1376             ret.abiOverride = abiOverride;
1377             ret.volumeUuid = volumeUuid;
1378             ret.grantedRuntimePermissions = grantedRuntimePermissions;
1379             ret.whitelistedRestrictedPermissions = whitelistedRestrictedPermissions;
1380             ret.installerPackageName = installerPackageName;
1381             ret.isMultiPackage = isMultiPackage;
1382             ret.isStaged = isStaged;
1383             ret.requiredInstalledVersionCode = requiredInstalledVersionCode;
1384             return ret;
1385         }
1386 
1387         /**
1388          * Check if there are hidden options set.
1389          *
1390          * <p>Hidden options are those options that cannot be verified via public or system-api
1391          * methods on {@link SessionInfo}.
1392          *
1393          * @return {@code true} if any hidden option is set.
1394          *
1395          * @hide
1396          */
areHiddenOptionsSet()1397         public boolean areHiddenOptionsSet() {
1398             return (installFlags & (PackageManager.INSTALL_REQUEST_DOWNGRADE
1399                     | PackageManager.INSTALL_ALLOW_DOWNGRADE
1400                     | PackageManager.INSTALL_DONT_KILL_APP
1401                     | PackageManager.INSTALL_INSTANT_APP
1402                     | PackageManager.INSTALL_FULL_APP
1403                     | PackageManager.INSTALL_VIRTUAL_PRELOAD
1404                     | PackageManager.INSTALL_ALLOCATE_AGGRESSIVE)) != installFlags
1405                     || abiOverride != null || volumeUuid != null;
1406         }
1407 
1408         /**
1409          * Provide value of {@link PackageInfo#installLocation}, which may be used
1410          * to determine where the app will be staged. Defaults to
1411          * {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}.
1412          */
setInstallLocation(int installLocation)1413         public void setInstallLocation(int installLocation) {
1414             this.installLocation = installLocation;
1415         }
1416 
1417         /**
1418          * Optionally indicate the total size (in bytes) of all APKs that will be
1419          * delivered in this session. The system may use this to ensure enough disk
1420          * space exists before proceeding, or to estimate container size for
1421          * installations living on external storage.
1422          *
1423          * @see PackageInfo#INSTALL_LOCATION_AUTO
1424          * @see PackageInfo#INSTALL_LOCATION_PREFER_EXTERNAL
1425          */
setSize(long sizeBytes)1426         public void setSize(long sizeBytes) {
1427             this.sizeBytes = sizeBytes;
1428         }
1429 
1430         /**
1431          * Optionally set the package name of the app being installed. It's strongly
1432          * recommended that you provide this value when known, so that observers can
1433          * communicate installing apps to users.
1434          * <p>
1435          * If the APKs staged in the session aren't consistent with this package
1436          * name, the install will fail. Regardless of this value, all APKs in the
1437          * app must have the same package name.
1438          */
setAppPackageName(@ullable String appPackageName)1439         public void setAppPackageName(@Nullable String appPackageName) {
1440             this.appPackageName = appPackageName;
1441         }
1442 
1443         /**
1444          * Optionally set an icon representing the app being installed. This should
1445          * be roughly {@link ActivityManager#getLauncherLargeIconSize()} in both
1446          * dimensions.
1447          */
setAppIcon(@ullable Bitmap appIcon)1448         public void setAppIcon(@Nullable Bitmap appIcon) {
1449             this.appIcon = appIcon;
1450         }
1451 
1452         /**
1453          * Optionally set a label representing the app being installed.
1454          */
setAppLabel(@ullable CharSequence appLabel)1455         public void setAppLabel(@Nullable CharSequence appLabel) {
1456             this.appLabel = (appLabel != null) ? appLabel.toString() : null;
1457         }
1458 
1459         /**
1460          * Optionally set the URI where this package was downloaded from. This is
1461          * informational and may be used as a signal for anti-malware purposes.
1462          *
1463          * @see Intent#EXTRA_ORIGINATING_URI
1464          */
setOriginatingUri(@ullable Uri originatingUri)1465         public void setOriginatingUri(@Nullable Uri originatingUri) {
1466             this.originatingUri = originatingUri;
1467         }
1468 
1469         /**
1470          * Sets the UID that initiated the package installation. This is informational
1471          * and may be used as a signal for anti-malware purposes.
1472          */
setOriginatingUid(int originatingUid)1473         public void setOriginatingUid(int originatingUid) {
1474             this.originatingUid = originatingUid;
1475         }
1476 
1477         /**
1478          * Optionally set the URI that referred you to install this package. This is
1479          * informational and may be used as a signal for anti-malware purposes.
1480          *
1481          * @see Intent#EXTRA_REFERRER
1482          */
setReferrerUri(@ullable Uri referrerUri)1483         public void setReferrerUri(@Nullable Uri referrerUri) {
1484             this.referrerUri = referrerUri;
1485         }
1486 
1487         /**
1488          * Sets which runtime permissions to be granted to the package at installation.
1489          *
1490          * @param permissions The permissions to grant or null to grant all runtime
1491          *     permissions.
1492          *
1493          * @hide
1494          */
1495         @TestApi
1496         @SystemApi
1497         @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS)
setGrantedRuntimePermissions(String[] permissions)1498         public void setGrantedRuntimePermissions(String[] permissions) {
1499             installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
1500             this.grantedRuntimePermissions = permissions;
1501         }
1502 
1503         /**
1504          * Sets which restricted permissions to be whitelisted for the app. Whitelisting
1505          * is not granting the permissions, rather it allows the app to hold permissions
1506          * which are otherwise restricted. Whitelisting a non restricted permission has
1507          * no effect.
1508          *
1509          * <p> Permissions can be hard restricted which means that the app cannot hold
1510          * them or soft restricted where the app can hold the permission but in a weaker
1511          * form. Whether a permission is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard
1512          * restricted} or {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted}
1513          * depends on the permission declaration. Whitelisting a hard restricted permission
1514          * allows the app to hold that permission and whitelisting a soft restricted
1515          * permission allows the app to hold the permission in its full, unrestricted form.
1516          *
1517          * <p> Permissions can also be immutably restricted which means that the whitelist
1518          * state of the permission can be determined only at install time and cannot be
1519          * changed on updated or at a later point via the package manager APIs.
1520          *
1521          * <p>Initially, all restricted permissions are whitelisted but you can change
1522          * which ones are whitelisted by calling this method or the corresponding ones
1523          * on the {@link PackageManager}.
1524          *
1525          * @see PackageManager#addWhitelistedRestrictedPermission(String, String, int)
1526          * @see PackageManager#removeWhitelistedRestrictedPermission(String, String, int)
1527          */
setWhitelistedRestrictedPermissions(@ullable Set<String> permissions)1528         public void setWhitelistedRestrictedPermissions(@Nullable Set<String> permissions) {
1529             if (permissions == RESTRICTED_PERMISSIONS_ALL) {
1530                 installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
1531                 whitelistedRestrictedPermissions = null;
1532             } else {
1533                 installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
1534                 whitelistedRestrictedPermissions = (permissions != null)
1535                         ? new ArrayList<>(permissions) : null;
1536             }
1537         }
1538 
1539         /**
1540          * Request that rollbacks be enabled or disabled for the given upgrade.
1541          *
1542          * <p>If the parent session is staged or has rollback enabled, all children sessions
1543          * must have the same properties.
1544          *
1545          * @param enable set to {@code true} to enable, {@code false} to disable
1546          * @hide
1547          */
1548         @SystemApi @TestApi
setEnableRollback(boolean enable)1549         public void setEnableRollback(boolean enable) {
1550             if (enable) {
1551                 installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
1552             } else {
1553                 installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
1554             }
1555         }
1556 
1557         /**
1558          * @deprecated use {@link #setRequestDowngrade(boolean)}.
1559          * {@hide}
1560          */
1561         @SystemApi
1562         @Deprecated
setAllowDowngrade(boolean allowDowngrade)1563         public void setAllowDowngrade(boolean allowDowngrade) {
1564             setRequestDowngrade(allowDowngrade);
1565         }
1566 
1567         /** {@hide} */
1568         @SystemApi
setRequestDowngrade(boolean requestDowngrade)1569         public void setRequestDowngrade(boolean requestDowngrade) {
1570             if (requestDowngrade) {
1571                 installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
1572             } else {
1573                 installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE;
1574             }
1575         }
1576 
1577         /**
1578          * Require the given version of the package be installed.
1579          * The install will only be allowed if the existing version code of
1580          * the package installed on the device matches the given version code.
1581          * Use {@link * PackageManager#VERSION_CODE_HIGHEST} to allow
1582          * installation regardless of the currently installed package version.
1583          *
1584          * @hide
1585          */
setRequiredInstalledVersionCode(long versionCode)1586         public void setRequiredInstalledVersionCode(long versionCode) {
1587             requiredInstalledVersionCode = versionCode;
1588         }
1589 
1590         /** {@hide} */
setInstallFlagsForcePermissionPrompt()1591         public void setInstallFlagsForcePermissionPrompt() {
1592             installFlags |= PackageManager.INSTALL_FORCE_PERMISSION_PROMPT;
1593         }
1594 
1595         /** {@hide} */
1596         @SystemApi
setDontKillApp(boolean dontKillApp)1597         public void setDontKillApp(boolean dontKillApp) {
1598             if (dontKillApp) {
1599                 installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
1600             } else {
1601                 installFlags &= ~PackageManager.INSTALL_DONT_KILL_APP;
1602             }
1603         }
1604 
1605         /** {@hide} */
1606         @SystemApi
setInstallAsInstantApp(boolean isInstantApp)1607         public void setInstallAsInstantApp(boolean isInstantApp) {
1608             if (isInstantApp) {
1609                 installFlags |= PackageManager.INSTALL_INSTANT_APP;
1610                 installFlags &= ~PackageManager.INSTALL_FULL_APP;
1611             } else {
1612                 installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
1613                 installFlags |= PackageManager.INSTALL_FULL_APP;
1614             }
1615         }
1616 
1617         /**
1618          * Sets the install as a virtual preload. Will only have effect when called
1619          * by the verifier.
1620          * {@hide}
1621          */
1622         @SystemApi
setInstallAsVirtualPreload()1623         public void setInstallAsVirtualPreload() {
1624             installFlags |= PackageManager.INSTALL_VIRTUAL_PRELOAD;
1625         }
1626 
1627         /**
1628          * Set the reason for installing this package.
1629          * <p>
1630          * The install reason should be a pre-defined integer. The behavior is
1631          * undefined if other values are used.
1632          *
1633          * @see PackageManager#INSTALL_REASON_UNKNOWN
1634          * @see PackageManager#INSTALL_REASON_POLICY
1635          * @see PackageManager#INSTALL_REASON_DEVICE_RESTORE
1636          * @see PackageManager#INSTALL_REASON_DEVICE_SETUP
1637          * @see PackageManager#INSTALL_REASON_USER
1638          */
setInstallReason(@nstallReason int installReason)1639         public void setInstallReason(@InstallReason int installReason) {
1640             this.installReason = installReason;
1641         }
1642 
1643         /** {@hide} */
1644         @SystemApi
1645         @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE)
setAllocateAggressive(boolean allocateAggressive)1646         public void setAllocateAggressive(boolean allocateAggressive) {
1647             if (allocateAggressive) {
1648                 installFlags |= PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
1649             } else {
1650                 installFlags &= ~PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
1651             }
1652         }
1653 
1654         /**
1655          * Set the installer package for the app.
1656          *
1657          * By default this is the app that created the {@link PackageInstaller} object.
1658          *
1659          * @param installerPackageName name of the installer package
1660          * {@hide}
1661          */
setInstallerPackageName(String installerPackageName)1662         public void setInstallerPackageName(String installerPackageName) {
1663             this.installerPackageName = installerPackageName;
1664         }
1665 
1666         /**
1667          * Set this session to be the parent of a multi-package install.
1668          *
1669          * A multi-package install session contains no APKs and only references other install
1670          * sessions via ID. When a multi-package session is committed, all of its children
1671          * are committed to the system in an atomic manner. If any children fail to install,
1672          * all of them do, including the multi-package session.
1673          */
setMultiPackage()1674         public void setMultiPackage() {
1675             this.isMultiPackage = true;
1676         }
1677 
1678         /**
1679          * Set this session to be staged to be installed at reboot.
1680          *
1681          * Staged sessions are scheduled to be installed at next reboot. Staged sessions can also be
1682          * multi-package. In that case, if any of the children sessions fail to install at reboot,
1683          * all the other children sessions are aborted as well.
1684          *
1685          * <p>If the parent session is staged or has rollback enabled, all children sessions
1686          * must have the same properties.
1687          *
1688          * {@hide}
1689          */
1690         @SystemApi @TestApi
1691         @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
setStaged()1692         public void setStaged() {
1693             this.isStaged = true;
1694         }
1695 
1696         /**
1697          * Set this session to be installing an APEX package.
1698          *
1699          * {@hide}
1700          */
1701         @SystemApi @TestApi
1702         @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
setInstallAsApex()1703         public void setInstallAsApex() {
1704             installFlags |= PackageManager.INSTALL_APEX;
1705         }
1706 
1707         /** @hide */
getEnableRollback()1708         public boolean getEnableRollback() {
1709             return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0;
1710         }
1711 
1712         /** {@hide} */
dump(IndentingPrintWriter pw)1713         public void dump(IndentingPrintWriter pw) {
1714             pw.printPair("mode", mode);
1715             pw.printHexPair("installFlags", installFlags);
1716             pw.printPair("installLocation", installLocation);
1717             pw.printPair("sizeBytes", sizeBytes);
1718             pw.printPair("appPackageName", appPackageName);
1719             pw.printPair("appIcon", (appIcon != null));
1720             pw.printPair("appLabel", appLabel);
1721             pw.printPair("originatingUri", originatingUri);
1722             pw.printPair("originatingUid", originatingUid);
1723             pw.printPair("referrerUri", referrerUri);
1724             pw.printPair("abiOverride", abiOverride);
1725             pw.printPair("volumeUuid", volumeUuid);
1726             pw.printPair("grantedRuntimePermissions", grantedRuntimePermissions);
1727             pw.printPair("whitelistedRestrictedPermissions", whitelistedRestrictedPermissions);
1728             pw.printPair("installerPackageName", installerPackageName);
1729             pw.printPair("isMultiPackage", isMultiPackage);
1730             pw.printPair("isStaged", isStaged);
1731             pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode);
1732             pw.println();
1733         }
1734 
1735         @Override
describeContents()1736         public int describeContents() {
1737             return 0;
1738         }
1739 
1740         @Override
writeToParcel(Parcel dest, int flags)1741         public void writeToParcel(Parcel dest, int flags) {
1742             dest.writeInt(mode);
1743             dest.writeInt(installFlags);
1744             dest.writeInt(installLocation);
1745             dest.writeInt(installReason);
1746             dest.writeLong(sizeBytes);
1747             dest.writeString(appPackageName);
1748             dest.writeParcelable(appIcon, flags);
1749             dest.writeString(appLabel);
1750             dest.writeParcelable(originatingUri, flags);
1751             dest.writeInt(originatingUid);
1752             dest.writeParcelable(referrerUri, flags);
1753             dest.writeString(abiOverride);
1754             dest.writeString(volumeUuid);
1755             dest.writeStringArray(grantedRuntimePermissions);
1756             dest.writeStringList(whitelistedRestrictedPermissions);
1757             dest.writeString(installerPackageName);
1758             dest.writeBoolean(isMultiPackage);
1759             dest.writeBoolean(isStaged);
1760             dest.writeLong(requiredInstalledVersionCode);
1761         }
1762 
1763         public static final Parcelable.Creator<SessionParams>
1764                 CREATOR = new Parcelable.Creator<SessionParams>() {
1765                     @Override
1766                     public SessionParams createFromParcel(Parcel p) {
1767                         return new SessionParams(p);
1768                     }
1769 
1770                     @Override
1771                     public SessionParams[] newArray(int size) {
1772                         return new SessionParams[size];
1773                     }
1774                 };
1775     }
1776 
1777     /**
1778      * Details for an active install session.
1779      */
1780     public static class SessionInfo implements Parcelable {
1781 
1782         /**
1783          * A session ID that does not exist or is invalid.
1784          */
1785         public static final int INVALID_ID = -1;
1786         /** {@hide} */
1787         private static final int[] NO_SESSIONS = {};
1788 
1789         /** @hide */
1790         @IntDef(prefix = { "STAGED_SESSION_" }, value = {
1791                 STAGED_SESSION_NO_ERROR,
1792                 STAGED_SESSION_VERIFICATION_FAILED,
1793                 STAGED_SESSION_ACTIVATION_FAILED,
1794                 STAGED_SESSION_UNKNOWN})
1795         @Retention(RetentionPolicy.SOURCE)
1796         public @interface StagedSessionErrorCode{}
1797         /**
1798          * Constant indicating that no error occurred during the preparation or the activation of
1799          * this staged session.
1800          */
1801         public static final int STAGED_SESSION_NO_ERROR = 0;
1802 
1803         /**
1804          * Constant indicating that an error occurred during the verification phase (pre-reboot) of
1805          * this staged session.
1806          */
1807         public static final int STAGED_SESSION_VERIFICATION_FAILED = 1;
1808 
1809         /**
1810          * Constant indicating that an error occurred during the activation phase (post-reboot) of
1811          * this staged session.
1812          */
1813         public static final int STAGED_SESSION_ACTIVATION_FAILED = 2;
1814 
1815         /**
1816          * Constant indicating that an unknown error occurred while processing this staged session.
1817          */
1818         public static final int STAGED_SESSION_UNKNOWN = 3;
1819 
1820         /** {@hide} */
1821         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1822         public int sessionId;
1823         /** {@hide} */
1824         public int userId;
1825         /** {@hide} */
1826         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1827         public String installerPackageName;
1828         /** {@hide} */
1829         @UnsupportedAppUsage
1830         public String resolvedBaseCodePath;
1831         /** {@hide} */
1832         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1833         public float progress;
1834         /** {@hide} */
1835         @UnsupportedAppUsage
1836         public boolean sealed;
1837         /** {@hide} */
1838         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1839         public boolean active;
1840 
1841         /** {@hide} */
1842         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1843         public int mode;
1844         /** {@hide} */
1845         public @InstallReason int installReason;
1846         /** {@hide} */
1847         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1848         public long sizeBytes;
1849         /** {@hide} */
1850         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1851         public String appPackageName;
1852         /** {@hide} */
1853         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1854         public Bitmap appIcon;
1855         /** {@hide} */
1856         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1857         public CharSequence appLabel;
1858 
1859         /** {@hide} */
1860         public int installLocation;
1861         /** {@hide} */
1862         public Uri originatingUri;
1863         /** {@hide} */
1864         public int originatingUid;
1865         /** {@hide} */
1866         public Uri referrerUri;
1867         /** {@hide} */
1868         public String[] grantedRuntimePermissions;
1869         /** {@hide}*/
1870         public List<String> whitelistedRestrictedPermissions;
1871         /** {@hide} */
1872         public int installFlags;
1873         /** {@hide} */
1874         public boolean isMultiPackage;
1875         /** {@hide} */
1876         public boolean isStaged;
1877         /** {@hide} */
1878         public int parentSessionId = INVALID_ID;
1879         /** {@hide} */
1880         public int[] childSessionIds = NO_SESSIONS;
1881 
1882         /** {@hide} */
1883         public boolean isStagedSessionApplied;
1884         /** {@hide} */
1885         public boolean isStagedSessionReady;
1886         /** {@hide} */
1887         public boolean isStagedSessionFailed;
1888         private int mStagedSessionErrorCode;
1889         private String mStagedSessionErrorMessage;
1890 
1891         /** {@hide} */
1892         public boolean isCommitted;
1893 
1894         /** {@hide} */
1895         public long updatedMillis;
1896 
1897         /** {@hide} */
1898         @UnsupportedAppUsage
SessionInfo()1899         public SessionInfo() {
1900         }
1901 
1902         /** {@hide} */
SessionInfo(Parcel source)1903         public SessionInfo(Parcel source) {
1904             sessionId = source.readInt();
1905             userId = source.readInt();
1906             installerPackageName = source.readString();
1907             resolvedBaseCodePath = source.readString();
1908             progress = source.readFloat();
1909             sealed = source.readInt() != 0;
1910             active = source.readInt() != 0;
1911 
1912             mode = source.readInt();
1913             installReason = source.readInt();
1914             sizeBytes = source.readLong();
1915             appPackageName = source.readString();
1916             appIcon = source.readParcelable(null);
1917             appLabel = source.readString();
1918 
1919             installLocation = source.readInt();
1920             originatingUri = source.readParcelable(null);
1921             originatingUid = source.readInt();
1922             referrerUri = source.readParcelable(null);
1923             grantedRuntimePermissions = source.readStringArray();
1924             whitelistedRestrictedPermissions = source.createStringArrayList();
1925 
1926             installFlags = source.readInt();
1927             isMultiPackage = source.readBoolean();
1928             isStaged = source.readBoolean();
1929             parentSessionId = source.readInt();
1930             childSessionIds = source.createIntArray();
1931             if (childSessionIds == null) {
1932                 childSessionIds = NO_SESSIONS;
1933             }
1934             isStagedSessionApplied = source.readBoolean();
1935             isStagedSessionReady = source.readBoolean();
1936             isStagedSessionFailed = source.readBoolean();
1937             mStagedSessionErrorCode = source.readInt();
1938             mStagedSessionErrorMessage = source.readString();
1939             isCommitted = source.readBoolean();
1940         }
1941 
1942         /**
1943          * Return the ID for this session.
1944          */
getSessionId()1945         public int getSessionId() {
1946             return sessionId;
1947         }
1948 
1949         /**
1950          * Return the user associated with this session.
1951          */
getUser()1952         public @NonNull UserHandle getUser() {
1953             return new UserHandle(userId);
1954         }
1955 
1956         /**
1957          * Return the package name of the app that owns this session.
1958          */
getInstallerPackageName()1959         public @Nullable String getInstallerPackageName() {
1960             return installerPackageName;
1961         }
1962 
1963         /**
1964          * Return current overall progress of this session, between 0 and 1.
1965          * <p>
1966          * Note that this progress may not directly correspond to the value
1967          * reported by
1968          * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
1969          * system may carve out a portion of the overall progress to represent
1970          * its own internal installation work.
1971          */
getProgress()1972         public float getProgress() {
1973             return progress;
1974         }
1975 
1976         /**
1977          * Return if this session is currently active.
1978          * <p>
1979          * A session is considered active whenever there is ongoing forward
1980          * progress being made, such as the installer holding an open
1981          * {@link Session} instance while streaming data into place, or the
1982          * system optimizing code as the result of
1983          * {@link Session#commit(IntentSender)}.
1984          * <p>
1985          * If the installer closes the {@link Session} without committing, the
1986          * session is considered inactive until the installer opens the session
1987          * again.
1988          */
isActive()1989         public boolean isActive() {
1990             return active;
1991         }
1992 
1993         /**
1994          * Return if this session is sealed.
1995          * <p>
1996          * Once sealed, no further changes may be made to the session. A session
1997          * is sealed the moment {@link Session#commit(IntentSender)} is called.
1998          */
isSealed()1999         public boolean isSealed() {
2000             return sealed;
2001         }
2002 
2003         /**
2004          * Return the reason for installing this package.
2005          *
2006          * @return The install reason.
2007          */
getInstallReason()2008         public @InstallReason int getInstallReason() {
2009             return installReason;
2010         }
2011 
2012         /** {@hide} */
2013         @Deprecated
isOpen()2014         public boolean isOpen() {
2015             return isActive();
2016         }
2017 
2018         /**
2019          * Return the package name this session is working with. May be {@code null}
2020          * if unknown.
2021          */
getAppPackageName()2022         public @Nullable String getAppPackageName() {
2023             return appPackageName;
2024         }
2025 
2026         /**
2027          * Return an icon representing the app being installed. May be {@code null}
2028          * if unavailable.
2029          */
getAppIcon()2030         public @Nullable Bitmap getAppIcon() {
2031             if (appIcon == null) {
2032                 // Icon may have been omitted for calls that return bulk session
2033                 // lists, so try fetching the specific icon.
2034                 try {
2035                     final SessionInfo info = AppGlobals.getPackageManager().getPackageInstaller()
2036                             .getSessionInfo(sessionId);
2037                     appIcon = (info != null) ? info.appIcon : null;
2038                 } catch (RemoteException e) {
2039                     throw e.rethrowFromSystemServer();
2040                 }
2041             }
2042             return appIcon;
2043         }
2044 
2045         /**
2046          * Return a label representing the app being installed. May be {@code null}
2047          * if unavailable.
2048          */
getAppLabel()2049         public @Nullable CharSequence getAppLabel() {
2050             return appLabel;
2051         }
2052 
2053         /**
2054          * Return an Intent that can be started to view details about this install
2055          * session. This may surface actions such as pause, resume, or cancel.
2056          * <p>
2057          * In some cases, a matching Activity may not exist, so ensure you safeguard
2058          * against this.
2059          *
2060          * @see PackageInstaller#ACTION_SESSION_DETAILS
2061          */
createDetailsIntent()2062         public @Nullable Intent createDetailsIntent() {
2063             final Intent intent = new Intent(PackageInstaller.ACTION_SESSION_DETAILS);
2064             intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
2065             intent.setPackage(installerPackageName);
2066             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2067             return intent;
2068         }
2069 
2070         /**
2071          * Get the mode of the session as set in the constructor of the {@link SessionParams}.
2072          *
2073          * @return One of {@link SessionParams#MODE_FULL_INSTALL}
2074          *         or {@link SessionParams#MODE_INHERIT_EXISTING}
2075          */
getMode()2076         public int getMode() {
2077             return mode;
2078         }
2079 
2080         /**
2081          * Get the value set in {@link SessionParams#setInstallLocation(int)}.
2082          */
getInstallLocation()2083         public int getInstallLocation() {
2084             return installLocation;
2085         }
2086 
2087         /**
2088          * Get the value as set in {@link SessionParams#setSize(long)}.
2089          *
2090          * <p>The value is a hint and does not have to match the actual size.
2091          */
getSize()2092         public long getSize() {
2093             return sizeBytes;
2094         }
2095 
2096         /**
2097          * Get the value set in {@link SessionParams#setOriginatingUri(Uri)}.
2098          * Note: This value will only be non-null for the owner of the session.
2099          */
getOriginatingUri()2100         public @Nullable Uri getOriginatingUri() {
2101             return originatingUri;
2102         }
2103 
2104         /**
2105          * Get the value set in {@link SessionParams#setOriginatingUid(int)}.
2106          */
getOriginatingUid()2107         public int getOriginatingUid() {
2108             return originatingUid;
2109         }
2110 
2111         /**
2112          * Get the value set in {@link SessionParams#setReferrerUri(Uri)}
2113          * Note: This value will only be non-null for the owner of the session.
2114          */
getReferrerUri()2115         public @Nullable Uri getReferrerUri() {
2116             return referrerUri;
2117         }
2118 
2119         /**
2120          * Get the value set in {@link SessionParams#setGrantedRuntimePermissions(String[])}.
2121          *
2122          * @hide
2123          */
2124         @SystemApi
getGrantedRuntimePermissions()2125         public @Nullable String[] getGrantedRuntimePermissions() {
2126             return grantedRuntimePermissions;
2127         }
2128 
2129         /**
2130          * Get the value set in {@link SessionParams#setWhitelistedRestrictedPermissions(Set)}.
2131          * Note that if all permissions are whitelisted this method returns {@link
2132          * SessionParams#RESTRICTED_PERMISSIONS_ALL}.
2133          *
2134          * @hide
2135          */
2136         @TestApi
2137         @SystemApi
getWhitelistedRestrictedPermissions()2138         public @NonNull Set<String> getWhitelistedRestrictedPermissions() {
2139             if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0) {
2140                 return SessionParams.RESTRICTED_PERMISSIONS_ALL;
2141             }
2142             if (whitelistedRestrictedPermissions != null) {
2143                 return new ArraySet<>(whitelistedRestrictedPermissions);
2144             }
2145             return Collections.emptySet();
2146         }
2147 
2148         /**
2149          * Get the value set in {@link SessionParams#setAllowDowngrade(boolean)}.
2150          *
2151          * @deprecated use {@link #getRequestDowngrade()}.
2152          * @hide
2153          */
2154         @SystemApi
2155         @Deprecated
getAllowDowngrade()2156         public boolean getAllowDowngrade() {
2157             return getRequestDowngrade();
2158         }
2159 
2160         /**
2161          * Get the value set in {@link SessionParams#setRequestDowngrade(boolean)}.
2162          *
2163          * @hide
2164          */
2165         @SystemApi
getRequestDowngrade()2166         public boolean getRequestDowngrade() {
2167             return (installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0;
2168         }
2169 
2170         /**
2171          * Get the value set in {@link SessionParams#setDontKillApp(boolean)}.
2172          *
2173          * @hide
2174          */
2175         @SystemApi
getDontKillApp()2176         public boolean getDontKillApp() {
2177             return (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0;
2178         }
2179 
2180         /**
2181          * If {@link SessionParams#setInstallAsInstantApp(boolean)} was called with {@code true},
2182          * return true. If it was called with {@code false} or if it was not called return false.
2183          *
2184          * @hide
2185          *
2186          * @see #getInstallAsFullApp
2187          */
2188         @SystemApi
getInstallAsInstantApp(boolean isInstantApp)2189         public boolean getInstallAsInstantApp(boolean isInstantApp) {
2190             return (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
2191         }
2192 
2193         /**
2194          * If {@link SessionParams#setInstallAsInstantApp(boolean)} was called with {@code false},
2195          * return true. If it was called with {@code true} or if it was not called return false.
2196          *
2197          * @hide
2198          *
2199          * @see #getInstallAsInstantApp
2200          */
2201         @SystemApi
getInstallAsFullApp(boolean isInstantApp)2202         public boolean getInstallAsFullApp(boolean isInstantApp) {
2203             return (installFlags & PackageManager.INSTALL_FULL_APP) != 0;
2204         }
2205 
2206         /**
2207          * Get if {@link SessionParams#setInstallAsVirtualPreload()} was called.
2208          *
2209          * @hide
2210          */
2211         @SystemApi
getInstallAsVirtualPreload()2212         public boolean getInstallAsVirtualPreload() {
2213             return (installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0;
2214         }
2215 
2216         /**
2217          * Return whether rollback is enabled or disabled for the given upgrade.
2218          *
2219          * @hide
2220          */
2221         @SystemApi
getEnableRollback()2222         public boolean getEnableRollback() {
2223             return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0;
2224         }
2225 
2226         /**
2227          * Get the value set in {@link SessionParams#setAllocateAggressive(boolean)}.
2228          *
2229          * @hide
2230          */
2231         @SystemApi
getAllocateAggressive()2232         public boolean getAllocateAggressive() {
2233             return (installFlags & PackageManager.INSTALL_ALLOCATE_AGGRESSIVE) != 0;
2234         }
2235 
2236 
2237         /** {@hide} */
2238         @Deprecated
getDetailsIntent()2239         public @Nullable Intent getDetailsIntent() {
2240             return createDetailsIntent();
2241         }
2242 
2243         /**
2244          * Returns true if this session is a multi-package session containing references to other
2245          * sessions.
2246          */
isMultiPackage()2247         public boolean isMultiPackage() {
2248             return isMultiPackage;
2249         }
2250 
2251         /**
2252          * Returns true if this session is a staged session which will be applied at next reboot.
2253          */
isStaged()2254         public boolean isStaged() {
2255             return isStaged;
2256         }
2257 
2258         /**
2259          * Returns the parent multi-package session ID if this session belongs to one,
2260          * {@link #INVALID_ID} otherwise.
2261          */
getParentSessionId()2262         public int getParentSessionId() {
2263             return parentSessionId;
2264         }
2265 
2266         /**
2267          * Returns the set of session IDs that will be committed when this session is commited if
2268          * this session is a multi-package session.
2269          */
2270         @NonNull
getChildSessionIds()2271         public int[] getChildSessionIds() {
2272             return childSessionIds;
2273         }
2274 
checkSessionIsStaged()2275         private void checkSessionIsStaged() {
2276             if (!isStaged) {
2277                 throw new IllegalStateException("Session is not marked as staged.");
2278             }
2279         }
2280 
2281         /**
2282          * Whether the staged session has been applied successfully, meaning that all of its
2283          * packages have been activated and no further action is required.
2284          * Only meaningful if {@code isStaged} is true.
2285          */
isStagedSessionApplied()2286         public boolean isStagedSessionApplied() {
2287             checkSessionIsStaged();
2288             return isStagedSessionApplied;
2289         }
2290 
2291         /**
2292          * Whether the staged session is ready to be applied at next reboot. Only meaningful if
2293          * {@code isStaged} is true.
2294          */
isStagedSessionReady()2295         public boolean isStagedSessionReady() {
2296             checkSessionIsStaged();
2297             return isStagedSessionReady;
2298         }
2299 
2300         /**
2301          * Whether something went wrong and the staged session is declared as failed, meaning that
2302          * it will be ignored at next reboot. Only meaningful if {@code isStaged} is true.
2303          */
isStagedSessionFailed()2304         public boolean isStagedSessionFailed() {
2305             checkSessionIsStaged();
2306             return isStagedSessionFailed;
2307         }
2308 
2309         /**
2310          * If something went wrong with a staged session, clients can check this error code to
2311          * understand which kind of failure happened. Only meaningful if {@code isStaged} is true.
2312          */
getStagedSessionErrorCode()2313         public @StagedSessionErrorCode int getStagedSessionErrorCode() {
2314             checkSessionIsStaged();
2315             return mStagedSessionErrorCode;
2316         }
2317 
2318         /**
2319          * Text description of the error code returned by {@code getStagedSessionErrorCode}, or
2320          * empty string if no error was encountered.
2321          */
getStagedSessionErrorMessage()2322         public @NonNull String getStagedSessionErrorMessage() {
2323             checkSessionIsStaged();
2324             return mStagedSessionErrorMessage;
2325         }
2326 
2327         /** {@hide} */
setStagedSessionErrorCode(@tagedSessionErrorCode int errorCode, String errorMessage)2328         public void setStagedSessionErrorCode(@StagedSessionErrorCode int errorCode,
2329                                               String errorMessage) {
2330             mStagedSessionErrorCode = errorCode;
2331             mStagedSessionErrorMessage = errorMessage;
2332         }
2333 
2334         /**
2335          * Returns {@code true} if {@link Session#commit(IntentSender)}} was called for this
2336          * session.
2337          */
isCommitted()2338         public boolean isCommitted() {
2339             return isCommitted;
2340         }
2341 
2342         /**
2343          * The timestamp of the last update that occurred to the session, including changing of
2344          * states in case of staged sessions.
2345          */
2346         @CurrentTimeMillisLong
getUpdatedMillis()2347         public long getUpdatedMillis() {
2348             return updatedMillis;
2349         }
2350 
2351         @Override
describeContents()2352         public int describeContents() {
2353             return 0;
2354         }
2355 
2356         @Override
writeToParcel(Parcel dest, int flags)2357         public void writeToParcel(Parcel dest, int flags) {
2358             dest.writeInt(sessionId);
2359             dest.writeInt(userId);
2360             dest.writeString(installerPackageName);
2361             dest.writeString(resolvedBaseCodePath);
2362             dest.writeFloat(progress);
2363             dest.writeInt(sealed ? 1 : 0);
2364             dest.writeInt(active ? 1 : 0);
2365 
2366             dest.writeInt(mode);
2367             dest.writeInt(installReason);
2368             dest.writeLong(sizeBytes);
2369             dest.writeString(appPackageName);
2370             dest.writeParcelable(appIcon, flags);
2371             dest.writeString(appLabel != null ? appLabel.toString() : null);
2372 
2373             dest.writeInt(installLocation);
2374             dest.writeParcelable(originatingUri, flags);
2375             dest.writeInt(originatingUid);
2376             dest.writeParcelable(referrerUri, flags);
2377             dest.writeStringArray(grantedRuntimePermissions);
2378             dest.writeStringList(whitelistedRestrictedPermissions);
2379             dest.writeInt(installFlags);
2380             dest.writeBoolean(isMultiPackage);
2381             dest.writeBoolean(isStaged);
2382             dest.writeInt(parentSessionId);
2383             dest.writeIntArray(childSessionIds);
2384             dest.writeBoolean(isStagedSessionApplied);
2385             dest.writeBoolean(isStagedSessionReady);
2386             dest.writeBoolean(isStagedSessionFailed);
2387             dest.writeInt(mStagedSessionErrorCode);
2388             dest.writeString(mStagedSessionErrorMessage);
2389             dest.writeBoolean(isCommitted);
2390         }
2391 
2392         public static final Parcelable.Creator<SessionInfo>
2393                 CREATOR = new Parcelable.Creator<SessionInfo>() {
2394                     @Override
2395                     public SessionInfo createFromParcel(Parcel p) {
2396                         return new SessionInfo(p);
2397                     }
2398 
2399                     @Override
2400                     public SessionInfo[] newArray(int size) {
2401                         return new SessionInfo[size];
2402                     }
2403                 };
2404     }
2405 }
2406