• 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 import static android.content.pm.PackageInfo.INSTALL_LOCATION_AUTO;
30 import static android.content.pm.PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
31 import static android.content.pm.PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL;
32 
33 import android.Manifest;
34 import android.annotation.CallbackExecutor;
35 import android.annotation.CurrentTimeMillisLong;
36 import android.annotation.DurationMillisLong;
37 import android.annotation.FlaggedApi;
38 import android.annotation.IntDef;
39 import android.annotation.NonNull;
40 import android.annotation.Nullable;
41 import android.annotation.RequiresPermission;
42 import android.annotation.SdkConstant;
43 import android.annotation.SdkConstant.SdkConstantType;
44 import android.annotation.SuppressLint;
45 import android.annotation.SystemApi;
46 import android.annotation.TestApi;
47 import android.app.ActivityManager;
48 import android.app.ActivityThread;
49 import android.app.AppGlobals;
50 import android.app.PendingIntent;
51 import android.compat.annotation.UnsupportedAppUsage;
52 import android.content.BroadcastReceiver;
53 import android.content.Context;
54 import android.content.Intent;
55 import android.content.IntentFilter;
56 import android.content.IntentSender;
57 import android.content.pm.PackageManager.DeleteFlags;
58 import android.content.pm.PackageManager.InstallReason;
59 import android.content.pm.PackageManager.InstallScenario;
60 import android.content.pm.parsing.ApkLiteParseUtils;
61 import android.content.pm.parsing.PackageLite;
62 import android.content.pm.parsing.result.ParseResult;
63 import android.content.pm.parsing.result.ParseTypeImpl;
64 import android.content.pm.verify.domain.DomainSet;
65 import android.graphics.Bitmap;
66 import android.icu.util.ULocale;
67 import android.net.Uri;
68 import android.os.Build;
69 import android.os.FileBridge;
70 import android.os.Handler;
71 import android.os.HandlerExecutor;
72 import android.os.Parcel;
73 import android.os.ParcelFileDescriptor;
74 import android.os.Parcelable;
75 import android.os.ParcelableException;
76 import android.os.PersistableBundle;
77 import android.os.RemoteCallback;
78 import android.os.RemoteException;
79 import android.os.SystemProperties;
80 import android.os.UserHandle;
81 import android.system.ErrnoException;
82 import android.system.Os;
83 import android.text.TextUtils;
84 import android.util.ArrayMap;
85 import android.util.ArraySet;
86 import android.util.ExceptionUtils;
87 
88 import com.android.internal.content.InstallLocationUtils;
89 import com.android.internal.util.ArrayUtils;
90 import com.android.internal.util.DataClass;
91 import com.android.internal.util.IndentingPrintWriter;
92 import com.android.internal.util.Preconditions;
93 import com.android.internal.util.function.pooled.PooledLambda;
94 
95 import java.io.Closeable;
96 import java.io.File;
97 import java.io.FileNotFoundException;
98 import java.io.IOException;
99 import java.io.InputStream;
100 import java.io.OutputStream;
101 import java.lang.annotation.Retention;
102 import java.lang.annotation.RetentionPolicy;
103 import java.security.MessageDigest;
104 import java.security.cert.Certificate;
105 import java.security.cert.CertificateEncodingException;
106 import java.security.cert.X509Certificate;
107 import java.util.ArrayList;
108 import java.util.Collection;
109 import java.util.Collections;
110 import java.util.Iterator;
111 import java.util.List;
112 import java.util.Objects;
113 import java.util.Set;
114 import java.util.concurrent.Executor;
115 import java.util.function.Consumer;
116 
117 /**
118  * Offers the ability to install, upgrade, and remove applications on the
119  * device. This includes support for apps packaged either as a single
120  * "monolithic" APK, or apps packaged as multiple "split" APKs.
121  * <p>
122  * An app is delivered for installation through a
123  * {@link PackageInstaller.Session}, which any app can create. Once the session
124  * is created, the installer can stream one or more APKs into place until it
125  * decides to either commit or destroy the session. Committing may require user
126  * intervention to complete the installation, unless the caller falls into one of the
127  * following categories, in which case the installation will complete automatically.
128  * <ul>
129  * <li>the device owner
130  * <li>the affiliated profile owner
131  * </ul>
132  * <p>
133  * Sessions can install brand new apps, upgrade existing apps, or add new splits
134  * into an existing app.
135  * <p>
136  * Apps packaged as multiple split APKs always consist of a single "base" APK
137  * (with a {@code null} split name) and zero or more "split" APKs (with unique
138  * split names). Any subset of these APKs can be installed together, as long as
139  * the following constraints are met:
140  * <ul>
141  * <li>All APKs must have the exact same package name, version code, and signing
142  * certificates.
143  * <li>All APKs must have unique split names.
144  * <li>All installations must contain a single base APK.
145  * </ul>
146  * <p>
147  * The ApiDemos project contains examples of using this API:
148  * <code>ApiDemos/src/com/example/android/apis/content/InstallApk*.java</code>.
149  */
150 public class PackageInstaller {
151     private static final String TAG = "PackageInstaller";
152 
153     private static final String ACTION_WAIT_INSTALL_CONSTRAINTS =
154             "android.content.pm.action.WAIT_INSTALL_CONSTRAINTS";
155 
156     /** {@hide} */
157     public static final boolean ENABLE_REVOCABLE_FD =
158             SystemProperties.getBoolean("fw.revocable_fd", false);
159 
160     /**
161      * Activity Action: Show details about a particular install session. This
162      * may surface actions such as pause, resume, or cancel.
163      * <p>
164      * This should always be scoped to the installer package that owns the
165      * session. Clients should use {@link SessionInfo#createDetailsIntent()} to
166      * build this intent correctly.
167      * <p>
168      * In some cases, a matching Activity may not exist, so ensure you safeguard
169      * against this.
170      * <p>
171      * The session to show details for is defined in {@link #EXTRA_SESSION_ID}.
172      */
173     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
174     public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
175 
176     /**
177      * Broadcast Action: Explicit broadcast sent to the last known default launcher when a session
178      * for a new install is committed. For managed profile, this is sent to the default launcher
179      * of the primary profile.
180      * For user-profiles that have items restricted on home screen, this broadcast is sent to
181      * the default launcher of the primary profile, only if it has either
182      * {@link Manifest.permission.ACCESS_HIDDEN_PROFILES_FULL} or
183      * {@link Manifest.permission.ACCESS_HIDDEN_PROFILES} permission.
184      * <p>
185      * The associated session is defined in {@link #EXTRA_SESSION} and the user for which this
186      * session was created in {@link Intent#EXTRA_USER}.
187      */
188     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
189     public static final String ACTION_SESSION_COMMITTED =
190             "android.content.pm.action.SESSION_COMMITTED";
191 
192     /**
193      * Broadcast Action: Send information about a staged install session when its state is updated.
194      * <p>
195      * The associated session information is defined in {@link #EXTRA_SESSION}.
196      */
197     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
198     public static final String ACTION_SESSION_UPDATED =
199             "android.content.pm.action.SESSION_UPDATED";
200 
201     /**
202      * Intent action to indicate that user action is required for current install. This action can
203      * be used only by system apps.
204      *
205      * @hide
206      */
207     @SystemApi
208     public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL";
209 
210     /**
211      * Activity Action: Intent sent to the installer when a session for requesting
212      * user pre-approval, and user needs to confirm the installation.
213      *
214      * @hide
215      */
216     @SystemApi
217     public static final String ACTION_CONFIRM_PRE_APPROVAL =
218             "android.content.pm.action.CONFIRM_PRE_APPROVAL";
219 
220     /**
221      * Intent action to be sent to the implementer of
222      * {@link android.content.pm.dependencyinstaller.DependencyInstallerService}.
223      *
224      * @hide
225      */
226     @FlaggedApi(Flags.FLAG_SDK_DEPENDENCY_INSTALLER)
227     @SystemApi
228     public static final String ACTION_INSTALL_DEPENDENCY =
229             "android.content.pm.action.INSTALL_DEPENDENCY";
230 
231     /**
232      * An integer session ID that an operation is working with.
233      *
234      * @see Intent#getIntExtra(String, int)
235      */
236     public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
237 
238     /**
239      * {@link SessionInfo} that an operation is working with.
240      *
241      * @see Intent#getParcelableExtra(String)
242      */
243     public static final String EXTRA_SESSION = "android.content.pm.extra.SESSION";
244 
245     /**
246      * Package name that an operation is working with.
247      *
248      * @see Intent#getStringExtra(String)
249      */
250     public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
251 
252     /**
253      * Current status of an operation. Will be one of
254      * {@link #STATUS_PENDING_USER_ACTION}, {@link #STATUS_SUCCESS},
255      * {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED},
256      * {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT},
257      * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID},
258      * {@link #STATUS_FAILURE_STORAGE}, or {@link #STATUS_FAILURE_TIMEOUT}.
259      * <p>
260      * More information about a status may be available through additional
261      * extras; see the individual status documentation for details.
262      *
263      * @see Intent#getIntExtra(String, int)
264      */
265     public static final String EXTRA_STATUS = "android.content.pm.extra.STATUS";
266 
267     /**
268      * Indicate if the status is for a pre-approval request.
269      *
270      * If callers use the same {@link IntentSender} for both
271      * {@link Session#requestUserPreapproval(PreapprovalDetails, IntentSender)} and
272      * {@link Session#commit(IntentSender)}, they can use this to differentiate between them.
273      *
274      * @see Intent#getBooleanExtra(String, boolean)
275      */
276     public static final String EXTRA_PRE_APPROVAL = "android.content.pm.extra.PRE_APPROVAL";
277 
278     /**
279      * Detailed string representation of the status, including raw details that
280      * are useful for debugging.
281      *
282      * @see Intent#getStringExtra(String)
283      */
284     public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
285 
286     /**
287      * Another package name relevant to a status. This is typically the package
288      * responsible for causing an operation failure.
289      *
290      * @see Intent#getStringExtra(String)
291      */
292     public static final String
293             EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
294 
295     /**
296      * Storage path relevant to a status.
297      *
298      * @see Intent#getStringExtra(String)
299      */
300     public static final String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH";
301 
302     /**
303      * The {@link InstallConstraints} object.
304      *
305      * @see Intent#getParcelableExtra(String, Class)
306      * @see #waitForInstallConstraints(List, InstallConstraints, IntentSender, long)
307      */
308     public static final String EXTRA_INSTALL_CONSTRAINTS =
309             "android.content.pm.extra.INSTALL_CONSTRAINTS";
310 
311     /**
312      * The {@link InstallConstraintsResult} object.
313      *
314      * @see Intent#getParcelableExtra(String, Class)
315      * @see #waitForInstallConstraints(List, InstallConstraints, IntentSender, long)
316      */
317     public static final String EXTRA_INSTALL_CONSTRAINTS_RESULT =
318             "android.content.pm.extra.INSTALL_CONSTRAINTS_RESULT";
319 
320     /** {@hide} */
321     @Deprecated
322     public static final String EXTRA_PACKAGE_NAMES = "android.content.pm.extra.PACKAGE_NAMES";
323 
324     /**
325      * The status as used internally in the package manager. Refer to {@link PackageManager} for
326      * a list of all valid legacy statuses.
327      *
328      * @hide
329      */
330     @SystemApi
331     public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS";
332     /** {@hide} */
333     public static final String EXTRA_LEGACY_BUNDLE = "android.content.pm.extra.LEGACY_BUNDLE";
334     /**
335      * The callback to execute once an uninstall is completed (used for both successful and
336      * unsuccessful uninstalls).
337      *
338      * @hide
339      */
340     @SystemApi
341     public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK";
342     /**
343      * Key for passing extra delete flags during archiving.
344      *
345      * @hide
346      */
347     @SystemApi
348     @FlaggedApi(android.content.pm.Flags.FLAG_ARCHIVING)
349     public static final String EXTRA_DELETE_FLAGS = "android.content.pm.extra.DELETE_FLAGS";
350 
351     /**
352      * Type of DataLoader for this session. Will be one of
353      * {@link #DATA_LOADER_TYPE_NONE}, {@link #DATA_LOADER_TYPE_STREAMING},
354      * {@link #DATA_LOADER_TYPE_INCREMENTAL}.
355      * <p>
356      * See the individual types documentation for details.
357      *
358      * @see Intent#getIntExtra(String, int)
359      * {@hide}
360      */
361     @SystemApi
362     public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE";
363 
364     /**
365      * Path to the validated base APK for this session, which may point at an
366      * APK inside the session (when the session defines the base), or it may
367      * point at the existing base APK (when adding splits to an existing app).
368      *
369      * @hide
370      * @deprecated Resolved base path of an install session should not be available to unauthorized
371      * callers. Use {@link SessionInfo#getResolvedBaseApkPath()} instead.
372      */
373     @Deprecated
374     @SystemApi
375     public static final String EXTRA_RESOLVED_BASE_PATH =
376             "android.content.pm.extra.RESOLVED_BASE_PATH";
377 
378     /**
379      * Extra field for the package name of a package that is requested to be unarchived. Sent as
380      * part of the {@link android.content.Intent#ACTION_UNARCHIVE_PACKAGE} intent.
381      */
382     @FlaggedApi(Flags.FLAG_ARCHIVING)
383     public static final String EXTRA_UNARCHIVE_PACKAGE_NAME =
384             "android.content.pm.extra.UNARCHIVE_PACKAGE_NAME";
385 
386     /**
387      * Extra field for the unarchive ID. Sent as
388      * part of the {@link android.content.Intent#ACTION_UNARCHIVE_PACKAGE} intent.
389      *
390      * @see SessionParams#setUnarchiveId
391      */
392     @FlaggedApi(Flags.FLAG_ARCHIVING)
393     public static final String EXTRA_UNARCHIVE_ID =
394             "android.content.pm.extra.UNARCHIVE_ID";
395 
396     /**
397      * If true, the requestor of the unarchival has specified that the app should be unarchived
398      * for all users. Sent as part of the {@link android.content.Intent#ACTION_UNARCHIVE_PACKAGE}
399      * intent.
400      */
401     @FlaggedApi(Flags.FLAG_ARCHIVING)
402     public static final String EXTRA_UNARCHIVE_ALL_USERS =
403             "android.content.pm.extra.UNARCHIVE_ALL_USERS";
404 
405     /**
406      * Current status of an unarchive operation. Will be one of
407      * {@link #UNARCHIVAL_OK}, {@link #UNARCHIVAL_ERROR_USER_ACTION_NEEDED},
408      * {@link #UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE}, {@link #UNARCHIVAL_ERROR_NO_CONNECTIVITY},
409      * {@link #UNARCHIVAL_GENERIC_ERROR}, {@link #UNARCHIVAL_ERROR_INSTALLER_DISABLED} or
410      * {@link #UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED}.
411      *
412      * <p> If the status is not {@link #UNARCHIVAL_OK}, then {@link Intent#EXTRA_INTENT} will be set
413      * with an intent for a corresponding follow-up action (e.g. storage clearing dialog) or a
414      * failure dialog.
415      *
416      * <p> Used as part of {@link #requestUnarchive} to return the status of the unarchival through
417      * the {@link IntentSender}.
418      *
419      * @see #requestUnarchive
420      */
421     @FlaggedApi(Flags.FLAG_ARCHIVING)
422     public static final String EXTRA_UNARCHIVE_STATUS = "android.content.pm.extra.UNARCHIVE_STATUS";
423 
424     /**
425      * A list of warnings that occurred during installation.
426      *
427      * @hide
428      */
429     public static final String EXTRA_WARNINGS = "android.content.pm.extra.WARNINGS";
430 
431     /**
432      * Streaming installation pending.
433      * Caller should make sure DataLoader is able to prepare image and reinitiate the operation.
434      *
435      * @see #EXTRA_SESSION_ID
436      * {@hide}
437      */
438     public static final int STATUS_PENDING_STREAMING = -2;
439 
440     /**
441      * User action is currently required to proceed. You can launch the intent
442      * activity described by {@link Intent#EXTRA_INTENT} to involve the user and
443      * continue.
444      * <p>
445      * You may choose to immediately launch the intent if the user is actively
446      * using your app. Otherwise, you should use a notification to guide the
447      * user back into your app before launching.
448      *
449      * @see Intent#getParcelableExtra(String)
450      */
451     public static final int STATUS_PENDING_USER_ACTION = -1;
452 
453     /**
454      * The operation succeeded.
455      */
456     public static final int STATUS_SUCCESS = 0;
457 
458     /**
459      * The operation failed in a generic way. The system will always try to
460      * provide a more specific failure reason, but in some rare cases this may
461      * be delivered.
462      *
463      * @see #EXTRA_STATUS_MESSAGE
464      */
465     public static final int STATUS_FAILURE = 1;
466 
467     /**
468      * The operation failed because it was blocked. For example, a device policy
469      * may be blocking the operation, a package verifier may have blocked the
470      * operation, or the app may be required for core system operation.
471      * <p>
472      * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
473      * specific package blocking the install.
474      *
475      * @see #EXTRA_STATUS_MESSAGE
476      * @see #EXTRA_OTHER_PACKAGE_NAME
477      */
478     public static final int STATUS_FAILURE_BLOCKED = 2;
479 
480     /**
481      * The operation failed because it was actively aborted. For example, the
482      * user actively declined requested permissions, or the session was
483      * abandoned.
484      *
485      * @see #EXTRA_STATUS_MESSAGE
486      */
487     public static final int STATUS_FAILURE_ABORTED = 3;
488 
489     /**
490      * The operation failed because one or more of the APKs was invalid. For
491      * example, they might be malformed, corrupt, incorrectly signed,
492      * mismatched, etc.
493      *
494      * @see #EXTRA_STATUS_MESSAGE
495      */
496     public static final int STATUS_FAILURE_INVALID = 4;
497 
498     /**
499      * The operation failed because it conflicts (or is inconsistent with) with
500      * another package already installed on the device. For example, an existing
501      * permission, incompatible certificates, etc. The user may be able to
502      * uninstall another app to fix the issue.
503      * <p>
504      * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
505      * specific package identified as the cause of the conflict.
506      *
507      * @see #EXTRA_STATUS_MESSAGE
508      * @see #EXTRA_OTHER_PACKAGE_NAME
509      */
510     public static final int STATUS_FAILURE_CONFLICT = 5;
511 
512     /**
513      * The operation failed because of storage issues. For example, the device
514      * may be running low on space, or external media may be unavailable. The
515      * user may be able to help free space or insert different external media.
516      * <p>
517      * The result may also contain {@link #EXTRA_STORAGE_PATH} with the path to
518      * the storage device that caused the failure.
519      *
520      * @see #EXTRA_STATUS_MESSAGE
521      * @see #EXTRA_STORAGE_PATH
522      */
523     public static final int STATUS_FAILURE_STORAGE = 6;
524 
525     /**
526      * The operation failed because it is fundamentally incompatible with this
527      * device. For example, the app may require a hardware feature that doesn't
528      * exist, it may be missing native code for the ABIs supported by the
529      * device, or it requires a newer SDK version, etc.
530      *
531      * Starting in {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, an app with only 32-bit native
532      * code can still be installed on a device that supports both 64-bit and 32-bit ABIs.
533      * However, a warning dialog will be displayed when the app is launched.
534      *
535      * @see #EXTRA_STATUS_MESSAGE
536      */
537     public static final int STATUS_FAILURE_INCOMPATIBLE = 7;
538 
539     /**
540      * The operation failed because it didn't complete within the specified timeout.
541      *
542      * @see #EXTRA_STATUS_MESSAGE
543      */
544     public static final int STATUS_FAILURE_TIMEOUT = 8;
545 
546     /**
547      * Default value, non-streaming installation session.
548      *
549      * @see #EXTRA_DATA_LOADER_TYPE
550      * {@hide}
551      */
552     @SystemApi
553     public static final int DATA_LOADER_TYPE_NONE = DataLoaderType.NONE;
554 
555     /**
556      * Streaming installation using data loader.
557      *
558      * @see #EXTRA_DATA_LOADER_TYPE
559      * {@hide}
560      */
561     @SystemApi
562     public static final int DATA_LOADER_TYPE_STREAMING = DataLoaderType.STREAMING;
563 
564     /**
565      * Streaming installation using Incremental FileSystem.
566      *
567      * @see #EXTRA_DATA_LOADER_TYPE
568      * {@hide}
569      */
570     @SystemApi
571     public static final int DATA_LOADER_TYPE_INCREMENTAL = DataLoaderType.INCREMENTAL;
572 
573     /**
574      * Target location for the file in installation session is /data/app/<packageName>-<id>.
575      * This is the intended location for APKs.
576      * Requires permission to install packages.
577      * {@hide}
578      */
579     @SystemApi
580     public static final int LOCATION_DATA_APP = InstallationFileLocation.DATA_APP;
581 
582     /**
583      * Target location for the file in installation session is
584      * /data/media/<userid>/Android/obb/<packageName>. This is the intended location for OBBs.
585      * {@hide}
586      */
587     @SystemApi
588     public static final int LOCATION_MEDIA_OBB = InstallationFileLocation.MEDIA_OBB;
589 
590     /**
591      * Target location for the file in installation session is
592      * /data/media/<userid>/Android/data/<packageName>.
593      * This is the intended location for application data.
594      * Can only be used by an app itself running under specific user.
595      * {@hide}
596      */
597     @SystemApi
598     public static final int LOCATION_MEDIA_DATA = InstallationFileLocation.MEDIA_DATA;
599 
600     /** @hide */
601     @IntDef(prefix = { "LOCATION_" }, value = {
602             LOCATION_DATA_APP,
603             LOCATION_MEDIA_OBB,
604             LOCATION_MEDIA_DATA})
605     @Retention(RetentionPolicy.SOURCE)
606     public @interface FileLocation{}
607 
608     /**
609      * The installer did not call {@link PackageInstaller.SessionParams#setPackageSource(int)} to
610      * specify the package source.
611      */
612     public static final int PACKAGE_SOURCE_UNSPECIFIED = 0;
613 
614     /**
615      * Code indicating that the package being installed is from a source not reflected by any
616      * other package source constant.
617      */
618     public static final int PACKAGE_SOURCE_OTHER = 1;
619 
620     /**
621      * Code indicating that the package being installed is from a store. An app store that
622      * installs an app for the user would use this.
623      */
624     public static final int PACKAGE_SOURCE_STORE = 2;
625 
626     /**
627      * Code indicating that the package being installed comes from a local file on the device. A
628      * file manager that is facilitating the installation of an APK file would use this.
629      */
630     public static final int PACKAGE_SOURCE_LOCAL_FILE = 3;
631 
632     /**
633      * Code indicating that the package being installed comes from a file that was downloaded to
634      * the device by the user. For use in place of {@link #PACKAGE_SOURCE_LOCAL_FILE} when the
635      * installer knows the package was downloaded.
636      */
637     public static final int PACKAGE_SOURCE_DOWNLOADED_FILE = 4;
638 
639     /** @hide */
640     @IntDef(prefix = { "PACKAGE_SOURCE_" }, value = {
641             PACKAGE_SOURCE_UNSPECIFIED,
642             PACKAGE_SOURCE_STORE,
643             PACKAGE_SOURCE_LOCAL_FILE,
644             PACKAGE_SOURCE_DOWNLOADED_FILE,
645             PACKAGE_SOURCE_OTHER
646     })
647     @Retention(RetentionPolicy.SOURCE)
648     @interface PackageSourceType{}
649 
650     /**
651      * Indicate the user intervention is required when the installer attempts to commit the session.
652      * This is the default case.
653      *
654      * @hide
655      */
656     @SystemApi
657     public static final int REASON_CONFIRM_PACKAGE_CHANGE = 0;
658 
659     /**
660      * Indicate the user intervention is required because the update ownership enforcement is
661      * enabled, and the update owner will change.
662      *
663      * @see PackageInstaller.SessionParams#setRequestUpdateOwnership
664      * @see InstallSourceInfo#getUpdateOwnerPackageName
665      * @hide
666      */
667     @SystemApi
668     public static final int REASON_OWNERSHIP_CHANGED = 1;
669 
670     /**
671      * Indicate the user intervention is required because the update ownership enforcement is
672      * enabled, and remind the update owner is a different package.
673      *
674      * @see PackageInstaller.SessionParams#setRequestUpdateOwnership
675      * @see InstallSourceInfo#getUpdateOwnerPackageName
676      * @hide
677      */
678     @SystemApi
679     public static final int REASON_REMIND_OWNERSHIP = 2;
680 
681     /** @hide */
682     @IntDef(prefix = { "REASON_" }, value = {
683             REASON_CONFIRM_PACKAGE_CHANGE,
684             REASON_OWNERSHIP_CHANGED,
685             REASON_REMIND_OWNERSHIP,
686     })
687     @Retention(RetentionPolicy.SOURCE)
688     public @interface UserActionReason {}
689 
690     /**
691      * The unarchival status is not set.
692      *
693      * @hide
694      */
695     public static final int UNARCHIVAL_STATUS_UNSET = -1;
696 
697     /**
698      * The unarchival is possible and will commence.
699      *
700      * <p> Note that this does not mean that the unarchival has completed. This status should be
701      * sent before any longer asynchronous action (e.g. app download) is started.
702      */
703     @FlaggedApi(Flags.FLAG_ARCHIVING)
704     public static final int UNARCHIVAL_OK = 0;
705 
706     /**
707      * The user needs to interact with the installer to enable the installation.
708      *
709      * <p> An example use case for this could be that the user needs to login to allow the
710      * download for a paid app.
711      */
712     @FlaggedApi(Flags.FLAG_ARCHIVING)
713     public static final int UNARCHIVAL_ERROR_USER_ACTION_NEEDED = 1;
714 
715     /**
716      * Not enough storage to unarchive the application.
717      *
718      * <p> The installer can optionally provide a {@code userActionIntent} for a space-clearing
719      * dialog. If no action is provided, then a generic intent
720      * {@link android.os.storage.StorageManager#ACTION_MANAGE_STORAGE} is started instead.
721      */
722     @FlaggedApi(Flags.FLAG_ARCHIVING)
723     public static final int UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE = 2;
724 
725     /**
726      * The device is not connected to the internet
727      */
728     @FlaggedApi(Flags.FLAG_ARCHIVING)
729     public static final int UNARCHIVAL_ERROR_NO_CONNECTIVITY = 3;
730 
731     /**
732      * The installer responsible for the unarchival is disabled.
733      *
734      * <p> The system will return this status if appropriate. Installers do not need to verify for
735      * this error.
736      */
737     @FlaggedApi(Flags.FLAG_ARCHIVING)
738     public static final int UNARCHIVAL_ERROR_INSTALLER_DISABLED = 4;
739 
740     /**
741      * The installer responsible for the unarchival has been uninstalled
742      *
743      * <p> The system will return this status if appropriate. Installers do not need to verify for
744      * this error.
745      */
746     @FlaggedApi(Flags.FLAG_ARCHIVING)
747     public static final int UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED = 5;
748 
749     /**
750      * Generic error: The app cannot be unarchived.
751      */
752     @FlaggedApi(Flags.FLAG_ARCHIVING)
753     public static final int UNARCHIVAL_GENERIC_ERROR = 100;
754 
755     /**
756      * The set of error types that can be set for
757      * {@link #reportUnarchivalState}.
758      *
759      * @hide
760      */
761     @IntDef(value = {
762             UNARCHIVAL_STATUS_UNSET,
763             UNARCHIVAL_OK,
764             UNARCHIVAL_ERROR_USER_ACTION_NEEDED,
765             UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE,
766             UNARCHIVAL_ERROR_NO_CONNECTIVITY,
767             UNARCHIVAL_ERROR_INSTALLER_DISABLED,
768             UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED,
769             UNARCHIVAL_GENERIC_ERROR,
770     })
771     @Retention(RetentionPolicy.SOURCE)
772     public @interface UnarchivalStatus {}
773 
774 
775     /** Default set of checksums - includes all available checksums.
776      * @see Session#requestChecksums  */
777     private static final int DEFAULT_CHECKSUMS =
778             TYPE_WHOLE_MERKLE_ROOT_4K_SHA256 | TYPE_WHOLE_MD5 | TYPE_WHOLE_SHA1 | TYPE_WHOLE_SHA256
779                     | TYPE_WHOLE_SHA512 | TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256
780                     | TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512;
781 
782     private final IPackageInstaller mInstaller;
783     private final int mUserId;
784     private final String mInstallerPackageName;
785     private final String mAttributionTag;
786 
787     private final ArrayList<SessionCallbackDelegate> mDelegates = new ArrayList<>();
788 
789     /** {@hide} */
PackageInstaller(IPackageInstaller installer, String installerPackageName, String installerAttributionTag, int userId)790     public PackageInstaller(IPackageInstaller installer,
791             String installerPackageName, String installerAttributionTag, int userId) {
792         Objects.requireNonNull(installer, "installer cannot be null");
793         mInstaller = installer;
794         mInstallerPackageName = installerPackageName;
795         mAttributionTag = installerAttributionTag;
796         mUserId = userId;
797     }
798 
799     /**
800      * Create a new session using the given parameters, returning a unique ID
801      * that represents the session. Once created, the session can be opened
802      * multiple times across multiple device boots.
803      * <p>
804      * The system may automatically destroy sessions that have not been
805      * finalized (either committed or abandoned) within a reasonable period of
806      * time, typically on the order of a day.
807      *
808      * @throws IOException if parameters were unsatisfiable, such as lack of
809      *             disk space or unavailable media.
810      * @throws SecurityException when installation services are unavailable,
811      *             such as when called from a restricted user.
812      * @throws IllegalArgumentException when {@link SessionParams} is invalid.
813      * @return positive, non-zero unique ID that represents the created session.
814      *         This ID remains consistent across device reboots until the
815      *         session is finalized. IDs are not reused during a given boot.
816      */
createSession(@onNull SessionParams params)817     public int createSession(@NonNull SessionParams params) throws IOException {
818         try {
819             return mInstaller.createSession(params, mInstallerPackageName, mAttributionTag,
820                     mUserId);
821         } catch (RuntimeException e) {
822             ExceptionUtils.maybeUnwrapIOException(e);
823             throw e;
824         } catch (RemoteException e) {
825             throw e.rethrowFromSystemServer();
826         }
827     }
828 
829     /**
830      * Open an existing session to actively perform work. To succeed, the caller
831      * must be the owner of the install session.
832      *
833      * @throws IOException if parameters were unsatisfiable, such as lack of
834      *             disk space or unavailable media.
835      * @throws SecurityException when the caller does not own the session, or
836      *             the session is invalid.
837      */
openSession(int sessionId)838     public @NonNull Session openSession(int sessionId) throws IOException {
839         try {
840             try {
841                 return new Session(mInstaller.openSession(sessionId));
842             } catch (RemoteException e) {
843                 throw e.rethrowFromSystemServer();
844             }
845         } catch (RuntimeException e) {
846             ExceptionUtils.maybeUnwrapIOException(e);
847             throw e;
848         }
849     }
850 
851     /**
852      * Update the icon representing the app being installed in a specific
853      * session. This should be roughly
854      * {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions.
855      *
856      * @throws SecurityException when the caller does not own the session, or
857      *             the session is invalid.
858      */
updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon)859     public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) {
860         try {
861             mInstaller.updateSessionAppIcon(sessionId, appIcon);
862         } catch (RemoteException e) {
863             throw e.rethrowFromSystemServer();
864         }
865     }
866 
867     /**
868      * Update the label representing the app being installed in a specific
869      * session.
870      *
871      * @throws SecurityException when the caller does not own the session, or
872      *             the session is invalid.
873      */
updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel)874     public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) {
875         try {
876             final String val = (appLabel != null) ? appLabel.toString() : null;
877             mInstaller.updateSessionAppLabel(sessionId, val);
878         } catch (RemoteException e) {
879             throw e.rethrowFromSystemServer();
880         }
881     }
882 
883     /**
884      * Completely abandon the given session, destroying all staged data and
885      * rendering it invalid. Abandoned sessions will be reported to
886      * {@link SessionCallback} listeners as failures. This is equivalent to
887      * opening the session and calling {@link Session#abandon()}.
888      *
889      * @throws SecurityException when the caller does not own the session, or
890      *             the session is invalid.
891      */
abandonSession(int sessionId)892     public void abandonSession(int sessionId) {
893         try {
894             mInstaller.abandonSession(sessionId);
895         } catch (RemoteException e) {
896             throw e.rethrowFromSystemServer();
897         }
898     }
899 
900     /**
901      * Return details for a specific session. Callers need to either declare &lt;queries&gt;
902      * element with the specific package name in the app's manifest, have the
903      * android.permission.QUERY_ALL_PACKAGES, or be the session owner to retrieve these details.
904      *
905      * @return details for the requested session, or {@code null} if the session
906      *         does not exist.
907      */
getSessionInfo(int sessionId)908     public @Nullable SessionInfo getSessionInfo(int sessionId) {
909         try {
910             return mInstaller.getSessionInfo(sessionId);
911         } catch (RemoteException e) {
912             throw e.rethrowFromSystemServer();
913         }
914     }
915 
916     /**
917      * Return list of all known install sessions, regardless of the installer. Callers need to
918      * either declare &lt;queries&gt; element with the specific  package name in the app's manifest,
919      * have the android.permission.QUERY_ALL_PACKAGES, or be the session owner to retrieve these
920      * details.
921      */
getAllSessions()922     public @NonNull List<SessionInfo> getAllSessions() {
923         try {
924             return mInstaller.getAllSessions(mUserId).getList();
925         } catch (RemoteException e) {
926             throw e.rethrowFromSystemServer();
927         }
928     }
929 
930     /**
931      * Return list of all known install sessions owned by the calling app.
932      */
getMySessions()933     public @NonNull List<SessionInfo> getMySessions() {
934         try {
935             return mInstaller.getMySessions(mInstallerPackageName, mUserId).getList();
936         } catch (RemoteException e) {
937             throw e.rethrowFromSystemServer();
938         }
939     }
940 
941     /**
942      * Return list of all staged install sessions. Callers need to either declare &lt;queries&gt;
943      * element with the specific package name in the app's manifest, have the
944      * android.permission.QUERY_ALL_PACKAGES, or be the session owner to retrieve these details.
945      */
getStagedSessions()946     public @NonNull List<SessionInfo> getStagedSessions() {
947         try {
948             // TODO: limit this to the mUserId?
949             return mInstaller.getStagedSessions().getList();
950         } catch (RemoteException e) {
951             throw e.rethrowFromSystemServer();
952         }
953     }
954 
955     /**
956      * Returns first active staged session, or {@code null} if there is none.
957      *
958      * <p>For more information on what sessions are considered active see
959      * {@link SessionInfo#isStagedSessionActive()}.
960      *
961      * @deprecated Use {@link #getActiveStagedSessions} as there can be more than one active staged
962      * session
963      */
964     @Deprecated
getActiveStagedSession()965     public @Nullable SessionInfo getActiveStagedSession() {
966         List<SessionInfo> activeSessions = getActiveStagedSessions();
967         return activeSessions.isEmpty() ? null : activeSessions.get(0);
968     }
969 
970     /**
971      * Returns list of active staged sessions. Returns empty list if there is none.
972      *
973      * <p>For more information on what sessions are considered active see
974      *      * {@link SessionInfo#isStagedSessionActive()}.
975      */
getActiveStagedSessions()976     public @NonNull List<SessionInfo> getActiveStagedSessions() {
977         final List<SessionInfo> activeStagedSessions = new ArrayList<>();
978         final List<SessionInfo> stagedSessions = getStagedSessions();
979         for (int i = 0; i < stagedSessions.size(); i++) {
980             final SessionInfo sessionInfo = stagedSessions.get(i);
981             if (sessionInfo.isStagedSessionActive()) {
982                 activeStagedSessions.add(sessionInfo);
983             }
984         }
985         return activeStagedSessions;
986     }
987 
988     /**
989      * Uninstall the given package, removing it completely from the device. This
990      * method is available to:
991      * <ul>
992      * <li>the current "installer of record" for the package
993      * <li>the device owner
994      * <li>the affiliated profile owner
995      * </ul>
996      *
997      * @param packageName The package to uninstall.
998      * @param statusReceiver Where to deliver the result of the operation indicated by the extra
999      *                       {@link #EXTRA_STATUS}. Refer to the individual status codes
1000      *                       on how to handle them.
1001      *
1002      * @see android.app.admin.DevicePolicyManager
1003      */
1004     @RequiresPermission(anyOf = {
1005             Manifest.permission.DELETE_PACKAGES,
1006             Manifest.permission.REQUEST_DELETE_PACKAGES})
uninstall(@onNull String packageName, @NonNull IntentSender statusReceiver)1007     public void uninstall(@NonNull String packageName, @NonNull IntentSender statusReceiver) {
1008         uninstall(packageName, 0 /*flags*/, statusReceiver);
1009     }
1010 
1011     /**
1012      * Uninstall the given package, removing it completely from the device. This
1013      * method is only available to the current "installer of record" for the
1014      * package.
1015      *
1016      * @param packageName The package to uninstall.
1017      * @param flags Flags for uninstall.
1018      * @param statusReceiver Where to deliver the result of the operation indicated by the extra
1019      *                       {@link #EXTRA_STATUS}. Refer to the individual status codes
1020      *                       on how to handle them.
1021      *
1022      * @hide
1023      */
uninstall(@onNull String packageName, @DeleteFlags int flags, @NonNull IntentSender statusReceiver)1024     public void uninstall(@NonNull String packageName, @DeleteFlags int flags,
1025             @NonNull IntentSender statusReceiver) {
1026         uninstall(new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
1027                 flags, statusReceiver);
1028     }
1029 
1030     /**
1031      * Uninstall the given package with a specific version code, removing it
1032      * completely from the device. If the version code of the package
1033      * does not match the one passed in the versioned package argument this
1034      * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to
1035      * uninstall the latest version of the package.
1036      * <p>
1037      * This method is available to:
1038      * <ul>
1039      * <li>the current "installer of record" for the package
1040      * <li>the device owner
1041      * <li>the affiliated profile owner
1042      * </ul>
1043      *
1044      * @param versionedPackage The versioned package to uninstall.
1045      * @param statusReceiver Where to deliver the result of the operation indicated by the extra
1046      *                       {@link #EXTRA_STATUS}. Refer to the individual status codes
1047      *                       on how to handle them.
1048      *
1049      * @see android.app.admin.DevicePolicyManager
1050      */
1051     @RequiresPermission(anyOf = {
1052             Manifest.permission.DELETE_PACKAGES,
1053             Manifest.permission.REQUEST_DELETE_PACKAGES})
uninstall(@onNull VersionedPackage versionedPackage, @NonNull IntentSender statusReceiver)1054     public void uninstall(@NonNull VersionedPackage versionedPackage,
1055             @NonNull IntentSender statusReceiver) {
1056         uninstall(versionedPackage, 0 /*flags*/, statusReceiver);
1057     }
1058 
1059     /**
1060      * Uninstall the given package with a specific version code, removing it
1061      * completely from the device. This method is only available to the current
1062      * "installer of record" for the package. If the version code of the package
1063      * does not match the one passed in the versioned package argument this
1064      * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to
1065      * uninstall the latest version of the package.
1066      *
1067      * @param versionedPackage The versioned package to uninstall.
1068      * @param flags Flags for uninstall.
1069      * @param statusReceiver Where to deliver the result of the operation indicated by the extra
1070      *                       {@link #EXTRA_STATUS}. Refer to the individual status codes
1071      *                       on how to handle them.
1072      */
1073     @RequiresPermission(anyOf = {
1074             Manifest.permission.DELETE_PACKAGES,
1075             Manifest.permission.REQUEST_DELETE_PACKAGES})
uninstall(@onNull VersionedPackage versionedPackage, @DeleteFlags int flags, @NonNull IntentSender statusReceiver)1076     public void uninstall(@NonNull VersionedPackage versionedPackage, @DeleteFlags int flags,
1077             @NonNull IntentSender statusReceiver) {
1078         Objects.requireNonNull(versionedPackage, "versionedPackage cannot be null");
1079         try {
1080             mInstaller.uninstall(versionedPackage, mInstallerPackageName,
1081                     flags, statusReceiver, mUserId);
1082         } catch (RemoteException e) {
1083             throw e.rethrowFromSystemServer();
1084         }
1085     }
1086 
1087     /**
1088      * Install the given package, which already exists on the device, for the user for which this
1089      * installer was created.
1090      *
1091      * <p>This will
1092      * {@link PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set) allowlist
1093      * all restricted permissions}.
1094      *
1095      * @param packageName The package to install.
1096      * @param installReason Reason for install.
1097      * @param statusReceiver Where to deliver the result of the operation indicated by the extra
1098      *                       {@link #EXTRA_STATUS}. Refer to the individual status codes
1099      *                       on how to handle them.
1100      */
1101     @RequiresPermission(allOf = {
1102             Manifest.permission.INSTALL_PACKAGES,
1103             Manifest.permission.INSTALL_EXISTING_PACKAGES})
installExistingPackage(@onNull String packageName, @InstallReason int installReason, @Nullable IntentSender statusReceiver)1104     public void installExistingPackage(@NonNull String packageName,
1105             @InstallReason int installReason,
1106             @Nullable IntentSender statusReceiver) {
1107         Objects.requireNonNull(packageName, "packageName cannot be null");
1108         try {
1109             mInstaller.installExistingPackage(packageName,
1110                     PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS, installReason,
1111                     statusReceiver, mUserId, null);
1112         } catch (RemoteException e) {
1113             throw e.rethrowFromSystemServer();
1114         }
1115     }
1116 
1117     /**
1118      * Uninstall the given package for the user for which this installer was created if the package
1119      * will still exist for other users on the device.
1120      *
1121      * @param packageName The package to uninstall.
1122      * @param statusReceiver Where to deliver the result of the operation indicated by the extra
1123      *                       {@link #EXTRA_STATUS}. Refer to the individual status codes
1124      *                       on how to handle them.
1125      */
1126     @RequiresPermission(Manifest.permission.DELETE_PACKAGES)
uninstallExistingPackage(@onNull String packageName, @Nullable IntentSender statusReceiver)1127     public void uninstallExistingPackage(@NonNull String packageName,
1128             @Nullable IntentSender statusReceiver) {
1129         Objects.requireNonNull(packageName, "packageName cannot be null");
1130         try {
1131             mInstaller.uninstallExistingPackage(
1132                     new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
1133                     mInstallerPackageName, statusReceiver, mUserId);
1134         } catch (RemoteException e) {
1135             throw e.rethrowFromSystemServer();
1136         }
1137     }
1138 
1139     /**
1140      * Install package in an archived state.
1141      *
1142      * @param archivedPackageInfo archived package data such as package name, signature etc.
1143      * @param sessionParams used to create an underlying installation session
1144      * @param statusReceiver Called when the state of the session changes. Intents
1145      *                       sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
1146      *                       individual status codes on how to handle them.
1147      * @see #createSession
1148      * @see PackageInstaller.Session#commit
1149      */
1150     @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
1151     @FlaggedApi(Flags.FLAG_ARCHIVING)
installPackageArchived(@onNull ArchivedPackageInfo archivedPackageInfo, @NonNull SessionParams sessionParams, @NonNull IntentSender statusReceiver)1152     public void installPackageArchived(@NonNull ArchivedPackageInfo archivedPackageInfo,
1153             @NonNull SessionParams sessionParams,
1154             @NonNull IntentSender statusReceiver) {
1155         Objects.requireNonNull(archivedPackageInfo, "archivedPackageInfo cannot be null");
1156         Objects.requireNonNull(sessionParams, "sessionParams cannot be null");
1157         Objects.requireNonNull(statusReceiver, "statusReceiver cannot be null");
1158         try {
1159             mInstaller.installPackageArchived(
1160                     archivedPackageInfo.getParcel(),
1161                     sessionParams,
1162                     statusReceiver,
1163                     mInstallerPackageName,
1164                     new UserHandle(mUserId));
1165         } catch (RemoteException e) {
1166             throw e.rethrowFromSystemServer();
1167         }
1168     }
1169 
1170     /** {@hide} */
1171     @SystemApi
1172     @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
setPermissionsResult(int sessionId, boolean accepted)1173     public void setPermissionsResult(int sessionId, boolean accepted) {
1174         try {
1175             mInstaller.setPermissionsResult(sessionId, accepted);
1176         } catch (RemoteException e) {
1177             throw e.rethrowFromSystemServer();
1178         }
1179     }
1180 
1181     /**
1182      * Check if install constraints are satisfied for the given packages.
1183      *
1184      * Note this query result is just a hint and subject to race because system states could
1185      * change anytime in-between this query and committing the session.
1186      *
1187      * The result is returned by a callback because some constraints might take a long time
1188      * to evaluate.
1189      *
1190      * @param packageNames a list of package names to check the constraints for installation
1191      * @param constraints the constraints for installation.
1192      * @param executor the {@link Executor} on which to invoke the callback
1193      * @param callback called when the {@link InstallConstraintsResult} is ready
1194      *
1195      * @throws SecurityException if the given packages' installer of record doesn't match the
1196      *             caller's own package name or the installerPackageName set by the caller doesn't
1197      *             match the caller's own package name.
1198      */
checkInstallConstraints(@onNull List<String> packageNames, @NonNull InstallConstraints constraints, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<InstallConstraintsResult> callback)1199     public void checkInstallConstraints(@NonNull List<String> packageNames,
1200             @NonNull InstallConstraints constraints,
1201             @NonNull @CallbackExecutor Executor executor,
1202             @NonNull Consumer<InstallConstraintsResult> callback) {
1203         Objects.requireNonNull(executor);
1204         Objects.requireNonNull(callback);
1205         try {
1206             var remoteCallback = new RemoteCallback(b -> {
1207                 executor.execute(() -> {
1208                     callback.accept(b.getParcelable("result", InstallConstraintsResult.class));
1209                 });
1210             });
1211             mInstaller.checkInstallConstraints(
1212                     mInstallerPackageName, packageNames, constraints, remoteCallback);
1213         } catch (RemoteException e) {
1214             throw e.rethrowFromSystemServer();
1215         }
1216     }
1217 
1218     /**
1219      * Similar to {@link #checkInstallConstraints(List, InstallConstraints, Executor, Consumer)},
1220      * but the callback is invoked only when the constraints are satisfied or after timeout.
1221      * <p>
1222      * Note: the device idle constraint might take a long time to evaluate. The system will
1223      * ensure the constraint is evaluated completely before handling timeout.
1224      *
1225      * @param packageNames a list of package names to check the constraints for installation
1226      * @param constraints the constraints for installation.
1227      * @param callback Called when the constraints are satisfied or after timeout.
1228      *                 Intents sent to this callback contain:
1229      *                 {@link Intent#EXTRA_PACKAGES} for the input package names,
1230      *                 {@link #EXTRA_INSTALL_CONSTRAINTS} for the input constraints,
1231      *                 {@link #EXTRA_INSTALL_CONSTRAINTS_RESULT} for the result.
1232      * @param timeoutMillis The maximum time to wait, in milliseconds until the constraints are
1233      *                      satisfied. Valid range is from 0 to one week. {@code 0} means the
1234      *                      callback will be invoked immediately no matter constraints are
1235      *                      satisfied or not.
1236      * @throws SecurityException if the given packages' installer of record doesn't match the
1237      *             caller's own package name or the installerPackageName set by the caller doesn't
1238      *             match the caller's own package name.
1239      */
waitForInstallConstraints(@onNull List<String> packageNames, @NonNull InstallConstraints constraints, @NonNull IntentSender callback, @DurationMillisLong long timeoutMillis)1240     public void waitForInstallConstraints(@NonNull List<String> packageNames,
1241             @NonNull InstallConstraints constraints,
1242             @NonNull IntentSender callback,
1243             @DurationMillisLong long timeoutMillis) {
1244         try {
1245             mInstaller.waitForInstallConstraints(
1246                     mInstallerPackageName, packageNames, constraints, callback, timeoutMillis);
1247         } catch (RemoteException e) {
1248             throw e.rethrowFromSystemServer();
1249         }
1250     }
1251 
1252     /**
1253      * Commit the session when all constraints are satisfied. This is a convenient method to
1254      * combine {@link #waitForInstallConstraints(List, InstallConstraints, IntentSender, long)}
1255      * and {@link Session#commit(IntentSender)}.
1256      * <p>
1257      * Once this method is called, the session is sealed and no additional mutations
1258      * may be performed on the session. In the case of timeout, you may commit the
1259      * session again using this method or {@link Session#commit(IntentSender)} for retries.
1260      *
1261      * @param sessionId the session ID to commit when all constraints are satisfied.
1262      * @param statusReceiver Called when the state of the session changes. Intents
1263      *                       sent to this receiver contain {@link #EXTRA_STATUS}.
1264      *                       Refer to the individual status codes on how to handle them.
1265      * @param constraints The requirements to satisfy before committing the session.
1266      * @param timeoutMillis The maximum time to wait, in milliseconds until the
1267      *                      constraints are satisfied. The caller will be notified via
1268      *                      {@code statusReceiver} if timeout happens before commit.
1269      * @throws IllegalArgumentException if the {@code statusReceiver} from an immutable
1270      *             {@link android.app.PendingIntent} when caller has a target SDK of API
1271      *             35 or above.
1272      */
commitSessionAfterInstallConstraintsAreMet(int sessionId, @NonNull IntentSender statusReceiver, @NonNull InstallConstraints constraints, @DurationMillisLong long timeoutMillis)1273     public void commitSessionAfterInstallConstraintsAreMet(int sessionId,
1274             @NonNull IntentSender statusReceiver, @NonNull InstallConstraints constraints,
1275             @DurationMillisLong long timeoutMillis) {
1276         try {
1277             var session = mInstaller.openSession(sessionId);
1278             session.seal();
1279             var packageNames = session.fetchPackageNames();
1280             var context = ActivityThread.currentApplication();
1281             var localIntentSender = new LocalIntentSender(context, sessionId, session,
1282                     statusReceiver);
1283             waitForInstallConstraints(packageNames, constraints,
1284                     localIntentSender.getIntentSender(), timeoutMillis);
1285         } catch (RemoteException e) {
1286             throw e.rethrowFromSystemServer();
1287         }
1288     }
1289 
1290     private static final class LocalIntentSender extends BroadcastReceiver {
1291 
1292         private final Context mContext;
1293         private final IntentSender mStatusReceiver;
1294         private final int mSessionId;
1295         private final IPackageInstallerSession mSession;
1296 
LocalIntentSender(Context context, int sessionId, IPackageInstallerSession session, IntentSender statusReceiver)1297         LocalIntentSender(Context context, int sessionId, IPackageInstallerSession session,
1298                 IntentSender statusReceiver) {
1299             mContext = context;
1300             mSessionId = sessionId;
1301             mSession = session;
1302             mStatusReceiver = statusReceiver;
1303         }
1304 
getIntentSender()1305         private IntentSender getIntentSender() {
1306             Intent intent = new Intent(ACTION_WAIT_INSTALL_CONSTRAINTS).setPackage(
1307                     mContext.getPackageName());
1308             mContext.registerReceiver(this, new IntentFilter(ACTION_WAIT_INSTALL_CONSTRAINTS),
1309                     Context.RECEIVER_EXPORTED);
1310             PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent,
1311                     PendingIntent.FLAG_MUTABLE);
1312             return pendingIntent.getIntentSender();
1313         }
1314 
1315         @Override
onReceive(Context context, Intent intent)1316         public void onReceive(Context context, Intent intent) {
1317             InstallConstraintsResult result = intent.getParcelableExtra(
1318                     PackageInstaller.EXTRA_INSTALL_CONSTRAINTS_RESULT,
1319                     InstallConstraintsResult.class);
1320             try {
1321                 if (result.areAllConstraintsSatisfied()) {
1322                     mSession.commit(mStatusReceiver, false);
1323                 } else {
1324                     // timeout
1325                     final Intent fillIn = new Intent();
1326                     fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
1327                     fillIn.putExtra(PackageInstaller.EXTRA_STATUS, STATUS_FAILURE_TIMEOUT);
1328                     fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
1329                             "Install constraints not satisfied within timeout");
1330                     mStatusReceiver.sendIntent(ActivityThread.currentApplication(), 0, fillIn, null,
1331                             null);
1332                 }
1333             } catch (Exception ignore) {
1334                 // no-op
1335             } finally {
1336                 unregisterReceiver();
1337             }
1338         }
1339 
unregisterReceiver()1340         private void unregisterReceiver() {
1341             mContext.unregisterReceiver(this);
1342         }
1343     }
1344 
1345     /**
1346      * Events for observing session lifecycle.
1347      * <p>
1348      * A typical session lifecycle looks like this:
1349      * <ul>
1350      * <li>An installer creates a session to indicate pending app delivery. All
1351      * install details are available at this point.
1352      * <li>The installer opens the session to deliver APK data. Note that a
1353      * session may be opened and closed multiple times as network connectivity
1354      * changes. The installer may deliver periodic progress updates.
1355      * <li>The installer commits or abandons the session, resulting in the
1356      * session being finished.
1357      * </ul>
1358      */
1359     public static abstract class SessionCallback {
1360         /**
1361          * New session has been created. Details about the session can be
1362          * obtained from {@link PackageInstaller#getSessionInfo(int)}.
1363          */
onCreated(int sessionId)1364         public abstract void onCreated(int sessionId);
1365 
1366         /**
1367          * Badging details for an existing session has changed. For example, the
1368          * app icon or label has been updated.
1369          */
onBadgingChanged(int sessionId)1370         public abstract void onBadgingChanged(int sessionId);
1371 
1372         /**
1373          * Active state for session has been changed.
1374          * <p>
1375          * A session is considered active whenever there is ongoing forward
1376          * progress being made, such as the installer holding an open
1377          * {@link Session} instance while streaming data into place, or the
1378          * system optimizing code as the result of
1379          * {@link Session#commit(IntentSender)}.
1380          * <p>
1381          * If the installer closes the {@link Session} without committing, the
1382          * session is considered inactive until the installer opens the session
1383          * again.
1384          */
onActiveChanged(int sessionId, boolean active)1385         public abstract void onActiveChanged(int sessionId, boolean active);
1386 
1387         /**
1388          * Progress for given session has been updated.
1389          * <p>
1390          * Note that this progress may not directly correspond to the value
1391          * reported by
1392          * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
1393          * system may carve out a portion of the overall progress to represent
1394          * its own internal installation work.
1395          */
onProgressChanged(int sessionId, float progress)1396         public abstract void onProgressChanged(int sessionId, float progress);
1397 
1398         /**
1399          * Session has completely finished, either with success or failure.
1400          */
onFinished(int sessionId, boolean success)1401         public abstract void onFinished(int sessionId, boolean success);
1402     }
1403 
1404     /** {@hide} */
1405     static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub {
1406         private static final int MSG_SESSION_CREATED = 1;
1407         private static final int MSG_SESSION_BADGING_CHANGED = 2;
1408         private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
1409         private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
1410         private static final int MSG_SESSION_FINISHED = 5;
1411 
1412         final SessionCallback mCallback;
1413         final Executor mExecutor;
1414 
SessionCallbackDelegate(SessionCallback callback, Executor executor)1415         SessionCallbackDelegate(SessionCallback callback, Executor executor) {
1416             mCallback = callback;
1417             mExecutor = executor;
1418         }
1419 
1420         @Override
onSessionCreated(int sessionId)1421         public void onSessionCreated(int sessionId) {
1422             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onCreated, mCallback,
1423                     sessionId).recycleOnUse());
1424         }
1425 
1426         @Override
onSessionBadgingChanged(int sessionId)1427         public void onSessionBadgingChanged(int sessionId) {
1428             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onBadgingChanged,
1429                     mCallback, sessionId).recycleOnUse());
1430         }
1431 
1432         @Override
onSessionActiveChanged(int sessionId, boolean active)1433         public void onSessionActiveChanged(int sessionId, boolean active) {
1434             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onActiveChanged,
1435                     mCallback, sessionId, active).recycleOnUse());
1436         }
1437 
1438         @Override
onSessionProgressChanged(int sessionId, float progress)1439         public void onSessionProgressChanged(int sessionId, float progress) {
1440             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onProgressChanged,
1441                     mCallback, sessionId, progress).recycleOnUse());
1442         }
1443 
1444         @Override
onSessionFinished(int sessionId, boolean success)1445         public void onSessionFinished(int sessionId, boolean success) {
1446             mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onFinished,
1447                     mCallback, sessionId, success).recycleOnUse());
1448         }
1449     }
1450 
1451     /** {@hide} */
1452     @Deprecated
addSessionCallback(@onNull SessionCallback callback)1453     public void addSessionCallback(@NonNull SessionCallback callback) {
1454         registerSessionCallback(callback);
1455     }
1456 
1457     /**
1458      * Register to watch for session lifecycle events. The callers need to be the session
1459      * owner or have the android.permission.QUERY_ALL_PACKAGES to watch for these events.
1460      */
registerSessionCallback(@onNull SessionCallback callback)1461     public void registerSessionCallback(@NonNull SessionCallback callback) {
1462         registerSessionCallback(callback, new Handler());
1463     }
1464 
1465     /** {@hide} */
1466     @Deprecated
addSessionCallback(@onNull SessionCallback callback, @NonNull Handler handler)1467     public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
1468         registerSessionCallback(callback, handler);
1469     }
1470 
1471     /**
1472      * Register to watch for session lifecycle events. No special permissions
1473      * are required to watch for these events.
1474      *
1475      * @param handler to dispatch callback events through, otherwise uses
1476      *            calling thread.
1477      */
registerSessionCallback(@onNull SessionCallback callback, @NonNull Handler handler)1478     public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
1479         synchronized (mDelegates) {
1480             final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
1481                     new HandlerExecutor(handler));
1482             try {
1483                 mInstaller.registerCallback(delegate, mUserId);
1484             } catch (RemoteException e) {
1485                 throw e.rethrowFromSystemServer();
1486             }
1487             mDelegates.add(delegate);
1488         }
1489     }
1490 
1491     /** {@hide} */
1492     @Deprecated
removeSessionCallback(@onNull SessionCallback callback)1493     public void removeSessionCallback(@NonNull SessionCallback callback) {
1494         unregisterSessionCallback(callback);
1495     }
1496 
1497     /**
1498      * Unregister a previously registered callback.
1499      */
unregisterSessionCallback(@onNull SessionCallback callback)1500     public void unregisterSessionCallback(@NonNull SessionCallback callback) {
1501         synchronized (mDelegates) {
1502             for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
1503                 final SessionCallbackDelegate delegate = i.next();
1504                 if (delegate.mCallback == callback) {
1505                     try {
1506                         mInstaller.unregisterCallback(delegate);
1507                     } catch (RemoteException e) {
1508                         throw e.rethrowFromSystemServer();
1509                     }
1510                     i.remove();
1511                 }
1512             }
1513         }
1514     }
1515 
1516     /**
1517      * An installation that is being actively staged. For an install to succeed,
1518      * all existing and new packages must have identical package names, version
1519      * codes, and signing certificates.
1520      * <p>
1521      * A session may contain any number of split packages. If the application
1522      * does not yet exist, this session must include a base package.
1523      * <p>
1524      * If an APK included in this session is already defined by the existing
1525      * installation (for example, the same split name), the APK in this session
1526      * will replace the existing APK.
1527      * <p>
1528      * In such a case that multiple packages need to be committed simultaneously,
1529      * multiple sessions can be referenced by a single multi-package session.
1530      * This session is created with no package name and calling
1531      * {@link SessionParams#setMultiPackage()}. The individual session IDs can be
1532      * added with {@link #addChildSessionId(int)} and commit of the multi-package
1533      * session will result in all child sessions being committed atomically.
1534      */
1535     public static class Session implements Closeable {
1536         /** {@hide} */
1537         protected final IPackageInstallerSession mSession;
1538 
1539         /** {@hide} */
Session(IPackageInstallerSession session)1540         public Session(IPackageInstallerSession session) {
1541             mSession = session;
1542         }
1543 
1544         /** {@hide} */
1545         @Deprecated
setProgress(float progress)1546         public void setProgress(float progress) {
1547             setStagingProgress(progress);
1548         }
1549 
1550         /**
1551          * Set current progress of staging this session. Valid values are
1552          * anywhere between 0 and 1.
1553          * <p>
1554          * Note that this progress may not directly correspond to the value
1555          * reported by {@link SessionCallback#onProgressChanged(int, float)}, as
1556          * the system may carve out a portion of the overall progress to
1557          * represent its own internal installation work.
1558          */
setStagingProgress(float progress)1559         public void setStagingProgress(float progress) {
1560             try {
1561                 mSession.setClientProgress(progress);
1562             } catch (RemoteException e) {
1563                 throw e.rethrowFromSystemServer();
1564             }
1565         }
1566 
1567         /** {@hide} */
1568         @UnsupportedAppUsage
addProgress(float progress)1569         public void addProgress(float progress) {
1570             try {
1571                 mSession.addClientProgress(progress);
1572             } catch (RemoteException e) {
1573                 throw e.rethrowFromSystemServer();
1574             }
1575         }
1576 
1577         /**
1578          * Open a stream to write an APK file into the session.
1579          * <p>
1580          * The returned stream will start writing data at the requested offset
1581          * in the underlying file, which can be used to resume a partially
1582          * written file. If a valid file length is specified, the system will
1583          * preallocate the underlying disk space to optimize placement on disk.
1584          * It's strongly recommended to provide a valid file length when known.
1585          * <p>
1586          * You can write data into the returned stream, optionally call
1587          * {@link #fsync(OutputStream)} as needed to ensure bytes have been
1588          * persisted to disk, and then close when finished. All streams must be
1589          * closed before calling {@link #commit(IntentSender)}.
1590          *
1591          * @param name arbitrary, unique name of your choosing to identify the
1592          *            APK being written. You can open a file again for
1593          *            additional writes (such as after a reboot) by using the
1594          *            same name. This name is only meaningful within the context
1595          *            of a single install session.
1596          * @param offsetBytes offset into the file to begin writing at, or 0 to
1597          *            start at the beginning of the file.
1598          * @param lengthBytes total size of the file being written, used to
1599          *            preallocate the underlying disk space, or -1 if unknown.
1600          *            The system may clear various caches as needed to allocate
1601          *            this space.
1602          * @throws IOException if trouble opening the file for writing, such as
1603          *             lack of disk space or unavailable media.
1604          * @throws SecurityException if called after the session has been
1605          *             sealed or abandoned
1606          */
openWrite(@onNull String name, long offsetBytes, long lengthBytes)1607         public @NonNull OutputStream openWrite(@NonNull String name, long offsetBytes,
1608                 long lengthBytes) throws IOException {
1609             try {
1610                 if (ENABLE_REVOCABLE_FD) {
1611                     return new ParcelFileDescriptor.AutoCloseOutputStream(
1612                             mSession.openWrite(name, offsetBytes, lengthBytes));
1613                 } else {
1614                     final ParcelFileDescriptor clientSocket = mSession.openWrite(name,
1615                             offsetBytes, lengthBytes);
1616                     return new FileBridge.FileBridgeOutputStream(clientSocket);
1617                 }
1618             } catch (RuntimeException e) {
1619                 ExceptionUtils.maybeUnwrapIOException(e);
1620                 throw e;
1621             } catch (RemoteException e) {
1622                 throw e.rethrowFromSystemServer();
1623             }
1624         }
1625 
1626         /** {@hide} */
write(@onNull String name, long offsetBytes, long lengthBytes, @NonNull ParcelFileDescriptor fd)1627         public void write(@NonNull String name, long offsetBytes, long lengthBytes,
1628                 @NonNull ParcelFileDescriptor fd) throws IOException {
1629             try {
1630                 mSession.write(name, offsetBytes, lengthBytes, fd);
1631             } catch (RuntimeException e) {
1632                 ExceptionUtils.maybeUnwrapIOException(e);
1633                 throw e;
1634             } catch (RemoteException e) {
1635                 throw e.rethrowFromSystemServer();
1636             }
1637         }
1638 
1639         /**
1640          * Populate an APK file by creating a hard link to avoid the need to copy.
1641          * <p>
1642          * Note this API is used by RollbackManager only and can only be called from system_server.
1643          * {@code target} will be relabeled if link is created successfully. RollbackManager has
1644          * to delete {@code target} when the session is committed successfully to avoid SELinux
1645          * label conflicts.
1646          * <p>
1647          * Note No more bytes should be written to the file once the link is created successfully.
1648          *
1649          * @param target the path of the link target
1650          *
1651          * @hide
1652          */
stageViaHardLink(String target)1653         public void stageViaHardLink(String target) throws IOException {
1654             try {
1655                 mSession.stageViaHardLink(target);
1656             } catch (RuntimeException e) {
1657                 ExceptionUtils.maybeUnwrapIOException(e);
1658                 throw e;
1659             } catch (RemoteException e) {
1660                 throw e.rethrowFromSystemServer();
1661             }
1662         }
1663 
1664         /**
1665          * Ensure that any outstanding data for given stream has been committed
1666          * to disk. This is only valid for streams returned from
1667          * {@link #openWrite(String, long, long)}.
1668          */
fsync(@onNull OutputStream out)1669         public void fsync(@NonNull OutputStream out) throws IOException {
1670             if (ENABLE_REVOCABLE_FD) {
1671                 if (out instanceof ParcelFileDescriptor.AutoCloseOutputStream) {
1672                     try {
1673                         Os.fsync(((ParcelFileDescriptor.AutoCloseOutputStream) out).getFD());
1674                     } catch (ErrnoException e) {
1675                         throw e.rethrowAsIOException();
1676                     }
1677                 } else {
1678                     throw new IllegalArgumentException("Unrecognized stream");
1679                 }
1680             } else {
1681                 if (out instanceof FileBridge.FileBridgeOutputStream) {
1682                     ((FileBridge.FileBridgeOutputStream) out).fsync();
1683                 } else {
1684                     throw new IllegalArgumentException("Unrecognized stream");
1685                 }
1686             }
1687         }
1688 
1689         /**
1690          * Return all APK names contained in this session.
1691          * <p>
1692          * This returns all names which have been previously written through
1693          * {@link #openWrite(String, long, long)} as part of this session.
1694          *
1695          * @throws SecurityException if called after the session has been abandoned.
1696          */
getNames()1697         public @NonNull String[] getNames() throws IOException {
1698             try {
1699                 return mSession.getNames();
1700             } catch (RuntimeException e) {
1701                 ExceptionUtils.maybeUnwrapIOException(e);
1702                 throw e;
1703             } catch (RemoteException e) {
1704                 throw e.rethrowFromSystemServer();
1705             }
1706         }
1707 
1708         /**
1709          * Open a stream to read an APK file from the session.
1710          * <p>
1711          * This is only valid for names which have been previously written
1712          * through {@link #openWrite(String, long, long)} as part of this
1713          * session. For example, this stream may be used to calculate a
1714          * {@link MessageDigest} of a written APK before committing.
1715          *
1716          * @throws SecurityException if called after the session has been
1717          *             committed or abandoned.
1718          */
openRead(@onNull String name)1719         public @NonNull InputStream openRead(@NonNull String name) throws IOException {
1720             try {
1721                 final ParcelFileDescriptor pfd = mSession.openRead(name);
1722                 return new ParcelFileDescriptor.AutoCloseInputStream(pfd);
1723             } catch (RuntimeException e) {
1724                 ExceptionUtils.maybeUnwrapIOException(e);
1725                 throw e;
1726             } catch (RemoteException e) {
1727                 throw e.rethrowFromSystemServer();
1728             }
1729         }
1730 
1731         /**
1732          * Removes a split.
1733          * <p>
1734          * Split removals occur prior to adding new APKs. If upgrading a feature
1735          * split, it is not expected nor desirable to remove the split prior to
1736          * upgrading.
1737          * <p>
1738          * When split removal is bundled with new APKs, the packageName must be
1739          * identical.
1740          */
removeSplit(@onNull String splitName)1741         public void removeSplit(@NonNull String splitName) throws IOException {
1742             try {
1743                 mSession.removeSplit(splitName);
1744             } catch (RuntimeException e) {
1745                 ExceptionUtils.maybeUnwrapIOException(e);
1746                 throw e;
1747             } catch (RemoteException e) {
1748                 throw e.rethrowFromSystemServer();
1749             }
1750         }
1751 
1752         /**
1753          * @return data loader params or null if the session is not using one.
1754          * {@hide}
1755          */
1756         @SystemApi
1757         @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2)
getDataLoaderParams()1758         public @Nullable DataLoaderParams getDataLoaderParams() {
1759             try {
1760                 DataLoaderParamsParcel data = mSession.getDataLoaderParams();
1761                 if (data == null) {
1762                     return null;
1763                 }
1764                 return new DataLoaderParams(data);
1765             } catch (RemoteException e) {
1766                 throw e.rethrowFromSystemServer();
1767             }
1768         }
1769 
1770         /**
1771          * Adds a file to session. On commit this file will be pulled from DataLoader {@code
1772          * android.service.dataloader.DataLoaderService.DataLoader}.
1773          *
1774          * @param location target location for the file. Possible values:
1775          *            {@link #LOCATION_DATA_APP},
1776          *            {@link #LOCATION_MEDIA_OBB},
1777          *            {@link #LOCATION_MEDIA_DATA}.
1778          * @param name arbitrary, unique name of your choosing to identify the
1779          *            APK being written. You can open a file again for
1780          *            additional writes (such as after a reboot) by using the
1781          *            same name. This name is only meaningful within the context
1782          *            of a single install session.
1783          * @param lengthBytes total size of the file being written.
1784          *            The system may clear various caches as needed to allocate
1785          *            this space.
1786          * @param metadata additional info use by DataLoader to pull data for the file.
1787          * @param signature additional file signature, e.g.
1788          *                  <a href="https://source.android.com/security/apksigning/v4.html">APK Signature Scheme v4</a>
1789          * @throws SecurityException if called after the session has been
1790          *             sealed or abandoned
1791          * @throws IllegalStateException if called for non-streaming session
1792          *
1793          * @see android.content.pm.InstallationFile
1794          *
1795          * {@hide}
1796          */
1797         @SystemApi
1798         @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2)
addFile(@ileLocation int location, @NonNull String name, long lengthBytes, @NonNull byte[] metadata, @Nullable byte[] signature)1799         public void addFile(@FileLocation int location, @NonNull String name, long lengthBytes,
1800                 @NonNull byte[] metadata, @Nullable byte[] signature) {
1801             try {
1802                 mSession.addFile(location, name, lengthBytes, metadata, signature);
1803             } catch (RemoteException e) {
1804                 throw e.rethrowFromSystemServer();
1805             }
1806         }
1807 
1808         /**
1809          * Removes a file.
1810          *
1811          * @param location target location for the file. Possible values:
1812          *            {@link #LOCATION_DATA_APP},
1813          *            {@link #LOCATION_MEDIA_OBB},
1814          *            {@link #LOCATION_MEDIA_DATA}.
1815          * @param name name of a file, e.g. split.
1816          * @throws SecurityException if called after the session has been
1817          *             sealed or abandoned
1818          * @throws IllegalStateException if called for non-DataLoader session
1819          * {@hide}
1820          */
1821         @SystemApi
1822         @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2)
removeFile(@ileLocation int location, @NonNull String name)1823         public void removeFile(@FileLocation int location, @NonNull String name) {
1824             try {
1825                 mSession.removeFile(location, name);
1826             } catch (RemoteException e) {
1827                 throw e.rethrowFromSystemServer();
1828             }
1829         }
1830 
1831         /**
1832          * Sets installer-provided checksums for the APK file in session.
1833          *
1834          * @param name      previously written as part of this session.
1835          *                  {@link #openWrite}
1836          * @param checksums installer intends to make available via
1837          *                  {@link PackageManager#requestChecksums} or {@link #requestChecksums}.
1838          * @param signature DER PKCS#7 detached signature bytes over binary serialized checksums
1839          *                  to enable integrity checking for the checksums or null for no integrity
1840          *                  checking. {@link PackageManager#requestChecksums} will return
1841          *                  the certificate used to create signature.
1842          *                  Binary format for checksums:
1843          *                  <pre>{@code DataOutputStream dos;
1844          *                  dos.writeInt(checksum.getType());
1845          *                  dos.writeInt(checksum.getValue().length);
1846          *                  dos.write(checksum.getValue());}</pre>
1847          *                  If using <b>openssl cms</b>, make sure to specify -binary -nosmimecap.
1848          *                  @see <a href="https://www.openssl.org/docs/man1.0.2/man1/cms.html">openssl cms</a>
1849          * @throws SecurityException if called after the session has been
1850          *                           committed or abandoned.
1851          * @throws IllegalStateException if checksums for this file have already been added.
1852          * @deprecated  do not use installer-provided checksums,
1853          *              use platform-enforced checksums
1854          *              e.g. {@link Checksum#TYPE_WHOLE_MERKLE_ROOT_4K_SHA256}
1855          *              in {@link PackageManager#requestChecksums}.
1856          */
1857         @Deprecated
setChecksums(@onNull String name, @NonNull List<Checksum> checksums, @Nullable byte[] signature)1858         public void setChecksums(@NonNull String name, @NonNull List<Checksum> checksums,
1859                 @Nullable byte[] signature) throws IOException {
1860             Objects.requireNonNull(name);
1861             Objects.requireNonNull(checksums);
1862 
1863             try {
1864                 mSession.setChecksums(name, checksums.toArray(new Checksum[checksums.size()]),
1865                         signature);
1866             } catch (RuntimeException e) {
1867                 ExceptionUtils.maybeUnwrapIOException(e);
1868                 throw e;
1869             } catch (RemoteException e) {
1870                 throw e.rethrowFromSystemServer();
1871             }
1872         }
1873 
encodeCertificates(List<Certificate> certs)1874         private static List<byte[]> encodeCertificates(List<Certificate> certs) throws
1875                 CertificateEncodingException {
1876             if (certs == null) {
1877                 return null;
1878             }
1879             List<byte[]> result = new ArrayList<>(certs.size());
1880             for (Certificate cert : certs) {
1881                 if (!(cert instanceof X509Certificate)) {
1882                     throw new CertificateEncodingException("Only X509 certificates supported.");
1883                 }
1884                 result.add(cert.getEncoded());
1885             }
1886             return result;
1887         }
1888 
1889         /**
1890          * Requests checksums for the APK file in session.
1891          * <p>
1892          * A possible use case is replying to {@link Intent#ACTION_PACKAGE_NEEDS_VERIFICATION}
1893          * broadcast.
1894          * The checksums will be returned asynchronously via onChecksumsReadyListener.
1895          * <p>
1896          * By default returns all readily available checksums:
1897          * <ul>
1898          * <li>enforced by platform,
1899          * <li>enforced by the installer.
1900          * </ul>
1901          * If the caller needs a specific checksum type, they can specify it as required.
1902          * <p>
1903          * <b>Caution: Android can not verify installer-provided checksums. Make sure you specify
1904          * trusted installers.</b>
1905          * <p>
1906          * @param name      previously written as part of this session.
1907          *                  {@link #openWrite}
1908          * @param required to explicitly request the checksum types. Will incur significant
1909          *                 CPU/memory/disk usage.
1910          * @param trustedInstallers for checksums enforced by installer, which installers are to be
1911          *                          trusted.
1912          *                          {@link PackageManager#TRUST_ALL} will return checksums from any
1913          *                          installer,
1914          *                          {@link PackageManager#TRUST_NONE} disables optimized
1915          *                          installer-enforced checksums, otherwise the list has to be
1916          *                          a non-empty list of certificates.
1917          * @param executor the {@link Executor} on which to invoke the callback
1918          * @param onChecksumsReadyListener called once when the results are available.
1919          * @throws CertificateEncodingException if an encoding error occurs for trustedInstallers.
1920          * @throws FileNotFoundException if the file does not exist.
1921          * @throws IllegalArgumentException if the list of trusted installer certificates is empty.
1922          */
requestChecksums(@onNull String name, @Checksum.TypeMask int required, @NonNull List<Certificate> trustedInstallers, @NonNull @CallbackExecutor Executor executor, @NonNull PackageManager.OnChecksumsReadyListener onChecksumsReadyListener)1923         public void requestChecksums(@NonNull String name, @Checksum.TypeMask int required,
1924                 @NonNull List<Certificate> trustedInstallers,
1925                 @NonNull @CallbackExecutor Executor executor,
1926                 @NonNull PackageManager.OnChecksumsReadyListener onChecksumsReadyListener)
1927                 throws CertificateEncodingException, FileNotFoundException {
1928             Objects.requireNonNull(name);
1929             Objects.requireNonNull(trustedInstallers);
1930             Objects.requireNonNull(executor);
1931             Objects.requireNonNull(onChecksumsReadyListener);
1932             if (trustedInstallers == PackageManager.TRUST_ALL) {
1933                 trustedInstallers = null;
1934             } else if (trustedInstallers == PackageManager.TRUST_NONE) {
1935                 trustedInstallers = Collections.emptyList();
1936             } else if (trustedInstallers.isEmpty()) {
1937                 throw new IllegalArgumentException(
1938                         "trustedInstallers has to be one of TRUST_ALL/TRUST_NONE or a non-empty "
1939                                 + "list of certificates.");
1940             }
1941             try {
1942                 IOnChecksumsReadyListener onChecksumsReadyListenerDelegate =
1943                         new IOnChecksumsReadyListener.Stub() {
1944                             @Override
1945                             public void onChecksumsReady(List<ApkChecksum> checksums)
1946                                     throws RemoteException {
1947                                 executor.execute(
1948                                         () -> onChecksumsReadyListener.onChecksumsReady(checksums));
1949                             }
1950                         };
1951                 mSession.requestChecksums(name, DEFAULT_CHECKSUMS, required,
1952                         encodeCertificates(trustedInstallers), onChecksumsReadyListenerDelegate);
1953             } catch (ParcelableException e) {
1954                 e.maybeRethrow(FileNotFoundException.class);
1955                 throw new RuntimeException(e);
1956             } catch (RemoteException e) {
1957                 throw e.rethrowFromSystemServer();
1958             }
1959         }
1960 
1961         /**
1962          * Attempt to commit everything staged in this session. This may require
1963          * user intervention, and so it may not happen immediately. The final
1964          * result of the commit will be reported through the given callback.
1965          * <p>
1966          * Once this method is called, the session is sealed and no additional mutations may be
1967          * performed on the session. In case of device reboot or data loader transient failure
1968          * before the session has been finalized, you may commit the session again.
1969          * <p>
1970          * If the installer is the device owner, the affiliated profile owner, or has received
1971          * user pre-approval of this session, there will be no user intervention.
1972          *
1973          * @param statusReceiver Called when the state of the session changes. Intents
1974          *                       sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
1975          *                       individual status codes on how to handle them.
1976          *
1977          * @throws SecurityException if streams opened through
1978          *             {@link #openWrite(String, long, long)} are still open.
1979          * @throws IllegalArgumentException if the {@code statusReceiver} from an immutable
1980          *             {@link android.app.PendingIntent} when caller has a target SDK of API
1981          *             version 35 or above.
1982          *
1983          * @see android.app.admin.DevicePolicyManager
1984          * @see #requestUserPreapproval
1985          */
commit(@onNull IntentSender statusReceiver)1986         public void commit(@NonNull IntentSender statusReceiver) {
1987             try {
1988                 mSession.commit(statusReceiver, false);
1989             } catch (RemoteException e) {
1990                 throw e.rethrowFromSystemServer();
1991             }
1992         }
1993 
1994         /**
1995          * Attempt to commit a session that has been {@link #transfer(String) transferred}.
1996          *
1997          * <p>If the device reboots before the session has been finalized, you may commit the
1998          * session again.
1999          *
2000          * <p>The caller of this method is responsible to ensure the safety of the session. As the
2001          * session was created by another - usually less trusted - app, it is paramount that before
2002          * committing <u>all</u> public and system {@link SessionInfo properties of the session}
2003          * and <u>all</u> {@link #openRead(String) APKs} are verified by the caller. It might happen
2004          * that new properties are added to the session with a new API revision. In this case the
2005          * callers need to be updated.
2006          *
2007          * @param statusReceiver Called when the state of the session changes. Intents
2008          *                       sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
2009          *                       individual status codes on how to handle them.
2010          * @throws IllegalArgumentException if the {@code statusReceiver} from an immutable
2011          *             {@link android.app.PendingIntent} when caller has a target SDK of API
2012          *             35 or above.
2013          *
2014          * @hide
2015          */
2016         @SystemApi
2017         @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
commitTransferred(@onNull IntentSender statusReceiver)2018         public void commitTransferred(@NonNull IntentSender statusReceiver) {
2019             try {
2020                 mSession.commit(statusReceiver, true);
2021             } catch (RemoteException e) {
2022                 throw e.rethrowFromSystemServer();
2023             }
2024         }
2025 
2026         /**
2027          * Transfer the session to a new owner.
2028          * <p>
2029          * Only sessions that update the installing app can be transferred.
2030          * <p>
2031          * After the transfer to a package with a different uid all method calls on the session
2032          * will cause {@link SecurityException}s.
2033          * <p>
2034          * Once this method is called, the session is sealed and no additional mutations beside
2035          * committing it may be performed on the session.
2036          *
2037          * @param packageName The package of the new owner. Needs to hold the INSTALL_PACKAGES
2038          *                    permission.
2039          *
2040          * @throws PackageManager.NameNotFoundException if the new owner could not be found.
2041          * @throws SecurityException if called after the session has been committed or abandoned.
2042          * @throws IllegalStateException if streams opened through
2043          *                                  {@link #openWrite(String, long, long) are still open.
2044          * @throws IllegalArgumentException if {@code packageName} is invalid.
2045          */
transfer(@onNull String packageName)2046         public void transfer(@NonNull String packageName)
2047                 throws PackageManager.NameNotFoundException {
2048             Preconditions.checkArgument(!TextUtils.isEmpty(packageName));
2049 
2050             try {
2051                 mSession.transfer(packageName);
2052             } catch (ParcelableException e) {
2053                 e.maybeRethrow(PackageManager.NameNotFoundException.class);
2054                 throw new RuntimeException(e);
2055             } catch (RemoteException e) {
2056                 throw e.rethrowFromSystemServer();
2057             }
2058         }
2059 
2060         /**
2061          * Release this session object. You can open the session again if it
2062          * hasn't been finalized.
2063          */
2064         @Override
close()2065         public void close() {
2066             try {
2067                 mSession.close();
2068             } catch (RemoteException e) {
2069                 throw e.rethrowFromSystemServer();
2070             }
2071         }
2072 
2073         /**
2074          * Completely abandon this session, destroying all staged data and
2075          * rendering it invalid. Abandoned sessions will be reported to
2076          * {@link SessionCallback} listeners as failures. This is equivalent to
2077          * {@link #abandonSession(int)}.
2078          * <p>If the parent is abandoned, all children will also be abandoned. Any written data
2079          * would be destroyed and the created {@link Session} information will be discarded.</p>
2080          */
abandon()2081         public void abandon() {
2082             try {
2083                 mSession.abandon();
2084             } catch (RemoteException e) {
2085                 throw e.rethrowFromSystemServer();
2086             }
2087         }
2088 
2089         /**
2090          * @return {@code true} if this session will commit more than one package when it is
2091          * committed.
2092          */
isMultiPackage()2093         public boolean isMultiPackage() {
2094             try {
2095                 return mSession.isMultiPackage();
2096             } catch (RemoteException e) {
2097                 throw e.rethrowFromSystemServer();
2098             }
2099         }
2100 
2101         /**
2102          * @return {@code true} if this session will be staged and applied at next reboot.
2103          */
isStaged()2104         public boolean isStaged() {
2105             try {
2106                 return mSession.isStaged();
2107             } catch (RemoteException e) {
2108                 throw e.rethrowFromSystemServer();
2109             }
2110         }
2111 
2112         /**
2113          * @return Session's {@link SessionParams#installFlags}.
2114          * @hide
2115          */
getInstallFlags()2116         public int getInstallFlags() {
2117             try {
2118                 return mSession.getInstallFlags();
2119             } catch (RemoteException e) {
2120                 throw e.rethrowFromSystemServer();
2121             }
2122         }
2123 
2124         /**
2125          * @return the session ID of the multi-package session that this belongs to or
2126          * {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session.
2127          */
getParentSessionId()2128         public int getParentSessionId() {
2129             try {
2130                 return mSession.getParentSessionId();
2131             } catch (RemoteException e) {
2132                 throw e.rethrowFromSystemServer();
2133             }
2134         }
2135 
2136         /**
2137          * @return the set of session IDs that will be committed atomically when this session is
2138          * committed if this is a multi-package session or null if none exist.
2139          */
2140         @NonNull
getChildSessionIds()2141         public int[] getChildSessionIds() {
2142             try {
2143                 return mSession.getChildSessionIds();
2144             } catch (RemoteException e) {
2145                 throw e.rethrowFromSystemServer();
2146             }
2147         }
2148 
2149         /**
2150          * Adds a session ID to the set of sessions that will be committed atomically
2151          * when this session is committed.
2152          *
2153          * <p>If the parent is staged or has rollback enabled, all children must have
2154          * the same properties.</p>
2155          * <p>If the parent is abandoned, all children will also be abandoned.</p>
2156          *
2157          * @param sessionId the session ID to add to this multi-package session.
2158          */
addChildSessionId(int sessionId)2159         public void addChildSessionId(int sessionId) {
2160             try {
2161                 mSession.addChildSessionId(sessionId);
2162             } catch (RemoteException e) {
2163                 e.rethrowFromSystemServer();
2164             }
2165         }
2166 
2167         /**
2168          * Removes a session ID from the set of sessions that will be committed
2169          * atomically when this session is committed.
2170          *
2171          * @param sessionId the session ID to remove from this multi-package session.
2172          */
removeChildSessionId(int sessionId)2173         public void removeChildSessionId(int sessionId) {
2174             try {
2175                 mSession.removeChildSessionId(sessionId);
2176             } catch (RemoteException e) {
2177                 e.rethrowFromSystemServer();
2178             }
2179         }
2180 
2181         /**
2182          * @return A PersistableBundle containing the app metadata set with
2183          * {@link Session#setAppMetadata(PersistableBundle)}. In the case where this data does not
2184          * exist, an empty PersistableBundle is returned.
2185          */
2186         @NonNull
getAppMetadata()2187         public PersistableBundle getAppMetadata() {
2188             PersistableBundle data = null;
2189             try {
2190                 ParcelFileDescriptor pfd = mSession.getAppMetadataFd();
2191                 if (pfd != null) {
2192                     try (InputStream inputStream =
2193                             new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
2194                         data = PersistableBundle.readFromStream(inputStream);
2195                     }
2196                 }
2197             } catch (RemoteException e) {
2198                 e.rethrowFromSystemServer();
2199             } catch (IOException e) {
2200                 throw new RuntimeException(e);
2201             }
2202             return data != null ? data : new PersistableBundle();
2203         }
2204 
openWriteAppMetadata()2205         private OutputStream openWriteAppMetadata() throws IOException {
2206             try {
2207                 if (ENABLE_REVOCABLE_FD) {
2208                     return new ParcelFileDescriptor.AutoCloseOutputStream(
2209                             mSession.openWriteAppMetadata());
2210                 } else {
2211                     final ParcelFileDescriptor clientSocket = mSession.openWriteAppMetadata();
2212                     return new FileBridge.FileBridgeOutputStream(clientSocket);
2213                 }
2214             } catch (RuntimeException e) {
2215                 ExceptionUtils.maybeUnwrapIOException(e);
2216                 throw e;
2217             } catch (RemoteException e) {
2218                 throw e.rethrowFromSystemServer();
2219             }
2220         }
2221 
2222         /**
2223          * Optionally set the app metadata. The size of this data cannot exceed the maximum allowed.
2224          * Any existing data from the previous install will not be retained even if no data is set
2225          * for the current install session. Setting data to null or an empty PersistableBundle will
2226          * remove any metadata that has previously been set in the same session.
2227          *
2228          * @param data a PersistableBundle containing the app metadata.
2229          * @throws IOException if writing the data fails.
2230          */
setAppMetadata(@ullable PersistableBundle data)2231         public void setAppMetadata(@Nullable PersistableBundle data) throws IOException {
2232             if (data == null || data.isEmpty()) {
2233                 try {
2234                     mSession.removeAppMetadata();
2235                 } catch (RemoteException e) {
2236                     throw e.rethrowFromSystemServer();
2237                 }
2238                 return;
2239             }
2240             Objects.requireNonNull(data);
2241             try (OutputStream outputStream = openWriteAppMetadata()) {
2242                 data.writeToStream(outputStream);
2243             }
2244         }
2245 
2246         /**
2247          * Attempt to request the approval before committing this session.
2248          *
2249          * For installers that have been granted the
2250          * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES REQUEST_INSTALL_PACKAGES}
2251          * permission, they can request the approval from users before
2252          * {@link Session#commit(IntentSender)} is called. This may require user intervention as
2253          * well. When user intervention is required, installers will receive a
2254          * {@link #STATUS_PENDING_USER_ACTION} callback, and {@link #STATUS_SUCCESS} otherwise.
2255          * In case that requesting user pre-approval is not available, installers will receive
2256          * {@link #STATUS_FAILURE_BLOCKED} instead. Note that if the users decline the request,
2257          * this session will be abandoned.
2258          *
2259          * If user intervention is required but never resolved, or requesting user
2260          * pre-approval is not available, you may still call {@link Session#commit(IntentSender)}
2261          * as the typical installation.
2262          *
2263          * @param details the adequate context to this session for requesting the approval from
2264          *                users prior to commit.
2265          * @param statusReceiver called when the state of the session changes.
2266          *                       Intents sent to this receiver contain {@link #EXTRA_STATUS}
2267          *                       and the {@link #EXTRA_PRE_APPROVAL} would be {@code true}.
2268          *                       Refer to the individual status codes on how to handle them.
2269          *
2270          * @throws IllegalArgumentException when {@link PreapprovalDetails} is {@code null}.
2271          * @throws IllegalArgumentException if {@link IntentSender} is {@code null}.
2272          * @throws IllegalStateException if called on a multi-package session (no matter
2273          *                               the parent session or any of the children sessions).
2274          * @throws IllegalStateException if called again after this method has been called on
2275          *                               this session.
2276          * @throws SecurityException when the caller does not own this session.
2277          * @throws SecurityException if called after the session has been committed or abandoned.
2278          */
requestUserPreapproval(@onNull PreapprovalDetails details, @NonNull IntentSender statusReceiver)2279         public void requestUserPreapproval(@NonNull PreapprovalDetails details,
2280                 @NonNull IntentSender statusReceiver) {
2281             Preconditions.checkArgument(details != null, "preapprovalDetails cannot be null.");
2282             Preconditions.checkArgument(statusReceiver != null, "statusReceiver cannot be null.");
2283             try {
2284                 mSession.requestUserPreapproval(details, statusReceiver);
2285             } catch (RemoteException e) {
2286                 e.rethrowFromSystemServer();
2287             }
2288         }
2289 
2290         /**
2291          * @return {@code true} if this session will keep the existing application enabled setting
2292          * after installation.
2293          */
isApplicationEnabledSettingPersistent()2294         public boolean isApplicationEnabledSettingPersistent() {
2295             try {
2296                 return mSession.isApplicationEnabledSettingPersistent();
2297             } catch (RemoteException e) {
2298                 throw e.rethrowFromSystemServer();
2299             }
2300         }
2301 
2302         /**
2303          * @return {@code true} if the installer requested the update ownership enforcement
2304          * for the packages in this session.
2305          *
2306          * @see PackageInstaller.SessionParams#setRequestUpdateOwnership
2307          */
isRequestUpdateOwnership()2308         public boolean isRequestUpdateOwnership() {
2309             try {
2310                 return mSession.isRequestUpdateOwnership();
2311             } catch (RemoteException e) {
2312                 throw e.rethrowFromSystemServer();
2313             }
2314         }
2315 
2316         /**
2317          * Sets the pre-verified domains for the app to be installed. By setting pre-verified
2318          * domains, the installer allows the app to be opened by the app links of these domains
2319          * immediately after it is installed.
2320          *
2321          * <p>The specified pre-verified domains should be a subset of the hostnames declared with
2322          * {@code android:host} and {@code android:autoVerify=true} in the intent filters of the
2323          * AndroidManifest.xml of the app. If some of the specified domains are not declared in
2324          * the manifest, they will be ignored.</p>
2325          * <p>If this API is called multiple times on the same {@link #Session}, the last call
2326          * overrides the previous ones.</p>
2327          * <p>The instant app installer is the only entity that may call this API.
2328          * </p>
2329          *
2330          * @param preVerifiedDomains domains that are already pre-verified by the installer.
2331          *
2332          * @throws IllegalArgumentException if the number or the total size of the pre-verified
2333          *                                  domains exceeds the maximum allowed, or if the domain
2334          *                                  names contain invalid characters.
2335          * @throws SecurityException if called from an installer that is not the instant app
2336          *                           installer of the device, or if called after the session has
2337          *                           been committed or abandoned.
2338          *
2339          * @hide
2340          */
2341         @SystemApi
2342         @FlaggedApi(Flags.FLAG_SET_PRE_VERIFIED_DOMAINS)
2343         @RequiresPermission(Manifest.permission.ACCESS_INSTANT_APPS)
setPreVerifiedDomains(@onNull Set<String> preVerifiedDomains)2344         public void setPreVerifiedDomains(@NonNull Set<String> preVerifiedDomains) {
2345             Preconditions.checkArgument(preVerifiedDomains != null && !preVerifiedDomains.isEmpty(),
2346                     "Provided pre-verified domains cannot be null or empty.");
2347             try {
2348                 mSession.setPreVerifiedDomains(new DomainSet(preVerifiedDomains));
2349             } catch (RemoteException e) {
2350                 throw e.rethrowFromSystemServer();
2351             }
2352         }
2353 
2354         /**
2355          * Retrieve the pre-verified domains set in a session.
2356          * See {@link #setPreVerifiedDomains(Set)} for the definition of pre-verified domains.
2357          *
2358          * @throws SecurityException if called from an installer that is not the owner of the
2359          *                           session, or if called after the session has been committed or
2360          *                           abandoned.
2361          * @hide
2362          */
2363         @SystemApi
2364         @FlaggedApi(Flags.FLAG_SET_PRE_VERIFIED_DOMAINS)
2365         @RequiresPermission(Manifest.permission.ACCESS_INSTANT_APPS)
2366         @NonNull
getPreVerifiedDomains()2367         public Set<String> getPreVerifiedDomains() {
2368             try {
2369                 DomainSet domainSet = mSession.getPreVerifiedDomains();
2370                 return domainSet != null ? domainSet.getDomains() : Collections.emptySet();
2371             } catch (RemoteException e) {
2372                 throw e.rethrowFromSystemServer();
2373             }
2374         }
2375     }
2376 
2377     /**
2378      * Parse a single APK or a directory of APKs to get install relevant information about
2379      * the package wrapped in {@link InstallInfo}.
2380      * @throws PackageParsingException if the package source file(s) provided is(are) not valid,
2381      * or the parser isn't able to parse the supplied source(s).
2382      * @hide
2383      */
2384     @SystemApi
2385     @NonNull
readInstallInfo(@onNull File file, int flags)2386     public InstallInfo readInstallInfo(@NonNull File file, int flags)
2387             throws PackageParsingException {
2388         final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
2389         final ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
2390                 input.reset(), file, flags);
2391         if (result.isError()) {
2392             throw new PackageParsingException(result.getErrorCode(), result.getErrorMessage());
2393         }
2394         return new InstallInfo(result);
2395     }
2396 
2397     /**
2398      * Parse a single APK file passed as an FD to get install relevant information about
2399      * the package wrapped in {@link InstallInfo}.
2400      * @throws PackageParsingException if the package source file(s) provided is(are) not valid,
2401      * or the parser isn't able to parse the supplied source(s).
2402      * @hide
2403      */
2404     @SystemApi
2405     @NonNull
2406     @FlaggedApi(Flags.FLAG_READ_INSTALL_INFO)
readInstallInfo(@onNull ParcelFileDescriptor pfd, @Nullable String debugPathName, int flags)2407     public InstallInfo readInstallInfo(@NonNull ParcelFileDescriptor pfd,
2408             @Nullable String debugPathName, int flags) throws PackageParsingException {
2409         final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
2410         final ParseResult<PackageLite> result = ApkLiteParseUtils.parseMonolithicPackageLite(input,
2411                 pfd.getFileDescriptor(), debugPathName, flags);
2412         if (result.isError()) {
2413             throw new PackageParsingException(result.getErrorCode(), result.getErrorMessage());
2414         }
2415         return new InstallInfo(result);
2416     }
2417 
2418     /**
2419      * Requests to archive a package which is currently installed.
2420      *
2421      * <p> During the archival process, the apps APKs and cache are removed from the device while
2422      * the user data is kept. Through the {@link #requestUnarchive} call, apps
2423      * can be restored again through their responsible installer.
2424      *
2425      * <p> Archived apps are returned as displayable apps through the {@link LauncherApps} APIs and
2426      * will be displayed to users with UI treatment to highlight that said apps are archived. If
2427      * a user taps on an archived app, the app will be unarchived and the restoration process is
2428      * communicated.
2429      *
2430      * @param statusReceiver Callback used to notify when the operation is completed.
2431      * @throws PackageManager.NameNotFoundException If {@code packageName} isn't found or not
2432      *                                              available to the caller or isn't archived.
2433      */
2434     @RequiresPermission(anyOf = {
2435             Manifest.permission.DELETE_PACKAGES,
2436             Manifest.permission.REQUEST_DELETE_PACKAGES})
2437     @FlaggedApi(Flags.FLAG_ARCHIVING)
requestArchive(@onNull String packageName, @NonNull IntentSender statusReceiver)2438     public void requestArchive(@NonNull String packageName, @NonNull IntentSender statusReceiver)
2439             throws PackageManager.NameNotFoundException {
2440         try {
2441             mInstaller.requestArchive(packageName, mInstallerPackageName, /*flags=*/ 0,
2442                     statusReceiver, new UserHandle(mUserId));
2443         } catch (ParcelableException e) {
2444             e.maybeRethrow(PackageManager.NameNotFoundException.class);
2445             throw new RuntimeException(e);
2446         } catch (RemoteException e) {
2447             throw e.rethrowFromSystemServer();
2448         }
2449     }
2450 
2451     /**
2452      * Requests to unarchive a currently archived package.
2453      *
2454      * <p> Sends a request to unarchive an app to the responsible installer. The installer is
2455      * determined by {@link InstallSourceInfo#getUpdateOwnerPackageName()}, or
2456      * {@link InstallSourceInfo#getInstallingPackageName()} if the former value is null.
2457      *
2458      * <p> The installation will happen asynchronously and can be observed through
2459      * {@link android.content.Intent#ACTION_PACKAGE_ADDED}.
2460      *
2461      * @param statusReceiver Callback used to notify whether the installer has accepted the
2462      *                       unarchival request or an error has occurred. The status update will be
2463      *                       sent though {@link #EXTRA_UNARCHIVE_STATUS}. Only one status will be
2464      *                       sent.
2465      * @throws PackageManager.NameNotFoundException If {@code packageName} isn't found or not
2466      *                                              visible to the caller or if the package has no
2467      *                                              installer on the device anymore to unarchive it.
2468      * @throws IOException If parameters were unsatisfiable, such as lack of disk space.
2469      */
2470     @RequiresPermission(anyOf = {
2471             Manifest.permission.INSTALL_PACKAGES,
2472             Manifest.permission.REQUEST_INSTALL_PACKAGES})
2473     @FlaggedApi(Flags.FLAG_ARCHIVING)
requestUnarchive(@onNull String packageName, @NonNull IntentSender statusReceiver)2474     public void requestUnarchive(@NonNull String packageName, @NonNull IntentSender statusReceiver)
2475             throws IOException, PackageManager.NameNotFoundException {
2476         try {
2477             mInstaller.requestUnarchive(packageName, mInstallerPackageName, statusReceiver,
2478                     new UserHandle(mUserId));
2479         } catch (ParcelableException e) {
2480             e.maybeRethrow(IOException.class);
2481             e.maybeRethrow(PackageManager.NameNotFoundException.class);
2482             throw new RuntimeException(e);
2483         } catch (RemoteException e) {
2484             throw e.rethrowFromSystemServer();
2485         }
2486     }
2487 
2488     /**
2489      * Reports the status of an unarchival to the system.
2490      *
2491      * @param unarchiveId          the ID provided by the system as part of the
2492      *                             intent.action.UNARCHIVE broadcast with EXTRA_UNARCHIVE_ID.
2493      * @param status               is used for the system to provide the user with necessary
2494      *                             follow-up steps or errors.
2495      * @param requiredStorageBytes If the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this field
2496      *                             should be set to specify how many additional bytes of storage
2497      *                             are required to unarchive the app.
2498      * @param userActionIntent     Optional intent to start a follow up action required to
2499      *                             facilitate the unarchival flow (e.g. user needs to log in).
2500      * @throws PackageManager.NameNotFoundException if no unarchival with {@code unarchiveId} exists
2501      */
2502     // TODO(b/314960798) Remove old API once it's unused
2503     @RequiresPermission(anyOf = {
2504             Manifest.permission.INSTALL_PACKAGES,
2505             Manifest.permission.REQUEST_INSTALL_PACKAGES})
2506     @FlaggedApi(Flags.FLAG_ARCHIVING)
reportUnarchivalStatus(int unarchiveId, @UnarchivalStatus int status, long requiredStorageBytes, @Nullable PendingIntent userActionIntent)2507     public void reportUnarchivalStatus(int unarchiveId, @UnarchivalStatus int status,
2508             long requiredStorageBytes, @Nullable PendingIntent userActionIntent)
2509             throws PackageManager.NameNotFoundException {
2510         try {
2511             mInstaller.reportUnarchivalStatus(unarchiveId, status, requiredStorageBytes,
2512                     userActionIntent, new UserHandle(mUserId));
2513         } catch (ParcelableException e) {
2514             e.maybeRethrow(PackageManager.NameNotFoundException.class);
2515             throw new RuntimeException(e);
2516         } catch (RemoteException e) {
2517             throw e.rethrowFromSystemServer();
2518         }
2519     }
2520 
2521     /**
2522      * Reports the state of an unarchival to the system.
2523      *
2524      * @see UnarchivalState for the different state options.
2525      * @throws PackageManager.NameNotFoundException if no unarchival with {@code unarchiveId} exists
2526      */
2527     @RequiresPermission(anyOf = {
2528             Manifest.permission.INSTALL_PACKAGES,
2529             Manifest.permission.REQUEST_INSTALL_PACKAGES})
2530     @FlaggedApi(Flags.FLAG_ARCHIVING)
reportUnarchivalState(@onNull UnarchivalState unarchivalState)2531     public void reportUnarchivalState(@NonNull UnarchivalState unarchivalState)
2532             throws PackageManager.NameNotFoundException {
2533         Objects.requireNonNull(unarchivalState);
2534         try {
2535             mInstaller.reportUnarchivalStatus(unarchivalState.getUnarchiveId(),
2536                     unarchivalState.getStatus(), unarchivalState.getRequiredStorageBytes(),
2537                     unarchivalState.getUserActionIntent(), new UserHandle(mUserId));
2538         } catch (ParcelableException e) {
2539             e.maybeRethrow(PackageManager.NameNotFoundException.class);
2540         } catch (RemoteException e) {
2541             throw e.rethrowFromSystemServer();
2542         }
2543     }
2544 
2545     // (b/239722738) This class serves as a bridge between the PackageLite class, which
2546     // is a hidden class, and the consumers of this class. (e.g. InstallInstalling.java)
2547     // This is a part of an effort to remove dependency on hidden APIs and use SystemAPIs or
2548     // public APIs.
2549     /**
2550      * Install related details from an APK or a folder of APK(s).
2551      *
2552      * @hide
2553      */
2554     @SystemApi
2555     public static class InstallInfo {
2556 
2557         /** @hide */
2558         @IntDef(prefix = { "INSTALL_LOCATION_" }, value = {
2559                 INSTALL_LOCATION_AUTO,
2560                 INSTALL_LOCATION_INTERNAL_ONLY,
2561                 INSTALL_LOCATION_PREFER_EXTERNAL
2562         })
2563         @Retention(RetentionPolicy.SOURCE)
2564         public @interface InstallLocation{}
2565 
2566         private PackageLite mPkg;
2567 
InstallInfo(ParseResult<PackageLite> result)2568         InstallInfo(ParseResult<PackageLite> result) {
2569             mPkg = result.getResult();
2570         }
2571 
2572         /**
2573          * See {@link PackageLite#getPackageName()}
2574          */
2575         @NonNull
getPackageName()2576         public String getPackageName() {
2577             return mPkg.getPackageName();
2578         }
2579 
2580         /**
2581          * @return The default install location defined by an application in
2582          * {@link android.R.attr#installLocation} attribute.
2583          */
getInstallLocation()2584         public @InstallLocation int getInstallLocation() {
2585             return mPkg.getInstallLocation();
2586         }
2587 
2588         /**
2589          * @param params {@link SessionParams} of the installation
2590          * @return Total disk space occupied by an application after installation.
2591          * Includes the size of the raw APKs, possibly unpacked resources, raw dex metadata files,
2592          * and all relevant native code.
2593          * @throws IOException when size of native binaries cannot be calculated.
2594          */
calculateInstalledSize(@onNull SessionParams params)2595         public long calculateInstalledSize(@NonNull SessionParams params) throws IOException {
2596             return InstallLocationUtils.calculateInstalledSize(mPkg, params.abiOverride);
2597         }
2598 
2599         /**
2600          * @param params {@link SessionParams} of the installation
2601          * @param pfd of an APK opened for read
2602          * @return Total disk space occupied by an application after installation.
2603          * Includes the size of the raw APKs, possibly unpacked resources, raw dex metadata files,
2604          * and all relevant native code.
2605          * @throws IOException when size of native binaries cannot be calculated.
2606          */
2607         @FlaggedApi(Flags.FLAG_READ_INSTALL_INFO)
calculateInstalledSize(@onNull SessionParams params, @NonNull ParcelFileDescriptor pfd)2608         public long calculateInstalledSize(@NonNull SessionParams params,
2609                 @NonNull ParcelFileDescriptor pfd) throws IOException {
2610             return InstallLocationUtils.calculateInstalledSize(mPkg, params.abiOverride,
2611                     pfd.getFileDescriptor());
2612         }
2613     }
2614 
2615     /**
2616      * Generic exception class for using with parsing operations.
2617      *
2618      * @hide
2619      */
2620     @SystemApi
2621     public static class PackageParsingException extends Exception {
2622         private final int mErrorCode;
2623 
2624         /** {@hide} */
PackageParsingException(int errorCode, @Nullable String detailedMessage)2625         public PackageParsingException(int errorCode, @Nullable String detailedMessage) {
2626             super(detailedMessage);
2627             mErrorCode = errorCode;
2628         }
2629 
getErrorCode()2630         public int getErrorCode() {
2631             return mErrorCode;
2632         }
2633     }
2634 
2635     /**
2636      * Parameters for creating a new {@link PackageInstaller.Session}.
2637      */
2638     public static class SessionParams implements Parcelable {
2639 
2640         /** {@hide} */
2641         public static final int MODE_INVALID = -1;
2642 
2643         /**
2644          * Mode for an install session whose staged APKs should fully replace any
2645          * existing APKs for the target app.
2646          */
2647         public static final int MODE_FULL_INSTALL = 1;
2648 
2649         /**
2650          * Mode for an install session that should inherit any existing APKs for the
2651          * target app, unless they have been explicitly overridden (based on split
2652          * name) by the session. For example, this can be used to add one or more
2653          * split APKs to an existing installation.
2654          * <p>
2655          * If there are no existing APKs for the target app, this behaves like
2656          * {@link #MODE_FULL_INSTALL}.
2657          */
2658         public static final int MODE_INHERIT_EXISTING = 2;
2659 
2660         /**
2661          * Special constant to refer to all restricted permissions.
2662          */
2663         public static final @NonNull Set<String> RESTRICTED_PERMISSIONS_ALL = new ArraySet<>();
2664 
2665         /** {@hide} */
2666         public static final int UID_UNKNOWN = -1;
2667 
2668         /**
2669          * This value is derived from the maximum file name length. No package above this limit
2670          * can ever be successfully installed on the device.
2671          * @hide
2672          */
2673         public static final int MAX_PACKAGE_NAME_LENGTH = 255;
2674 
2675         /** @hide */
2676         @IntDef(prefix = {"USER_ACTION_"}, value = {
2677                 USER_ACTION_UNSPECIFIED,
2678                 USER_ACTION_REQUIRED,
2679                 USER_ACTION_NOT_REQUIRED
2680         })
2681         @Retention(RetentionPolicy.SOURCE)
2682         public @interface UserActionRequirement {}
2683 
2684         /**
2685          * This value is passed by the installer to {@link SessionParams#setRequireUserAction(int)}
2686          * to indicate that user action is unspecified for this install.
2687          * {@code requireUserAction} also defaults to this value unless modified by
2688          * {@link SessionParams#setRequireUserAction(int)}
2689          */
2690         public static final int USER_ACTION_UNSPECIFIED = 0;
2691 
2692         /**
2693          * This value is passed by the installer to {@link SessionParams#setRequireUserAction(int)}
2694          * to indicate that user action is required for this install.
2695          */
2696         public static final int USER_ACTION_REQUIRED = 1;
2697 
2698         /**
2699          * This value is passed by the installer to {@link SessionParams#setRequireUserAction(int)}
2700          * to indicate that user action is not required for this install.
2701          */
2702         public static final int USER_ACTION_NOT_REQUIRED = 2;
2703 
2704         /** @hide */
2705         @IntDef(prefix = {"PERMISSION_STATE_"}, value = {
2706                 PERMISSION_STATE_DEFAULT,
2707                 PERMISSION_STATE_GRANTED,
2708                 PERMISSION_STATE_DENIED,
2709         })
2710         @Retention(RetentionPolicy.SOURCE)
2711         public @interface PermissionState {}
2712 
2713         /**
2714          * Value is passed by the installer to {@link #setPermissionState(String, int)} to set
2715          * the state of a permission. This indicates no preference by the installer, relying on
2716          * the device's default policy to set the grant state of the permission.
2717          */
2718         public static final int PERMISSION_STATE_DEFAULT = 0;
2719 
2720         /**
2721          * Value is passed by the installer to {@link #setPermissionState(String, int)} to set
2722          * the state of a permission. This indicates the installers wants to automatically grant
2723          * the permission to the package being installed. The user and other actors in the system
2724          * may still be able to deny the permission after installation.
2725          */
2726         public static final int PERMISSION_STATE_GRANTED = 1;
2727 
2728         /**
2729          * Value is passed by the installer to {@link #setPermissionState(String, int)} to set
2730          * the state of a permission. This indicates the installers wants to deny the permission
2731          * by default to the package being installed. The user and other actors in the system may
2732          * still be able to grant the permission after installation.
2733          */
2734         public static final int PERMISSION_STATE_DENIED = 2;
2735 
2736         /** {@hide} */
2737         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
2738         public int mode = MODE_INVALID;
2739         /** {@hide} */
2740         @UnsupportedAppUsage
2741         public int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
2742         /** {@hide} */
2743         public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
2744         /** {@hide} */
2745         public @InstallReason int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
2746         /**
2747          * {@hide}
2748          *
2749          * This flag indicates which installation scenario best describes this session.  The system
2750          * may use this value when making decisions about how to handle the installation, such as
2751          * prioritizing system health or user experience.
2752          */
2753         public @InstallScenario int installScenario = PackageManager.INSTALL_SCENARIO_DEFAULT;
2754         /** {@hide} */
2755         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2756         public long sizeBytes = -1;
2757         /** {@hide} */
2758         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
2759         public String appPackageName;
2760         /** {@hide} */
2761         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2762         public Bitmap appIcon;
2763         /** {@hide} */
2764         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
2765         public String appLabel;
2766         /** {@hide} */
2767         public long appIconLastModified = -1;
2768         /** {@hide} */
2769         public Uri originatingUri;
2770         /** {@hide} */
2771         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2772         public int originatingUid = UID_UNKNOWN;
2773         /** {@hide} */
2774         public Uri referrerUri;
2775         /** {@hide} */
2776         public String abiOverride;
2777         /** {@hide} */
2778         public String volumeUuid;
2779         /** {@hide} */
2780         public List<String> whitelistedRestrictedPermissions;
2781         /** {@hide} */
2782         public int autoRevokePermissionsMode = MODE_DEFAULT;
2783         /** {@hide} */
2784         public String installerPackageName;
2785         /** {@hide} */
2786         public boolean isMultiPackage;
2787         /** {@hide} */
2788         public int packageSource = PACKAGE_SOURCE_UNSPECIFIED;
2789         /** {@hide} */
2790         public boolean isStaged;
2791         /** {@hide} */
2792         public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST;
2793         /** {@hide} */
2794         public DataLoaderParams dataLoaderParams;
2795         /** {@hide} */
2796         public int rollbackDataPolicy = PackageManager.ROLLBACK_DATA_POLICY_RESTORE;
2797         /** @hide */
2798         public long rollbackLifetimeMillis = 0;
2799         /** {@hide} */
2800         public int rollbackImpactLevel = PackageManager.ROLLBACK_USER_IMPACT_LOW;
2801         /** {@hide} */
2802         public boolean forceQueryableOverride;
2803         /** {@hide} */
2804         public int requireUserAction = USER_ACTION_UNSPECIFIED;
2805         /** {@hide} */
2806         public boolean applicationEnabledSettingPersistent = false;
2807         /** {@hide} */
2808         public int developmentInstallFlags = 0;
2809         /** {@hide} */
2810         public int unarchiveId = -1;
2811         /** {@hide} */
2812         public @Nullable String dexoptCompilerFilter = null;
2813         /** {@hide} */
2814         public boolean isAutoInstallDependenciesEnabled = true;
2815 
2816         private final ArrayMap<String, Integer> mPermissionStates;
2817 
2818         /**
2819          * Construct parameters for a new package install session.
2820          *
2821          * @param mode one of {@link #MODE_FULL_INSTALL} or
2822          *            {@link #MODE_INHERIT_EXISTING} describing how the session
2823          *            should interact with an existing app.
2824          */
SessionParams(int mode)2825         public SessionParams(int mode) {
2826             this.mode = mode;
2827             mPermissionStates = new ArrayMap<>();
2828         }
2829 
2830         /** {@hide} */
SessionParams(Parcel source)2831         public SessionParams(Parcel source) {
2832             mode = source.readInt();
2833             installFlags = source.readInt();
2834             installLocation = source.readInt();
2835             installReason = source.readInt();
2836             installScenario = source.readInt();
2837             sizeBytes = source.readLong();
2838             appPackageName = source.readString();
2839             appIcon = source.readParcelable(null, android.graphics.Bitmap.class);
2840             appLabel = source.readString();
2841             originatingUri = source.readParcelable(null, android.net.Uri.class);
2842             originatingUid = source.readInt();
2843             referrerUri = source.readParcelable(null, android.net.Uri.class);
2844             abiOverride = source.readString();
2845             volumeUuid = source.readString();
2846             mPermissionStates = new ArrayMap<>();
2847             source.readMap(mPermissionStates, null, String.class, Integer.class);
2848             whitelistedRestrictedPermissions = source.createStringArrayList();
2849             autoRevokePermissionsMode = source.readInt();
2850             installerPackageName = source.readString();
2851             isMultiPackage = source.readBoolean();
2852             isStaged = source.readBoolean();
2853             forceQueryableOverride = source.readBoolean();
2854             requiredInstalledVersionCode = source.readLong();
2855             DataLoaderParamsParcel dataLoaderParamsParcel = source.readParcelable(
2856                     DataLoaderParamsParcel.class.getClassLoader(), android.content.pm.DataLoaderParamsParcel.class);
2857             if (dataLoaderParamsParcel != null) {
2858                 dataLoaderParams = new DataLoaderParams(dataLoaderParamsParcel);
2859             }
2860             rollbackDataPolicy = source.readInt();
2861             rollbackLifetimeMillis = source.readLong();
2862             rollbackImpactLevel = source.readInt();
2863             requireUserAction = source.readInt();
2864             packageSource = source.readInt();
2865             applicationEnabledSettingPersistent = source.readBoolean();
2866             developmentInstallFlags = source.readInt();
2867             unarchiveId = source.readInt();
2868             dexoptCompilerFilter = source.readString();
2869             isAutoInstallDependenciesEnabled = source.readBoolean();
2870         }
2871 
2872         /** {@hide} */
copy()2873         public SessionParams copy() {
2874             SessionParams ret = new SessionParams(mode);
2875             ret.installFlags = installFlags;
2876             ret.installLocation = installLocation;
2877             ret.installReason = installReason;
2878             ret.installScenario = installScenario;
2879             ret.sizeBytes = sizeBytes;
2880             ret.appPackageName = appPackageName;
2881             ret.appIcon = appIcon;  // not a copy.
2882             ret.appLabel = appLabel;
2883             ret.originatingUri = originatingUri;  // not a copy, but immutable.
2884             ret.originatingUid = originatingUid;
2885             ret.referrerUri = referrerUri;  // not a copy, but immutable.
2886             ret.abiOverride = abiOverride;
2887             ret.volumeUuid = volumeUuid;
2888             ret.mPermissionStates.putAll(mPermissionStates);
2889             ret.whitelistedRestrictedPermissions = whitelistedRestrictedPermissions;
2890             ret.autoRevokePermissionsMode = autoRevokePermissionsMode;
2891             ret.installerPackageName = installerPackageName;
2892             ret.isMultiPackage = isMultiPackage;
2893             ret.isStaged = isStaged;
2894             ret.forceQueryableOverride = forceQueryableOverride;
2895             ret.requiredInstalledVersionCode = requiredInstalledVersionCode;
2896             ret.dataLoaderParams = dataLoaderParams;
2897             ret.rollbackDataPolicy = rollbackDataPolicy;
2898             ret.rollbackLifetimeMillis = rollbackLifetimeMillis;
2899             ret.rollbackImpactLevel = rollbackImpactLevel;
2900             ret.requireUserAction = requireUserAction;
2901             ret.packageSource = packageSource;
2902             ret.applicationEnabledSettingPersistent = applicationEnabledSettingPersistent;
2903             ret.developmentInstallFlags = developmentInstallFlags;
2904             ret.unarchiveId = unarchiveId;
2905             ret.dexoptCompilerFilter = dexoptCompilerFilter;
2906             ret.isAutoInstallDependenciesEnabled = isAutoInstallDependenciesEnabled;
2907             return ret;
2908         }
2909 
2910         /**
2911          * Check if there are hidden options set.
2912          *
2913          * <p>Hidden options are those options that cannot be verified via public or system-api
2914          * methods on {@link SessionInfo}.
2915          *
2916          * @return {@code true} if any hidden option is set.
2917          *
2918          * @hide
2919          */
areHiddenOptionsSet()2920         public boolean areHiddenOptionsSet() {
2921             return (installFlags & (PackageManager.INSTALL_REQUEST_DOWNGRADE
2922                     | PackageManager.INSTALL_ALLOW_DOWNGRADE
2923                     | PackageManager.INSTALL_DONT_KILL_APP
2924                     | PackageManager.INSTALL_INSTANT_APP
2925                     | PackageManager.INSTALL_FULL_APP
2926                     | PackageManager.INSTALL_VIRTUAL_PRELOAD
2927                     | PackageManager.INSTALL_ALLOCATE_AGGRESSIVE)) != installFlags
2928                     || abiOverride != null || volumeUuid != null;
2929         }
2930 
2931         /**
2932          * Provide value of {@link PackageInfo#installLocation}, which may be used
2933          * to determine where the app will be staged. Defaults to
2934          * {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}.
2935          */
setInstallLocation(int installLocation)2936         public void setInstallLocation(int installLocation) {
2937             this.installLocation = installLocation;
2938         }
2939 
2940         /**
2941          * Optionally indicate the total size (in bytes) of all APKs that will be
2942          * delivered in this session. The system may use this to ensure enough disk
2943          * space exists before proceeding, or to estimate container size for
2944          * installations living on external storage.
2945          *
2946          * @see PackageInfo#INSTALL_LOCATION_AUTO
2947          * @see PackageInfo#INSTALL_LOCATION_PREFER_EXTERNAL
2948          */
setSize(long sizeBytes)2949         public void setSize(long sizeBytes) {
2950             this.sizeBytes = sizeBytes;
2951         }
2952 
2953         /**
2954          * Optionally set the package name of the app being installed. It's strongly
2955          * recommended that you provide this value when known, so that observers can
2956          * communicate installing apps to users.
2957          * <p>
2958          * If the APKs staged in the session aren't consistent with this package
2959          * name, the install will fail. Regardless of this value, all APKs in the
2960          * app must have the same package name.
2961          */
setAppPackageName(@ullable String appPackageName)2962         public void setAppPackageName(@Nullable String appPackageName) {
2963             this.appPackageName = appPackageName;
2964         }
2965 
2966         /**
2967          * Optionally set an icon representing the app being installed. This should
2968          * be roughly {@link ActivityManager#getLauncherLargeIconSize()} in both
2969          * dimensions.
2970          */
setAppIcon(@ullable Bitmap appIcon)2971         public void setAppIcon(@Nullable Bitmap appIcon) {
2972             this.appIcon = appIcon;
2973         }
2974 
2975         /**
2976          * Optionally set a label representing the app being installed.
2977          *
2978          * This value will be trimmed to the first 1000 characters.
2979          */
setAppLabel(@ullable CharSequence appLabel)2980         public void setAppLabel(@Nullable CharSequence appLabel) {
2981             this.appLabel = (appLabel != null) ? appLabel.toString() : null;
2982         }
2983 
2984         /**
2985          * Optionally set the URI where this package was downloaded from. This is
2986          * informational and may be used as a signal for anti-malware purposes.
2987          *
2988          * @see Intent#EXTRA_ORIGINATING_URI
2989          */
setOriginatingUri(@ullable Uri originatingUri)2990         public void setOriginatingUri(@Nullable Uri originatingUri) {
2991             this.originatingUri = originatingUri;
2992         }
2993 
2994         /**
2995          * Sets the UID that initiated the package installation. This is informational
2996          * and may be used as a signal for anti-malware purposes.
2997          */
setOriginatingUid(int originatingUid)2998         public void setOriginatingUid(int originatingUid) {
2999             this.originatingUid = originatingUid;
3000         }
3001 
3002         /**
3003          * Optionally set the URI that referred you to install this package. This is
3004          * informational and may be used as a signal for anti-malware purposes.
3005          *
3006          * @see Intent#EXTRA_REFERRER
3007          */
setReferrerUri(@ullable Uri referrerUri)3008         public void setReferrerUri(@Nullable Uri referrerUri) {
3009             this.referrerUri = referrerUri;
3010         }
3011 
3012         /**
3013          * Sets which runtime permissions to be granted to the package at installation.
3014          *
3015          * @param permissions The permissions to grant or null to grant all runtime
3016          *     permissions.
3017          *
3018          * @deprecated Prefer {@link #setPermissionState(String, int)} instead starting in
3019          * {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}.
3020          * @hide
3021          */
3022         @Deprecated
3023         @SystemApi
3024         @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS)
setGrantedRuntimePermissions(String[] permissions)3025         public void setGrantedRuntimePermissions(String[] permissions) {
3026             if (permissions == null) {
3027                 // The new API has no mechanism to grant all requested permissions
3028                 installFlags |= PackageManager.INSTALL_GRANT_ALL_REQUESTED_PERMISSIONS;
3029                 mPermissionStates.clear();
3030             } else {
3031                 installFlags &= ~PackageManager.INSTALL_GRANT_ALL_REQUESTED_PERMISSIONS;
3032                 // Otherwise call the new API to grant the permissions specified
3033                 for (String permission : permissions) {
3034                     setPermissionState(permission, PERMISSION_STATE_GRANTED);
3035                 }
3036             }
3037         }
3038 
3039         /**
3040          * Sets the state of permissions for the package at installation.
3041          * <p/>
3042          * Granting any runtime permissions require the
3043          * {@code android.Manifest.permission#INSTALL_GRANT_RUNTIME_PERMISSIONS}
3044          * permission to be held by the caller. Revoking runtime
3045          * permissions is not allowed, even during app update sessions.
3046          * <p/>
3047          * Holders without the permission are allowed to change the following special permissions:
3048          * <p/>
3049          * On platform {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE UPSIDE_DOWN_CAKE}:
3050          * <ul>
3051          *     <li>{@link Manifest.permission#USE_FULL_SCREEN_INTENT}</li>
3052          * </ul>
3053          * Install time permissions, which cannot be revoked by the user, cannot be changed by the
3054          * installer.
3055          * <p/>
3056          * See <a href="https://developer.android.com/guide/topics/permissions/overview">
3057          * Permissions on Android</a> for more information.
3058          *
3059          * @param permissionName The permission to change state for.
3060          * @param state          Either {@link #PERMISSION_STATE_DEFAULT},
3061          *                       {@link #PERMISSION_STATE_GRANTED},
3062          *                       or {@link #PERMISSION_STATE_DENIED} to set the permission to.
3063          *
3064          * @return This object for easier chaining.
3065          */
3066         @RequiresPermission(value = android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS,
3067                 conditional = true)
3068         @NonNull
setPermissionState(@onNull String permissionName, @PermissionState int state)3069         public SessionParams setPermissionState(@NonNull String permissionName,
3070                 @PermissionState int state) {
3071             if (TextUtils.isEmpty(permissionName)) {
3072                 throw new IllegalArgumentException("Provided permissionName cannot be "
3073                         + (permissionName == null ? "null" : "empty"));
3074             }
3075 
3076             switch (state) {
3077                 case PERMISSION_STATE_DEFAULT:
3078                     mPermissionStates.remove(permissionName);
3079                     break;
3080                 case PERMISSION_STATE_GRANTED:
3081                 case PERMISSION_STATE_DENIED:
3082                     mPermissionStates.put(permissionName, state);
3083                     break;
3084                 default:
3085                     throw new IllegalArgumentException("Unexpected permission state int: " + state);
3086             }
3087 
3088             return this;
3089         }
3090 
3091         /** @hide */
setPermissionStates(Collection<String> grantPermissions, Collection<String> denyPermissions)3092         public void setPermissionStates(Collection<String> grantPermissions,
3093                 Collection<String> denyPermissions) {
3094             for (String grantPermission : grantPermissions) {
3095                 mPermissionStates.put(grantPermission, PERMISSION_STATE_GRANTED);
3096             }
3097             for (String denyPermission : denyPermissions) {
3098                 mPermissionStates.put(denyPermission, PERMISSION_STATE_DENIED);
3099             }
3100         }
3101 
3102         /**
3103          * Optionally indicate the package source of the app being installed. This is
3104          * informational and may be used as a signal by the system.
3105          *
3106          * An installer should specify {@link #PACKAGE_SOURCE_OTHER} if no other package source
3107          * constant adequately reflects the source for this session.
3108          *
3109          * The default value is {@link #PACKAGE_SOURCE_UNSPECIFIED}.
3110          */
setPackageSource(@ackageSourceType int packageSource)3111         public void setPackageSource(@PackageSourceType int packageSource) {
3112             this.packageSource = packageSource;
3113         }
3114 
3115         /**
3116          * Sets which restricted permissions to be allowlisted for the app. Allowlisting
3117          * is not granting the permissions, rather it allows the app to hold permissions
3118          * which are otherwise restricted. Allowlisting a non restricted permission has
3119          * no effect.
3120          *
3121          * <p> Permissions can be hard restricted which means that the app cannot hold
3122          * them or soft restricted where the app can hold the permission but in a weaker
3123          * form. Whether a permission is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard
3124          * restricted} or {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted}
3125          * depends on the permission declaration. Allowlisting a hard restricted permission
3126          * allows the app to hold that permission and allowlisting a soft restricted
3127          * permission allows the app to hold the permission in its full, unrestricted form.
3128          *
3129          * <p> Permissions can also be immutably restricted which means that the allowlist
3130          * state of the permission can be determined only at install time and cannot be
3131          * changed on updated or at a later point via the package manager APIs.
3132          *
3133          * <p>Initially, all restricted permissions are allowlisted but you can change
3134          * which ones are allowlisted by calling this method or the corresponding ones
3135          * on the {@link PackageManager}. Only soft or hard restricted permissions on the current
3136          * Android version are supported and any invalid entries will be removed.
3137          *
3138          * @see PackageManager#addWhitelistedRestrictedPermission(String, String, int)
3139          * @see PackageManager#removeWhitelistedRestrictedPermission(String, String, int)
3140          */
setWhitelistedRestrictedPermissions(@ullable Set<String> permissions)3141         public void setWhitelistedRestrictedPermissions(@Nullable Set<String> permissions) {
3142             if (permissions == RESTRICTED_PERMISSIONS_ALL) {
3143                 installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
3144                 whitelistedRestrictedPermissions = null;
3145             } else {
3146                 installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
3147                 whitelistedRestrictedPermissions = (permissions != null)
3148                         ? new ArrayList<>(permissions) : null;
3149             }
3150         }
3151 
3152         /**
3153          * Sets whether permissions should be auto-revoked if this package is unused for an
3154          * extended periodd of time.
3155          *
3156          * It's disabled by default but generally the installer should enable it for most packages,
3157          * excluding only those where doing so might cause breakage that cannot be easily addressed
3158          * by simply re-requesting the permission(s).
3159          *
3160          * If user explicitly enabled or disabled it via settings, this call is ignored.
3161          *
3162          * @param shouldAutoRevoke whether permissions should be auto-revoked.
3163          *
3164          * @deprecated No longer used
3165          */
3166         @Deprecated
setAutoRevokePermissionsMode(boolean shouldAutoRevoke)3167         public void setAutoRevokePermissionsMode(boolean shouldAutoRevoke) {
3168             autoRevokePermissionsMode = shouldAutoRevoke ? MODE_ALLOWED : MODE_IGNORED;
3169         }
3170 
3171         /**
3172          * Request that rollbacks be enabled or disabled for the given upgrade with rollback data
3173          * policy set to RESTORE.
3174          *
3175          * <p>If the parent session is staged or has rollback enabled, all children sessions
3176          * must have the same properties.
3177          *
3178          * @param enable set to {@code true} to enable, {@code false} to disable
3179          * @see SessionParams#setEnableRollback(boolean, int)
3180          * @hide
3181          */
3182         @SystemApi
setEnableRollback(boolean enable)3183         public void setEnableRollback(boolean enable) {
3184             setEnableRollback(enable, PackageManager.ROLLBACK_DATA_POLICY_RESTORE);
3185         }
3186 
3187         /**
3188          * Request that rollbacks be enabled or disabled for the given upgrade.
3189          *
3190          * <p>If the parent session is staged or has rollback enabled, all children sessions
3191          * must have the same properties.
3192          *
3193          * <p> For a multi-package install, this method must be called on each child session to
3194          * specify rollback data policies explicitly. Note each child session is allowed to have
3195          * different policies.
3196          *
3197          * @param enable set to {@code true} to enable, {@code false} to disable
3198          * @param dataPolicy the rollback data policy for this session
3199          * @hide
3200          */
3201         @SystemApi
setEnableRollback(boolean enable, @PackageManager.RollbackDataPolicy int dataPolicy)3202         public void setEnableRollback(boolean enable,
3203                 @PackageManager.RollbackDataPolicy int dataPolicy) {
3204             if (enable) {
3205                 installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
3206             } else {
3207                 installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
3208                 rollbackLifetimeMillis = 0;
3209             }
3210             rollbackDataPolicy = dataPolicy;
3211         }
3212 
3213         /**
3214          * If rollback enabled for this session (via {@link #setEnableRollback}, set period
3215          * after which rollback files will be deleted due to expiration
3216          * {@link RollbackManagerServiceImpl#deleteRollback}.
3217          *
3218          * <p>For multi-package installs, this value must be set on the parent session.
3219          * Child session rollback lifetime will be ignored.
3220          *
3221          * @param lifetimeMillis period after which rollback expires
3222          * @throws IllegalArgumentException if lifetimeMillis is negative or rollback is not
3223          * enabled via setEnableRollback.
3224          * @hide
3225          */
3226         @SystemApi
3227         @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
3228         @FlaggedApi(Flags.FLAG_ROLLBACK_LIFETIME)
setRollbackLifetimeMillis(@urationMillisLong long lifetimeMillis)3229         public void setRollbackLifetimeMillis(@DurationMillisLong long lifetimeMillis) {
3230             if (lifetimeMillis < 0) {
3231                 throw new IllegalArgumentException("rollbackLifetimeMillis can't be negative.");
3232             }
3233             if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
3234                 throw new IllegalArgumentException(
3235                         "Can't set rollbackLifetimeMillis when rollback is not enabled");
3236             }
3237             rollbackLifetimeMillis = lifetimeMillis;
3238         }
3239 
3240         /**
3241          * rollbackImpactLevel is a measure of impact a rollback has on the user. This can take one
3242          * of 3 values:
3243          * <ul>
3244          *     <li>{@link PackageManager#ROLLBACK_USER_IMPACT_LOW} (default)</li>
3245          *     <li>{@link PackageManager#ROLLBACK_USER_IMPACT_HIGH} (1)</li>
3246          *     <li>{@link PackageManager#ROLLBACK_USER_IMPACT_ONLY_MANUAL} (2)</li>
3247          * </ul>
3248          *
3249          * @hide
3250          */
3251         @SystemApi
3252         @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
setRollbackImpactLevel(@ackageManager.RollbackImpactLevel int impactLevel)3253         public void setRollbackImpactLevel(@PackageManager.RollbackImpactLevel int impactLevel) {
3254             if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
3255                 throw new IllegalArgumentException(
3256                         "Can't set rollbackImpactLevel when rollback is not enabled");
3257             }
3258             rollbackImpactLevel = impactLevel;
3259         }
3260 
3261         /**
3262          * @deprecated use {@link #setRequestDowngrade(boolean)}.
3263          * {@hide}
3264          */
3265         @SystemApi
3266         @Deprecated
setAllowDowngrade(boolean allowDowngrade)3267         public void setAllowDowngrade(boolean allowDowngrade) {
3268             setRequestDowngrade(allowDowngrade);
3269         }
3270 
3271         /** {@hide} */
3272         @SystemApi
setRequestDowngrade(boolean requestDowngrade)3273         public void setRequestDowngrade(boolean requestDowngrade) {
3274             if (requestDowngrade) {
3275                 installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
3276             } else {
3277                 installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE;
3278             }
3279         }
3280 
3281         /**
3282          * Require the given version of the package be installed.
3283          * The install will only be allowed if the existing version code of
3284          * the package installed on the device matches the given version code.
3285          * Use {@link * PackageManager#VERSION_CODE_HIGHEST} to allow
3286          * installation regardless of the currently installed package version.
3287          *
3288          * @hide
3289          */
setRequiredInstalledVersionCode(long versionCode)3290         public void setRequiredInstalledVersionCode(long versionCode) {
3291             requiredInstalledVersionCode = versionCode;
3292         }
3293 
3294         /** {@hide} */
setInstallFlagsForcePermissionPrompt()3295         public void setInstallFlagsForcePermissionPrompt() {
3296             installFlags |= PackageManager.INSTALL_FORCE_PERMISSION_PROMPT;
3297         }
3298 
3299         /**
3300          * Requests that the system not kill any of the package's running
3301          * processes as part of a {@link SessionParams#MODE_INHERIT_EXISTING}
3302          * session in which splits being added. By default, all installs will
3303          * result in the package's running processes being killed before the
3304          * install completes.
3305          *
3306          * @param dontKillApp set to {@code true} to request that the processes
3307          *                    belonging to the package not be killed as part of
3308          *                    this install.
3309          */
setDontKillApp(boolean dontKillApp)3310         public void setDontKillApp(boolean dontKillApp) {
3311             if (dontKillApp) {
3312                 installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
3313             } else {
3314                 installFlags &= ~PackageManager.INSTALL_DONT_KILL_APP;
3315             }
3316         }
3317 
3318         /** {@hide} */
3319         @SystemApi
setInstallAsInstantApp(boolean isInstantApp)3320         public void setInstallAsInstantApp(boolean isInstantApp) {
3321             if (isInstantApp) {
3322                 installFlags |= PackageManager.INSTALL_INSTANT_APP;
3323                 installFlags &= ~PackageManager.INSTALL_FULL_APP;
3324             } else {
3325                 installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
3326                 installFlags |= PackageManager.INSTALL_FULL_APP;
3327             }
3328         }
3329 
3330         /**
3331          * Sets the install as a virtual preload. Will only have effect when called
3332          * by the verifier.
3333          * {@hide}
3334          */
3335         @SystemApi
setInstallAsVirtualPreload()3336         public void setInstallAsVirtualPreload() {
3337             installFlags |= PackageManager.INSTALL_VIRTUAL_PRELOAD;
3338         }
3339 
3340         /**
3341          * Set the reason for installing this package.
3342          * <p>
3343          * The install reason should be a pre-defined integer. The behavior is
3344          * undefined if other values are used.
3345          *
3346          * @see PackageManager#INSTALL_REASON_UNKNOWN
3347          * @see PackageManager#INSTALL_REASON_POLICY
3348          * @see PackageManager#INSTALL_REASON_DEVICE_RESTORE
3349          * @see PackageManager#INSTALL_REASON_DEVICE_SETUP
3350          * @see PackageManager#INSTALL_REASON_USER
3351          */
setInstallReason(@nstallReason int installReason)3352         public void setInstallReason(@InstallReason int installReason) {
3353             this.installReason = installReason;
3354         }
3355 
3356         /** {@hide} */
3357         @SystemApi
3358         @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE)
setAllocateAggressive(boolean allocateAggressive)3359         public void setAllocateAggressive(boolean allocateAggressive) {
3360             if (allocateAggressive) {
3361                 installFlags |= PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
3362             } else {
3363                 installFlags &= ~PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
3364             }
3365         }
3366 
3367         /**
3368          * @hide
3369          */
3370         @TestApi
setInstallFlagAllowTest()3371         public void setInstallFlagAllowTest() {
3372             installFlags |= PackageManager.INSTALL_ALLOW_TEST;
3373         }
3374 
3375         /**
3376          * Set the installer package for the app.
3377          *
3378          * By default this is the app that created the {@link PackageInstaller} object.
3379          *
3380          * Note: Only applications with {@link android.Manifest.permission#INSTALL_PACKAGES}
3381          * permission are allowed to set an installer that is not the caller's own installer
3382          * package name, otherwise it will cause a {@link SecurityException} when creating the
3383          * install session.
3384          *
3385          * @param installerPackageName The name of the installer package, its length must be less
3386          *                            than {@code 255}, otherwise it will be invalid.
3387          */
setInstallerPackageName(@ullable String installerPackageName)3388         public void setInstallerPackageName(@Nullable String installerPackageName) {
3389             this.installerPackageName = installerPackageName;
3390         }
3391 
3392         /**
3393          * Set this session to be the parent of a multi-package install.
3394          *
3395          * A multi-package install session contains no APKs and only references other install
3396          * sessions via ID. When a multi-package session is committed, all of its children
3397          * are committed to the system in an atomic manner. If any children fail to install,
3398          * all of them do, including the multi-package session.
3399          */
setMultiPackage()3400         public void setMultiPackage() {
3401             this.isMultiPackage = true;
3402         }
3403 
3404         /**
3405          * Set this session to be staged to be installed at reboot.
3406          *
3407          * Staged sessions are scheduled to be installed at next reboot. Staged sessions can also be
3408          * multi-package. In that case, if any of the children sessions fail to install at reboot,
3409          * all the other children sessions are aborted as well.
3410          *
3411          * <p>If the parent session is staged or has rollback enabled, all children sessions
3412          * must have the same properties.
3413          *
3414          * {@hide}
3415          */
3416         @SystemApi
3417         @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
setStaged()3418         public void setStaged() {
3419             this.isStaged = true;
3420         }
3421 
3422         /**
3423          * Set this session to be installing an APEX package.
3424          *
3425          * {@hide}
3426          */
3427         @SystemApi
3428         @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
setInstallAsApex()3429         public void setInstallAsApex() {
3430             installFlags |= PackageManager.INSTALL_APEX;
3431         }
3432 
3433         /** @hide */
getEnableRollback()3434         public boolean getEnableRollback() {
3435             return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0;
3436         }
3437 
3438         /**
3439          * Set the data loader params for the session.
3440          * This also switches installation into data loading mode and disallow direct writes into
3441          * staging folder.
3442          *
3443          * @see android.service.dataloader.DataLoaderService.DataLoader
3444          *
3445          * {@hide}
3446          */
3447         @SystemApi
3448         @RequiresPermission(allOf = {
3449                 Manifest.permission.INSTALL_PACKAGES,
3450                 Manifest.permission.USE_INSTALLER_V2})
setDataLoaderParams(@onNull DataLoaderParams dataLoaderParams)3451         public void setDataLoaderParams(@NonNull DataLoaderParams dataLoaderParams) {
3452             this.dataLoaderParams = dataLoaderParams;
3453         }
3454 
3455         /**
3456          *
3457          * {@hide}
3458          */
setForceQueryable()3459         public void setForceQueryable() {
3460             this.forceQueryableOverride = true;
3461         }
3462 
3463         /**
3464          * Optionally indicate whether user action should be required when the session is
3465          * committed.
3466          * <p>
3467          * Defaults to {@link #USER_ACTION_UNSPECIFIED} unless otherwise set. When unspecified for
3468          * installers using the
3469          * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES REQUEST_INSTALL_PACKAGES}
3470          * permission will behave as if set to {@link #USER_ACTION_REQUIRED}, and
3471          * {@link #USER_ACTION_NOT_REQUIRED} otherwise. When {@code requireUserAction} is set to
3472          * {@link #USER_ACTION_REQUIRED}, installers will receive a
3473          * {@link #STATUS_PENDING_USER_ACTION} callback once the session is committed, indicating
3474          * that user action is required for the install to proceed.
3475          * <p>
3476          * For installers that have been granted the
3477          * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES REQUEST_INSTALL_PACKAGES}
3478          * permission, user action will not be required when all of the following conditions are
3479          * met:
3480          *
3481          * <ul>
3482          *     <li>{@code requireUserAction} is set to {@link #USER_ACTION_NOT_REQUIRED}.</li>
3483          *     <li>The app being installed targets:
3484          *          <ul>
3485          *              <li>{@link android.os.Build.VERSION_CODES#Q API 29} or higher on
3486          *              Android S  ({@link android.os.Build.VERSION_CODES#S API 31})</li>
3487          *              <li>{@link android.os.Build.VERSION_CODES#R API 30} or higher on
3488          *              Android T ({@link android.os.Build.VERSION_CODES#TIRAMISU API 33})</li>
3489          *              <li>{@link android.os.Build.VERSION_CODES#S API 31} or higher on
3490          *              Android U ({@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE API 34})
3491          *              </li>
3492          *              <li>{@link android.os.Build.VERSION_CODES#TIRAMISU API 33} or higher on
3493          *              Android V ({@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM API 35})
3494          *              </li>
3495          *          </ul>
3496          *     </li>
3497          *     <li>The installer is:
3498          *         <ul>
3499          *             <li>The {@link InstallSourceInfo#getUpdateOwnerPackageName() update owner}
3500          *             of an existing version of the app (in other words, this install session is
3501          *             an app update) if the update ownership enforcement is enabled.</li>
3502          *             <li>The
3503          *             {@link InstallSourceInfo#getInstallingPackageName() installer of record}
3504          *             of an existing version of the app (in other words, this install
3505          *             session is an app update) if the update ownership enforcement isn't
3506          *             enabled.</li>
3507          *             <li>Updating itself.</li>
3508          *         </ul>
3509          *     </li>
3510          *     <li>The installer declares the
3511          *     {@link android.Manifest.permission#UPDATE_PACKAGES_WITHOUT_USER_ACTION
3512          *     UPDATE_PACKAGES_WITHOUT_USER_ACTION} permission.</li>
3513          * </ul>
3514          * <p>
3515          * Note: The target API level requirement will advance in future Android versions.
3516          * Session owners should always be prepared to handle {@link #STATUS_PENDING_USER_ACTION}.
3517          *
3518          * @param requireUserAction whether user action should be required.
3519          */
setRequireUserAction( @essionParams.UserActionRequirement int requireUserAction)3520         public void setRequireUserAction(
3521                 @SessionParams.UserActionRequirement int requireUserAction) {
3522             if (requireUserAction != USER_ACTION_UNSPECIFIED
3523                     && requireUserAction != USER_ACTION_REQUIRED
3524                     && requireUserAction != USER_ACTION_NOT_REQUIRED) {
3525                 throw new IllegalArgumentException("requireUserAction set as invalid value of "
3526                         + requireUserAction + ", but must be one of ["
3527                         + "USER_ACTION_UNSPECIFIED, USER_ACTION_REQUIRED, USER_ACTION_NOT_REQUIRED"
3528                         + "]");
3529             }
3530             this.requireUserAction = requireUserAction;
3531         }
3532 
3533         /**
3534          * Sets the install scenario for this session, which describes the expected user journey.
3535          */
setInstallScenario(@nstallScenario int installScenario)3536         public void setInstallScenario(@InstallScenario int installScenario) {
3537             this.installScenario = installScenario;
3538         }
3539 
3540         /**
3541          * Request to keep the original application enabled setting. This will prevent the
3542          * application from being enabled if it was previously in a disabled state.
3543          */
setApplicationEnabledSettingPersistent()3544         public void setApplicationEnabledSettingPersistent() {
3545             this.applicationEnabledSettingPersistent = true;
3546         }
3547 
3548         /**
3549          * Optionally indicate whether the package being installed needs the update ownership
3550          * enforcement. Once the update ownership enforcement is enabled, the other installers
3551          * will need the user action to update the package even if the installers have been
3552          * granted the {@link android.Manifest.permission#INSTALL_PACKAGES INSTALL_PACKAGES}
3553          * permission. Default to {@code false}.
3554          *
3555          * The update ownership enforcement can only be enabled on initial installation. Set
3556          * this to {@code true} on package update is a no-op.
3557          *
3558          * Note: To enable the update ownership enforcement, the installer must have the
3559          * {@link android.Manifest.permission#ENFORCE_UPDATE_OWNERSHIP ENFORCE_UPDATE_OWNERSHIP}
3560          * permission.
3561          */
3562         @RequiresPermission(Manifest.permission.ENFORCE_UPDATE_OWNERSHIP)
setRequestUpdateOwnership(boolean enable)3563         public void setRequestUpdateOwnership(boolean enable) {
3564             if (enable) {
3565                 this.installFlags |= PackageManager.INSTALL_REQUEST_UPDATE_OWNERSHIP;
3566             } else {
3567                 this.installFlags &= ~PackageManager.INSTALL_REQUEST_UPDATE_OWNERSHIP;
3568             }
3569         }
3570 
3571         /**
3572          * Used to set the unarchive ID received as part of an
3573          * {@link Intent#ACTION_UNARCHIVE_PACKAGE}.
3574          *
3575          * <p> The ID should be retrieved from the unarchive intent and passed into the
3576          * session that's being created to unarchive the app in question. Used to link the unarchive
3577          * intent and the install session to disambiguate.
3578          */
3579         @FlaggedApi(Flags.FLAG_ARCHIVING)
setUnarchiveId(int unarchiveId)3580         public void setUnarchiveId(int unarchiveId) {
3581             this.unarchiveId = unarchiveId;
3582         }
3583 
3584         /** @hide */
setDexoptCompilerFilter(@ullable String dexoptCompilerFilter)3585         public void setDexoptCompilerFilter(@Nullable String dexoptCompilerFilter) {
3586             this.dexoptCompilerFilter = dexoptCompilerFilter;
3587         }
3588 
3589         /** @hide */
3590         @NonNull
getPermissionStates()3591         public ArrayMap<String, Integer> getPermissionStates() {
3592             return mPermissionStates;
3593         }
3594 
3595         /** @hide */
3596         @Nullable
getLegacyGrantedRuntimePermissions()3597         public String[] getLegacyGrantedRuntimePermissions() {
3598             if ((installFlags & PackageManager.INSTALL_GRANT_ALL_REQUESTED_PERMISSIONS) != 0) {
3599                 return null;
3600             }
3601 
3602             var grantedPermissions = new ArrayList<String>();
3603             for (int index = 0; index < mPermissionStates.size(); index++) {
3604                 var permissionName = mPermissionStates.keyAt(index);
3605                 var state = mPermissionStates.valueAt(index);
3606                 if (state == PERMISSION_STATE_GRANTED) {
3607                     grantedPermissions.add(permissionName);
3608                 }
3609             }
3610 
3611             return grantedPermissions.toArray(ArrayUtils.emptyArray(String.class));
3612         }
3613 
3614         /**
3615          * Optionally indicate whether missing SDK or static shared library dependencies should be
3616          * automatically fetched and installed when installing an app that wants to use these
3617          * dependencies.
3618          *
3619          * <p> This feature is enabled by default. Note that in the case of a multi-package
3620          * installation session, no dependencies will be automatically installed even if this field
3621          * is set to true.
3622          *
3623          * @param enableAutoInstallDependencies {@code true} to enable auto-installation of missing
3624          *                                      SDK or static shared library dependencies,
3625          *                                      {@code false} to disable and fail immediately if
3626          *                                      dependencies aren't already installed.
3627          */
3628         @FlaggedApi(Flags.FLAG_SDK_DEPENDENCY_INSTALLER)
setAutoInstallDependenciesEnabled(boolean enableAutoInstallDependencies)3629         public void setAutoInstallDependenciesEnabled(boolean enableAutoInstallDependencies) {
3630             isAutoInstallDependenciesEnabled = enableAutoInstallDependencies;
3631         }
3632 
3633         /** {@hide} */
dump(IndentingPrintWriter pw)3634         public void dump(IndentingPrintWriter pw) {
3635             pw.printPair("mode", mode);
3636             pw.printHexPair("installFlags", installFlags);
3637             pw.printPair("installLocation", installLocation);
3638             pw.printPair("installReason", installReason);
3639             pw.printPair("installScenario", installScenario);
3640             pw.printPair("sizeBytes", sizeBytes);
3641             pw.printPair("appPackageName", appPackageName);
3642             pw.printPair("appIcon", (appIcon != null));
3643             pw.printPair("appLabel", appLabel);
3644             pw.printPair("originatingUri", originatingUri);
3645             pw.printPair("originatingUid", originatingUid);
3646             pw.printPair("referrerUri", referrerUri);
3647             pw.printPair("abiOverride", abiOverride);
3648             pw.printPair("volumeUuid", volumeUuid);
3649             pw.printPair("mPermissionStates", mPermissionStates);
3650             pw.printPair("packageSource", packageSource);
3651             pw.printPair("whitelistedRestrictedPermissions", whitelistedRestrictedPermissions);
3652             pw.printPair("autoRevokePermissions", autoRevokePermissionsMode);
3653             pw.printPair("installerPackageName", installerPackageName);
3654             pw.printPair("isMultiPackage", isMultiPackage);
3655             pw.printPair("isStaged", isStaged);
3656             pw.printPair("forceQueryable", forceQueryableOverride);
3657             pw.printPair("requireUserAction", SessionInfo.userActionToString(requireUserAction));
3658             pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode);
3659             pw.printPair("dataLoaderParams", dataLoaderParams);
3660             pw.printPair("rollbackDataPolicy", rollbackDataPolicy);
3661             pw.printPair("rollbackLifetimeMillis", rollbackLifetimeMillis);
3662             pw.printPair("rollbackImpactLevel", rollbackImpactLevel);
3663             pw.printPair("applicationEnabledSettingPersistent",
3664                     applicationEnabledSettingPersistent);
3665             pw.printHexPair("developmentInstallFlags", developmentInstallFlags);
3666             pw.printPair("unarchiveId", unarchiveId);
3667             pw.printPair("dexoptCompilerFilter", dexoptCompilerFilter);
3668             pw.printPair("isAutoInstallDependenciesEnabled", isAutoInstallDependenciesEnabled);
3669             pw.println();
3670         }
3671 
3672         @Override
describeContents()3673         public int describeContents() {
3674             return 0;
3675         }
3676 
3677         @Override
writeToParcel(Parcel dest, int flags)3678         public void writeToParcel(Parcel dest, int flags) {
3679             dest.writeInt(mode);
3680             dest.writeInt(installFlags);
3681             dest.writeInt(installLocation);
3682             dest.writeInt(installReason);
3683             dest.writeInt(installScenario);
3684             dest.writeLong(sizeBytes);
3685             dest.writeString(appPackageName);
3686             dest.writeParcelable(appIcon, flags);
3687             dest.writeString(appLabel);
3688             dest.writeParcelable(originatingUri, flags);
3689             dest.writeInt(originatingUid);
3690             dest.writeParcelable(referrerUri, flags);
3691             dest.writeString(abiOverride);
3692             dest.writeString(volumeUuid);
3693             dest.writeMap(mPermissionStates);
3694             dest.writeStringList(whitelistedRestrictedPermissions);
3695             dest.writeInt(autoRevokePermissionsMode);
3696             dest.writeString(installerPackageName);
3697             dest.writeBoolean(isMultiPackage);
3698             dest.writeBoolean(isStaged);
3699             dest.writeBoolean(forceQueryableOverride);
3700             dest.writeLong(requiredInstalledVersionCode);
3701             if (dataLoaderParams != null) {
3702                 dest.writeParcelable(dataLoaderParams.getData(), flags);
3703             } else {
3704                 dest.writeParcelable(null, flags);
3705             }
3706             dest.writeInt(rollbackDataPolicy);
3707             dest.writeLong(rollbackLifetimeMillis);
3708             dest.writeInt(rollbackImpactLevel);
3709             dest.writeInt(requireUserAction);
3710             dest.writeInt(packageSource);
3711             dest.writeBoolean(applicationEnabledSettingPersistent);
3712             dest.writeInt(developmentInstallFlags);
3713             dest.writeInt(unarchiveId);
3714             dest.writeString(dexoptCompilerFilter);
3715             dest.writeBoolean(isAutoInstallDependenciesEnabled);
3716         }
3717 
3718         public static final Parcelable.Creator<SessionParams>
3719                 CREATOR = new Parcelable.Creator<SessionParams>() {
3720                     @Override
3721                     public SessionParams createFromParcel(Parcel p) {
3722                         return new SessionParams(p);
3723                     }
3724 
3725                     @Override
3726                     public SessionParams[] newArray(int size) {
3727                         return new SessionParams[size];
3728                     }
3729                 };
3730     }
3731 
3732     /**
3733      * Details for an active install session.
3734      */
3735     public static class SessionInfo implements Parcelable {
3736 
3737         /**
3738          * A session ID that does not exist or is invalid.
3739          */
3740         public static final int INVALID_ID = -1;
3741         /** {@hide} */
3742         private static final int[] NO_SESSIONS = {};
3743 
3744         /**
3745          * @deprecated use {@link #SESSION_NO_ERROR}.
3746          */
3747         @Deprecated
3748         public static final int STAGED_SESSION_NO_ERROR = 0;
3749 
3750         /**
3751          * @deprecated use {@link #SESSION_VERIFICATION_FAILED}.
3752          */
3753         @Deprecated
3754         public static final int STAGED_SESSION_VERIFICATION_FAILED = 1;
3755 
3756         /**
3757          * @deprecated use {@link #SESSION_ACTIVATION_FAILED}.
3758          */
3759         @Deprecated
3760         public static final int STAGED_SESSION_ACTIVATION_FAILED = 2;
3761 
3762         /**
3763          * @deprecated use {@link #SESSION_UNKNOWN_ERROR}.
3764          */
3765         @Deprecated
3766         public static final int STAGED_SESSION_UNKNOWN = 3;
3767 
3768         /**
3769          * @deprecated use {@link #SESSION_CONFLICT}.
3770          */
3771         @Deprecated
3772         public static final int STAGED_SESSION_CONFLICT = 4;
3773 
3774         /**
3775          * Constant indicating that no error occurred during the preparation or the activation of
3776          * this session.
3777          */
3778         public static final int SESSION_NO_ERROR = 0;
3779 
3780         /**
3781          * Constant indicating that an error occurred during the verification phase of
3782          * this session.
3783          */
3784         public static final int SESSION_VERIFICATION_FAILED = 1;
3785 
3786         /**
3787          * Constant indicating that an error occurred during the activation phase of
3788          * this session.
3789          */
3790         public static final int SESSION_ACTIVATION_FAILED = 2;
3791 
3792         /**
3793          * Constant indicating that an unknown error occurred while processing this session.
3794          */
3795         public static final int SESSION_UNKNOWN_ERROR = 3;
3796 
3797         /**
3798          * Constant indicating that the session was in conflict with another session and had
3799          * to be sacrificed for resolution.
3800          */
3801         public static final int SESSION_CONFLICT = 4;
3802 
userActionToString(int requireUserAction)3803         private static String userActionToString(int requireUserAction) {
3804             switch(requireUserAction) {
3805                 case SessionParams.USER_ACTION_REQUIRED:
3806                     return "REQUIRED";
3807                 case SessionParams.USER_ACTION_NOT_REQUIRED:
3808                     return "NOT_REQUIRED";
3809                 default:
3810                     return "UNSPECIFIED";
3811             }
3812         }
3813 
3814         /** {@hide} */
3815         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
3816         public int sessionId;
3817         /** {@hide} */
3818         public int userId;
3819         /** {@hide} */
3820         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
3821         public String installerPackageName;
3822         /** {@hide} */
3823         public String installerAttributionTag;
3824         /** {@hide} */
3825         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
3826         public String resolvedBaseCodePath;
3827         /** {@hide} */
3828         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
3829         public float progress;
3830         /** {@hide} */
3831         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
3832         public boolean sealed;
3833         /** {@hide} */
3834         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
3835         public boolean active;
3836 
3837         /** {@hide} */
3838         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
3839         public int mode;
3840         /** {@hide} */
3841         public @InstallReason int installReason;
3842         /** {@hide} */
3843         public @InstallScenario int installScenario;
3844         /** {@hide} */
3845         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
3846         public long sizeBytes;
3847         /** {@hide} */
3848         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
3849         public String appPackageName;
3850         /** {@hide} */
3851         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
3852         public Bitmap appIcon;
3853         /** {@hide} */
3854         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
3855         public CharSequence appLabel;
3856 
3857         /** {@hide} */
3858         public int installLocation;
3859         /** {@hide} */
3860         public Uri originatingUri;
3861         /** {@hide} */
3862         public int originatingUid;
3863         /** {@hide} */
3864         public Uri referrerUri;
3865         /** {@hide} */
3866         public String[] grantedRuntimePermissions;
3867         /** {@hide}*/
3868         public List<String> whitelistedRestrictedPermissions;
3869         /** {@hide}*/
3870         public int autoRevokePermissionsMode = MODE_DEFAULT;
3871         /** {@hide} */
3872         public int installFlags;
3873         /** {@hide} */
3874         public boolean isMultiPackage;
3875         /** {@hide} */
3876         public boolean isStaged;
3877         /** {@hide} */
3878         public boolean forceQueryable;
3879         /** {@hide} */
3880         public int parentSessionId = INVALID_ID;
3881         /** {@hide} */
3882         public int[] childSessionIds = NO_SESSIONS;
3883 
3884         /** {@hide} */
3885         public boolean isSessionApplied;
3886         /** {@hide} */
3887         public boolean isSessionReady;
3888         /** {@hide} */
3889         public boolean isSessionFailed;
3890         private int mSessionErrorCode;
3891         private String mSessionErrorMessage;
3892 
3893         /** {@hide} */
3894         public boolean isAutoInstallingDependenciesEnabled;
3895 
3896         /** {@hide} */
3897         public boolean isCommitted;
3898 
3899         /** {@hide} */
3900         public long createdMillis;
3901 
3902         /** {@hide} */
3903         public long updatedMillis;
3904 
3905         /** {@hide} */
3906         public int rollbackDataPolicy;
3907 
3908         /** @hide */
3909         public long rollbackLifetimeMillis;
3910 
3911         /** {@hide} */
3912         public int rollbackImpactLevel;
3913 
3914         /** {@hide} */
3915         public int requireUserAction;
3916 
3917         /** {@hide} */
3918         public int packageSource = PACKAGE_SOURCE_UNSPECIFIED;
3919 
3920         /** {@hide} */
3921         public int installerUid;
3922 
3923         /** @hide */
3924         public boolean isPreapprovalRequested;
3925 
3926         /** @hide */
3927         public boolean applicationEnabledSettingPersistent;
3928 
3929         /** @hide */
3930         public int pendingUserActionReason;
3931 
3932         /** {@hide} */
3933         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
SessionInfo()3934         public SessionInfo() {
3935         }
3936 
3937         /** {@hide} */
SessionInfo(Parcel source)3938         public SessionInfo(Parcel source) {
3939             sessionId = source.readInt();
3940             userId = source.readInt();
3941             installerPackageName = source.readString();
3942             installerAttributionTag = source.readString();
3943             resolvedBaseCodePath = source.readString();
3944             progress = source.readFloat();
3945             sealed = source.readInt() != 0;
3946             active = source.readInt() != 0;
3947 
3948             mode = source.readInt();
3949             installReason = source.readInt();
3950             installScenario = source.readInt();
3951             sizeBytes = source.readLong();
3952             appPackageName = source.readString();
3953             appIcon = source.readParcelable(null, android.graphics.Bitmap.class);
3954             appLabel = source.readString();
3955 
3956             installLocation = source.readInt();
3957             originatingUri = source.readParcelable(null, android.net.Uri.class);
3958             originatingUid = source.readInt();
3959             referrerUri = source.readParcelable(null, android.net.Uri.class);
3960             grantedRuntimePermissions = source.readStringArray();
3961             whitelistedRestrictedPermissions = source.createStringArrayList();
3962             autoRevokePermissionsMode = source.readInt();
3963 
3964             installFlags = source.readInt();
3965             isMultiPackage = source.readBoolean();
3966             isStaged = source.readBoolean();
3967             forceQueryable = source.readBoolean();
3968             parentSessionId = source.readInt();
3969             childSessionIds = source.createIntArray();
3970             if (childSessionIds == null) {
3971                 childSessionIds = NO_SESSIONS;
3972             }
3973             isSessionApplied = source.readBoolean();
3974             isSessionReady = source.readBoolean();
3975             isSessionFailed = source.readBoolean();
3976             mSessionErrorCode = source.readInt();
3977             mSessionErrorMessage = source.readString();
3978             isCommitted = source.readBoolean();
3979             isPreapprovalRequested = source.readBoolean();
3980             rollbackDataPolicy = source.readInt();
3981             rollbackLifetimeMillis = source.readLong();
3982             rollbackImpactLevel = source.readInt();
3983             createdMillis = source.readLong();
3984             requireUserAction = source.readInt();
3985             installerUid = source.readInt();
3986             packageSource = source.readInt();
3987             applicationEnabledSettingPersistent = source.readBoolean();
3988             pendingUserActionReason = source.readInt();
3989             isAutoInstallingDependenciesEnabled = source.readBoolean();
3990         }
3991 
3992         /**
3993          * Return the ID for this session.
3994          */
getSessionId()3995         public int getSessionId() {
3996             return sessionId;
3997         }
3998 
3999         /**
4000          * Return the user associated with this session.
4001          */
getUser()4002         public @NonNull UserHandle getUser() {
4003             return new UserHandle(userId);
4004         }
4005 
4006         /**
4007          * Return the package name of the app that owns this session.
4008          */
getInstallerPackageName()4009         public @Nullable String getInstallerPackageName() {
4010             return installerPackageName;
4011         }
4012 
4013         /**
4014          * @return {@link android.content.Context#getAttributionTag attribution tag} of the context
4015          * that created this session
4016          */
getInstallerAttributionTag()4017         public @Nullable String getInstallerAttributionTag() {
4018             return installerAttributionTag;
4019         }
4020 
4021         /**
4022          * Return current overall progress of this session, between 0 and 1.
4023          * <p>
4024          * Note that this progress may not directly correspond to the value
4025          * reported by
4026          * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
4027          * system may carve out a portion of the overall progress to represent
4028          * its own internal installation work.
4029          */
getProgress()4030         public float getProgress() {
4031             return progress;
4032         }
4033 
4034         /**
4035          * Return if this session is currently active.
4036          * <p>
4037          * A session is considered active whenever there is ongoing forward
4038          * progress being made, such as the installer holding an open
4039          * {@link Session} instance while streaming data into place, or the
4040          * system optimizing code as the result of
4041          * {@link Session#commit(IntentSender)}.
4042          * <p>
4043          * If the installer closes the {@link Session} without committing, the
4044          * session is considered inactive until the installer opens the session
4045          * again.
4046          */
isActive()4047         public boolean isActive() {
4048             return active;
4049         }
4050 
4051         /**
4052          * Return if this session is sealed.
4053          * <p>
4054          * Once sealed, no further changes may be made to the session. A session
4055          * is sealed the moment {@link Session#commit(IntentSender)} is called.
4056          */
isSealed()4057         public boolean isSealed() {
4058             return sealed;
4059         }
4060 
4061         /**
4062          * Return the reason for installing this package.
4063          *
4064          * @return The install reason.
4065          */
getInstallReason()4066         public @InstallReason int getInstallReason() {
4067             return installReason;
4068         }
4069 
4070         /** {@hide} */
4071         @Deprecated
isOpen()4072         public boolean isOpen() {
4073             return isActive();
4074         }
4075 
4076         /**
4077          * Return the package name this session is working with. May be {@code null}
4078          * if unknown.
4079          */
getAppPackageName()4080         public @Nullable String getAppPackageName() {
4081             return appPackageName;
4082         }
4083 
4084         /**
4085          * Return an icon representing the app being installed. May be {@code null}
4086          * if unavailable.
4087          */
getAppIcon()4088         public @Nullable Bitmap getAppIcon() {
4089             if (appIcon == null) {
4090                 // Icon may have been omitted for calls that return bulk session
4091                 // lists, so try fetching the specific icon.
4092                 try {
4093                     final SessionInfo info = AppGlobals.getPackageManager().getPackageInstaller()
4094                             .getSessionInfo(sessionId);
4095                     appIcon = (info != null) ? info.appIcon : null;
4096                 } catch (RemoteException e) {
4097                     throw e.rethrowFromSystemServer();
4098                 }
4099             }
4100             return appIcon;
4101         }
4102 
4103         /**
4104          * Return a label representing the app being installed. May be {@code null}
4105          * if unavailable.
4106          */
getAppLabel()4107         public @Nullable CharSequence getAppLabel() {
4108             return appLabel;
4109         }
4110 
4111         /**
4112          * Return an Intent that can be started to view details about this install
4113          * session. This may surface actions such as pause, resume, or cancel.
4114          * <p>
4115          * In some cases, a matching Activity may not exist, so ensure you safeguard
4116          * against this.
4117          *
4118          * @see PackageInstaller#ACTION_SESSION_DETAILS
4119          */
createDetailsIntent()4120         public @Nullable Intent createDetailsIntent() {
4121             final Intent intent = new Intent(PackageInstaller.ACTION_SESSION_DETAILS);
4122             intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
4123             intent.setPackage(installerPackageName);
4124             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
4125             return intent;
4126         }
4127 
4128         /**
4129          * Get the mode of the session as set in the constructor of the {@link SessionParams}.
4130          *
4131          * @return One of {@link SessionParams#MODE_FULL_INSTALL}
4132          *         or {@link SessionParams#MODE_INHERIT_EXISTING}
4133          */
getMode()4134         public int getMode() {
4135             return mode;
4136         }
4137 
4138         /**
4139          * Get the value set in {@link SessionParams#setInstallLocation(int)}.
4140          */
getInstallLocation()4141         public int getInstallLocation() {
4142             return installLocation;
4143         }
4144 
4145         /**
4146          * Get the value as set in {@link SessionParams#setSize(long)}.
4147          *
4148          * <p>The value is a hint and does not have to match the actual size.
4149          */
getSize()4150         public long getSize() {
4151             return sizeBytes;
4152         }
4153 
4154         /**
4155          * Get the value set in {@link SessionParams#setOriginatingUri(Uri)}.
4156          * Note: This value will only be non-null for the owner of the session.
4157          */
getOriginatingUri()4158         public @Nullable Uri getOriginatingUri() {
4159             return originatingUri;
4160         }
4161 
4162         /**
4163          * Get the value set in {@link SessionParams#setOriginatingUid(int)}.
4164          */
getOriginatingUid()4165         public int getOriginatingUid() {
4166             return originatingUid;
4167         }
4168 
4169         /**
4170          * Get the value set in {@link SessionParams#setReferrerUri(Uri)}
4171          * Note: This value will only be non-null for the owner of the session.
4172          */
getReferrerUri()4173         public @Nullable Uri getReferrerUri() {
4174             return referrerUri;
4175         }
4176 
4177         /**
4178          * @return the path to the validated base APK for this session, which may point at an
4179          * APK inside the session (when the session defines the base), or it may
4180          * point at the existing base APK (when adding splits to an existing app).
4181          *
4182          * @hide
4183          */
4184         @SystemApi
4185         @RequiresPermission(Manifest.permission.READ_INSTALLED_SESSION_PATHS)
4186         @FlaggedApi(Flags.FLAG_GET_RESOLVED_APK_PATH)
getResolvedBaseApkPath()4187         public @Nullable String getResolvedBaseApkPath() {
4188             return resolvedBaseCodePath;
4189         }
4190 
4191         /**
4192          * Get the value set in {@link SessionParams#setGrantedRuntimePermissions(String[])}.
4193          *
4194          * @hide
4195          */
4196         @SystemApi
getGrantedRuntimePermissions()4197         public @Nullable String[] getGrantedRuntimePermissions() {
4198             return grantedRuntimePermissions;
4199         }
4200 
4201         /**
4202          * Get the value set in {@link SessionParams#setWhitelistedRestrictedPermissions(Set)}.
4203          * Note that if all permissions are allowlisted this method returns {@link
4204          * SessionParams#RESTRICTED_PERMISSIONS_ALL}.
4205          *
4206          * @hide
4207          */
4208         @SystemApi
getWhitelistedRestrictedPermissions()4209         public @NonNull Set<String> getWhitelistedRestrictedPermissions() {
4210             if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0) {
4211                 return SessionParams.RESTRICTED_PERMISSIONS_ALL;
4212             }
4213             if (whitelistedRestrictedPermissions != null) {
4214                 return new ArraySet<>(whitelistedRestrictedPermissions);
4215             }
4216             return Collections.emptySet();
4217         }
4218 
4219         /**
4220          * Get the status of whether permission auto-revocation should be allowed, ignored, or
4221          * deferred to manifest data.
4222          *
4223          * @see android.app.AppOpsManager#MODE_ALLOWED
4224          * @see android.app.AppOpsManager#MODE_IGNORED
4225          * @see android.app.AppOpsManager#MODE_DEFAULT
4226          *
4227          * @return the status of auto-revoke for this package
4228          *
4229          * @hide
4230          */
4231         @SystemApi
getAutoRevokePermissionsMode()4232         public int getAutoRevokePermissionsMode() {
4233             return autoRevokePermissionsMode;
4234         }
4235 
4236         /**
4237          * Get the value set in {@link SessionParams#setAllowDowngrade(boolean)}.
4238          *
4239          * @deprecated use {@link #getRequestDowngrade()}.
4240          * @hide
4241          */
4242         @SystemApi
4243         @Deprecated
getAllowDowngrade()4244         public boolean getAllowDowngrade() {
4245             return getRequestDowngrade();
4246         }
4247 
4248         /**
4249          * Get the value set in {@link SessionParams#setRequestDowngrade(boolean)}.
4250          *
4251          * @hide
4252          */
4253         @SystemApi
getRequestDowngrade()4254         public boolean getRequestDowngrade() {
4255             return (installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0;
4256         }
4257 
4258         /**
4259          * Get the value set in {@link SessionParams#setDontKillApp(boolean)}.
4260          */
getDontKillApp()4261         public boolean getDontKillApp() {
4262             return (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0;
4263         }
4264 
4265         /**
4266          * Get if this session is to be installed as Instant Apps.
4267          *
4268          * @param isInstantApp an unused parameter and is ignored.
4269          * @return {@code true} if {@link SessionParams#setInstallAsInstantApp(boolean)} was called
4270          * with {@code true}; {@code false} if it was called with {@code false} or if it was not
4271          * called.
4272          *
4273          * @see #getInstallAsFullApp
4274          *
4275          * @hide
4276          */
4277         @SystemApi
getInstallAsInstantApp(boolean isInstantApp)4278         public boolean getInstallAsInstantApp(boolean isInstantApp) {
4279             return (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
4280         }
4281 
4282         /**
4283          * Get if this session is to be installed as full apps.
4284          *
4285          * @param isInstantApp an unused parameter and is ignored.
4286          * @return {@code true} if {@link SessionParams#setInstallAsInstantApp(boolean)} was called
4287          * with {@code false}; {code false} if it was called with {@code true} or if it was not
4288          * called.
4289          *
4290          * @see #getInstallAsInstantApp
4291          *
4292          * @hide
4293          */
4294         @SystemApi
getInstallAsFullApp(boolean isInstantApp)4295         public boolean getInstallAsFullApp(boolean isInstantApp) {
4296             return (installFlags & PackageManager.INSTALL_FULL_APP) != 0;
4297         }
4298 
4299         /**
4300          * Get if {@link SessionParams#setInstallAsVirtualPreload()} was called.
4301          *
4302          * @hide
4303          */
4304         @SystemApi
getInstallAsVirtualPreload()4305         public boolean getInstallAsVirtualPreload() {
4306             return (installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0;
4307         }
4308 
4309         /**
4310          * Return whether rollback is enabled or disabled for the given upgrade.
4311          *
4312          * @hide
4313          */
4314         @SystemApi
getEnableRollback()4315         public boolean getEnableRollback() {
4316             return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0;
4317         }
4318 
4319         /**
4320          * Get the value set in {@link SessionParams#setAllocateAggressive(boolean)}.
4321          *
4322          * @hide
4323          */
4324         @SystemApi
getAllocateAggressive()4325         public boolean getAllocateAggressive() {
4326             return (installFlags & PackageManager.INSTALL_ALLOCATE_AGGRESSIVE) != 0;
4327         }
4328 
4329 
4330         /** {@hide} */
4331         @Deprecated
getDetailsIntent()4332         public @Nullable Intent getDetailsIntent() {
4333             return createDetailsIntent();
4334         }
4335 
4336         /**
4337          * Get the package source that was set in
4338          * {@link PackageInstaller.SessionParams#setPackageSource(int)}.
4339          */
getPackageSource()4340         public @PackageSourceType int getPackageSource() {
4341             return packageSource;
4342         }
4343 
4344         /**
4345          * Returns true if this session is a multi-package session containing references to other
4346          * sessions.
4347          */
isMultiPackage()4348         public boolean isMultiPackage() {
4349             return isMultiPackage;
4350         }
4351 
4352         /**
4353          * Returns true if this session is a staged session.
4354          */
isStaged()4355         public boolean isStaged() {
4356             return isStaged;
4357         }
4358 
4359         /**
4360          * Return the data policy associated with the rollback for the given upgrade.
4361          *
4362          * @hide
4363          */
4364         @SystemApi
4365         @PackageManager.RollbackDataPolicy
getRollbackDataPolicy()4366         public int getRollbackDataPolicy() {
4367             return rollbackDataPolicy;
4368         }
4369 
4370         /**
4371          * Returns true if this session is marked as forceQueryable
4372          * {@hide}
4373          */
isForceQueryable()4374         public boolean isForceQueryable() {
4375             return forceQueryable;
4376         }
4377 
4378         /**
4379          * Returns {@code true} if this session is an active staged session.
4380          *
4381          * We consider a session active if it has been committed and it is either pending
4382          * verification, or will be applied at next reboot.
4383          *
4384          * <p>Staged session is active iff:
4385          * <ul>
4386          *     <li>It is committed, i.e. {@link SessionInfo#isCommitted()} is {@code true}, and
4387          *     <li>it is not applied, i.e. {@link SessionInfo#isStagedSessionApplied()} is {@code
4388          *     false}, and
4389          *     <li>it is not failed, i.e. {@link SessionInfo#isStagedSessionFailed()} is
4390          *     {@code false}.
4391          * </ul>
4392          *
4393          * <p>In case of a multi-package session, reasoning above is applied to the parent session,
4394          * since that is the one that should have been {@link Session#commit committed}.
4395          */
isStagedSessionActive()4396         public boolean isStagedSessionActive() {
4397             return isStaged && isCommitted && !isSessionApplied && !isSessionFailed
4398                     && !hasParentSessionId();
4399         }
4400 
4401         /**
4402          * Returns the parent multi-package session ID if this session belongs to one,
4403          * {@link #INVALID_ID} otherwise.
4404          */
getParentSessionId()4405         public int getParentSessionId() {
4406             return parentSessionId;
4407         }
4408 
4409         /**
4410          * Returns true if session has a valid parent session, otherwise false.
4411          */
hasParentSessionId()4412         public boolean hasParentSessionId() {
4413             return parentSessionId != INVALID_ID;
4414         }
4415 
4416         /**
4417          * Returns the set of session IDs that will be committed when this session is committed if
4418          * this session is a multi-package session.
4419          */
4420         @NonNull
getChildSessionIds()4421         public int[] getChildSessionIds() {
4422             return childSessionIds;
4423         }
4424 
checkSessionIsStaged()4425         private void checkSessionIsStaged() {
4426             if (!isStaged) {
4427                 throw new IllegalStateException("Session is not marked as staged.");
4428             }
4429         }
4430 
4431         /**
4432          * Whether the staged session has been applied successfully, meaning that all of its
4433          * packages have been activated and no further action is required.
4434          * Only meaningful if {@code isStaged} is true.
4435          */
isStagedSessionApplied()4436         public boolean isStagedSessionApplied() {
4437             checkSessionIsStaged();
4438             return isSessionApplied;
4439         }
4440 
4441         /**
4442          * Whether the staged session is ready to be applied at next reboot. Only meaningful if
4443          * {@code isStaged} is true.
4444          */
isStagedSessionReady()4445         public boolean isStagedSessionReady() {
4446             checkSessionIsStaged();
4447             return isSessionReady;
4448         }
4449 
4450         /**
4451          * Whether something went wrong and the staged session is declared as failed, meaning that
4452          * it will be ignored at next reboot. Only meaningful if {@code isStaged} is true.
4453          */
isStagedSessionFailed()4454         public boolean isStagedSessionFailed() {
4455             checkSessionIsStaged();
4456             return isSessionFailed;
4457         }
4458 
4459         /**
4460          * If something went wrong with a staged session, clients can check this error code to
4461          * understand which kind of failure happened. Only meaningful if {@code isStaged} is true.
4462          */
getStagedSessionErrorCode()4463         public int getStagedSessionErrorCode() {
4464             checkSessionIsStaged();
4465             return mSessionErrorCode;
4466         }
4467 
4468         /**
4469          * Text description of the error code returned by {@code getStagedSessionErrorCode}, or
4470          * empty string if no error was encountered.
4471          */
getStagedSessionErrorMessage()4472         public @NonNull String getStagedSessionErrorMessage() {
4473             checkSessionIsStaged();
4474             return mSessionErrorMessage;
4475         }
4476 
4477         /** {@hide} */
setSessionErrorCode(int errorCode, String errorMessage)4478         public void setSessionErrorCode(int errorCode, String errorMessage) {
4479             mSessionErrorCode = errorCode;
4480             mSessionErrorMessage = errorMessage;
4481         }
4482 
4483         /**
4484          * Returns {@code true} if {@link Session#commit(IntentSender)}} was called for this
4485          * session.
4486          */
isCommitted()4487         public boolean isCommitted() {
4488             return isCommitted;
4489         }
4490 
4491         /**
4492          * The timestamp of the initial creation of the session.
4493          */
getCreatedMillis()4494         public long getCreatedMillis() {
4495             return createdMillis;
4496         }
4497 
4498         /**
4499          * The timestamp of the last update that occurred to the session, including changing of
4500          * states in case of staged sessions.
4501          */
4502         @CurrentTimeMillisLong
getUpdatedMillis()4503         public long getUpdatedMillis() {
4504             return updatedMillis;
4505         }
4506 
4507         /**
4508          * Whether user action was required by the installer.
4509          *
4510          * <p>
4511          * Note: a return value of {@code USER_ACTION_NOT_REQUIRED} does not guarantee that the
4512          * install will not result in user action.
4513          *
4514          * @return {@link SessionParams#USER_ACTION_NOT_REQUIRED},
4515          *         {@link SessionParams#USER_ACTION_REQUIRED} or
4516          *         {@link SessionParams#USER_ACTION_UNSPECIFIED}
4517          */
4518         @SessionParams.UserActionRequirement
getRequireUserAction()4519         public int getRequireUserAction() {
4520             return requireUserAction;
4521         }
4522 
4523         /**
4524          * Returns the Uid of the owner of the session.
4525          */
getInstallerUid()4526         public int getInstallerUid() {
4527             return installerUid;
4528         }
4529 
4530         /**
4531          * Returns {@code true} if this session will keep the existing application enabled setting
4532          * after installation.
4533          */
isApplicationEnabledSettingPersistent()4534         public boolean isApplicationEnabledSettingPersistent() {
4535             return applicationEnabledSettingPersistent;
4536         }
4537 
4538         /**
4539          * Returns whether this session has requested user pre-approval.
4540          */
isPreApprovalRequested()4541         public boolean isPreApprovalRequested() {
4542             return isPreapprovalRequested;
4543         }
4544 
4545         /**
4546          * @return {@code true} if the installer requested the update ownership enforcement
4547          * for the packages in this session.
4548          *
4549          * @see PackageInstaller.SessionParams#setRequestUpdateOwnership
4550          */
isRequestUpdateOwnership()4551         public boolean isRequestUpdateOwnership() {
4552             return (installFlags & PackageManager.INSTALL_REQUEST_UPDATE_OWNERSHIP) != 0;
4553         }
4554 
4555         /**
4556          * Return the reason for requiring the user action.
4557          * @hide
4558          */
4559         @SystemApi
getPendingUserActionReason()4560         public @UserActionReason int getPendingUserActionReason() {
4561             return pendingUserActionReason;
4562         }
4563 
4564         /**
4565          * Returns true if the session is an unarchival.
4566          *
4567          * @see PackageInstaller#requestUnarchive
4568          */
4569         @FlaggedApi(Flags.FLAG_ARCHIVING)
isUnarchival()4570         public boolean isUnarchival() {
4571             return (installFlags & PackageManager.INSTALL_UNARCHIVE) != 0;
4572         }
4573 
4574         /**
4575          * Check whether missing SDK or static shared library dependencies should be automatically
4576          * fetched and installed when installing an app that wants to use these dependencies.
4577          *
4578          * <p> Note that in the case of a multi-package installation session, no dependencies will
4579          * be automatically installed even if this method returns true.
4580          *
4581          * @return true if the dependencies will be auto-installed, false otherwise.
4582          */
4583         @FlaggedApi(Flags.FLAG_SDK_DEPENDENCY_INSTALLER)
isAutoInstallDependenciesEnabled()4584         public boolean isAutoInstallDependenciesEnabled() {
4585             return isAutoInstallingDependenciesEnabled;
4586         }
4587 
4588         @Override
describeContents()4589         public int describeContents() {
4590             return 0;
4591         }
4592 
4593         @Override
writeToParcel(Parcel dest, int flags)4594         public void writeToParcel(Parcel dest, int flags) {
4595             dest.writeInt(sessionId);
4596             dest.writeInt(userId);
4597             dest.writeString(installerPackageName);
4598             dest.writeString(installerAttributionTag);
4599             dest.writeString(resolvedBaseCodePath);
4600             dest.writeFloat(progress);
4601             dest.writeInt(sealed ? 1 : 0);
4602             dest.writeInt(active ? 1 : 0);
4603 
4604             dest.writeInt(mode);
4605             dest.writeInt(installReason);
4606             dest.writeInt(installScenario);
4607             dest.writeLong(sizeBytes);
4608             dest.writeString(appPackageName);
4609             dest.writeParcelable(appIcon, flags);
4610             dest.writeString(appLabel != null ? appLabel.toString() : null);
4611 
4612             dest.writeInt(installLocation);
4613             dest.writeParcelable(originatingUri, flags);
4614             dest.writeInt(originatingUid);
4615             dest.writeParcelable(referrerUri, flags);
4616             dest.writeStringArray(grantedRuntimePermissions);
4617             dest.writeStringList(whitelistedRestrictedPermissions);
4618             dest.writeInt(autoRevokePermissionsMode);
4619             dest.writeInt(installFlags);
4620             dest.writeBoolean(isMultiPackage);
4621             dest.writeBoolean(isStaged);
4622             dest.writeBoolean(forceQueryable);
4623             dest.writeInt(parentSessionId);
4624             dest.writeIntArray(childSessionIds);
4625             dest.writeBoolean(isSessionApplied);
4626             dest.writeBoolean(isSessionReady);
4627             dest.writeBoolean(isSessionFailed);
4628             dest.writeInt(mSessionErrorCode);
4629             dest.writeString(mSessionErrorMessage);
4630             dest.writeBoolean(isCommitted);
4631             dest.writeBoolean(isPreapprovalRequested);
4632             dest.writeInt(rollbackDataPolicy);
4633             dest.writeLong(rollbackLifetimeMillis);
4634             dest.writeInt(rollbackImpactLevel);
4635             dest.writeLong(createdMillis);
4636             dest.writeInt(requireUserAction);
4637             dest.writeInt(installerUid);
4638             dest.writeInt(packageSource);
4639             dest.writeBoolean(applicationEnabledSettingPersistent);
4640             dest.writeInt(pendingUserActionReason);
4641             dest.writeBoolean(isAutoInstallingDependenciesEnabled);
4642         }
4643 
4644         public static final Parcelable.Creator<SessionInfo>
4645                 CREATOR = new Parcelable.Creator<SessionInfo>() {
4646                     @Override
4647                     public SessionInfo createFromParcel(Parcel p) {
4648                         return new SessionInfo(p);
4649                     }
4650 
4651                     @Override
4652                     public SessionInfo[] newArray(int size) {
4653                         return new SessionInfo[size];
4654                     }
4655                 };
4656     }
4657 
4658     /**
4659      * Details for requesting the pre-commit install approval.
4660      */
4661     @DataClass(genConstructor = false, genToString = true)
4662     public static final class PreapprovalDetails implements Parcelable {
4663         /**
4664          * The icon representing the app to be installed.
4665          */
4666         private final @Nullable Bitmap mIcon;
4667         /**
4668          * The label representing the app to be installed.
4669          */
4670         private final @NonNull CharSequence mLabel;
4671         /**
4672          * The locale of the app label being used.
4673          */
4674         private final @NonNull ULocale mLocale;
4675         /**
4676          * The package name of the app to be installed.
4677          */
4678         private final @NonNull String mPackageName;
4679 
4680         /**
4681          * Creates a new PreapprovalDetails.
4682          *
4683          * @param icon
4684          *   The icon representing the app to be installed.
4685          * @param label
4686          *   The label representing the app to be installed.
4687          * @param locale
4688          *   The locale is used to get the app label from the APKs (includes the base APK and
4689          *   split APKs) related to the package to be installed.
4690          * @param packageName
4691          *   The package name of the app to be installed.
4692          * @hide
4693          */
PreapprovalDetails( @ullable Bitmap icon, @NonNull CharSequence label, @NonNull ULocale locale, @NonNull String packageName)4694         public PreapprovalDetails(
4695                 @Nullable Bitmap icon,
4696                 @NonNull CharSequence label,
4697                 @NonNull ULocale locale,
4698                 @NonNull String packageName) {
4699             mIcon = icon;
4700             mLabel = label;
4701             Preconditions.checkArgument(!TextUtils.isEmpty(mLabel),
4702                     "App label cannot be empty.");
4703             mLocale = locale;
4704             Preconditions.checkArgument(!Objects.isNull(mLocale),
4705                     "Locale cannot be null.");
4706             mPackageName = packageName;
4707             Preconditions.checkArgument(!TextUtils.isEmpty(mPackageName),
4708                     "Package name cannot be empty.");
4709         }
4710 
4711         @Override
writeToParcel(@onNull Parcel dest, int flags)4712         public void writeToParcel(@NonNull Parcel dest, int flags) {
4713             byte flg = 0;
4714             if (mIcon != null) flg |= 0x1;
4715             dest.writeByte(flg);
4716             if (mIcon != null) mIcon.writeToParcel(dest, flags);
4717             dest.writeCharSequence(mLabel);
4718             dest.writeString8(mLocale.toString());
4719             dest.writeString8(mPackageName);
4720         }
4721 
4722         @Override
describeContents()4723         public int describeContents() { return 0; }
4724 
4725         /** @hide */
PreapprovalDetails(@onNull Parcel in)4726         /* package-private */ PreapprovalDetails(@NonNull Parcel in) {
4727             byte flg = in.readByte();
4728             final Bitmap icon = (flg & 0x1) == 0 ? null : Bitmap.CREATOR.createFromParcel(in);
4729             final CharSequence label = in.readCharSequence();
4730             final ULocale locale = new ULocale(in.readString8());
4731             final String packageName = in.readString8();
4732 
4733             mIcon = icon;
4734             mLabel = label;
4735             Preconditions.checkArgument(!TextUtils.isEmpty(mLabel),
4736                     "App label cannot be empty.");
4737             mLocale = locale;
4738             Preconditions.checkArgument(!Objects.isNull(mLocale),
4739                     "Locale cannot be null.");
4740             mPackageName = packageName;
4741             Preconditions.checkArgument(!TextUtils.isEmpty(mPackageName),
4742                     "Package name cannot be empty.");
4743         }
4744 
4745         public static final @NonNull Parcelable.Creator<PreapprovalDetails> CREATOR
4746                 = new Parcelable.Creator<PreapprovalDetails>() {
4747             @Override
4748             public PreapprovalDetails[] newArray(int size) {
4749                 return new PreapprovalDetails[size];
4750             }
4751 
4752             @Override
4753             public PreapprovalDetails createFromParcel(@NonNull Parcel in) {
4754                 return new PreapprovalDetails(in);
4755             }
4756         };
4757 
4758         /**
4759          * A builder for {@link PreapprovalDetails}
4760          */
4761         public static final class Builder {
4762 
4763             private @Nullable Bitmap mIcon;
4764             private @NonNull CharSequence mLabel;
4765             private @NonNull ULocale mLocale;
4766             private @NonNull String mPackageName;
4767 
4768             private long mBuilderFieldsSet = 0L;
4769 
4770             /**
4771              * Creates a new Builder.
4772              */
Builder()4773             public Builder() {}
4774 
4775             /**
4776              * The icon representing the app to be installed.
4777              */
setIcon(@onNull Bitmap value)4778             public @NonNull Builder setIcon(@NonNull Bitmap value) {
4779                 checkNotUsed();
4780                 mBuilderFieldsSet |= 0x1;
4781                 mIcon = value;
4782                 return this;
4783             }
4784 
4785             /**
4786              * The label representing the app to be installed.
4787              */
setLabel(@onNull CharSequence value)4788             public @NonNull Builder setLabel(@NonNull CharSequence value) {
4789                 checkNotUsed();
4790                 mBuilderFieldsSet |= 0x2;
4791                 mLabel = value;
4792                 return this;
4793             }
4794 
4795             /**
4796              * The locale is used to get the app label from the APKs (includes the base APK and
4797              * split APKs) related to the package to be installed. The caller needs to make sure
4798              * the app label is consistent with the app label of {@link PreapprovalDetails} when
4799              * validating the installation. Otherwise, the pre-approval install session will fail.
4800              */
setLocale(@onNull ULocale value)4801             public @NonNull Builder setLocale(@NonNull ULocale value) {
4802                 checkNotUsed();
4803                 mBuilderFieldsSet |= 0x4;
4804                 mLocale = value;
4805                 return this;
4806             }
4807 
4808             /**
4809              * The package name of the app to be installed.
4810              */
setPackageName(@onNull String value)4811             public @NonNull Builder setPackageName(@NonNull String value) {
4812                 checkNotUsed();
4813                 mBuilderFieldsSet |= 0x8;
4814                 mPackageName = value;
4815                 return this;
4816             }
4817 
4818             /** Builds the instance. This builder should not be touched after calling this! */
build()4819             public @NonNull PreapprovalDetails build() {
4820                 checkNotUsed();
4821                 mBuilderFieldsSet |= 0x10; // Mark builder used
4822 
4823                 PreapprovalDetails o = new PreapprovalDetails(
4824                         mIcon,
4825                         mLabel,
4826                         mLocale,
4827                         mPackageName);
4828                 return o;
4829             }
4830 
checkNotUsed()4831             private void checkNotUsed() {
4832                 if ((mBuilderFieldsSet & 0x10) != 0) {
4833                     throw new IllegalStateException("This Builder should not be reused. "
4834                             + "Use a new Builder instance instead");
4835                 }
4836             }
4837         }
4838 
4839 
4840 
4841 
4842         // Code below generated by codegen v1.0.23.
4843         //
4844         // DO NOT MODIFY!
4845         // CHECKSTYLE:OFF Generated code
4846         //
4847         // To regenerate run:
4848         // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/PackageInstaller.java
4849         //
4850         // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
4851         //   Settings > Editor > Code Style > Formatter Control
4852         //@formatter:off
4853 
4854 
4855         /**
4856          * The icon representing the app to be installed.
4857          */
4858         @DataClass.Generated.Member
getIcon()4859         public @Nullable Bitmap getIcon() {
4860             return mIcon;
4861         }
4862 
4863         /**
4864          * The label representing the app to be installed.
4865          */
4866         @DataClass.Generated.Member
getLabel()4867         public @NonNull CharSequence getLabel() {
4868             return mLabel;
4869         }
4870 
4871         /**
4872          * The locale of the app label being used.
4873          */
4874         @DataClass.Generated.Member
getLocale()4875         public @NonNull ULocale getLocale() {
4876             return mLocale;
4877         }
4878 
4879         /**
4880          * The package name of the app to be installed.
4881          */
4882         @DataClass.Generated.Member
getPackageName()4883         public @NonNull String getPackageName() {
4884             return mPackageName;
4885         }
4886 
4887         @Override
4888         @DataClass.Generated.Member
toString()4889         public String toString() {
4890             // You can override field toString logic by defining methods like:
4891             // String fieldNameToString() { ... }
4892 
4893             return "PreapprovalDetails { " +
4894                     "icon = " + mIcon + ", " +
4895                     "label = " + mLabel + ", " +
4896                     "locale = " + mLocale + ", " +
4897                     "packageName = " + mPackageName +
4898             " }";
4899         }
4900 
4901         @DataClass.Generated(
4902                 time = 1676970504308L,
4903                 codegenVersion = "1.0.23",
4904                 sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
4905                 inputSignatures = "private final @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate final @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate final @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate final @android.annotation.NonNull java.lang.String mPackageName\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<android.content.pm.PackageInstaller.PreapprovalDetails> CREATOR\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\npublic @java.lang.Override int describeContents()\nclass PreapprovalDetails extends java.lang.Object implements [android.os.Parcelable]\nprivate @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate @android.annotation.NonNull java.lang.String mPackageName\nprivate  long mBuilderFieldsSet\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setIcon(android.graphics.Bitmap)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setLabel(java.lang.CharSequence)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setLocale(android.icu.util.ULocale)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setPackageName(java.lang.String)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails build()\nprivate  void checkNotUsed()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genToString=true)")
4906 
4907         @Deprecated
__metadata()4908         private void __metadata() {}
4909 
4910         //@formatter:on
4911         // End of generated code
4912 
4913     }
4914 
4915     /**
4916      * The callback result of {@link #checkInstallConstraints(List, InstallConstraints, Executor, Consumer)}.
4917      */
4918     @DataClass(genParcelable = true, genHiddenConstructor = true)
4919     @DataClass.Suppress("isAllConstraintsSatisfied")
4920     public static final class InstallConstraintsResult implements Parcelable {
4921         /**
4922          * True if all constraints are satisfied.
4923          */
4924         private boolean mAllConstraintsSatisfied;
4925 
4926         /**
4927          * True if all constraints are satisfied.
4928          */
areAllConstraintsSatisfied()4929         public boolean areAllConstraintsSatisfied() {
4930             return mAllConstraintsSatisfied;
4931         }
4932 
4933 
4934 
4935         // Code below generated by codegen v1.0.23.
4936         //
4937         // DO NOT MODIFY!
4938         // CHECKSTYLE:OFF Generated code
4939         //
4940         // To regenerate run:
4941         // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/PackageInstaller.java
4942         //
4943         // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
4944         //   Settings > Editor > Code Style > Formatter Control
4945         //@formatter:off
4946 
4947 
4948         /**
4949          * Creates a new InstallConstraintsResult.
4950          *
4951          * @param allConstraintsSatisfied
4952          *   True if all constraints are satisfied.
4953          * @hide
4954          */
4955         @DataClass.Generated.Member
InstallConstraintsResult( boolean allConstraintsSatisfied)4956         public InstallConstraintsResult(
4957                 boolean allConstraintsSatisfied) {
4958             this.mAllConstraintsSatisfied = allConstraintsSatisfied;
4959 
4960             // onConstructed(); // You can define this method to get a callback
4961         }
4962 
4963         @Override
4964         @DataClass.Generated.Member
writeToParcel(@onNull Parcel dest, int flags)4965         public void writeToParcel(@NonNull Parcel dest, int flags) {
4966             // You can override field parcelling by defining methods like:
4967             // void parcelFieldName(Parcel dest, int flags) { ... }
4968 
4969             byte flg = 0;
4970             if (mAllConstraintsSatisfied) flg |= 0x1;
4971             dest.writeByte(flg);
4972         }
4973 
4974         @Override
4975         @DataClass.Generated.Member
describeContents()4976         public int describeContents() { return 0; }
4977 
4978         /** @hide */
4979         @SuppressWarnings({"unchecked", "RedundantCast"})
4980         @DataClass.Generated.Member
InstallConstraintsResult(@onNull Parcel in)4981         /* package-private */ InstallConstraintsResult(@NonNull Parcel in) {
4982             // You can override field unparcelling by defining methods like:
4983             // static FieldType unparcelFieldName(Parcel in) { ... }
4984 
4985             byte flg = in.readByte();
4986             boolean allConstraintsSatisfied = (flg & 0x1) != 0;
4987 
4988             this.mAllConstraintsSatisfied = allConstraintsSatisfied;
4989 
4990             // onConstructed(); // You can define this method to get a callback
4991         }
4992 
4993         @DataClass.Generated.Member
4994         public static final @NonNull Parcelable.Creator<InstallConstraintsResult> CREATOR
4995                 = new Parcelable.Creator<InstallConstraintsResult>() {
4996             @Override
4997             public InstallConstraintsResult[] newArray(int size) {
4998                 return new InstallConstraintsResult[size];
4999             }
5000 
5001             @Override
5002             public InstallConstraintsResult createFromParcel(@NonNull Parcel in) {
5003                 return new InstallConstraintsResult(in);
5004             }
5005         };
5006 
5007         @DataClass.Generated(
5008                 time = 1676970504336L,
5009                 codegenVersion = "1.0.23",
5010                 sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
5011                 inputSignatures = "private  boolean mAllConstraintsSatisfied\npublic  boolean areAllConstraintsSatisfied()\nclass InstallConstraintsResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true)")
5012         @Deprecated
__metadata()5013         private void __metadata() {}
5014 
5015 
5016         //@formatter:on
5017         // End of generated code
5018 
5019     }
5020 
5021     /**
5022      * A class to encapsulate constraints for installation.
5023      *
5024      * When used with {@link #checkInstallConstraints(List, InstallConstraints, Executor, Consumer)}, it
5025      * specifies the conditions to check against for the packages in question. This can be used
5026      * by app stores to deliver auto updates without disrupting the user experience (referred as
5027      * gentle update) - for example, an app store might hold off updates when it find out the
5028      * app to update is interacting with the user.
5029      *
5030      * Use {@link Builder} to create a new instance and call mutator methods to add constraints.
5031      * If no mutators were called, default constraints will be generated which implies no
5032      * constraints. It is recommended to use preset constraints which are useful in most
5033      * cases.
5034      *
5035      * For the purpose of gentle update, it is recommended to always use {@link #GENTLE_UPDATE}
5036      * for the system knows best how to do it. It will also benefits the installer as the
5037      * platform evolves and add more constraints to improve the accuracy and efficiency of
5038      * gentle update.
5039      *
5040      * Note the constraints are applied transitively. If app Foo is used by app Bar (via shared
5041      * library or bounded service), the constraints will also be applied to Bar.
5042      */
5043     @DataClass(genParcelable = true, genHiddenConstructor = true, genEqualsHashCode=true)
5044     public static final class InstallConstraints implements Parcelable {
5045         /**
5046          * Preset constraints suitable for gentle update.
5047          */
5048         @NonNull
5049         public static final InstallConstraints GENTLE_UPDATE =
5050                 new Builder().setAppNotInteractingRequired().build();
5051 
5052         private final boolean mDeviceIdleRequired;
5053         private final boolean mAppNotForegroundRequired;
5054         private final boolean mAppNotInteractingRequired;
5055         private final boolean mAppNotTopVisibleRequired;
5056         private final boolean mNotInCallRequired;
5057 
5058         /**
5059          * Builder class for constructing {@link InstallConstraints}.
5060          */
5061         public static final class Builder {
5062             private boolean mDeviceIdleRequired;
5063             private boolean mAppNotForegroundRequired;
5064             private boolean mAppNotInteractingRequired;
5065             private boolean mAppNotTopVisibleRequired;
5066             private boolean mNotInCallRequired;
5067 
5068             /**
5069              * This constraint requires the device is idle.
5070              */
5071             @SuppressLint("MissingGetterMatchingBuilder")
5072             @NonNull
setDeviceIdleRequired()5073             public Builder setDeviceIdleRequired() {
5074                 mDeviceIdleRequired = true;
5075                 return this;
5076             }
5077 
5078             /**
5079              * This constraint requires the app in question is not in the foreground.
5080              */
5081             @SuppressLint("MissingGetterMatchingBuilder")
5082             @NonNull
setAppNotForegroundRequired()5083             public Builder setAppNotForegroundRequired() {
5084                 mAppNotForegroundRequired = true;
5085                 return this;
5086             }
5087 
5088             /**
5089              * This constraint requires the app in question is not interacting with the user.
5090              * User interaction includes:
5091              * <ul>
5092              *     <li>playing or recording audio/video</li>
5093              *     <li>sending or receiving network data</li>
5094              *     <li>being visible to the user</li>
5095              * </ul>
5096              */
5097             @SuppressLint("MissingGetterMatchingBuilder")
5098             @NonNull
setAppNotInteractingRequired()5099             public Builder setAppNotInteractingRequired() {
5100                 mAppNotInteractingRequired = true;
5101                 return this;
5102             }
5103 
5104             /**
5105              * This constraint requires the app in question is not top-visible to the user.
5106              * A top-visible app is showing UI at the top of the screen that the user is
5107              * interacting with.
5108              *
5109              * Note this constraint is a subset of {@link #setAppNotForegroundRequired()}
5110              * because a top-visible app is also a foreground app. This is also a subset
5111              * of {@link #setAppNotInteractingRequired()} because a top-visible app is interacting
5112              * with the user.
5113              *
5114              * @see ActivityManager.RunningAppProcessInfo#IMPORTANCE_FOREGROUND
5115              */
5116             @SuppressLint("MissingGetterMatchingBuilder")
5117             @NonNull
setAppNotTopVisibleRequired()5118             public Builder setAppNotTopVisibleRequired() {
5119                 mAppNotTopVisibleRequired = true;
5120                 return this;
5121             }
5122 
5123             /**
5124              * This constraint requires there is no ongoing call in the device.
5125              */
5126             @SuppressLint("MissingGetterMatchingBuilder")
5127             @NonNull
setNotInCallRequired()5128             public Builder setNotInCallRequired() {
5129                 mNotInCallRequired = true;
5130                 return this;
5131             }
5132 
5133             /**
5134              * Builds a new {@link InstallConstraints} instance.
5135              */
5136             @NonNull
build()5137             public InstallConstraints build() {
5138                 return new InstallConstraints(mDeviceIdleRequired, mAppNotForegroundRequired,
5139                         mAppNotInteractingRequired, mAppNotTopVisibleRequired, mNotInCallRequired);
5140             }
5141         }
5142 
5143 
5144 
5145         // Code below generated by codegen v1.0.23.
5146         //
5147         // DO NOT MODIFY!
5148         // CHECKSTYLE:OFF Generated code
5149         //
5150         // To regenerate run:
5151         // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/PackageInstaller.java
5152         //
5153         // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
5154         //   Settings > Editor > Code Style > Formatter Control
5155         //@formatter:off
5156 
5157 
5158         /**
5159          * Creates a new InstallConstraints.
5160          *
5161          * @hide
5162          */
5163         @DataClass.Generated.Member
InstallConstraints( boolean deviceIdleRequired, boolean appNotForegroundRequired, boolean appNotInteractingRequired, boolean appNotTopVisibleRequired, boolean notInCallRequired)5164         public InstallConstraints(
5165                 boolean deviceIdleRequired,
5166                 boolean appNotForegroundRequired,
5167                 boolean appNotInteractingRequired,
5168                 boolean appNotTopVisibleRequired,
5169                 boolean notInCallRequired) {
5170             this.mDeviceIdleRequired = deviceIdleRequired;
5171             this.mAppNotForegroundRequired = appNotForegroundRequired;
5172             this.mAppNotInteractingRequired = appNotInteractingRequired;
5173             this.mAppNotTopVisibleRequired = appNotTopVisibleRequired;
5174             this.mNotInCallRequired = notInCallRequired;
5175 
5176             // onConstructed(); // You can define this method to get a callback
5177         }
5178 
5179         @DataClass.Generated.Member
isDeviceIdleRequired()5180         public boolean isDeviceIdleRequired() {
5181             return mDeviceIdleRequired;
5182         }
5183 
5184         @DataClass.Generated.Member
isAppNotForegroundRequired()5185         public boolean isAppNotForegroundRequired() {
5186             return mAppNotForegroundRequired;
5187         }
5188 
5189         @DataClass.Generated.Member
isAppNotInteractingRequired()5190         public boolean isAppNotInteractingRequired() {
5191             return mAppNotInteractingRequired;
5192         }
5193 
5194         @DataClass.Generated.Member
isAppNotTopVisibleRequired()5195         public boolean isAppNotTopVisibleRequired() {
5196             return mAppNotTopVisibleRequired;
5197         }
5198 
5199         @DataClass.Generated.Member
isNotInCallRequired()5200         public boolean isNotInCallRequired() {
5201             return mNotInCallRequired;
5202         }
5203 
5204         @Override
5205         @DataClass.Generated.Member
equals(@ullable Object o)5206         public boolean equals(@Nullable Object o) {
5207             // You can override field equality logic by defining either of the methods like:
5208             // boolean fieldNameEquals(InstallConstraints other) { ... }
5209             // boolean fieldNameEquals(FieldType otherValue) { ... }
5210 
5211             if (this == o) return true;
5212             if (o == null || getClass() != o.getClass()) return false;
5213             @SuppressWarnings("unchecked")
5214             InstallConstraints that = (InstallConstraints) o;
5215             //noinspection PointlessBooleanExpression
5216             return true
5217                     && mDeviceIdleRequired == that.mDeviceIdleRequired
5218                     && mAppNotForegroundRequired == that.mAppNotForegroundRequired
5219                     && mAppNotInteractingRequired == that.mAppNotInteractingRequired
5220                     && mAppNotTopVisibleRequired == that.mAppNotTopVisibleRequired
5221                     && mNotInCallRequired == that.mNotInCallRequired;
5222         }
5223 
5224         @Override
5225         @DataClass.Generated.Member
hashCode()5226         public int hashCode() {
5227             // You can override field hashCode logic by defining methods like:
5228             // int fieldNameHashCode() { ... }
5229 
5230             int _hash = 1;
5231             _hash = 31 * _hash + Boolean.hashCode(mDeviceIdleRequired);
5232             _hash = 31 * _hash + Boolean.hashCode(mAppNotForegroundRequired);
5233             _hash = 31 * _hash + Boolean.hashCode(mAppNotInteractingRequired);
5234             _hash = 31 * _hash + Boolean.hashCode(mAppNotTopVisibleRequired);
5235             _hash = 31 * _hash + Boolean.hashCode(mNotInCallRequired);
5236             return _hash;
5237         }
5238 
5239         @Override
5240         @DataClass.Generated.Member
writeToParcel(@onNull Parcel dest, int flags)5241         public void writeToParcel(@NonNull Parcel dest, int flags) {
5242             // You can override field parcelling by defining methods like:
5243             // void parcelFieldName(Parcel dest, int flags) { ... }
5244 
5245             byte flg = 0;
5246             if (mDeviceIdleRequired) flg |= 0x1;
5247             if (mAppNotForegroundRequired) flg |= 0x2;
5248             if (mAppNotInteractingRequired) flg |= 0x4;
5249             if (mAppNotTopVisibleRequired) flg |= 0x8;
5250             if (mNotInCallRequired) flg |= 0x10;
5251             dest.writeByte(flg);
5252         }
5253 
5254         @Override
5255         @DataClass.Generated.Member
describeContents()5256         public int describeContents() { return 0; }
5257 
5258         /** @hide */
5259         @SuppressWarnings({"unchecked", "RedundantCast"})
5260         @DataClass.Generated.Member
InstallConstraints(@onNull Parcel in)5261         /* package-private */ InstallConstraints(@NonNull Parcel in) {
5262             // You can override field unparcelling by defining methods like:
5263             // static FieldType unparcelFieldName(Parcel in) { ... }
5264 
5265             byte flg = in.readByte();
5266             boolean deviceIdleRequired = (flg & 0x1) != 0;
5267             boolean appNotForegroundRequired = (flg & 0x2) != 0;
5268             boolean appNotInteractingRequired = (flg & 0x4) != 0;
5269             boolean appNotTopVisibleRequired = (flg & 0x8) != 0;
5270             boolean notInCallRequired = (flg & 0x10) != 0;
5271 
5272             this.mDeviceIdleRequired = deviceIdleRequired;
5273             this.mAppNotForegroundRequired = appNotForegroundRequired;
5274             this.mAppNotInteractingRequired = appNotInteractingRequired;
5275             this.mAppNotTopVisibleRequired = appNotTopVisibleRequired;
5276             this.mNotInCallRequired = notInCallRequired;
5277 
5278             // onConstructed(); // You can define this method to get a callback
5279         }
5280 
5281         @DataClass.Generated.Member
5282         public static final @NonNull Parcelable.Creator<InstallConstraints> CREATOR
5283                 = new Parcelable.Creator<InstallConstraints>() {
5284             @Override
5285             public InstallConstraints[] newArray(int size) {
5286                 return new InstallConstraints[size];
5287             }
5288 
5289             @Override
5290             public InstallConstraints createFromParcel(@NonNull Parcel in) {
5291                 return new InstallConstraints(in);
5292             }
5293         };
5294 
5295         @DataClass.Generated(
5296                 time = 1676970504352L,
5297                 codegenVersion = "1.0.23",
5298                 sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
5299                 inputSignatures = "public static final @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints GENTLE_UPDATE\nprivate final  boolean mDeviceIdleRequired\nprivate final  boolean mAppNotForegroundRequired\nprivate final  boolean mAppNotInteractingRequired\nprivate final  boolean mAppNotTopVisibleRequired\nprivate final  boolean mNotInCallRequired\nclass InstallConstraints extends java.lang.Object implements [android.os.Parcelable]\nprivate  boolean mDeviceIdleRequired\nprivate  boolean mAppNotForegroundRequired\nprivate  boolean mAppNotInteractingRequired\nprivate  boolean mAppNotTopVisibleRequired\nprivate  boolean mNotInCallRequired\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setDeviceIdleRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotForegroundRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotInteractingRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotTopVisibleRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setNotInCallRequired()\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints build()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true, genEqualsHashCode=true)")
5300 
5301         @Deprecated
__metadata()5302         private void __metadata() {}
5303 
5304         //@formatter:on
5305         // End of generated code
5306 
5307     }
5308 
5309     /**
5310      * Used to communicate the unarchival state in {@link #reportUnarchivalState}.
5311      */
5312     @FlaggedApi(Flags.FLAG_ARCHIVING)
5313     public static final class UnarchivalState {
5314 
5315         /**
5316          * The caller is able to facilitate the unarchival for the given {@code unarchiveId}.
5317          *
5318          * @param unarchiveId the ID provided by the system as part of the intent.action.UNARCHIVE
5319          *                    broadcast with EXTRA_UNARCHIVE_ID.
5320          */
5321         @NonNull
createOkState(int unarchiveId)5322         public static UnarchivalState createOkState(int unarchiveId) {
5323             return new UnarchivalState(unarchiveId, UNARCHIVAL_OK, /* requiredStorageBytes= */ -1,
5324                     /* userActionIntent= */ null);
5325         }
5326 
5327         /**
5328          * User action is required before commencing with the unarchival for the given
5329          * {@code unarchiveId}. E.g., this could be used if it's necessary for the user to sign-in
5330          * first.
5331          *
5332          * @param unarchiveId      the ID provided by the system as part of the
5333          *                         intent.action.UNARCHIVE
5334          *                         broadcast with EXTRA_UNARCHIVE_ID.
5335          * @param userActionIntent optional intent to start a follow up action required to
5336          *                         facilitate the unarchival flow (e.g. user needs to log in).
5337          */
5338         @NonNull
createUserActionRequiredState(int unarchiveId, @NonNull PendingIntent userActionIntent)5339         public static UnarchivalState createUserActionRequiredState(int unarchiveId,
5340                 @NonNull PendingIntent userActionIntent) {
5341             Objects.requireNonNull(userActionIntent);
5342             return new UnarchivalState(unarchiveId, UNARCHIVAL_ERROR_USER_ACTION_NEEDED,
5343                     /* requiredStorageBytes= */ -1, userActionIntent);
5344         }
5345 
5346         /**
5347          * There is not enough storage to start the unarchival for the given {@code unarchiveId}.
5348          *
5349          * @param unarchiveId          the ID provided by the system as part of the
5350          *                             intent.action.UNARCHIVE
5351          *                             broadcast with EXTRA_UNARCHIVE_ID.
5352          * @param requiredStorageBytes ff the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this
5353          *                             field should be set to specify how many additional bytes of
5354          *                             storage are required to unarchive the app.
5355          * @param userActionIntent     can optionally be set to provide a custom storage-clearing
5356          *                             action.
5357          */
5358         @NonNull
createInsufficientStorageState(int unarchiveId, long requiredStorageBytes, @Nullable PendingIntent userActionIntent)5359         public static UnarchivalState createInsufficientStorageState(int unarchiveId,
5360                 long requiredStorageBytes, @Nullable PendingIntent userActionIntent) {
5361             return new UnarchivalState(unarchiveId, UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE,
5362                     requiredStorageBytes, userActionIntent);
5363         }
5364 
5365         /**
5366          * The device has no data connectivity and unarchival cannot be started for the given
5367          * {@code unarchiveId}.
5368          *
5369          * @param unarchiveId the ID provided by the system as part of the intent.action.UNARCHIVE
5370          *                    broadcast with EXTRA_UNARCHIVE_ID.
5371          */
5372         @NonNull
createNoConnectivityState(int unarchiveId)5373         public static UnarchivalState createNoConnectivityState(int unarchiveId) {
5374             return new UnarchivalState(unarchiveId, UNARCHIVAL_ERROR_NO_CONNECTIVITY,
5375                     /* requiredStorageBytes= */ -1,/* userActionIntent= */ null);
5376         }
5377 
5378         /**
5379          * Generic error state for all cases that are not covered by other methods in this class.
5380          *
5381          * @param unarchiveId the ID provided by the system as part of the intent.action.UNARCHIVE
5382          *                    broadcast with EXTRA_UNARCHIVE_ID.
5383          */
5384         @NonNull
createGenericErrorState(int unarchiveId)5385         public static UnarchivalState createGenericErrorState(int unarchiveId) {
5386             return new UnarchivalState(unarchiveId, UNARCHIVAL_GENERIC_ERROR,
5387                     /* requiredStorageBytes= */ -1,/* userActionIntent= */ null);
5388         }
5389 
5390 
5391         /**
5392          * The ID provided by the system as part of the intent.action.UNARCHIVE broadcast with
5393          * EXTRA_UNARCHIVE_ID.
5394          */
5395         private final int mUnarchiveId;
5396 
5397         /** Used for the system to provide the user with necessary follow-up steps or errors. */
5398         @UnarchivalStatus
5399         private final int mStatus;
5400 
5401         /**
5402          * If the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this field should be set to specify
5403          * how many additional bytes of storage are required to unarchive the app.
5404          */
5405         private final long mRequiredStorageBytes;
5406 
5407         /**
5408          * Optional intent to start a follow up action required to facilitate the unarchival flow
5409          * (e.g., user needs to log in).
5410          */
5411         @Nullable
5412         private final PendingIntent mUserActionIntent;
5413 
5414         /**
5415          * Creates a new UnarchivalState.
5416          *
5417          * @param unarchiveId          The ID provided by the system as part of the
5418          *                             intent.action.UNARCHIVE broadcast with
5419          *                             EXTRA_UNARCHIVE_ID.
5420          * @param status               Used for the system to provide the user with necessary
5421          *                             follow-up steps or errors.
5422          * @param requiredStorageBytes If the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this
5423          *                             field should be set to specify
5424          *                             how many additional bytes of storage are required to
5425          *                             unarchive the app.
5426          * @param userActionIntent     Optional intent to start a follow up action required to
5427          *                             facilitate the unarchival flow
5428          *                             (e.g,. user needs to log in).
5429          * @hide
5430          */
UnarchivalState( int unarchiveId, @UnarchivalStatus int status, long requiredStorageBytes, @Nullable PendingIntent userActionIntent)5431         private UnarchivalState(
5432                 int unarchiveId,
5433                 @UnarchivalStatus int status,
5434                 long requiredStorageBytes,
5435                 @Nullable PendingIntent userActionIntent) {
5436             this.mUnarchiveId = unarchiveId;
5437             this.mStatus = status;
5438             com.android.internal.util.AnnotationValidations.validate(
5439                     UnarchivalStatus.class, null, mStatus);
5440             this.mRequiredStorageBytes = requiredStorageBytes;
5441             this.mUserActionIntent = userActionIntent;
5442         }
5443 
5444         /**
5445          * The ID provided by the system as part of the intent.action.UNARCHIVE broadcast with
5446          * EXTRA_UNARCHIVE_ID.
5447          *
5448          * @hide
5449          */
getUnarchiveId()5450         int getUnarchiveId() {
5451             return mUnarchiveId;
5452         }
5453 
5454         /**
5455          * Used for the system to provide the user with necessary follow-up steps or errors.
5456          *
5457          * @hide
5458          */
getStatus()5459         @UnarchivalStatus int getStatus() {
5460             return mStatus;
5461         }
5462 
5463         /**
5464          * If the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this field should be set to specify
5465          * how many additional bytes of storage are required to unarchive the app.
5466          *
5467          * @hide
5468          */
getRequiredStorageBytes()5469         long getRequiredStorageBytes() {
5470             return mRequiredStorageBytes;
5471         }
5472 
5473         /**
5474          * Optional intent to start a follow up action required to facilitate the unarchival flow
5475          * (e.g. user needs to log in).
5476          *
5477          * @hide
5478          */
getUserActionIntent()5479         @Nullable PendingIntent getUserActionIntent() {
5480             return mUserActionIntent;
5481         }
5482     }
5483 
5484 }
5485