blob: a15caa09bb608ace488bd5ba41bc61611f7ef8f1 [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 Freni56c14dd2019-04-03 16:20:22 +010020import android.annotation.CurrentTimeMillisLong;
Dario Freni71eee5e2018-12-06 15:47:16 +000021import android.annotation.IntDef;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -070022import android.annotation.NonNull;
23import android.annotation.Nullable;
Svet Ganov7121e182015-07-13 22:38:12 -070024import android.annotation.RequiresPermission;
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -070025import android.annotation.SdkConstant;
26import android.annotation.SdkConstant.SdkConstantType;
Svet Ganov7121e182015-07-13 22:38:12 -070027import android.annotation.SystemApi;
Richard Uhler8a977452019-03-08 13:27:17 +000028import android.annotation.TestApi;
Mathew Inwood5c0d3542018-08-14 13:54:31 +010029import android.annotation.UnsupportedAppUsage;
Jeff Sharkeya0907432014-08-15 10:23:11 -070030import android.app.ActivityManager;
Jeff Sharkeyda1247a2017-06-08 14:13:29 -060031import android.app.AppGlobals;
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -070032import android.content.Intent;
Jeff Sharkeya0907432014-08-15 10:23:11 -070033import android.content.IntentSender;
Todd Kennedycda831f2017-05-16 10:54:33 -070034import android.content.pm.PackageManager.DeleteFlags;
Bartosz Fabianowski40a00622017-04-18 14:39:23 +020035import android.content.pm.PackageManager.InstallReason;
Jeff Sharkeya0907432014-08-15 10:23:11 -070036import android.graphics.Bitmap;
37import android.net.Uri;
Mathew Inwood8c854f82018-09-14 12:35:36 +010038import android.os.Build;
Jeff Sharkey78cc3402014-05-22 10:52:49 -070039import android.os.FileBridge;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -070040import android.os.Handler;
Jon Miranda2b340a22019-01-25 14:03:49 -080041import android.os.HandlerExecutor;
Jeff Sharkeya0907432014-08-15 10:23:11 -070042import android.os.Parcel;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070043import android.os.ParcelFileDescriptor;
Jeff Sharkeya0907432014-08-15 10:23:11 -070044import android.os.Parcelable;
Philip P. Moltmann7460c592017-08-08 20:07:11 +000045import android.os.ParcelableException;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070046import android.os.RemoteException;
Jeff Sharkey02d4e342017-03-10 21:53:48 -070047import android.os.SystemProperties;
Jon Miranda2b340a22019-01-25 14:03:49 -080048import android.os.UserHandle;
Jeff Sharkey02d4e342017-03-10 21:53:48 -070049import android.system.ErrnoException;
50import android.system.Os;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070051import android.util.ArraySet;
Jeff Sharkeya1031142014-07-12 18:09:46 -070052import android.util.ExceptionUtils;
Jeff Sharkeya0907432014-08-15 10:23:11 -070053
54import com.android.internal.util.IndentingPrintWriter;
Svet Ganov67882122016-12-11 16:36:34 -080055import com.android.internal.util.Preconditions;
Jon Miranda2b340a22019-01-25 14:03:49 -080056import com.android.internal.util.function.pooled.PooledLambda;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070057
Jeff Sharkeyec55ef02014-07-08 11:28:00 -070058import java.io.Closeable;
Jeff Sharkeya1031142014-07-12 18:09:46 -070059import java.io.IOException;
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -070060import java.io.InputStream;
Jeff Sharkey78cc3402014-05-22 10:52:49 -070061import java.io.OutputStream;
Dario Freni71eee5e2018-12-06 15:47:16 +000062import java.lang.annotation.Retention;
63import java.lang.annotation.RetentionPolicy;
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -070064import java.security.MessageDigest;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -070065import java.util.ArrayList;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070066import java.util.Collections;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -070067import java.util.Iterator;
Jeff Sharkeybb580672014-07-10 12:10:25 -070068import java.util.List;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070069import java.util.Set;
Jon Miranda2b340a22019-01-25 14:03:49 -080070import java.util.concurrent.Executor;
Jeff Sharkey78cc3402014-05-22 10:52:49 -070071
Jeff Sharkey6c833e02014-07-14 22:44:30 -070072/**
73 * Offers the ability to install, upgrade, and remove applications on the
74 * device. This includes support for apps packaged either as a single
75 * "monolithic" APK, or apps packaged as multiple "split" APKs.
76 * <p>
77 * An app is delivered for installation through a
78 * {@link PackageInstaller.Session}, which any app can create. Once the session
79 * is created, the installer can stream one or more APKs into place until it
80 * decides to either commit or destroy the session. Committing may require user
Rubin Xufd4a3b42018-12-05 16:03:27 +000081 * intervention to complete the installation, unless the caller falls into one of the
82 * following categories, in which case the installation will complete automatically.
83 * <ul>
84 * <li>the device owner
85 * <li>the affiliated profile owner
Rubin Xufd4a3b42018-12-05 16:03:27 +000086 * </ul>
Jeff Sharkey6c833e02014-07-14 22:44:30 -070087 * <p>
88 * Sessions can install brand new apps, upgrade existing apps, or add new splits
Jeff Sharkeyda96e132014-07-15 14:54:09 -070089 * into an existing app.
Jeff Sharkey6c833e02014-07-14 22:44:30 -070090 * <p>
Jeff Sharkeyda96e132014-07-15 14:54:09 -070091 * Apps packaged as multiple split APKs always consist of a single "base" APK
Jeff Sharkey6c833e02014-07-14 22:44:30 -070092 * (with a {@code null} split name) and zero or more "split" APKs (with unique
93 * split names). Any subset of these APKs can be installed together, as long as
94 * the following constraints are met:
95 * <ul>
96 * <li>All APKs must have the exact same package name, version code, and signing
97 * certificates.
Jeff Sharkey6c833e02014-07-14 22:44:30 -070098 * <li>All APKs must have unique split names.
Jeff Sharkeyda96e132014-07-15 14:54:09 -070099 * <li>All installations must contain a single base APK.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700100 * </ul>
Peter Visontayf702fd42017-11-17 14:00:47 +0000101 * <p>
102 * The ApiDemos project contains examples of using this API:
103 * <code>ApiDemos/src/com/example/android/apis/content/InstallApk*.java</code>.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700104 */
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700105public class PackageInstaller {
Jeff Sharkeya0907432014-08-15 10:23:11 -0700106 private static final String TAG = "PackageInstaller";
107
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700108 /** {@hide} */
109 public static final boolean ENABLE_REVOCABLE_FD =
110 SystemProperties.getBoolean("fw.revocable_fd", false);
111
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700112 /**
113 * Activity Action: Show details about a particular install session. This
114 * may surface actions such as pause, resume, or cancel.
115 * <p>
116 * This should always be scoped to the installer package that owns the
Jeff Sharkeyde742312014-09-15 14:04:56 -0700117 * session. Clients should use {@link SessionInfo#createDetailsIntent()} to
Jeff Sharkeya0907432014-08-15 10:23:11 -0700118 * build this intent correctly.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700119 * <p>
120 * In some cases, a matching Activity may not exist, so ensure you safeguard
121 * against this.
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700122 * <p>
123 * The session to show details for is defined in {@link #EXTRA_SESSION_ID}.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700124 */
125 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
126 public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
127
Sunny Goyal6d7cb232017-01-30 10:43:18 -0800128 /**
129 * Broadcast Action: Explicit broadcast sent to the last known default launcher when a session
130 * for a new install is committed. For managed profile, this is sent to the default launcher
131 * of the primary profile.
132 * <p>
133 * The associated session is defined in {@link #EXTRA_SESSION} and the user for which this
134 * session was created in {@link Intent#EXTRA_USER}.
135 */
136 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
137 public static final String ACTION_SESSION_COMMITTED =
138 "android.content.pm.action.SESSION_COMMITTED";
139
Dario Frenie487ea22018-12-12 15:41:59 +0000140 /**
141 * Broadcast Action: Send information about a staged install session when its state is updated.
142 * <p>
143 * The associated session information is defined in {@link #EXTRA_SESSION}.
144 */
145 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
146 public static final String ACTION_SESSION_UPDATED =
147 "android.content.pm.action.SESSION_UPDATED";
148
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700149 /** {@hide} */
Philip P. Moltmanne8fe3cb2018-07-23 14:27:11 -0700150 public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL";
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700151
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700152 /**
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700153 * An integer session ID that an operation is working with.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700154 *
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700155 * @see Intent#getIntExtra(String, int)
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700156 */
157 public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
158
Jeff Sharkeya0907432014-08-15 10:23:11 -0700159 /**
Sunny Goyal6d7cb232017-01-30 10:43:18 -0800160 * {@link SessionInfo} that an operation is working with.
161 *
162 * @see Intent#getParcelableExtra(String)
163 */
164 public static final String EXTRA_SESSION = "android.content.pm.extra.SESSION";
165
166 /**
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700167 * Package name that an operation is working with.
Jeff Sharkeya0907432014-08-15 10:23:11 -0700168 *
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700169 * @see Intent#getStringExtra(String)
Jeff Sharkeya0907432014-08-15 10:23:11 -0700170 */
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700171 public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
172
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700173 /**
174 * Current status of an operation. Will be one of
175 * {@link #STATUS_PENDING_USER_ACTION}, {@link #STATUS_SUCCESS},
176 * {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED},
177 * {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT},
178 * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID}, or
179 * {@link #STATUS_FAILURE_STORAGE}.
180 * <p>
181 * More information about a status may be available through additional
182 * extras; see the individual status documentation for details.
183 *
184 * @see Intent#getIntExtra(String, int)
185 */
186 public static final String EXTRA_STATUS = "android.content.pm.extra.STATUS";
187
188 /**
189 * Detailed string representation of the status, including raw details that
190 * are useful for debugging.
191 *
192 * @see Intent#getStringExtra(String)
193 */
194 public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
195
196 /**
197 * Another package name relevant to a status. This is typically the package
198 * responsible for causing an operation failure.
199 *
200 * @see Intent#getStringExtra(String)
201 */
202 public static final String
203 EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
204
205 /**
206 * Storage path relevant to a status.
207 *
208 * @see Intent#getStringExtra(String)
209 */
210 public static final String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH";
211
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700212 /** {@hide} */
213 @Deprecated
Jeff Sharkeya0907432014-08-15 10:23:11 -0700214 public static final String EXTRA_PACKAGE_NAMES = "android.content.pm.extra.PACKAGE_NAMES";
215
216 /** {@hide} */
217 public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS";
218 /** {@hide} */
219 public static final String EXTRA_LEGACY_BUNDLE = "android.content.pm.extra.LEGACY_BUNDLE";
Jeff Sharkeyf0600952014-08-07 17:31:53 -0700220 /** {@hide} */
221 public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK";
222
Jeff Sharkeya0907432014-08-15 10:23:11 -0700223 /**
224 * User action is currently required to proceed. You can launch the intent
225 * activity described by {@link Intent#EXTRA_INTENT} to involve the user and
226 * continue.
227 * <p>
228 * You may choose to immediately launch the intent if the user is actively
229 * using your app. Otherwise, you should use a notification to guide the
230 * user back into your app before launching.
231 *
232 * @see Intent#getParcelableExtra(String)
233 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700234 public static final int STATUS_PENDING_USER_ACTION = -1;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700235
236 /**
237 * The operation succeeded.
238 */
239 public static final int STATUS_SUCCESS = 0;
240
241 /**
242 * The operation failed in a generic way. The system will always try to
243 * provide a more specific failure reason, but in some rare cases this may
244 * be delivered.
245 *
246 * @see #EXTRA_STATUS_MESSAGE
247 */
248 public static final int STATUS_FAILURE = 1;
249
250 /**
251 * The operation failed because it was blocked. For example, a device policy
252 * may be blocking the operation, a package verifier may have blocked the
253 * operation, or the app may be required for core system operation.
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700254 * <p>
255 * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
256 * specific package blocking the install.
Jeff Sharkeya0907432014-08-15 10:23:11 -0700257 *
258 * @see #EXTRA_STATUS_MESSAGE
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700259 * @see #EXTRA_OTHER_PACKAGE_NAME
Jeff Sharkeya0907432014-08-15 10:23:11 -0700260 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700261 public static final int STATUS_FAILURE_BLOCKED = 2;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700262
263 /**
264 * The operation failed because it was actively aborted. For example, the
265 * user actively declined requested permissions, or the session was
266 * abandoned.
267 *
268 * @see #EXTRA_STATUS_MESSAGE
269 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700270 public static final int STATUS_FAILURE_ABORTED = 3;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700271
272 /**
273 * The operation failed because one or more of the APKs was invalid. For
274 * example, they might be malformed, corrupt, incorrectly signed,
275 * mismatched, etc.
276 *
277 * @see #EXTRA_STATUS_MESSAGE
278 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700279 public static final int STATUS_FAILURE_INVALID = 4;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700280
281 /**
282 * The operation failed because it conflicts (or is inconsistent with) with
283 * another package already installed on the device. For example, an existing
284 * permission, incompatible certificates, etc. The user may be able to
285 * uninstall another app to fix the issue.
286 * <p>
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700287 * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700288 * specific package identified as the cause of the conflict.
Jeff Sharkeya0907432014-08-15 10:23:11 -0700289 *
290 * @see #EXTRA_STATUS_MESSAGE
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700291 * @see #EXTRA_OTHER_PACKAGE_NAME
Jeff Sharkeya0907432014-08-15 10:23:11 -0700292 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700293 public static final int STATUS_FAILURE_CONFLICT = 5;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700294
295 /**
296 * The operation failed because of storage issues. For example, the device
297 * may be running low on space, or external media may be unavailable. The
298 * user may be able to help free space or insert different external media.
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700299 * <p>
300 * The result may also contain {@link #EXTRA_STORAGE_PATH} with the path to
301 * the storage device that caused the failure.
Jeff Sharkeya0907432014-08-15 10:23:11 -0700302 *
303 * @see #EXTRA_STATUS_MESSAGE
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700304 * @see #EXTRA_STORAGE_PATH
Jeff Sharkeya0907432014-08-15 10:23:11 -0700305 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700306 public static final int STATUS_FAILURE_STORAGE = 6;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700307
308 /**
309 * The operation failed because it is fundamentally incompatible with this
310 * device. For example, the app may require a hardware feature that doesn't
311 * exist, it may be missing native code for the ABIs supported by the
312 * device, or it requires a newer SDK version, etc.
313 *
314 * @see #EXTRA_STATUS_MESSAGE
315 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700316 public static final int STATUS_FAILURE_INCOMPATIBLE = 7;
Jeff Sharkeya0907432014-08-15 10:23:11 -0700317
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700318 private final IPackageInstaller mInstaller;
319 private final int mUserId;
320 private final String mInstallerPackageName;
321
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700322 private final ArrayList<SessionCallbackDelegate> mDelegates = new ArrayList<>();
323
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700324 /** {@hide} */
Svet Ganov67882122016-12-11 16:36:34 -0800325 public PackageInstaller(IPackageInstaller installer,
Jeff Sharkeyec55ef02014-07-08 11:28:00 -0700326 String installerPackageName, int userId) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700327 mInstaller = installer;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700328 mInstallerPackageName = installerPackageName;
Jeff Sharkeyec55ef02014-07-08 11:28:00 -0700329 mUserId = userId;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700330 }
331
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700332 /**
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700333 * Create a new session using the given parameters, returning a unique ID
334 * that represents the session. Once created, the session can be opened
335 * multiple times across multiple device boots.
336 * <p>
337 * The system may automatically destroy sessions that have not been
338 * finalized (either committed or abandoned) within a reasonable period of
339 * time, typically on the order of a day.
340 *
341 * @throws IOException if parameters were unsatisfiable, such as lack of
342 * disk space or unavailable media.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700343 * @throws SecurityException when installation services are unavailable,
344 * such as when called from a restricted user.
345 * @throws IllegalArgumentException when {@link SessionParams} is invalid.
Jeff Sharkeyf174c6e2014-08-05 10:42:27 -0700346 * @return positive, non-zero unique ID that represents the created session.
347 * This ID remains consistent across device reboots until the
348 * session is finalized. IDs are not reused during a given boot.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700349 */
Jeff Sharkeya0907432014-08-15 10:23:11 -0700350 public int createSession(@NonNull SessionParams params) throws IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700351 try {
Philip P. Moltmann79c238a2017-12-13 15:59:07 -0800352 final String installerPackage;
353 if (params.installerPackageName == null) {
354 installerPackage = mInstallerPackageName;
355 } else {
356 installerPackage = params.installerPackageName;
357 }
358
359 return mInstaller.createSession(params, installerPackage, mUserId);
Jeff Sharkeya1031142014-07-12 18:09:46 -0700360 } catch (RuntimeException e) {
361 ExceptionUtils.maybeUnwrapIOException(e);
362 throw e;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700363 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700364 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700365 }
366 }
367
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700368 /**
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700369 * Open an existing session to actively perform work. To succeed, the caller
370 * must be the owner of the install session.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700371 *
372 * @throws IOException if parameters were unsatisfiable, such as lack of
373 * disk space or unavailable media.
374 * @throws SecurityException when the caller does not own the session, or
375 * the session is invalid.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700376 */
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700377 public @NonNull Session openSession(int sessionId) throws IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700378 try {
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000379 try {
380 return new Session(mInstaller.openSession(sessionId));
381 } catch (RemoteException e) {
382 throw e.rethrowFromSystemServer();
383 }
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700384 } catch (RuntimeException e) {
385 ExceptionUtils.maybeUnwrapIOException(e);
386 throw e;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700387 }
388 }
389
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700390 /**
391 * Update the icon representing the app being installed in a specific
392 * session. This should be roughly
393 * {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700394 *
395 * @throws SecurityException when the caller does not own the session, or
396 * the session is invalid.
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700397 */
398 public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) {
399 try {
400 mInstaller.updateSessionAppIcon(sessionId, appIcon);
401 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700402 throw e.rethrowFromSystemServer();
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700403 }
404 }
405
406 /**
407 * Update the label representing the app being installed in a specific
408 * session.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700409 *
410 * @throws SecurityException when the caller does not own the session, or
411 * the session is invalid.
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700412 */
413 public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) {
414 try {
415 final String val = (appLabel != null) ? appLabel.toString() : null;
416 mInstaller.updateSessionAppLabel(sessionId, val);
417 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700418 throw e.rethrowFromSystemServer();
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700419 }
420 }
421
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700422 /**
423 * Completely abandon the given session, destroying all staged data and
424 * rendering it invalid. Abandoned sessions will be reported to
425 * {@link SessionCallback} listeners as failures. This is equivalent to
426 * opening the session and calling {@link Session#abandon()}.
427 *
428 * @throws SecurityException when the caller does not own the session, or
429 * the session is invalid.
430 */
Jeff Sharkey381d94b2014-08-24 14:45:56 -0700431 public void abandonSession(int sessionId) {
432 try {
433 mInstaller.abandonSession(sessionId);
434 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700435 throw e.rethrowFromSystemServer();
Jeff Sharkey381d94b2014-08-24 14:45:56 -0700436 }
437 }
438
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700439 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700440 * Return details for a specific session. No special permissions are
441 * required to retrieve these details.
442 *
443 * @return details for the requested session, or {@code null} if the session
444 * does not exist.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700445 */
Jeff Sharkeya0907432014-08-15 10:23:11 -0700446 public @Nullable SessionInfo getSessionInfo(int sessionId) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700447 try {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700448 return mInstaller.getSessionInfo(sessionId);
449 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700450 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700451 }
452 }
453
454 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700455 * Return list of all known install sessions, regardless of the installer.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700456 */
Jeff Sharkeya0907432014-08-15 10:23:11 -0700457 public @NonNull List<SessionInfo> getAllSessions() {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700458 try {
Jeff Sharkey97d47ed2014-10-15 09:19:47 -0700459 return mInstaller.getAllSessions(mUserId).getList();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700460 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700461 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700462 }
463 }
464
465 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700466 * Return list of all known install sessions owned by the calling app.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700467 */
Jeff Sharkeya0907432014-08-15 10:23:11 -0700468 public @NonNull List<SessionInfo> getMySessions() {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700469 try {
Jeff Sharkey97d47ed2014-10-15 09:19:47 -0700470 return mInstaller.getMySessions(mInstallerPackageName, mUserId).getList();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700471 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700472 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700473 }
474 }
475
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700476 /**
Dario Freniaac4ba42018-12-06 15:47:16 +0000477 * Return list of all staged install sessions.
478 */
479 public @NonNull List<SessionInfo> getStagedSessions() {
480 try {
481 // TODO: limit this to the mUserId?
482 return mInstaller.getStagedSessions().getList();
483 } catch (RemoteException e) {
484 throw e.rethrowFromSystemServer();
485 }
486 }
487
488 /**
Nikita Ioffe00a08f12019-03-07 20:55:08 +0000489 * Returns an active staged session, or {@code null} if there is none.
490 *
491 * <p>Staged session is active iff:
492 * <ul>
Nikita Ioffe05305022019-04-10 17:15:36 +0100493 * <li>It is committed, i.e. {@link SessionInfo#isCommitted()} is {@code true}, and
494 * <li>it is not applied, i.e. {@link SessionInfo#isStagedSessionApplied()} is {@code
495 * false}, and
496 * <li>it is not failed, i.e. {@link SessionInfo#isStagedSessionFailed()} is {@code false}.
Nikita Ioffe00a08f12019-03-07 20:55:08 +0000497 * </ul>
498 *
Nikita Ioffe05305022019-04-10 17:15:36 +0100499 * <p>In case of a multi-apk session, reasoning above is applied to the parent session, since
500 * that is the one that should been {@link Session#commit committed}.
Nikita Ioffe00a08f12019-03-07 20:55:08 +0000501 */
502 public @Nullable SessionInfo getActiveStagedSession() {
503 final List<SessionInfo> stagedSessions = getStagedSessions();
504 for (SessionInfo s : stagedSessions) {
505 if (s.isStagedSessionApplied() || s.isStagedSessionFailed()) {
506 // Finalized session.
507 continue;
508 }
509 if (s.getParentSessionId() != SessionInfo.INVALID_ID) {
510 // Child session.
511 continue;
512 }
513 if (s.isCommitted()) {
514 return s;
515 }
516 }
517 return null;
518 }
519
520 /**
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700521 * Uninstall the given package, removing it completely from the device. This
Tony Mak366ee622018-02-12 17:52:34 +0000522 * method is available to:
523 * <ul>
524 * <li>the current "installer of record" for the package
525 * <li>the device owner
526 * <li>the affiliated profile owner
527 * </ul>
Svet Ganov67882122016-12-11 16:36:34 -0800528 *
529 * @param packageName The package to uninstall.
530 * @param statusReceiver Where to deliver the result.
Tony Mak366ee622018-02-12 17:52:34 +0000531 *
532 * @see android.app.admin.DevicePolicyManager
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700533 */
Philip P. Moltmannd9bb39a2017-09-05 12:41:15 -0700534 @RequiresPermission(anyOf = {
535 Manifest.permission.DELETE_PACKAGES,
536 Manifest.permission.REQUEST_DELETE_PACKAGES})
Jeff Sharkeya0907432014-08-15 10:23:11 -0700537 public void uninstall(@NonNull String packageName, @NonNull IntentSender statusReceiver) {
Todd Kennedycda831f2017-05-16 10:54:33 -0700538 uninstall(packageName, 0 /*flags*/, statusReceiver);
539 }
540
541 /**
542 * Uninstall the given package, removing it completely from the device. This
543 * method is only available to the current "installer of record" for the
544 * package.
545 *
546 * @param packageName The package to uninstall.
547 * @param flags Flags for uninstall.
548 * @param statusReceiver Where to deliver the result.
549 *
550 * @hide
551 */
552 public void uninstall(@NonNull String packageName, @DeleteFlags int flags,
553 @NonNull IntentSender statusReceiver) {
554 uninstall(new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
555 flags, statusReceiver);
Svet Ganov67882122016-12-11 16:36:34 -0800556 }
557
558 /**
559 * Uninstall the given package with a specific version code, removing it
Tony Mak366ee622018-02-12 17:52:34 +0000560 * completely from the device. If the version code of the package
Svet Ganov67882122016-12-11 16:36:34 -0800561 * does not match the one passed in the versioned package argument this
562 * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to
563 * uninstall the latest version of the package.
Tony Mak366ee622018-02-12 17:52:34 +0000564 * <p>
565 * This method is available to:
566 * <ul>
567 * <li>the current "installer of record" for the package
568 * <li>the device owner
569 * <li>the affiliated profile owner
570 * </ul>
Svet Ganov67882122016-12-11 16:36:34 -0800571 *
572 * @param versionedPackage The versioned package to uninstall.
573 * @param statusReceiver Where to deliver the result.
Tony Mak366ee622018-02-12 17:52:34 +0000574 *
575 * @see android.app.admin.DevicePolicyManager
Svet Ganov67882122016-12-11 16:36:34 -0800576 */
Philip P. Moltmannd9bb39a2017-09-05 12:41:15 -0700577 @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,
581 @NonNull IntentSender statusReceiver) {
582 uninstall(versionedPackage, 0 /*flags*/, statusReceiver);
583 }
584
585 /**
586 * Uninstall the given package with a specific version code, removing it
587 * completely from the device. This method is only available to the current
588 * "installer of record" for the package. If the version code of the package
589 * does not match the one passed in the versioned package argument this
590 * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to
591 * uninstall the latest version of the package.
592 *
593 * @param versionedPackage The versioned package to uninstall.
594 * @param flags Flags for uninstall.
595 * @param statusReceiver Where to deliver the result.
596 *
597 * @hide
598 */
Svet Ganov67882122016-12-11 16:36:34 -0800599 @RequiresPermission(anyOf = {
600 Manifest.permission.DELETE_PACKAGES,
601 Manifest.permission.REQUEST_DELETE_PACKAGES})
Todd Kennedycda831f2017-05-16 10:54:33 -0700602 public void uninstall(@NonNull VersionedPackage versionedPackage, @DeleteFlags int flags,
Svet Ganov67882122016-12-11 16:36:34 -0800603 @NonNull IntentSender statusReceiver) {
604 Preconditions.checkNotNull(versionedPackage, "versionedPackage cannot be null");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700605 try {
Svet Ganov67882122016-12-11 16:36:34 -0800606 mInstaller.uninstall(versionedPackage, mInstallerPackageName,
Todd Kennedycda831f2017-05-16 10:54:33 -0700607 flags, statusReceiver, mUserId);
Jeff Sharkeybb580672014-07-10 12:10:25 -0700608 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700609 throw e.rethrowFromSystemServer();
Jeff Sharkeybb580672014-07-10 12:10:25 -0700610 }
611 }
612
Chandan Nathe8e463b2019-01-28 15:23:38 +0000613 /**
614 * Install the given package, which already exists on the device, for the user for which this
615 * installer was created.
616 *
Philip P. Moltmanna4bd1502019-05-13 17:10:46 -0700617 * <p>This will
618 * {@link PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set) whitelist
619 * all restricted permissions}.
620 *
Chandan Nathe8e463b2019-01-28 15:23:38 +0000621 * @param packageName The package to install.
622 * @param installReason Reason for install.
623 * @param statusReceiver Where to deliver the result.
624 */
625 @RequiresPermission(allOf = {
626 Manifest.permission.INSTALL_PACKAGES,
627 Manifest.permission.INSTALL_EXISTING_PACKAGES})
628 public void installExistingPackage(@NonNull String packageName,
629 @InstallReason int installReason,
630 @Nullable IntentSender statusReceiver) {
631 Preconditions.checkNotNull(packageName, "packageName cannot be null");
632 try {
Philip P. Moltmanna4bd1502019-05-13 17:10:46 -0700633 mInstaller.installExistingPackage(packageName,
634 PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS, installReason,
635 statusReceiver, mUserId, null);
Chandan Nathe8e463b2019-01-28 15:23:38 +0000636 } catch (RemoteException e) {
637 throw e.rethrowFromSystemServer();
638 }
639 }
640
641
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700642 /** {@hide} */
Todd Kennedy04cc1912017-03-03 13:05:12 -0800643 @SystemApi
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600644 @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700645 public void setPermissionsResult(int sessionId, boolean accepted) {
646 try {
647 mInstaller.setPermissionsResult(sessionId, accepted);
648 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700649 throw e.rethrowFromSystemServer();
Jeff Sharkey7328a1b2014-08-07 14:01:43 -0700650 }
651 }
652
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700653 /**
654 * Events for observing session lifecycle.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700655 * <p>
656 * A typical session lifecycle looks like this:
657 * <ul>
658 * <li>An installer creates a session to indicate pending app delivery. All
659 * install details are available at this point.
660 * <li>The installer opens the session to deliver APK data. Note that a
661 * session may be opened and closed multiple times as network connectivity
662 * changes. The installer may deliver periodic progress updates.
663 * <li>The installer commits or abandons the session, resulting in the
664 * session being finished.
665 * </ul>
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700666 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700667 public static abstract class SessionCallback {
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700668 /**
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700669 * New session has been created. Details about the session can be
670 * obtained from {@link PackageInstaller#getSessionInfo(int)}.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700671 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700672 public abstract void onCreated(int sessionId);
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700673
674 /**
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700675 * Badging details for an existing session has changed. For example, the
676 * app icon or label has been updated.
677 */
678 public abstract void onBadgingChanged(int sessionId);
679
680 /**
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700681 * Active state for session has been changed.
682 * <p>
683 * A session is considered active whenever there is ongoing forward
684 * progress being made, such as the installer holding an open
685 * {@link Session} instance while streaming data into place, or the
686 * system optimizing code as the result of
687 * {@link Session#commit(IntentSender)}.
688 * <p>
689 * If the installer closes the {@link Session} without committing, the
690 * session is considered inactive until the installer opens the session
691 * again.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700692 */
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700693 public abstract void onActiveChanged(int sessionId, boolean active);
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700694
695 /**
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700696 * Progress for given session has been updated.
697 * <p>
698 * Note that this progress may not directly correspond to the value
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700699 * reported by
700 * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
701 * system may carve out a portion of the overall progress to represent
702 * its own internal installation work.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700703 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700704 public abstract void onProgressChanged(int sessionId, float progress);
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700705
706 /**
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700707 * Session has completely finished, either with success or failure.
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700708 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700709 public abstract void onFinished(int sessionId, boolean success);
Jeff Sharkeybb580672014-07-10 12:10:25 -0700710 }
711
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700712 /** {@hide} */
Jon Miranda2b340a22019-01-25 14:03:49 -0800713 static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700714 private static final int MSG_SESSION_CREATED = 1;
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700715 private static final int MSG_SESSION_BADGING_CHANGED = 2;
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700716 private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700717 private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700718 private static final int MSG_SESSION_FINISHED = 5;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700719
720 final SessionCallback mCallback;
Jon Miranda2b340a22019-01-25 14:03:49 -0800721 final Executor mExecutor;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700722
Jon Miranda2b340a22019-01-25 14:03:49 -0800723 SessionCallbackDelegate(SessionCallback callback, Executor executor) {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700724 mCallback = callback;
Jon Miranda2b340a22019-01-25 14:03:49 -0800725 mExecutor = executor;
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700726 }
727
728 @Override
729 public void onSessionCreated(int sessionId) {
Jon Miranda2b340a22019-01-25 14:03:49 -0800730 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onCreated, mCallback,
731 sessionId).recycleOnUse());
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700732 }
733
734 @Override
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700735 public void onSessionBadgingChanged(int sessionId) {
Jon Miranda2b340a22019-01-25 14:03:49 -0800736 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onBadgingChanged,
737 mCallback, sessionId).recycleOnUse());
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700738 }
739
740 @Override
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700741 public void onSessionActiveChanged(int sessionId, boolean active) {
Jon Miranda2b340a22019-01-25 14:03:49 -0800742 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onActiveChanged,
743 mCallback, sessionId, active).recycleOnUse());
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700744 }
745
746 @Override
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700747 public void onSessionProgressChanged(int sessionId, float progress) {
Jon Miranda2b340a22019-01-25 14:03:49 -0800748 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onProgressChanged,
749 mCallback, sessionId, progress).recycleOnUse());
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700750 }
751
752 @Override
753 public void onSessionFinished(int sessionId, boolean success) {
Jon Miranda2b340a22019-01-25 14:03:49 -0800754 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onFinished,
755 mCallback, sessionId, success).recycleOnUse());
Jeff Sharkeybb580672014-07-10 12:10:25 -0700756 }
757 }
758
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700759 /** {@hide} */
760 @Deprecated
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700761 public void addSessionCallback(@NonNull SessionCallback callback) {
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700762 registerSessionCallback(callback);
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700763 }
764
765 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700766 * Register to watch for session lifecycle events. No special permissions
767 * are required to watch for these events.
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700768 */
769 public void registerSessionCallback(@NonNull SessionCallback callback) {
770 registerSessionCallback(callback, new Handler());
771 }
772
773 /** {@hide} */
774 @Deprecated
775 public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
776 registerSessionCallback(callback, handler);
777 }
778
779 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700780 * Register to watch for session lifecycle events. No special permissions
781 * are required to watch for these events.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700782 *
783 * @param handler to dispatch callback events through, otherwise uses
784 * calling thread.
785 */
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700786 public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700787 synchronized (mDelegates) {
788 final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
Jon Miranda2b340a22019-01-25 14:03:49 -0800789 new HandlerExecutor(handler));
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700790 try {
791 mInstaller.registerCallback(delegate, mUserId);
792 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700793 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700794 }
795 mDelegates.add(delegate);
796 }
797 }
798
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700799 /** {@hide} */
800 @Deprecated
801 public void removeSessionCallback(@NonNull SessionCallback callback) {
802 unregisterSessionCallback(callback);
803 }
804
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700805 /**
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700806 * Unregister a previously registered callback.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700807 */
Jeff Sharkeyec9bad22014-09-05 09:45:20 -0700808 public void unregisterSessionCallback(@NonNull SessionCallback callback) {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700809 synchronized (mDelegates) {
810 for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
811 final SessionCallbackDelegate delegate = i.next();
812 if (delegate.mCallback == callback) {
813 try {
814 mInstaller.unregisterCallback(delegate);
815 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700816 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700817 }
818 i.remove();
819 }
820 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700821 }
822 }
823
824 /**
825 * An installation that is being actively staged. For an install to succeed,
826 * all existing and new packages must have identical package names, version
827 * codes, and signing certificates.
828 * <p>
829 * A session may contain any number of split packages. If the application
830 * does not yet exist, this session must include a base package.
831 * <p>
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700832 * If an APK included in this session is already defined by the existing
833 * installation (for example, the same split name), the APK in this session
834 * will replace the existing APK.
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000835 * <p>
Patrick Baumann2e887a12019-04-10 13:36:57 -0700836 * In such a case that multiple packages need to be committed simultaneously,
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000837 * multiple sessions can be referenced by a single multi-package session.
838 * This session is created with no package name and calling
Patrick Baumann2e887a12019-04-10 13:36:57 -0700839 * {@link SessionParams#setMultiPackage()}. The individual session IDs can be
840 * added with {@link #addChildSessionId(int)} and commit of the multi-package
841 * session will result in all child sessions being committed atomically.
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700842 */
Jeff Sharkeyec55ef02014-07-08 11:28:00 -0700843 public static class Session implements Closeable {
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000844 /** {@hide} */
845 protected final IPackageInstallerSession mSession;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700846
847 /** {@hide} */
848 public Session(IPackageInstallerSession session) {
849 mSession = session;
850 }
851
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700852 /** {@hide} */
853 @Deprecated
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700854 public void setProgress(float progress) {
Jeff Sharkeybc7bce32014-09-05 15:53:05 -0700855 setStagingProgress(progress);
856 }
857
858 /**
859 * Set current progress of staging this session. Valid values are
860 * anywhere between 0 and 1.
861 * <p>
862 * Note that this progress may not directly correspond to the value
863 * reported by {@link SessionCallback#onProgressChanged(int, float)}, as
864 * the system may carve out a portion of the overall progress to
865 * represent its own internal installation work.
866 */
867 public void setStagingProgress(float progress) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700868 try {
Jeff Sharkeya1031142014-07-12 18:09:46 -0700869 mSession.setClientProgress(progress);
870 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700871 throw e.rethrowFromSystemServer();
Jeff Sharkeya1031142014-07-12 18:09:46 -0700872 }
873 }
874
875 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100876 @UnsupportedAppUsage
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700877 public void addProgress(float progress) {
Jeff Sharkeya1031142014-07-12 18:09:46 -0700878 try {
879 mSession.addClientProgress(progress);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700880 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700881 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700882 }
883 }
884
Jeff Sharkey78cc3402014-05-22 10:52:49 -0700885 /**
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700886 * Open a stream to write an APK file into the session.
887 * <p>
888 * The returned stream will start writing data at the requested offset
889 * in the underlying file, which can be used to resume a partially
890 * written file. If a valid file length is specified, the system will
891 * preallocate the underlying disk space to optimize placement on disk.
892 * It's strongly recommended to provide a valid file length when known.
893 * <p>
894 * You can write data into the returned stream, optionally call
895 * {@link #fsync(OutputStream)} as needed to ensure bytes have been
896 * persisted to disk, and then close when finished. All streams must be
Jeff Sharkeya0907432014-08-15 10:23:11 -0700897 * closed before calling {@link #commit(IntentSender)}.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700898 *
899 * @param name arbitrary, unique name of your choosing to identify the
900 * APK being written. You can open a file again for
901 * additional writes (such as after a reboot) by using the
902 * same name. This name is only meaningful within the context
903 * of a single install session.
904 * @param offsetBytes offset into the file to begin writing at, or 0 to
905 * start at the beginning of the file.
906 * @param lengthBytes total size of the file being written, used to
907 * preallocate the underlying disk space, or -1 if unknown.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700908 * The system may clear various caches as needed to allocate
909 * this space.
910 * @throws IOException if trouble opening the file for writing, such as
911 * lack of disk space or unavailable media.
912 * @throws SecurityException if called after the session has been
Philip P. Moltmann7460c592017-08-08 20:07:11 +0000913 * sealed or abandoned
Jeff Sharkey78cc3402014-05-22 10:52:49 -0700914 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700915 public @NonNull OutputStream openWrite(@NonNull String name, long offsetBytes,
916 long lengthBytes) throws IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700917 try {
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700918 if (ENABLE_REVOCABLE_FD) {
919 return new ParcelFileDescriptor.AutoCloseOutputStream(
920 mSession.openWrite(name, offsetBytes, lengthBytes));
921 } else {
922 final ParcelFileDescriptor clientSocket = mSession.openWrite(name,
923 offsetBytes, lengthBytes);
924 return new FileBridge.FileBridgeOutputStream(clientSocket);
925 }
Jeff Sharkeya1031142014-07-12 18:09:46 -0700926 } catch (RuntimeException e) {
927 ExceptionUtils.maybeUnwrapIOException(e);
928 throw e;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700929 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700930 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700931 }
Jeff Sharkey0451de62018-02-02 11:27:21 -0700932 }
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700933
Jeff Sharkey0451de62018-02-02 11:27:21 -0700934 /** {@hide} */
935 public void write(@NonNull String name, long offsetBytes, long lengthBytes,
936 @NonNull ParcelFileDescriptor fd) throws IOException {
937 try {
938 mSession.write(name, offsetBytes, lengthBytes, fd);
939 } catch (RuntimeException e) {
940 ExceptionUtils.maybeUnwrapIOException(e);
941 throw e;
942 } catch (RemoteException e) {
943 throw e.rethrowFromSystemServer();
944 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700945 }
946
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700947 /**
948 * Ensure that any outstanding data for given stream has been committed
949 * to disk. This is only valid for streams returned from
950 * {@link #openWrite(String, long, long)}.
951 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -0700952 public void fsync(@NonNull OutputStream out) throws IOException {
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700953 if (ENABLE_REVOCABLE_FD) {
954 if (out instanceof ParcelFileDescriptor.AutoCloseOutputStream) {
955 try {
956 Os.fsync(((ParcelFileDescriptor.AutoCloseOutputStream) out).getFD());
957 } catch (ErrnoException e) {
958 throw e.rethrowAsIOException();
959 }
960 } else {
961 throw new IllegalArgumentException("Unrecognized stream");
962 }
Jeff Sharkeya1031142014-07-12 18:09:46 -0700963 } else {
Jeff Sharkey02d4e342017-03-10 21:53:48 -0700964 if (out instanceof FileBridge.FileBridgeOutputStream) {
965 ((FileBridge.FileBridgeOutputStream) out).fsync();
966 } else {
967 throw new IllegalArgumentException("Unrecognized stream");
968 }
Jeff Sharkeya1031142014-07-12 18:09:46 -0700969 }
970 }
971
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700972 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -0700973 * Return all APK names contained in this session.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700974 * <p>
975 * This returns all names which have been previously written through
976 * {@link #openWrite(String, long, long)} as part of this session.
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 */
Jeff Sharkey742e7902014-08-16 19:09:13 -0700981 public @NonNull String[] getNames() throws IOException {
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700982 try {
Jeff Sharkeya0907432014-08-15 10:23:11 -0700983 return mSession.getNames();
Jeff Sharkey742e7902014-08-16 19:09:13 -0700984 } catch (RuntimeException e) {
985 ExceptionUtils.maybeUnwrapIOException(e);
986 throw e;
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700987 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700988 throw e.rethrowFromSystemServer();
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -0700989 }
990 }
991
992 /**
993 * Open a stream to read an APK file from the session.
994 * <p>
995 * This is only valid for names which have been previously written
996 * through {@link #openWrite(String, long, long)} as part of this
997 * session. For example, this stream may be used to calculate a
998 * {@link MessageDigest} of a written APK before committing.
Jeff Sharkey77d218e2014-09-06 12:20:37 -0700999 *
1000 * @throws SecurityException if called after the session has been
1001 * committed or abandoned.
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -07001002 */
1003 public @NonNull InputStream openRead(@NonNull String name) throws IOException {
1004 try {
1005 final ParcelFileDescriptor pfd = mSession.openRead(name);
1006 return new ParcelFileDescriptor.AutoCloseInputStream(pfd);
1007 } catch (RuntimeException e) {
1008 ExceptionUtils.maybeUnwrapIOException(e);
1009 throw e;
1010 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001011 throw e.rethrowFromSystemServer();
Jeff Sharkey1cb2d0d2014-07-30 16:45:01 -07001012 }
1013 }
1014
1015 /**
Todd Kennedyeb9b0532016-03-08 10:10:54 -08001016 * Removes a split.
1017 * <p>
1018 * Split removals occur prior to adding new APKs. If upgrading a feature
1019 * split, it is not expected nor desirable to remove the split prior to
1020 * upgrading.
1021 * <p>
1022 * When split removal is bundled with new APKs, the packageName must be
1023 * identical.
1024 */
1025 public void removeSplit(@NonNull String splitName) throws IOException {
1026 try {
1027 mSession.removeSplit(splitName);
1028 } catch (RuntimeException e) {
1029 ExceptionUtils.maybeUnwrapIOException(e);
1030 throw e;
1031 } catch (RemoteException e) {
1032 throw e.rethrowFromSystemServer();
1033 }
1034 }
1035
1036 /**
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001037 * Attempt to commit everything staged in this session. This may require
1038 * user intervention, and so it may not happen immediately. The final
1039 * result of the commit will be reported through the given callback.
1040 * <p>
Todd Kennedy04cc1912017-03-03 13:05:12 -08001041 * Once this method is called, the session is sealed and no additional
1042 * mutations may be performed on the session. If the device reboots
1043 * before the session has been finalized, you may commit the session again.
Tony Mak366ee622018-02-12 17:52:34 +00001044 * <p>
1045 * If the installer is the device owner or the affiliated profile owner, there will be no
1046 * user intervention.
Jeff Sharkey77d218e2014-09-06 12:20:37 -07001047 *
Philip P. Moltmann2fe7dee2018-09-14 08:45:42 -07001048 * @param statusReceiver Called when the state of the session changes. Intents
1049 * sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
1050 * individual status codes on how to handle them.
1051 *
Jeff Sharkey77d218e2014-09-06 12:20:37 -07001052 * @throws SecurityException if streams opened through
1053 * {@link #openWrite(String, long, long)} are still open.
Tony Mak366ee622018-02-12 17:52:34 +00001054 *
1055 * @see android.app.admin.DevicePolicyManager
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001056 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001057 public void commit(@NonNull IntentSender statusReceiver) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001058 try {
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001059 mSession.commit(statusReceiver, false);
1060 } catch (RemoteException e) {
1061 throw e.rethrowFromSystemServer();
1062 }
1063 }
1064
1065 /**
1066 * Attempt to commit a session that has been {@link #transfer(String) transferred}.
1067 *
1068 * <p>If the device reboots before the session has been finalized, you may commit the
1069 * session again.
1070 *
1071 * <p>The caller of this method is responsible to ensure the safety of the session. As the
1072 * session was created by another - usually less trusted - app, it is paramount that before
1073 * committing <u>all</u> public and system {@link SessionInfo properties of the session}
1074 * and <u>all</u> {@link #openRead(String) APKs} are verified by the caller. It might happen
1075 * that new properties are added to the session with a new API revision. In this case the
1076 * callers need to be updated.
1077 *
Philip P. Moltmann2fe7dee2018-09-14 08:45:42 -07001078 * @param statusReceiver Called when the state of the session changes. Intents
1079 * sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
1080 * individual status codes on how to handle them.
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001081 *
1082 * @hide
1083 */
1084 @SystemApi
1085 @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
1086 public void commitTransferred(@NonNull IntentSender statusReceiver) {
1087 try {
1088 mSession.commit(statusReceiver, true);
1089 } catch (RemoteException e) {
1090 throw e.rethrowFromSystemServer();
1091 }
1092 }
1093
1094 /**
1095 * Transfer the session to a new owner.
1096 * <p>
1097 * Only sessions that update the installing app can be transferred.
1098 * <p>
1099 * After the transfer to a package with a different uid all method calls on the session
1100 * will cause {@link SecurityException}s.
1101 * <p>
1102 * Once this method is called, the session is sealed and no additional mutations beside
1103 * committing it may be performed on the session.
1104 *
1105 * @param packageName The package of the new owner. Needs to hold the INSTALL_PACKAGES
1106 * permission.
1107 *
1108 * @throws PackageManager.NameNotFoundException if the new owner could not be found.
1109 * @throws SecurityException if called after the session has been committed or abandoned.
1110 * @throws SecurityException if the session does not update the original installer
1111 * @throws SecurityException if streams opened through
1112 * {@link #openWrite(String, long, long) are still open.
1113 */
1114 public void transfer(@NonNull String packageName)
1115 throws PackageManager.NameNotFoundException {
1116 Preconditions.checkNotNull(packageName);
1117
1118 try {
1119 mSession.transfer(packageName);
1120 } catch (ParcelableException e) {
1121 e.maybeRethrow(PackageManager.NameNotFoundException.class);
1122 throw new RuntimeException(e);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001123 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001124 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001125 }
1126 }
1127
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001128 /**
1129 * Release this session object. You can open the session again if it
1130 * hasn't been finalized.
1131 */
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001132 @Override
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001133 public void close() {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001134 try {
1135 mSession.close();
1136 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001137 throw e.rethrowFromSystemServer();
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001138 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001139 }
1140
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001141 /**
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001142 * Completely abandon this session, destroying all staged data and
Jeff Sharkey77d218e2014-09-06 12:20:37 -07001143 * rendering it invalid. Abandoned sessions will be reported to
1144 * {@link SessionCallback} listeners as failures. This is equivalent to
1145 * opening the session and calling {@link Session#abandon()}.
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001146 */
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001147 public void abandon() {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001148 try {
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001149 mSession.abandon();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001150 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001151 throw e.rethrowFromSystemServer();
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001152 }
1153 }
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001154
1155 /**
1156 * @return {@code true} if this session will commit more than one package when it is
1157 * committed.
1158 */
1159 public boolean isMultiPackage() {
1160 try {
1161 return mSession.isMultiPackage();
1162 } catch (RemoteException e) {
1163 throw e.rethrowFromSystemServer();
1164 }
1165 }
1166
1167 /**
Dario Freniaac4ba42018-12-06 15:47:16 +00001168 * @return {@code true} if this session will be staged and applied at next reboot.
1169 */
1170 public boolean isStaged() {
1171 try {
1172 return mSession.isStaged();
1173 } catch (RemoteException e) {
1174 throw e.rethrowFromSystemServer();
1175 }
1176 }
1177
1178 /**
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001179 * @return the session ID of the multi-package session that this belongs to or
1180 * {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session.
1181 */
1182 public int getParentSessionId() {
1183 try {
1184 return mSession.getParentSessionId();
1185 } catch (RemoteException e) {
1186 throw e.rethrowFromSystemServer();
1187 }
1188 }
1189
1190 /**
1191 * @return the set of session IDs that will be committed atomically when this session is
1192 * committed if this is a multi-package session or null if none exist.
1193 */
1194 @NonNull
1195 public int[] getChildSessionIds() {
1196 try {
1197 return mSession.getChildSessionIds();
1198 } catch (RemoteException e) {
1199 throw e.rethrowFromSystemServer();
1200 }
1201 }
1202
1203 /**
1204 * Adds a session ID to the set of sessions that will be committed atomically
1205 * when this session is committed.
1206 *
shafik43f1af92019-03-14 15:14:00 +00001207 * <p>If the parent is staged or has rollback enabled, all children must have
1208 * the same properties.
1209 *
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001210 * @param sessionId the session ID to add to this multi-package session.
1211 */
1212 public void addChildSessionId(int sessionId) {
1213 try {
1214 mSession.addChildSessionId(sessionId);
1215 } catch (RemoteException e) {
Patrick Baumann00321b72019-04-09 15:07:25 -07001216 e.rethrowFromSystemServer();
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001217 }
1218 }
1219
1220 /**
1221 * Removes a session ID from the set of sessions that will be committed
1222 * atomically when this session is committed.
1223 *
1224 * @param sessionId the session ID to remove from this multi-package session.
1225 */
1226 public void removeChildSessionId(int sessionId) {
1227 try {
1228 mSession.removeChildSessionId(sessionId);
1229 } catch (RemoteException e) {
Patrick Baumann00321b72019-04-09 15:07:25 -07001230 e.rethrowFromSystemServer();
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001231 }
1232 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001233 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001234
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001235 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001236 * Parameters for creating a new {@link PackageInstaller.Session}.
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001237 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001238 public static class SessionParams implements Parcelable {
1239
1240 /** {@hide} */
1241 public static final int MODE_INVALID = -1;
Jeff Sharkeyf0600952014-08-07 17:31:53 -07001242
1243 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001244 * Mode for an install session whose staged APKs should fully replace any
1245 * existing APKs for the target app.
Jeff Sharkeyf0600952014-08-07 17:31:53 -07001246 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001247 public static final int MODE_FULL_INSTALL = 1;
Jeff Sharkeyf0600952014-08-07 17:31:53 -07001248
1249 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001250 * Mode for an install session that should inherit any existing APKs for the
1251 * target app, unless they have been explicitly overridden (based on split
1252 * name) by the session. For example, this can be used to add one or more
1253 * split APKs to an existing installation.
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07001254 * <p>
Jeff Sharkeya0907432014-08-15 10:23:11 -07001255 * If there are no existing APKs for the target app, this behaves like
1256 * {@link #MODE_FULL_INSTALL}.
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07001257 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001258 public static final int MODE_INHERIT_EXISTING = 2;
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07001259
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001260 /**
1261 * Special constant to refer to all restricted permissions.
1262 */
1263 public static final @NonNull Set<String> RESTRICTED_PERMISSIONS_ALL = new ArraySet<>();
1264
Jeff Sharkeya0907432014-08-15 10:23:11 -07001265 /** {@hide} */
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001266 public static final int UID_UNKNOWN = -1;
1267
1268 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001269 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001270 public int mode = MODE_INVALID;
1271 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001272 @UnsupportedAppUsage
Svet Ganov83a3a4a2019-05-03 18:50:43 -07001273 public int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
Jeff Sharkeya0907432014-08-15 10:23:11 -07001274 /** {@hide} */
1275 public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
1276 /** {@hide} */
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001277 public @InstallReason int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
Bartosz Fabianowskia34f53f2017-01-11 18:08:47 +01001278 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001279 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001280 public long sizeBytes = -1;
1281 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001282 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001283 public String appPackageName;
1284 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001285 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001286 public Bitmap appIcon;
1287 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001288 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001289 public String appLabel;
1290 /** {@hide} */
Jeff Sharkey02bd7842014-10-06 15:14:27 -07001291 public long appIconLastModified = -1;
1292 /** {@hide} */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001293 public Uri originatingUri;
1294 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001295 @UnsupportedAppUsage
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001296 public int originatingUid = UID_UNKNOWN;
1297 /** {@hide} */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001298 public Uri referrerUri;
1299 /** {@hide} */
1300 public String abiOverride;
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001301 /** {@hide} */
1302 public String volumeUuid;
Svet Ganov7121e182015-07-13 22:38:12 -07001303 /** {@hide} */
1304 public String[] grantedRuntimePermissions;
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001305 /** {@hide} */
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001306 public List<String> whitelistedRestrictedPermissions;
1307 /** {@hide} */
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001308 public String installerPackageName;
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001309 /** {@hide} */
1310 public boolean isMultiPackage;
Dario Freniaac4ba42018-12-06 15:47:16 +00001311 /** {@hide} */
1312 public boolean isStaged;
Richard Uhler2124d4b2019-04-25 13:01:39 +01001313 /** {@hide} */
1314 public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST;
Jeff Sharkeybb580672014-07-10 12:10:25 -07001315
Jeff Sharkeya0907432014-08-15 10:23:11 -07001316 /**
1317 * Construct parameters for a new package install session.
1318 *
1319 * @param mode one of {@link #MODE_FULL_INSTALL} or
1320 * {@link #MODE_INHERIT_EXISTING} describing how the session
1321 * should interact with an existing app.
1322 */
1323 public SessionParams(int mode) {
1324 this.mode = mode;
1325 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001326
Jeff Sharkeya0907432014-08-15 10:23:11 -07001327 /** {@hide} */
1328 public SessionParams(Parcel source) {
1329 mode = source.readInt();
1330 installFlags = source.readInt();
1331 installLocation = source.readInt();
Bartosz Fabianowskia34f53f2017-01-11 18:08:47 +01001332 installReason = source.readInt();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001333 sizeBytes = source.readLong();
1334 appPackageName = source.readString();
1335 appIcon = source.readParcelable(null);
1336 appLabel = source.readString();
1337 originatingUri = source.readParcelable(null);
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001338 originatingUid = source.readInt();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001339 referrerUri = source.readParcelable(null);
1340 abiOverride = source.readString();
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001341 volumeUuid = source.readString();
Svet Ganov7121e182015-07-13 22:38:12 -07001342 grantedRuntimePermissions = source.readStringArray();
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001343 whitelistedRestrictedPermissions = source.createStringArrayList();
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001344 installerPackageName = source.readString();
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001345 isMultiPackage = source.readBoolean();
Dario Freniaac4ba42018-12-06 15:47:16 +00001346 isStaged = source.readBoolean();
Richard Uhler2124d4b2019-04-25 13:01:39 +01001347 requiredInstalledVersionCode = source.readLong();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001348 }
1349
Dario Freni4b572c02019-01-29 09:40:31 +00001350 /** {@hide} */
1351 public SessionParams copy() {
1352 SessionParams ret = new SessionParams(mode);
1353 ret.installFlags = installFlags;
1354 ret.installLocation = installLocation;
1355 ret.installReason = installReason;
1356 ret.sizeBytes = sizeBytes;
1357 ret.appPackageName = appPackageName;
1358 ret.appIcon = appIcon; // not a copy.
1359 ret.appLabel = appLabel;
1360 ret.originatingUri = originatingUri; // not a copy, but immutable.
1361 ret.originatingUid = originatingUid;
1362 ret.referrerUri = referrerUri; // not a copy, but immutable.
1363 ret.abiOverride = abiOverride;
1364 ret.volumeUuid = volumeUuid;
1365 ret.grantedRuntimePermissions = grantedRuntimePermissions;
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001366 ret.whitelistedRestrictedPermissions = whitelistedRestrictedPermissions;
Dario Freni4b572c02019-01-29 09:40:31 +00001367 ret.installerPackageName = installerPackageName;
1368 ret.isMultiPackage = isMultiPackage;
1369 ret.isStaged = isStaged;
Richard Uhler2124d4b2019-04-25 13:01:39 +01001370 ret.requiredInstalledVersionCode = requiredInstalledVersionCode;
Dario Freni4b572c02019-01-29 09:40:31 +00001371 return ret;
1372 }
1373
Jeff Sharkeya0907432014-08-15 10:23:11 -07001374 /**
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001375 * Check if there are hidden options set.
1376 *
1377 * <p>Hidden options are those options that cannot be verified via public or system-api
1378 * methods on {@link SessionInfo}.
1379 *
1380 * @return {@code true} if any hidden option is set.
1381 *
1382 * @hide
1383 */
1384 public boolean areHiddenOptionsSet() {
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00001385 return (installFlags & (PackageManager.INSTALL_REQUEST_DOWNGRADE
1386 | PackageManager.INSTALL_ALLOW_DOWNGRADE
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001387 | PackageManager.INSTALL_DONT_KILL_APP
1388 | PackageManager.INSTALL_INSTANT_APP
1389 | PackageManager.INSTALL_FULL_APP
1390 | PackageManager.INSTALL_VIRTUAL_PRELOAD
1391 | PackageManager.INSTALL_ALLOCATE_AGGRESSIVE)) != installFlags
1392 || abiOverride != null || volumeUuid != null;
1393 }
1394
1395 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001396 * Provide value of {@link PackageInfo#installLocation}, which may be used
1397 * to determine where the app will be staged. Defaults to
1398 * {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}.
1399 */
1400 public void setInstallLocation(int installLocation) {
1401 this.installLocation = installLocation;
1402 }
1403
1404 /**
1405 * Optionally indicate the total size (in bytes) of all APKs that will be
1406 * delivered in this session. The system may use this to ensure enough disk
1407 * space exists before proceeding, or to estimate container size for
1408 * installations living on external storage.
1409 *
1410 * @see PackageInfo#INSTALL_LOCATION_AUTO
1411 * @see PackageInfo#INSTALL_LOCATION_PREFER_EXTERNAL
1412 */
1413 public void setSize(long sizeBytes) {
1414 this.sizeBytes = sizeBytes;
1415 }
1416
1417 /**
1418 * Optionally set the package name of the app being installed. It's strongly
1419 * recommended that you provide this value when known, so that observers can
1420 * communicate installing apps to users.
1421 * <p>
1422 * If the APKs staged in the session aren't consistent with this package
1423 * name, the install will fail. Regardless of this value, all APKs in the
1424 * app must have the same package name.
1425 */
1426 public void setAppPackageName(@Nullable String appPackageName) {
1427 this.appPackageName = appPackageName;
1428 }
1429
1430 /**
1431 * Optionally set an icon representing the app being installed. This should
1432 * be roughly {@link ActivityManager#getLauncherLargeIconSize()} in both
1433 * dimensions.
1434 */
1435 public void setAppIcon(@Nullable Bitmap appIcon) {
1436 this.appIcon = appIcon;
1437 }
1438
1439 /**
1440 * Optionally set a label representing the app being installed.
1441 */
1442 public void setAppLabel(@Nullable CharSequence appLabel) {
1443 this.appLabel = (appLabel != null) ? appLabel.toString() : null;
1444 }
1445
1446 /**
Todd Kennedy1ed6b872016-03-10 10:07:00 -08001447 * Optionally set the URI where this package was downloaded from. This is
1448 * informational and may be used as a signal for anti-malware purposes.
Jeff Sharkeya0907432014-08-15 10:23:11 -07001449 *
1450 * @see Intent#EXTRA_ORIGINATING_URI
1451 */
1452 public void setOriginatingUri(@Nullable Uri originatingUri) {
1453 this.originatingUri = originatingUri;
1454 }
1455
1456 /**
Nikolas Bravo62831002017-11-07 21:07:15 +00001457 * Sets the UID that initiated the package installation. This is informational
Todd Kennedy1ed6b872016-03-10 10:07:00 -08001458 * and may be used as a signal for anti-malware purposes.
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001459 */
1460 public void setOriginatingUid(int originatingUid) {
1461 this.originatingUid = originatingUid;
1462 }
1463
1464 /**
Todd Kennedy1ed6b872016-03-10 10:07:00 -08001465 * Optionally set the URI that referred you to install this package. This is
1466 * informational and may be used as a signal for anti-malware purposes.
Jeff Sharkeya0907432014-08-15 10:23:11 -07001467 *
1468 * @see Intent#EXTRA_REFERRER
1469 */
1470 public void setReferrerUri(@Nullable Uri referrerUri) {
1471 this.referrerUri = referrerUri;
1472 }
1473
Svet Ganov7121e182015-07-13 22:38:12 -07001474 /**
1475 * Sets which runtime permissions to be granted to the package at installation.
Svet Ganov7121e182015-07-13 22:38:12 -07001476 *
1477 * @param permissions The permissions to grant or null to grant all runtime
1478 * permissions.
1479 *
1480 * @hide
1481 */
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001482 @TestApi
Svet Ganov7121e182015-07-13 22:38:12 -07001483 @SystemApi
1484 @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS)
1485 public void setGrantedRuntimePermissions(String[] permissions) {
1486 installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
1487 this.grantedRuntimePermissions = permissions;
1488 }
1489
Richard Uhlerb29f1452018-09-12 16:38:15 +01001490 /**
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001491 * Sets which restricted permissions to be whitelisted for the app. Whitelisting
1492 * is not granting the permissions, rather it allows the app to hold permissions
1493 * which are otherwise restricted. Whitelisting a non restricted permission has
1494 * no effect.
1495 *
1496 * <p> Permissions can be hard restricted which means that the app cannot hold
1497 * them or soft restricted where the app can hold the permission but in a weaker
1498 * form. Whether a permission is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard
1499 * restricted} or {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted}
1500 * depends on the permission declaration. Whitelisting a hard restricted permission
1501 * allows the app to hold that permission and whitelisting a soft restricted
1502 * permission allows the app to hold the permission in its full, unrestricted form.
1503 *
Svet Ganovd563e932019-04-14 13:07:41 -07001504 * <p> Permissions can also be immutably restricted which means that the whitelist
1505 * state of the permission can be determined only at install time and cannot be
1506 * changed on updated or at a later point via the package manager APIs.
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001507 *
Svet Ganov83a3a4a2019-05-03 18:50:43 -07001508 * <p>Initially, all restricted permissions are whitelisted but you can change
1509 * which ones are whitelisted by calling this method or the corresponding ones
1510 * on the {@link PackageManager}.
1511 *
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001512 * @see PackageManager#addWhitelistedRestrictedPermission(String, String, int)
1513 * @see PackageManager#removeWhitelistedRestrictedPermission(String, String, int)
1514 */
1515 public void setWhitelistedRestrictedPermissions(@Nullable Set<String> permissions) {
1516 if (permissions == RESTRICTED_PERMISSIONS_ALL) {
1517 installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
Svet Ganov83a3a4a2019-05-03 18:50:43 -07001518 whitelistedRestrictedPermissions = null;
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001519 } else {
1520 installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
Svet Ganov83a3a4a2019-05-03 18:50:43 -07001521 whitelistedRestrictedPermissions = (permissions != null)
1522 ? new ArrayList<>(permissions) : null;
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001523 }
1524 }
1525
1526 /**
shafik92ea53f2019-03-08 18:05:59 +00001527 * Request that rollbacks be enabled or disabled for the given upgrade.
1528 *
shafik43f1af92019-03-14 15:14:00 +00001529 * <p>If the parent session is staged or has rollback enabled, all children sessions
1530 * must have the same properties.
1531 *
shafik92ea53f2019-03-08 18:05:59 +00001532 * @param enable set to {@code true} to enable, {@code false} to disable
1533 * @hide
1534 */
Richard Uhler8a977452019-03-08 13:27:17 +00001535 @SystemApi @TestApi
shafik92ea53f2019-03-08 18:05:59 +00001536 public void setEnableRollback(boolean enable) {
1537 if (enable) {
1538 installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
1539 } else {
1540 installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
1541 }
1542 }
1543
1544 /**
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00001545 * @deprecated use {@link #setRequestDowngrade(boolean)}.
1546 * {@hide}
1547 */
1548 @SystemApi
1549 @Deprecated
1550 public void setAllowDowngrade(boolean allowDowngrade) {
1551 setRequestDowngrade(allowDowngrade);
1552 }
1553
Jeff Sharkeya0907432014-08-15 10:23:11 -07001554 /** {@hide} */
Todd Kennedyc84d1ab2016-03-11 11:37:17 -08001555 @SystemApi
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00001556 public void setRequestDowngrade(boolean requestDowngrade) {
1557 if (requestDowngrade) {
1558 installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
Todd Kennedy948b7022016-03-14 14:29:52 -07001559 } else {
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00001560 installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE;
Todd Kennedy948b7022016-03-14 14:29:52 -07001561 }
Todd Kennedyc84d1ab2016-03-11 11:37:17 -08001562 }
1563
Richard Uhler2124d4b2019-04-25 13:01:39 +01001564 /**
1565 * Require the given version of the package be installed.
1566 * The install will only be allowed if the existing version code of
1567 * the package installed on the device matches the given version code.
1568 * Use {@link * PackageManager#VERSION_CODE_HIGHEST} to allow
1569 * installation regardless of the currently installed package version.
1570 *
1571 * @hide
1572 */
1573 public void setRequiredInstalledVersionCode(long versionCode) {
1574 requiredInstalledVersionCode = versionCode;
1575 }
1576
Todd Kennedyc84d1ab2016-03-11 11:37:17 -08001577 /** {@hide} */
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001578 public void setInstallFlagsForcePermissionPrompt() {
1579 installFlags |= PackageManager.INSTALL_FORCE_PERMISSION_PROMPT;
1580 }
1581
1582 /** {@hide} */
Todd Kennedy24ca5c62016-03-16 15:42:01 -07001583 @SystemApi
1584 public void setDontKillApp(boolean dontKillApp) {
1585 if (dontKillApp) {
1586 installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
1587 } else {
1588 installFlags &= ~PackageManager.INSTALL_DONT_KILL_APP;
1589 }
Todd Kennedy39bfee52016-02-24 10:28:21 -08001590 }
1591
1592 /** {@hide} */
Todd Kennedyb7717682016-11-30 15:41:21 -08001593 @SystemApi
1594 public void setInstallAsInstantApp(boolean isInstantApp) {
1595 if (isInstantApp) {
Todd Kennedybe0b8892017-02-15 14:13:52 -08001596 installFlags |= PackageManager.INSTALL_INSTANT_APP;
1597 installFlags &= ~PackageManager.INSTALL_FULL_APP;
Todd Kennedyb7717682016-11-30 15:41:21 -08001598 } else {
Todd Kennedybe0b8892017-02-15 14:13:52 -08001599 installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
1600 installFlags |= PackageManager.INSTALL_FULL_APP;
Todd Kennedyb7717682016-11-30 15:41:21 -08001601 }
1602 }
1603
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001604 /**
Todd Kennedy78a72502017-07-19 12:49:30 -07001605 * Sets the install as a virtual preload. Will only have effect when called
1606 * by the verifier.
1607 * {@hide}
1608 */
1609 @SystemApi
1610 public void setInstallAsVirtualPreload() {
1611 installFlags |= PackageManager.INSTALL_VIRTUAL_PRELOAD;
1612 }
1613
1614 /**
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001615 * Set the reason for installing this package.
Todd Kennedy5fdbabb2018-03-07 15:59:41 -08001616 * <p>
1617 * The install reason should be a pre-defined integer. The behavior is
1618 * undefined if other values are used.
1619 *
Aurimas Liutikas7f695332018-05-31 21:07:32 -07001620 * @see PackageManager#INSTALL_REASON_UNKNOWN
1621 * @see PackageManager#INSTALL_REASON_POLICY
1622 * @see PackageManager#INSTALL_REASON_DEVICE_RESTORE
1623 * @see PackageManager#INSTALL_REASON_DEVICE_SETUP
Todd Kennedy5fdbabb2018-03-07 15:59:41 -08001624 * @see PackageManager#INSTALL_REASON_USER
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001625 */
1626 public void setInstallReason(@InstallReason int installReason) {
Bartosz Fabianowskia34f53f2017-01-11 18:08:47 +01001627 this.installReason = installReason;
1628 }
1629
Todd Kennedyb7717682016-11-30 15:41:21 -08001630 /** {@hide} */
Jeff Sharkey683bcd32017-03-18 17:54:51 -06001631 @SystemApi
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -06001632 @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE)
Jeff Sharkey683bcd32017-03-18 17:54:51 -06001633 public void setAllocateAggressive(boolean allocateAggressive) {
1634 if (allocateAggressive) {
1635 installFlags |= PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
1636 } else {
1637 installFlags &= ~PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
1638 }
1639 }
1640
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001641 /**
1642 * Set the installer package for the app.
1643 *
1644 * By default this is the app that created the {@link PackageInstaller} object.
1645 *
1646 * @param installerPackageName name of the installer package
1647 * {@hide}
1648 */
1649 public void setInstallerPackageName(String installerPackageName) {
1650 this.installerPackageName = installerPackageName;
1651 }
1652
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001653 /**
1654 * Set this session to be the parent of a multi-package install.
1655 *
1656 * A multi-package install session contains no APKs and only references other install
1657 * sessions via ID. When a multi-package session is committed, all of its children
1658 * are committed to the system in an atomic manner. If any children fail to install,
1659 * all of them do, including the multi-package session.
1660 */
1661 public void setMultiPackage() {
1662 this.isMultiPackage = true;
1663 }
1664
Dario Freniaac4ba42018-12-06 15:47:16 +00001665 /**
1666 * Set this session to be staged to be installed at reboot.
1667 *
1668 * Staged sessions are scheduled to be installed at next reboot. Staged sessions can also be
1669 * multi-package. In that case, if any of the children sessions fail to install at reboot,
1670 * all the other children sessions are aborted as well.
Dario Freni77786d92019-02-08 17:26:05 +00001671 *
shafik43f1af92019-03-14 15:14:00 +00001672 * <p>If the parent session is staged or has rollback enabled, all children sessions
1673 * must have the same properties.
1674 *
Dario Freni77786d92019-02-08 17:26:05 +00001675 * {@hide}
Dario Freniaac4ba42018-12-06 15:47:16 +00001676 */
Richard Uhler8a977452019-03-08 13:27:17 +00001677 @SystemApi @TestApi
Dario Freni77786d92019-02-08 17:26:05 +00001678 @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
Dario Freniaac4ba42018-12-06 15:47:16 +00001679 public void setStaged() {
1680 this.isStaged = true;
1681 }
1682
Dario Freni3fa46d82019-01-23 19:31:47 +00001683 /**
1684 * Set this session to be installing an APEX package.
Nikita Ioffe4501c112019-02-22 11:51:09 +00001685 *
1686 * {@hide}
Dario Freni3fa46d82019-01-23 19:31:47 +00001687 */
Richard Uhler8a977452019-03-08 13:27:17 +00001688 @SystemApi @TestApi
Nikita Ioffe4501c112019-02-22 11:51:09 +00001689 @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
Dario Freni3fa46d82019-01-23 19:31:47 +00001690 public void setInstallAsApex() {
1691 installFlags |= PackageManager.INSTALL_APEX;
1692 }
1693
shafik43f1af92019-03-14 15:14:00 +00001694 /** @hide */
1695 public boolean getEnableRollback() {
1696 return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0;
1697 }
1698
Jeff Sharkey683bcd32017-03-18 17:54:51 -06001699 /** {@hide} */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001700 public void dump(IndentingPrintWriter pw) {
1701 pw.printPair("mode", mode);
1702 pw.printHexPair("installFlags", installFlags);
1703 pw.printPair("installLocation", installLocation);
1704 pw.printPair("sizeBytes", sizeBytes);
1705 pw.printPair("appPackageName", appPackageName);
1706 pw.printPair("appIcon", (appIcon != null));
1707 pw.printPair("appLabel", appLabel);
1708 pw.printPair("originatingUri", originatingUri);
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001709 pw.printPair("originatingUid", originatingUid);
Jeff Sharkeya0907432014-08-15 10:23:11 -07001710 pw.printPair("referrerUri", referrerUri);
1711 pw.printPair("abiOverride", abiOverride);
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001712 pw.printPair("volumeUuid", volumeUuid);
Svet Ganov7121e182015-07-13 22:38:12 -07001713 pw.printPair("grantedRuntimePermissions", grantedRuntimePermissions);
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001714 pw.printPair("whitelistedRestrictedPermissions", whitelistedRestrictedPermissions);
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001715 pw.printPair("installerPackageName", installerPackageName);
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001716 pw.printPair("isMultiPackage", isMultiPackage);
Dario Freniaac4ba42018-12-06 15:47:16 +00001717 pw.printPair("isStaged", isStaged);
Richard Uhler2124d4b2019-04-25 13:01:39 +01001718 pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode);
Jeff Sharkeya0907432014-08-15 10:23:11 -07001719 pw.println();
Jeff Sharkeybb580672014-07-10 12:10:25 -07001720 }
1721
1722 @Override
Jeff Sharkeya0907432014-08-15 10:23:11 -07001723 public int describeContents() {
1724 return 0;
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07001725 }
1726
1727 @Override
Jeff Sharkeya0907432014-08-15 10:23:11 -07001728 public void writeToParcel(Parcel dest, int flags) {
1729 dest.writeInt(mode);
1730 dest.writeInt(installFlags);
1731 dest.writeInt(installLocation);
Bartosz Fabianowskia34f53f2017-01-11 18:08:47 +01001732 dest.writeInt(installReason);
Jeff Sharkeya0907432014-08-15 10:23:11 -07001733 dest.writeLong(sizeBytes);
1734 dest.writeString(appPackageName);
1735 dest.writeParcelable(appIcon, flags);
1736 dest.writeString(appLabel);
1737 dest.writeParcelable(originatingUri, flags);
Todd Kennedya1d12cf2015-09-29 15:43:00 -07001738 dest.writeInt(originatingUid);
Jeff Sharkeya0907432014-08-15 10:23:11 -07001739 dest.writeParcelable(referrerUri, flags);
1740 dest.writeString(abiOverride);
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001741 dest.writeString(volumeUuid);
Svet Ganov7121e182015-07-13 22:38:12 -07001742 dest.writeStringArray(grantedRuntimePermissions);
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001743 dest.writeStringList(whitelistedRestrictedPermissions);
Philip P. Moltmann79c238a2017-12-13 15:59:07 -08001744 dest.writeString(installerPackageName);
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001745 dest.writeBoolean(isMultiPackage);
Dario Freniaac4ba42018-12-06 15:47:16 +00001746 dest.writeBoolean(isStaged);
Richard Uhler2124d4b2019-04-25 13:01:39 +01001747 dest.writeLong(requiredInstalledVersionCode);
Jeff Sharkeybb580672014-07-10 12:10:25 -07001748 }
Jeff Sharkeya0907432014-08-15 10:23:11 -07001749
1750 public static final Parcelable.Creator<SessionParams>
1751 CREATOR = new Parcelable.Creator<SessionParams>() {
1752 @Override
1753 public SessionParams createFromParcel(Parcel p) {
1754 return new SessionParams(p);
1755 }
1756
1757 @Override
1758 public SessionParams[] newArray(int size) {
1759 return new SessionParams[size];
1760 }
1761 };
Jeff Sharkeybb580672014-07-10 12:10:25 -07001762 }
1763
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001764 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001765 * Details for an active install session.
Jeff Sharkey6c833e02014-07-14 22:44:30 -07001766 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001767 public static class SessionInfo implements Parcelable {
1768
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001769 /**
1770 * A session ID that does not exist or is invalid.
1771 */
1772 public static final int INVALID_ID = -1;
1773 /** {@hide} */
1774 private static final int[] NO_SESSIONS = {};
Dario Freni71eee5e2018-12-06 15:47:16 +00001775
1776 /** @hide */
Dario Frenib6d28962019-01-31 15:52:24 +00001777 @IntDef(prefix = { "STAGED_SESSION_" }, value = {
1778 STAGED_SESSION_NO_ERROR,
1779 STAGED_SESSION_VERIFICATION_FAILED,
1780 STAGED_SESSION_ACTIVATION_FAILED,
1781 STAGED_SESSION_UNKNOWN})
Dario Freni71eee5e2018-12-06 15:47:16 +00001782 @Retention(RetentionPolicy.SOURCE)
1783 public @interface StagedSessionErrorCode{}
1784 /**
1785 * Constant indicating that no error occurred during the preparation or the activation of
1786 * this staged session.
1787 */
Dario Frenib6d28962019-01-31 15:52:24 +00001788 public static final int STAGED_SESSION_NO_ERROR = 0;
Dario Freni71eee5e2018-12-06 15:47:16 +00001789
1790 /**
1791 * Constant indicating that an error occurred during the verification phase (pre-reboot) of
1792 * this staged session.
1793 */
Dario Frenib6d28962019-01-31 15:52:24 +00001794 public static final int STAGED_SESSION_VERIFICATION_FAILED = 1;
Dario Freni71eee5e2018-12-06 15:47:16 +00001795
1796 /**
1797 * Constant indicating that an error occurred during the activation phase (post-reboot) of
1798 * this staged session.
1799 */
Dario Frenib6d28962019-01-31 15:52:24 +00001800 public static final int STAGED_SESSION_ACTIVATION_FAILED = 2;
1801
1802 /**
1803 * Constant indicating that an unknown error occurred while processing this staged session.
1804 */
1805 public static final int STAGED_SESSION_UNKNOWN = 3;
Dario Freni71eee5e2018-12-06 15:47:16 +00001806
Jeff Sharkeya0907432014-08-15 10:23:11 -07001807 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001808 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001809 public int sessionId;
1810 /** {@hide} */
Jon Miranda2b340a22019-01-25 14:03:49 -08001811 public int userId;
1812 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001813 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001814 public String installerPackageName;
1815 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001816 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001817 public String resolvedBaseCodePath;
1818 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001819 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001820 public float progress;
1821 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001822 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001823 public boolean sealed;
1824 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001825 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001826 public boolean active;
Jeff Sharkeya0907432014-08-15 10:23:11 -07001827
1828 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001829 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001830 public int mode;
1831 /** {@hide} */
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001832 public @InstallReason int installReason;
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001833 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001834 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001835 public long sizeBytes;
1836 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001837 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001838 public String appPackageName;
1839 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001840 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001841 public Bitmap appIcon;
1842 /** {@hide} */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001843 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkeya0907432014-08-15 10:23:11 -07001844 public CharSequence appLabel;
1845
1846 /** {@hide} */
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001847 public int installLocation;
1848 /** {@hide} */
1849 public Uri originatingUri;
1850 /** {@hide} */
1851 public int originatingUid;
1852 /** {@hide} */
1853 public Uri referrerUri;
1854 /** {@hide} */
1855 public String[] grantedRuntimePermissions;
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001856 /** {@hide}*/
1857 public List<String> whitelistedRestrictedPermissions;
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001858 /** {@hide} */
1859 public int installFlags;
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001860 /** {@hide} */
1861 public boolean isMultiPackage;
1862 /** {@hide} */
Dario Freniaac4ba42018-12-06 15:47:16 +00001863 public boolean isStaged;
1864 /** {@hide} */
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001865 public int parentSessionId = INVALID_ID;
1866 /** {@hide} */
1867 public int[] childSessionIds = NO_SESSIONS;
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001868
1869 /** {@hide} */
Dario Freni60a96c12019-02-24 21:01:29 +00001870 public boolean isStagedSessionApplied;
Dario Freni71eee5e2018-12-06 15:47:16 +00001871 /** {@hide} */
Dario Freni60a96c12019-02-24 21:01:29 +00001872 public boolean isStagedSessionReady;
Dario Freni71eee5e2018-12-06 15:47:16 +00001873 /** {@hide} */
Dario Freni60a96c12019-02-24 21:01:29 +00001874 public boolean isStagedSessionFailed;
Dario Freni71eee5e2018-12-06 15:47:16 +00001875 private int mStagedSessionErrorCode;
Dario Freni275b4ab2019-01-25 09:55:16 +00001876 private String mStagedSessionErrorMessage;
Dario Freni71eee5e2018-12-06 15:47:16 +00001877
1878 /** {@hide} */
Nikita Ioffe00a08f12019-03-07 20:55:08 +00001879 public boolean isCommitted;
1880
1881 /** {@hide} */
Dario Freni56c14dd2019-04-03 16:20:22 +01001882 public long updatedMillis;
1883
1884 /** {@hide} */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001885 @UnsupportedAppUsage
Jeff Sharkeya0907432014-08-15 10:23:11 -07001886 public SessionInfo() {
1887 }
1888
1889 /** {@hide} */
1890 public SessionInfo(Parcel source) {
1891 sessionId = source.readInt();
Jon Miranda2b340a22019-01-25 14:03:49 -08001892 userId = source.readInt();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001893 installerPackageName = source.readString();
1894 resolvedBaseCodePath = source.readString();
1895 progress = source.readFloat();
1896 sealed = source.readInt() != 0;
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001897 active = source.readInt() != 0;
Jeff Sharkeya0907432014-08-15 10:23:11 -07001898
1899 mode = source.readInt();
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001900 installReason = source.readInt();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001901 sizeBytes = source.readLong();
1902 appPackageName = source.readString();
1903 appIcon = source.readParcelable(null);
1904 appLabel = source.readString();
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001905
1906 installLocation = source.readInt();
1907 originatingUri = source.readParcelable(null);
1908 originatingUid = source.readInt();
1909 referrerUri = source.readParcelable(null);
1910 grantedRuntimePermissions = source.readStringArray();
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001911 whitelistedRestrictedPermissions = source.createStringArrayList();
1912
Philip P. Moltmann7460c592017-08-08 20:07:11 +00001913 installFlags = source.readInt();
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001914 isMultiPackage = source.readBoolean();
Dario Freniaac4ba42018-12-06 15:47:16 +00001915 isStaged = source.readBoolean();
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001916 parentSessionId = source.readInt();
1917 childSessionIds = source.createIntArray();
1918 if (childSessionIds == null) {
1919 childSessionIds = NO_SESSIONS;
1920 }
Dario Freni60a96c12019-02-24 21:01:29 +00001921 isStagedSessionApplied = source.readBoolean();
1922 isStagedSessionReady = source.readBoolean();
1923 isStagedSessionFailed = source.readBoolean();
Dario Freni71eee5e2018-12-06 15:47:16 +00001924 mStagedSessionErrorCode = source.readInt();
Dario Freni275b4ab2019-01-25 09:55:16 +00001925 mStagedSessionErrorMessage = source.readString();
Nikita Ioffe00a08f12019-03-07 20:55:08 +00001926 isCommitted = source.readBoolean();
Jeff Sharkeya0907432014-08-15 10:23:11 -07001927 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001928
1929 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001930 * Return the ID for this session.
Jeff Sharkeybb580672014-07-10 12:10:25 -07001931 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001932 public int getSessionId() {
1933 return sessionId;
1934 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001935
1936 /**
Jon Miranda2b340a22019-01-25 14:03:49 -08001937 * Return the user associated with this session.
1938 */
Jon Miranda93505982019-03-08 09:33:42 -08001939 public @NonNull UserHandle getUser() {
Jon Miranda2b340a22019-01-25 14:03:49 -08001940 return new UserHandle(userId);
1941 }
1942
1943 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07001944 * Return the package name of the app that owns this session.
1945 */
1946 public @Nullable String getInstallerPackageName() {
1947 return installerPackageName;
1948 }
1949
1950 /**
1951 * Return current overall progress of this session, between 0 and 1.
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07001952 * <p>
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001953 * Note that this progress may not directly correspond to the value
1954 * reported by
1955 * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
1956 * system may carve out a portion of the overall progress to represent
1957 * its own internal installation work.
Jeff Sharkeybb580672014-07-10 12:10:25 -07001958 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07001959 public float getProgress() {
1960 return progress;
1961 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07001962
1963 /**
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001964 * Return if this session is currently active.
1965 * <p>
1966 * A session is considered active whenever there is ongoing forward
1967 * progress being made, such as the installer holding an open
1968 * {@link Session} instance while streaming data into place, or the
1969 * system optimizing code as the result of
1970 * {@link Session#commit(IntentSender)}.
1971 * <p>
1972 * If the installer closes the {@link Session} without committing, the
1973 * session is considered inactive until the installer opens the session
1974 * again.
Jeff Sharkeybb580672014-07-10 12:10:25 -07001975 */
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001976 public boolean isActive() {
1977 return active;
1978 }
1979
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001980 /**
Todd Kennedy04cc1912017-03-03 13:05:12 -08001981 * Return if this session is sealed.
1982 * <p>
1983 * Once sealed, no further changes may be made to the session. A session
1984 * is sealed the moment {@link Session#commit(IntentSender)} is called.
1985 */
1986 public boolean isSealed() {
1987 return sealed;
1988 }
1989
1990 /**
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001991 * Return the reason for installing this package.
1992 *
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001993 * @return The install reason.
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001994 */
Bartosz Fabianowski40a00622017-04-18 14:39:23 +02001995 public @InstallReason int getInstallReason() {
Sunny Goyal6d7cb232017-01-30 10:43:18 -08001996 return installReason;
1997 }
1998
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07001999 /** {@hide} */
2000 @Deprecated
Jeff Sharkeya0907432014-08-15 10:23:11 -07002001 public boolean isOpen() {
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07002002 return isActive();
Jeff Sharkeya0907432014-08-15 10:23:11 -07002003 }
Jeff Sharkeybb580672014-07-10 12:10:25 -07002004
2005 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07002006 * Return the package name this session is working with. May be {@code null}
2007 * if unknown.
Jeff Sharkeybb580672014-07-10 12:10:25 -07002008 */
Jeff Sharkeya0907432014-08-15 10:23:11 -07002009 public @Nullable String getAppPackageName() {
2010 return appPackageName;
2011 }
Jeff Sharkey16c8e3f2014-07-24 17:08:17 -07002012
Jeff Sharkey7328a1b2014-08-07 14:01:43 -07002013 /**
Jeff Sharkeya0907432014-08-15 10:23:11 -07002014 * Return an icon representing the app being installed. May be {@code null}
2015 * if unavailable.
2016 */
2017 public @Nullable Bitmap getAppIcon() {
Jeff Sharkeyda1247a2017-06-08 14:13:29 -06002018 if (appIcon == null) {
2019 // Icon may have been omitted for calls that return bulk session
2020 // lists, so try fetching the specific icon.
2021 try {
Jeff Sharkeyd1dd2c62017-08-02 09:28:53 -06002022 final SessionInfo info = AppGlobals.getPackageManager().getPackageInstaller()
2023 .getSessionInfo(sessionId);
2024 appIcon = (info != null) ? info.appIcon : null;
Jeff Sharkeyda1247a2017-06-08 14:13:29 -06002025 } catch (RemoteException e) {
2026 throw e.rethrowFromSystemServer();
2027 }
2028 }
Jeff Sharkeya0907432014-08-15 10:23:11 -07002029 return appIcon;
2030 }
2031
2032 /**
2033 * Return a label representing the app being installed. May be {@code null}
2034 * if unavailable.
2035 */
2036 public @Nullable CharSequence getAppLabel() {
2037 return appLabel;
2038 }
2039
2040 /**
2041 * Return an Intent that can be started to view details about this install
2042 * session. This may surface actions such as pause, resume, or cancel.
2043 * <p>
2044 * In some cases, a matching Activity may not exist, so ensure you safeguard
2045 * against this.
Jeff Sharkey7328a1b2014-08-07 14:01:43 -07002046 *
Jeff Sharkeya0907432014-08-15 10:23:11 -07002047 * @see PackageInstaller#ACTION_SESSION_DETAILS
Jeff Sharkey7328a1b2014-08-07 14:01:43 -07002048 */
Jeff Sharkeyde742312014-09-15 14:04:56 -07002049 public @Nullable Intent createDetailsIntent() {
Jeff Sharkeya0907432014-08-15 10:23:11 -07002050 final Intent intent = new Intent(PackageInstaller.ACTION_SESSION_DETAILS);
2051 intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
2052 intent.setPackage(installerPackageName);
2053 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2054 return intent;
Jeff Sharkeybb580672014-07-10 12:10:25 -07002055 }
2056
Philip P. Moltmann7460c592017-08-08 20:07:11 +00002057 /**
2058 * Get the mode of the session as set in the constructor of the {@link SessionParams}.
2059 *
2060 * @return One of {@link SessionParams#MODE_FULL_INSTALL}
2061 * or {@link SessionParams#MODE_INHERIT_EXISTING}
2062 */
2063 public int getMode() {
2064 return mode;
2065 }
2066
2067 /**
2068 * Get the value set in {@link SessionParams#setInstallLocation(int)}.
2069 */
2070 public int getInstallLocation() {
2071 return installLocation;
2072 }
2073
2074 /**
2075 * Get the value as set in {@link SessionParams#setSize(long)}.
2076 *
2077 * <p>The value is a hint and does not have to match the actual size.
2078 */
2079 public long getSize() {
2080 return sizeBytes;
2081 }
2082
2083 /**
2084 * Get the value set in {@link SessionParams#setOriginatingUri(Uri)}.
2085 */
2086 public @Nullable Uri getOriginatingUri() {
2087 return originatingUri;
2088 }
2089
2090 /**
2091 * Get the value set in {@link SessionParams#setOriginatingUid(int)}.
2092 */
2093 public int getOriginatingUid() {
2094 return originatingUid;
2095 }
2096
2097 /**
2098 * Get the value set in {@link SessionParams#setReferrerUri(Uri)}
2099 */
2100 public @Nullable Uri getReferrerUri() {
2101 return referrerUri;
2102 }
2103
2104 /**
2105 * Get the value set in {@link SessionParams#setGrantedRuntimePermissions(String[])}.
2106 *
2107 * @hide
2108 */
2109 @SystemApi
2110 public @Nullable String[] getGrantedRuntimePermissions() {
2111 return grantedRuntimePermissions;
2112 }
2113
2114 /**
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002115 * Get the value set in {@link SessionParams#setWhitelistedRestrictedPermissions(Set)}.
2116 * Note that if all permissions are whitelisted this method returns {@link
2117 * SessionParams#RESTRICTED_PERMISSIONS_ALL}.
2118 *
2119 * @hide
2120 */
2121 @TestApi
2122 @SystemApi
2123 public @NonNull Set<String> getWhitelistedRestrictedPermissions() {
2124 if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0) {
2125 return SessionParams.RESTRICTED_PERMISSIONS_ALL;
2126 }
2127 if (whitelistedRestrictedPermissions != null) {
2128 return new ArraySet<>(whitelistedRestrictedPermissions);
2129 }
2130 return Collections.emptySet();
2131 }
2132
2133 /**
Philip P. Moltmann7460c592017-08-08 20:07:11 +00002134 * Get the value set in {@link SessionParams#setAllowDowngrade(boolean)}.
2135 *
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00002136 * @deprecated use {@link #getRequestDowngrade()}.
Philip P. Moltmann7460c592017-08-08 20:07:11 +00002137 * @hide
2138 */
2139 @SystemApi
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00002140 @Deprecated
Philip P. Moltmann7460c592017-08-08 20:07:11 +00002141 public boolean getAllowDowngrade() {
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00002142 return getRequestDowngrade();
2143 }
2144
2145 /**
2146 * Get the value set in {@link SessionParams#setRequestDowngrade(boolean)}.
2147 *
2148 * @hide
2149 */
2150 @SystemApi
2151 public boolean getRequestDowngrade() {
2152 return (installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0;
Philip P. Moltmann7460c592017-08-08 20:07:11 +00002153 }
2154
2155 /**
2156 * Get the value set in {@link SessionParams#setDontKillApp(boolean)}.
2157 *
2158 * @hide
2159 */
2160 @SystemApi
2161 public boolean getDontKillApp() {
2162 return (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0;
2163 }
2164
2165 /**
2166 * If {@link SessionParams#setInstallAsInstantApp(boolean)} was called with {@code true},
2167 * return true. If it was called with {@code false} or if it was not called return false.
2168 *
2169 * @hide
2170 *
2171 * @see #getInstallAsFullApp
2172 */
2173 @SystemApi
2174 public boolean getInstallAsInstantApp(boolean isInstantApp) {
2175 return (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
2176 }
2177
2178 /**
2179 * If {@link SessionParams#setInstallAsInstantApp(boolean)} was called with {@code false},
2180 * return true. If it was called with {@code true} or if it was not called return false.
2181 *
2182 * @hide
2183 *
2184 * @see #getInstallAsInstantApp
2185 */
2186 @SystemApi
2187 public boolean getInstallAsFullApp(boolean isInstantApp) {
2188 return (installFlags & PackageManager.INSTALL_FULL_APP) != 0;
2189 }
2190
2191 /**
2192 * Get if {@link SessionParams#setInstallAsVirtualPreload()} was called.
2193 *
2194 * @hide
2195 */
2196 @SystemApi
2197 public boolean getInstallAsVirtualPreload() {
2198 return (installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0;
2199 }
2200
2201 /**
shafik92ea53f2019-03-08 18:05:59 +00002202 * Return whether rollback is enabled or disabled for the given upgrade.
2203 *
2204 * @hide
2205 */
2206 @SystemApi
2207 public boolean getEnableRollback() {
2208 return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0;
2209 }
2210
2211 /**
Philip P. Moltmann7460c592017-08-08 20:07:11 +00002212 * Get the value set in {@link SessionParams#setAllocateAggressive(boolean)}.
2213 *
2214 * @hide
2215 */
2216 @SystemApi
2217 public boolean getAllocateAggressive() {
2218 return (installFlags & PackageManager.INSTALL_ALLOCATE_AGGRESSIVE) != 0;
2219 }
2220
2221
Jeff Sharkeyde742312014-09-15 14:04:56 -07002222 /** {@hide} */
2223 @Deprecated
2224 public @Nullable Intent getDetailsIntent() {
2225 return createDetailsIntent();
2226 }
2227
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002228 /**
2229 * Returns true if this session is a multi-package session containing references to other
2230 * sessions.
2231 */
2232 public boolean isMultiPackage() {
2233 return isMultiPackage;
2234 }
2235
2236 /**
Dario Freniaac4ba42018-12-06 15:47:16 +00002237 * Returns true if this session is a staged session which will be applied at next reboot.
2238 */
2239 public boolean isStaged() {
2240 return isStaged;
2241 }
2242
2243 /**
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002244 * Returns the parent multi-package session ID if this session belongs to one,
2245 * {@link #INVALID_ID} otherwise.
2246 */
2247 public int getParentSessionId() {
2248 return parentSessionId;
2249 }
2250
2251 /**
2252 * Returns the set of session IDs that will be committed when this session is commited if
2253 * this session is a multi-package session.
2254 */
Patrick Baumannb00bd622019-04-01 14:10:07 -07002255 @NonNull
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002256 public int[] getChildSessionIds() {
2257 return childSessionIds;
2258 }
2259
Dario Freni60a96c12019-02-24 21:01:29 +00002260 private void checkSessionIsStaged() {
2261 if (!isStaged) {
2262 throw new IllegalStateException("Session is not marked as staged.");
2263 }
2264 }
2265
Dario Freni71eee5e2018-12-06 15:47:16 +00002266 /**
2267 * Whether the staged session has been applied successfully, meaning that all of its
2268 * packages have been activated and no further action is required.
2269 * Only meaningful if {@code isStaged} is true.
2270 */
Dario Freni60a96c12019-02-24 21:01:29 +00002271 public boolean isStagedSessionApplied() {
2272 checkSessionIsStaged();
2273 return isStagedSessionApplied;
Dario Freni71eee5e2018-12-06 15:47:16 +00002274 }
2275
2276 /**
2277 * Whether the staged session is ready to be applied at next reboot. Only meaningful if
2278 * {@code isStaged} is true.
2279 */
Dario Freni60a96c12019-02-24 21:01:29 +00002280 public boolean isStagedSessionReady() {
2281 checkSessionIsStaged();
2282 return isStagedSessionReady;
Dario Freni71eee5e2018-12-06 15:47:16 +00002283 }
2284
2285 /**
2286 * Whether something went wrong and the staged session is declared as failed, meaning that
2287 * it will be ignored at next reboot. Only meaningful if {@code isStaged} is true.
2288 */
Dario Freni60a96c12019-02-24 21:01:29 +00002289 public boolean isStagedSessionFailed() {
2290 checkSessionIsStaged();
2291 return isStagedSessionFailed;
Dario Freni71eee5e2018-12-06 15:47:16 +00002292 }
2293
2294 /**
2295 * If something went wrong with a staged session, clients can check this error code to
2296 * understand which kind of failure happened. Only meaningful if {@code isStaged} is true.
2297 */
Dario Freni60a96c12019-02-24 21:01:29 +00002298 public @StagedSessionErrorCode int getStagedSessionErrorCode() {
2299 checkSessionIsStaged();
Dario Freni71eee5e2018-12-06 15:47:16 +00002300 return mStagedSessionErrorCode;
2301 }
2302
Dario Freni275b4ab2019-01-25 09:55:16 +00002303 /**
2304 * Text description of the error code returned by {@code getStagedSessionErrorCode}, or
2305 * empty string if no error was encountered.
2306 */
Dario Freniaa796c12019-03-06 12:26:16 +00002307 public @NonNull String getStagedSessionErrorMessage() {
Dario Freni60a96c12019-02-24 21:01:29 +00002308 checkSessionIsStaged();
Dario Freni275b4ab2019-01-25 09:55:16 +00002309 return mStagedSessionErrorMessage;
2310 }
2311
Dario Freni71eee5e2018-12-06 15:47:16 +00002312 /** {@hide} */
Dario Freni275b4ab2019-01-25 09:55:16 +00002313 public void setStagedSessionErrorCode(@StagedSessionErrorCode int errorCode,
2314 String errorMessage) {
Dario Freni71eee5e2018-12-06 15:47:16 +00002315 mStagedSessionErrorCode = errorCode;
Dario Freni275b4ab2019-01-25 09:55:16 +00002316 mStagedSessionErrorMessage = errorMessage;
Dario Freni71eee5e2018-12-06 15:47:16 +00002317 }
2318
Nikita Ioffe00a08f12019-03-07 20:55:08 +00002319 /**
Nikita Ioffe05305022019-04-10 17:15:36 +01002320 * Returns {@code true} if {@link Session#commit(IntentSender)}} was called for this
2321 * session.
Nikita Ioffe00a08f12019-03-07 20:55:08 +00002322 */
2323 public boolean isCommitted() {
2324 return isCommitted;
2325 }
2326
Dario Freni56c14dd2019-04-03 16:20:22 +01002327 /**
2328 * The timestamp of the last update that occurred to the session, including changing of
2329 * states in case of staged sessions.
2330 */
2331 @CurrentTimeMillisLong
2332 public long getUpdatedMillis() {
2333 return updatedMillis;
2334 }
2335
Jeff Sharkeybb580672014-07-10 12:10:25 -07002336 @Override
Jeff Sharkeya0907432014-08-15 10:23:11 -07002337 public int describeContents() {
2338 return 0;
Jeff Sharkeyfbd0e9f2014-08-06 16:34:34 -07002339 }
2340
2341 @Override
Jeff Sharkeya0907432014-08-15 10:23:11 -07002342 public void writeToParcel(Parcel dest, int flags) {
2343 dest.writeInt(sessionId);
Jon Miranda2b340a22019-01-25 14:03:49 -08002344 dest.writeInt(userId);
Jeff Sharkeya0907432014-08-15 10:23:11 -07002345 dest.writeString(installerPackageName);
2346 dest.writeString(resolvedBaseCodePath);
2347 dest.writeFloat(progress);
2348 dest.writeInt(sealed ? 1 : 0);
Jeff Sharkeybc7bce32014-09-05 15:53:05 -07002349 dest.writeInt(active ? 1 : 0);
Jeff Sharkeybb580672014-07-10 12:10:25 -07002350
Jeff Sharkeya0907432014-08-15 10:23:11 -07002351 dest.writeInt(mode);
Sunny Goyal6d7cb232017-01-30 10:43:18 -08002352 dest.writeInt(installReason);
Jeff Sharkeya0907432014-08-15 10:23:11 -07002353 dest.writeLong(sizeBytes);
2354 dest.writeString(appPackageName);
2355 dest.writeParcelable(appIcon, flags);
2356 dest.writeString(appLabel != null ? appLabel.toString() : null);
Philip P. Moltmann7460c592017-08-08 20:07:11 +00002357
2358 dest.writeInt(installLocation);
2359 dest.writeParcelable(originatingUri, flags);
2360 dest.writeInt(originatingUid);
2361 dest.writeParcelable(referrerUri, flags);
2362 dest.writeStringArray(grantedRuntimePermissions);
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002363 dest.writeStringList(whitelistedRestrictedPermissions);
Philip P. Moltmann7460c592017-08-08 20:07:11 +00002364 dest.writeInt(installFlags);
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002365 dest.writeBoolean(isMultiPackage);
Dario Freniaac4ba42018-12-06 15:47:16 +00002366 dest.writeBoolean(isStaged);
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002367 dest.writeInt(parentSessionId);
2368 dest.writeIntArray(childSessionIds);
Dario Freni60a96c12019-02-24 21:01:29 +00002369 dest.writeBoolean(isStagedSessionApplied);
2370 dest.writeBoolean(isStagedSessionReady);
2371 dest.writeBoolean(isStagedSessionFailed);
Dario Freni71eee5e2018-12-06 15:47:16 +00002372 dest.writeInt(mStagedSessionErrorCode);
Dario Freni275b4ab2019-01-25 09:55:16 +00002373 dest.writeString(mStagedSessionErrorMessage);
Nikita Ioffe00a08f12019-03-07 20:55:08 +00002374 dest.writeBoolean(isCommitted);
Jeff Sharkeybb580672014-07-10 12:10:25 -07002375 }
Jeff Sharkeya0907432014-08-15 10:23:11 -07002376
2377 public static final Parcelable.Creator<SessionInfo>
2378 CREATOR = new Parcelable.Creator<SessionInfo>() {
2379 @Override
2380 public SessionInfo createFromParcel(Parcel p) {
2381 return new SessionInfo(p);
2382 }
2383
2384 @Override
2385 public SessionInfo[] newArray(int size) {
2386 return new SessionInfo[size];
2387 }
2388 };
Jeff Sharkeybb580672014-07-10 12:10:25 -07002389 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07002390}