blob: 2dc014c45fad8592a6944f52d53f06631d7ff8b4 [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;
39import android.os.Looper;
40import android.os.Message;
Jeff Sharkeya0907432014-08-15 10:23:11 -070041import android.os.Parcel;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070042import android.os.ParcelFileDescriptor;
Jeff Sharkeya0907432014-08-15 10:23:11 -070043import android.os.Parcelable;
Philip P. Moltmann7460c592017-08-08 20:07:11 +000044import android.os.ParcelableException;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070045import android.os.RemoteException;
Jeff Sharkey02d4e342017-03-10 21:53:48 -070046import android.os.SystemProperties;
47import 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;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070053
Jeff Sharkeyec55ef02014-07-08 11:28:00 -070054import java.io.Closeable;
Jeff Sharkeya1031142014-07-12 18:09:46 -070055import java.io.IOException;
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -070056import java.io.InputStream;
Jeff Sharkey78cc3402014-05-22 10:52:49 -070057import java.io.OutputStream;
Dario Freni71eee5e2018-12-06 15:47:16 +000058import java.lang.annotation.Retention;
59import java.lang.annotation.RetentionPolicy;
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -070060import java.security.MessageDigest;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -070061import java.util.ArrayList;
62import java.util.Iterator;
Jeff Sharkeybb580672014-07-10 12:10:25 -070063import java.util.List;
Jeff Sharkey78cc3402014-05-22 10:52:49 -070064
Jeff Sharkey6c833e02014-07-14 22:44:30 -070065/**
66 * Offers the ability to install, upgrade, and remove applications on the
67 * device. This includes support for apps packaged either as a single
68 * "monolithic" APK, or apps packaged as multiple "split" APKs.
69 * <p>
70 * An app is delivered for installation through a
71 * {@link PackageInstaller.Session}, which any app can create. Once the session
72 * is created, the installer can stream one or more APKs into place until it
73 * decides to either commit or destroy the session. Committing may require user
Rubin Xufd4a3b42018-12-05 16:03:27 +000074 * intervention to complete the installation, unless the caller falls into one of the
75 * following categories, in which case the installation will complete automatically.
76 * <ul>
77 * <li>the device owner
78 * <li>the affiliated profile owner
79 * <li>the device owner delegated app with
80 * {@link android.app.admin.DevicePolicyManager#DELEGATION_PACKAGE_INSTALLATION}
81 * </ul>
Jeff Sharkey6c833e02014-07-14 22:44:30 -070082 * <p>
83 * Sessions can install brand new apps, upgrade existing apps, or add new splits
Jeff Sharkeyda96e132014-07-15 14:54:09 -070084 * into an existing app.
Jeff Sharkey6c833e02014-07-14 22:44:30 -070085 * <p>
Jeff Sharkeyda96e132014-07-15 14:54:09 -070086 * Apps packaged as multiple split APKs always consist of a single "base" APK
Jeff Sharkey6c833e02014-07-14 22:44:30 -070087 * (with a {@code null} split name) and zero or more "split" APKs (with unique
88 * split names). Any subset of these APKs can be installed together, as long as
89 * the following constraints are met:
90 * <ul>
91 * <li>All APKs must have the exact same package name, version code, and signing
92 * certificates.
Jeff Sharkey6c833e02014-07-14 22:44:30 -070093 * <li>All APKs must have unique split names.
Jeff Sharkeyda96e132014-07-15 14:54:09 -070094 * <li>All installations must contain a single base APK.
Jeff Sharkey6c833e02014-07-14 22:44:30 -070095 * </ul>
Peter Visontayf702fd42017-11-17 14:00:47 +000096 * <p>
97 * The ApiDemos project contains examples of using this API:
98 * <code>ApiDemos/src/com/example/android/apis/content/InstallApk*.java</code>.
Ricky Waic5ea08b2018-09-05 20:55:11 +010099 * <p>
100 * On Android Q or above, an app installed notification will be posted
101 * by system after a new app is installed.
102 * To customize installer's notification icon, you should declare the following in the manifest
103 * &lt;application> as follows: </p>
104 * <pre>
105 * &lt;meta-data android:name="com.android.packageinstaller.notification.smallIcon"
106 * android:resource="@drawable/installer_notification_icon"/>
107 * </pre>
108 * <pre>
109 * &lt;meta-data android:name="com.android.packageinstaller.notification.color"
110 * android:resource="@color/installer_notification_color"/>
111 * </pre>
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700112 */
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700113public class PackageInstaller {
Jeff Sharkeya0907432014-08-15 10:23:11 -0700114 private static final String TAG = "PackageInstaller";
115
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700116 /** {@hide} */
117 public static final boolean ENABLE_REVOCABLE_FD =
118 SystemProperties.getBoolean("fw.revocable_fd", false);
119
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700120 /**
121 * Activity Action: Show details about a particular install session. This
122 * may surface actions such as pause, resume, or cancel.
123 * <p>
124 * This should always be scoped to the installer package that owns the
Jeff Sharkeyde742312014-09-15 14:04:56 -0700125 * session. Clients should use {@link SessionInfo#createDetailsIntent()} to
Jeff Sharkeya0907432014-08-15 10:23:11 -0700126 * build this intent correctly.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700127 * <p>
128 * In some cases, a matching Activity may not exist, so ensure you safeguard
129 * against this.
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700130 * <p>
131 * The session to show details for is defined in {@link #EXTRA_SESSION_ID}.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700132 */
133 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
134 public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
135
Sunny Goyal6d7cb232017-01-30 10:43:18 -0800136 /**
137 * Broadcast Action: Explicit broadcast sent to the last known default launcher when a session
138 * for a new install is committed. For managed profile, this is sent to the default launcher
139 * of the primary profile.
140 * <p>
141 * The associated session is defined in {@link #EXTRA_SESSION} and the user for which this
142 * session was created in {@link Intent#EXTRA_USER}.
143 */
144 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
145 public static final String ACTION_SESSION_COMMITTED =
146 "android.content.pm.action.SESSION_COMMITTED";
147
Dario Frenie487ea22018-12-12 15:41:59 +0000148 /**
149 * Broadcast Action: Send information about a staged install session when its state is updated.
150 * <p>
151 * The associated session information is defined in {@link #EXTRA_SESSION}.
152 */
153 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
154 public static final String ACTION_SESSION_UPDATED =
155 "android.content.pm.action.SESSION_UPDATED";
156
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700157 /** {@hide} */
Philip P. Moltmanne8fe3cb2018-07-23 14:27:11 -0700158 public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL";
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700159
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700160 /**
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700161 * An integer session ID that an operation is working with.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700162 *
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700163 * @see Intent#getIntExtra(String, int)
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700164 */
165 public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
166
Jeff Sharkeya0907432014-08-15 10:23:11 -0700167 /**
Sunny Goyal6d7cb232017-01-30 10:43:18 -0800168 * {@link SessionInfo} that an operation is working with.
169 *
170 * @see Intent#getParcelableExtra(String)
171 */
172 public static final String EXTRA_SESSION = "android.content.pm.extra.SESSION";
173
174 /**
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700175 * Package name that an operation is working with.
Jeff Sharkeya0907432014-08-15 10:23:11 -0700176 *
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700177 * @see Intent#getStringExtra(String)
Jeff Sharkeya0907432014-08-15 10:23:11 -0700178 */
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700179 public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
180
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700181 /**
182 * Current status of an operation. Will be one of
183 * {@link #STATUS_PENDING_USER_ACTION}, {@link #STATUS_SUCCESS},
184 * {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED},
185 * {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT},
186 * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID}, or
187 * {@link #STATUS_FAILURE_STORAGE}.
188 * <p>
189 * More information about a status may be available through additional
190 * extras; see the individual status documentation for details.
191 *
192 * @see Intent#getIntExtra(String, int)
193 */
194 public static final String EXTRA_STATUS = "android.content.pm.extra.STATUS";
195
196 /**
197 * Detailed string representation of the status, including raw details that
198 * are useful for debugging.
199 *
200 * @see Intent#getStringExtra(String)
201 */
202 public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
203
204 /**
205 * Another package name relevant to a status. This is typically the package
206 * responsible for causing an operation failure.
207 *
208 * @see Intent#getStringExtra(String)
209 */
210 public static final String
211 EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
212
213 /**
214 * Storage path relevant to a status.
215 *
216 * @see Intent#getStringExtra(String)
217 */
218 public static final String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH";
219
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700220 /** {@hide} */
221 @Deprecated
Jeff Sharkeya0907432014-08-15 10:23:11 -0700222 public static final String EXTRA_PACKAGE_NAMES = "android.content.pm.extra.PACKAGE_NAMES";
223
224 /** {@hide} */
225 public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS";
226 /** {@hide} */
227 public static final String EXTRA_LEGACY_BUNDLE = "android.content.pm.extra.LEGACY_BUNDLE";
Jeff Sharkeyf0600952014-08-07 17:31:53 -0700228 /** {@hide} */
229 public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK";
230
Jeff Sharkeya0907432014-08-15 10:23:11 -0700231 /**
232 * User action is currently required to proceed. You can launch the intent
233 * activity described by {@link Intent#EXTRA_INTENT} to involve the user and
234 * continue.
235 * <p>
236 * You may choose to immediately launch the intent if the user is actively
237 * using your app. Otherwise, you should use a notification to guide the
238 * user back into your app before launching.
239 *
240 * @see Intent#getParcelableExtra(String)
241 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700242 public static final int STATUS_PENDING_USER_ACTION = -1;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700243
244 /**
245 * The operation succeeded.
246 */
247 public static final int STATUS_SUCCESS = 0;
248
249 /**
250 * The operation failed in a generic way. The system will always try to
251 * provide a more specific failure reason, but in some rare cases this may
252 * be delivered.
253 *
254 * @see #EXTRA_STATUS_MESSAGE
255 */
256 public static final int STATUS_FAILURE = 1;
257
258 /**
259 * The operation failed because it was blocked. For example, a device policy
260 * may be blocking the operation, a package verifier may have blocked the
261 * operation, or the app may be required for core system operation.
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700262 * <p>
263 * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
264 * specific package blocking the install.
Jeff Sharkeya0907432014-08-15 10:23:11 -0700265 *
266 * @see #EXTRA_STATUS_MESSAGE
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700267 * @see #EXTRA_OTHER_PACKAGE_NAME
Jeff Sharkeya0907432014-08-15 10:23:11 -0700268 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700269 public static final int STATUS_FAILURE_BLOCKED = 2;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700270
271 /**
272 * The operation failed because it was actively aborted. For example, the
273 * user actively declined requested permissions, or the session was
274 * abandoned.
275 *
276 * @see #EXTRA_STATUS_MESSAGE
277 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700278 public static final int STATUS_FAILURE_ABORTED = 3;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700279
280 /**
281 * The operation failed because one or more of the APKs was invalid. For
282 * example, they might be malformed, corrupt, incorrectly signed,
283 * mismatched, etc.
284 *
285 * @see #EXTRA_STATUS_MESSAGE
286 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700287 public static final int STATUS_FAILURE_INVALID = 4;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700288
289 /**
290 * The operation failed because it conflicts (or is inconsistent with) with
291 * another package already installed on the device. For example, an existing
292 * permission, incompatible certificates, etc. The user may be able to
293 * uninstall another app to fix the issue.
294 * <p>
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700295 * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700296 * specific package identified as the cause of the conflict.
Jeff Sharkeya0907432014-08-15 10:23:11 -0700297 *
298 * @see #EXTRA_STATUS_MESSAGE
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700299 * @see #EXTRA_OTHER_PACKAGE_NAME
Jeff Sharkeya0907432014-08-15 10:23:11 -0700300 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700301 public static final int STATUS_FAILURE_CONFLICT = 5;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700302
303 /**
304 * The operation failed because of storage issues. For example, the device
305 * may be running low on space, or external media may be unavailable. The
306 * user may be able to help free space or insert different external media.
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700307 * <p>
308 * The result may also contain {@link #EXTRA_STORAGE_PATH} with the path to
309 * the storage device that caused the failure.
Jeff Sharkeya0907432014-08-15 10:23:11 -0700310 *
311 * @see #EXTRA_STATUS_MESSAGE
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700312 * @see #EXTRA_STORAGE_PATH
Jeff Sharkeya0907432014-08-15 10:23:11 -0700313 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700314 public static final int STATUS_FAILURE_STORAGE = 6;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700315
316 /**
317 * The operation failed because it is fundamentally incompatible with this
318 * device. For example, the app may require a hardware feature that doesn't
319 * exist, it may be missing native code for the ABIs supported by the
320 * device, or it requires a newer SDK version, etc.
321 *
322 * @see #EXTRA_STATUS_MESSAGE
323 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700324 public static final int STATUS_FAILURE_INCOMPATIBLE = 7;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700325
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700326 private final IPackageInstaller mInstaller;
327 private final int mUserId;
328 private final String mInstallerPackageName;
329
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700330 private final ArrayList<SessionCallbackDelegate> mDelegates = new ArrayList<>();
331
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700332 /** {@hide} */
Svet Ganov67882122016-12-11 16:36:34 -0800333 public PackageInstaller(IPackageInstaller installer,
Jeff Sharkeyec55ef02014-07-08 11:28:00 -0700334 String installerPackageName, int userId) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700335 mInstaller = installer;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700336 mInstallerPackageName = installerPackageName;
Jeff Sharkeyec55ef02014-07-08 11:28:00 -0700337 mUserId = userId;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700338 }
339
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700340 /**
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700341 * Create a new session using the given parameters, returning a unique ID
342 * that represents the session. Once created, the session can be opened
343 * multiple times across multiple device boots.
344 * <p>
345 * The system may automatically destroy sessions that have not been
346 * finalized (either committed or abandoned) within a reasonable period of
347 * time, typically on the order of a day.
348 *
349 * @throws IOException if parameters were unsatisfiable, such as lack of
350 * disk space or unavailable media.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700351 * @throws SecurityException when installation services are unavailable,
352 * such as when called from a restricted user.
353 * @throws IllegalArgumentException when {@link SessionParams} is invalid.
Jeff Sharkeyf174c6e2014-08-05 10:42:27 -0700354 * @return positive, non-zero unique ID that represents the created session.
355 * This ID remains consistent across device reboots until the
356 * session is finalized. IDs are not reused during a given boot.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700357 */
Jeff Sharkeya0907432014-08-15 10:23:11 -0700358 public int createSession(@NonNull SessionParams params) throws IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700359 try {
Philip P. Moltmann79c238a2017-12-13 15:59:07 -0800360 final String installerPackage;
361 if (params.installerPackageName == null) {
362 installerPackage = mInstallerPackageName;
363 } else {
364 installerPackage = params.installerPackageName;
365 }
366
367 return mInstaller.createSession(params, installerPackage, mUserId);
Jeff Sharkeya1031142014-07-12 18:09:46 -0700368 } catch (RuntimeException e) {
369 ExceptionUtils.maybeUnwrapIOException(e);
370 throw e;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700371 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700372 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700373 }
374 }
375
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700376 /**
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700377 * Open an existing session to actively perform work. To succeed, the caller
378 * must be the owner of the install session.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700379 *
380 * @throws IOException if parameters were unsatisfiable, such as lack of
381 * disk space or unavailable media.
382 * @throws SecurityException when the caller does not own the session, or
383 * the session is invalid.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700384 */
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700385 public @NonNull Session openSession(int sessionId) throws IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700386 try {
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000387 try {
388 return new Session(mInstaller.openSession(sessionId));
389 } catch (RemoteException e) {
390 throw e.rethrowFromSystemServer();
391 }
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700392 } catch (RuntimeException e) {
393 ExceptionUtils.maybeUnwrapIOException(e);
394 throw e;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700395 }
396 }
397
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700398 /**
399 * Update the icon representing the app being installed in a specific
400 * session. This should be roughly
401 * {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700402 *
403 * @throws SecurityException when the caller does not own the session, or
404 * the session is invalid.
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700405 */
406 public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) {
407 try {
408 mInstaller.updateSessionAppIcon(sessionId, appIcon);
409 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700410 throw e.rethrowFromSystemServer();
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700411 }
412 }
413
414 /**
415 * Update the label representing the app being installed in a specific
416 * session.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700417 *
418 * @throws SecurityException when the caller does not own the session, or
419 * the session is invalid.
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700420 */
421 public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) {
422 try {
423 final String val = (appLabel != null) ? appLabel.toString() : null;
424 mInstaller.updateSessionAppLabel(sessionId, val);
425 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700426 throw e.rethrowFromSystemServer();
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700427 }
428 }
429
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700430 /**
431 * Completely abandon the given session, destroying all staged data and
432 * rendering it invalid. Abandoned sessions will be reported to
433 * {@link SessionCallback} listeners as failures. This is equivalent to
434 * opening the session and calling {@link Session#abandon()}.
435 *
436 * @throws SecurityException when the caller does not own the session, or
437 * the session is invalid.
438 */
Jeff Sharkey381d94b2014-08-24 14:45:56 -0700439 public void abandonSession(int sessionId) {
440 try {
441 mInstaller.abandonSession(sessionId);
442 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700443 throw e.rethrowFromSystemServer();
Jeff Sharkey381d94b2014-08-24 14:45:56 -0700444 }
445 }
446
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700447 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700448 * Return details for a specific session. No special permissions are
449 * required to retrieve these details.
450 *
451 * @return details for the requested session, or {@code null} if the session
452 * does not exist.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700453 */
Jeff Sharkeya0907432014-08-15 10:23:11 -0700454 public @Nullable SessionInfo getSessionInfo(int sessionId) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700455 try {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700456 return mInstaller.getSessionInfo(sessionId);
457 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700458 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700459 }
460 }
461
462 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700463 * Return list of all known install sessions, regardless of the installer.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700464 */
Jeff Sharkeya0907432014-08-15 10:23:11 -0700465 public @NonNull List<SessionInfo> getAllSessions() {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700466 try {
Jeff Sharkey97d47ed2014-10-15 09:19:47 -0700467 return mInstaller.getAllSessions(mUserId).getList();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700468 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700469 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700470 }
471 }
472
473 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700474 * Return list of all known install sessions owned by the calling app.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700475 */
Jeff Sharkeya0907432014-08-15 10:23:11 -0700476 public @NonNull List<SessionInfo> getMySessions() {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700477 try {
Jeff Sharkey97d47ed2014-10-15 09:19:47 -0700478 return mInstaller.getMySessions(mInstallerPackageName, mUserId).getList();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700479 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700480 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700481 }
482 }
483
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700484 /**
Dario Freniaac4ba42018-12-06 15:47:16 +0000485 * Return list of all staged install sessions.
486 */
487 public @NonNull List<SessionInfo> getStagedSessions() {
488 try {
489 // TODO: limit this to the mUserId?
490 return mInstaller.getStagedSessions().getList();
491 } catch (RemoteException e) {
492 throw e.rethrowFromSystemServer();
493 }
494 }
495
496 /**
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700497 * Uninstall the given package, removing it completely from the device. This
Tony Mak366ee622018-02-12 17:52:34 +0000498 * method is available to:
499 * <ul>
500 * <li>the current "installer of record" for the package
501 * <li>the device owner
502 * <li>the affiliated profile owner
Rubin Xufd4a3b42018-12-05 16:03:27 +0000503 * <li>the device owner delegated app with
504 * {@link android.app.admin.DevicePolicyManager#DELEGATION_PACKAGE_INSTALLATION}
Tony Mak366ee622018-02-12 17:52:34 +0000505 * </ul>
Svet Ganov67882122016-12-11 16:36:34 -0800506 *
507 * @param packageName The package to uninstall.
508 * @param statusReceiver Where to deliver the result.
Tony Mak366ee622018-02-12 17:52:34 +0000509 *
510 * @see android.app.admin.DevicePolicyManager
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700511 */
Philip P. Moltmannd9bb39a2017-09-05 12:41:15 -0700512 @RequiresPermission(anyOf = {
513 Manifest.permission.DELETE_PACKAGES,
514 Manifest.permission.REQUEST_DELETE_PACKAGES})
Jeff Sharkeya0907432014-08-15 10:23:11 -0700515 public void uninstall(@NonNull String packageName, @NonNull IntentSender statusReceiver) {
Todd Kennedycda831f2017-05-16 10:54:33 -0700516 uninstall(packageName, 0 /*flags*/, statusReceiver);
517 }
518
519 /**
520 * Uninstall the given package, removing it completely from the device. This
521 * method is only available to the current "installer of record" for the
522 * package.
523 *
524 * @param packageName The package to uninstall.
525 * @param flags Flags for uninstall.
526 * @param statusReceiver Where to deliver the result.
527 *
528 * @hide
529 */
530 public void uninstall(@NonNull String packageName, @DeleteFlags int flags,
531 @NonNull IntentSender statusReceiver) {
532 uninstall(new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
533 flags, statusReceiver);
Svet Ganov67882122016-12-11 16:36:34 -0800534 }
535
536 /**
537 * Uninstall the given package with a specific version code, removing it
Tony Mak366ee622018-02-12 17:52:34 +0000538 * completely from the device. If the version code of the package
Svet Ganov67882122016-12-11 16:36:34 -0800539 * does not match the one passed in the versioned package argument this
540 * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to
541 * uninstall the latest version of the package.
Tony Mak366ee622018-02-12 17:52:34 +0000542 * <p>
543 * This method is available to:
544 * <ul>
545 * <li>the current "installer of record" for the package
546 * <li>the device owner
547 * <li>the affiliated profile owner
548 * </ul>
Svet Ganov67882122016-12-11 16:36:34 -0800549 *
550 * @param versionedPackage The versioned package to uninstall.
551 * @param statusReceiver Where to deliver the result.
Tony Mak366ee622018-02-12 17:52:34 +0000552 *
553 * @see android.app.admin.DevicePolicyManager
Svet Ganov67882122016-12-11 16:36:34 -0800554 */
Philip P. Moltmannd9bb39a2017-09-05 12:41:15 -0700555 @RequiresPermission(anyOf = {
556 Manifest.permission.DELETE_PACKAGES,
557 Manifest.permission.REQUEST_DELETE_PACKAGES})
Todd Kennedycda831f2017-05-16 10:54:33 -0700558 public void uninstall(@NonNull VersionedPackage versionedPackage,
559 @NonNull IntentSender statusReceiver) {
560 uninstall(versionedPackage, 0 /*flags*/, statusReceiver);
561 }
562
563 /**
564 * Uninstall the given package with a specific version code, removing it
565 * completely from the device. This method is only available to the current
566 * "installer of record" for the package. If the version code of the package
567 * does not match the one passed in the versioned package argument this
568 * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to
569 * uninstall the latest version of the package.
570 *
571 * @param versionedPackage The versioned package to uninstall.
572 * @param flags Flags for uninstall.
573 * @param statusReceiver Where to deliver the result.
574 *
575 * @hide
576 */
Svet Ganov67882122016-12-11 16:36:34 -0800577 @RequiresPermission(anyOf = {
578 Manifest.permission.DELETE_PACKAGES,
579 Manifest.permission.REQUEST_DELETE_PACKAGES})
Todd Kennedycda831f2017-05-16 10:54:33 -0700580 public void uninstall(@NonNull VersionedPackage versionedPackage, @DeleteFlags int flags,
Svet Ganov67882122016-12-11 16:36:34 -0800581 @NonNull IntentSender statusReceiver) {
582 Preconditions.checkNotNull(versionedPackage, "versionedPackage cannot be null");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700583 try {
Svet Ganov67882122016-12-11 16:36:34 -0800584 mInstaller.uninstall(versionedPackage, mInstallerPackageName,
Todd Kennedycda831f2017-05-16 10:54:33 -0700585 flags, statusReceiver, mUserId);
Jeff Sharkeybb580672014-07-10 12:10:25 -0700586 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700587 throw e.rethrowFromSystemServer();
Jeff Sharkeybb580672014-07-10 12:10:25 -0700588 }
589 }
590
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700591 /** {@hide} */
Todd Kennedy04cc1912017-03-03 13:05:12 -0800592 @SystemApi
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600593 @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700594 public void setPermissionsResult(int sessionId, boolean accepted) {
595 try {
596 mInstaller.setPermissionsResult(sessionId, accepted);
597 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700598 throw e.rethrowFromSystemServer();
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700599 }
600 }
601
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700602 /**
603 * Events for observing session lifecycle.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700604 * <p>
605 * A typical session lifecycle looks like this:
606 * <ul>
607 * <li>An installer creates a session to indicate pending app delivery. All
608 * install details are available at this point.
609 * <li>The installer opens the session to deliver APK data. Note that a
610 * session may be opened and closed multiple times as network connectivity
611 * changes. The installer may deliver periodic progress updates.
612 * <li>The installer commits or abandons the session, resulting in the
613 * session being finished.
614 * </ul>
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700615 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700616 public static abstract class SessionCallback {
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700617 /**
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700618 * New session has been created. Details about the session can be
619 * obtained from {@link PackageInstaller#getSessionInfo(int)}.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700620 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700621 public abstract void onCreated(int sessionId);
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700622
623 /**
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700624 * Badging details for an existing session has changed. For example, the
625 * app icon or label has been updated.
626 */
627 public abstract void onBadgingChanged(int sessionId);
628
629 /**
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700630 * Active state for session has been changed.
631 * <p>
632 * A session is considered active whenever there is ongoing forward
633 * progress being made, such as the installer holding an open
634 * {@link Session} instance while streaming data into place, or the
635 * system optimizing code as the result of
636 * {@link Session#commit(IntentSender)}.
637 * <p>
638 * If the installer closes the {@link Session} without committing, the
639 * session is considered inactive until the installer opens the session
640 * again.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700641 */
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700642 public abstract void onActiveChanged(int sessionId, boolean active);
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700643
644 /**
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700645 * Progress for given session has been updated.
646 * <p>
647 * Note that this progress may not directly correspond to the value
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700648 * reported by
649 * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
650 * system may carve out a portion of the overall progress to represent
651 * its own internal installation work.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700652 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700653 public abstract void onProgressChanged(int sessionId, float progress);
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700654
655 /**
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700656 * Session has completely finished, either with success or failure.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700657 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700658 public abstract void onFinished(int sessionId, boolean success);
Jeff Sharkeybb580672014-07-10 12:10:25 -0700659 }
660
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700661 /** {@hide} */
662 private static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub implements
663 Handler.Callback {
664 private static final int MSG_SESSION_CREATED = 1;
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700665 private static final int MSG_SESSION_BADGING_CHANGED = 2;
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700666 private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700667 private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700668 private static final int MSG_SESSION_FINISHED = 5;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700669
670 final SessionCallback mCallback;
671 final Handler mHandler;
672
673 public SessionCallbackDelegate(SessionCallback callback, Looper looper) {
674 mCallback = callback;
675 mHandler = new Handler(looper, this);
676 }
677
678 @Override
679 public boolean handleMessage(Message msg) {
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700680 final int sessionId = msg.arg1;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700681 switch (msg.what) {
682 case MSG_SESSION_CREATED:
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700683 mCallback.onCreated(sessionId);
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700684 return true;
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700685 case MSG_SESSION_BADGING_CHANGED:
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700686 mCallback.onBadgingChanged(sessionId);
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700687 return true;
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700688 case MSG_SESSION_ACTIVE_CHANGED:
689 final boolean active = msg.arg2 != 0;
690 mCallback.onActiveChanged(sessionId, active);
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700691 return true;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700692 case MSG_SESSION_PROGRESS_CHANGED:
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700693 mCallback.onProgressChanged(sessionId, (float) msg.obj);
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700694 return true;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700695 case MSG_SESSION_FINISHED:
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700696 mCallback.onFinished(sessionId, msg.arg2 != 0);
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700697 return true;
698 }
699 return false;
700 }
701
702 @Override
703 public void onSessionCreated(int sessionId) {
704 mHandler.obtainMessage(MSG_SESSION_CREATED, sessionId, 0).sendToTarget();
705 }
706
707 @Override
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700708 public void onSessionBadgingChanged(int sessionId) {
709 mHandler.obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, 0).sendToTarget();
710 }
711
712 @Override
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700713 public void onSessionActiveChanged(int sessionId, boolean active) {
714 mHandler.obtainMessage(MSG_SESSION_ACTIVE_CHANGED, sessionId, active ? 1 : 0)
715 .sendToTarget();
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700716 }
717
718 @Override
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700719 public void onSessionProgressChanged(int sessionId, float progress) {
720 mHandler.obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, 0, progress)
721 .sendToTarget();
722 }
723
724 @Override
725 public void onSessionFinished(int sessionId, boolean success) {
726 mHandler.obtainMessage(MSG_SESSION_FINISHED, sessionId, success ? 1 : 0)
727 .sendToTarget();
Jeff Sharkeybb580672014-07-10 12:10:25 -0700728 }
729 }
730
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700731 /** {@hide} */
732 @Deprecated
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700733 public void addSessionCallback(@NonNull SessionCallback callback) {
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700734 registerSessionCallback(callback);
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700735 }
736
737 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700738 * Register to watch for session lifecycle events. No special permissions
739 * are required to watch for these events.
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700740 */
741 public void registerSessionCallback(@NonNull SessionCallback callback) {
742 registerSessionCallback(callback, new Handler());
743 }
744
745 /** {@hide} */
746 @Deprecated
747 public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
748 registerSessionCallback(callback, handler);
749 }
750
751 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700752 * Register to watch for session lifecycle events. No special permissions
753 * are required to watch for these events.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700754 *
755 * @param handler to dispatch callback events through, otherwise uses
756 * calling thread.
757 */
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700758 public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700759 synchronized (mDelegates) {
760 final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
761 handler.getLooper());
762 try {
763 mInstaller.registerCallback(delegate, mUserId);
764 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700765 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700766 }
767 mDelegates.add(delegate);
768 }
769 }
770
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700771 /** {@hide} */
772 @Deprecated
773 public void removeSessionCallback(@NonNull SessionCallback callback) {
774 unregisterSessionCallback(callback);
775 }
776
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700777 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700778 * Unregister a previously registered callback.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700779 */
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700780 public void unregisterSessionCallback(@NonNull SessionCallback callback) {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700781 synchronized (mDelegates) {
782 for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
783 final SessionCallbackDelegate delegate = i.next();
784 if (delegate.mCallback == callback) {
785 try {
786 mInstaller.unregisterCallback(delegate);
787 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700788 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700789 }
790 i.remove();
791 }
792 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700793 }
794 }
795
796 /**
797 * An installation that is being actively staged. For an install to succeed,
798 * all existing and new packages must have identical package names, version
799 * codes, and signing certificates.
800 * <p>
801 * A session may contain any number of split packages. If the application
802 * does not yet exist, this session must include a base package.
803 * <p>
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700804 * If an APK included in this session is already defined by the existing
805 * installation (for example, the same split name), the APK in this session
806 * will replace the existing APK.
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000807 * <p>
808 * In such a case that multiple packages need to be commited simultaneously,
809 * multiple sessions can be referenced by a single multi-package session.
810 * This session is created with no package name and calling
811 * {@link SessionParams#setMultiPackage()} with {@code true}. The
812 * individual session IDs can be added with {@link #addChildSessionId(int)}
813 * and commit of the multi-package session will result in all child sessions
814 * being committed atomically.
Dario Freniaac4ba42018-12-06 15:47:16 +0000815 * <p>
816 * If a package requires to be installed only at reboot, the session should
817 * be marked as a staged session by calling {@link SessionParams#setStaged()}
818 * with {@code true}. This can also apply to a multi-package session, in
819 * which case all the packages in the session will be applied at reboot.
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700820 */
Jeff Sharkeyec55ef02014-07-08 11:28:00 -0700821 public static class Session implements Closeable {
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000822 /** {@hide} */
823 protected final IPackageInstallerSession mSession;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700824
825 /** {@hide} */
826 public Session(IPackageInstallerSession session) {
827 mSession = session;
828 }
829
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700830 /** {@hide} */
831 @Deprecated
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700832 public void setProgress(float progress) {
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700833 setStagingProgress(progress);
834 }
835
836 /**
837 * Set current progress of staging this session. Valid values are
838 * anywhere between 0 and 1.
839 * <p>
840 * Note that this progress may not directly correspond to the value
841 * reported by {@link SessionCallback#onProgressChanged(int, float)}, as
842 * the system may carve out a portion of the overall progress to
843 * represent its own internal installation work.
844 */
845 public void setStagingProgress(float progress) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700846 try {
Jeff Sharkeya1031142014-07-12 18:09:46 -0700847 mSession.setClientProgress(progress);
848 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700849 throw e.rethrowFromSystemServer();
Jeff Sharkeya1031142014-07-12 18:09:46 -0700850 }
851 }
852
853 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100854 @UnsupportedAppUsage
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700855 public void addProgress(float progress) {
Jeff Sharkeya1031142014-07-12 18:09:46 -0700856 try {
857 mSession.addClientProgress(progress);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700858 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700859 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700860 }
861 }
862
Jeff Sharkey78cc3402014-05-22 10:52:49 -0700863 /**
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700864 * Open a stream to write an APK file into the session.
865 * <p>
866 * The returned stream will start writing data at the requested offset
867 * in the underlying file, which can be used to resume a partially
868 * written file. If a valid file length is specified, the system will
869 * preallocate the underlying disk space to optimize placement on disk.
870 * It's strongly recommended to provide a valid file length when known.
871 * <p>
872 * You can write data into the returned stream, optionally call
873 * {@link #fsync(OutputStream)} as needed to ensure bytes have been
874 * persisted to disk, and then close when finished. All streams must be
Jeff Sharkeya0907432014-08-15 10:23:11 -0700875 * closed before calling {@link #commit(IntentSender)}.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700876 *
877 * @param name arbitrary, unique name of your choosing to identify the
878 * APK being written. You can open a file again for
879 * additional writes (such as after a reboot) by using the
880 * same name. This name is only meaningful within the context
881 * of a single install session.
882 * @param offsetBytes offset into the file to begin writing at, or 0 to
883 * start at the beginning of the file.
884 * @param lengthBytes total size of the file being written, used to
885 * preallocate the underlying disk space, or -1 if unknown.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700886 * The system may clear various caches as needed to allocate
887 * this space.
888 * @throws IOException if trouble opening the file for writing, such as
889 * lack of disk space or unavailable media.
890 * @throws SecurityException if called after the session has been
Philip P. Moltmann7460c592017-08-08 20:07:11 +0000891 * sealed or abandoned
Jeff Sharkey78cc3402014-05-22 10:52:49 -0700892 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700893 public @NonNull OutputStream openWrite(@NonNull String name, long offsetBytes,
894 long lengthBytes) throws IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700895 try {
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700896 if (ENABLE_REVOCABLE_FD) {
897 return new ParcelFileDescriptor.AutoCloseOutputStream(
898 mSession.openWrite(name, offsetBytes, lengthBytes));
899 } else {
900 final ParcelFileDescriptor clientSocket = mSession.openWrite(name,
901 offsetBytes, lengthBytes);
902 return new FileBridge.FileBridgeOutputStream(clientSocket);
903 }
Jeff Sharkeya1031142014-07-12 18:09:46 -0700904 } catch (RuntimeException e) {
905 ExceptionUtils.maybeUnwrapIOException(e);
906 throw e;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700907 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700908 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700909 }
Jeff Sharkey0451de62018-02-02 11:27:21 -0700910 }
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700911
Jeff Sharkey0451de62018-02-02 11:27:21 -0700912 /** {@hide} */
913 public void write(@NonNull String name, long offsetBytes, long lengthBytes,
914 @NonNull ParcelFileDescriptor fd) throws IOException {
915 try {
916 mSession.write(name, offsetBytes, lengthBytes, fd);
917 } catch (RuntimeException e) {
918 ExceptionUtils.maybeUnwrapIOException(e);
919 throw e;
920 } catch (RemoteException e) {
921 throw e.rethrowFromSystemServer();
922 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700923 }
924
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700925 /**
926 * Ensure that any outstanding data for given stream has been committed
927 * to disk. This is only valid for streams returned from
928 * {@link #openWrite(String, long, long)}.
929 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700930 public void fsync(@NonNull OutputStream out) throws IOException {
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700931 if (ENABLE_REVOCABLE_FD) {
932 if (out instanceof ParcelFileDescriptor.AutoCloseOutputStream) {
933 try {
934 Os.fsync(((ParcelFileDescriptor.AutoCloseOutputStream) out).getFD());
935 } catch (ErrnoException e) {
936 throw e.rethrowAsIOException();
937 }
938 } else {
939 throw new IllegalArgumentException("Unrecognized stream");
940 }
Jeff Sharkeya1031142014-07-12 18:09:46 -0700941 } else {
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700942 if (out instanceof FileBridge.FileBridgeOutputStream) {
943 ((FileBridge.FileBridgeOutputStream) out).fsync();
944 } else {
945 throw new IllegalArgumentException("Unrecognized stream");
946 }
Jeff Sharkeya1031142014-07-12 18:09:46 -0700947 }
948 }
949
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700950 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -0700951 * Return all APK names contained in this session.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700952 * <p>
953 * This returns all names which have been previously written through
954 * {@link #openWrite(String, long, long)} as part of this session.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700955 *
956 * @throws SecurityException if called after the session has been
957 * committed or abandoned.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700958 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700959 public @NonNull String[] getNames() throws IOException {
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700960 try {
Jeff Sharkeya0907432014-08-15 10:23:11 -0700961 return mSession.getNames();
Jeff Sharkey742e7902014-08-16 19:09:13 -0700962 } catch (RuntimeException e) {
963 ExceptionUtils.maybeUnwrapIOException(e);
964 throw e;
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700965 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700966 throw e.rethrowFromSystemServer();
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700967 }
968 }
969
970 /**
971 * Open a stream to read an APK file from the session.
972 * <p>
973 * This is only valid for names which have been previously written
974 * through {@link #openWrite(String, long, long)} as part of this
975 * session. For example, this stream may be used to calculate a
976 * {@link MessageDigest} of a written APK before committing.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700977 *
978 * @throws SecurityException if called after the session has been
979 * committed or abandoned.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700980 */
981 public @NonNull InputStream openRead(@NonNull String name) throws IOException {
982 try {
983 final ParcelFileDescriptor pfd = mSession.openRead(name);
984 return new ParcelFileDescriptor.AutoCloseInputStream(pfd);
985 } catch (RuntimeException e) {
986 ExceptionUtils.maybeUnwrapIOException(e);
987 throw e;
988 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700989 throw e.rethrowFromSystemServer();
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700990 }
991 }
992
993 /**
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800994 * Removes a split.
995 * <p>
996 * Split removals occur prior to adding new APKs. If upgrading a feature
997 * split, it is not expected nor desirable to remove the split prior to
998 * upgrading.
999 * <p>
1000 * When split removal is bundled with new APKs, the packageName must be
1001 * identical.
1002 */
1003 public void removeSplit(@NonNull String splitName) throws IOException {
1004 try {
1005 mSession.removeSplit(splitName);
1006 } catch (RuntimeException e) {
1007 ExceptionUtils.maybeUnwrapIOException(e);
1008 throw e;
1009 } catch (RemoteException e) {
1010 throw e.rethrowFromSystemServer();
1011 }
1012 }
1013
1014 /**
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001015 * Attempt to commit everything staged in this session. This may require
1016 * user intervention, and so it may not happen immediately. The final
1017 * result of the commit will be reported through the given callback.
1018 * <p>
Todd Kennedy04cc1912017-03-03 13:05:12 -08001019 * Once this method is called, the session is sealed and no additional
1020 * mutations may be performed on the session. If the device reboots
1021 * before the session has been finalized, you may commit the session again.
Tony Mak366ee622018-02-12 17:52:34 +00001022 * <p>
1023 * If the installer is the device owner or the affiliated profile owner, there will be no
1024 * user intervention.
Jeff Sharkey77d218e2014-09-06 12:20:37 -07001025 *
Philip P. Moltmann2fe7dee2018-09-14 08:45:42 -07001026 * @param statusReceiver Called when the state of the session changes. Intents
1027 * sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
1028 * individual status codes on how to handle them.
1029 *
Jeff Sharkey77d218e2014-09-06 12:20:37 -07001030 * @throws SecurityException if streams opened through
1031 * {@link #openWrite(String, long, long)} are still open.
Tony Mak366ee622018-02-12 17:52:34 +00001032 *
1033 * @see android.app.admin.DevicePolicyManager
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001034 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001035 public void commit(@NonNull IntentSender statusReceiver) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001036 try {
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001037 mSession.commit(statusReceiver, false);
1038 } catch (RemoteException e) {
1039 throw e.rethrowFromSystemServer();
1040 }
1041 }
1042
1043 /**
1044 * Attempt to commit a session that has been {@link #transfer(String) transferred}.
1045 *
1046 * <p>If the device reboots before the session has been finalized, you may commit the
1047 * session again.
1048 *
1049 * <p>The caller of this method is responsible to ensure the safety of the session. As the
1050 * session was created by another - usually less trusted - app, it is paramount that before
1051 * committing <u>all</u> public and system {@link SessionInfo properties of the session}
1052 * and <u>all</u> {@link #openRead(String) APKs} are verified by the caller. It might happen
1053 * that new properties are added to the session with a new API revision. In this case the
1054 * callers need to be updated.
1055 *
Philip P. Moltmann2fe7dee2018-09-14 08:45:42 -07001056 * @param statusReceiver Called when the state of the session changes. Intents
1057 * sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
1058 * individual status codes on how to handle them.
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001059 *
1060 * @hide
1061 */
1062 @SystemApi
1063 @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
1064 public void commitTransferred(@NonNull IntentSender statusReceiver) {
1065 try {
1066 mSession.commit(statusReceiver, true);
1067 } catch (RemoteException e) {
1068 throw e.rethrowFromSystemServer();
1069 }
1070 }
1071
1072 /**
1073 * Transfer the session to a new owner.
1074 * <p>
1075 * Only sessions that update the installing app can be transferred.
1076 * <p>
1077 * After the transfer to a package with a different uid all method calls on the session
1078 * will cause {@link SecurityException}s.
1079 * <p>
1080 * Once this method is called, the session is sealed and no additional mutations beside
1081 * committing it may be performed on the session.
1082 *
1083 * @param packageName The package of the new owner. Needs to hold the INSTALL_PACKAGES
1084 * permission.
1085 *
1086 * @throws PackageManager.NameNotFoundException if the new owner could not be found.
1087 * @throws SecurityException if called after the session has been committed or abandoned.
1088 * @throws SecurityException if the session does not update the original installer
1089 * @throws SecurityException if streams opened through
1090 * {@link #openWrite(String, long, long) are still open.
1091 */
1092 public void transfer(@NonNull String packageName)
1093 throws PackageManager.NameNotFoundException {
1094 Preconditions.checkNotNull(packageName);
1095
1096 try {
1097 mSession.transfer(packageName);
1098 } catch (ParcelableException e) {
1099 e.maybeRethrow(PackageManager.NameNotFoundException.class);
1100 throw new RuntimeException(e);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001101 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001102 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001103 }
1104 }
1105
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001106 /**
1107 * Release this session object. You can open the session again if it
1108 * hasn't been finalized.
1109 */
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001110 @Override
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001111 public void close() {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001112 try {
1113 mSession.close();
1114 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001115 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001116 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001117 }
1118
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001119 /**
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001120 * Completely abandon this session, destroying all staged data and
Jeff Sharkey77d218e2014-09-06 12:20:37 -07001121 * rendering it invalid. Abandoned sessions will be reported to
1122 * {@link SessionCallback} listeners as failures. This is equivalent to
1123 * opening the session and calling {@link Session#abandon()}.
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001124 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001125 public void abandon() {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001126 try {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001127 mSession.abandon();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001128 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001129 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001130 }
1131 }
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001132
1133 /**
1134 * @return {@code true} if this session will commit more than one package when it is
1135 * committed.
1136 */
1137 public boolean isMultiPackage() {
1138 try {
1139 return mSession.isMultiPackage();
1140 } catch (RemoteException e) {
1141 throw e.rethrowFromSystemServer();
1142 }
1143 }
1144
1145 /**
Dario Freniaac4ba42018-12-06 15:47:16 +00001146 * @return {@code true} if this session will be staged and applied at next reboot.
1147 */
1148 public boolean isStaged() {
1149 try {
1150 return mSession.isStaged();
1151 } catch (RemoteException e) {
1152 throw e.rethrowFromSystemServer();
1153 }
1154 }
1155
1156 /**
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001157 * @return the session ID of the multi-package session that this belongs to or
1158 * {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session.
1159 */
1160 public int getParentSessionId() {
1161 try {
1162 return mSession.getParentSessionId();
1163 } catch (RemoteException e) {
1164 throw e.rethrowFromSystemServer();
1165 }
1166 }
1167
1168 /**
1169 * @return the set of session IDs that will be committed atomically when this session is
1170 * committed if this is a multi-package session or null if none exist.
1171 */
1172 @NonNull
1173 public int[] getChildSessionIds() {
1174 try {
1175 return mSession.getChildSessionIds();
1176 } catch (RemoteException e) {
1177 throw e.rethrowFromSystemServer();
1178 }
1179 }
1180
1181 /**
1182 * Adds a session ID to the set of sessions that will be committed atomically
1183 * when this session is committed.
1184 *
1185 * @param sessionId the session ID to add to this multi-package session.
1186 */
1187 public void addChildSessionId(int sessionId) {
1188 try {
1189 mSession.addChildSessionId(sessionId);
1190 } catch (RemoteException e) {
1191 throw e.rethrowFromSystemServer();
1192 }
1193 }
1194
1195 /**
1196 * Removes a session ID from the set of sessions that will be committed
1197 * atomically when this session is committed.
1198 *
1199 * @param sessionId the session ID to remove from this multi-package session.
1200 */
1201 public void removeChildSessionId(int sessionId) {
1202 try {
1203 mSession.removeChildSessionId(sessionId);
1204 } catch (RemoteException e) {
1205 throw e.rethrowFromSystemServer();
1206 }
1207 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001208 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001209
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001210 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001211 * Parameters for creating a new {@link PackageInstaller.Session}.
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001212 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001213 public static class SessionParams implements Parcelable {
1214
1215 /** {@hide} */
1216 public static final int MODE_INVALID = -1;
Jeff Sharkeyf0600952014-08-07 17:31:53 -07001217
1218 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001219 * Mode for an install session whose staged APKs should fully replace any
1220 * existing APKs for the target app.
Jeff Sharkeyf0600952014-08-07 17:31:53 -07001221 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001222 public static final int MODE_FULL_INSTALL = 1;
Jeff Sharkeyf0600952014-08-07 17:31:53 -07001223
1224 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001225 * Mode for an install session that should inherit any existing APKs for the
1226 * target app, unless they have been explicitly overridden (based on split
1227 * name) by the session. For example, this can be used to add one or more
1228 * split APKs to an existing installation.
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07001229 * <p>
Jeff Sharkeya0907432014-08-15 10:23:11 -07001230 * If there are no existing APKs for the target app, this behaves like
1231 * {@link #MODE_FULL_INSTALL}.
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07001232 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001233 public static final int MODE_INHERIT_EXISTING = 2;
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07001234
Jeff Sharkeya0907432014-08-15 10:23:11 -07001235 /** {@hide} */
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001236 public static final int UID_UNKNOWN = -1;
1237
1238 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001239 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001240 public int mode = MODE_INVALID;
1241 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001242 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001243 public int installFlags;
1244 /** {@hide} */
1245 public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
1246 /** {@hide} */
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001247 public @InstallReason int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
Bartosz Fabianowskia34f53f2017-01-11 18:08:47 +01001248 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001249 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001250 public long sizeBytes = -1;
1251 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001252 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001253 public String appPackageName;
1254 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001255 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001256 public Bitmap appIcon;
1257 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001258 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001259 public String appLabel;
1260 /** {@hide} */
Jeff Sharkey02bd7842014-10-06 15:14:27 -07001261 public long appIconLastModified = -1;
1262 /** {@hide} */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001263 public Uri originatingUri;
1264 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001265 @UnsupportedAppUsage
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001266 public int originatingUid = UID_UNKNOWN;
1267 /** {@hide} */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001268 public Uri referrerUri;
1269 /** {@hide} */
1270 public String abiOverride;
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001271 /** {@hide} */
1272 public String volumeUuid;
Svet Ganov7121e182015-07-13 22:38:12 -07001273 /** {@hide} */
1274 public String[] grantedRuntimePermissions;
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001275 /** {@hide} */
1276 public String installerPackageName;
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001277 /** {@hide} */
1278 public boolean isMultiPackage;
Dario Freniaac4ba42018-12-06 15:47:16 +00001279 /** {@hide} */
1280 public boolean isStaged;
Jeff Sharkeybb580672014-07-10 12:10:25 -07001281
Jeff Sharkeya0907432014-08-15 10:23:11 -07001282 /**
1283 * Construct parameters for a new package install session.
1284 *
1285 * @param mode one of {@link #MODE_FULL_INSTALL} or
1286 * {@link #MODE_INHERIT_EXISTING} describing how the session
1287 * should interact with an existing app.
1288 */
1289 public SessionParams(int mode) {
1290 this.mode = mode;
1291 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001292
Jeff Sharkeya0907432014-08-15 10:23:11 -07001293 /** {@hide} */
1294 public SessionParams(Parcel source) {
1295 mode = source.readInt();
1296 installFlags = source.readInt();
1297 installLocation = source.readInt();
Bartosz Fabianowskia34f53f2017-01-11 18:08:47 +01001298 installReason = source.readInt();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001299 sizeBytes = source.readLong();
1300 appPackageName = source.readString();
1301 appIcon = source.readParcelable(null);
1302 appLabel = source.readString();
1303 originatingUri = source.readParcelable(null);
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001304 originatingUid = source.readInt();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001305 referrerUri = source.readParcelable(null);
1306 abiOverride = source.readString();
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001307 volumeUuid = source.readString();
Svet Ganov7121e182015-07-13 22:38:12 -07001308 grantedRuntimePermissions = source.readStringArray();
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001309 installerPackageName = source.readString();
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001310 isMultiPackage = source.readBoolean();
Dario Freniaac4ba42018-12-06 15:47:16 +00001311 isStaged = source.readBoolean();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001312 }
1313
1314 /**
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001315 * Check if there are hidden options set.
1316 *
1317 * <p>Hidden options are those options that cannot be verified via public or system-api
1318 * methods on {@link SessionInfo}.
1319 *
1320 * @return {@code true} if any hidden option is set.
1321 *
1322 * @hide
1323 */
1324 public boolean areHiddenOptionsSet() {
1325 return (installFlags & (PackageManager.INSTALL_ALLOW_DOWNGRADE
1326 | PackageManager.INSTALL_DONT_KILL_APP
1327 | PackageManager.INSTALL_INSTANT_APP
1328 | PackageManager.INSTALL_FULL_APP
1329 | PackageManager.INSTALL_VIRTUAL_PRELOAD
1330 | PackageManager.INSTALL_ALLOCATE_AGGRESSIVE)) != installFlags
1331 || abiOverride != null || volumeUuid != null;
1332 }
1333
1334 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001335 * Provide value of {@link PackageInfo#installLocation}, which may be used
1336 * to determine where the app will be staged. Defaults to
1337 * {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}.
1338 */
1339 public void setInstallLocation(int installLocation) {
1340 this.installLocation = installLocation;
1341 }
1342
1343 /**
1344 * Optionally indicate the total size (in bytes) of all APKs that will be
1345 * delivered in this session. The system may use this to ensure enough disk
1346 * space exists before proceeding, or to estimate container size for
1347 * installations living on external storage.
1348 *
1349 * @see PackageInfo#INSTALL_LOCATION_AUTO
1350 * @see PackageInfo#INSTALL_LOCATION_PREFER_EXTERNAL
1351 */
1352 public void setSize(long sizeBytes) {
1353 this.sizeBytes = sizeBytes;
1354 }
1355
1356 /**
1357 * Optionally set the package name of the app being installed. It's strongly
1358 * recommended that you provide this value when known, so that observers can
1359 * communicate installing apps to users.
1360 * <p>
1361 * If the APKs staged in the session aren't consistent with this package
1362 * name, the install will fail. Regardless of this value, all APKs in the
1363 * app must have the same package name.
1364 */
1365 public void setAppPackageName(@Nullable String appPackageName) {
1366 this.appPackageName = appPackageName;
1367 }
1368
1369 /**
1370 * Optionally set an icon representing the app being installed. This should
1371 * be roughly {@link ActivityManager#getLauncherLargeIconSize()} in both
1372 * dimensions.
1373 */
1374 public void setAppIcon(@Nullable Bitmap appIcon) {
1375 this.appIcon = appIcon;
1376 }
1377
1378 /**
1379 * Optionally set a label representing the app being installed.
1380 */
1381 public void setAppLabel(@Nullable CharSequence appLabel) {
1382 this.appLabel = (appLabel != null) ? appLabel.toString() : null;
1383 }
1384
1385 /**
Todd Kennedy1ed6b872016-03-10 10:07:00 -08001386 * Optionally set the URI where this package was downloaded from. This is
1387 * informational and may be used as a signal for anti-malware purposes.
Jeff Sharkeya0907432014-08-15 10:23:11 -07001388 *
1389 * @see Intent#EXTRA_ORIGINATING_URI
1390 */
1391 public void setOriginatingUri(@Nullable Uri originatingUri) {
1392 this.originatingUri = originatingUri;
1393 }
1394
1395 /**
Nikolas Bravo62831002017-11-07 21:07:15 +00001396 * Sets the UID that initiated the package installation. This is informational
Todd Kennedy1ed6b872016-03-10 10:07:00 -08001397 * and may be used as a signal for anti-malware purposes.
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001398 */
1399 public void setOriginatingUid(int originatingUid) {
1400 this.originatingUid = originatingUid;
1401 }
1402
1403 /**
Todd Kennedy1ed6b872016-03-10 10:07:00 -08001404 * Optionally set the URI that referred you to install this package. This is
1405 * informational and may be used as a signal for anti-malware purposes.
Jeff Sharkeya0907432014-08-15 10:23:11 -07001406 *
1407 * @see Intent#EXTRA_REFERRER
1408 */
1409 public void setReferrerUri(@Nullable Uri referrerUri) {
1410 this.referrerUri = referrerUri;
1411 }
1412
Svet Ganov7121e182015-07-13 22:38:12 -07001413 /**
1414 * Sets which runtime permissions to be granted to the package at installation.
Svet Ganov7121e182015-07-13 22:38:12 -07001415 *
1416 * @param permissions The permissions to grant or null to grant all runtime
1417 * permissions.
1418 *
1419 * @hide
1420 */
1421 @SystemApi
1422 @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS)
1423 public void setGrantedRuntimePermissions(String[] permissions) {
1424 installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
1425 this.grantedRuntimePermissions = permissions;
1426 }
1427
Richard Uhlerb29f1452018-09-12 16:38:15 +01001428 /**
1429 * Request that rollbacks be enabled for the given upgrade.
Richard Uhlerc739c8c2018-12-12 11:03:34 +00001430 * @hide
Richard Uhlerb29f1452018-09-12 16:38:15 +01001431 */
Richard Uhlerc739c8c2018-12-12 11:03:34 +00001432 @SystemApi
Richard Uhlerb29f1452018-09-12 16:38:15 +01001433 public void setEnableRollback() {
1434 installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
1435 }
1436
Jeff Sharkeya0907432014-08-15 10:23:11 -07001437 /** {@hide} */
Todd Kennedyc84d1ab2016-03-11 11:37:17 -08001438 @SystemApi
Todd Kennedy948b7022016-03-14 14:29:52 -07001439 public void setAllowDowngrade(boolean allowDowngrade) {
1440 if (allowDowngrade) {
1441 installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
1442 } else {
1443 installFlags &= ~PackageManager.INSTALL_ALLOW_DOWNGRADE;
1444 }
Todd Kennedyc84d1ab2016-03-11 11:37:17 -08001445 }
1446
1447 /** {@hide} */
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001448 public void setInstallFlagsForcePermissionPrompt() {
1449 installFlags |= PackageManager.INSTALL_FORCE_PERMISSION_PROMPT;
1450 }
1451
1452 /** {@hide} */
Todd Kennedy24ca5c62016-03-16 15:42:01 -07001453 @SystemApi
1454 public void setDontKillApp(boolean dontKillApp) {
1455 if (dontKillApp) {
1456 installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
1457 } else {
1458 installFlags &= ~PackageManager.INSTALL_DONT_KILL_APP;
1459 }
Todd Kennedy39bfee52016-02-24 10:28:21 -08001460 }
1461
1462 /** {@hide} */
Todd Kennedyb7717682016-11-30 15:41:21 -08001463 @SystemApi
1464 public void setInstallAsInstantApp(boolean isInstantApp) {
1465 if (isInstantApp) {
Todd Kennedybe0b8892017-02-15 14:13:52 -08001466 installFlags |= PackageManager.INSTALL_INSTANT_APP;
1467 installFlags &= ~PackageManager.INSTALL_FULL_APP;
Todd Kennedyb7717682016-11-30 15:41:21 -08001468 } else {
Todd Kennedybe0b8892017-02-15 14:13:52 -08001469 installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
1470 installFlags |= PackageManager.INSTALL_FULL_APP;
Todd Kennedyb7717682016-11-30 15:41:21 -08001471 }
1472 }
1473
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001474 /**
Todd Kennedy78a72502017-07-19 12:49:30 -07001475 * Sets the install as a virtual preload. Will only have effect when called
1476 * by the verifier.
1477 * {@hide}
1478 */
1479 @SystemApi
1480 public void setInstallAsVirtualPreload() {
1481 installFlags |= PackageManager.INSTALL_VIRTUAL_PRELOAD;
1482 }
1483
1484 /**
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001485 * Set the reason for installing this package.
Todd Kennedy5fdbabb2018-03-07 15:59:41 -08001486 * <p>
1487 * The install reason should be a pre-defined integer. The behavior is
1488 * undefined if other values are used.
1489 *
Aurimas Liutikas7f695332018-05-31 21:07:32 -07001490 * @see PackageManager#INSTALL_REASON_UNKNOWN
1491 * @see PackageManager#INSTALL_REASON_POLICY
1492 * @see PackageManager#INSTALL_REASON_DEVICE_RESTORE
1493 * @see PackageManager#INSTALL_REASON_DEVICE_SETUP
Todd Kennedy5fdbabb2018-03-07 15:59:41 -08001494 * @see PackageManager#INSTALL_REASON_USER
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001495 */
1496 public void setInstallReason(@InstallReason int installReason) {
Bartosz Fabianowskia34f53f2017-01-11 18:08:47 +01001497 this.installReason = installReason;
1498 }
1499
Todd Kennedyb7717682016-11-30 15:41:21 -08001500 /** {@hide} */
Jeff Sharkey683bcd32017-03-18 17:54:51 -06001501 @SystemApi
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -06001502 @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE)
Jeff Sharkey683bcd32017-03-18 17:54:51 -06001503 public void setAllocateAggressive(boolean allocateAggressive) {
1504 if (allocateAggressive) {
1505 installFlags |= PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
1506 } else {
1507 installFlags &= ~PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
1508 }
1509 }
1510
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001511 /**
1512 * Set the installer package for the app.
1513 *
1514 * By default this is the app that created the {@link PackageInstaller} object.
1515 *
1516 * @param installerPackageName name of the installer package
1517 * {@hide}
1518 */
1519 public void setInstallerPackageName(String installerPackageName) {
1520 this.installerPackageName = installerPackageName;
1521 }
1522
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001523 /**
1524 * Set this session to be the parent of a multi-package install.
1525 *
1526 * A multi-package install session contains no APKs and only references other install
1527 * sessions via ID. When a multi-package session is committed, all of its children
1528 * are committed to the system in an atomic manner. If any children fail to install,
1529 * all of them do, including the multi-package session.
1530 */
1531 public void setMultiPackage() {
1532 this.isMultiPackage = true;
1533 }
1534
Dario Freniaac4ba42018-12-06 15:47:16 +00001535 /**
1536 * Set this session to be staged to be installed at reboot.
1537 *
1538 * Staged sessions are scheduled to be installed at next reboot. Staged sessions can also be
1539 * multi-package. In that case, if any of the children sessions fail to install at reboot,
1540 * all the other children sessions are aborted as well.
1541 */
1542 public void setStaged() {
1543 this.isStaged = true;
1544 }
1545
Dario Freni3fa46d82019-01-23 19:31:47 +00001546 /**
1547 * Set this session to be installing an APEX package.
1548 */
1549 public void setInstallAsApex() {
1550 installFlags |= PackageManager.INSTALL_APEX;
1551 }
1552
Jeff Sharkey683bcd32017-03-18 17:54:51 -06001553 /** {@hide} */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001554 public void dump(IndentingPrintWriter pw) {
1555 pw.printPair("mode", mode);
1556 pw.printHexPair("installFlags", installFlags);
1557 pw.printPair("installLocation", installLocation);
1558 pw.printPair("sizeBytes", sizeBytes);
1559 pw.printPair("appPackageName", appPackageName);
1560 pw.printPair("appIcon", (appIcon != null));
1561 pw.printPair("appLabel", appLabel);
1562 pw.printPair("originatingUri", originatingUri);
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001563 pw.printPair("originatingUid", originatingUid);
Jeff Sharkeya0907432014-08-15 10:23:11 -07001564 pw.printPair("referrerUri", referrerUri);
1565 pw.printPair("abiOverride", abiOverride);
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001566 pw.printPair("volumeUuid", volumeUuid);
Svet Ganov7121e182015-07-13 22:38:12 -07001567 pw.printPair("grantedRuntimePermissions", grantedRuntimePermissions);
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001568 pw.printPair("installerPackageName", installerPackageName);
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001569 pw.printPair("isMultiPackage", isMultiPackage);
Dario Freniaac4ba42018-12-06 15:47:16 +00001570 pw.printPair("isStaged", isStaged);
Jeff Sharkeya0907432014-08-15 10:23:11 -07001571 pw.println();
Jeff Sharkeybb580672014-07-10 12:10:25 -07001572 }
1573
1574 @Override
Jeff Sharkeya0907432014-08-15 10:23:11 -07001575 public int describeContents() {
1576 return 0;
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07001577 }
1578
1579 @Override
Jeff Sharkeya0907432014-08-15 10:23:11 -07001580 public void writeToParcel(Parcel dest, int flags) {
1581 dest.writeInt(mode);
1582 dest.writeInt(installFlags);
1583 dest.writeInt(installLocation);
Bartosz Fabianowskia34f53f2017-01-11 18:08:47 +01001584 dest.writeInt(installReason);
Jeff Sharkeya0907432014-08-15 10:23:11 -07001585 dest.writeLong(sizeBytes);
1586 dest.writeString(appPackageName);
1587 dest.writeParcelable(appIcon, flags);
1588 dest.writeString(appLabel);
1589 dest.writeParcelable(originatingUri, flags);
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001590 dest.writeInt(originatingUid);
Jeff Sharkeya0907432014-08-15 10:23:11 -07001591 dest.writeParcelable(referrerUri, flags);
1592 dest.writeString(abiOverride);
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001593 dest.writeString(volumeUuid);
Svet Ganov7121e182015-07-13 22:38:12 -07001594 dest.writeStringArray(grantedRuntimePermissions);
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001595 dest.writeString(installerPackageName);
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001596 dest.writeBoolean(isMultiPackage);
Dario Freniaac4ba42018-12-06 15:47:16 +00001597 dest.writeBoolean(isStaged);
Jeff Sharkeybb580672014-07-10 12:10:25 -07001598 }
Jeff Sharkeya0907432014-08-15 10:23:11 -07001599
1600 public static final Parcelable.Creator<SessionParams>
1601 CREATOR = new Parcelable.Creator<SessionParams>() {
1602 @Override
1603 public SessionParams createFromParcel(Parcel p) {
1604 return new SessionParams(p);
1605 }
1606
1607 @Override
1608 public SessionParams[] newArray(int size) {
1609 return new SessionParams[size];
1610 }
1611 };
Jeff Sharkeybb580672014-07-10 12:10:25 -07001612 }
1613
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001614 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001615 * Details for an active install session.
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001616 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001617 public static class SessionInfo implements Parcelable {
1618
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001619 /**
1620 * A session ID that does not exist or is invalid.
1621 */
1622 public static final int INVALID_ID = -1;
1623 /** {@hide} */
1624 private static final int[] NO_SESSIONS = {};
Dario Freni71eee5e2018-12-06 15:47:16 +00001625
1626 /** @hide */
1627 @IntDef(value = {NO_ERROR, VERIFICATION_FAILED, ACTIVATION_FAILED})
1628 @Retention(RetentionPolicy.SOURCE)
1629 public @interface StagedSessionErrorCode{}
1630 /**
1631 * Constant indicating that no error occurred during the preparation or the activation of
1632 * this staged session.
1633 */
1634 public static final int NO_ERROR = 0;
1635
1636 /**
1637 * Constant indicating that an error occurred during the verification phase (pre-reboot) of
1638 * this staged session.
1639 */
1640 public static final int VERIFICATION_FAILED = 1;
1641
1642 /**
1643 * Constant indicating that an error occurred during the activation phase (post-reboot) of
1644 * this staged session.
1645 */
1646 public static final int ACTIVATION_FAILED = 2;
1647
Jeff Sharkeya0907432014-08-15 10:23:11 -07001648 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001649 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001650 public int sessionId;
1651 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001652 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001653 public String installerPackageName;
1654 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001655 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001656 public String resolvedBaseCodePath;
1657 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001658 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001659 public float progress;
1660 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001661 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001662 public boolean sealed;
1663 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001664 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001665 public boolean active;
Jeff Sharkeya0907432014-08-15 10:23:11 -07001666
1667 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001668 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001669 public int mode;
1670 /** {@hide} */
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001671 public @InstallReason int installReason;
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001672 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001673 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001674 public long sizeBytes;
1675 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001676 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001677 public String appPackageName;
1678 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001679 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001680 public Bitmap appIcon;
1681 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001682 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001683 public CharSequence appLabel;
1684
1685 /** {@hide} */
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001686 public int installLocation;
1687 /** {@hide} */
1688 public Uri originatingUri;
1689 /** {@hide} */
1690 public int originatingUid;
1691 /** {@hide} */
1692 public Uri referrerUri;
1693 /** {@hide} */
1694 public String[] grantedRuntimePermissions;
1695 /** {@hide} */
1696 public int installFlags;
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001697 /** {@hide} */
1698 public boolean isMultiPackage;
1699 /** {@hide} */
Dario Freniaac4ba42018-12-06 15:47:16 +00001700 public boolean isStaged;
1701 /** {@hide} */
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001702 public int parentSessionId = INVALID_ID;
1703 /** {@hide} */
1704 public int[] childSessionIds = NO_SESSIONS;
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001705
1706 /** {@hide} */
Dario Freni71eee5e2018-12-06 15:47:16 +00001707 public boolean isSessionApplied;
1708 /** {@hide} */
1709 public boolean isSessionReady;
1710 /** {@hide} */
1711 public boolean isSessionFailed;
1712 private int mStagedSessionErrorCode;
Dario Freni275b4ab2019-01-25 09:55:16 +00001713 private String mStagedSessionErrorMessage;
Dario Freni71eee5e2018-12-06 15:47:16 +00001714
1715 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001716 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001717 public SessionInfo() {
1718 }
1719
1720 /** {@hide} */
1721 public SessionInfo(Parcel source) {
1722 sessionId = source.readInt();
1723 installerPackageName = source.readString();
1724 resolvedBaseCodePath = source.readString();
1725 progress = source.readFloat();
1726 sealed = source.readInt() != 0;
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001727 active = source.readInt() != 0;
Jeff Sharkeya0907432014-08-15 10:23:11 -07001728
1729 mode = source.readInt();
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001730 installReason = source.readInt();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001731 sizeBytes = source.readLong();
1732 appPackageName = source.readString();
1733 appIcon = source.readParcelable(null);
1734 appLabel = source.readString();
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001735
1736 installLocation = source.readInt();
1737 originatingUri = source.readParcelable(null);
1738 originatingUid = source.readInt();
1739 referrerUri = source.readParcelable(null);
1740 grantedRuntimePermissions = source.readStringArray();
1741 installFlags = source.readInt();
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001742 isMultiPackage = source.readBoolean();
Dario Freniaac4ba42018-12-06 15:47:16 +00001743 isStaged = source.readBoolean();
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001744 parentSessionId = source.readInt();
1745 childSessionIds = source.createIntArray();
1746 if (childSessionIds == null) {
1747 childSessionIds = NO_SESSIONS;
1748 }
Dario Freni71eee5e2018-12-06 15:47:16 +00001749 isSessionApplied = source.readBoolean();
1750 isSessionReady = source.readBoolean();
1751 isSessionFailed = source.readBoolean();
1752 mStagedSessionErrorCode = source.readInt();
Dario Freni275b4ab2019-01-25 09:55:16 +00001753 mStagedSessionErrorMessage = source.readString();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001754 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001755
1756 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001757 * Return the ID for this session.
Jeff Sharkeybb580672014-07-10 12:10:25 -07001758 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001759 public int getSessionId() {
1760 return sessionId;
1761 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001762
1763 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001764 * Return the package name of the app that owns this session.
1765 */
1766 public @Nullable String getInstallerPackageName() {
1767 return installerPackageName;
1768 }
1769
1770 /**
1771 * Return current overall progress of this session, between 0 and 1.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001772 * <p>
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001773 * Note that this progress may not directly correspond to the value
1774 * reported by
1775 * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
1776 * system may carve out a portion of the overall progress to represent
1777 * its own internal installation work.
Jeff Sharkeybb580672014-07-10 12:10:25 -07001778 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001779 public float getProgress() {
1780 return progress;
1781 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001782
1783 /**
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001784 * Return if this session is currently active.
1785 * <p>
1786 * A session is considered active whenever there is ongoing forward
1787 * progress being made, such as the installer holding an open
1788 * {@link Session} instance while streaming data into place, or the
1789 * system optimizing code as the result of
1790 * {@link Session#commit(IntentSender)}.
1791 * <p>
1792 * If the installer closes the {@link Session} without committing, the
1793 * session is considered inactive until the installer opens the session
1794 * again.
Jeff Sharkeybb580672014-07-10 12:10:25 -07001795 */
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001796 public boolean isActive() {
1797 return active;
1798 }
1799
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001800 /**
Todd Kennedy04cc1912017-03-03 13:05:12 -08001801 * Return if this session is sealed.
1802 * <p>
1803 * Once sealed, no further changes may be made to the session. A session
1804 * is sealed the moment {@link Session#commit(IntentSender)} is called.
1805 */
1806 public boolean isSealed() {
1807 return sealed;
1808 }
1809
1810 /**
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001811 * Return the reason for installing this package.
1812 *
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001813 * @return The install reason.
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001814 */
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001815 public @InstallReason int getInstallReason() {
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001816 return installReason;
1817 }
1818
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001819 /** {@hide} */
1820 @Deprecated
Jeff Sharkeya0907432014-08-15 10:23:11 -07001821 public boolean isOpen() {
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001822 return isActive();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001823 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001824
1825 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001826 * Return the package name this session is working with. May be {@code null}
1827 * if unknown.
Jeff Sharkeybb580672014-07-10 12:10:25 -07001828 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001829 public @Nullable String getAppPackageName() {
1830 return appPackageName;
1831 }
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001832
Jeff Sharkey7328a1b2014-08-07 14:01:43 -07001833 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001834 * Return an icon representing the app being installed. May be {@code null}
1835 * if unavailable.
1836 */
1837 public @Nullable Bitmap getAppIcon() {
Jeff Sharkeyda1247a2017-06-08 14:13:29 -06001838 if (appIcon == null) {
1839 // Icon may have been omitted for calls that return bulk session
1840 // lists, so try fetching the specific icon.
1841 try {
Jeff Sharkeyd1dd2c62017-08-02 09:28:53 -06001842 final SessionInfo info = AppGlobals.getPackageManager().getPackageInstaller()
1843 .getSessionInfo(sessionId);
1844 appIcon = (info != null) ? info.appIcon : null;
Jeff Sharkeyda1247a2017-06-08 14:13:29 -06001845 } catch (RemoteException e) {
1846 throw e.rethrowFromSystemServer();
1847 }
1848 }
Jeff Sharkeya0907432014-08-15 10:23:11 -07001849 return appIcon;
1850 }
1851
1852 /**
1853 * Return a label representing the app being installed. May be {@code null}
1854 * if unavailable.
1855 */
1856 public @Nullable CharSequence getAppLabel() {
1857 return appLabel;
1858 }
1859
1860 /**
1861 * Return an Intent that can be started to view details about this install
1862 * session. This may surface actions such as pause, resume, or cancel.
1863 * <p>
1864 * In some cases, a matching Activity may not exist, so ensure you safeguard
1865 * against this.
Jeff Sharkey7328a1b2014-08-07 14:01:43 -07001866 *
Jeff Sharkeya0907432014-08-15 10:23:11 -07001867 * @see PackageInstaller#ACTION_SESSION_DETAILS
Jeff Sharkey7328a1b2014-08-07 14:01:43 -07001868 */
Jeff Sharkeyde742312014-09-15 14:04:56 -07001869 public @Nullable Intent createDetailsIntent() {
Jeff Sharkeya0907432014-08-15 10:23:11 -07001870 final Intent intent = new Intent(PackageInstaller.ACTION_SESSION_DETAILS);
1871 intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
1872 intent.setPackage(installerPackageName);
1873 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1874 return intent;
Jeff Sharkeybb580672014-07-10 12:10:25 -07001875 }
1876
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001877 /**
1878 * Get the mode of the session as set in the constructor of the {@link SessionParams}.
1879 *
1880 * @return One of {@link SessionParams#MODE_FULL_INSTALL}
1881 * or {@link SessionParams#MODE_INHERIT_EXISTING}
1882 */
1883 public int getMode() {
1884 return mode;
1885 }
1886
1887 /**
1888 * Get the value set in {@link SessionParams#setInstallLocation(int)}.
1889 */
1890 public int getInstallLocation() {
1891 return installLocation;
1892 }
1893
1894 /**
1895 * Get the value as set in {@link SessionParams#setSize(long)}.
1896 *
1897 * <p>The value is a hint and does not have to match the actual size.
1898 */
1899 public long getSize() {
1900 return sizeBytes;
1901 }
1902
1903 /**
1904 * Get the value set in {@link SessionParams#setOriginatingUri(Uri)}.
1905 */
1906 public @Nullable Uri getOriginatingUri() {
1907 return originatingUri;
1908 }
1909
1910 /**
1911 * Get the value set in {@link SessionParams#setOriginatingUid(int)}.
1912 */
1913 public int getOriginatingUid() {
1914 return originatingUid;
1915 }
1916
1917 /**
1918 * Get the value set in {@link SessionParams#setReferrerUri(Uri)}
1919 */
1920 public @Nullable Uri getReferrerUri() {
1921 return referrerUri;
1922 }
1923
1924 /**
1925 * Get the value set in {@link SessionParams#setGrantedRuntimePermissions(String[])}.
1926 *
1927 * @hide
1928 */
1929 @SystemApi
1930 public @Nullable String[] getGrantedRuntimePermissions() {
1931 return grantedRuntimePermissions;
1932 }
1933
1934 /**
1935 * Get the value set in {@link SessionParams#setAllowDowngrade(boolean)}.
1936 *
1937 * @hide
1938 */
1939 @SystemApi
1940 public boolean getAllowDowngrade() {
1941 return (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
1942 }
1943
1944 /**
1945 * Get the value set in {@link SessionParams#setDontKillApp(boolean)}.
1946 *
1947 * @hide
1948 */
1949 @SystemApi
1950 public boolean getDontKillApp() {
1951 return (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0;
1952 }
1953
1954 /**
1955 * If {@link SessionParams#setInstallAsInstantApp(boolean)} was called with {@code true},
1956 * return true. If it was called with {@code false} or if it was not called return false.
1957 *
1958 * @hide
1959 *
1960 * @see #getInstallAsFullApp
1961 */
1962 @SystemApi
1963 public boolean getInstallAsInstantApp(boolean isInstantApp) {
1964 return (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
1965 }
1966
1967 /**
1968 * If {@link SessionParams#setInstallAsInstantApp(boolean)} was called with {@code false},
1969 * return true. If it was called with {@code true} or if it was not called return false.
1970 *
1971 * @hide
1972 *
1973 * @see #getInstallAsInstantApp
1974 */
1975 @SystemApi
1976 public boolean getInstallAsFullApp(boolean isInstantApp) {
1977 return (installFlags & PackageManager.INSTALL_FULL_APP) != 0;
1978 }
1979
1980 /**
1981 * Get if {@link SessionParams#setInstallAsVirtualPreload()} was called.
1982 *
1983 * @hide
1984 */
1985 @SystemApi
1986 public boolean getInstallAsVirtualPreload() {
1987 return (installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0;
1988 }
1989
1990 /**
1991 * Get the value set in {@link SessionParams#setAllocateAggressive(boolean)}.
1992 *
1993 * @hide
1994 */
1995 @SystemApi
1996 public boolean getAllocateAggressive() {
1997 return (installFlags & PackageManager.INSTALL_ALLOCATE_AGGRESSIVE) != 0;
1998 }
1999
2000
Jeff Sharkeyde742312014-09-15 14:04:56 -07002001 /** {@hide} */
2002 @Deprecated
2003 public @Nullable Intent getDetailsIntent() {
2004 return createDetailsIntent();
2005 }
2006
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002007 /**
2008 * Returns true if this session is a multi-package session containing references to other
2009 * sessions.
2010 */
2011 public boolean isMultiPackage() {
2012 return isMultiPackage;
2013 }
2014
2015 /**
Dario Freniaac4ba42018-12-06 15:47:16 +00002016 * Returns true if this session is a staged session which will be applied at next reboot.
2017 */
2018 public boolean isStaged() {
2019 return isStaged;
2020 }
2021
2022 /**
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002023 * Returns the parent multi-package session ID if this session belongs to one,
2024 * {@link #INVALID_ID} otherwise.
2025 */
2026 public int getParentSessionId() {
2027 return parentSessionId;
2028 }
2029
2030 /**
2031 * Returns the set of session IDs that will be committed when this session is commited if
2032 * this session is a multi-package session.
2033 */
2034 public int[] getChildSessionIds() {
2035 return childSessionIds;
2036 }
2037
Dario Freni71eee5e2018-12-06 15:47:16 +00002038 /**
2039 * Whether the staged session has been applied successfully, meaning that all of its
2040 * packages have been activated and no further action is required.
2041 * Only meaningful if {@code isStaged} is true.
2042 */
2043 public boolean isSessionApplied() {
2044 return isSessionApplied;
2045 }
2046
2047 /**
2048 * Whether the staged session is ready to be applied at next reboot. Only meaningful if
2049 * {@code isStaged} is true.
2050 */
2051 public boolean isSessionReady() {
2052 return isSessionReady;
2053 }
2054
2055 /**
2056 * Whether something went wrong and the staged session is declared as failed, meaning that
2057 * it will be ignored at next reboot. Only meaningful if {@code isStaged} is true.
2058 */
2059 public boolean isSessionFailed() {
2060 return isSessionFailed;
2061 }
2062
2063 /**
2064 * If something went wrong with a staged session, clients can check this error code to
2065 * understand which kind of failure happened. Only meaningful if {@code isStaged} is true.
2066 */
2067 public int getStagedSessionErrorCode() {
2068 return mStagedSessionErrorCode;
2069 }
2070
Dario Freni275b4ab2019-01-25 09:55:16 +00002071 /**
2072 * Text description of the error code returned by {@code getStagedSessionErrorCode}, or
2073 * empty string if no error was encountered.
2074 */
2075 public String getStagedSessionErrorMessage() {
2076 return mStagedSessionErrorMessage;
2077 }
2078
Dario Freni71eee5e2018-12-06 15:47:16 +00002079 /** {@hide} */
Dario Freni275b4ab2019-01-25 09:55:16 +00002080 public void setStagedSessionErrorCode(@StagedSessionErrorCode int errorCode,
2081 String errorMessage) {
Dario Freni71eee5e2018-12-06 15:47:16 +00002082 mStagedSessionErrorCode = errorCode;
Dario Freni275b4ab2019-01-25 09:55:16 +00002083 mStagedSessionErrorMessage = errorMessage;
Dario Freni71eee5e2018-12-06 15:47:16 +00002084 }
2085
Jeff Sharkeybb580672014-07-10 12:10:25 -07002086 @Override
Jeff Sharkeya0907432014-08-15 10:23:11 -07002087 public int describeContents() {
2088 return 0;
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07002089 }
2090
2091 @Override
Jeff Sharkeya0907432014-08-15 10:23:11 -07002092 public void writeToParcel(Parcel dest, int flags) {
2093 dest.writeInt(sessionId);
2094 dest.writeString(installerPackageName);
2095 dest.writeString(resolvedBaseCodePath);
2096 dest.writeFloat(progress);
2097 dest.writeInt(sealed ? 1 : 0);
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07002098 dest.writeInt(active ? 1 : 0);
Jeff Sharkeybb580672014-07-10 12:10:25 -07002099
Jeff Sharkeya0907432014-08-15 10:23:11 -07002100 dest.writeInt(mode);
Sunny Goyal6d7cb232017-01-30 10:43:18 -08002101 dest.writeInt(installReason);
Jeff Sharkeya0907432014-08-15 10:23:11 -07002102 dest.writeLong(sizeBytes);
2103 dest.writeString(appPackageName);
2104 dest.writeParcelable(appIcon, flags);
2105 dest.writeString(appLabel != null ? appLabel.toString() : null);
Philip P. Moltmann7460c592017-08-08 20:07:11 +00002106
2107 dest.writeInt(installLocation);
2108 dest.writeParcelable(originatingUri, flags);
2109 dest.writeInt(originatingUid);
2110 dest.writeParcelable(referrerUri, flags);
2111 dest.writeStringArray(grantedRuntimePermissions);
2112 dest.writeInt(installFlags);
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002113 dest.writeBoolean(isMultiPackage);
Dario Freniaac4ba42018-12-06 15:47:16 +00002114 dest.writeBoolean(isStaged);
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002115 dest.writeInt(parentSessionId);
2116 dest.writeIntArray(childSessionIds);
Dario Freni71eee5e2018-12-06 15:47:16 +00002117 dest.writeBoolean(isSessionApplied);
2118 dest.writeBoolean(isSessionReady);
2119 dest.writeBoolean(isSessionFailed);
2120 dest.writeInt(mStagedSessionErrorCode);
Dario Freni275b4ab2019-01-25 09:55:16 +00002121 dest.writeString(mStagedSessionErrorMessage);
Jeff Sharkeybb580672014-07-10 12:10:25 -07002122 }
Jeff Sharkeya0907432014-08-15 10:23:11 -07002123
2124 public static final Parcelable.Creator<SessionInfo>
2125 CREATOR = new Parcelable.Creator<SessionInfo>() {
2126 @Override
2127 public SessionInfo createFromParcel(Parcel p) {
2128 return new SessionInfo(p);
2129 }
2130
2131 @Override
2132 public SessionInfo[] newArray(int size) {
2133 return new SessionInfo[size];
2134 }
2135 };
Jeff Sharkeybb580672014-07-10 12:10:25 -07002136 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07002137}