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 static android.app.AppOpsManager.MODE_ALLOWED;
20 import static android.app.AppOpsManager.MODE_DEFAULT;
21 import static android.app.AppOpsManager.MODE_IGNORED;
22 
23 import android.Manifest;
24 import android.annotation.CurrentTimeMillisLong;
25 import android.annotation.IntDef;
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.annotation.RequiresPermission;
29 import android.annotation.SdkConstant;
30 import android.annotation.SdkConstant.SdkConstantType;
31 import android.annotation.SystemApi;
32 import android.annotation.TestApi;
33 import android.app.ActivityManager;
34 import android.app.AppGlobals;
35 import android.compat.annotation.UnsupportedAppUsage;
36 import android.content.Intent;
37 import android.content.IntentSender;
38 import android.content.pm.PackageManager.DeleteFlags;
39 import android.content.pm.PackageManager.InstallReason;
40 import android.content.pm.PackageManager.InstallScenario;
41 import android.graphics.Bitmap;
42 import android.net.Uri;
43 import android.os.Build;
44 import android.os.FileBridge;
45 import android.os.Handler;
46 import android.os.HandlerExecutor;
47 import android.os.Parcel;
48 import android.os.ParcelFileDescriptor;
49 import android.os.Parcelable;
50 import android.os.ParcelableException;
51 import android.os.RemoteException;
52 import android.os.SystemProperties;
53 import android.os.UserHandle;
54 import android.system.ErrnoException;
55 import android.system.Os;
56 import android.text.TextUtils;
57 import android.util.ArraySet;
58 import android.util.ExceptionUtils;
59 
60 import com.android.internal.util.IndentingPrintWriter;
61 import com.android.internal.util.Preconditions;
62 import com.android.internal.util.function.pooled.PooledLambda;
63 
64 import java.io.Closeable;
65 import java.io.IOException;
66 import java.io.InputStream;
67 import java.io.OutputStream;
68 import java.lang.annotation.Retention;
69 import java.lang.annotation.RetentionPolicy;
70 import java.security.MessageDigest;
71 import java.util.ArrayList;
72 import java.util.Collections;
73 import java.util.Iterator;
74 import java.util.List;
75 import java.util.Objects;
76 import java.util.Set;
77 import java.util.concurrent.Executor;
78 
79 /**
80  * Offers the ability to install, upgrade, and remove applications on the
81  * device. This includes support for apps packaged either as a single
82  * "monolithic" APK, or apps packaged as multiple "split" APKs.
83  * <p>
84  * An app is delivered for installation through a
85  * {@link PackageInstaller.Session}, which any app can create. Once the session
86  * is created, the installer can stream one or more APKs into place until it
87  * decides to either commit or destroy the session. Committing may require user
88  * intervention to complete the installation, unless the caller falls into one of the
89  * following categories, in which case the installation will complete automatically.
90  * <ul>
91  * <li>the device owner
92  * <li>the affiliated profile owner
93  * </ul>
94  * <p>
95  * Sessions can install brand new apps, upgrade existing apps, or add new splits
96  * into an existing app.
97  * <p>
98  * Apps packaged as multiple split APKs always consist of a single "base" APK
99  * (with a {@code null} split name) and zero or more "split" APKs (with unique
100  * split names). Any subset of these APKs can be installed together, as long as
101  * the following constraints are met:
102  * <ul>
103  * <li>All APKs must have the exact same package name, version code, and signing
104  * certificates.
105  * <li>All APKs must have unique split names.
106  * <li>All installations must contain a single base APK.
107  * </ul>
108  * <p>
109  * The ApiDemos project contains examples of using this API:
110  * <code>ApiDemos/src/com/example/android/apis/content/InstallApk*.java</code>.
111  */
112 public class PackageInstaller {
113     private static final String TAG = "PackageInstaller";
114 
115     /** {@hide} */
116     public static final boolean ENABLE_REVOCABLE_FD =
117             SystemProperties.getBoolean("fw.revocable_fd", false);
118 
119     /**
120      * Activity Action: Show details about a particular install session. This
121      * may surface actions such as pause, resume, or cancel.
122      * <p>
123      * This should always be scoped to the installer package that owns the
124      * session. Clients should use {@link SessionInfo#createDetailsIntent()} to
125      * build this intent correctly.
126      * <p>
127      * In some cases, a matching Activity may not exist, so ensure you safeguard
128      * against this.
129      * <p>
130      * The session to show details for is defined in {@link #EXTRA_SESSION_ID}.
131      */
132     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
133     public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
134 
135     /**
136      * Broadcast Action: Explicit broadcast sent to the last known default launcher when a session
137      * for a new install is committed. For managed profile, this is sent to the default launcher
138      * of the primary profile.
139      * <p>
140      * The associated session is defined in {@link #EXTRA_SESSION} and the user for which this
141      * session was created in {@link Intent#EXTRA_USER}.
142      */
143     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
144     public static final String ACTION_SESSION_COMMITTED =
145             "android.content.pm.action.SESSION_COMMITTED";
146 
147     /**
148      * Broadcast Action: Send information about a staged install session when its state is updated.
149      * <p>
150      * The associated session information is defined in {@link #EXTRA_SESSION}.
151      */
152     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
153     public static final String ACTION_SESSION_UPDATED =
154             "android.content.pm.action.SESSION_UPDATED";
155 
156     /** {@hide} */
157     public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL";
158 
159     /**
160      * An integer session ID that an operation is working with.
161      *
162      * @see Intent#getIntExtra(String, int)
163      */
164     public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
165 
166     /**
167      * {@link SessionInfo} that an operation is working with.
168      *
169      * @see Intent#getParcelableExtra(String)
170      */
171     public static final String EXTRA_SESSION = "android.content.pm.extra.SESSION";
172 
173     /**
174      * Package name that an operation is working with.
175      *
176      * @see Intent#getStringExtra(String)
177      */
178     public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
179 
180     /**
181      * Current status of an operation. Will be one of
182      * {@link #STATUS_PENDING_USER_ACTION}, {@link #STATUS_SUCCESS},
183      * {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED},
184      * {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT},
185      * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID}, or
186      * {@link #STATUS_FAILURE_STORAGE}.
187      * <p>
188      * More information about a status may be available through additional
189      * extras; see the individual status documentation for details.
190      *
191      * @see Intent#getIntExtra(String, int)
192      */
193     public static final String EXTRA_STATUS = "android.content.pm.extra.STATUS";
194 
195     /**
196      * Detailed string representation of the status, including raw details that
197      * are useful for debugging.
198      *
199      * @see Intent#getStringExtra(String)
200      */
201     public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
202 
203     /**
204      * Another package name relevant to a status. This is typically the package
205      * responsible for causing an operation failure.
206      *
207      * @see Intent#getStringExtra(String)
208      */
209     public static final String
210             EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
211 
212     /**
213      * Storage path relevant to a status.
214      *
215      * @see Intent#getStringExtra(String)
216      */
217     public static final String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH";
218 
219     /** {@hide} */
220     @Deprecated
221     public static final String EXTRA_PACKAGE_NAMES = "android.content.pm.extra.PACKAGE_NAMES";
222 
223     /** {@hide} */
224     public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS";
225     /** {@hide} */
226     public static final String EXTRA_LEGACY_BUNDLE = "android.content.pm.extra.LEGACY_BUNDLE";
227     /** {@hide} */
228     public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK";
229 
230     /**
231      * Type of DataLoader for this session. Will be one of
232      * {@link #DATA_LOADER_TYPE_NONE}, {@link #DATA_LOADER_TYPE_STREAMING},
233      * {@link #DATA_LOADER_TYPE_INCREMENTAL}.
234      * <p>
235      * See the individual types documentation for details.
236      *
237      * @see Intent#getIntExtra(String, int)
238      * {@hide}
239      */
240     @SystemApi
241     public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE";
242 
243     /**
244      * Streaming installation pending.
245      * Caller should make sure DataLoader is able to prepare image and reinitiate the operation.
246      *
247      * @see #EXTRA_SESSION_ID
248      * {@hide}
249      */
250     public static final int STATUS_PENDING_STREAMING = -2;
251 
252     /**
253      * User action is currently required to proceed. You can launch the intent
254      * activity described by {@link Intent#EXTRA_INTENT} to involve the user and
255      * continue.
256      * <p>
257      * You may choose to immediately launch the intent if the user is actively
258      * using your app. Otherwise, you should use a notification to guide the
259      * user back into your app before launching.
260      *
261      * @see Intent#getParcelableExtra(String)
262      */
263     public static final int STATUS_PENDING_USER_ACTION = -1;
264 
265     /**
266      * The operation succeeded.
267      */
268     public static final int STATUS_SUCCESS = 0;
269 
270     /**
271      * The operation failed in a generic way. The system will always try to
272      * provide a more specific failure reason, but in some rare cases this may
273      * be delivered.
274      *
275      * @see #EXTRA_STATUS_MESSAGE
276      */
277     public static final int STATUS_FAILURE = 1;
278 
279     /**
280      * The operation failed because it was blocked. For example, a device policy
281      * may be blocking the operation, a package verifier may have blocked the
282      * operation, or the app may be required for core system operation.
283      * <p>
284      * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
285      * specific package blocking the install.
286      *
287      * @see #EXTRA_STATUS_MESSAGE
288      * @see #EXTRA_OTHER_PACKAGE_NAME
289      */
290     public static final int STATUS_FAILURE_BLOCKED = 2;
291 
292     /**
293      * The operation failed because it was actively aborted. For example, the
294      * user actively declined requested permissions, or the session was
295      * abandoned.
296      *
297      * @see #EXTRA_STATUS_MESSAGE
298      */
299     public static final int STATUS_FAILURE_ABORTED = 3;
300 
301     /**
302      * The operation failed because one or more of the APKs was invalid. For
303      * example, they might be malformed, corrupt, incorrectly signed,
304      * mismatched, etc.
305      *
306      * @see #EXTRA_STATUS_MESSAGE
307      */
308     public static final int STATUS_FAILURE_INVALID = 4;
309 
310     /**
311      * The operation failed because it conflicts (or is inconsistent with) with
312      * another package already installed on the device. For example, an existing
313      * permission, incompatible certificates, etc. The user may be able to
314      * uninstall another app to fix the issue.
315      * <p>
316      * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
317      * specific package identified as the cause of the conflict.
318      *
319      * @see #EXTRA_STATUS_MESSAGE
320      * @see #EXTRA_OTHER_PACKAGE_NAME
321      */
322     public static final int STATUS_FAILURE_CONFLICT = 5;
323 
324     /**
325      * The operation failed because of storage issues. For example, the device
326      * may be running low on space, or external media may be unavailable. The
327      * user may be able to help free space or insert different external media.
328      * <p>
329      * The result may also contain {@link #EXTRA_STORAGE_PATH} with the path to
330      * the storage device that caused the failure.
331      *
332      * @see #EXTRA_STATUS_MESSAGE
333      * @see #EXTRA_STORAGE_PATH
334      */
335     public static final int STATUS_FAILURE_STORAGE = 6;
336 
337     /**
338      * The operation failed because it is fundamentally incompatible with this
339      * device. For example, the app may require a hardware feature that doesn't
340      * exist, it may be missing native code for the ABIs supported by the
341      * device, or it requires a newer SDK version, etc.
342      *
343      * @see #EXTRA_STATUS_MESSAGE
344      */
345     public static final int STATUS_FAILURE_INCOMPATIBLE = 7;
346 
347     /**
348      * Default value, non-streaming installation session.
349      *
350      * @see #EXTRA_DATA_LOADER_TYPE
351      * {@hide}
352      */
353     @SystemApi
354     public static final int DATA_LOADER_TYPE_NONE = DataLoaderType.NONE;
355 
356     /**
357      * Streaming installation using data loader.
358      *
359      * @see #EXTRA_DATA_LOADER_TYPE
360      * {@hide}
361      */
362     @SystemApi
363     public static final int DATA_LOADER_TYPE_STREAMING = DataLoaderType.STREAMING;
364 
365     /**
366      * Streaming installation using Incremental FileSystem.
367      *
368      * @see #EXTRA_DATA_LOADER_TYPE
369      * {@hide}
370      */
371     @SystemApi
372     public static final int DATA_LOADER_TYPE_INCREMENTAL = DataLoaderType.INCREMENTAL;
373 
374     /**
375      * Target location for the file in installation session is /data/app/<packageName>-<id>.
376      * This is the intended location for APKs.
377      * Requires permission to install packages.
378      * {@hide}
379      */
380     @SystemApi
381     public static final int LOCATION_DATA_APP = InstallationFileLocation.DATA_APP;
382 
383     /**
384      * Target location for the file in installation session is
385      * /data/media/<userid>/Android/obb/<packageName>. This is the intended location for OBBs.
386      * {@hide}
387      */
388     @SystemApi
389     public static final int LOCATION_MEDIA_OBB = InstallationFileLocation.MEDIA_OBB;
390 
391     /**
392      * Target location for the file in installation session is
393      * /data/media/<userid>/Android/data/<packageName>.
394      * This is the intended location for application data.
395      * Can only be used by an app itself running under specific user.
396      * {@hide}
397      */
398     @SystemApi
399     public static final int LOCATION_MEDIA_DATA = InstallationFileLocation.MEDIA_DATA;
400 
401     /** @hide */
402     @IntDef(prefix = { "LOCATION_" }, value = {
403             LOCATION_DATA_APP,
404             LOCATION_MEDIA_OBB,
405             LOCATION_MEDIA_DATA})
406     @Retention(RetentionPolicy.SOURCE)
407     public @interface FileLocation{}
408 
409     private final IPackageInstaller mInstaller;
410     private final int mUserId;
411     private final String mInstallerPackageName;
412     private final String mAttributionTag;
413 
414     private final ArrayList<SessionCallbackDelegate> mDelegates = new ArrayList<>();
415 
416     /** {@hide} */
PackageInstaller(IPackageInstaller installer, String installerPackageName, String installerAttributionTag, int userId)417     public PackageInstaller(IPackageInstaller installer,
418             String installerPackageName, String installerAttributionTag, int userId) {
419         mInstaller = installer;
420         mInstallerPackageName = installerPackageName;
421         mAttributionTag = installerAttributionTag;
422         mUserId = userId;
423     }
424 
425     /**
426      * Create a new session using the given parameters, returning a unique ID
427      * that represents the session. Once created, the session can be opened
428      * multiple times across multiple device boots.
429      * <p>
430      * The system may automatically destroy sessions that have not been
431      * finalized (either committed or abandoned) within a reasonable period of
432      * time, typically on the order of a day.
433      *
434      * @throws IOException if parameters were unsatisfiable, such as lack of
435      *             disk space or unavailable media.
436      * @throws SecurityException when installation services are unavailable,
437      *             such as when called from a restricted user.
438      * @throws IllegalArgumentException when {@link SessionParams} is invalid.
439      * @return positive, non-zero unique ID that represents the created session.
440      *         This ID remains consistent across device reboots until the
441      *         session is finalized. IDs are not reused during a given boot.
442      */
createSession(@onNull SessionParams params)443     public int createSession(@NonNull SessionParams params) throws IOException {
444         try {
445             return mInstaller.createSession(params, mInstallerPackageName, mAttributionTag,
446                     mUserId);
447         } catch (RuntimeException e) {
448             ExceptionUtils.maybeUnwrapIOException(e);
449             throw e;
450         } catch (RemoteException e) {
451             throw e.rethrowFromSystemServer();
452         }
453     }
454 
455     /**
456      * Open an existing session to actively perform work. To succeed, the caller
457      * must be the owner of the install session.
458      *
459      * @throws IOException if parameters were unsatisfiable, such as lack of
460      *             disk space or unavailable media.
461      * @throws SecurityException when the caller does not own the session, or
462      *             the session is invalid.
463      */
openSession(int sessionId)464     public @NonNull Session openSession(int sessionId) throws IOException {
465         try {
466             try {
467                 return new Session(mInstaller.openSession(sessionId));
468             } catch (RemoteException e) {
469                 throw e.rethrowFromSystemServer();
470             }
471         } catch (RuntimeException e) {
472             ExceptionUtils.maybeUnwrapIOException(e);
473             throw e;
474         }
475     }
476 
477     /**
478      * Update the icon representing the app being installed in a specific
479      * session. This should be roughly
480      * {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions.
481      *
482      * @throws SecurityException when the caller does not own the session, or
483      *             the session is invalid.
484      */
updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon)485     public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) {
486         try {
487             mInstaller.updateSessionAppIcon(sessionId, appIcon);
488         } catch (RemoteException e) {
489             throw e.rethrowFromSystemServer();
490         }
491     }
492 
493     /**
494      * Update the label representing the app being installed in a specific
495      * session.
496      *
497      * @throws SecurityException when the caller does not own the session, or
498      *             the session is invalid.
499      */
updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel)500     public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) {
501         try {
502             final String val = (appLabel != null) ? appLabel.toString() : null;
503             mInstaller.updateSessionAppLabel(sessionId, val);
504         } catch (RemoteException e) {
505             throw e.rethrowFromSystemServer();
506         }
507     }
508 
509     /**
510      * Completely abandon the given session, destroying all staged data and
511      * rendering it invalid. Abandoned sessions will be reported to
512      * {@link SessionCallback} listeners as failures. This is equivalent to
513      * opening the session and calling {@link Session#abandon()}.
514      *
515      * @throws SecurityException when the caller does not own the session, or
516      *             the session is invalid.
517      */
abandonSession(int sessionId)518     public void abandonSession(int sessionId) {
519         try {
520             mInstaller.abandonSession(sessionId);
521         } catch (RemoteException e) {
522             throw e.rethrowFromSystemServer();
523         }
524     }
525 
526     /**
527      * Return details for a specific session. No special permissions are
528      * required to retrieve these details.
529      *
530      * @return details for the requested session, or {@code null} if the session
531      *         does not exist.
532      */
getSessionInfo(int sessionId)533     public @Nullable SessionInfo getSessionInfo(int sessionId) {
534         try {
535             return mInstaller.getSessionInfo(sessionId);
536         } catch (RemoteException e) {
537             throw e.rethrowFromSystemServer();
538         }
539     }
540 
541     /**
542      * Return list of all known install sessions, regardless of the installer.
543      */
getAllSessions()544     public @NonNull List<SessionInfo> getAllSessions() {
545         try {
546             return mInstaller.getAllSessions(mUserId).getList();
547         } catch (RemoteException e) {
548             throw e.rethrowFromSystemServer();
549         }
550     }
551 
552     /**
553      * Return list of all known install sessions owned by the calling app.
554      */
getMySessions()555     public @NonNull List<SessionInfo> getMySessions() {
556         try {
557             return mInstaller.getMySessions(mInstallerPackageName, mUserId).getList();
558         } catch (RemoteException e) {
559             throw e.rethrowFromSystemServer();
560         }
561     }
562 
563     /**
564      * Return list of all staged install sessions.
565      */
getStagedSessions()566     public @NonNull List<SessionInfo> getStagedSessions() {
567         try {
568             // TODO: limit this to the mUserId?
569             return mInstaller.getStagedSessions().getList();
570         } catch (RemoteException e) {
571             throw e.rethrowFromSystemServer();
572         }
573     }
574 
575     /**
576      * Returns first active staged session, or {@code null} if there is none.
577      *
578      * <p>For more information on what sessions are considered active see
579      * {@link SessionInfo#isStagedSessionActive()}.
580      *
581      * @deprecated Use {@link #getActiveStagedSessions} as there can be more than one active staged
582      * session
583      */
584     @Deprecated
getActiveStagedSession()585     public @Nullable SessionInfo getActiveStagedSession() {
586         List<SessionInfo> activeSessions = getActiveStagedSessions();
587         return activeSessions.isEmpty() ? null : activeSessions.get(0);
588     }
589 
590     /**
591      * Returns list of active staged sessions. Returns empty list if there is none.
592      *
593      * <p>For more information on what sessions are considered active see
594      *      * {@link SessionInfo#isStagedSessionActive()}.
595      */
getActiveStagedSessions()596     public @NonNull List<SessionInfo> getActiveStagedSessions() {
597         final List<SessionInfo> activeStagedSessions = new ArrayList<>();
598         final List<SessionInfo> stagedSessions = getStagedSessions();
599         for (int i = 0; i < stagedSessions.size(); i++) {
600             final SessionInfo sessionInfo = stagedSessions.get(i);
601             if (sessionInfo.isStagedSessionActive()) {
602                 activeStagedSessions.add(sessionInfo);
603             }
604         }
605         return activeStagedSessions;
606     }
607 
608     /**
609      * Uninstall the given package, removing it completely from the device. This
610      * method is available to:
611      * <ul>
612      * <li>the current "installer of record" for the package
613      * <li>the device owner
614      * <li>the affiliated profile owner
615      * </ul>
616      *
617      * @param packageName The package to uninstall.
618      * @param statusReceiver Where to deliver the result.
619      *
620      * @see android.app.admin.DevicePolicyManager
621      */
622     @RequiresPermission(anyOf = {
623             Manifest.permission.DELETE_PACKAGES,
624             Manifest.permission.REQUEST_DELETE_PACKAGES})
uninstall(@onNull String packageName, @NonNull IntentSender statusReceiver)625     public void uninstall(@NonNull String packageName, @NonNull IntentSender statusReceiver) {
626         uninstall(packageName, 0 /*flags*/, statusReceiver);
627     }
628 
629     /**
630      * Uninstall the given package, removing it completely from the device. This
631      * method is only available to the current "installer of record" for the
632      * package.
633      *
634      * @param packageName The package to uninstall.
635      * @param flags Flags for uninstall.
636      * @param statusReceiver Where to deliver the result.
637      *
638      * @hide
639      */
uninstall(@onNull String packageName, @DeleteFlags int flags, @NonNull IntentSender statusReceiver)640     public void uninstall(@NonNull String packageName, @DeleteFlags int flags,
641             @NonNull IntentSender statusReceiver) {
642         uninstall(new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
643                 flags, statusReceiver);
644     }
645 
646     /**
647      * Uninstall the given package with a specific version code, removing it
648      * completely from the device. If the version code of the package
649      * does not match the one passed in the versioned package argument this
650      * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to
651      * uninstall the latest version of the package.
652      * <p>
653      * This method is available to:
654      * <ul>
655      * <li>the current "installer of record" for the package
656      * <li>the device owner
657      * <li>the affiliated profile owner
658      * </ul>
659      *
660      * @param versionedPackage The versioned package to uninstall.
661      * @param statusReceiver Where to deliver the result.
662      *
663      * @see android.app.admin.DevicePolicyManager
664      */
665     @RequiresPermission(anyOf = {
666             Manifest.permission.DELETE_PACKAGES,
667             Manifest.permission.REQUEST_DELETE_PACKAGES})
uninstall(@onNull VersionedPackage versionedPackage, @NonNull IntentSender statusReceiver)668     public void uninstall(@NonNull VersionedPackage versionedPackage,
669             @NonNull IntentSender statusReceiver) {
670         uninstall(versionedPackage, 0 /*flags*/, statusReceiver);
671     }
672 
673     /**
674      * Uninstall the given package with a specific version code, removing it
675      * completely from the device. This method is only available to the current
676      * "installer of record" for the package. If the version code of the package
677      * does not match the one passed in the versioned package argument this
678      * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to
679      * uninstall the latest version of the package.
680      *
681      * @param versionedPackage The versioned package to uninstall.
682      * @param flags Flags for uninstall.
683      * @param statusReceiver Where to deliver the result.
684      *
685      * @hide
686      */
687     @RequiresPermission(anyOf = {
688             Manifest.permission.DELETE_PACKAGES,
689             Manifest.permission.REQUEST_DELETE_PACKAGES})
uninstall(@onNull VersionedPackage versionedPackage, @DeleteFlags int flags, @NonNull IntentSender statusReceiver)690     public void uninstall(@NonNull VersionedPackage versionedPackage, @DeleteFlags int flags,
691             @NonNull IntentSender statusReceiver) {
692         Objects.requireNonNull(versionedPackage, "versionedPackage cannot be null");
693         try {
694             mInstaller.uninstall(versionedPackage, mInstallerPackageName,
695                     flags, statusReceiver, mUserId);
696         } catch (RemoteException e) {
697             throw e.rethrowFromSystemServer();
698         }
699     }
700 
701     /**
702      * Install the given package, which already exists on the device, for the user for which this
703      * installer was created.
704      *
705      * <p>This will
706      * {@link PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set) allowlist
707      * all restricted permissions}.
708      *
709      * @param packageName The package to install.
710      * @param installReason Reason for install.
711      * @param statusReceiver Where to deliver the result.
712      */
713     @RequiresPermission(allOf = {
714             Manifest.permission.INSTALL_PACKAGES,
715             Manifest.permission.INSTALL_EXISTING_PACKAGES})
installExistingPackage(@onNull String packageName, @InstallReason int installReason, @Nullable IntentSender statusReceiver)716     public void installExistingPackage(@NonNull String packageName,
717             @InstallReason int installReason,
718             @Nullable IntentSender statusReceiver) {
719         Objects.requireNonNull(packageName, "packageName cannot be null");
720         try {
721             mInstaller.installExistingPackage(packageName,
722                     PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS, installReason,
723                     statusReceiver, mUserId, null);
724         } catch (RemoteException e) {
725             throw e.rethrowFromSystemServer();
726         }
727     }
728 
729     /**
730      * Uninstall the given package for the user for which this installer was created if the package
731      * will still exist for other users on the device.
732      *
733      * @param packageName The package to install.
734      * @param statusReceiver Where to deliver the result.
735      */
736     @RequiresPermission(Manifest.permission.DELETE_PACKAGES)
uninstallExistingPackage(@onNull String packageName, @Nullable IntentSender statusReceiver)737     public void uninstallExistingPackage(@NonNull String packageName,
738             @Nullable IntentSender statusReceiver) {
739         Objects.requireNonNull(packageName, "packageName cannot be null");
740         try {
741             mInstaller.uninstallExistingPackage(
742                     new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
743                     mInstallerPackageName, statusReceiver, mUserId);
744         } catch (RemoteException e) {
745             throw e.rethrowFromSystemServer();
746         }
747     }
748 
749     /** {@hide} */
750     @SystemApi
751     @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
setPermissionsResult(int sessionId, boolean accepted)752     public void setPermissionsResult(int sessionId, boolean accepted) {
753         try {
754             mInstaller.setPermissionsResult(sessionId, accepted);
755         } catch (RemoteException e) {
756             throw e.rethrowFromSystemServer();
757         }
758     }
759 
760     /**
761      * Events for observing session lifecycle.
762      * <p>
763      * A typical session lifecycle looks like this:
764      * <ul>
765      * <li>An installer creates a session to indicate pending app delivery. All
766      * install details are available at this point.
767      * <li>The installer opens the session to deliver APK data. Note that a
768      * session may be opened and closed multiple times as network connectivity
769      * changes. The installer may deliver periodic progress updates.
770      * <li>The installer commits or abandons the session, resulting in the
771      * session being finished.
772      * </ul>
773      */
774     public static abstract class SessionCallback {
775         /**
776          * New session has been created. Details about the session can be
777          * obtained from {@link PackageInstaller#getSessionInfo(int)}.
778          */
onCreated(int sessionId)779         public abstract void onCreated(int sessionId);
780 
781         /**
782          * Badging details for an existing session has changed. For example, the
783          * app icon or label has been updated.
784          */
onBadgingChanged(int sessionId)785         public abstract void onBadgingChanged(int sessionId);
786 
787         /**
788          * Active state for session has been changed.
789          * <p>
790          * A session is considered active whenever there is ongoing forward
791          * progress being made, such as the installer holding an open
792          * {@link Session} instance while streaming data into place, or the
793          * system optimizing code as the result of
794          * {@link Session#commit(IntentSender)}.
795          * <p>
796          * If the installer closes the {@link Session} without committing, the
797          * session is considered inactive until the installer opens the session
798          * again.
799          */
onActiveChanged(int sessionId, boolean active)800         public abstract void onActiveChanged(int sessionId, boolean active);
801 
802         /**
803          * Progress for given session has been updated.
804          * <p>
805          * Note that this progress may not directly correspond to the value
806          * reported by
807          * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
808          * system may carve out a portion of the overall progress to represent
809          * its own internal installation work.
810          */
onProgressChanged(int sessionId, float progress)811         public abstract void onProgressChanged(int sessionId, float progress);
812 
813         /**
814          * Session has completely finished, either with success or failure.
815          */
onFinished(int sessionId, boolean success)816         public abstract void onFinished(int sessionId, boolean success);
817     }
818 
819     /** {@hide} */
820     static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub {
821         private static final int MSG_SESSION_CREATED = 1;
822         private static final int MSG_SESSION_BADGING_CHANGED = 2;
823         private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
824         private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
825         private static final int MSG_SESSION_FINISHED = 5;
826 
827         final SessionCallback mCallback;
828         final Executor mExecutor;
829 
SessionCallbackDelegate(SessionCallback callback, Executor executor)830         SessionCallbackDelegate(SessionCallback callback, Executor executor) {
831             mCallback = callback;
832             mExecutor = executor;
833         }
834 
835         @Override
onSessionCreated(int sessionId)836         public void onSessionCreated(int sessionId) {
837             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onCreated, mCallback,
838                     sessionId).recycleOnUse());
839         }
840 
841         @Override
onSessionBadgingChanged(int sessionId)842         public void onSessionBadgingChanged(int sessionId) {
843             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onBadgingChanged,
844                     mCallback, sessionId).recycleOnUse());
845         }
846 
847         @Override
onSessionActiveChanged(int sessionId, boolean active)848         public void onSessionActiveChanged(int sessionId, boolean active) {
849             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onActiveChanged,
850                     mCallback, sessionId, active).recycleOnUse());
851         }
852 
853         @Override
onSessionProgressChanged(int sessionId, float progress)854         public void onSessionProgressChanged(int sessionId, float progress) {
855             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onProgressChanged,
856                     mCallback, sessionId, progress).recycleOnUse());
857         }
858 
859         @Override
onSessionFinished(int sessionId, boolean success)860         public void onSessionFinished(int sessionId, boolean success) {
861             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onFinished,
862                     mCallback, sessionId, success).recycleOnUse());
863         }
864     }
865 
866     /** {@hide} */
867     @Deprecated
addSessionCallback(@onNull SessionCallback callback)868     public void addSessionCallback(@NonNull SessionCallback callback) {
869         registerSessionCallback(callback);
870     }
871 
872     /**
873      * Register to watch for session lifecycle events. No special permissions
874      * are required to watch for these events.
875      */
registerSessionCallback(@onNull SessionCallback callback)876     public void registerSessionCallback(@NonNull SessionCallback callback) {
877         registerSessionCallback(callback, new Handler());
878     }
879 
880     /** {@hide} */
881     @Deprecated
addSessionCallback(@onNull SessionCallback callback, @NonNull Handler handler)882     public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
883         registerSessionCallback(callback, handler);
884     }
885 
886     /**
887      * Register to watch for session lifecycle events. No special permissions
888      * are required to watch for these events.
889      *
890      * @param handler to dispatch callback events through, otherwise uses
891      *            calling thread.
892      */
registerSessionCallback(@onNull SessionCallback callback, @NonNull Handler handler)893     public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
894         synchronized (mDelegates) {
895             final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
896                     new HandlerExecutor(handler));
897             try {
898                 mInstaller.registerCallback(delegate, mUserId);
899             } catch (RemoteException e) {
900                 throw e.rethrowFromSystemServer();
901             }
902             mDelegates.add(delegate);
903         }
904     }
905 
906     /** {@hide} */
907     @Deprecated
removeSessionCallback(@onNull SessionCallback callback)908     public void removeSessionCallback(@NonNull SessionCallback callback) {
909         unregisterSessionCallback(callback);
910     }
911 
912     /**
913      * Unregister a previously registered callback.
914      */
unregisterSessionCallback(@onNull SessionCallback callback)915     public void unregisterSessionCallback(@NonNull SessionCallback callback) {
916         synchronized (mDelegates) {
917             for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
918                 final SessionCallbackDelegate delegate = i.next();
919                 if (delegate.mCallback == callback) {
920                     try {
921                         mInstaller.unregisterCallback(delegate);
922                     } catch (RemoteException e) {
923                         throw e.rethrowFromSystemServer();
924                     }
925                     i.remove();
926                 }
927             }
928         }
929     }
930 
931     /**
932      * An installation that is being actively staged. For an install to succeed,
933      * all existing and new packages must have identical package names, version
934      * codes, and signing certificates.
935      * <p>
936      * A session may contain any number of split packages. If the application
937      * does not yet exist, this session must include a base package.
938      * <p>
939      * If an APK included in this session is already defined by the existing
940      * installation (for example, the same split name), the APK in this session
941      * will replace the existing APK.
942      * <p>
943      * In such a case that multiple packages need to be committed simultaneously,
944      * multiple sessions can be referenced by a single multi-package session.
945      * This session is created with no package name and calling
946      * {@link SessionParams#setMultiPackage()}. The individual session IDs can be
947      * added with {@link #addChildSessionId(int)} and commit of the multi-package
948      * session will result in all child sessions being committed atomically.
949      */
950     public static class Session implements Closeable {
951         /** {@hide} */
952         protected final IPackageInstallerSession mSession;
953 
954         /** {@hide} */
Session(IPackageInstallerSession session)955         public Session(IPackageInstallerSession session) {
956             mSession = session;
957         }
958 
959         /** {@hide} */
960         @Deprecated
setProgress(float progress)961         public void setProgress(float progress) {
962             setStagingProgress(progress);
963         }
964 
965         /**
966          * Set current progress of staging this session. Valid values are
967          * anywhere between 0 and 1.
968          * <p>
969          * Note that this progress may not directly correspond to the value
970          * reported by {@link SessionCallback#onProgressChanged(int, float)}, as
971          * the system may carve out a portion of the overall progress to
972          * represent its own internal installation work.
973          */
setStagingProgress(float progress)974         public void setStagingProgress(float progress) {
975             try {
976                 mSession.setClientProgress(progress);
977             } catch (RemoteException e) {
978                 throw e.rethrowFromSystemServer();
979             }
980         }
981 
982         /** {@hide} */
983         @UnsupportedAppUsage
addProgress(float progress)984         public void addProgress(float progress) {
985             try {
986                 mSession.addClientProgress(progress);
987             } catch (RemoteException e) {
988                 throw e.rethrowFromSystemServer();
989             }
990         }
991 
992         /**
993          * Open a stream to write an APK file into the session.
994          * <p>
995          * The returned stream will start writing data at the requested offset
996          * in the underlying file, which can be used to resume a partially
997          * written file. If a valid file length is specified, the system will
998          * preallocate the underlying disk space to optimize placement on disk.
999          * It's strongly recommended to provide a valid file length when known.
1000          * <p>
1001          * You can write data into the returned stream, optionally call
1002          * {@link #fsync(OutputStream)} as needed to ensure bytes have been
1003          * persisted to disk, and then close when finished. All streams must be
1004          * closed before calling {@link #commit(IntentSender)}.
1005          *
1006          * @param name arbitrary, unique name of your choosing to identify the
1007          *            APK being written. You can open a file again for
1008          *            additional writes (such as after a reboot) by using the
1009          *            same name. This name is only meaningful within the context
1010          *            of a single install session.
1011          * @param offsetBytes offset into the file to begin writing at, or 0 to
1012          *            start at the beginning of the file.
1013          * @param lengthBytes total size of the file being written, used to
1014          *            preallocate the underlying disk space, or -1 if unknown.
1015          *            The system may clear various caches as needed to allocate
1016          *            this space.
1017          * @throws IOException if trouble opening the file for writing, such as
1018          *             lack of disk space or unavailable media.
1019          * @throws SecurityException if called after the session has been
1020          *             sealed or abandoned
1021          */
openWrite(@onNull String name, long offsetBytes, long lengthBytes)1022         public @NonNull OutputStream openWrite(@NonNull String name, long offsetBytes,
1023                 long lengthBytes) throws IOException {
1024             try {
1025                 if (ENABLE_REVOCABLE_FD) {
1026                     return new ParcelFileDescriptor.AutoCloseOutputStream(
1027                             mSession.openWrite(name, offsetBytes, lengthBytes));
1028                 } else {
1029                     final ParcelFileDescriptor clientSocket = mSession.openWrite(name,
1030                             offsetBytes, lengthBytes);
1031                     return new FileBridge.FileBridgeOutputStream(clientSocket);
1032                 }
1033             } catch (RuntimeException e) {
1034                 ExceptionUtils.maybeUnwrapIOException(e);
1035                 throw e;
1036             } catch (RemoteException e) {
1037                 throw e.rethrowFromSystemServer();
1038             }
1039         }
1040 
1041         /** {@hide} */
write(@onNull String name, long offsetBytes, long lengthBytes, @NonNull ParcelFileDescriptor fd)1042         public void write(@NonNull String name, long offsetBytes, long lengthBytes,
1043                 @NonNull ParcelFileDescriptor fd) throws IOException {
1044             try {
1045                 mSession.write(name, offsetBytes, lengthBytes, fd);
1046             } catch (RuntimeException e) {
1047                 ExceptionUtils.maybeUnwrapIOException(e);
1048                 throw e;
1049             } catch (RemoteException e) {
1050                 throw e.rethrowFromSystemServer();
1051             }
1052         }
1053 
1054         /**
1055          * Populate an APK file by creating a hard link to avoid the need to copy.
1056          * <p>
1057          * Note this API is used by RollbackManager only and can only be called from system_server.
1058          * {@code target} will be relabeled if link is created successfully. RollbackManager has
1059          * to delete {@code target} when the session is committed successfully to avoid SELinux
1060          * label conflicts.
1061          * <p>
1062          * Note No more bytes should be written to the file once the link is created successfully.
1063          *
1064          * @param target the path of the link target
1065          *
1066          * @hide
1067          */
stageViaHardLink(String target)1068         public void stageViaHardLink(String target) throws IOException {
1069             try {
1070                 mSession.stageViaHardLink(target);
1071             } catch (RuntimeException e) {
1072                 ExceptionUtils.maybeUnwrapIOException(e);
1073                 throw e;
1074             } catch (RemoteException e) {
1075                 throw e.rethrowFromSystemServer();
1076             }
1077         }
1078 
1079         /**
1080          * Ensure that any outstanding data for given stream has been committed
1081          * to disk. This is only valid for streams returned from
1082          * {@link #openWrite(String, long, long)}.
1083          */
fsync(@onNull OutputStream out)1084         public void fsync(@NonNull OutputStream out) throws IOException {
1085             if (ENABLE_REVOCABLE_FD) {
1086                 if (out instanceof ParcelFileDescriptor.AutoCloseOutputStream) {
1087                     try {
1088                         Os.fsync(((ParcelFileDescriptor.AutoCloseOutputStream) out).getFD());
1089                     } catch (ErrnoException e) {
1090                         throw e.rethrowAsIOException();
1091                     }
1092                 } else {
1093                     throw new IllegalArgumentException("Unrecognized stream");
1094                 }
1095             } else {
1096                 if (out instanceof FileBridge.FileBridgeOutputStream) {
1097                     ((FileBridge.FileBridgeOutputStream) out).fsync();
1098                 } else {
1099                     throw new IllegalArgumentException("Unrecognized stream");
1100                 }
1101             }
1102         }
1103 
1104         /**
1105          * Return all APK names contained in this session.
1106          * <p>
1107          * This returns all names which have been previously written through
1108          * {@link #openWrite(String, long, long)} as part of this session.
1109          *
1110          * @throws SecurityException if called after the session has been
1111          *             committed or abandoned.
1112          */
getNames()1113         public @NonNull String[] getNames() throws IOException {
1114             try {
1115                 return mSession.getNames();
1116             } catch (RuntimeException e) {
1117                 ExceptionUtils.maybeUnwrapIOException(e);
1118                 throw e;
1119             } catch (RemoteException e) {
1120                 throw e.rethrowFromSystemServer();
1121             }
1122         }
1123 
1124         /**
1125          * Open a stream to read an APK file from the session.
1126          * <p>
1127          * This is only valid for names which have been previously written
1128          * through {@link #openWrite(String, long, long)} as part of this
1129          * session. For example, this stream may be used to calculate a
1130          * {@link MessageDigest} of a written APK before committing.
1131          *
1132          * @throws SecurityException if called after the session has been
1133          *             committed or abandoned.
1134          */
openRead(@onNull String name)1135         public @NonNull InputStream openRead(@NonNull String name) throws IOException {
1136             try {
1137                 final ParcelFileDescriptor pfd = mSession.openRead(name);
1138                 return new ParcelFileDescriptor.AutoCloseInputStream(pfd);
1139             } catch (RuntimeException e) {
1140                 ExceptionUtils.maybeUnwrapIOException(e);
1141                 throw e;
1142             } catch (RemoteException e) {
1143                 throw e.rethrowFromSystemServer();
1144             }
1145         }
1146 
1147         /**
1148          * Removes a split.
1149          * <p>
1150          * Split removals occur prior to adding new APKs. If upgrading a feature
1151          * split, it is not expected nor desirable to remove the split prior to
1152          * upgrading.
1153          * <p>
1154          * When split removal is bundled with new APKs, the packageName must be
1155          * identical.
1156          */
removeSplit(@onNull String splitName)1157         public void removeSplit(@NonNull String splitName) throws IOException {
1158             try {
1159                 mSession.removeSplit(splitName);
1160             } catch (RuntimeException e) {
1161                 ExceptionUtils.maybeUnwrapIOException(e);
1162                 throw e;
1163             } catch (RemoteException e) {
1164                 throw e.rethrowFromSystemServer();
1165             }
1166         }
1167 
1168         /**
1169          * @return data loader params or null if the session is not using one.
1170          * {@hide}
1171          */
1172         @SystemApi
1173         @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2)
getDataLoaderParams()1174         public @Nullable DataLoaderParams getDataLoaderParams() {
1175             try {
1176                 DataLoaderParamsParcel data = mSession.getDataLoaderParams();
1177                 if (data == null) {
1178                     return null;
1179                 }
1180                 return new DataLoaderParams(data);
1181             } catch (RemoteException e) {
1182                 throw e.rethrowFromSystemServer();
1183             }
1184         }
1185 
1186         /**
1187          * Adds a file to session. On commit this file will be pulled from DataLoader {@code
1188          * android.service.dataloader.DataLoaderService.DataLoader}.
1189          *
1190          * @param location target location for the file. Possible values:
1191          *            {@link #LOCATION_DATA_APP},
1192          *            {@link #LOCATION_MEDIA_OBB},
1193          *            {@link #LOCATION_MEDIA_DATA}.
1194          * @param name arbitrary, unique name of your choosing to identify the
1195          *            APK being written. You can open a file again for
1196          *            additional writes (such as after a reboot) by using the
1197          *            same name. This name is only meaningful within the context
1198          *            of a single install session.
1199          * @param lengthBytes total size of the file being written.
1200          *            The system may clear various caches as needed to allocate
1201          *            this space.
1202          * @param metadata additional info use by DataLoader to pull data for the file.
1203          * @param signature additional file signature, e.g.
1204          *                  <a href="https://source.android.com/security/apksigning/v4.html">APK Signature Scheme v4</a>
1205          * @throws SecurityException if called after the session has been
1206          *             sealed or abandoned
1207          * @throws IllegalStateException if called for non-streaming session
1208          *
1209          * @see android.content.pm.InstallationFile
1210          *
1211          * {@hide}
1212          */
1213         @SystemApi
1214         @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2)
addFile(@ileLocation int location, @NonNull String name, long lengthBytes, @NonNull byte[] metadata, @Nullable byte[] signature)1215         public void addFile(@FileLocation int location, @NonNull String name, long lengthBytes,
1216                 @NonNull byte[] metadata, @Nullable byte[] signature) {
1217             try {
1218                 mSession.addFile(location, name, lengthBytes, metadata, signature);
1219             } catch (RemoteException e) {
1220                 throw e.rethrowFromSystemServer();
1221             }
1222         }
1223 
1224         /**
1225          * Removes a file.
1226          *
1227          * @param location target location for the file. Possible values:
1228          *            {@link #LOCATION_DATA_APP},
1229          *            {@link #LOCATION_MEDIA_OBB},
1230          *            {@link #LOCATION_MEDIA_DATA}.
1231          * @param name name of a file, e.g. split.
1232          * @throws SecurityException if called after the session has been
1233          *             sealed or abandoned
1234          * @throws IllegalStateException if called for non-DataLoader session
1235          * {@hide}
1236          */
1237         @SystemApi
1238         @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2)
removeFile(@ileLocation int location, @NonNull String name)1239         public void removeFile(@FileLocation int location, @NonNull String name) {
1240             try {
1241                 mSession.removeFile(location, name);
1242             } catch (RemoteException e) {
1243                 throw e.rethrowFromSystemServer();
1244             }
1245         }
1246 
1247         /**
1248          * Sets installer-provided checksums for the APK file in session.
1249          *
1250          * @param name      previously written as part of this session.
1251          *                  {@link #openWrite}
1252          * @param checksums installer intends to make available via
1253          *                  {@link PackageManager#requestChecksums}.
1254          * @param signature DER PKCS#7 detached signature bytes over binary serialized checksums
1255          *                  to enable integrity checking for the checksums or null for no integrity
1256          *                  checking. {@link PackageManager#requestChecksums} will return
1257          *                  the certificate used to create signature.
1258          *                  Binary format for checksums:
1259          *                  <pre>{@code DataOutputStream dos;
1260          *                  dos.writeInt(checksum.getType());
1261          *                  dos.writeInt(checksum.getValue().length);
1262          *                  dos.write(checksum.getValue());}</pre>
1263          *                  If using <b>openssl cms</b>, make sure to specify -binary -nosmimecap.
1264          *                  @see <a href="https://www.openssl.org/docs/man1.0.2/man1/cms.html">openssl cms</a>
1265          * @throws SecurityException if called after the session has been
1266          *                           committed or abandoned.
1267          * @throws IllegalStateException if checksums for this file have already been added.
1268          * @deprecated  do not use installer-provided checksums,
1269          *              use platform-enforced checksums
1270          *              e.g. {@link Checksum#TYPE_WHOLE_MERKLE_ROOT_4K_SHA256}
1271          *              in {@link PackageManager#requestChecksums}.
1272          */
1273         @Deprecated
setChecksums(@onNull String name, @NonNull List<Checksum> checksums, @Nullable byte[] signature)1274         public void setChecksums(@NonNull String name, @NonNull List<Checksum> checksums,
1275                 @Nullable byte[] signature) throws IOException {
1276             Objects.requireNonNull(name);
1277             Objects.requireNonNull(checksums);
1278 
1279             try {
1280                 mSession.setChecksums(name, checksums.toArray(new Checksum[checksums.size()]),
1281                         signature);
1282             } catch (RuntimeException e) {
1283                 ExceptionUtils.maybeUnwrapIOException(e);
1284                 throw e;
1285             } catch (RemoteException e) {
1286                 throw e.rethrowFromSystemServer();
1287             }
1288         }
1289 
1290         /**
1291          * Attempt to commit everything staged in this session. This may require
1292          * user intervention, and so it may not happen immediately. The final
1293          * result of the commit will be reported through the given callback.
1294          * <p>
1295          * Once this method is called, the session is sealed and no additional mutations may be
1296          * performed on the session. In case of device reboot or data loader transient failure
1297          * before the session has been finalized, you may commit the session again.
1298          * <p>
1299          * If the installer is the device owner or the affiliated profile owner, there will be no
1300          * user intervention.
1301          *
1302          * @param statusReceiver Called when the state of the session changes. Intents
1303          *                       sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
1304          *                       individual status codes on how to handle them.
1305          *
1306          * @throws SecurityException if streams opened through
1307          *             {@link #openWrite(String, long, long)} are still open.
1308          *
1309          * @see android.app.admin.DevicePolicyManager
1310          */
commit(@onNull IntentSender statusReceiver)1311         public void commit(@NonNull IntentSender statusReceiver) {
1312             try {
1313                 mSession.commit(statusReceiver, false);
1314             } catch (RemoteException e) {
1315                 throw e.rethrowFromSystemServer();
1316             }
1317         }
1318 
1319         /**
1320          * Attempt to commit a session that has been {@link #transfer(String) transferred}.
1321          *
1322          * <p>If the device reboots before the session has been finalized, you may commit the
1323          * session again.
1324          *
1325          * <p>The caller of this method is responsible to ensure the safety of the session. As the
1326          * session was created by another - usually less trusted - app, it is paramount that before
1327          * committing <u>all</u> public and system {@link SessionInfo properties of the session}
1328          * and <u>all</u> {@link #openRead(String) APKs} are verified by the caller. It might happen
1329          * that new properties are added to the session with a new API revision. In this case the
1330          * callers need to be updated.
1331          *
1332          * @param statusReceiver Called when the state of the session changes. Intents
1333          *                       sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
1334          *                       individual status codes on how to handle them.
1335          *
1336          * @hide
1337          */
1338         @SystemApi
1339         @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
commitTransferred(@onNull IntentSender statusReceiver)1340         public void commitTransferred(@NonNull IntentSender statusReceiver) {
1341             try {
1342                 mSession.commit(statusReceiver, true);
1343             } catch (RemoteException e) {
1344                 throw e.rethrowFromSystemServer();
1345             }
1346         }
1347 
1348         /**
1349          * Transfer the session to a new owner.
1350          * <p>
1351          * Only sessions that update the installing app can be transferred.
1352          * <p>
1353          * After the transfer to a package with a different uid all method calls on the session
1354          * will cause {@link SecurityException}s.
1355          * <p>
1356          * Once this method is called, the session is sealed and no additional mutations beside
1357          * committing it may be performed on the session.
1358          *
1359          * @param packageName The package of the new owner. Needs to hold the INSTALL_PACKAGES
1360          *                    permission.
1361          *
1362          * @throws PackageManager.NameNotFoundException if the new owner could not be found.
1363          * @throws SecurityException if called after the session has been committed or abandoned.
1364          * @throws IllegalStateException if streams opened through
1365          *                                  {@link #openWrite(String, long, long) are still open.
1366          * @throws IllegalArgumentException if {@code packageName} is invalid.
1367          */
transfer(@onNull String packageName)1368         public void transfer(@NonNull String packageName)
1369                 throws PackageManager.NameNotFoundException {
1370             Preconditions.checkArgument(!TextUtils.isEmpty(packageName));
1371 
1372             try {
1373                 mSession.transfer(packageName);
1374             } catch (ParcelableException e) {
1375                 e.maybeRethrow(PackageManager.NameNotFoundException.class);
1376                 throw new RuntimeException(e);
1377             } catch (RemoteException e) {
1378                 throw e.rethrowFromSystemServer();
1379             }
1380         }
1381 
1382         /**
1383          * Release this session object. You can open the session again if it
1384          * hasn't been finalized.
1385          */
1386         @Override
close()1387         public void close() {
1388             try {
1389                 mSession.close();
1390             } catch (RemoteException e) {
1391                 throw e.rethrowFromSystemServer();
1392             }
1393         }
1394 
1395         /**
1396          * Completely abandon this session, destroying all staged data and
1397          * rendering it invalid. Abandoned sessions will be reported to
1398          * {@link SessionCallback} listeners as failures. This is equivalent to
1399          * {@link #abandonSession(int)}.
1400          * <p>If the parent is abandoned, all children will also be abandoned. Any written data
1401          * would be destroyed and the created {@link Session} information will be discarded.</p>
1402          */
abandon()1403         public void abandon() {
1404             try {
1405                 mSession.abandon();
1406             } catch (RemoteException e) {
1407                 throw e.rethrowFromSystemServer();
1408             }
1409         }
1410 
1411         /**
1412          * @return {@code true} if this session will commit more than one package when it is
1413          * committed.
1414          */
isMultiPackage()1415         public boolean isMultiPackage() {
1416             try {
1417                 return mSession.isMultiPackage();
1418             } catch (RemoteException e) {
1419                 throw e.rethrowFromSystemServer();
1420             }
1421         }
1422 
1423         /**
1424          * @return {@code true} if this session will be staged and applied at next reboot.
1425          */
isStaged()1426         public boolean isStaged() {
1427             try {
1428                 return mSession.isStaged();
1429             } catch (RemoteException e) {
1430                 throw e.rethrowFromSystemServer();
1431             }
1432         }
1433 
1434         /**
1435          * @return Session's {@link SessionParams#installFlags}.
1436          * @hide
1437          */
getInstallFlags()1438         public int getInstallFlags() {
1439             try {
1440                 return mSession.getInstallFlags();
1441             } catch (RemoteException e) {
1442                 throw e.rethrowFromSystemServer();
1443             }
1444         }
1445 
1446         /**
1447          * @return the session ID of the multi-package session that this belongs to or
1448          * {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session.
1449          */
getParentSessionId()1450         public int getParentSessionId() {
1451             try {
1452                 return mSession.getParentSessionId();
1453             } catch (RemoteException e) {
1454                 throw e.rethrowFromSystemServer();
1455             }
1456         }
1457 
1458         /**
1459          * @return the set of session IDs that will be committed atomically when this session is
1460          * committed if this is a multi-package session or null if none exist.
1461          */
1462         @NonNull
getChildSessionIds()1463         public int[] getChildSessionIds() {
1464             try {
1465                 return mSession.getChildSessionIds();
1466             } catch (RemoteException e) {
1467                 throw e.rethrowFromSystemServer();
1468             }
1469         }
1470 
1471         /**
1472          * Adds a session ID to the set of sessions that will be committed atomically
1473          * when this session is committed.
1474          *
1475          * <p>If the parent is staged or has rollback enabled, all children must have
1476          * the same properties.</p>
1477          * <p>If the parent is abandoned, all children will also be abandoned.</p>
1478          *
1479          * @param sessionId the session ID to add to this multi-package session.
1480          */
addChildSessionId(int sessionId)1481         public void addChildSessionId(int sessionId) {
1482             try {
1483                 mSession.addChildSessionId(sessionId);
1484             } catch (RemoteException e) {
1485                 e.rethrowFromSystemServer();
1486             }
1487         }
1488 
1489         /**
1490          * Removes a session ID from the set of sessions that will be committed
1491          * atomically when this session is committed.
1492          *
1493          * @param sessionId the session ID to remove from this multi-package session.
1494          */
removeChildSessionId(int sessionId)1495         public void removeChildSessionId(int sessionId) {
1496             try {
1497                 mSession.removeChildSessionId(sessionId);
1498             } catch (RemoteException e) {
1499                 e.rethrowFromSystemServer();
1500             }
1501         }
1502     }
1503 
1504     /**
1505      * Parameters for creating a new {@link PackageInstaller.Session}.
1506      */
1507     public static class SessionParams implements Parcelable {
1508 
1509         /** {@hide} */
1510         public static final int MODE_INVALID = -1;
1511 
1512         /**
1513          * Mode for an install session whose staged APKs should fully replace any
1514          * existing APKs for the target app.
1515          */
1516         public static final int MODE_FULL_INSTALL = 1;
1517 
1518         /**
1519          * Mode for an install session that should inherit any existing APKs for the
1520          * target app, unless they have been explicitly overridden (based on split
1521          * name) by the session. For example, this can be used to add one or more
1522          * split APKs to an existing installation.
1523          * <p>
1524          * If there are no existing APKs for the target app, this behaves like
1525          * {@link #MODE_FULL_INSTALL}.
1526          */
1527         public static final int MODE_INHERIT_EXISTING = 2;
1528 
1529         /**
1530          * Special constant to refer to all restricted permissions.
1531          */
1532         public static final @NonNull Set<String> RESTRICTED_PERMISSIONS_ALL = new ArraySet<>();
1533 
1534         /** {@hide} */
1535         public static final int UID_UNKNOWN = -1;
1536 
1537         /**
1538          * This value is derived from the maximum file name length. No package above this limit
1539          * can ever be successfully installed on the device.
1540          * @hide
1541          */
1542         public static final int MAX_PACKAGE_NAME_LENGTH = 255;
1543 
1544         /** @hide */
1545         @IntDef(prefix = {"USER_ACTION_"}, value = {
1546                 USER_ACTION_UNSPECIFIED,
1547                 USER_ACTION_REQUIRED,
1548                 USER_ACTION_NOT_REQUIRED
1549         })
1550         @Retention(RetentionPolicy.SOURCE)
1551         public @interface UserActionRequirement {}
1552 
1553         /**
1554          * The installer did not call {@link SessionParams#setRequireUserAction(int)} to
1555          * specify whether user action should be required for the install.
1556          */
1557         public static final int USER_ACTION_UNSPECIFIED = 0;
1558 
1559         /**
1560          * The installer called {@link SessionParams#setRequireUserAction(int)} with
1561          * {@code true} to require user action for the install to complete.
1562          */
1563         public static final int USER_ACTION_REQUIRED = 1;
1564 
1565         /**
1566          * The installer called {@link SessionParams#setRequireUserAction(int)} with
1567          * {@code false} to request that user action not be required for this install.
1568          */
1569         public static final int USER_ACTION_NOT_REQUIRED = 2;
1570 
1571         /** {@hide} */
1572         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1573         public int mode = MODE_INVALID;
1574         /** {@hide} */
1575         @UnsupportedAppUsage
1576         public int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
1577         /** {@hide} */
1578         public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
1579         /** {@hide} */
1580         public @InstallReason int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
1581         /**
1582          * {@hide}
1583          *
1584          * This flag indicates which installation scenario best describes this session.  The system
1585          * may use this value when making decisions about how to handle the installation, such as
1586          * prioritizing system health or user experience.
1587          */
1588         public @InstallScenario int installScenario = PackageManager.INSTALL_SCENARIO_DEFAULT;
1589         /** {@hide} */
1590         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1591         public long sizeBytes = -1;
1592         /** {@hide} */
1593         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1594         public String appPackageName;
1595         /** {@hide} */
1596         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1597         public Bitmap appIcon;
1598         /** {@hide} */
1599         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1600         public String appLabel;
1601         /** {@hide} */
1602         public long appIconLastModified = -1;
1603         /** {@hide} */
1604         public Uri originatingUri;
1605         /** {@hide} */
1606         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1607         public int originatingUid = UID_UNKNOWN;
1608         /** {@hide} */
1609         public Uri referrerUri;
1610         /** {@hide} */
1611         public String abiOverride;
1612         /** {@hide} */
1613         public String volumeUuid;
1614         /** {@hide} */
1615         public String[] grantedRuntimePermissions;
1616         /** {@hide} */
1617         public List<String> whitelistedRestrictedPermissions;
1618         /** {@hide} */
1619         public int autoRevokePermissionsMode = MODE_DEFAULT;
1620         /** {@hide} */
1621         public String installerPackageName;
1622         /** {@hide} */
1623         public boolean isMultiPackage;
1624         /** {@hide} */
1625         public boolean isStaged;
1626         /** {@hide} */
1627         public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST;
1628         /** {@hide} */
1629         public DataLoaderParams dataLoaderParams;
1630         /** {@hide} */
1631         public int rollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE;
1632         /** {@hide} */
1633         public boolean forceQueryableOverride;
1634         /** {@hide} */
1635         public int requireUserAction = USER_ACTION_UNSPECIFIED;
1636 
1637         /**
1638          * Construct parameters for a new package install session.
1639          *
1640          * @param mode one of {@link #MODE_FULL_INSTALL} or
1641          *            {@link #MODE_INHERIT_EXISTING} describing how the session
1642          *            should interact with an existing app.
1643          */
SessionParams(int mode)1644         public SessionParams(int mode) {
1645             this.mode = mode;
1646         }
1647 
1648         /** {@hide} */
SessionParams(Parcel source)1649         public SessionParams(Parcel source) {
1650             mode = source.readInt();
1651             installFlags = source.readInt();
1652             installLocation = source.readInt();
1653             installReason = source.readInt();
1654             installScenario = source.readInt();
1655             sizeBytes = source.readLong();
1656             appPackageName = source.readString();
1657             appIcon = source.readParcelable(null);
1658             appLabel = source.readString();
1659             originatingUri = source.readParcelable(null);
1660             originatingUid = source.readInt();
1661             referrerUri = source.readParcelable(null);
1662             abiOverride = source.readString();
1663             volumeUuid = source.readString();
1664             grantedRuntimePermissions = source.readStringArray();
1665             whitelistedRestrictedPermissions = source.createStringArrayList();
1666             autoRevokePermissionsMode = source.readInt();
1667             installerPackageName = source.readString();
1668             isMultiPackage = source.readBoolean();
1669             isStaged = source.readBoolean();
1670             forceQueryableOverride = source.readBoolean();
1671             requiredInstalledVersionCode = source.readLong();
1672             DataLoaderParamsParcel dataLoaderParamsParcel = source.readParcelable(
1673                     DataLoaderParamsParcel.class.getClassLoader());
1674             if (dataLoaderParamsParcel != null) {
1675                 dataLoaderParams = new DataLoaderParams(dataLoaderParamsParcel);
1676             }
1677             rollbackDataPolicy = source.readInt();
1678             requireUserAction = source.readInt();
1679         }
1680 
1681         /** {@hide} */
copy()1682         public SessionParams copy() {
1683             SessionParams ret = new SessionParams(mode);
1684             ret.installFlags = installFlags;
1685             ret.installLocation = installLocation;
1686             ret.installReason = installReason;
1687             ret.installScenario = installScenario;
1688             ret.sizeBytes = sizeBytes;
1689             ret.appPackageName = appPackageName;
1690             ret.appIcon = appIcon;  // not a copy.
1691             ret.appLabel = appLabel;
1692             ret.originatingUri = originatingUri;  // not a copy, but immutable.
1693             ret.originatingUid = originatingUid;
1694             ret.referrerUri = referrerUri;  // not a copy, but immutable.
1695             ret.abiOverride = abiOverride;
1696             ret.volumeUuid = volumeUuid;
1697             ret.grantedRuntimePermissions = grantedRuntimePermissions;
1698             ret.whitelistedRestrictedPermissions = whitelistedRestrictedPermissions;
1699             ret.autoRevokePermissionsMode = autoRevokePermissionsMode;
1700             ret.installerPackageName = installerPackageName;
1701             ret.isMultiPackage = isMultiPackage;
1702             ret.isStaged = isStaged;
1703             ret.forceQueryableOverride = forceQueryableOverride;
1704             ret.requiredInstalledVersionCode = requiredInstalledVersionCode;
1705             ret.dataLoaderParams = dataLoaderParams;
1706             ret.rollbackDataPolicy = rollbackDataPolicy;
1707             ret.requireUserAction = requireUserAction;
1708             return ret;
1709         }
1710 
1711         /**
1712          * Check if there are hidden options set.
1713          *
1714          * <p>Hidden options are those options that cannot be verified via public or system-api
1715          * methods on {@link SessionInfo}.
1716          *
1717          * @return {@code true} if any hidden option is set.
1718          *
1719          * @hide
1720          */
areHiddenOptionsSet()1721         public boolean areHiddenOptionsSet() {
1722             return (installFlags & (PackageManager.INSTALL_REQUEST_DOWNGRADE
1723                     | PackageManager.INSTALL_ALLOW_DOWNGRADE
1724                     | PackageManager.INSTALL_DONT_KILL_APP
1725                     | PackageManager.INSTALL_INSTANT_APP
1726                     | PackageManager.INSTALL_FULL_APP
1727                     | PackageManager.INSTALL_VIRTUAL_PRELOAD
1728                     | PackageManager.INSTALL_ALLOCATE_AGGRESSIVE)) != installFlags
1729                     || abiOverride != null || volumeUuid != null;
1730         }
1731 
1732         /**
1733          * Provide value of {@link PackageInfo#installLocation}, which may be used
1734          * to determine where the app will be staged. Defaults to
1735          * {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}.
1736          */
setInstallLocation(int installLocation)1737         public void setInstallLocation(int installLocation) {
1738             this.installLocation = installLocation;
1739         }
1740 
1741         /**
1742          * Optionally indicate the total size (in bytes) of all APKs that will be
1743          * delivered in this session. The system may use this to ensure enough disk
1744          * space exists before proceeding, or to estimate container size for
1745          * installations living on external storage.
1746          *
1747          * @see PackageInfo#INSTALL_LOCATION_AUTO
1748          * @see PackageInfo#INSTALL_LOCATION_PREFER_EXTERNAL
1749          */
setSize(long sizeBytes)1750         public void setSize(long sizeBytes) {
1751             this.sizeBytes = sizeBytes;
1752         }
1753 
1754         /**
1755          * Optionally set the package name of the app being installed. It's strongly
1756          * recommended that you provide this value when known, so that observers can
1757          * communicate installing apps to users.
1758          * <p>
1759          * If the APKs staged in the session aren't consistent with this package
1760          * name, the install will fail. Regardless of this value, all APKs in the
1761          * app must have the same package name.
1762          */
setAppPackageName(@ullable String appPackageName)1763         public void setAppPackageName(@Nullable String appPackageName) {
1764             this.appPackageName = appPackageName;
1765         }
1766 
1767         /**
1768          * Optionally set an icon representing the app being installed. This should
1769          * be roughly {@link ActivityManager#getLauncherLargeIconSize()} in both
1770          * dimensions.
1771          */
setAppIcon(@ullable Bitmap appIcon)1772         public void setAppIcon(@Nullable Bitmap appIcon) {
1773             this.appIcon = appIcon;
1774         }
1775 
1776         /**
1777          * Optionally set a label representing the app being installed.
1778          *
1779          * This value will be trimmed to the first 1000 characters.
1780          */
setAppLabel(@ullable CharSequence appLabel)1781         public void setAppLabel(@Nullable CharSequence appLabel) {
1782             this.appLabel = (appLabel != null) ? appLabel.toString() : null;
1783         }
1784 
1785         /**
1786          * Optionally set the URI where this package was downloaded from. This is
1787          * informational and may be used as a signal for anti-malware purposes.
1788          *
1789          * @see Intent#EXTRA_ORIGINATING_URI
1790          */
setOriginatingUri(@ullable Uri originatingUri)1791         public void setOriginatingUri(@Nullable Uri originatingUri) {
1792             this.originatingUri = originatingUri;
1793         }
1794 
1795         /**
1796          * Sets the UID that initiated the package installation. This is informational
1797          * and may be used as a signal for anti-malware purposes.
1798          */
setOriginatingUid(int originatingUid)1799         public void setOriginatingUid(int originatingUid) {
1800             this.originatingUid = originatingUid;
1801         }
1802 
1803         /**
1804          * Optionally set the URI that referred you to install this package. This is
1805          * informational and may be used as a signal for anti-malware purposes.
1806          *
1807          * @see Intent#EXTRA_REFERRER
1808          */
setReferrerUri(@ullable Uri referrerUri)1809         public void setReferrerUri(@Nullable Uri referrerUri) {
1810             this.referrerUri = referrerUri;
1811         }
1812 
1813         /**
1814          * Sets which runtime permissions to be granted to the package at installation.
1815          *
1816          * @param permissions The permissions to grant or null to grant all runtime
1817          *     permissions.
1818          *
1819          * @hide
1820          */
1821         @SystemApi
1822         @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS)
setGrantedRuntimePermissions(String[] permissions)1823         public void setGrantedRuntimePermissions(String[] permissions) {
1824             installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
1825             this.grantedRuntimePermissions = permissions;
1826         }
1827 
1828         /**
1829          * Sets which restricted permissions to be allowlisted for the app. Allowlisting
1830          * is not granting the permissions, rather it allows the app to hold permissions
1831          * which are otherwise restricted. Allowlisting a non restricted permission has
1832          * no effect.
1833          *
1834          * <p> Permissions can be hard restricted which means that the app cannot hold
1835          * them or soft restricted where the app can hold the permission but in a weaker
1836          * form. Whether a permission is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard
1837          * restricted} or {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted}
1838          * depends on the permission declaration. Allowlisting a hard restricted permission
1839          * allows the app to hold that permission and allowlisting a soft restricted
1840          * permission allows the app to hold the permission in its full, unrestricted form.
1841          *
1842          * <p> Permissions can also be immutably restricted which means that the allowlist
1843          * state of the permission can be determined only at install time and cannot be
1844          * changed on updated or at a later point via the package manager APIs.
1845          *
1846          * <p>Initially, all restricted permissions are allowlisted but you can change
1847          * which ones are allowlisted by calling this method or the corresponding ones
1848          * on the {@link PackageManager}. Only soft or hard restricted permissions on the current
1849          * Android version are supported and any invalid entries will be removed.
1850          *
1851          * @see PackageManager#addWhitelistedRestrictedPermission(String, String, int)
1852          * @see PackageManager#removeWhitelistedRestrictedPermission(String, String, int)
1853          */
setWhitelistedRestrictedPermissions(@ullable Set<String> permissions)1854         public void setWhitelistedRestrictedPermissions(@Nullable Set<String> permissions) {
1855             if (permissions == RESTRICTED_PERMISSIONS_ALL) {
1856                 installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
1857                 whitelistedRestrictedPermissions = null;
1858             } else {
1859                 installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
1860                 whitelistedRestrictedPermissions = (permissions != null)
1861                         ? new ArrayList<>(permissions) : null;
1862             }
1863         }
1864 
1865         /**
1866          * Sets whether permissions should be auto-revoked if this package is unused for an
1867          * extended periodd of time.
1868          *
1869          * It's disabled by default but generally the installer should enable it for most packages,
1870          * excluding only those where doing so might cause breakage that cannot be easily addressed
1871          * by simply re-requesting the permission(s).
1872          *
1873          * If user explicitly enabled or disabled it via settings, this call is ignored.
1874          *
1875          * @param shouldAutoRevoke whether permissions should be auto-revoked.
1876          *
1877          * @deprecated No longer used
1878          */
1879         @Deprecated
setAutoRevokePermissionsMode(boolean shouldAutoRevoke)1880         public void setAutoRevokePermissionsMode(boolean shouldAutoRevoke) {
1881             autoRevokePermissionsMode = shouldAutoRevoke ? MODE_ALLOWED : MODE_IGNORED;
1882         }
1883 
1884         /**
1885          * Request that rollbacks be enabled or disabled for the given upgrade with rollback data
1886          * policy set to RESTORE.
1887          *
1888          * <p>If the parent session is staged or has rollback enabled, all children sessions
1889          * must have the same properties.
1890          *
1891          * @param enable set to {@code true} to enable, {@code false} to disable
1892          * @see SessionParams#setEnableRollback(boolean, int)
1893          * @hide
1894          */
1895         @SystemApi
setEnableRollback(boolean enable)1896         public void setEnableRollback(boolean enable) {
1897             if (enable) {
1898                 installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
1899             } else {
1900                 installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
1901             }
1902             rollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE;
1903         }
1904 
1905         /**
1906          * Request that rollbacks be enabled or disabled for the given upgrade.
1907          *
1908          * <p>If the parent session is staged or has rollback enabled, all children sessions
1909          * must have the same properties.
1910          *
1911          * <p> For a multi-package install, this method must be called on each child session to
1912          * specify rollback data policies explicitly. Note each child session is allowed to have
1913          * different policies.
1914          *
1915          * @param enable set to {@code true} to enable, {@code false} to disable
1916          * @param dataPolicy the rollback data policy for this session
1917          * @hide
1918          */
1919         @SystemApi
setEnableRollback(boolean enable, @PackageManager.RollbackDataPolicy int dataPolicy)1920         public void setEnableRollback(boolean enable,
1921                 @PackageManager.RollbackDataPolicy int dataPolicy) {
1922             if (enable) {
1923                 installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
1924             } else {
1925                 installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
1926             }
1927             rollbackDataPolicy = dataPolicy;
1928         }
1929 
1930 
1931         /**
1932          * @deprecated use {@link #setRequestDowngrade(boolean)}.
1933          * {@hide}
1934          */
1935         @SystemApi
1936         @Deprecated
setAllowDowngrade(boolean allowDowngrade)1937         public void setAllowDowngrade(boolean allowDowngrade) {
1938             setRequestDowngrade(allowDowngrade);
1939         }
1940 
1941         /** {@hide} */
1942         @SystemApi
setRequestDowngrade(boolean requestDowngrade)1943         public void setRequestDowngrade(boolean requestDowngrade) {
1944             if (requestDowngrade) {
1945                 installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
1946             } else {
1947                 installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE;
1948             }
1949         }
1950 
1951         /**
1952          * Require the given version of the package be installed.
1953          * The install will only be allowed if the existing version code of
1954          * the package installed on the device matches the given version code.
1955          * Use {@link * PackageManager#VERSION_CODE_HIGHEST} to allow
1956          * installation regardless of the currently installed package version.
1957          *
1958          * @hide
1959          */
setRequiredInstalledVersionCode(long versionCode)1960         public void setRequiredInstalledVersionCode(long versionCode) {
1961             requiredInstalledVersionCode = versionCode;
1962         }
1963 
1964         /** {@hide} */
setInstallFlagsForcePermissionPrompt()1965         public void setInstallFlagsForcePermissionPrompt() {
1966             installFlags |= PackageManager.INSTALL_FORCE_PERMISSION_PROMPT;
1967         }
1968 
1969         /** {@hide} */
1970         @SystemApi
setDontKillApp(boolean dontKillApp)1971         public void setDontKillApp(boolean dontKillApp) {
1972             if (dontKillApp) {
1973                 installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
1974             } else {
1975                 installFlags &= ~PackageManager.INSTALL_DONT_KILL_APP;
1976             }
1977         }
1978 
1979         /** {@hide} */
1980         @SystemApi
setInstallAsInstantApp(boolean isInstantApp)1981         public void setInstallAsInstantApp(boolean isInstantApp) {
1982             if (isInstantApp) {
1983                 installFlags |= PackageManager.INSTALL_INSTANT_APP;
1984                 installFlags &= ~PackageManager.INSTALL_FULL_APP;
1985             } else {
1986                 installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
1987                 installFlags |= PackageManager.INSTALL_FULL_APP;
1988             }
1989         }
1990 
1991         /**
1992          * Sets the install as a virtual preload. Will only have effect when called
1993          * by the verifier.
1994          * {@hide}
1995          */
1996         @SystemApi
setInstallAsVirtualPreload()1997         public void setInstallAsVirtualPreload() {
1998             installFlags |= PackageManager.INSTALL_VIRTUAL_PRELOAD;
1999         }
2000 
2001         /**
2002          * Set the reason for installing this package.
2003          * <p>
2004          * The install reason should be a pre-defined integer. The behavior is
2005          * undefined if other values are used.
2006          *
2007          * @see PackageManager#INSTALL_REASON_UNKNOWN
2008          * @see PackageManager#INSTALL_REASON_POLICY
2009          * @see PackageManager#INSTALL_REASON_DEVICE_RESTORE
2010          * @see PackageManager#INSTALL_REASON_DEVICE_SETUP
2011          * @see PackageManager#INSTALL_REASON_USER
2012          */
setInstallReason(@nstallReason int installReason)2013         public void setInstallReason(@InstallReason int installReason) {
2014             this.installReason = installReason;
2015         }
2016 
2017         /** {@hide} */
2018         @SystemApi
2019         @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE)
setAllocateAggressive(boolean allocateAggressive)2020         public void setAllocateAggressive(boolean allocateAggressive) {
2021             if (allocateAggressive) {
2022                 installFlags |= PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
2023             } else {
2024                 installFlags &= ~PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
2025             }
2026         }
2027 
2028         /**
2029          * @hide
2030          */
2031         @TestApi
setInstallFlagAllowTest()2032         public void setInstallFlagAllowTest() {
2033             installFlags |= PackageManager.INSTALL_ALLOW_TEST;
2034         }
2035 
2036         /**
2037          * Set the installer package for the app.
2038          *
2039          * By default this is the app that created the {@link PackageInstaller} object.
2040          *
2041          * @param installerPackageName name of the installer package
2042          * {@hide}
2043          */
2044         @TestApi
setInstallerPackageName(@ullable String installerPackageName)2045         public void setInstallerPackageName(@Nullable String installerPackageName) {
2046             this.installerPackageName = installerPackageName;
2047         }
2048 
2049         /**
2050          * Set this session to be the parent of a multi-package install.
2051          *
2052          * A multi-package install session contains no APKs and only references other install
2053          * sessions via ID. When a multi-package session is committed, all of its children
2054          * are committed to the system in an atomic manner. If any children fail to install,
2055          * all of them do, including the multi-package session.
2056          */
setMultiPackage()2057         public void setMultiPackage() {
2058             this.isMultiPackage = true;
2059         }
2060 
2061         /**
2062          * Set this session to be staged to be installed at reboot.
2063          *
2064          * Staged sessions are scheduled to be installed at next reboot. Staged sessions can also be
2065          * multi-package. In that case, if any of the children sessions fail to install at reboot,
2066          * all the other children sessions are aborted as well.
2067          *
2068          * <p>If the parent session is staged or has rollback enabled, all children sessions
2069          * must have the same properties.
2070          *
2071          * {@hide}
2072          */
2073         @SystemApi
2074         @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
setStaged()2075         public void setStaged() {
2076             this.isStaged = true;
2077         }
2078 
2079         /**
2080          * Set this session to be installing an APEX package.
2081          *
2082          * {@hide}
2083          */
2084         @SystemApi
2085         @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
setInstallAsApex()2086         public void setInstallAsApex() {
2087             installFlags |= PackageManager.INSTALL_APEX;
2088         }
2089 
2090         /** @hide */
getEnableRollback()2091         public boolean getEnableRollback() {
2092             return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0;
2093         }
2094 
2095         /**
2096          * Set the data loader params for the session.
2097          * This also switches installation into data loading mode and disallow direct writes into
2098          * staging folder.
2099          *
2100          * @see android.service.dataloader.DataLoaderService.DataLoader
2101          *
2102          * {@hide}
2103          */
2104         @SystemApi
2105         @RequiresPermission(allOf = {
2106                 Manifest.permission.INSTALL_PACKAGES,
2107                 Manifest.permission.USE_INSTALLER_V2})
setDataLoaderParams(@onNull DataLoaderParams dataLoaderParams)2108         public void setDataLoaderParams(@NonNull DataLoaderParams dataLoaderParams) {
2109             this.dataLoaderParams = dataLoaderParams;
2110         }
2111 
2112         /**
2113          *
2114          * {@hide}
2115          */
setForceQueryable()2116         public void setForceQueryable() {
2117             this.forceQueryableOverride = true;
2118         }
2119 
2120         /**
2121          * Optionally indicate whether user action should be required when the session is
2122          * committed.
2123          * <p>
2124          * Defaults to {@link #USER_ACTION_UNSPECIFIED} unless otherwise set. When unspecified for
2125          * installers using the
2126          * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES REQUEST_INSTALL_PACKAGES}
2127          * permission will behave as if set to {@link #USER_ACTION_REQUIRED}, and
2128          * {@link #USER_ACTION_NOT_REQUIRED} otherwise. When {@code requireUserAction} is set to
2129          * {@link #USER_ACTION_REQUIRED}, installers will receive a
2130          * {@link #STATUS_PENDING_USER_ACTION} callback once the session is committed, indicating
2131          * that user action is required for the install to proceed.
2132          * <p>
2133          * For installers that have been granted the
2134          * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES REQUEST_INSTALL_PACKAGES}
2135          * permission, user action will not be required when all of the following conditions are
2136          * met:
2137          *
2138          * <ul>
2139          *     <li>{@code requireUserAction} is set to {@link #USER_ACTION_NOT_REQUIRED}.</li>
2140          *     <li>The app being installed targets {@link android.os.Build.VERSION_CODES#Q API 29}
2141          *     or higher.</li>
2142          *     <li>The installer is the {@link InstallSourceInfo#getInstallingPackageName()
2143          *     installer of record} of an existing version of the app (in other words, this install
2144          *     session is an app update) or the installer is updating itself.</li>
2145          *     <li>The installer declares the
2146          *     {@link android.Manifest.permission#UPDATE_PACKAGES_WITHOUT_USER_ACTION
2147          *     UPDATE_PACKAGES_WITHOUT_USER_ACTION} permission.</li>
2148          * </ul>
2149          * <p>
2150          * Note: The target API level requirement will advance in future Android versions.
2151          * Session owners should always be prepared to handle {@link #STATUS_PENDING_USER_ACTION}.
2152          *
2153          * @param requireUserAction whether user action should be required.
2154          */
setRequireUserAction( @essionParams.UserActionRequirement int requireUserAction)2155         public void setRequireUserAction(
2156                 @SessionParams.UserActionRequirement int requireUserAction) {
2157             if (requireUserAction != USER_ACTION_UNSPECIFIED
2158                     && requireUserAction != USER_ACTION_REQUIRED
2159                     && requireUserAction != USER_ACTION_NOT_REQUIRED) {
2160                 throw new IllegalArgumentException("requireUserAction set as invalid value of "
2161                         + requireUserAction + ", but must be one of ["
2162                         + "USER_ACTION_UNSPECIFIED, USER_ACTION_REQUIRED, USER_ACTION_NOT_REQUIRED"
2163                         + "]");
2164             }
2165             this.requireUserAction = requireUserAction;
2166         }
2167 
2168         /**
2169          * Sets the install scenario for this session, which describes the expected user journey.
2170          */
setInstallScenario(@nstallScenario int installScenario)2171         public void setInstallScenario(@InstallScenario int installScenario) {
2172             this.installScenario = installScenario;
2173         }
2174 
2175         /** {@hide} */
dump(IndentingPrintWriter pw)2176         public void dump(IndentingPrintWriter pw) {
2177             pw.printPair("mode", mode);
2178             pw.printHexPair("installFlags", installFlags);
2179             pw.printPair("installLocation", installLocation);
2180             pw.printPair("installReason", installReason);
2181             pw.printPair("installScenario", installScenario);
2182             pw.printPair("sizeBytes", sizeBytes);
2183             pw.printPair("appPackageName", appPackageName);
2184             pw.printPair("appIcon", (appIcon != null));
2185             pw.printPair("appLabel", appLabel);
2186             pw.printPair("originatingUri", originatingUri);
2187             pw.printPair("originatingUid", originatingUid);
2188             pw.printPair("referrerUri", referrerUri);
2189             pw.printPair("abiOverride", abiOverride);
2190             pw.printPair("volumeUuid", volumeUuid);
2191             pw.printPair("grantedRuntimePermissions", grantedRuntimePermissions);
2192             pw.printPair("whitelistedRestrictedPermissions", whitelistedRestrictedPermissions);
2193             pw.printPair("autoRevokePermissions", autoRevokePermissionsMode);
2194             pw.printPair("installerPackageName", installerPackageName);
2195             pw.printPair("isMultiPackage", isMultiPackage);
2196             pw.printPair("isStaged", isStaged);
2197             pw.printPair("forceQueryable", forceQueryableOverride);
2198             pw.printPair("requireUserAction", SessionInfo.userActionToString(requireUserAction));
2199             pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode);
2200             pw.printPair("dataLoaderParams", dataLoaderParams);
2201             pw.printPair("rollbackDataPolicy", rollbackDataPolicy);
2202             pw.println();
2203         }
2204 
2205         @Override
describeContents()2206         public int describeContents() {
2207             return 0;
2208         }
2209 
2210         @Override
writeToParcel(Parcel dest, int flags)2211         public void writeToParcel(Parcel dest, int flags) {
2212             dest.writeInt(mode);
2213             dest.writeInt(installFlags);
2214             dest.writeInt(installLocation);
2215             dest.writeInt(installReason);
2216             dest.writeInt(installScenario);
2217             dest.writeLong(sizeBytes);
2218             dest.writeString(appPackageName);
2219             dest.writeParcelable(appIcon, flags);
2220             dest.writeString(appLabel);
2221             dest.writeParcelable(originatingUri, flags);
2222             dest.writeInt(originatingUid);
2223             dest.writeParcelable(referrerUri, flags);
2224             dest.writeString(abiOverride);
2225             dest.writeString(volumeUuid);
2226             dest.writeStringArray(grantedRuntimePermissions);
2227             dest.writeStringList(whitelistedRestrictedPermissions);
2228             dest.writeInt(autoRevokePermissionsMode);
2229             dest.writeString(installerPackageName);
2230             dest.writeBoolean(isMultiPackage);
2231             dest.writeBoolean(isStaged);
2232             dest.writeBoolean(forceQueryableOverride);
2233             dest.writeLong(requiredInstalledVersionCode);
2234             if (dataLoaderParams != null) {
2235                 dest.writeParcelable(dataLoaderParams.getData(), flags);
2236             } else {
2237                 dest.writeParcelable(null, flags);
2238             }
2239             dest.writeInt(rollbackDataPolicy);
2240             dest.writeInt(requireUserAction);
2241         }
2242 
2243         public static final Parcelable.Creator<SessionParams>
2244                 CREATOR = new Parcelable.Creator<SessionParams>() {
2245                     @Override
2246                     public SessionParams createFromParcel(Parcel p) {
2247                         return new SessionParams(p);
2248                     }
2249 
2250                     @Override
2251                     public SessionParams[] newArray(int size) {
2252                         return new SessionParams[size];
2253                     }
2254                 };
2255     }
2256 
2257     /**
2258      * Details for an active install session.
2259      */
2260     public static class SessionInfo implements Parcelable {
2261 
2262         /**
2263          * A session ID that does not exist or is invalid.
2264          */
2265         public static final int INVALID_ID = -1;
2266         /** {@hide} */
2267         private static final int[] NO_SESSIONS = {};
2268 
2269         /** @hide */
2270         @IntDef(prefix = { "STAGED_SESSION_" }, value = {
2271                 STAGED_SESSION_NO_ERROR,
2272                 STAGED_SESSION_VERIFICATION_FAILED,
2273                 STAGED_SESSION_ACTIVATION_FAILED,
2274                 STAGED_SESSION_UNKNOWN,
2275                 STAGED_SESSION_CONFLICT})
2276         @Retention(RetentionPolicy.SOURCE)
2277         public @interface StagedSessionErrorCode{}
2278         /**
2279          * Constant indicating that no error occurred during the preparation or the activation of
2280          * this staged session.
2281          */
2282         public static final int STAGED_SESSION_NO_ERROR = 0;
2283 
2284         /**
2285          * Constant indicating that an error occurred during the verification phase (pre-reboot) of
2286          * this staged session.
2287          */
2288         public static final int STAGED_SESSION_VERIFICATION_FAILED = 1;
2289 
2290         /**
2291          * Constant indicating that an error occurred during the activation phase (post-reboot) of
2292          * this staged session.
2293          */
2294         public static final int STAGED_SESSION_ACTIVATION_FAILED = 2;
2295 
2296         /**
2297          * Constant indicating that an unknown error occurred while processing this staged session.
2298          */
2299         public static final int STAGED_SESSION_UNKNOWN = 3;
2300 
2301         /**
2302          * Constant indicating that the session was in conflict with another staged session and had
2303          * to be sacrificed for resolution.
2304          */
2305         public static final int STAGED_SESSION_CONFLICT = 4;
2306 
userActionToString(int requireUserAction)2307         private static String userActionToString(int requireUserAction) {
2308             switch(requireUserAction) {
2309                 case SessionParams.USER_ACTION_REQUIRED:
2310                     return "REQUIRED";
2311                 case SessionParams.USER_ACTION_NOT_REQUIRED:
2312                     return "NOT_REQUIRED";
2313                 default:
2314                     return "UNSPECIFIED";
2315             }
2316         }
2317 
2318         /** {@hide} */
2319         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
2320         public int sessionId;
2321         /** {@hide} */
2322         public int userId;
2323         /** {@hide} */
2324         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
2325         public String installerPackageName;
2326         /** {@hide} */
2327         public String installerAttributionTag;
2328         /** {@hide} */
2329         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2330         public String resolvedBaseCodePath;
2331         /** {@hide} */
2332         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
2333         public float progress;
2334         /** {@hide} */
2335         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2336         public boolean sealed;
2337         /** {@hide} */
2338         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
2339         public boolean active;
2340 
2341         /** {@hide} */
2342         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
2343         public int mode;
2344         /** {@hide} */
2345         public @InstallReason int installReason;
2346         /** {@hide} */
2347         public @InstallScenario int installScenario;
2348         /** {@hide} */
2349         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
2350         public long sizeBytes;
2351         /** {@hide} */
2352         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
2353         public String appPackageName;
2354         /** {@hide} */
2355         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
2356         public Bitmap appIcon;
2357         /** {@hide} */
2358         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
2359         public CharSequence appLabel;
2360 
2361         /** {@hide} */
2362         public int installLocation;
2363         /** {@hide} */
2364         public Uri originatingUri;
2365         /** {@hide} */
2366         public int originatingUid;
2367         /** {@hide} */
2368         public Uri referrerUri;
2369         /** {@hide} */
2370         public String[] grantedRuntimePermissions;
2371         /** {@hide}*/
2372         public List<String> whitelistedRestrictedPermissions;
2373         /** {@hide}*/
2374         public int autoRevokePermissionsMode = MODE_DEFAULT;
2375         /** {@hide} */
2376         public int installFlags;
2377         /** {@hide} */
2378         public boolean isMultiPackage;
2379         /** {@hide} */
2380         public boolean isStaged;
2381         /** {@hide} */
2382         public boolean forceQueryable;
2383         /** {@hide} */
2384         public int parentSessionId = INVALID_ID;
2385         /** {@hide} */
2386         public int[] childSessionIds = NO_SESSIONS;
2387 
2388         /** {@hide} */
2389         public boolean isStagedSessionApplied;
2390         /** {@hide} */
2391         public boolean isStagedSessionReady;
2392         /** {@hide} */
2393         public boolean isStagedSessionFailed;
2394         private int mStagedSessionErrorCode;
2395         private String mStagedSessionErrorMessage;
2396 
2397         /** {@hide} */
2398         public boolean isCommitted;
2399 
2400         /** {@hide} */
2401         public long createdMillis;
2402 
2403         /** {@hide} */
2404         public long updatedMillis;
2405 
2406         /** {@hide} */
2407         public int rollbackDataPolicy;
2408 
2409         /** {@hide} */
2410         public int requireUserAction;
2411 
2412         /** {@hide} */
2413         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
SessionInfo()2414         public SessionInfo() {
2415         }
2416 
2417         /** {@hide} */
SessionInfo(Parcel source)2418         public SessionInfo(Parcel source) {
2419             sessionId = source.readInt();
2420             userId = source.readInt();
2421             installerPackageName = source.readString();
2422             installerAttributionTag = source.readString();
2423             resolvedBaseCodePath = source.readString();
2424             progress = source.readFloat();
2425             sealed = source.readInt() != 0;
2426             active = source.readInt() != 0;
2427 
2428             mode = source.readInt();
2429             installReason = source.readInt();
2430             installScenario = source.readInt();
2431             sizeBytes = source.readLong();
2432             appPackageName = source.readString();
2433             appIcon = source.readParcelable(null);
2434             appLabel = source.readString();
2435 
2436             installLocation = source.readInt();
2437             originatingUri = source.readParcelable(null);
2438             originatingUid = source.readInt();
2439             referrerUri = source.readParcelable(null);
2440             grantedRuntimePermissions = source.readStringArray();
2441             whitelistedRestrictedPermissions = source.createStringArrayList();
2442             autoRevokePermissionsMode = source.readInt();
2443 
2444             installFlags = source.readInt();
2445             isMultiPackage = source.readBoolean();
2446             isStaged = source.readBoolean();
2447             forceQueryable = source.readBoolean();
2448             parentSessionId = source.readInt();
2449             childSessionIds = source.createIntArray();
2450             if (childSessionIds == null) {
2451                 childSessionIds = NO_SESSIONS;
2452             }
2453             isStagedSessionApplied = source.readBoolean();
2454             isStagedSessionReady = source.readBoolean();
2455             isStagedSessionFailed = source.readBoolean();
2456             mStagedSessionErrorCode = source.readInt();
2457             mStagedSessionErrorMessage = source.readString();
2458             isCommitted = source.readBoolean();
2459             rollbackDataPolicy = source.readInt();
2460             createdMillis = source.readLong();
2461             requireUserAction = source.readInt();
2462         }
2463 
2464         /**
2465          * Return the ID for this session.
2466          */
getSessionId()2467         public int getSessionId() {
2468             return sessionId;
2469         }
2470 
2471         /**
2472          * Return the user associated with this session.
2473          */
getUser()2474         public @NonNull UserHandle getUser() {
2475             return new UserHandle(userId);
2476         }
2477 
2478         /**
2479          * Return the package name of the app that owns this session.
2480          */
getInstallerPackageName()2481         public @Nullable String getInstallerPackageName() {
2482             return installerPackageName;
2483         }
2484 
2485         /**
2486          * @return {@link android.content.Context#getAttributionTag attribution tag} of the context
2487          * that created this session
2488          */
getInstallerAttributionTag()2489         public @Nullable String getInstallerAttributionTag() {
2490             return installerAttributionTag;
2491         }
2492 
2493         /**
2494          * Return current overall progress of this session, between 0 and 1.
2495          * <p>
2496          * Note that this progress may not directly correspond to the value
2497          * reported by
2498          * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
2499          * system may carve out a portion of the overall progress to represent
2500          * its own internal installation work.
2501          */
getProgress()2502         public float getProgress() {
2503             return progress;
2504         }
2505 
2506         /**
2507          * Return if this session is currently active.
2508          * <p>
2509          * A session is considered active whenever there is ongoing forward
2510          * progress being made, such as the installer holding an open
2511          * {@link Session} instance while streaming data into place, or the
2512          * system optimizing code as the result of
2513          * {@link Session#commit(IntentSender)}.
2514          * <p>
2515          * If the installer closes the {@link Session} without committing, the
2516          * session is considered inactive until the installer opens the session
2517          * again.
2518          */
isActive()2519         public boolean isActive() {
2520             return active;
2521         }
2522 
2523         /**
2524          * Return if this session is sealed.
2525          * <p>
2526          * Once sealed, no further changes may be made to the session. A session
2527          * is sealed the moment {@link Session#commit(IntentSender)} is called.
2528          */
isSealed()2529         public boolean isSealed() {
2530             return sealed;
2531         }
2532 
2533         /**
2534          * Return the reason for installing this package.
2535          *
2536          * @return The install reason.
2537          */
getInstallReason()2538         public @InstallReason int getInstallReason() {
2539             return installReason;
2540         }
2541 
2542         /** {@hide} */
2543         @Deprecated
isOpen()2544         public boolean isOpen() {
2545             return isActive();
2546         }
2547 
2548         /**
2549          * Return the package name this session is working with. May be {@code null}
2550          * if unknown.
2551          */
getAppPackageName()2552         public @Nullable String getAppPackageName() {
2553             return appPackageName;
2554         }
2555 
2556         /**
2557          * Return an icon representing the app being installed. May be {@code null}
2558          * if unavailable.
2559          */
getAppIcon()2560         public @Nullable Bitmap getAppIcon() {
2561             if (appIcon == null) {
2562                 // Icon may have been omitted for calls that return bulk session
2563                 // lists, so try fetching the specific icon.
2564                 try {
2565                     final SessionInfo info = AppGlobals.getPackageManager().getPackageInstaller()
2566                             .getSessionInfo(sessionId);
2567                     appIcon = (info != null) ? info.appIcon : null;
2568                 } catch (RemoteException e) {
2569                     throw e.rethrowFromSystemServer();
2570                 }
2571             }
2572             return appIcon;
2573         }
2574 
2575         /**
2576          * Return a label representing the app being installed. May be {@code null}
2577          * if unavailable.
2578          */
getAppLabel()2579         public @Nullable CharSequence getAppLabel() {
2580             return appLabel;
2581         }
2582 
2583         /**
2584          * Return an Intent that can be started to view details about this install
2585          * session. This may surface actions such as pause, resume, or cancel.
2586          * <p>
2587          * In some cases, a matching Activity may not exist, so ensure you safeguard
2588          * against this.
2589          *
2590          * @see PackageInstaller#ACTION_SESSION_DETAILS
2591          */
createDetailsIntent()2592         public @Nullable Intent createDetailsIntent() {
2593             final Intent intent = new Intent(PackageInstaller.ACTION_SESSION_DETAILS);
2594             intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
2595             intent.setPackage(installerPackageName);
2596             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2597             return intent;
2598         }
2599 
2600         /**
2601          * Get the mode of the session as set in the constructor of the {@link SessionParams}.
2602          *
2603          * @return One of {@link SessionParams#MODE_FULL_INSTALL}
2604          *         or {@link SessionParams#MODE_INHERIT_EXISTING}
2605          */
getMode()2606         public int getMode() {
2607             return mode;
2608         }
2609 
2610         /**
2611          * Get the value set in {@link SessionParams#setInstallLocation(int)}.
2612          */
getInstallLocation()2613         public int getInstallLocation() {
2614             return installLocation;
2615         }
2616 
2617         /**
2618          * Get the value as set in {@link SessionParams#setSize(long)}.
2619          *
2620          * <p>The value is a hint and does not have to match the actual size.
2621          */
getSize()2622         public long getSize() {
2623             return sizeBytes;
2624         }
2625 
2626         /**
2627          * Get the value set in {@link SessionParams#setOriginatingUri(Uri)}.
2628          * Note: This value will only be non-null for the owner of the session.
2629          */
getOriginatingUri()2630         public @Nullable Uri getOriginatingUri() {
2631             return originatingUri;
2632         }
2633 
2634         /**
2635          * Get the value set in {@link SessionParams#setOriginatingUid(int)}.
2636          */
getOriginatingUid()2637         public int getOriginatingUid() {
2638             return originatingUid;
2639         }
2640 
2641         /**
2642          * Get the value set in {@link SessionParams#setReferrerUri(Uri)}
2643          * Note: This value will only be non-null for the owner of the session.
2644          */
getReferrerUri()2645         public @Nullable Uri getReferrerUri() {
2646             return referrerUri;
2647         }
2648 
2649         /**
2650          * Get the value set in {@link SessionParams#setGrantedRuntimePermissions(String[])}.
2651          *
2652          * @hide
2653          */
2654         @SystemApi
getGrantedRuntimePermissions()2655         public @Nullable String[] getGrantedRuntimePermissions() {
2656             return grantedRuntimePermissions;
2657         }
2658 
2659         /**
2660          * Get the value set in {@link SessionParams#setWhitelistedRestrictedPermissions(Set)}.
2661          * Note that if all permissions are allowlisted this method returns {@link
2662          * SessionParams#RESTRICTED_PERMISSIONS_ALL}.
2663          *
2664          * @hide
2665          */
2666         @SystemApi
getWhitelistedRestrictedPermissions()2667         public @NonNull Set<String> getWhitelistedRestrictedPermissions() {
2668             if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0) {
2669                 return SessionParams.RESTRICTED_PERMISSIONS_ALL;
2670             }
2671             if (whitelistedRestrictedPermissions != null) {
2672                 return new ArraySet<>(whitelistedRestrictedPermissions);
2673             }
2674             return Collections.emptySet();
2675         }
2676 
2677         /**
2678          * Get the status of whether permission auto-revocation should be allowed, ignored, or
2679          * deferred to manifest data.
2680          *
2681          * @see android.app.AppOpsManager#MODE_ALLOWED
2682          * @see android.app.AppOpsManager#MODE_IGNORED
2683          * @see android.app.AppOpsManager#MODE_DEFAULT
2684          *
2685          * @return the status of auto-revoke for this package
2686          *
2687          * @hide
2688          */
2689         @SystemApi
getAutoRevokePermissionsMode()2690         public int getAutoRevokePermissionsMode() {
2691             return autoRevokePermissionsMode;
2692         }
2693 
2694         /**
2695          * Get the value set in {@link SessionParams#setAllowDowngrade(boolean)}.
2696          *
2697          * @deprecated use {@link #getRequestDowngrade()}.
2698          * @hide
2699          */
2700         @SystemApi
2701         @Deprecated
getAllowDowngrade()2702         public boolean getAllowDowngrade() {
2703             return getRequestDowngrade();
2704         }
2705 
2706         /**
2707          * Get the value set in {@link SessionParams#setRequestDowngrade(boolean)}.
2708          *
2709          * @hide
2710          */
2711         @SystemApi
getRequestDowngrade()2712         public boolean getRequestDowngrade() {
2713             return (installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0;
2714         }
2715 
2716         /**
2717          * Get the value set in {@link SessionParams#setDontKillApp(boolean)}.
2718          *
2719          * @hide
2720          */
2721         @SystemApi
getDontKillApp()2722         public boolean getDontKillApp() {
2723             return (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0;
2724         }
2725 
2726         /**
2727          * Get if this session is to be installed as Instant Apps.
2728          *
2729          * @param isInstantApp an unused parameter and is ignored.
2730          * @return {@code true} if {@link SessionParams#setInstallAsInstantApp(boolean)} was called
2731          * with {@code true}; {@code false} if it was called with {@code false} or if it was not
2732          * called.
2733          *
2734          * @see #getInstallAsFullApp
2735          *
2736          * @hide
2737          */
2738         @SystemApi
getInstallAsInstantApp(boolean isInstantApp)2739         public boolean getInstallAsInstantApp(boolean isInstantApp) {
2740             return (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
2741         }
2742 
2743         /**
2744          * Get if this session is to be installed as full apps.
2745          *
2746          * @param isInstantApp an unused parameter and is ignored.
2747          * @return {@code true} if {@link SessionParams#setInstallAsInstantApp(boolean)} was called
2748          * with {@code false}; {code false} if it was called with {@code true} or if it was not
2749          * called.
2750          *
2751          * @see #getInstallAsInstantApp
2752          *
2753          * @hide
2754          */
2755         @SystemApi
getInstallAsFullApp(boolean isInstantApp)2756         public boolean getInstallAsFullApp(boolean isInstantApp) {
2757             return (installFlags & PackageManager.INSTALL_FULL_APP) != 0;
2758         }
2759 
2760         /**
2761          * Get if {@link SessionParams#setInstallAsVirtualPreload()} was called.
2762          *
2763          * @hide
2764          */
2765         @SystemApi
getInstallAsVirtualPreload()2766         public boolean getInstallAsVirtualPreload() {
2767             return (installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0;
2768         }
2769 
2770         /**
2771          * Return whether rollback is enabled or disabled for the given upgrade.
2772          *
2773          * @hide
2774          */
2775         @SystemApi
getEnableRollback()2776         public boolean getEnableRollback() {
2777             return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0;
2778         }
2779 
2780         /**
2781          * Get the value set in {@link SessionParams#setAllocateAggressive(boolean)}.
2782          *
2783          * @hide
2784          */
2785         @SystemApi
getAllocateAggressive()2786         public boolean getAllocateAggressive() {
2787             return (installFlags & PackageManager.INSTALL_ALLOCATE_AGGRESSIVE) != 0;
2788         }
2789 
2790 
2791         /** {@hide} */
2792         @Deprecated
getDetailsIntent()2793         public @Nullable Intent getDetailsIntent() {
2794             return createDetailsIntent();
2795         }
2796 
2797         /**
2798          * Returns true if this session is a multi-package session containing references to other
2799          * sessions.
2800          */
isMultiPackage()2801         public boolean isMultiPackage() {
2802             return isMultiPackage;
2803         }
2804 
2805         /**
2806          * Returns true if this session is a staged session.
2807          */
isStaged()2808         public boolean isStaged() {
2809             return isStaged;
2810         }
2811 
2812         /**
2813          * Return the data policy associated with the rollback for the given upgrade.
2814          *
2815          * @hide
2816          */
2817         @SystemApi
2818         @PackageManager.RollbackDataPolicy
getRollbackDataPolicy()2819         public int getRollbackDataPolicy() {
2820             return rollbackDataPolicy;
2821         }
2822 
2823         /**
2824          * Returns true if this session is marked as forceQueryable
2825          * {@hide}
2826          */
isForceQueryable()2827         public boolean isForceQueryable() {
2828             return forceQueryable;
2829         }
2830 
2831         /**
2832          * Returns {@code true} if this session is an active staged session.
2833          *
2834          * We consider a session active if it has been committed and it is either pending
2835          * verification, or will be applied at next reboot.
2836          *
2837          * <p>Staged session is active iff:
2838          * <ul>
2839          *     <li>It is committed, i.e. {@link SessionInfo#isCommitted()} is {@code true}, and
2840          *     <li>it is not applied, i.e. {@link SessionInfo#isStagedSessionApplied()} is {@code
2841          *     false}, and
2842          *     <li>it is not failed, i.e. {@link SessionInfo#isStagedSessionFailed()} is
2843          *     {@code false}.
2844          * </ul>
2845          *
2846          * <p>In case of a multi-package session, reasoning above is applied to the parent session,
2847          * since that is the one that should have been {@link Session#commit committed}.
2848          */
isStagedSessionActive()2849         public boolean isStagedSessionActive() {
2850             return isStaged && isCommitted && !isStagedSessionApplied && !isStagedSessionFailed
2851                     && !hasParentSessionId();
2852         }
2853 
2854         /**
2855          * Returns the parent multi-package session ID if this session belongs to one,
2856          * {@link #INVALID_ID} otherwise.
2857          */
getParentSessionId()2858         public int getParentSessionId() {
2859             return parentSessionId;
2860         }
2861 
2862         /**
2863          * Returns true if session has a valid parent session, otherwise false.
2864          */
hasParentSessionId()2865         public boolean hasParentSessionId() {
2866             return parentSessionId != INVALID_ID;
2867         }
2868 
2869         /**
2870          * Returns the set of session IDs that will be committed when this session is commited if
2871          * this session is a multi-package session.
2872          */
2873         @NonNull
getChildSessionIds()2874         public int[] getChildSessionIds() {
2875             return childSessionIds;
2876         }
2877 
checkSessionIsStaged()2878         private void checkSessionIsStaged() {
2879             if (!isStaged) {
2880                 throw new IllegalStateException("Session is not marked as staged.");
2881             }
2882         }
2883 
2884         /**
2885          * Whether the staged session has been applied successfully, meaning that all of its
2886          * packages have been activated and no further action is required.
2887          * Only meaningful if {@code isStaged} is true.
2888          */
isStagedSessionApplied()2889         public boolean isStagedSessionApplied() {
2890             checkSessionIsStaged();
2891             return isStagedSessionApplied;
2892         }
2893 
2894         /**
2895          * Whether the staged session is ready to be applied at next reboot. Only meaningful if
2896          * {@code isStaged} is true.
2897          */
isStagedSessionReady()2898         public boolean isStagedSessionReady() {
2899             checkSessionIsStaged();
2900             return isStagedSessionReady;
2901         }
2902 
2903         /**
2904          * Whether something went wrong and the staged session is declared as failed, meaning that
2905          * it will be ignored at next reboot. Only meaningful if {@code isStaged} is true.
2906          */
isStagedSessionFailed()2907         public boolean isStagedSessionFailed() {
2908             checkSessionIsStaged();
2909             return isStagedSessionFailed;
2910         }
2911 
2912         /**
2913          * If something went wrong with a staged session, clients can check this error code to
2914          * understand which kind of failure happened. Only meaningful if {@code isStaged} is true.
2915          */
getStagedSessionErrorCode()2916         public @StagedSessionErrorCode int getStagedSessionErrorCode() {
2917             checkSessionIsStaged();
2918             return mStagedSessionErrorCode;
2919         }
2920 
2921         /**
2922          * Text description of the error code returned by {@code getStagedSessionErrorCode}, or
2923          * empty string if no error was encountered.
2924          */
getStagedSessionErrorMessage()2925         public @NonNull String getStagedSessionErrorMessage() {
2926             checkSessionIsStaged();
2927             return mStagedSessionErrorMessage;
2928         }
2929 
2930         /** {@hide} */
setStagedSessionErrorCode(@tagedSessionErrorCode int errorCode, String errorMessage)2931         public void setStagedSessionErrorCode(@StagedSessionErrorCode int errorCode,
2932                                               String errorMessage) {
2933             mStagedSessionErrorCode = errorCode;
2934             mStagedSessionErrorMessage = errorMessage;
2935         }
2936 
2937         /**
2938          * Returns {@code true} if {@link Session#commit(IntentSender)}} was called for this
2939          * session.
2940          */
isCommitted()2941         public boolean isCommitted() {
2942             return isCommitted;
2943         }
2944 
2945         /**
2946          * The timestamp of the initial creation of the session.
2947          */
getCreatedMillis()2948         public long getCreatedMillis() {
2949             return createdMillis;
2950         }
2951 
2952         /**
2953          * The timestamp of the last update that occurred to the session, including changing of
2954          * states in case of staged sessions.
2955          */
2956         @CurrentTimeMillisLong
getUpdatedMillis()2957         public long getUpdatedMillis() {
2958             return updatedMillis;
2959         }
2960 
2961         /**
2962          * Whether user action was required by the installer.
2963          *
2964          * <p>
2965          * Note: a return value of {@code USER_ACTION_NOT_REQUIRED} does not guarantee that the
2966          * install will not result in user action.
2967          *
2968          * @return {@link SessionParams#USER_ACTION_NOT_REQUIRED},
2969          *         {@link SessionParams#USER_ACTION_REQUIRED} or
2970          *         {@link SessionParams#USER_ACTION_UNSPECIFIED}
2971          */
2972         @SessionParams.UserActionRequirement
getRequireUserAction()2973         public int getRequireUserAction() {
2974             return requireUserAction;
2975         }
2976 
2977         @Override
describeContents()2978         public int describeContents() {
2979             return 0;
2980         }
2981 
2982         @Override
writeToParcel(Parcel dest, int flags)2983         public void writeToParcel(Parcel dest, int flags) {
2984             dest.writeInt(sessionId);
2985             dest.writeInt(userId);
2986             dest.writeString(installerPackageName);
2987             dest.writeString(installerAttributionTag);
2988             dest.writeString(resolvedBaseCodePath);
2989             dest.writeFloat(progress);
2990             dest.writeInt(sealed ? 1 : 0);
2991             dest.writeInt(active ? 1 : 0);
2992 
2993             dest.writeInt(mode);
2994             dest.writeInt(installReason);
2995             dest.writeInt(installScenario);
2996             dest.writeLong(sizeBytes);
2997             dest.writeString(appPackageName);
2998             dest.writeParcelable(appIcon, flags);
2999             dest.writeString(appLabel != null ? appLabel.toString() : null);
3000 
3001             dest.writeInt(installLocation);
3002             dest.writeParcelable(originatingUri, flags);
3003             dest.writeInt(originatingUid);
3004             dest.writeParcelable(referrerUri, flags);
3005             dest.writeStringArray(grantedRuntimePermissions);
3006             dest.writeStringList(whitelistedRestrictedPermissions);
3007             dest.writeInt(autoRevokePermissionsMode);
3008             dest.writeInt(installFlags);
3009             dest.writeBoolean(isMultiPackage);
3010             dest.writeBoolean(isStaged);
3011             dest.writeBoolean(forceQueryable);
3012             dest.writeInt(parentSessionId);
3013             dest.writeIntArray(childSessionIds);
3014             dest.writeBoolean(isStagedSessionApplied);
3015             dest.writeBoolean(isStagedSessionReady);
3016             dest.writeBoolean(isStagedSessionFailed);
3017             dest.writeInt(mStagedSessionErrorCode);
3018             dest.writeString(mStagedSessionErrorMessage);
3019             dest.writeBoolean(isCommitted);
3020             dest.writeInt(rollbackDataPolicy);
3021             dest.writeLong(createdMillis);
3022             dest.writeInt(requireUserAction);
3023         }
3024 
3025         public static final Parcelable.Creator<SessionInfo>
3026                 CREATOR = new Parcelable.Creator<SessionInfo>() {
3027                     @Override
3028                     public SessionInfo createFromParcel(Parcel p) {
3029                         return new SessionInfo(p);
3030                     }
3031 
3032                     @Override
3033                     public SessionInfo[] newArray(int size) {
3034                         return new SessionInfo[size];
3035                     }
3036                 };
3037     }
3038 }
3039