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