blob: 7b4dd195ded93ab9022ef171ca3013ee7d5ff34c [file] [log] [blame]
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001/*
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
17package android.content.pm;
18
Svet Ganov67882122016-12-11 16:36:34 -080019import android.Manifest;
Dario Freni71eee5e2018-12-06 15:47:16 +000020import android.annotation.IntDef;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -070021import android.annotation.NonNull;
22import android.annotation.Nullable;
Svet Ganov7121e182015-07-13 22:38:12 -070023import android.annotation.RequiresPermission;
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -070024import android.annotation.SdkConstant;
25import android.annotation.SdkConstant.SdkConstantType;
Svet Ganov7121e182015-07-13 22:38:12 -070026import android.annotation.SystemApi;
Mathew Inwood5c0d3542018-08-14 13:54:31 +010027import android.annotation.UnsupportedAppUsage;
Jeff Sharkeya0907432014-08-15 10:23:11 -070028import android.app.ActivityManager;
Jeff Sharkeyda1247a2017-06-08 14:13:29 -060029import android.app.AppGlobals;
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -070030import android.content.Intent;
Jeff Sharkeya0907432014-08-15 10:23:11 -070031import android.content.IntentSender;
Todd Kennedycda831f2017-05-16 10:54:33 -070032import android.content.pm.PackageManager.DeleteFlags;
Bartosz Fabianowski40a00622017-04-18 14:39:23 +020033import android.content.pm.PackageManager.InstallReason;
Jeff Sharkeya0907432014-08-15 10:23:11 -070034import android.graphics.Bitmap;
35import android.net.Uri;
Mathew Inwood8c854f82018-09-14 12:35:36 +010036import android.os.Build;
Jeff Sharkey78cc3402014-05-22 10:52:49 -070037import android.os.FileBridge;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -070038import android.os.Handler;
Jon Miranda2b340a22019-01-25 14:03:49 -080039import android.os.HandlerExecutor;
Jeff Sharkeya0907432014-08-15 10:23:11 -070040import android.os.Parcel;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070041import android.os.ParcelFileDescriptor;
Jeff Sharkeya0907432014-08-15 10:23:11 -070042import android.os.Parcelable;
Philip P. Moltmann7460c592017-08-08 20:07:11 +000043import android.os.ParcelableException;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070044import android.os.RemoteException;
Jeff Sharkey02d4e342017-03-10 21:53:48 -070045import android.os.SystemProperties;
Jon Miranda2b340a22019-01-25 14:03:49 -080046import android.os.UserHandle;
Jeff Sharkey02d4e342017-03-10 21:53:48 -070047import android.system.ErrnoException;
48import android.system.Os;
Jeff Sharkeya1031142014-07-12 18:09:46 -070049import android.util.ExceptionUtils;
Jeff Sharkeya0907432014-08-15 10:23:11 -070050
51import com.android.internal.util.IndentingPrintWriter;
Svet Ganov67882122016-12-11 16:36:34 -080052import com.android.internal.util.Preconditions;
Jon Miranda2b340a22019-01-25 14:03:49 -080053import com.android.internal.util.function.pooled.PooledLambda;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070054
Jeff Sharkeyec55ef02014-07-08 11:28:00 -070055import java.io.Closeable;
Jeff Sharkeya1031142014-07-12 18:09:46 -070056import java.io.IOException;
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -070057import java.io.InputStream;
Jeff Sharkey78cc3402014-05-22 10:52:49 -070058import java.io.OutputStream;
Dario Freni71eee5e2018-12-06 15:47:16 +000059import java.lang.annotation.Retention;
60import java.lang.annotation.RetentionPolicy;
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -070061import java.security.MessageDigest;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -070062import java.util.ArrayList;
63import java.util.Iterator;
Jeff Sharkeybb580672014-07-10 12:10:25 -070064import java.util.List;
Jon Miranda2b340a22019-01-25 14:03:49 -080065import java.util.concurrent.Executor;
Jeff Sharkey78cc3402014-05-22 10:52:49 -070066
Jeff Sharkey6c833e02014-07-14 22:44:30 -070067/**
68 * Offers the ability to install, upgrade, and remove applications on the
69 * device. This includes support for apps packaged either as a single
70 * "monolithic" APK, or apps packaged as multiple "split" APKs.
71 * <p>
72 * An app is delivered for installation through a
73 * {@link PackageInstaller.Session}, which any app can create. Once the session
74 * is created, the installer can stream one or more APKs into place until it
75 * decides to either commit or destroy the session. Committing may require user
Rubin Xufd4a3b42018-12-05 16:03:27 +000076 * intervention to complete the installation, unless the caller falls into one of the
77 * following categories, in which case the installation will complete automatically.
78 * <ul>
79 * <li>the device owner
80 * <li>the affiliated profile owner
81 * <li>the device owner delegated app with
82 * {@link android.app.admin.DevicePolicyManager#DELEGATION_PACKAGE_INSTALLATION}
83 * </ul>
Jeff Sharkey6c833e02014-07-14 22:44:30 -070084 * <p>
85 * Sessions can install brand new apps, upgrade existing apps, or add new splits
Jeff Sharkeyda96e132014-07-15 14:54:09 -070086 * into an existing app.
Jeff Sharkey6c833e02014-07-14 22:44:30 -070087 * <p>
Jeff Sharkeyda96e132014-07-15 14:54:09 -070088 * Apps packaged as multiple split APKs always consist of a single "base" APK
Jeff Sharkey6c833e02014-07-14 22:44:30 -070089 * (with a {@code null} split name) and zero or more "split" APKs (with unique
90 * split names). Any subset of these APKs can be installed together, as long as
91 * the following constraints are met:
92 * <ul>
93 * <li>All APKs must have the exact same package name, version code, and signing
94 * certificates.
Jeff Sharkey6c833e02014-07-14 22:44:30 -070095 * <li>All APKs must have unique split names.
Jeff Sharkeyda96e132014-07-15 14:54:09 -070096 * <li>All installations must contain a single base APK.
Jeff Sharkey6c833e02014-07-14 22:44:30 -070097 * </ul>
Peter Visontayf702fd42017-11-17 14:00:47 +000098 * <p>
99 * The ApiDemos project contains examples of using this API:
100 * <code>ApiDemos/src/com/example/android/apis/content/InstallApk*.java</code>.
Ricky Waic5ea08b2018-09-05 20:55:11 +0100101 * <p>
102 * On Android Q or above, an app installed notification will be posted
103 * by system after a new app is installed.
104 * To customize installer's notification icon, you should declare the following in the manifest
105 * &lt;application> as follows: </p>
106 * <pre>
107 * &lt;meta-data android:name="com.android.packageinstaller.notification.smallIcon"
108 * android:resource="@drawable/installer_notification_icon"/>
109 * </pre>
110 * <pre>
111 * &lt;meta-data android:name="com.android.packageinstaller.notification.color"
112 * android:resource="@color/installer_notification_color"/>
113 * </pre>
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700114 */
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700115public class PackageInstaller {
Jeff Sharkeya0907432014-08-15 10:23:11 -0700116 private static final String TAG = "PackageInstaller";
117
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700118 /** {@hide} */
119 public static final boolean ENABLE_REVOCABLE_FD =
120 SystemProperties.getBoolean("fw.revocable_fd", false);
121
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700122 /**
123 * Activity Action: Show details about a particular install session. This
124 * may surface actions such as pause, resume, or cancel.
125 * <p>
126 * This should always be scoped to the installer package that owns the
Jeff Sharkeyde742312014-09-15 14:04:56 -0700127 * session. Clients should use {@link SessionInfo#createDetailsIntent()} to
Jeff Sharkeya0907432014-08-15 10:23:11 -0700128 * build this intent correctly.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700129 * <p>
130 * In some cases, a matching Activity may not exist, so ensure you safeguard
131 * against this.
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700132 * <p>
133 * The session to show details for is defined in {@link #EXTRA_SESSION_ID}.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700134 */
135 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
136 public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
137
Sunny Goyal6d7cb232017-01-30 10:43:18 -0800138 /**
139 * Broadcast Action: Explicit broadcast sent to the last known default launcher when a session
140 * for a new install is committed. For managed profile, this is sent to the default launcher
141 * of the primary profile.
142 * <p>
143 * The associated session is defined in {@link #EXTRA_SESSION} and the user for which this
144 * session was created in {@link Intent#EXTRA_USER}.
145 */
146 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
147 public static final String ACTION_SESSION_COMMITTED =
148 "android.content.pm.action.SESSION_COMMITTED";
149
Dario Frenie487ea22018-12-12 15:41:59 +0000150 /**
151 * Broadcast Action: Send information about a staged install session when its state is updated.
152 * <p>
153 * The associated session information is defined in {@link #EXTRA_SESSION}.
154 */
155 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
156 public static final String ACTION_SESSION_UPDATED =
157 "android.content.pm.action.SESSION_UPDATED";
158
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700159 /** {@hide} */
Philip P. Moltmanne8fe3cb2018-07-23 14:27:11 -0700160 public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL";
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700161
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700162 /**
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700163 * An integer session ID that an operation is working with.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700164 *
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700165 * @see Intent#getIntExtra(String, int)
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700166 */
167 public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
168
Jeff Sharkeya0907432014-08-15 10:23:11 -0700169 /**
Sunny Goyal6d7cb232017-01-30 10:43:18 -0800170 * {@link SessionInfo} that an operation is working with.
171 *
172 * @see Intent#getParcelableExtra(String)
173 */
174 public static final String EXTRA_SESSION = "android.content.pm.extra.SESSION";
175
176 /**
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700177 * Package name that an operation is working with.
Jeff Sharkeya0907432014-08-15 10:23:11 -0700178 *
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700179 * @see Intent#getStringExtra(String)
Jeff Sharkeya0907432014-08-15 10:23:11 -0700180 */
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700181 public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
182
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700183 /**
184 * Current status of an operation. Will be one of
185 * {@link #STATUS_PENDING_USER_ACTION}, {@link #STATUS_SUCCESS},
186 * {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED},
187 * {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT},
188 * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID}, or
189 * {@link #STATUS_FAILURE_STORAGE}.
190 * <p>
191 * More information about a status may be available through additional
192 * extras; see the individual status documentation for details.
193 *
194 * @see Intent#getIntExtra(String, int)
195 */
196 public static final String EXTRA_STATUS = "android.content.pm.extra.STATUS";
197
198 /**
199 * Detailed string representation of the status, including raw details that
200 * are useful for debugging.
201 *
202 * @see Intent#getStringExtra(String)
203 */
204 public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
205
206 /**
207 * Another package name relevant to a status. This is typically the package
208 * responsible for causing an operation failure.
209 *
210 * @see Intent#getStringExtra(String)
211 */
212 public static final String
213 EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
214
215 /**
216 * Storage path relevant to a status.
217 *
218 * @see Intent#getStringExtra(String)
219 */
220 public static final String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH";
221
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700222 /** {@hide} */
223 @Deprecated
Jeff Sharkeya0907432014-08-15 10:23:11 -0700224 public static final String EXTRA_PACKAGE_NAMES = "android.content.pm.extra.PACKAGE_NAMES";
225
226 /** {@hide} */
227 public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS";
228 /** {@hide} */
229 public static final String EXTRA_LEGACY_BUNDLE = "android.content.pm.extra.LEGACY_BUNDLE";
Jeff Sharkeyf0600952014-08-07 17:31:53 -0700230 /** {@hide} */
231 public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK";
232
Jeff Sharkeya0907432014-08-15 10:23:11 -0700233 /**
234 * User action is currently required to proceed. You can launch the intent
235 * activity described by {@link Intent#EXTRA_INTENT} to involve the user and
236 * continue.
237 * <p>
238 * You may choose to immediately launch the intent if the user is actively
239 * using your app. Otherwise, you should use a notification to guide the
240 * user back into your app before launching.
241 *
242 * @see Intent#getParcelableExtra(String)
243 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700244 public static final int STATUS_PENDING_USER_ACTION = -1;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700245
246 /**
247 * The operation succeeded.
248 */
249 public static final int STATUS_SUCCESS = 0;
250
251 /**
252 * The operation failed in a generic way. The system will always try to
253 * provide a more specific failure reason, but in some rare cases this may
254 * be delivered.
255 *
256 * @see #EXTRA_STATUS_MESSAGE
257 */
258 public static final int STATUS_FAILURE = 1;
259
260 /**
261 * The operation failed because it was blocked. For example, a device policy
262 * may be blocking the operation, a package verifier may have blocked the
263 * operation, or the app may be required for core system operation.
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700264 * <p>
265 * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
266 * specific package blocking the install.
Jeff Sharkeya0907432014-08-15 10:23:11 -0700267 *
268 * @see #EXTRA_STATUS_MESSAGE
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700269 * @see #EXTRA_OTHER_PACKAGE_NAME
Jeff Sharkeya0907432014-08-15 10:23:11 -0700270 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700271 public static final int STATUS_FAILURE_BLOCKED = 2;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700272
273 /**
274 * The operation failed because it was actively aborted. For example, the
275 * user actively declined requested permissions, or the session was
276 * abandoned.
277 *
278 * @see #EXTRA_STATUS_MESSAGE
279 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700280 public static final int STATUS_FAILURE_ABORTED = 3;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700281
282 /**
283 * The operation failed because one or more of the APKs was invalid. For
284 * example, they might be malformed, corrupt, incorrectly signed,
285 * mismatched, etc.
286 *
287 * @see #EXTRA_STATUS_MESSAGE
288 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700289 public static final int STATUS_FAILURE_INVALID = 4;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700290
291 /**
292 * The operation failed because it conflicts (or is inconsistent with) with
293 * another package already installed on the device. For example, an existing
294 * permission, incompatible certificates, etc. The user may be able to
295 * uninstall another app to fix the issue.
296 * <p>
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700297 * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700298 * specific package identified as the cause of the conflict.
Jeff Sharkeya0907432014-08-15 10:23:11 -0700299 *
300 * @see #EXTRA_STATUS_MESSAGE
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700301 * @see #EXTRA_OTHER_PACKAGE_NAME
Jeff Sharkeya0907432014-08-15 10:23:11 -0700302 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700303 public static final int STATUS_FAILURE_CONFLICT = 5;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700304
305 /**
306 * The operation failed because of storage issues. For example, the device
307 * may be running low on space, or external media may be unavailable. The
308 * user may be able to help free space or insert different external media.
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700309 * <p>
310 * The result may also contain {@link #EXTRA_STORAGE_PATH} with the path to
311 * the storage device that caused the failure.
Jeff Sharkeya0907432014-08-15 10:23:11 -0700312 *
313 * @see #EXTRA_STATUS_MESSAGE
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700314 * @see #EXTRA_STORAGE_PATH
Jeff Sharkeya0907432014-08-15 10:23:11 -0700315 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700316 public static final int STATUS_FAILURE_STORAGE = 6;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700317
318 /**
319 * The operation failed because it is fundamentally incompatible with this
320 * device. For example, the app may require a hardware feature that doesn't
321 * exist, it may be missing native code for the ABIs supported by the
322 * device, or it requires a newer SDK version, etc.
323 *
324 * @see #EXTRA_STATUS_MESSAGE
325 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700326 public static final int STATUS_FAILURE_INCOMPATIBLE = 7;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700327
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700328 private final IPackageInstaller mInstaller;
329 private final int mUserId;
330 private final String mInstallerPackageName;
331
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700332 private final ArrayList<SessionCallbackDelegate> mDelegates = new ArrayList<>();
333
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700334 /** {@hide} */
Svet Ganov67882122016-12-11 16:36:34 -0800335 public PackageInstaller(IPackageInstaller installer,
Jeff Sharkeyec55ef02014-07-08 11:28:00 -0700336 String installerPackageName, int userId) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700337 mInstaller = installer;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700338 mInstallerPackageName = installerPackageName;
Jeff Sharkeyec55ef02014-07-08 11:28:00 -0700339 mUserId = userId;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700340 }
341
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700342 /**
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700343 * Create a new session using the given parameters, returning a unique ID
344 * that represents the session. Once created, the session can be opened
345 * multiple times across multiple device boots.
346 * <p>
347 * The system may automatically destroy sessions that have not been
348 * finalized (either committed or abandoned) within a reasonable period of
349 * time, typically on the order of a day.
350 *
351 * @throws IOException if parameters were unsatisfiable, such as lack of
352 * disk space or unavailable media.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700353 * @throws SecurityException when installation services are unavailable,
354 * such as when called from a restricted user.
355 * @throws IllegalArgumentException when {@link SessionParams} is invalid.
Jeff Sharkeyf174c6e2014-08-05 10:42:27 -0700356 * @return positive, non-zero unique ID that represents the created session.
357 * This ID remains consistent across device reboots until the
358 * session is finalized. IDs are not reused during a given boot.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700359 */
Jeff Sharkeya0907432014-08-15 10:23:11 -0700360 public int createSession(@NonNull SessionParams params) throws IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700361 try {
Philip P. Moltmann79c238a2017-12-13 15:59:07 -0800362 final String installerPackage;
363 if (params.installerPackageName == null) {
364 installerPackage = mInstallerPackageName;
365 } else {
366 installerPackage = params.installerPackageName;
367 }
368
369 return mInstaller.createSession(params, installerPackage, mUserId);
Jeff Sharkeya1031142014-07-12 18:09:46 -0700370 } catch (RuntimeException e) {
371 ExceptionUtils.maybeUnwrapIOException(e);
372 throw e;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700373 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700374 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700375 }
376 }
377
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700378 /**
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700379 * Open an existing session to actively perform work. To succeed, the caller
380 * must be the owner of the install session.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700381 *
382 * @throws IOException if parameters were unsatisfiable, such as lack of
383 * disk space or unavailable media.
384 * @throws SecurityException when the caller does not own the session, or
385 * the session is invalid.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700386 */
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700387 public @NonNull Session openSession(int sessionId) throws IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700388 try {
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000389 try {
390 return new Session(mInstaller.openSession(sessionId));
391 } catch (RemoteException e) {
392 throw e.rethrowFromSystemServer();
393 }
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700394 } catch (RuntimeException e) {
395 ExceptionUtils.maybeUnwrapIOException(e);
396 throw e;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700397 }
398 }
399
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700400 /**
401 * Update the icon representing the app being installed in a specific
402 * session. This should be roughly
403 * {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700404 *
405 * @throws SecurityException when the caller does not own the session, or
406 * the session is invalid.
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700407 */
408 public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) {
409 try {
410 mInstaller.updateSessionAppIcon(sessionId, appIcon);
411 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700412 throw e.rethrowFromSystemServer();
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700413 }
414 }
415
416 /**
417 * Update the label representing the app being installed in a specific
418 * session.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700419 *
420 * @throws SecurityException when the caller does not own the session, or
421 * the session is invalid.
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700422 */
423 public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) {
424 try {
425 final String val = (appLabel != null) ? appLabel.toString() : null;
426 mInstaller.updateSessionAppLabel(sessionId, val);
427 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700428 throw e.rethrowFromSystemServer();
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700429 }
430 }
431
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700432 /**
433 * Completely abandon the given session, destroying all staged data and
434 * rendering it invalid. Abandoned sessions will be reported to
435 * {@link SessionCallback} listeners as failures. This is equivalent to
436 * opening the session and calling {@link Session#abandon()}.
437 *
438 * @throws SecurityException when the caller does not own the session, or
439 * the session is invalid.
440 */
Jeff Sharkey381d94b2014-08-24 14:45:56 -0700441 public void abandonSession(int sessionId) {
442 try {
443 mInstaller.abandonSession(sessionId);
444 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700445 throw e.rethrowFromSystemServer();
Jeff Sharkey381d94b2014-08-24 14:45:56 -0700446 }
447 }
448
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700449 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700450 * Return details for a specific session. No special permissions are
451 * required to retrieve these details.
452 *
453 * @return details for the requested session, or {@code null} if the session
454 * does not exist.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700455 */
Jeff Sharkeya0907432014-08-15 10:23:11 -0700456 public @Nullable SessionInfo getSessionInfo(int sessionId) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700457 try {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700458 return mInstaller.getSessionInfo(sessionId);
459 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700460 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700461 }
462 }
463
464 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700465 * Return list of all known install sessions, regardless of the installer.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700466 */
Jeff Sharkeya0907432014-08-15 10:23:11 -0700467 public @NonNull List<SessionInfo> getAllSessions() {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700468 try {
Jeff Sharkey97d47ed2014-10-15 09:19:47 -0700469 return mInstaller.getAllSessions(mUserId).getList();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700470 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700471 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700472 }
473 }
474
475 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700476 * Return list of all known install sessions owned by the calling app.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700477 */
Jeff Sharkeya0907432014-08-15 10:23:11 -0700478 public @NonNull List<SessionInfo> getMySessions() {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700479 try {
Jeff Sharkey97d47ed2014-10-15 09:19:47 -0700480 return mInstaller.getMySessions(mInstallerPackageName, mUserId).getList();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700481 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700482 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700483 }
484 }
485
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700486 /**
Dario Freniaac4ba42018-12-06 15:47:16 +0000487 * Return list of all staged install sessions.
488 */
489 public @NonNull List<SessionInfo> getStagedSessions() {
490 try {
491 // TODO: limit this to the mUserId?
492 return mInstaller.getStagedSessions().getList();
493 } catch (RemoteException e) {
494 throw e.rethrowFromSystemServer();
495 }
496 }
497
498 /**
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700499 * Uninstall the given package, removing it completely from the device. This
Tony Mak366ee622018-02-12 17:52:34 +0000500 * method is available to:
501 * <ul>
502 * <li>the current "installer of record" for the package
503 * <li>the device owner
504 * <li>the affiliated profile owner
Rubin Xufd4a3b42018-12-05 16:03:27 +0000505 * <li>the device owner delegated app with
506 * {@link android.app.admin.DevicePolicyManager#DELEGATION_PACKAGE_INSTALLATION}
Tony Mak366ee622018-02-12 17:52:34 +0000507 * </ul>
Svet Ganov67882122016-12-11 16:36:34 -0800508 *
509 * @param packageName The package to uninstall.
510 * @param statusReceiver Where to deliver the result.
Tony Mak366ee622018-02-12 17:52:34 +0000511 *
512 * @see android.app.admin.DevicePolicyManager
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700513 */
Philip P. Moltmannd9bb39a2017-09-05 12:41:15 -0700514 @RequiresPermission(anyOf = {
515 Manifest.permission.DELETE_PACKAGES,
516 Manifest.permission.REQUEST_DELETE_PACKAGES})
Jeff Sharkeya0907432014-08-15 10:23:11 -0700517 public void uninstall(@NonNull String packageName, @NonNull IntentSender statusReceiver) {
Todd Kennedycda831f2017-05-16 10:54:33 -0700518 uninstall(packageName, 0 /*flags*/, statusReceiver);
519 }
520
521 /**
522 * Uninstall the given package, removing it completely from the device. This
523 * method is only available to the current "installer of record" for the
524 * package.
525 *
526 * @param packageName The package to uninstall.
527 * @param flags Flags for uninstall.
528 * @param statusReceiver Where to deliver the result.
529 *
530 * @hide
531 */
532 public void uninstall(@NonNull String packageName, @DeleteFlags int flags,
533 @NonNull IntentSender statusReceiver) {
534 uninstall(new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
535 flags, statusReceiver);
Svet Ganov67882122016-12-11 16:36:34 -0800536 }
537
538 /**
539 * Uninstall the given package with a specific version code, removing it
Tony Mak366ee622018-02-12 17:52:34 +0000540 * completely from the device. If the version code of the package
Svet Ganov67882122016-12-11 16:36:34 -0800541 * does not match the one passed in the versioned package argument this
542 * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to
543 * uninstall the latest version of the package.
Tony Mak366ee622018-02-12 17:52:34 +0000544 * <p>
545 * This method is available to:
546 * <ul>
547 * <li>the current "installer of record" for the package
548 * <li>the device owner
549 * <li>the affiliated profile owner
550 * </ul>
Svet Ganov67882122016-12-11 16:36:34 -0800551 *
552 * @param versionedPackage The versioned package to uninstall.
553 * @param statusReceiver Where to deliver the result.
Tony Mak366ee622018-02-12 17:52:34 +0000554 *
555 * @see android.app.admin.DevicePolicyManager
Svet Ganov67882122016-12-11 16:36:34 -0800556 */
Philip P. Moltmannd9bb39a2017-09-05 12:41:15 -0700557 @RequiresPermission(anyOf = {
558 Manifest.permission.DELETE_PACKAGES,
559 Manifest.permission.REQUEST_DELETE_PACKAGES})
Todd Kennedycda831f2017-05-16 10:54:33 -0700560 public void uninstall(@NonNull VersionedPackage versionedPackage,
561 @NonNull IntentSender statusReceiver) {
562 uninstall(versionedPackage, 0 /*flags*/, statusReceiver);
563 }
564
565 /**
566 * Uninstall the given package with a specific version code, removing it
567 * completely from the device. This method is only available to the current
568 * "installer of record" for the package. If the version code of the package
569 * does not match the one passed in the versioned package argument this
570 * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to
571 * uninstall the latest version of the package.
572 *
573 * @param versionedPackage The versioned package to uninstall.
574 * @param flags Flags for uninstall.
575 * @param statusReceiver Where to deliver the result.
576 *
577 * @hide
578 */
Svet Ganov67882122016-12-11 16:36:34 -0800579 @RequiresPermission(anyOf = {
580 Manifest.permission.DELETE_PACKAGES,
581 Manifest.permission.REQUEST_DELETE_PACKAGES})
Todd Kennedycda831f2017-05-16 10:54:33 -0700582 public void uninstall(@NonNull VersionedPackage versionedPackage, @DeleteFlags int flags,
Svet Ganov67882122016-12-11 16:36:34 -0800583 @NonNull IntentSender statusReceiver) {
584 Preconditions.checkNotNull(versionedPackage, "versionedPackage cannot be null");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700585 try {
Svet Ganov67882122016-12-11 16:36:34 -0800586 mInstaller.uninstall(versionedPackage, mInstallerPackageName,
Todd Kennedycda831f2017-05-16 10:54:33 -0700587 flags, statusReceiver, mUserId);
Jeff Sharkeybb580672014-07-10 12:10:25 -0700588 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700589 throw e.rethrowFromSystemServer();
Jeff Sharkeybb580672014-07-10 12:10:25 -0700590 }
591 }
592
Chandan Nathe8e463b2019-01-28 15:23:38 +0000593 /**
594 * Install the given package, which already exists on the device, for the user for which this
595 * installer was created.
596 *
597 * @param packageName The package to install.
598 * @param installReason Reason for install.
599 * @param statusReceiver Where to deliver the result.
600 */
601 @RequiresPermission(allOf = {
602 Manifest.permission.INSTALL_PACKAGES,
603 Manifest.permission.INSTALL_EXISTING_PACKAGES})
604 public void installExistingPackage(@NonNull String packageName,
605 @InstallReason int installReason,
606 @Nullable IntentSender statusReceiver) {
607 Preconditions.checkNotNull(packageName, "packageName cannot be null");
608 try {
609 mInstaller.installExistingPackage(packageName, 0, installReason, statusReceiver,
610 mUserId);
611 } catch (RemoteException e) {
612 throw e.rethrowFromSystemServer();
613 }
614 }
615
616
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700617 /** {@hide} */
Todd Kennedy04cc1912017-03-03 13:05:12 -0800618 @SystemApi
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600619 @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700620 public void setPermissionsResult(int sessionId, boolean accepted) {
621 try {
622 mInstaller.setPermissionsResult(sessionId, accepted);
623 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700624 throw e.rethrowFromSystemServer();
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700625 }
626 }
627
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700628 /**
629 * Events for observing session lifecycle.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700630 * <p>
631 * A typical session lifecycle looks like this:
632 * <ul>
633 * <li>An installer creates a session to indicate pending app delivery. All
634 * install details are available at this point.
635 * <li>The installer opens the session to deliver APK data. Note that a
636 * session may be opened and closed multiple times as network connectivity
637 * changes. The installer may deliver periodic progress updates.
638 * <li>The installer commits or abandons the session, resulting in the
639 * session being finished.
640 * </ul>
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700641 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700642 public static abstract class SessionCallback {
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700643 /**
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700644 * New session has been created. Details about the session can be
645 * obtained from {@link PackageInstaller#getSessionInfo(int)}.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700646 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700647 public abstract void onCreated(int sessionId);
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700648
649 /**
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700650 * Badging details for an existing session has changed. For example, the
651 * app icon or label has been updated.
652 */
653 public abstract void onBadgingChanged(int sessionId);
654
655 /**
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700656 * Active state for session has been changed.
657 * <p>
658 * A session is considered active whenever there is ongoing forward
659 * progress being made, such as the installer holding an open
660 * {@link Session} instance while streaming data into place, or the
661 * system optimizing code as the result of
662 * {@link Session#commit(IntentSender)}.
663 * <p>
664 * If the installer closes the {@link Session} without committing, the
665 * session is considered inactive until the installer opens the session
666 * again.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700667 */
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700668 public abstract void onActiveChanged(int sessionId, boolean active);
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700669
670 /**
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700671 * Progress for given session has been updated.
672 * <p>
673 * Note that this progress may not directly correspond to the value
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700674 * reported by
675 * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
676 * system may carve out a portion of the overall progress to represent
677 * its own internal installation work.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700678 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700679 public abstract void onProgressChanged(int sessionId, float progress);
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700680
681 /**
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700682 * Session has completely finished, either with success or failure.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700683 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700684 public abstract void onFinished(int sessionId, boolean success);
Jeff Sharkeybb580672014-07-10 12:10:25 -0700685 }
686
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700687 /** {@hide} */
Jon Miranda2b340a22019-01-25 14:03:49 -0800688 static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700689 private static final int MSG_SESSION_CREATED = 1;
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700690 private static final int MSG_SESSION_BADGING_CHANGED = 2;
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700691 private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700692 private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700693 private static final int MSG_SESSION_FINISHED = 5;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700694
695 final SessionCallback mCallback;
Jon Miranda2b340a22019-01-25 14:03:49 -0800696 final Executor mExecutor;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700697
Jon Miranda2b340a22019-01-25 14:03:49 -0800698 SessionCallbackDelegate(SessionCallback callback, Executor executor) {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700699 mCallback = callback;
Jon Miranda2b340a22019-01-25 14:03:49 -0800700 mExecutor = executor;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700701 }
702
703 @Override
704 public void onSessionCreated(int sessionId) {
Jon Miranda2b340a22019-01-25 14:03:49 -0800705 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onCreated, mCallback,
706 sessionId).recycleOnUse());
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700707 }
708
709 @Override
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700710 public void onSessionBadgingChanged(int sessionId) {
Jon Miranda2b340a22019-01-25 14:03:49 -0800711 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onBadgingChanged,
712 mCallback, sessionId).recycleOnUse());
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700713 }
714
715 @Override
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700716 public void onSessionActiveChanged(int sessionId, boolean active) {
Jon Miranda2b340a22019-01-25 14:03:49 -0800717 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onActiveChanged,
718 mCallback, sessionId, active).recycleOnUse());
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700719 }
720
721 @Override
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700722 public void onSessionProgressChanged(int sessionId, float progress) {
Jon Miranda2b340a22019-01-25 14:03:49 -0800723 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onProgressChanged,
724 mCallback, sessionId, progress).recycleOnUse());
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700725 }
726
727 @Override
728 public void onSessionFinished(int sessionId, boolean success) {
Jon Miranda2b340a22019-01-25 14:03:49 -0800729 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onFinished,
730 mCallback, sessionId, success).recycleOnUse());
Jeff Sharkeybb580672014-07-10 12:10:25 -0700731 }
732 }
733
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700734 /** {@hide} */
735 @Deprecated
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700736 public void addSessionCallback(@NonNull SessionCallback callback) {
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700737 registerSessionCallback(callback);
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700738 }
739
740 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700741 * Register to watch for session lifecycle events. No special permissions
742 * are required to watch for these events.
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700743 */
744 public void registerSessionCallback(@NonNull SessionCallback callback) {
745 registerSessionCallback(callback, new Handler());
746 }
747
748 /** {@hide} */
749 @Deprecated
750 public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
751 registerSessionCallback(callback, handler);
752 }
753
754 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700755 * Register to watch for session lifecycle events. No special permissions
756 * are required to watch for these events.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700757 *
758 * @param handler to dispatch callback events through, otherwise uses
759 * calling thread.
760 */
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700761 public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700762 synchronized (mDelegates) {
763 final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
Jon Miranda2b340a22019-01-25 14:03:49 -0800764 new HandlerExecutor(handler));
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700765 try {
766 mInstaller.registerCallback(delegate, mUserId);
767 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700768 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700769 }
770 mDelegates.add(delegate);
771 }
772 }
773
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700774 /** {@hide} */
775 @Deprecated
776 public void removeSessionCallback(@NonNull SessionCallback callback) {
777 unregisterSessionCallback(callback);
778 }
779
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700780 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700781 * Unregister a previously registered callback.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700782 */
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700783 public void unregisterSessionCallback(@NonNull SessionCallback callback) {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700784 synchronized (mDelegates) {
785 for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
786 final SessionCallbackDelegate delegate = i.next();
787 if (delegate.mCallback == callback) {
788 try {
789 mInstaller.unregisterCallback(delegate);
790 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700791 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700792 }
793 i.remove();
794 }
795 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700796 }
797 }
798
799 /**
800 * An installation that is being actively staged. For an install to succeed,
801 * all existing and new packages must have identical package names, version
802 * codes, and signing certificates.
803 * <p>
804 * A session may contain any number of split packages. If the application
805 * does not yet exist, this session must include a base package.
806 * <p>
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700807 * If an APK included in this session is already defined by the existing
808 * installation (for example, the same split name), the APK in this session
809 * will replace the existing APK.
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000810 * <p>
811 * In such a case that multiple packages need to be commited simultaneously,
812 * multiple sessions can be referenced by a single multi-package session.
813 * This session is created with no package name and calling
814 * {@link SessionParams#setMultiPackage()} with {@code true}. The
815 * individual session IDs can be added with {@link #addChildSessionId(int)}
816 * and commit of the multi-package session will result in all child sessions
817 * being committed atomically.
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700818 */
Jeff Sharkeyec55ef02014-07-08 11:28:00 -0700819 public static class Session implements Closeable {
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000820 /** {@hide} */
821 protected final IPackageInstallerSession mSession;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700822
823 /** {@hide} */
824 public Session(IPackageInstallerSession session) {
825 mSession = session;
826 }
827
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700828 /** {@hide} */
829 @Deprecated
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700830 public void setProgress(float progress) {
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700831 setStagingProgress(progress);
832 }
833
834 /**
835 * Set current progress of staging this session. Valid values are
836 * anywhere between 0 and 1.
837 * <p>
838 * Note that this progress may not directly correspond to the value
839 * reported by {@link SessionCallback#onProgressChanged(int, float)}, as
840 * the system may carve out a portion of the overall progress to
841 * represent its own internal installation work.
842 */
843 public void setStagingProgress(float progress) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700844 try {
Jeff Sharkeya1031142014-07-12 18:09:46 -0700845 mSession.setClientProgress(progress);
846 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700847 throw e.rethrowFromSystemServer();
Jeff Sharkeya1031142014-07-12 18:09:46 -0700848 }
849 }
850
851 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100852 @UnsupportedAppUsage
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700853 public void addProgress(float progress) {
Jeff Sharkeya1031142014-07-12 18:09:46 -0700854 try {
855 mSession.addClientProgress(progress);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700856 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700857 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700858 }
859 }
860
Jeff Sharkey78cc3402014-05-22 10:52:49 -0700861 /**
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700862 * Open a stream to write an APK file into the session.
863 * <p>
864 * The returned stream will start writing data at the requested offset
865 * in the underlying file, which can be used to resume a partially
866 * written file. If a valid file length is specified, the system will
867 * preallocate the underlying disk space to optimize placement on disk.
868 * It's strongly recommended to provide a valid file length when known.
869 * <p>
870 * You can write data into the returned stream, optionally call
871 * {@link #fsync(OutputStream)} as needed to ensure bytes have been
872 * persisted to disk, and then close when finished. All streams must be
Jeff Sharkeya0907432014-08-15 10:23:11 -0700873 * closed before calling {@link #commit(IntentSender)}.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700874 *
875 * @param name arbitrary, unique name of your choosing to identify the
876 * APK being written. You can open a file again for
877 * additional writes (such as after a reboot) by using the
878 * same name. This name is only meaningful within the context
879 * of a single install session.
880 * @param offsetBytes offset into the file to begin writing at, or 0 to
881 * start at the beginning of the file.
882 * @param lengthBytes total size of the file being written, used to
883 * preallocate the underlying disk space, or -1 if unknown.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700884 * The system may clear various caches as needed to allocate
885 * this space.
886 * @throws IOException if trouble opening the file for writing, such as
887 * lack of disk space or unavailable media.
888 * @throws SecurityException if called after the session has been
Philip P. Moltmann7460c592017-08-08 20:07:11 +0000889 * sealed or abandoned
Jeff Sharkey78cc3402014-05-22 10:52:49 -0700890 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700891 public @NonNull OutputStream openWrite(@NonNull String name, long offsetBytes,
892 long lengthBytes) throws IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700893 try {
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700894 if (ENABLE_REVOCABLE_FD) {
895 return new ParcelFileDescriptor.AutoCloseOutputStream(
896 mSession.openWrite(name, offsetBytes, lengthBytes));
897 } else {
898 final ParcelFileDescriptor clientSocket = mSession.openWrite(name,
899 offsetBytes, lengthBytes);
900 return new FileBridge.FileBridgeOutputStream(clientSocket);
901 }
Jeff Sharkeya1031142014-07-12 18:09:46 -0700902 } catch (RuntimeException e) {
903 ExceptionUtils.maybeUnwrapIOException(e);
904 throw e;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700905 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700906 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700907 }
Jeff Sharkey0451de62018-02-02 11:27:21 -0700908 }
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700909
Jeff Sharkey0451de62018-02-02 11:27:21 -0700910 /** {@hide} */
911 public void write(@NonNull String name, long offsetBytes, long lengthBytes,
912 @NonNull ParcelFileDescriptor fd) throws IOException {
913 try {
914 mSession.write(name, offsetBytes, lengthBytes, fd);
915 } catch (RuntimeException e) {
916 ExceptionUtils.maybeUnwrapIOException(e);
917 throw e;
918 } catch (RemoteException e) {
919 throw e.rethrowFromSystemServer();
920 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700921 }
922
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700923 /**
924 * Ensure that any outstanding data for given stream has been committed
925 * to disk. This is only valid for streams returned from
926 * {@link #openWrite(String, long, long)}.
927 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700928 public void fsync(@NonNull OutputStream out) throws IOException {
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700929 if (ENABLE_REVOCABLE_FD) {
930 if (out instanceof ParcelFileDescriptor.AutoCloseOutputStream) {
931 try {
932 Os.fsync(((ParcelFileDescriptor.AutoCloseOutputStream) out).getFD());
933 } catch (ErrnoException e) {
934 throw e.rethrowAsIOException();
935 }
936 } else {
937 throw new IllegalArgumentException("Unrecognized stream");
938 }
Jeff Sharkeya1031142014-07-12 18:09:46 -0700939 } else {
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700940 if (out instanceof FileBridge.FileBridgeOutputStream) {
941 ((FileBridge.FileBridgeOutputStream) out).fsync();
942 } else {
943 throw new IllegalArgumentException("Unrecognized stream");
944 }
Jeff Sharkeya1031142014-07-12 18:09:46 -0700945 }
946 }
947
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700948 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -0700949 * Return all APK names contained in this session.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700950 * <p>
951 * This returns all names which have been previously written through
952 * {@link #openWrite(String, long, long)} as part of this session.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700953 *
954 * @throws SecurityException if called after the session has been
955 * committed or abandoned.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700956 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700957 public @NonNull String[] getNames() throws IOException {
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700958 try {
Jeff Sharkeya0907432014-08-15 10:23:11 -0700959 return mSession.getNames();
Jeff Sharkey742e7902014-08-16 19:09:13 -0700960 } catch (RuntimeException e) {
961 ExceptionUtils.maybeUnwrapIOException(e);
962 throw e;
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700963 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700964 throw e.rethrowFromSystemServer();
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700965 }
966 }
967
968 /**
969 * Open a stream to read an APK file from the session.
970 * <p>
971 * This is only valid for names which have been previously written
972 * through {@link #openWrite(String, long, long)} as part of this
973 * session. For example, this stream may be used to calculate a
974 * {@link MessageDigest} of a written APK before committing.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700975 *
976 * @throws SecurityException if called after the session has been
977 * committed or abandoned.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700978 */
979 public @NonNull InputStream openRead(@NonNull String name) throws IOException {
980 try {
981 final ParcelFileDescriptor pfd = mSession.openRead(name);
982 return new ParcelFileDescriptor.AutoCloseInputStream(pfd);
983 } catch (RuntimeException e) {
984 ExceptionUtils.maybeUnwrapIOException(e);
985 throw e;
986 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700987 throw e.rethrowFromSystemServer();
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700988 }
989 }
990
991 /**
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800992 * Removes a split.
993 * <p>
994 * Split removals occur prior to adding new APKs. If upgrading a feature
995 * split, it is not expected nor desirable to remove the split prior to
996 * upgrading.
997 * <p>
998 * When split removal is bundled with new APKs, the packageName must be
999 * identical.
1000 */
1001 public void removeSplit(@NonNull String splitName) throws IOException {
1002 try {
1003 mSession.removeSplit(splitName);
1004 } catch (RuntimeException e) {
1005 ExceptionUtils.maybeUnwrapIOException(e);
1006 throw e;
1007 } catch (RemoteException e) {
1008 throw e.rethrowFromSystemServer();
1009 }
1010 }
1011
1012 /**
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001013 * Attempt to commit everything staged in this session. This may require
1014 * user intervention, and so it may not happen immediately. The final
1015 * result of the commit will be reported through the given callback.
1016 * <p>
Todd Kennedy04cc1912017-03-03 13:05:12 -08001017 * Once this method is called, the session is sealed and no additional
1018 * mutations may be performed on the session. If the device reboots
1019 * before the session has been finalized, you may commit the session again.
Tony Mak366ee622018-02-12 17:52:34 +00001020 * <p>
1021 * If the installer is the device owner or the affiliated profile owner, there will be no
1022 * user intervention.
Jeff Sharkey77d218e2014-09-06 12:20:37 -07001023 *
Philip P. Moltmann2fe7dee2018-09-14 08:45:42 -07001024 * @param statusReceiver Called when the state of the session changes. Intents
1025 * sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
1026 * individual status codes on how to handle them.
1027 *
Jeff Sharkey77d218e2014-09-06 12:20:37 -07001028 * @throws SecurityException if streams opened through
1029 * {@link #openWrite(String, long, long)} are still open.
Tony Mak366ee622018-02-12 17:52:34 +00001030 *
1031 * @see android.app.admin.DevicePolicyManager
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001032 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001033 public void commit(@NonNull IntentSender statusReceiver) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001034 try {
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001035 mSession.commit(statusReceiver, false);
1036 } catch (RemoteException e) {
1037 throw e.rethrowFromSystemServer();
1038 }
1039 }
1040
1041 /**
1042 * Attempt to commit a session that has been {@link #transfer(String) transferred}.
1043 *
1044 * <p>If the device reboots before the session has been finalized, you may commit the
1045 * session again.
1046 *
1047 * <p>The caller of this method is responsible to ensure the safety of the session. As the
1048 * session was created by another - usually less trusted - app, it is paramount that before
1049 * committing <u>all</u> public and system {@link SessionInfo properties of the session}
1050 * and <u>all</u> {@link #openRead(String) APKs} are verified by the caller. It might happen
1051 * that new properties are added to the session with a new API revision. In this case the
1052 * callers need to be updated.
1053 *
Philip P. Moltmann2fe7dee2018-09-14 08:45:42 -07001054 * @param statusReceiver Called when the state of the session changes. Intents
1055 * sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
1056 * individual status codes on how to handle them.
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001057 *
1058 * @hide
1059 */
1060 @SystemApi
1061 @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
1062 public void commitTransferred(@NonNull IntentSender statusReceiver) {
1063 try {
1064 mSession.commit(statusReceiver, true);
1065 } catch (RemoteException e) {
1066 throw e.rethrowFromSystemServer();
1067 }
1068 }
1069
1070 /**
1071 * Transfer the session to a new owner.
1072 * <p>
1073 * Only sessions that update the installing app can be transferred.
1074 * <p>
1075 * After the transfer to a package with a different uid all method calls on the session
1076 * will cause {@link SecurityException}s.
1077 * <p>
1078 * Once this method is called, the session is sealed and no additional mutations beside
1079 * committing it may be performed on the session.
1080 *
1081 * @param packageName The package of the new owner. Needs to hold the INSTALL_PACKAGES
1082 * permission.
1083 *
1084 * @throws PackageManager.NameNotFoundException if the new owner could not be found.
1085 * @throws SecurityException if called after the session has been committed or abandoned.
1086 * @throws SecurityException if the session does not update the original installer
1087 * @throws SecurityException if streams opened through
1088 * {@link #openWrite(String, long, long) are still open.
1089 */
1090 public void transfer(@NonNull String packageName)
1091 throws PackageManager.NameNotFoundException {
1092 Preconditions.checkNotNull(packageName);
1093
1094 try {
1095 mSession.transfer(packageName);
1096 } catch (ParcelableException e) {
1097 e.maybeRethrow(PackageManager.NameNotFoundException.class);
1098 throw new RuntimeException(e);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001099 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001100 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001101 }
1102 }
1103
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001104 /**
1105 * Release this session object. You can open the session again if it
1106 * hasn't been finalized.
1107 */
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001108 @Override
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001109 public void close() {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001110 try {
1111 mSession.close();
1112 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001113 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001114 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001115 }
1116
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001117 /**
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001118 * Completely abandon this session, destroying all staged data and
Jeff Sharkey77d218e2014-09-06 12:20:37 -07001119 * rendering it invalid. Abandoned sessions will be reported to
1120 * {@link SessionCallback} listeners as failures. This is equivalent to
1121 * opening the session and calling {@link Session#abandon()}.
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001122 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001123 public void abandon() {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001124 try {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001125 mSession.abandon();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001126 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001127 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001128 }
1129 }
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001130
1131 /**
1132 * @return {@code true} if this session will commit more than one package when it is
1133 * committed.
1134 */
1135 public boolean isMultiPackage() {
1136 try {
1137 return mSession.isMultiPackage();
1138 } catch (RemoteException e) {
1139 throw e.rethrowFromSystemServer();
1140 }
1141 }
1142
1143 /**
Dario Freniaac4ba42018-12-06 15:47:16 +00001144 * @return {@code true} if this session will be staged and applied at next reboot.
1145 */
1146 public boolean isStaged() {
1147 try {
1148 return mSession.isStaged();
1149 } catch (RemoteException e) {
1150 throw e.rethrowFromSystemServer();
1151 }
1152 }
1153
1154 /**
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001155 * @return the session ID of the multi-package session that this belongs to or
1156 * {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session.
1157 */
1158 public int getParentSessionId() {
1159 try {
1160 return mSession.getParentSessionId();
1161 } catch (RemoteException e) {
1162 throw e.rethrowFromSystemServer();
1163 }
1164 }
1165
1166 /**
1167 * @return the set of session IDs that will be committed atomically when this session is
1168 * committed if this is a multi-package session or null if none exist.
1169 */
1170 @NonNull
1171 public int[] getChildSessionIds() {
1172 try {
1173 return mSession.getChildSessionIds();
1174 } catch (RemoteException e) {
1175 throw e.rethrowFromSystemServer();
1176 }
1177 }
1178
1179 /**
1180 * Adds a session ID to the set of sessions that will be committed atomically
1181 * when this session is committed.
1182 *
1183 * @param sessionId the session ID to add to this multi-package session.
1184 */
1185 public void addChildSessionId(int sessionId) {
1186 try {
1187 mSession.addChildSessionId(sessionId);
1188 } catch (RemoteException e) {
1189 throw e.rethrowFromSystemServer();
1190 }
1191 }
1192
1193 /**
1194 * Removes a session ID from the set of sessions that will be committed
1195 * atomically when this session is committed.
1196 *
1197 * @param sessionId the session ID to remove from this multi-package session.
1198 */
1199 public void removeChildSessionId(int sessionId) {
1200 try {
1201 mSession.removeChildSessionId(sessionId);
1202 } catch (RemoteException e) {
1203 throw e.rethrowFromSystemServer();
1204 }
1205 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001206 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001207
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001208 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001209 * Parameters for creating a new {@link PackageInstaller.Session}.
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001210 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001211 public static class SessionParams implements Parcelable {
1212
1213 /** {@hide} */
1214 public static final int MODE_INVALID = -1;
Jeff Sharkeyf0600952014-08-07 17:31:53 -07001215
1216 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001217 * Mode for an install session whose staged APKs should fully replace any
1218 * existing APKs for the target app.
Jeff Sharkeyf0600952014-08-07 17:31:53 -07001219 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001220 public static final int MODE_FULL_INSTALL = 1;
Jeff Sharkeyf0600952014-08-07 17:31:53 -07001221
1222 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001223 * Mode for an install session that should inherit any existing APKs for the
1224 * target app, unless they have been explicitly overridden (based on split
1225 * name) by the session. For example, this can be used to add one or more
1226 * split APKs to an existing installation.
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07001227 * <p>
Jeff Sharkeya0907432014-08-15 10:23:11 -07001228 * If there are no existing APKs for the target app, this behaves like
1229 * {@link #MODE_FULL_INSTALL}.
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07001230 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001231 public static final int MODE_INHERIT_EXISTING = 2;
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07001232
Jeff Sharkeya0907432014-08-15 10:23:11 -07001233 /** {@hide} */
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001234 public static final int UID_UNKNOWN = -1;
1235
1236 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001237 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001238 public int mode = MODE_INVALID;
1239 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001240 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001241 public int installFlags;
1242 /** {@hide} */
1243 public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
1244 /** {@hide} */
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001245 public @InstallReason int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
Bartosz Fabianowskia34f53f2017-01-11 18:08:47 +01001246 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001247 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001248 public long sizeBytes = -1;
1249 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001250 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001251 public String appPackageName;
1252 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001253 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001254 public Bitmap appIcon;
1255 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001256 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001257 public String appLabel;
1258 /** {@hide} */
Jeff Sharkey02bd7842014-10-06 15:14:27 -07001259 public long appIconLastModified = -1;
1260 /** {@hide} */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001261 public Uri originatingUri;
1262 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001263 @UnsupportedAppUsage
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001264 public int originatingUid = UID_UNKNOWN;
1265 /** {@hide} */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001266 public Uri referrerUri;
1267 /** {@hide} */
1268 public String abiOverride;
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001269 /** {@hide} */
1270 public String volumeUuid;
Svet Ganov7121e182015-07-13 22:38:12 -07001271 /** {@hide} */
1272 public String[] grantedRuntimePermissions;
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001273 /** {@hide} */
1274 public String installerPackageName;
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001275 /** {@hide} */
1276 public boolean isMultiPackage;
Dario Freniaac4ba42018-12-06 15:47:16 +00001277 /** {@hide} */
1278 public boolean isStaged;
Jeff Sharkeybb580672014-07-10 12:10:25 -07001279
Jeff Sharkeya0907432014-08-15 10:23:11 -07001280 /**
1281 * Construct parameters for a new package install session.
1282 *
1283 * @param mode one of {@link #MODE_FULL_INSTALL} or
1284 * {@link #MODE_INHERIT_EXISTING} describing how the session
1285 * should interact with an existing app.
1286 */
1287 public SessionParams(int mode) {
1288 this.mode = mode;
1289 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001290
Jeff Sharkeya0907432014-08-15 10:23:11 -07001291 /** {@hide} */
1292 public SessionParams(Parcel source) {
1293 mode = source.readInt();
1294 installFlags = source.readInt();
1295 installLocation = source.readInt();
Bartosz Fabianowskia34f53f2017-01-11 18:08:47 +01001296 installReason = source.readInt();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001297 sizeBytes = source.readLong();
1298 appPackageName = source.readString();
1299 appIcon = source.readParcelable(null);
1300 appLabel = source.readString();
1301 originatingUri = source.readParcelable(null);
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001302 originatingUid = source.readInt();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001303 referrerUri = source.readParcelable(null);
1304 abiOverride = source.readString();
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001305 volumeUuid = source.readString();
Svet Ganov7121e182015-07-13 22:38:12 -07001306 grantedRuntimePermissions = source.readStringArray();
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001307 installerPackageName = source.readString();
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001308 isMultiPackage = source.readBoolean();
Dario Freniaac4ba42018-12-06 15:47:16 +00001309 isStaged = source.readBoolean();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001310 }
1311
Dario Freni4b572c02019-01-29 09:40:31 +00001312 /** {@hide} */
1313 public SessionParams copy() {
1314 SessionParams ret = new SessionParams(mode);
1315 ret.installFlags = installFlags;
1316 ret.installLocation = installLocation;
1317 ret.installReason = installReason;
1318 ret.sizeBytes = sizeBytes;
1319 ret.appPackageName = appPackageName;
1320 ret.appIcon = appIcon; // not a copy.
1321 ret.appLabel = appLabel;
1322 ret.originatingUri = originatingUri; // not a copy, but immutable.
1323 ret.originatingUid = originatingUid;
1324 ret.referrerUri = referrerUri; // not a copy, but immutable.
1325 ret.abiOverride = abiOverride;
1326 ret.volumeUuid = volumeUuid;
1327 ret.grantedRuntimePermissions = grantedRuntimePermissions;
1328 ret.installerPackageName = installerPackageName;
1329 ret.isMultiPackage = isMultiPackage;
1330 ret.isStaged = isStaged;
1331 return ret;
1332 }
1333
Jeff Sharkeya0907432014-08-15 10:23:11 -07001334 /**
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001335 * Check if there are hidden options set.
1336 *
1337 * <p>Hidden options are those options that cannot be verified via public or system-api
1338 * methods on {@link SessionInfo}.
1339 *
1340 * @return {@code true} if any hidden option is set.
1341 *
1342 * @hide
1343 */
1344 public boolean areHiddenOptionsSet() {
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00001345 return (installFlags & (PackageManager.INSTALL_REQUEST_DOWNGRADE
1346 | PackageManager.INSTALL_ALLOW_DOWNGRADE
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001347 | PackageManager.INSTALL_DONT_KILL_APP
1348 | PackageManager.INSTALL_INSTANT_APP
1349 | PackageManager.INSTALL_FULL_APP
1350 | PackageManager.INSTALL_VIRTUAL_PRELOAD
1351 | PackageManager.INSTALL_ALLOCATE_AGGRESSIVE)) != installFlags
1352 || abiOverride != null || volumeUuid != null;
1353 }
1354
1355 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001356 * Provide value of {@link PackageInfo#installLocation}, which may be used
1357 * to determine where the app will be staged. Defaults to
1358 * {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}.
1359 */
1360 public void setInstallLocation(int installLocation) {
1361 this.installLocation = installLocation;
1362 }
1363
1364 /**
1365 * Optionally indicate the total size (in bytes) of all APKs that will be
1366 * delivered in this session. The system may use this to ensure enough disk
1367 * space exists before proceeding, or to estimate container size for
1368 * installations living on external storage.
1369 *
1370 * @see PackageInfo#INSTALL_LOCATION_AUTO
1371 * @see PackageInfo#INSTALL_LOCATION_PREFER_EXTERNAL
1372 */
1373 public void setSize(long sizeBytes) {
1374 this.sizeBytes = sizeBytes;
1375 }
1376
1377 /**
1378 * Optionally set the package name of the app being installed. It's strongly
1379 * recommended that you provide this value when known, so that observers can
1380 * communicate installing apps to users.
1381 * <p>
1382 * If the APKs staged in the session aren't consistent with this package
1383 * name, the install will fail. Regardless of this value, all APKs in the
1384 * app must have the same package name.
1385 */
1386 public void setAppPackageName(@Nullable String appPackageName) {
1387 this.appPackageName = appPackageName;
1388 }
1389
1390 /**
1391 * Optionally set an icon representing the app being installed. This should
1392 * be roughly {@link ActivityManager#getLauncherLargeIconSize()} in both
1393 * dimensions.
1394 */
1395 public void setAppIcon(@Nullable Bitmap appIcon) {
1396 this.appIcon = appIcon;
1397 }
1398
1399 /**
1400 * Optionally set a label representing the app being installed.
1401 */
1402 public void setAppLabel(@Nullable CharSequence appLabel) {
1403 this.appLabel = (appLabel != null) ? appLabel.toString() : null;
1404 }
1405
1406 /**
Todd Kennedy1ed6b872016-03-10 10:07:00 -08001407 * Optionally set the URI where this package was downloaded from. This is
1408 * informational and may be used as a signal for anti-malware purposes.
Jeff Sharkeya0907432014-08-15 10:23:11 -07001409 *
1410 * @see Intent#EXTRA_ORIGINATING_URI
1411 */
1412 public void setOriginatingUri(@Nullable Uri originatingUri) {
1413 this.originatingUri = originatingUri;
1414 }
1415
1416 /**
Nikolas Bravo62831002017-11-07 21:07:15 +00001417 * Sets the UID that initiated the package installation. This is informational
Todd Kennedy1ed6b872016-03-10 10:07:00 -08001418 * and may be used as a signal for anti-malware purposes.
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001419 */
1420 public void setOriginatingUid(int originatingUid) {
1421 this.originatingUid = originatingUid;
1422 }
1423
1424 /**
Todd Kennedy1ed6b872016-03-10 10:07:00 -08001425 * Optionally set the URI that referred you to install this package. This is
1426 * informational and may be used as a signal for anti-malware purposes.
Jeff Sharkeya0907432014-08-15 10:23:11 -07001427 *
1428 * @see Intent#EXTRA_REFERRER
1429 */
1430 public void setReferrerUri(@Nullable Uri referrerUri) {
1431 this.referrerUri = referrerUri;
1432 }
1433
Svet Ganov7121e182015-07-13 22:38:12 -07001434 /**
1435 * Sets which runtime permissions to be granted to the package at installation.
Svet Ganov7121e182015-07-13 22:38:12 -07001436 *
1437 * @param permissions The permissions to grant or null to grant all runtime
1438 * permissions.
1439 *
1440 * @hide
1441 */
1442 @SystemApi
1443 @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS)
1444 public void setGrantedRuntimePermissions(String[] permissions) {
1445 installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
1446 this.grantedRuntimePermissions = permissions;
1447 }
1448
Richard Uhlerb29f1452018-09-12 16:38:15 +01001449 /**
1450 * Request that rollbacks be enabled for the given upgrade.
shafik92ea53f2019-03-08 18:05:59 +00001451 *
1452 * @removed
1453 * @deprecated use {@link #setEnableRollback(boolean)} instead.
Richard Uhlerc739c8c2018-12-12 11:03:34 +00001454 * @hide
Richard Uhlerb29f1452018-09-12 16:38:15 +01001455 */
shafik92ea53f2019-03-08 18:05:59 +00001456 @Deprecated
Richard Uhlerc739c8c2018-12-12 11:03:34 +00001457 @SystemApi
Richard Uhlerb29f1452018-09-12 16:38:15 +01001458 public void setEnableRollback() {
1459 installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
1460 }
1461
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00001462 /**
shafik92ea53f2019-03-08 18:05:59 +00001463 * Request that rollbacks be enabled or disabled for the given upgrade.
1464 *
1465 * @param enable set to {@code true} to enable, {@code false} to disable
1466 * @hide
1467 */
1468 @SystemApi
1469 public void setEnableRollback(boolean enable) {
1470 if (enable) {
1471 installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
1472 } else {
1473 installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
1474 }
1475 }
1476
1477 /**
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00001478 * @deprecated use {@link #setRequestDowngrade(boolean)}.
1479 * {@hide}
1480 */
1481 @SystemApi
1482 @Deprecated
1483 public void setAllowDowngrade(boolean allowDowngrade) {
1484 setRequestDowngrade(allowDowngrade);
1485 }
1486
Jeff Sharkeya0907432014-08-15 10:23:11 -07001487 /** {@hide} */
Todd Kennedyc84d1ab2016-03-11 11:37:17 -08001488 @SystemApi
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00001489 public void setRequestDowngrade(boolean requestDowngrade) {
1490 if (requestDowngrade) {
1491 installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
Todd Kennedy948b7022016-03-14 14:29:52 -07001492 } else {
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00001493 installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE;
Todd Kennedy948b7022016-03-14 14:29:52 -07001494 }
Todd Kennedyc84d1ab2016-03-11 11:37:17 -08001495 }
1496
1497 /** {@hide} */
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001498 public void setInstallFlagsForcePermissionPrompt() {
1499 installFlags |= PackageManager.INSTALL_FORCE_PERMISSION_PROMPT;
1500 }
1501
1502 /** {@hide} */
Todd Kennedy24ca5c62016-03-16 15:42:01 -07001503 @SystemApi
1504 public void setDontKillApp(boolean dontKillApp) {
1505 if (dontKillApp) {
1506 installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
1507 } else {
1508 installFlags &= ~PackageManager.INSTALL_DONT_KILL_APP;
1509 }
Todd Kennedy39bfee52016-02-24 10:28:21 -08001510 }
1511
1512 /** {@hide} */
Todd Kennedyb7717682016-11-30 15:41:21 -08001513 @SystemApi
1514 public void setInstallAsInstantApp(boolean isInstantApp) {
1515 if (isInstantApp) {
Todd Kennedybe0b8892017-02-15 14:13:52 -08001516 installFlags |= PackageManager.INSTALL_INSTANT_APP;
1517 installFlags &= ~PackageManager.INSTALL_FULL_APP;
Todd Kennedyb7717682016-11-30 15:41:21 -08001518 } else {
Todd Kennedybe0b8892017-02-15 14:13:52 -08001519 installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
1520 installFlags |= PackageManager.INSTALL_FULL_APP;
Todd Kennedyb7717682016-11-30 15:41:21 -08001521 }
1522 }
1523
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001524 /**
Todd Kennedy78a72502017-07-19 12:49:30 -07001525 * Sets the install as a virtual preload. Will only have effect when called
1526 * by the verifier.
1527 * {@hide}
1528 */
1529 @SystemApi
1530 public void setInstallAsVirtualPreload() {
1531 installFlags |= PackageManager.INSTALL_VIRTUAL_PRELOAD;
1532 }
1533
1534 /**
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001535 * Set the reason for installing this package.
Todd Kennedy5fdbabb2018-03-07 15:59:41 -08001536 * <p>
1537 * The install reason should be a pre-defined integer. The behavior is
1538 * undefined if other values are used.
1539 *
Aurimas Liutikas7f695332018-05-31 21:07:32 -07001540 * @see PackageManager#INSTALL_REASON_UNKNOWN
1541 * @see PackageManager#INSTALL_REASON_POLICY
1542 * @see PackageManager#INSTALL_REASON_DEVICE_RESTORE
1543 * @see PackageManager#INSTALL_REASON_DEVICE_SETUP
Todd Kennedy5fdbabb2018-03-07 15:59:41 -08001544 * @see PackageManager#INSTALL_REASON_USER
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001545 */
1546 public void setInstallReason(@InstallReason int installReason) {
Bartosz Fabianowskia34f53f2017-01-11 18:08:47 +01001547 this.installReason = installReason;
1548 }
1549
Todd Kennedyb7717682016-11-30 15:41:21 -08001550 /** {@hide} */
Jeff Sharkey683bcd32017-03-18 17:54:51 -06001551 @SystemApi
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -06001552 @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE)
Jeff Sharkey683bcd32017-03-18 17:54:51 -06001553 public void setAllocateAggressive(boolean allocateAggressive) {
1554 if (allocateAggressive) {
1555 installFlags |= PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
1556 } else {
1557 installFlags &= ~PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
1558 }
1559 }
1560
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001561 /**
1562 * Set the installer package for the app.
1563 *
1564 * By default this is the app that created the {@link PackageInstaller} object.
1565 *
1566 * @param installerPackageName name of the installer package
1567 * {@hide}
1568 */
1569 public void setInstallerPackageName(String installerPackageName) {
1570 this.installerPackageName = installerPackageName;
1571 }
1572
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001573 /**
1574 * Set this session to be the parent of a multi-package install.
1575 *
1576 * A multi-package install session contains no APKs and only references other install
1577 * sessions via ID. When a multi-package session is committed, all of its children
1578 * are committed to the system in an atomic manner. If any children fail to install,
1579 * all of them do, including the multi-package session.
1580 */
1581 public void setMultiPackage() {
1582 this.isMultiPackage = true;
1583 }
1584
Dario Freniaac4ba42018-12-06 15:47:16 +00001585 /**
1586 * Set this session to be staged to be installed at reboot.
1587 *
1588 * Staged sessions are scheduled to be installed at next reboot. Staged sessions can also be
1589 * multi-package. In that case, if any of the children sessions fail to install at reboot,
1590 * all the other children sessions are aborted as well.
Dario Freni77786d92019-02-08 17:26:05 +00001591 *
1592 * {@hide}
Dario Freniaac4ba42018-12-06 15:47:16 +00001593 */
Dario Freni77786d92019-02-08 17:26:05 +00001594 @SystemApi
1595 @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
Dario Freniaac4ba42018-12-06 15:47:16 +00001596 public void setStaged() {
1597 this.isStaged = true;
1598 }
1599
Dario Freni3fa46d82019-01-23 19:31:47 +00001600 /**
1601 * Set this session to be installing an APEX package.
Nikita Ioffe4501c112019-02-22 11:51:09 +00001602 *
1603 * {@hide}
Dario Freni3fa46d82019-01-23 19:31:47 +00001604 */
Nikita Ioffe4501c112019-02-22 11:51:09 +00001605 @SystemApi
1606 @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
Dario Freni3fa46d82019-01-23 19:31:47 +00001607 public void setInstallAsApex() {
1608 installFlags |= PackageManager.INSTALL_APEX;
1609 }
1610
Jeff Sharkey683bcd32017-03-18 17:54:51 -06001611 /** {@hide} */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001612 public void dump(IndentingPrintWriter pw) {
1613 pw.printPair("mode", mode);
1614 pw.printHexPair("installFlags", installFlags);
1615 pw.printPair("installLocation", installLocation);
1616 pw.printPair("sizeBytes", sizeBytes);
1617 pw.printPair("appPackageName", appPackageName);
1618 pw.printPair("appIcon", (appIcon != null));
1619 pw.printPair("appLabel", appLabel);
1620 pw.printPair("originatingUri", originatingUri);
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001621 pw.printPair("originatingUid", originatingUid);
Jeff Sharkeya0907432014-08-15 10:23:11 -07001622 pw.printPair("referrerUri", referrerUri);
1623 pw.printPair("abiOverride", abiOverride);
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001624 pw.printPair("volumeUuid", volumeUuid);
Svet Ganov7121e182015-07-13 22:38:12 -07001625 pw.printPair("grantedRuntimePermissions", grantedRuntimePermissions);
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001626 pw.printPair("installerPackageName", installerPackageName);
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001627 pw.printPair("isMultiPackage", isMultiPackage);
Dario Freniaac4ba42018-12-06 15:47:16 +00001628 pw.printPair("isStaged", isStaged);
Jeff Sharkeya0907432014-08-15 10:23:11 -07001629 pw.println();
Jeff Sharkeybb580672014-07-10 12:10:25 -07001630 }
1631
1632 @Override
Jeff Sharkeya0907432014-08-15 10:23:11 -07001633 public int describeContents() {
1634 return 0;
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07001635 }
1636
1637 @Override
Jeff Sharkeya0907432014-08-15 10:23:11 -07001638 public void writeToParcel(Parcel dest, int flags) {
1639 dest.writeInt(mode);
1640 dest.writeInt(installFlags);
1641 dest.writeInt(installLocation);
Bartosz Fabianowskia34f53f2017-01-11 18:08:47 +01001642 dest.writeInt(installReason);
Jeff Sharkeya0907432014-08-15 10:23:11 -07001643 dest.writeLong(sizeBytes);
1644 dest.writeString(appPackageName);
1645 dest.writeParcelable(appIcon, flags);
1646 dest.writeString(appLabel);
1647 dest.writeParcelable(originatingUri, flags);
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001648 dest.writeInt(originatingUid);
Jeff Sharkeya0907432014-08-15 10:23:11 -07001649 dest.writeParcelable(referrerUri, flags);
1650 dest.writeString(abiOverride);
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001651 dest.writeString(volumeUuid);
Svet Ganov7121e182015-07-13 22:38:12 -07001652 dest.writeStringArray(grantedRuntimePermissions);
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001653 dest.writeString(installerPackageName);
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001654 dest.writeBoolean(isMultiPackage);
Dario Freniaac4ba42018-12-06 15:47:16 +00001655 dest.writeBoolean(isStaged);
Jeff Sharkeybb580672014-07-10 12:10:25 -07001656 }
Jeff Sharkeya0907432014-08-15 10:23:11 -07001657
1658 public static final Parcelable.Creator<SessionParams>
1659 CREATOR = new Parcelable.Creator<SessionParams>() {
1660 @Override
1661 public SessionParams createFromParcel(Parcel p) {
1662 return new SessionParams(p);
1663 }
1664
1665 @Override
1666 public SessionParams[] newArray(int size) {
1667 return new SessionParams[size];
1668 }
1669 };
Jeff Sharkeybb580672014-07-10 12:10:25 -07001670 }
1671
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001672 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001673 * Details for an active install session.
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001674 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001675 public static class SessionInfo implements Parcelable {
1676
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001677 /**
1678 * A session ID that does not exist or is invalid.
1679 */
1680 public static final int INVALID_ID = -1;
1681 /** {@hide} */
1682 private static final int[] NO_SESSIONS = {};
Dario Freni71eee5e2018-12-06 15:47:16 +00001683
1684 /** @hide */
Dario Frenib6d28962019-01-31 15:52:24 +00001685 @IntDef(prefix = { "STAGED_SESSION_" }, value = {
1686 STAGED_SESSION_NO_ERROR,
1687 STAGED_SESSION_VERIFICATION_FAILED,
1688 STAGED_SESSION_ACTIVATION_FAILED,
1689 STAGED_SESSION_UNKNOWN})
Dario Freni71eee5e2018-12-06 15:47:16 +00001690 @Retention(RetentionPolicy.SOURCE)
1691 public @interface StagedSessionErrorCode{}
1692 /**
1693 * Constant indicating that no error occurred during the preparation or the activation of
1694 * this staged session.
1695 */
Dario Frenib6d28962019-01-31 15:52:24 +00001696 public static final int STAGED_SESSION_NO_ERROR = 0;
Dario Freni71eee5e2018-12-06 15:47:16 +00001697
1698 /**
1699 * Constant indicating that an error occurred during the verification phase (pre-reboot) of
1700 * this staged session.
1701 */
Dario Frenib6d28962019-01-31 15:52:24 +00001702 public static final int STAGED_SESSION_VERIFICATION_FAILED = 1;
Dario Freni71eee5e2018-12-06 15:47:16 +00001703
1704 /**
1705 * Constant indicating that an error occurred during the activation phase (post-reboot) of
1706 * this staged session.
1707 */
Dario Frenib6d28962019-01-31 15:52:24 +00001708 public static final int STAGED_SESSION_ACTIVATION_FAILED = 2;
1709
1710 /**
1711 * Constant indicating that an unknown error occurred while processing this staged session.
1712 */
1713 public static final int STAGED_SESSION_UNKNOWN = 3;
Dario Freni71eee5e2018-12-06 15:47:16 +00001714
Jeff Sharkeya0907432014-08-15 10:23:11 -07001715 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001716 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001717 public int sessionId;
1718 /** {@hide} */
Jon Miranda2b340a22019-01-25 14:03:49 -08001719 public int userId;
1720 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001721 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001722 public String installerPackageName;
1723 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001724 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001725 public String resolvedBaseCodePath;
1726 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001727 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001728 public float progress;
1729 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001730 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001731 public boolean sealed;
1732 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001733 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001734 public boolean active;
Jeff Sharkeya0907432014-08-15 10:23:11 -07001735
1736 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001737 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001738 public int mode;
1739 /** {@hide} */
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001740 public @InstallReason int installReason;
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001741 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001742 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001743 public long sizeBytes;
1744 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001745 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001746 public String appPackageName;
1747 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001748 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001749 public Bitmap appIcon;
1750 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001751 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001752 public CharSequence appLabel;
1753
1754 /** {@hide} */
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001755 public int installLocation;
1756 /** {@hide} */
1757 public Uri originatingUri;
1758 /** {@hide} */
1759 public int originatingUid;
1760 /** {@hide} */
1761 public Uri referrerUri;
1762 /** {@hide} */
1763 public String[] grantedRuntimePermissions;
1764 /** {@hide} */
1765 public int installFlags;
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001766 /** {@hide} */
1767 public boolean isMultiPackage;
1768 /** {@hide} */
Dario Freniaac4ba42018-12-06 15:47:16 +00001769 public boolean isStaged;
1770 /** {@hide} */
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001771 public int parentSessionId = INVALID_ID;
1772 /** {@hide} */
1773 public int[] childSessionIds = NO_SESSIONS;
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001774
1775 /** {@hide} */
Dario Freni60a96c12019-02-24 21:01:29 +00001776 public boolean isStagedSessionApplied;
Dario Freni71eee5e2018-12-06 15:47:16 +00001777 /** {@hide} */
Dario Freni60a96c12019-02-24 21:01:29 +00001778 public boolean isStagedSessionReady;
Dario Freni71eee5e2018-12-06 15:47:16 +00001779 /** {@hide} */
Dario Freni60a96c12019-02-24 21:01:29 +00001780 public boolean isStagedSessionFailed;
Dario Freni71eee5e2018-12-06 15:47:16 +00001781 private int mStagedSessionErrorCode;
Dario Freni275b4ab2019-01-25 09:55:16 +00001782 private String mStagedSessionErrorMessage;
Dario Freni71eee5e2018-12-06 15:47:16 +00001783
1784 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001785 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001786 public SessionInfo() {
1787 }
1788
1789 /** {@hide} */
1790 public SessionInfo(Parcel source) {
1791 sessionId = source.readInt();
Jon Miranda2b340a22019-01-25 14:03:49 -08001792 userId = source.readInt();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001793 installerPackageName = source.readString();
1794 resolvedBaseCodePath = source.readString();
1795 progress = source.readFloat();
1796 sealed = source.readInt() != 0;
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001797 active = source.readInt() != 0;
Jeff Sharkeya0907432014-08-15 10:23:11 -07001798
1799 mode = source.readInt();
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001800 installReason = source.readInt();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001801 sizeBytes = source.readLong();
1802 appPackageName = source.readString();
1803 appIcon = source.readParcelable(null);
1804 appLabel = source.readString();
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001805
1806 installLocation = source.readInt();
1807 originatingUri = source.readParcelable(null);
1808 originatingUid = source.readInt();
1809 referrerUri = source.readParcelable(null);
1810 grantedRuntimePermissions = source.readStringArray();
1811 installFlags = source.readInt();
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001812 isMultiPackage = source.readBoolean();
Dario Freniaac4ba42018-12-06 15:47:16 +00001813 isStaged = source.readBoolean();
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001814 parentSessionId = source.readInt();
1815 childSessionIds = source.createIntArray();
1816 if (childSessionIds == null) {
1817 childSessionIds = NO_SESSIONS;
1818 }
Dario Freni60a96c12019-02-24 21:01:29 +00001819 isStagedSessionApplied = source.readBoolean();
1820 isStagedSessionReady = source.readBoolean();
1821 isStagedSessionFailed = source.readBoolean();
Dario Freni71eee5e2018-12-06 15:47:16 +00001822 mStagedSessionErrorCode = source.readInt();
Dario Freni275b4ab2019-01-25 09:55:16 +00001823 mStagedSessionErrorMessage = source.readString();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001824 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001825
1826 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001827 * Return the ID for this session.
Jeff Sharkeybb580672014-07-10 12:10:25 -07001828 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001829 public int getSessionId() {
1830 return sessionId;
1831 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001832
1833 /**
Jon Miranda2b340a22019-01-25 14:03:49 -08001834 * Return the user associated with this session.
1835 */
1836 public UserHandle getUser() {
1837 return new UserHandle(userId);
1838 }
1839
1840 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001841 * Return the package name of the app that owns this session.
1842 */
1843 public @Nullable String getInstallerPackageName() {
1844 return installerPackageName;
1845 }
1846
1847 /**
1848 * Return current overall progress of this session, between 0 and 1.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001849 * <p>
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001850 * Note that this progress may not directly correspond to the value
1851 * reported by
1852 * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
1853 * system may carve out a portion of the overall progress to represent
1854 * its own internal installation work.
Jeff Sharkeybb580672014-07-10 12:10:25 -07001855 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001856 public float getProgress() {
1857 return progress;
1858 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001859
1860 /**
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001861 * Return if this session is currently active.
1862 * <p>
1863 * A session is considered active whenever there is ongoing forward
1864 * progress being made, such as the installer holding an open
1865 * {@link Session} instance while streaming data into place, or the
1866 * system optimizing code as the result of
1867 * {@link Session#commit(IntentSender)}.
1868 * <p>
1869 * If the installer closes the {@link Session} without committing, the
1870 * session is considered inactive until the installer opens the session
1871 * again.
Jeff Sharkeybb580672014-07-10 12:10:25 -07001872 */
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001873 public boolean isActive() {
1874 return active;
1875 }
1876
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001877 /**
Todd Kennedy04cc1912017-03-03 13:05:12 -08001878 * Return if this session is sealed.
1879 * <p>
1880 * Once sealed, no further changes may be made to the session. A session
1881 * is sealed the moment {@link Session#commit(IntentSender)} is called.
1882 */
1883 public boolean isSealed() {
1884 return sealed;
1885 }
1886
1887 /**
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001888 * Return the reason for installing this package.
1889 *
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001890 * @return The install reason.
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001891 */
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001892 public @InstallReason int getInstallReason() {
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001893 return installReason;
1894 }
1895
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001896 /** {@hide} */
1897 @Deprecated
Jeff Sharkeya0907432014-08-15 10:23:11 -07001898 public boolean isOpen() {
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001899 return isActive();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001900 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001901
1902 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001903 * Return the package name this session is working with. May be {@code null}
1904 * if unknown.
Jeff Sharkeybb580672014-07-10 12:10:25 -07001905 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001906 public @Nullable String getAppPackageName() {
1907 return appPackageName;
1908 }
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001909
Jeff Sharkey7328a1b2014-08-07 14:01:43 -07001910 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001911 * Return an icon representing the app being installed. May be {@code null}
1912 * if unavailable.
1913 */
1914 public @Nullable Bitmap getAppIcon() {
Jeff Sharkeyda1247a2017-06-08 14:13:29 -06001915 if (appIcon == null) {
1916 // Icon may have been omitted for calls that return bulk session
1917 // lists, so try fetching the specific icon.
1918 try {
Jeff Sharkeyd1dd2c62017-08-02 09:28:53 -06001919 final SessionInfo info = AppGlobals.getPackageManager().getPackageInstaller()
1920 .getSessionInfo(sessionId);
1921 appIcon = (info != null) ? info.appIcon : null;
Jeff Sharkeyda1247a2017-06-08 14:13:29 -06001922 } catch (RemoteException e) {
1923 throw e.rethrowFromSystemServer();
1924 }
1925 }
Jeff Sharkeya0907432014-08-15 10:23:11 -07001926 return appIcon;
1927 }
1928
1929 /**
1930 * Return a label representing the app being installed. May be {@code null}
1931 * if unavailable.
1932 */
1933 public @Nullable CharSequence getAppLabel() {
1934 return appLabel;
1935 }
1936
1937 /**
1938 * Return an Intent that can be started to view details about this install
1939 * session. This may surface actions such as pause, resume, or cancel.
1940 * <p>
1941 * In some cases, a matching Activity may not exist, so ensure you safeguard
1942 * against this.
Jeff Sharkey7328a1b2014-08-07 14:01:43 -07001943 *
Jeff Sharkeya0907432014-08-15 10:23:11 -07001944 * @see PackageInstaller#ACTION_SESSION_DETAILS
Jeff Sharkey7328a1b2014-08-07 14:01:43 -07001945 */
Jeff Sharkeyde742312014-09-15 14:04:56 -07001946 public @Nullable Intent createDetailsIntent() {
Jeff Sharkeya0907432014-08-15 10:23:11 -07001947 final Intent intent = new Intent(PackageInstaller.ACTION_SESSION_DETAILS);
1948 intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
1949 intent.setPackage(installerPackageName);
1950 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1951 return intent;
Jeff Sharkeybb580672014-07-10 12:10:25 -07001952 }
1953
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001954 /**
1955 * Get the mode of the session as set in the constructor of the {@link SessionParams}.
1956 *
1957 * @return One of {@link SessionParams#MODE_FULL_INSTALL}
1958 * or {@link SessionParams#MODE_INHERIT_EXISTING}
1959 */
1960 public int getMode() {
1961 return mode;
1962 }
1963
1964 /**
1965 * Get the value set in {@link SessionParams#setInstallLocation(int)}.
1966 */
1967 public int getInstallLocation() {
1968 return installLocation;
1969 }
1970
1971 /**
1972 * Get the value as set in {@link SessionParams#setSize(long)}.
1973 *
1974 * <p>The value is a hint and does not have to match the actual size.
1975 */
1976 public long getSize() {
1977 return sizeBytes;
1978 }
1979
1980 /**
1981 * Get the value set in {@link SessionParams#setOriginatingUri(Uri)}.
1982 */
1983 public @Nullable Uri getOriginatingUri() {
1984 return originatingUri;
1985 }
1986
1987 /**
1988 * Get the value set in {@link SessionParams#setOriginatingUid(int)}.
1989 */
1990 public int getOriginatingUid() {
1991 return originatingUid;
1992 }
1993
1994 /**
1995 * Get the value set in {@link SessionParams#setReferrerUri(Uri)}
1996 */
1997 public @Nullable Uri getReferrerUri() {
1998 return referrerUri;
1999 }
2000
2001 /**
2002 * Get the value set in {@link SessionParams#setGrantedRuntimePermissions(String[])}.
2003 *
2004 * @hide
2005 */
2006 @SystemApi
2007 public @Nullable String[] getGrantedRuntimePermissions() {
2008 return grantedRuntimePermissions;
2009 }
2010
2011 /**
2012 * Get the value set in {@link SessionParams#setAllowDowngrade(boolean)}.
2013 *
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00002014 * @deprecated use {@link #getRequestDowngrade()}.
Philip P. Moltmann7460c592017-08-08 20:07:11 +00002015 * @hide
2016 */
2017 @SystemApi
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00002018 @Deprecated
Philip P. Moltmann7460c592017-08-08 20:07:11 +00002019 public boolean getAllowDowngrade() {
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00002020 return getRequestDowngrade();
2021 }
2022
2023 /**
2024 * Get the value set in {@link SessionParams#setRequestDowngrade(boolean)}.
2025 *
2026 * @hide
2027 */
2028 @SystemApi
2029 public boolean getRequestDowngrade() {
2030 return (installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0;
Philip P. Moltmann7460c592017-08-08 20:07:11 +00002031 }
2032
2033 /**
2034 * Get the value set in {@link SessionParams#setDontKillApp(boolean)}.
2035 *
2036 * @hide
2037 */
2038 @SystemApi
2039 public boolean getDontKillApp() {
2040 return (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0;
2041 }
2042
2043 /**
2044 * If {@link SessionParams#setInstallAsInstantApp(boolean)} was called with {@code true},
2045 * return true. If it was called with {@code false} or if it was not called return false.
2046 *
2047 * @hide
2048 *
2049 * @see #getInstallAsFullApp
2050 */
2051 @SystemApi
2052 public boolean getInstallAsInstantApp(boolean isInstantApp) {
2053 return (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
2054 }
2055
2056 /**
2057 * If {@link SessionParams#setInstallAsInstantApp(boolean)} was called with {@code false},
2058 * return true. If it was called with {@code true} or if it was not called return false.
2059 *
2060 * @hide
2061 *
2062 * @see #getInstallAsInstantApp
2063 */
2064 @SystemApi
2065 public boolean getInstallAsFullApp(boolean isInstantApp) {
2066 return (installFlags & PackageManager.INSTALL_FULL_APP) != 0;
2067 }
2068
2069 /**
2070 * Get if {@link SessionParams#setInstallAsVirtualPreload()} was called.
2071 *
2072 * @hide
2073 */
2074 @SystemApi
2075 public boolean getInstallAsVirtualPreload() {
2076 return (installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0;
2077 }
2078
2079 /**
shafik92ea53f2019-03-08 18:05:59 +00002080 * Return whether rollback is enabled or disabled for the given upgrade.
2081 *
2082 * @hide
2083 */
2084 @SystemApi
2085 public boolean getEnableRollback() {
2086 return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0;
2087 }
2088
2089 /**
Philip P. Moltmann7460c592017-08-08 20:07:11 +00002090 * Get the value set in {@link SessionParams#setAllocateAggressive(boolean)}.
2091 *
2092 * @hide
2093 */
2094 @SystemApi
2095 public boolean getAllocateAggressive() {
2096 return (installFlags & PackageManager.INSTALL_ALLOCATE_AGGRESSIVE) != 0;
2097 }
2098
2099
Jeff Sharkeyde742312014-09-15 14:04:56 -07002100 /** {@hide} */
2101 @Deprecated
2102 public @Nullable Intent getDetailsIntent() {
2103 return createDetailsIntent();
2104 }
2105
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002106 /**
2107 * Returns true if this session is a multi-package session containing references to other
2108 * sessions.
2109 */
2110 public boolean isMultiPackage() {
2111 return isMultiPackage;
2112 }
2113
2114 /**
Dario Freniaac4ba42018-12-06 15:47:16 +00002115 * Returns true if this session is a staged session which will be applied at next reboot.
2116 */
2117 public boolean isStaged() {
2118 return isStaged;
2119 }
2120
2121 /**
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002122 * Returns the parent multi-package session ID if this session belongs to one,
2123 * {@link #INVALID_ID} otherwise.
2124 */
2125 public int getParentSessionId() {
2126 return parentSessionId;
2127 }
2128
2129 /**
2130 * Returns the set of session IDs that will be committed when this session is commited if
2131 * this session is a multi-package session.
2132 */
2133 public int[] getChildSessionIds() {
2134 return childSessionIds;
2135 }
2136
Dario Freni60a96c12019-02-24 21:01:29 +00002137 private void checkSessionIsStaged() {
2138 if (!isStaged) {
2139 throw new IllegalStateException("Session is not marked as staged.");
2140 }
2141 }
2142
Dario Freni71eee5e2018-12-06 15:47:16 +00002143 /**
2144 * Whether the staged session has been applied successfully, meaning that all of its
2145 * packages have been activated and no further action is required.
2146 * Only meaningful if {@code isStaged} is true.
2147 */
Dario Freni60a96c12019-02-24 21:01:29 +00002148 public boolean isStagedSessionApplied() {
2149 checkSessionIsStaged();
2150 return isStagedSessionApplied;
Dario Freni71eee5e2018-12-06 15:47:16 +00002151 }
2152
2153 /**
2154 * Whether the staged session is ready to be applied at next reboot. Only meaningful if
2155 * {@code isStaged} is true.
2156 */
Dario Freni60a96c12019-02-24 21:01:29 +00002157 public boolean isStagedSessionReady() {
2158 checkSessionIsStaged();
2159 return isStagedSessionReady;
Dario Freni71eee5e2018-12-06 15:47:16 +00002160 }
2161
2162 /**
2163 * Whether something went wrong and the staged session is declared as failed, meaning that
2164 * it will be ignored at next reboot. Only meaningful if {@code isStaged} is true.
2165 */
Dario Freni60a96c12019-02-24 21:01:29 +00002166 public boolean isStagedSessionFailed() {
2167 checkSessionIsStaged();
2168 return isStagedSessionFailed;
Dario Freni71eee5e2018-12-06 15:47:16 +00002169 }
2170
2171 /**
2172 * If something went wrong with a staged session, clients can check this error code to
2173 * understand which kind of failure happened. Only meaningful if {@code isStaged} is true.
2174 */
Dario Freni60a96c12019-02-24 21:01:29 +00002175 public @StagedSessionErrorCode int getStagedSessionErrorCode() {
2176 checkSessionIsStaged();
Dario Freni71eee5e2018-12-06 15:47:16 +00002177 return mStagedSessionErrorCode;
2178 }
2179
Dario Freni275b4ab2019-01-25 09:55:16 +00002180 /**
2181 * Text description of the error code returned by {@code getStagedSessionErrorCode}, or
2182 * empty string if no error was encountered.
2183 */
Dario Freniaa796c12019-03-06 12:26:16 +00002184 public @NonNull String getStagedSessionErrorMessage() {
Dario Freni60a96c12019-02-24 21:01:29 +00002185 checkSessionIsStaged();
Dario Freni275b4ab2019-01-25 09:55:16 +00002186 return mStagedSessionErrorMessage;
2187 }
2188
Dario Freni71eee5e2018-12-06 15:47:16 +00002189 /** {@hide} */
Dario Freni275b4ab2019-01-25 09:55:16 +00002190 public void setStagedSessionErrorCode(@StagedSessionErrorCode int errorCode,
2191 String errorMessage) {
Dario Freni71eee5e2018-12-06 15:47:16 +00002192 mStagedSessionErrorCode = errorCode;
Dario Freni275b4ab2019-01-25 09:55:16 +00002193 mStagedSessionErrorMessage = errorMessage;
Dario Freni71eee5e2018-12-06 15:47:16 +00002194 }
2195
Jeff Sharkeybb580672014-07-10 12:10:25 -07002196 @Override
Jeff Sharkeya0907432014-08-15 10:23:11 -07002197 public int describeContents() {
2198 return 0;
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07002199 }
2200
2201 @Override
Jeff Sharkeya0907432014-08-15 10:23:11 -07002202 public void writeToParcel(Parcel dest, int flags) {
2203 dest.writeInt(sessionId);
Jon Miranda2b340a22019-01-25 14:03:49 -08002204 dest.writeInt(userId);
Jeff Sharkeya0907432014-08-15 10:23:11 -07002205 dest.writeString(installerPackageName);
2206 dest.writeString(resolvedBaseCodePath);
2207 dest.writeFloat(progress);
2208 dest.writeInt(sealed ? 1 : 0);
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07002209 dest.writeInt(active ? 1 : 0);
Jeff Sharkeybb580672014-07-10 12:10:25 -07002210
Jeff Sharkeya0907432014-08-15 10:23:11 -07002211 dest.writeInt(mode);
Sunny Goyal6d7cb232017-01-30 10:43:18 -08002212 dest.writeInt(installReason);
Jeff Sharkeya0907432014-08-15 10:23:11 -07002213 dest.writeLong(sizeBytes);
2214 dest.writeString(appPackageName);
2215 dest.writeParcelable(appIcon, flags);
2216 dest.writeString(appLabel != null ? appLabel.toString() : null);
Philip P. Moltmann7460c592017-08-08 20:07:11 +00002217
2218 dest.writeInt(installLocation);
2219 dest.writeParcelable(originatingUri, flags);
2220 dest.writeInt(originatingUid);
2221 dest.writeParcelable(referrerUri, flags);
2222 dest.writeStringArray(grantedRuntimePermissions);
2223 dest.writeInt(installFlags);
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002224 dest.writeBoolean(isMultiPackage);
Dario Freniaac4ba42018-12-06 15:47:16 +00002225 dest.writeBoolean(isStaged);
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002226 dest.writeInt(parentSessionId);
2227 dest.writeIntArray(childSessionIds);
Dario Freni60a96c12019-02-24 21:01:29 +00002228 dest.writeBoolean(isStagedSessionApplied);
2229 dest.writeBoolean(isStagedSessionReady);
2230 dest.writeBoolean(isStagedSessionFailed);
Dario Freni71eee5e2018-12-06 15:47:16 +00002231 dest.writeInt(mStagedSessionErrorCode);
Dario Freni275b4ab2019-01-25 09:55:16 +00002232 dest.writeString(mStagedSessionErrorMessage);
Jeff Sharkeybb580672014-07-10 12:10:25 -07002233 }
Jeff Sharkeya0907432014-08-15 10:23:11 -07002234
2235 public static final Parcelable.Creator<SessionInfo>
2236 CREATOR = new Parcelable.Creator<SessionInfo>() {
2237 @Override
2238 public SessionInfo createFromParcel(Parcel p) {
2239 return new SessionInfo(p);
2240 }
2241
2242 @Override
2243 public SessionInfo[] newArray(int size) {
2244 return new SessionInfo[size];
2245 }
2246 };
Jeff Sharkeybb580672014-07-10 12:10:25 -07002247 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07002248}