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