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