PackageInstallerService.java revision 742e790294b3441b79f715fe447069b63c6065db
13a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey/* 23a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey * Copyright (C) 2014 The Android Open Source Project 33a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey * 43a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 53a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey * you may not use this file except in compliance with the License. 63a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey * You may obtain a copy of the License at 73a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey * 83a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 93a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey * 103a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 113a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 123a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey * See the License for the specific language governing permissions and 143a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey * limitations under the License. 153a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey */ 163a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 173a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeypackage com.android.server.pm; 183a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 193a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport static android.content.pm.PackageManager.INSTALL_ALL_USERS; 203a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport static android.content.pm.PackageManager.INSTALL_FROM_ADB; 213a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport static android.content.pm.PackageManager.INSTALL_REPLACE_EXISTING; 22742e790294b3441b79f715fe447069b63c6065dbJeff Sharkeyimport static android.net.TrafficStats.MB_IN_BYTES; 231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readBitmapAttribute; 241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readBooleanAttribute; 251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readIntAttribute; 261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readLongAttribute; 271cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readStringAttribute; 281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readUriAttribute; 291cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeBitmapAttribute; 301cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeBooleanAttribute; 311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeIntAttribute; 321cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeLongAttribute; 331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeStringAttribute; 341cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeUriAttribute; 351cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; 361cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.START_TAG; 371cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 381cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.app.ActivityManager; 393a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.app.AppOpsManager; 40a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.app.PackageDeleteObserver; 41a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.app.PackageInstallObserver; 423a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.Context; 43f06009542390472872da986486d385001e91a2a7Jeff Sharkeyimport android.content.Intent; 44a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.content.IntentSender; 45a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.content.IntentSender.SendIntentException; 46742e790294b3441b79f715fe447069b63c6065dbJeff Sharkeyimport android.content.pm.ApplicationInfo; 473a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.pm.IPackageInstaller; 4816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkeyimport android.content.pm.IPackageInstallerCallback; 493a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.pm.IPackageInstallerSession; 50f06009542390472872da986486d385001e91a2a7Jeff Sharkeyimport android.content.pm.PackageInstaller; 51a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.content.pm.PackageInstaller.SessionInfo; 52a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.content.pm.PackageInstaller.SessionParams; 5316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkeyimport android.content.pm.PackageManager; 541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.graphics.Bitmap; 55f06009542390472872da986486d385001e91a2a7Jeff Sharkeyimport android.net.Uri; 563a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.Binder; 57a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.os.Bundle; 581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Environment; 593a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.FileUtils; 601cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Handler; 613a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.HandlerThread; 621cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Looper; 631cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Message; 643a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.Process; 65a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.os.RemoteCallbackList; 66a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.os.RemoteException; 67ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.os.SELinux; 683a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.UserHandle; 693a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.UserManager; 70742e790294b3441b79f715fe447069b63c6065dbJeff Sharkeyimport android.os.storage.StorageManager; 71ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.system.ErrnoException; 72ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.system.Os; 73a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.text.TextUtils; 741cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.text.format.DateUtils; 753a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.ArraySet; 761cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.util.AtomicFile; 77a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.util.ExceptionUtils; 781cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.util.Log; 793a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.Slog; 803a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.SparseArray; 81742e790294b3441b79f715fe447069b63c6065dbJeff Sharkeyimport android.util.SparseBooleanArray; 821cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.util.Xml; 833a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 843a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.android.internal.annotations.GuardedBy; 85742e790294b3441b79f715fe447069b63c6065dbJeff Sharkeyimport com.android.internal.content.PackageHelper; 861cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport com.android.internal.util.FastXmlSerializer; 87a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter; 883a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.android.server.IoThread; 893a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.google.android.collect.Sets; 903a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 911cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport libcore.io.IoUtils; 921cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 931cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport org.xmlpull.v1.XmlPullParser; 941cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport org.xmlpull.v1.XmlPullParserException; 951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport org.xmlpull.v1.XmlSerializer; 961cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 973a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport java.io.File; 981cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.io.FileInputStream; 991cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.io.FileNotFoundException; 1001cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.io.FileOutputStream; 101ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport java.io.FilenameFilter; 102ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport java.io.IOException; 1031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.security.SecureRandom; 104bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport java.util.ArrayList; 105bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport java.util.List; 10616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkeyimport java.util.Objects; 1071cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.util.Random; 1083a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1093a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeypublic class PackageInstallerService extends IPackageInstaller.Stub { 1103a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private static final String TAG = "PackageInstaller"; 1111cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final boolean LOGD = true; 1123a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1133a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: remove outstanding sessions when installer package goes away 1146c833e07a05c48ca60ee4d72421bf8b1e78dc710Jeff Sharkey // TODO: notify listeners in other users when package has been installed there 115742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // TODO: purge expired sessions periodically in addition to at reboot 1163a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey /** XML constants used in {@link #mSessionsFile} */ 1181cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String TAG_SESSIONS = "sessions"; 1191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String TAG_SESSION = "session"; 1201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SESSION_ID = "sessionId"; 1211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_USER_ID = "userId"; 1221cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_INSTALLER_PACKAGE_NAME = "installerPackageName"; 1231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_CREATED_MILLIS = "createdMillis"; 1241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir"; 125742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid"; 1261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SEALED = "sealed"; 1271cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_MODE = "mode"; 1281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_INSTALL_FLAGS = "installFlags"; 1291cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_INSTALL_LOCATION = "installLocation"; 1301cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SIZE_BYTES = "sizeBytes"; 1311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_APP_PACKAGE_NAME = "appPackageName"; 1321cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_APP_ICON = "appIcon"; 1331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_APP_LABEL = "appLabel"; 1341cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_ORIGINATING_URI = "originatingUri"; 1351cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_REFERRER_URI = "referrerUri"; 1361cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_ABI_OVERRIDE = "abiOverride"; 1371cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 138f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey /** Automatically destroy sessions older than this */ 1391cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final long MAX_AGE_MILLIS = 3 * DateUtils.DAY_IN_MILLIS; 140f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey /** Upper bound on number of active sessions for a UID */ 1411cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final long MAX_ACTIVE_SESSIONS = 1024; 142f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey /** Upper bound on number of historical sessions for a UID */ 143f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey private static final long MAX_HISTORICAL_SESSIONS = 1048576; 1441cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1453a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final Context mContext; 1463a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final PackageManagerService mPm; 1473a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final AppOpsManager mAppOps; 148742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey private final StorageManager mStorage; 1493a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1503a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final File mStagingDir; 151ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey private final HandlerThread mInstallThread; 1523a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1531cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final Callbacks mCallbacks; 1541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1551cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey /** 1561cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey * File storing persisted {@link #mSessions}. 1571cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey */ 1581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final AtomicFile mSessionsFile; 1591cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1601cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final InternalCallback mInternalCallback = new InternalCallback(); 1611cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1621cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey /** 1631cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey * Used for generating session IDs. Since this is created at boot time, 1641cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey * normal random might be predictable. 1651cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey */ 1661cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final Random mRandom = new SecureRandom(); 1673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1683a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @GuardedBy("mSessions") 1693a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>(); 1703a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1719a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey /** Historical sessions kept around for debugging purposes */ 1729a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey @GuardedBy("mSessions") 1739a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey private final SparseArray<PackageInstallerSession> mHistoricalSessions = new SparseArray<>(); 1749a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey 175742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey /** Sessions allocated to legacy users */ 176742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey @GuardedBy("mSessions") 177742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey private final SparseBooleanArray mLegacySessions = new SparseBooleanArray(); 178742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 179ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey private static final FilenameFilter sStageFilter = new FilenameFilter() { 180ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey @Override 181ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey public boolean accept(File dir, String name) { 182742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey return isStageName(name); 183ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 184ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey }; 185ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 1863a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public PackageInstallerService(Context context, PackageManagerService pm, File stagingDir) { 1873a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mContext = context; 1883a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mPm = pm; 1893a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 190742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey mStorage = StorageManager.from(mContext); 1913a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1923a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mStagingDir = stagingDir; 193ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 194ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mInstallThread = new HandlerThread(TAG); 195ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mInstallThread.start(); 1963a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks = new Callbacks(mInstallThread.getLooper()); 1981cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1991cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessionsFile = new AtomicFile( 2001cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey new File(Environment.getSystemSecureDirectory(), "install_sessions.xml")); 2011cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2023a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 2033a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey readSessionsLocked(); 2043a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 205742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final ArraySet<File> unclaimed = Sets.newArraySet(mStagingDir.listFiles(sStageFilter)); 206742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 207742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Ignore stages claimed by active sessions 2083a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 209ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 210742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey unclaimed.remove(session.internalStageDir); 211ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 212742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 213742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Clean up orphaned staging directories 214742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey for (File stage : unclaimed) { 215ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey Slog.w(TAG, "Deleting orphan stage " + stage); 216ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey if (stage.isDirectory()) { 217ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey FileUtils.deleteContents(stage); 218ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 219ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey stage.delete(); 2203a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 221ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 222ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 223ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 224742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey public void onSecureContainersAvailable() { 225742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey synchronized (mSessions) { 226742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final ArraySet<String> unclaimed = new ArraySet<>(); 227742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey for (String cid : PackageHelper.getSecureContainerList()) { 228742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (isStageName(cid)) { 229742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey unclaimed.add(cid); 230742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 231742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 232742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 233742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Ignore stages claimed by active sessions 234742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 235742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 236742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final String cid = session.externalStageCid; 237742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 238742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (unclaimed.remove(cid)) { 239742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Claimed by active session, mount it 240742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey PackageHelper.mountSdDir(cid, PackageManagerService.getEncryptKey(), 241742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey Process.SYSTEM_UID); 242742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 243742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 244742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 245742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Clean up orphaned staging containers 246742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey for (String cid : unclaimed) { 247742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey Slog.w(TAG, "Deleting orphan container " + cid); 248742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey PackageHelper.destroySdDir(cid); 249742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 250742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 251742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 252742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 253742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey public static boolean isStageName(String name) { 254742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final boolean isFile = name.startsWith("vmdl") && name.endsWith(".tmp"); 255742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final boolean isContainer = name.startsWith("smdl") && name.endsWith(".tmp"); 256742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final boolean isLegacyContainer = name.startsWith("smdl2tmp"); 257742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey return isFile || isContainer || isLegacyContainer; 2587328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey } 2597328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey 260ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey @Deprecated 261742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey public File allocateInternalStageDirLegacy() throws IOException { 262ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey synchronized (mSessions) { 263ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey try { 264ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final int sessionId = allocateSessionIdLocked(); 265742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey mLegacySessions.put(sessionId, true); 266742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey return prepareInternalStageDir(sessionId); 267ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } catch (IllegalStateException e) { 268ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey throw new IOException(e); 2693a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2703a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2713a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2723a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 273742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey @Deprecated 274742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey public String allocateExternalStageCidLegacy() { 275742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey synchronized (mSessions) { 276742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final int sessionId = allocateSessionIdLocked(); 277742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey mLegacySessions.put(sessionId, true); 278742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey return "smdl" + sessionId + ".tmp"; 279742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 280742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 281742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 2823a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void readSessionsLocked() { 2831cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (LOGD) Slog.v(TAG, "readSessionsLocked()"); 2841cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2853a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mSessions.clear(); 2861cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2871cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey FileInputStream fis = null; 2881cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey try { 2891cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey fis = mSessionsFile.openRead(); 2901cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final XmlPullParser in = Xml.newPullParser(); 2911cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey in.setInput(fis, null); 2921cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2931cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int type; 2941cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey while ((type = in.next()) != END_DOCUMENT) { 2951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (type == START_TAG) { 2961cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final String tag = in.getName(); 2971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (TAG_SESSION.equals(tag)) { 2981cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final PackageInstallerSession session = readSessionLocked(in); 2991cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final long age = System.currentTimeMillis() - session.createdMillis; 3001cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3011cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final boolean valid; 3021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (age >= MAX_AGE_MILLIS) { 3031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Slog.w(TAG, "Abandoning old session first created at " 3041cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey + session.createdMillis); 3051cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey valid = false; 306742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } else if (session.internalStageDir != null 307742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey && !session.internalStageDir.exists()) { 308742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey Slog.w(TAG, "Abandoning internal session with missing stage " 309742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey + session.internalStageDir); 3101cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey valid = false; 3111cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } else { 3121cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey valid = true; 3131cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3141cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3151cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (valid) { 3161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessions.put(session.sessionId, session); 3171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } else { 3181cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Since this is early during boot we don't send 3191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // any observer events about the session, but we 3201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // keep details around for dumpsys. 3211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mHistoricalSessions.put(session.sessionId, session); 3221cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (FileNotFoundException e) { 3271cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Missing sessions are okay, probably first boot 3281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (IOException e) { 3291cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Log.wtf(TAG, "Failed reading install sessions", e); 3301cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (XmlPullParserException e) { 3311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Log.wtf(TAG, "Failed reading install sessions", e); 3321cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } finally { 3331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey IoUtils.closeQuietly(fis); 3341cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3351cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3361cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3371cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private PackageInstallerSession readSessionLocked(XmlPullParser in) throws IOException { 3381cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int sessionId = readIntAttribute(in, ATTR_SESSION_ID); 3391cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int userId = readIntAttribute(in, ATTR_USER_ID); 3401cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final String installerPackageName = readStringAttribute(in, ATTR_INSTALLER_PACKAGE_NAME); 3411cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS); 342742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR); 343742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null; 344742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID); 3451cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final boolean sealed = readBooleanAttribute(in, ATTR_SEALED); 3461cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 347a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final SessionParams params = new SessionParams( 348a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey SessionParams.MODE_INVALID); 3491cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.mode = readIntAttribute(in, ATTR_MODE); 3501cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.installFlags = readIntAttribute(in, ATTR_INSTALL_FLAGS); 3511cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.installLocation = readIntAttribute(in, ATTR_INSTALL_LOCATION); 3521cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.sizeBytes = readLongAttribute(in, ATTR_SIZE_BYTES); 3531cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appPackageName = readStringAttribute(in, ATTR_APP_PACKAGE_NAME); 3541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appIcon = readBitmapAttribute(in, ATTR_APP_ICON); 3551cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appLabel = readStringAttribute(in, ATTR_APP_LABEL); 3561cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.originatingUri = readUriAttribute(in, ATTR_ORIGINATING_URI); 3571cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.referrerUri = readUriAttribute(in, ATTR_REFERRER_URI); 3581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.abiOverride = readStringAttribute(in, ATTR_ABI_OVERRIDE); 3591cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 360a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey return new PackageInstallerSession(mInternalCallback, mContext, mPm, 361a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mInstallThread.getLooper(), sessionId, userId, installerPackageName, params, 362742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey createdMillis, stageDir, stageCid, sealed); 3633a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 3643a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 3653a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void writeSessionsLocked() { 3661cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (LOGD) Slog.v(TAG, "writeSessionsLocked()"); 3671cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3681cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey FileOutputStream fos = null; 3691cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey try { 3701cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey fos = mSessionsFile.startWrite(); 3711cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3721cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey XmlSerializer out = new FastXmlSerializer(); 3731cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.setOutput(fos, "utf-8"); 3741cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.startDocument(null, true); 3751cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.startTag(null, TAG_SESSIONS); 3761cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int size = mSessions.size(); 3771cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey for (int i = 0; i < size; i++) { 3781cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 3791cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeSessionLocked(out, session); 3801cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3811cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.endTag(null, TAG_SESSIONS); 3821cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.endDocument(); 3831cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3841cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessionsFile.finishWrite(fos); 3851cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (IOException e) { 3861cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (fos != null) { 3871cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessionsFile.failWrite(fos); 3881cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3891cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3901cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3911cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3921cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void writeSessionLocked(XmlSerializer out, PackageInstallerSession session) 3931cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey throws IOException { 394a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final SessionParams params = session.params; 3951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3961cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.startTag(null, TAG_SESSION); 3971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3981cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_SESSION_ID, session.sessionId); 3991cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_USER_ID, session.userId); 4001cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME, 4011cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey session.installerPackageName); 4021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeLongAttribute(out, ATTR_CREATED_MILLIS, session.createdMillis); 403742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (session.internalStageDir != null) { 404742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey writeStringAttribute(out, ATTR_SESSION_STAGE_DIR, 405742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey session.internalStageDir.getAbsolutePath()); 406742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 407742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (session.externalStageCid != null) { 408742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey writeStringAttribute(out, ATTR_SESSION_STAGE_CID, session.externalStageCid); 409742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 410742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey writeBooleanAttribute(out, ATTR_SEALED, session.isSealed()); 4111cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 4121cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_MODE, params.mode); 4131cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_INSTALL_FLAGS, params.installFlags); 4141cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_INSTALL_LOCATION, params.installLocation); 4151cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeLongAttribute(out, ATTR_SIZE_BYTES, params.sizeBytes); 4161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeStringAttribute(out, ATTR_APP_PACKAGE_NAME, params.appPackageName); 4171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeBitmapAttribute(out, ATTR_APP_ICON, params.appIcon); 4181cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeStringAttribute(out, ATTR_APP_LABEL, params.appLabel); 4191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeUriAttribute(out, ATTR_ORIGINATING_URI, params.originatingUri); 4201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeUriAttribute(out, ATTR_REFERRER_URI, params.referrerUri); 4211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeStringAttribute(out, ATTR_ABI_OVERRIDE, params.abiOverride); 4221cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 4231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.endTag(null, TAG_SESSION); 4243a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4253a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 4263a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void writeSessionsAsync() { 4273a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey IoThread.getHandler().post(new Runnable() { 4283a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 4293a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public void run() { 4303a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 4313a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey writeSessionsLocked(); 4323a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4333a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4343a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey }); 4353a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4363a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 4373a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 438a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public int createSession(SessionParams params, String installerPackageName, int userId) { 439742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey try { 440742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey return createSessionInternal(params, installerPackageName, userId); 441742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } catch (IOException e) { 442742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throw ExceptionUtils.wrap(e); 443742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 444742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 445742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 446742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey private int createSessionInternal(SessionParams params, String installerPackageName, int userId) 447742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throws IOException { 4483a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final int callingUid = Binder.getCallingUid(); 449a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mPm.enforceCrossUserPermission(callingUid, userId, true, "createSession"); 4503a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 4513a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if (mPm.isUserRestricted(UserHandle.getUserId(callingUid), 4523a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey UserManager.DISALLOW_INSTALL_APPS)) { 4533a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new SecurityException("User restriction prevents installing"); 4543a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4553a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 4561cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) { 4571cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey installerPackageName = "com.android.shell"; 4581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 4593a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags |= INSTALL_FROM_ADB; 4601cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 4613a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } else { 462ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mAppOps.checkPackage(callingUid, installerPackageName); 463ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 4643a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags &= ~INSTALL_FROM_ADB; 4653a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags &= ~INSTALL_ALL_USERS; 4663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags |= INSTALL_REPLACE_EXISTING; 4673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4683a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 4691cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Defensively resize giant app icons 4701cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (params.appIcon != null) { 4711cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final ActivityManager am = (ActivityManager) mContext.getSystemService( 4721cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Context.ACTIVITY_SERVICE); 4731cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int iconSize = am.getLauncherLargeIconSize(); 4741cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if ((params.appIcon.getWidth() > iconSize * 2) 4751cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey || (params.appIcon.getHeight() > iconSize * 2)) { 4761cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize, 4771cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey true); 4781cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 4791cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 4801cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 481742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Figure out where we're going to be staging session data 482742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final boolean stageInternal; 483742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 484742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (params.mode == SessionParams.MODE_FULL_INSTALL) { 485742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Brand new install, use best resolved location. This also verifies 486742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // that target has enough free space for the install. 487742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final int resolved = PackageHelper.resolveInstallLocation(mContext, 488742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey params.installLocation, params.sizeBytes, params.installFlags); 489742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (resolved == PackageHelper.RECOMMEND_INSTALL_INTERNAL) { 490742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey stageInternal = true; 491742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } else if (resolved == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) { 492742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey stageInternal = false; 493742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } else { 494742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throw new IOException("No storage with enough free space; res=" + resolved); 495a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 496742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 497742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } else if (params.mode == SessionParams.MODE_INHERIT_EXISTING) { 498742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // We always stage inheriting sessions on internal storage first, 499742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // since we don't want to grow containers until we're sure that 500742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // everything looks legit. 501742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey stageInternal = true; 502742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey checkInternalStorage(params.sizeBytes); 503742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 504742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // If we have a good hunch we'll end up on external storage, verify 505742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // free space there too. 506742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final ApplicationInfo info = mPm.getApplicationInfo(params.appPackageName, 0, 507742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey userId); 508742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (info != null && (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) { 509742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey checkExternalStorage(params.sizeBytes); 510742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 511742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throw new UnsupportedOperationException("TODO: finish fleshing out ASEC support"); 512742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 513742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 514742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } else { 515742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throw new IllegalArgumentException("Invalid install mode: " + params.mode); 516a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 517a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 518a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final int sessionId; 519a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final PackageInstallerSession session; 5203a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 5211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Sanity check that installer isn't going crazy 522f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final int activeCount = getSessionCount(mSessions, callingUid); 5231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (activeCount >= MAX_ACTIVE_SESSIONS) { 524f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey throw new IllegalStateException( 525f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey "Too many active sessions for UID " + callingUid); 526f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey } 527f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final int historicalCount = getSessionCount(mHistoricalSessions, callingUid); 528f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey if (historicalCount >= MAX_HISTORICAL_SESSIONS) { 529f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey throw new IllegalStateException( 530f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey "Too many historical sessions for UID " + callingUid); 5311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 5321cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 533742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final long createdMillis = System.currentTimeMillis(); 534a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey sessionId = allocateSessionIdLocked(); 535a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 536742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // We're staging to exactly one location 537742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey File stageDir = null; 538742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey String stageCid = null; 539742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (stageInternal) { 540742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey stageDir = prepareInternalStageDir(sessionId); 541742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } else { 542742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey stageCid = prepareExternalStageCid(sessionId, params.sizeBytes); 543742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 5443a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 545a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey session = new PackageInstallerSession(mInternalCallback, mContext, mPm, 5461cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mInstallThread.getLooper(), sessionId, userId, installerPackageName, params, 547742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey createdMillis, stageDir, stageCid, false); 5483a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mSessions.put(sessionId, session); 5493a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 550a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 5511cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.notifySessionCreated(session.sessionId, session.userId); 552a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey writeSessionsAsync(); 553a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey return sessionId; 5543a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5553a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 556742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey private void checkInternalStorage(long sizeBytes) throws IOException { 557742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (sizeBytes <= 0) return; 558742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 559742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final File target = Environment.getDataDirectory(); 560742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final long targetBytes = sizeBytes + mStorage.getStorageLowBytes(target); 561742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 562742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey mPm.freeStorage(targetBytes); 563742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (target.getUsableSpace() < targetBytes) { 564742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throw new IOException("Not enough internal space to write " + sizeBytes + " bytes"); 565742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 566742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 567742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 568742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey private void checkExternalStorage(long sizeBytes) throws IOException { 569742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (sizeBytes <= 0) return; 570742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 571742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final File target = Environment.getExternalStorageDirectory(); 572742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final long targetBytes = sizeBytes + mStorage.getStorageLowBytes(target); 573742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 574742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (target.getUsableSpace() < targetBytes) { 575742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throw new IOException("Not enough external space to write " + sizeBytes + " bytes"); 576742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 577742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 578742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 5793a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 5803a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public IPackageInstallerSession openSession(int sessionId) { 5813a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 5823a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 5833a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if (session == null) { 5843a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new IllegalStateException("Missing session " + sessionId); 5853a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5861cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (!isCallingUidOwner(session)) { 5873a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new SecurityException("Caller has no access to session " + sessionId); 5883a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 589742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey session.open(); 5903a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey return session; 5913a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5923a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5933a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 5943a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private int allocateSessionIdLocked() { 5951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int n = 0; 5961cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int sessionId; 5971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey do { 598f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey sessionId = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1; 599742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (mSessions.get(sessionId) == null && mHistoricalSessions.get(sessionId) == null 600742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey && !mLegacySessions.get(sessionId, false)) { 6011cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return sessionId; 6021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 6031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } while (n++ < 32); 6041cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 6051cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey throw new IllegalStateException("Failed to allocate session ID"); 6063a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 6073a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 608742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey private File prepareInternalStageDir(int sessionId) throws IOException { 609ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final File file = new File(mStagingDir, "vmdl" + sessionId + ".tmp"); 610ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 611ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey if (file.exists()) { 612742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throw new IOException("Session dir already exists: " + file); 613ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 614ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 615ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey try { 616ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey Os.mkdir(file.getAbsolutePath(), 0755); 617ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey Os.chmod(file.getAbsolutePath(), 0755); 618ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } catch (ErrnoException e) { 619ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey // This purposefully throws if directory already exists 620742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throw new IOException("Failed to prepare session dir", e); 621ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 622ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 623ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey if (!SELinux.restorecon(file)) { 624742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throw new IOException("Failed to restorecon session dir"); 625ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 626ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 627ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey return file; 628ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 629ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 630742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey private String prepareExternalStageCid(int sessionId, long sizeBytes) throws IOException { 631742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (sizeBytes <= 0) { 632742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throw new IOException("Session must provide valid size for ASEC"); 633742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 634742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 635742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final String cid = "smdl" + sessionId + ".tmp"; 636742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 637742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Round up to nearest MB, plus another MB for filesystem overhead 638742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final int sizeMb = (int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES) + 1; 639742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 640742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (PackageHelper.createSdDir(sizeMb, cid, PackageManagerService.getEncryptKey(), 641742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey Process.SYSTEM_UID, true) == null) { 642742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throw new IOException("Failed to create ASEC"); 643742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 644742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 645742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey return cid; 646742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 647742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 6483a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 649a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public SessionInfo getSessionInfo(int sessionId) { 65016c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey synchronized (mSessions) { 65116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 6521cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (!isCallingUidOwner(session)) { 65316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey enforceCallerCanReadSessions(); 65416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 65516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey return session != null ? session.generateInfo() : null; 65616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 65716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 65816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 65916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey @Override 660a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public List<SessionInfo> getAllSessions(int userId) { 66116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getAllSessions"); 66216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey enforceCallerCanReadSessions(); 6633a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 664a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final List<SessionInfo> result = new ArrayList<>(); 6653a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 6663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 6673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 668bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey if (session.userId == userId) { 669bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey result.add(session.generateInfo()); 6703a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 6713a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 6723a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 673bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey return result; 6743a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 6753a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 6763a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 677a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public List<SessionInfo> getMySessions(String installerPackageName, int userId) { 67816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getMySessions"); 67916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mAppOps.checkPackage(Binder.getCallingUid(), installerPackageName); 68016c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 681a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final List<SessionInfo> result = new ArrayList<>(); 68216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey synchronized (mSessions) { 68316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 68416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 68516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey if (Objects.equals(session.installerPackageName, installerPackageName) 68616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey && session.userId == userId) { 68716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey result.add(session.generateInfo()); 68816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 68916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 69016c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 69116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey return result; 69216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 69316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 69416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey @Override 695a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void uninstall(String packageName, int flags, IntentSender statusReceiver, int userId) { 696a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "uninstall"); 69716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 698a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext, 699a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey statusReceiver); 700f06009542390472872da986486d385001e91a2a7Jeff Sharkey if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES) 701f06009542390472872da986486d385001e91a2a7Jeff Sharkey == PackageManager.PERMISSION_GRANTED) { 702f06009542390472872da986486d385001e91a2a7Jeff Sharkey // Sweet, call straight through! 703a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mPm.deletePackage(packageName, adapter.getBinder(), userId, flags); 704f06009542390472872da986486d385001e91a2a7Jeff Sharkey 705f06009542390472872da986486d385001e91a2a7Jeff Sharkey } else { 706f06009542390472872da986486d385001e91a2a7Jeff Sharkey // Take a short detour to confirm with user 707f06009542390472872da986486d385001e91a2a7Jeff Sharkey final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE); 708f06009542390472872da986486d385001e91a2a7Jeff Sharkey intent.setData(Uri.fromParts("package", packageName, null)); 709a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey intent.putExtra(PackageInstaller.EXTRA_CALLBACK, adapter.getBinder().asBinder()); 710a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey adapter.onUserActionRequired(intent); 711f06009542390472872da986486d385001e91a2a7Jeff Sharkey } 7123a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 7133a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 7143a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 7157328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey public void setPermissionsResult(int sessionId, boolean accepted) { 7167328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, TAG); 7177328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey 7187328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey synchronized (mSessions) { 7197328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey mSessions.get(sessionId).setPermissionsResult(accepted); 7207328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey } 7217328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey } 7227328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey 7237328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey @Override 72416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey public void registerCallback(IPackageInstallerCallback callback, int userId) { 72516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "registerCallback"); 72616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey enforceCallerCanReadSessions(); 727a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 7281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.register(callback, userId); 729bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey } 730bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey 731bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey @Override 73216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey public void unregisterCallback(IPackageInstallerCallback callback) { 73316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mCallbacks.unregister(callback); 734a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 735a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 736f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey private static int getSessionCount(SparseArray<PackageInstallerSession> sessions, 737f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey int installerUid) { 7381cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int count = 0; 739f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final int size = sessions.size(); 7401cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey for (int i = 0; i < size; i++) { 741f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final PackageInstallerSession session = sessions.valueAt(i); 7421cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (session.installerUid == installerUid) { 7431cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey count++; 7441cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 7451cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 7461cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return count; 7471cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 7481cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 7491cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private boolean isCallingUidOwner(PackageInstallerSession session) { 7501cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int callingUid = Binder.getCallingUid(); 7511cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (callingUid == Process.ROOT_UID) { 7521cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return true; 7531cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } else { 7541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return (session != null) && (callingUid == session.installerUid); 755a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 756a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 757a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 75816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey /** 75916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey * We allow those with permission, or the current home app. 76016c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey */ 76116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey private void enforceCallerCanReadSessions() { 76216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey final boolean hasPermission = (mContext.checkCallingOrSelfPermission( 76316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey android.Manifest.permission.READ_INSTALL_SESSIONS) 76416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey == PackageManager.PERMISSION_GRANTED); 76516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey final boolean isHomeApp = mPm.checkCallerIsHomeApp(); 76616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey if (hasPermission || isHomeApp) { 76716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey return; 76816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } else { 76916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey throw new SecurityException("Caller must be current home app to read install sessions"); 77016c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 77116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 77216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 773a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey static class PackageDeleteObserverAdapter extends PackageDeleteObserver { 774a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey private final Context mContext; 775a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey private final IntentSender mTarget; 776a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 777a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public PackageDeleteObserverAdapter(Context context, IntentSender target) { 778a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mContext = context; 779a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget = target; 780a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 781a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 782a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey @Override 783a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void onUserActionRequired(Intent intent) { 784a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final Intent fillIn = new Intent(); 785a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS, 786742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey PackageInstaller.STATUS_PENDING_USER_ACTION); 787a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(Intent.EXTRA_INTENT, intent); 788a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey try { 789a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget.sendIntent(mContext, 0, fillIn, null, null); 790a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } catch (SendIntentException ignored) { 791a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 792a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 793a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 794a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey @Override 795a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void onPackageDeleted(String basePackageName, int returnCode, String msg) { 796a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final Intent fillIn = new Intent(); 797a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS, 798a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.deleteStatusToPublicStatus(returnCode)); 799a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, 800a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.deleteStatusToString(returnCode, msg)); 801a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode); 802a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey try { 803a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget.sendIntent(mContext, 0, fillIn, null, null); 804a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } catch (SendIntentException ignored) { 805a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 806a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 807a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 808a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 809a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey static class PackageInstallObserverAdapter extends PackageInstallObserver { 810a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey private final Context mContext; 811a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey private final IntentSender mTarget; 812a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 813a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public PackageInstallObserverAdapter(Context context, IntentSender target) { 814a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mContext = context; 815a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget = target; 816a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 817a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 818a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey @Override 819a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void onUserActionRequired(Intent intent) { 820a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final Intent fillIn = new Intent(); 821a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS, 822742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey PackageInstaller.STATUS_PENDING_USER_ACTION); 823a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(Intent.EXTRA_INTENT, intent); 824a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey try { 825a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget.sendIntent(mContext, 0, fillIn, null, null); 826a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } catch (SendIntentException ignored) { 827a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 828a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 829a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 830a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey @Override 831a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void onPackageInstalled(String basePackageName, int returnCode, String msg, 832a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey Bundle extras) { 833a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final Intent fillIn = new Intent(); 834a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS, 835a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.installStatusToPublicStatus(returnCode)); 836a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, 837a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.installStatusToString(returnCode, msg)); 838a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode); 839a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey if (extras != null) { 840a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final String existing = extras.getString( 841a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE); 842a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey if (!TextUtils.isEmpty(existing)) { 843a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAMES, new String[] { 844a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey existing }); 845a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 846a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 847a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey try { 848a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget.sendIntent(mContext, 0, fillIn, null, null); 849a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } catch (SendIntentException ignored) { 850a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 851a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 852a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 853a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 8541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static class Callbacks extends Handler { 8551cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final int MSG_SESSION_CREATED = 1; 8561cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final int MSG_SESSION_OPENED = 2; 8571cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final int MSG_SESSION_PROGRESS_CHANGED = 3; 8581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final int MSG_SESSION_CLOSED = 4; 8591cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final int MSG_SESSION_FINISHED = 5; 8601cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 8611cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final RemoteCallbackList<IPackageInstallerCallback> 8621cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks = new RemoteCallbackList<>(); 8631cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 8641cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public Callbacks(Looper looper) { 8651cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey super(looper); 866a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 867a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 8681cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void register(IPackageInstallerCallback callback, int userId) { 8691cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.register(callback, new UserHandle(userId)); 8701cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 8711cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 8721cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void unregister(IPackageInstallerCallback callback) { 8731cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.unregister(callback); 8741cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 8751cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 8761cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey @Override 8771cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void handleMessage(Message msg) { 8781cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int userId = msg.arg2; 8791cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int n = mCallbacks.beginBroadcast(); 8801cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey for (int i = 0; i < n; i++) { 8811cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final IPackageInstallerCallback callback = mCallbacks.getBroadcastItem(i); 8821cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final UserHandle user = (UserHandle) mCallbacks.getBroadcastCookie(i); 8831cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // TODO: dispatch notifications for slave profiles 8841cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (userId == user.getIdentifier()) { 8851cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey try { 8861cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey invokeCallback(callback, msg); 8871cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (RemoteException ignored) { 8881cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 889a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 890a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 8911cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.finishBroadcast(); 892a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 893a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 8941cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void invokeCallback(IPackageInstallerCallback callback, Message msg) 8951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey throws RemoteException { 8961cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int sessionId = msg.arg1; 8971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey switch (msg.what) { 8981cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_CREATED: 8991cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionCreated(sessionId); 9001cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 9011cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_OPENED: 9021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionOpened(sessionId); 9031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 9041cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_PROGRESS_CHANGED: 9051cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionProgressChanged(sessionId, (float) msg.obj); 9061cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 9071cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_CLOSED: 9081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionClosed(sessionId); 9091cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 9101cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_FINISHED: 9111cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionFinished(sessionId, (boolean) msg.obj); 9121cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 913a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 914a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 9151cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void notifySessionCreated(int sessionId, int userId) { 9171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_CREATED, sessionId, userId).sendToTarget(); 9181cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 9191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void notifySessionOpened(int sessionId, int userId) { 9211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_OPENED, sessionId, userId).sendToTarget(); 9221cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 9231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void notifySessionProgressChanged(int sessionId, int userId, float progress) { 9251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, userId, progress).sendToTarget(); 9261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 9271cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void notifySessionClosed(int sessionId, int userId) { 9291cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_CLOSED, sessionId, userId).sendToTarget(); 9301cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 9311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9321cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void notifySessionFinished(int sessionId, int userId, boolean success) { 9331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_FINISHED, sessionId, userId, success).sendToTarget(); 9341cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 935a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 936a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 937a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey void dump(IndentingPrintWriter pw) { 938a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey synchronized (mSessions) { 9399a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println("Active install sessions:"); 9409a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.increaseIndent(); 9419a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey int N = mSessions.size(); 942a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey for (int i = 0; i < N; i++) { 943a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 944a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey session.dump(pw); 945a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey pw.println(); 946a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 9479a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println(); 9489a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.decreaseIndent(); 9499a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey 9509a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println("Historical install sessions:"); 9519a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.increaseIndent(); 9529a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey N = mHistoricalSessions.size(); 9539a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey for (int i = 0; i < N; i++) { 9549a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey final PackageInstallerSession session = mHistoricalSessions.valueAt(i); 9559a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey session.dump(pw); 9569a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println(); 9579a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey } 9589a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println(); 9599a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.decreaseIndent(); 960742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 961742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey pw.println("Legacy install sessions:"); 962742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey pw.increaseIndent(); 963742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey pw.println(mLegacySessions.toString()); 964742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey pw.decreaseIndent(); 965a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 966bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey } 967bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey 9681cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey class InternalCallback { 96916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey public void onSessionProgressChanged(PackageInstallerSession session, float progress) { 9701cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress); 9711cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 9721cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 973742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey public void onSessionOpened(PackageInstallerSession session) { 974742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey mCallbacks.notifySessionOpened(session.sessionId, session.userId); 975742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 976742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 9771cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void onSessionClosed(PackageInstallerSession session) { 9781cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.notifySessionClosed(session.sessionId, session.userId); 9793a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 9803a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 981a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey public void onSessionFinished(PackageInstallerSession session, boolean success) { 9821cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.notifySessionFinished(session.sessionId, session.userId, success); 983a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey synchronized (mSessions) { 984a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mSessions.remove(session.sessionId); 9859a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey mHistoricalSessions.put(session.sessionId, session); 986a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 9873a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey writeSessionsAsync(); 9883a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 9893a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 9903a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey} 991