PackageInstallerService.java revision 77d218e1869e69c8d436b09cd11dcfe45e50b2cf
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; 221cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readBitmapAttribute; 231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readBooleanAttribute; 241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readIntAttribute; 251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readLongAttribute; 261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readStringAttribute; 271cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readUriAttribute; 281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeBitmapAttribute; 291cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeBooleanAttribute; 301cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeIntAttribute; 311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeLongAttribute; 321cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeStringAttribute; 331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeUriAttribute; 341cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; 351cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.START_TAG; 361cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 371cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.app.ActivityManager; 383a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.app.AppOpsManager; 39a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.app.PackageDeleteObserver; 40a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.app.PackageInstallObserver; 413a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.Context; 42f06009542390472872da986486d385001e91a2a7Jeff Sharkeyimport android.content.Intent; 43a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.content.IntentSender; 44a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.content.IntentSender.SendIntentException; 453a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.pm.IPackageInstaller; 4616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkeyimport android.content.pm.IPackageInstallerCallback; 473a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.pm.IPackageInstallerSession; 48f06009542390472872da986486d385001e91a2a7Jeff Sharkeyimport android.content.pm.PackageInstaller; 49a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.content.pm.PackageInstaller.SessionInfo; 50a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.content.pm.PackageInstaller.SessionParams; 51ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkeyimport android.content.pm.PackageManager; 521cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.graphics.Bitmap; 53f06009542390472872da986486d385001e91a2a7Jeff Sharkeyimport android.net.Uri; 543a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.Binder; 55a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.os.Bundle; 561cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Environment; 573a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.FileUtils; 581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Handler; 593a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.HandlerThread; 601cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Looper; 611cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Message; 623a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.Process; 63a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.os.RemoteCallbackList; 64a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.os.RemoteException; 65ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.os.SELinux; 663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.UserHandle; 673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.UserManager; 68ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.system.ErrnoException; 69ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.system.Os; 70a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.text.TextUtils; 711cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.text.format.DateUtils; 723a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.ArraySet; 731cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.util.AtomicFile; 74a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.util.ExceptionUtils; 751cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.util.Log; 763a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.Slog; 773a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.SparseArray; 78742e790294b3441b79f715fe447069b63c6065dbJeff Sharkeyimport android.util.SparseBooleanArray; 791cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.util.Xml; 803a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 813a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.android.internal.annotations.GuardedBy; 82742e790294b3441b79f715fe447069b63c6065dbJeff Sharkeyimport com.android.internal.content.PackageHelper; 831cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport com.android.internal.util.FastXmlSerializer; 84a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter; 853a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.android.server.IoThread; 863a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.google.android.collect.Sets; 873a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 881cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport libcore.io.IoUtils; 891cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 901cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport org.xmlpull.v1.XmlPullParser; 911cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport org.xmlpull.v1.XmlPullParserException; 921cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport org.xmlpull.v1.XmlSerializer; 931cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 943a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport java.io.File; 951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.io.FileInputStream; 961cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.io.FileNotFoundException; 971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.io.FileOutputStream; 98ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport java.io.FilenameFilter; 99ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport java.io.IOException; 1001cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.security.SecureRandom; 101bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport java.util.ArrayList; 102bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport java.util.List; 10316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkeyimport java.util.Objects; 1041cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.util.Random; 1053a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1063a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeypublic class PackageInstallerService extends IPackageInstaller.Stub { 1073a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private static final String TAG = "PackageInstaller"; 1081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final boolean LOGD = true; 1093a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1103a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: remove outstanding sessions when installer package goes away 1116c833e07a05c48ca60ee4d72421bf8b1e78dc710Jeff Sharkey // TODO: notify listeners in other users when package has been installed there 112742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // TODO: purge expired sessions periodically in addition to at reboot 1133a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1141cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey /** XML constants used in {@link #mSessionsFile} */ 1151cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String TAG_SESSIONS = "sessions"; 1161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String TAG_SESSION = "session"; 1171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SESSION_ID = "sessionId"; 1181cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_USER_ID = "userId"; 1191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_INSTALLER_PACKAGE_NAME = "installerPackageName"; 1201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_CREATED_MILLIS = "createdMillis"; 1211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir"; 122742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid"; 12377d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey private static final String ATTR_PREPARED = "prepared"; 1241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SEALED = "sealed"; 1251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_MODE = "mode"; 1261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_INSTALL_FLAGS = "installFlags"; 1271cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_INSTALL_LOCATION = "installLocation"; 1281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SIZE_BYTES = "sizeBytes"; 1291cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_APP_PACKAGE_NAME = "appPackageName"; 1301cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_APP_ICON = "appIcon"; 1311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_APP_LABEL = "appLabel"; 1321cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_ORIGINATING_URI = "originatingUri"; 1331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_REFERRER_URI = "referrerUri"; 1341cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_ABI_OVERRIDE = "abiOverride"; 1351cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 136f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey /** Automatically destroy sessions older than this */ 1371cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final long MAX_AGE_MILLIS = 3 * DateUtils.DAY_IN_MILLIS; 138f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey /** Upper bound on number of active sessions for a UID */ 1391cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final long MAX_ACTIVE_SESSIONS = 1024; 140f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey /** Upper bound on number of historical sessions for a UID */ 141f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey private static final long MAX_HISTORICAL_SESSIONS = 1048576; 1421cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1433a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final Context mContext; 1443a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final PackageManagerService mPm; 1453a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final AppOpsManager mAppOps; 1463a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1473a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final File mStagingDir; 148ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey private final HandlerThread mInstallThread; 1493a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1501cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final Callbacks mCallbacks; 1511cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1521cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey /** 1531cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey * File storing persisted {@link #mSessions}. 1541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey */ 1551cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final AtomicFile mSessionsFile; 1561cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1571cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final InternalCallback mInternalCallback = new InternalCallback(); 1581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1591cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey /** 1601cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey * Used for generating session IDs. Since this is created at boot time, 1611cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey * normal random might be predictable. 1621cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey */ 1631cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final Random mRandom = new SecureRandom(); 1643a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1653a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @GuardedBy("mSessions") 1663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>(); 1673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1689a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey /** Historical sessions kept around for debugging purposes */ 1699a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey @GuardedBy("mSessions") 1709a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey private final SparseArray<PackageInstallerSession> mHistoricalSessions = new SparseArray<>(); 1719a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey 172742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey /** Sessions allocated to legacy users */ 173742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey @GuardedBy("mSessions") 174742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey private final SparseBooleanArray mLegacySessions = new SparseBooleanArray(); 175742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 176ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey private static final FilenameFilter sStageFilter = new FilenameFilter() { 177ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey @Override 178ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey public boolean accept(File dir, String name) { 179742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey return isStageName(name); 180ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 181ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey }; 182ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 1833a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public PackageInstallerService(Context context, PackageManagerService pm, File stagingDir) { 1843a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mContext = context; 1853a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mPm = pm; 1863a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 1873a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1883a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mStagingDir = stagingDir; 189ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 190ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mInstallThread = new HandlerThread(TAG); 191ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mInstallThread.start(); 1923a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1931cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks = new Callbacks(mInstallThread.getLooper()); 1941cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessionsFile = new AtomicFile( 1961cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey new File(Environment.getSystemSecureDirectory(), "install_sessions.xml")); 1971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1983a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 1993a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey readSessionsLocked(); 2003a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 201742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final ArraySet<File> unclaimed = Sets.newArraySet(mStagingDir.listFiles(sStageFilter)); 202742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 203742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Ignore stages claimed by active sessions 2043a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 205ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 206941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey unclaimed.remove(session.stageDir); 207ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 208742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 209742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Clean up orphaned staging directories 210742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey for (File stage : unclaimed) { 211ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey Slog.w(TAG, "Deleting orphan stage " + stage); 212ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey if (stage.isDirectory()) { 213ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey FileUtils.deleteContents(stage); 214ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 215ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey stage.delete(); 2163a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 217ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 218ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 219ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 220742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey public void onSecureContainersAvailable() { 221742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey synchronized (mSessions) { 222742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final ArraySet<String> unclaimed = new ArraySet<>(); 223742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey for (String cid : PackageHelper.getSecureContainerList()) { 224742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (isStageName(cid)) { 225742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey unclaimed.add(cid); 226742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 227742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 228742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 229742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Ignore stages claimed by active sessions 230742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 231742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 232941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey final String cid = session.stageCid; 233742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 234742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (unclaimed.remove(cid)) { 235742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Claimed by active session, mount it 236742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey PackageHelper.mountSdDir(cid, PackageManagerService.getEncryptKey(), 237742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey Process.SYSTEM_UID); 238742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 239742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 240742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 241742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Clean up orphaned staging containers 242742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey for (String cid : unclaimed) { 243742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey Slog.w(TAG, "Deleting orphan container " + cid); 244742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey PackageHelper.destroySdDir(cid); 245742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 246742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 247742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 248742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 249742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey public static boolean isStageName(String name) { 250742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final boolean isFile = name.startsWith("vmdl") && name.endsWith(".tmp"); 251742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final boolean isContainer = name.startsWith("smdl") && name.endsWith(".tmp"); 252742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final boolean isLegacyContainer = name.startsWith("smdl2tmp"); 253742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey return isFile || isContainer || isLegacyContainer; 2547328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey } 2557328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey 256ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey @Deprecated 257742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey public File allocateInternalStageDirLegacy() throws IOException { 258ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey synchronized (mSessions) { 259ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey try { 260ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final int sessionId = allocateSessionIdLocked(); 261742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey mLegacySessions.put(sessionId, true); 26277d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey final File stageDir = buildInternalStageDir(sessionId); 26377d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey prepareInternalStageDir(stageDir); 26477d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey return stageDir; 265ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } catch (IllegalStateException e) { 266ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey throw new IOException(e); 2673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2683a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2693a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2703a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 271742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey @Deprecated 272742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey public String allocateExternalStageCidLegacy() { 273742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey synchronized (mSessions) { 274742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final int sessionId = allocateSessionIdLocked(); 275742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey mLegacySessions.put(sessionId, true); 276742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey return "smdl" + sessionId + ".tmp"; 277742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 278742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 279742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 2803a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void readSessionsLocked() { 2811cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (LOGD) Slog.v(TAG, "readSessionsLocked()"); 2821cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2833a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mSessions.clear(); 2841cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2851cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey FileInputStream fis = null; 2861cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey try { 2871cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey fis = mSessionsFile.openRead(); 2881cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final XmlPullParser in = Xml.newPullParser(); 2891cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey in.setInput(fis, null); 2901cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2911cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int type; 2921cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey while ((type = in.next()) != END_DOCUMENT) { 2931cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (type == START_TAG) { 2941cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final String tag = in.getName(); 2951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (TAG_SESSION.equals(tag)) { 2961cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final PackageInstallerSession session = readSessionLocked(in); 2971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final long age = System.currentTimeMillis() - session.createdMillis; 2981cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2991cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final boolean valid; 3001cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (age >= MAX_AGE_MILLIS) { 3011cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Slog.w(TAG, "Abandoning old session first created at " 3021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey + session.createdMillis); 3031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey valid = false; 304941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey } else if (session.stageDir != null 305941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey && !session.stageDir.exists()) { 306742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey Slog.w(TAG, "Abandoning internal session with missing stage " 307941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey + session.stageDir); 3081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey valid = false; 3091cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } else { 3101cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey valid = true; 3111cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3121cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3131cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (valid) { 3141cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessions.put(session.sessionId, session); 3151cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } else { 3161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Since this is early during boot we don't send 3171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // any observer events about the session, but we 3181cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // keep details around for dumpsys. 3191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mHistoricalSessions.put(session.sessionId, session); 3201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3221cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (FileNotFoundException e) { 3251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Missing sessions are okay, probably first boot 3261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (IOException e) { 3271cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Log.wtf(TAG, "Failed reading install sessions", e); 3281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (XmlPullParserException e) { 3291cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Log.wtf(TAG, "Failed reading install sessions", e); 3301cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } finally { 3311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey IoUtils.closeQuietly(fis); 3321cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3341cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3351cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private PackageInstallerSession readSessionLocked(XmlPullParser in) throws IOException { 3361cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int sessionId = readIntAttribute(in, ATTR_SESSION_ID); 3371cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int userId = readIntAttribute(in, ATTR_USER_ID); 3381cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final String installerPackageName = readStringAttribute(in, ATTR_INSTALLER_PACKAGE_NAME); 3391cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS); 340742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR); 341742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null; 342742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID); 34377d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey final boolean prepared = readBooleanAttribute(in, ATTR_PREPARED, true); 3441cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final boolean sealed = readBooleanAttribute(in, ATTR_SEALED); 3451cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 346a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final SessionParams params = new SessionParams( 347a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey SessionParams.MODE_INVALID); 3481cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.mode = readIntAttribute(in, ATTR_MODE); 3491cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.installFlags = readIntAttribute(in, ATTR_INSTALL_FLAGS); 3501cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.installLocation = readIntAttribute(in, ATTR_INSTALL_LOCATION); 3511cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.sizeBytes = readLongAttribute(in, ATTR_SIZE_BYTES); 3521cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appPackageName = readStringAttribute(in, ATTR_APP_PACKAGE_NAME); 3531cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appIcon = readBitmapAttribute(in, ATTR_APP_ICON); 3541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appLabel = readStringAttribute(in, ATTR_APP_LABEL); 3551cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.originatingUri = readUriAttribute(in, ATTR_ORIGINATING_URI); 3561cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.referrerUri = readUriAttribute(in, ATTR_REFERRER_URI); 3571cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.abiOverride = readStringAttribute(in, ATTR_ABI_OVERRIDE); 3581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 359a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey return new PackageInstallerSession(mInternalCallback, mContext, mPm, 360a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mInstallThread.getLooper(), sessionId, userId, installerPackageName, params, 36177d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey createdMillis, stageDir, stageCid, prepared, sealed); 3623a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 3633a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 3643a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void writeSessionsLocked() { 3651cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (LOGD) Slog.v(TAG, "writeSessionsLocked()"); 3661cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3671cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey FileOutputStream fos = null; 3681cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey try { 3691cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey fos = mSessionsFile.startWrite(); 3701cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3711cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey XmlSerializer out = new FastXmlSerializer(); 3721cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.setOutput(fos, "utf-8"); 3731cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.startDocument(null, true); 3741cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.startTag(null, TAG_SESSIONS); 3751cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int size = mSessions.size(); 3761cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey for (int i = 0; i < size; i++) { 3771cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 3781cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeSessionLocked(out, session); 3791cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3801cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.endTag(null, TAG_SESSIONS); 3811cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.endDocument(); 3821cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3831cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessionsFile.finishWrite(fos); 3841cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (IOException e) { 3851cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (fos != null) { 3861cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessionsFile.failWrite(fos); 3871cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3881cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3891cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3901cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3911cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void writeSessionLocked(XmlSerializer out, PackageInstallerSession session) 3921cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey throws IOException { 393a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final SessionParams params = session.params; 3941cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.startTag(null, TAG_SESSION); 3961cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_SESSION_ID, session.sessionId); 3981cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_USER_ID, session.userId); 3991cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME, 4001cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey session.installerPackageName); 4011cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeLongAttribute(out, ATTR_CREATED_MILLIS, session.createdMillis); 402941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey if (session.stageDir != null) { 403742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey writeStringAttribute(out, ATTR_SESSION_STAGE_DIR, 404941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey session.stageDir.getAbsolutePath()); 405742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 406941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey if (session.stageCid != null) { 407941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey writeStringAttribute(out, ATTR_SESSION_STAGE_CID, session.stageCid); 408742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 40977d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey writeBooleanAttribute(out, ATTR_PREPARED, session.isPrepared()); 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 456381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey // TODO: double check all possible install flags 457381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey 4581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) { 4591cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey installerPackageName = "com.android.shell"; 4601cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 4613a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags |= INSTALL_FROM_ADB; 4621cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 4633a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } else { 464ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mAppOps.checkPackage(callingUid, installerPackageName); 465ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 4663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags &= ~INSTALL_FROM_ADB; 4673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags &= ~INSTALL_ALL_USERS; 4683a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags |= INSTALL_REPLACE_EXISTING; 4693a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4703a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 4711cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Defensively resize giant app icons 4721cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (params.appIcon != null) { 4731cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final ActivityManager am = (ActivityManager) mContext.getSystemService( 4741cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Context.ACTIVITY_SERVICE); 4751cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int iconSize = am.getLauncherLargeIconSize(); 4761cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if ((params.appIcon.getWidth() > iconSize * 2) 4771cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey || (params.appIcon.getHeight() > iconSize * 2)) { 4781cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize, 4791cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey true); 4801cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 4811cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 4821cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 48377d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey if (params.mode == SessionParams.MODE_FULL_INSTALL 48477d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey || params.mode == SessionParams.MODE_INHERIT_EXISTING) { 48577d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey // Resolve best location for install, based on combination of 48677d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey // requested install flags, delta size, and manifest settings. 487e812d9096915ad165de125520ed7371009587d1fRobin Lee final long ident = Binder.clearCallingIdentity(); 488e812d9096915ad165de125520ed7371009587d1fRobin Lee try { 489e812d9096915ad165de125520ed7371009587d1fRobin Lee final int resolved = PackageHelper.resolveInstallLocation(mContext, 490e812d9096915ad165de125520ed7371009587d1fRobin Lee params.appPackageName, params.installLocation, params.sizeBytes, 491e812d9096915ad165de125520ed7371009587d1fRobin Lee params.installFlags); 492e812d9096915ad165de125520ed7371009587d1fRobin Lee 493e812d9096915ad165de125520ed7371009587d1fRobin Lee if (resolved == PackageHelper.RECOMMEND_INSTALL_INTERNAL) { 49477d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey params.setInstallFlagsInternal(); 495e812d9096915ad165de125520ed7371009587d1fRobin Lee } else if (resolved == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) { 49677d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey params.setInstallFlagsExternal(); 497e812d9096915ad165de125520ed7371009587d1fRobin Lee } else { 498e812d9096915ad165de125520ed7371009587d1fRobin Lee throw new IOException("No storage with enough free space; res=" + resolved); 499e812d9096915ad165de125520ed7371009587d1fRobin Lee } 500e812d9096915ad165de125520ed7371009587d1fRobin Lee } finally { 501e812d9096915ad165de125520ed7371009587d1fRobin Lee Binder.restoreCallingIdentity(ident); 502a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 503742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } else { 504742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throw new IllegalArgumentException("Invalid install mode: " + params.mode); 505a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 506a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 507a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final int sessionId; 508a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final PackageInstallerSession session; 5093a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 5101cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Sanity check that installer isn't going crazy 511f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final int activeCount = getSessionCount(mSessions, callingUid); 5121cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (activeCount >= MAX_ACTIVE_SESSIONS) { 513f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey throw new IllegalStateException( 514f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey "Too many active sessions for UID " + callingUid); 515f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey } 516f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final int historicalCount = getSessionCount(mHistoricalSessions, callingUid); 517f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey if (historicalCount >= MAX_HISTORICAL_SESSIONS) { 518f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey throw new IllegalStateException( 519f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey "Too many historical sessions for UID " + callingUid); 5201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 5211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 522742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final long createdMillis = System.currentTimeMillis(); 523a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey sessionId = allocateSessionIdLocked(); 524a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 525742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // We're staging to exactly one location 526742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey File stageDir = null; 527742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey String stageCid = null; 52877d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) { 52977d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey stageDir = buildInternalStageDir(sessionId); 530742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } else { 53177d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey stageCid = buildExternalStageCid(sessionId); 532742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 5333a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 534a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey session = new PackageInstallerSession(mInternalCallback, mContext, mPm, 5351cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mInstallThread.getLooper(), sessionId, userId, installerPackageName, params, 53677d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey createdMillis, stageDir, stageCid, false, false); 5373a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mSessions.put(sessionId, session); 5383a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 539a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 5401cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.notifySessionCreated(session.sessionId, session.userId); 541a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey writeSessionsAsync(); 542a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey return sessionId; 5433a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5443a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 545381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey @Override 546ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey public void updateSessionAppIcon(int sessionId, Bitmap appIcon) { 547ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey synchronized (mSessions) { 548ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 549ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey if (session == null || !isCallingUidOwner(session)) { 550ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey throw new SecurityException("Caller has no access to session " + sessionId); 551ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 552ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey session.params.appIcon = appIcon; 553ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey mInternalCallback.onSessionBadgingChanged(session); 554ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 555ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 556ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey 557ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey @Override 558ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey public void updateSessionAppLabel(int sessionId, String appLabel) { 559ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey synchronized (mSessions) { 560ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 561ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey if (session == null || !isCallingUidOwner(session)) { 562ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey throw new SecurityException("Caller has no access to session " + sessionId); 563ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 564ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey session.params.appLabel = appLabel; 565ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey mInternalCallback.onSessionBadgingChanged(session); 566ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 567ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 568ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey 569ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey @Override 570381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey public void abandonSession(int sessionId) { 571381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey synchronized (mSessions) { 572381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 573381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey if (session == null || !isCallingUidOwner(session)) { 574381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey throw new SecurityException("Caller has no access to session " + sessionId); 575381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey } 576381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey session.abandon(); 577381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey } 578381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey } 579381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey 58077d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey @Override 58177d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey public IPackageInstallerSession openSession(int sessionId) { 58277d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey try { 58377d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey return openSessionInternal(sessionId); 58477d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey } catch (IOException e) { 58577d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey throw ExceptionUtils.wrap(e); 586742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 587742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 588742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 58977d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey private IPackageInstallerSession openSessionInternal(int sessionId) throws IOException { 5903a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 5913a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 592381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey if (session == null || !isCallingUidOwner(session)) { 5933a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new SecurityException("Caller has no access to session " + sessionId); 5943a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 595742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey session.open(); 5963a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey return session; 5973a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5983a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5993a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 6003a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private int allocateSessionIdLocked() { 6011cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int n = 0; 6021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int sessionId; 6031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey do { 604f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey sessionId = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1; 605742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (mSessions.get(sessionId) == null && mHistoricalSessions.get(sessionId) == null 606742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey && !mLegacySessions.get(sessionId, false)) { 6071cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return sessionId; 6081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 6091cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } while (n++ < 32); 6101cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 6111cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey throw new IllegalStateException("Failed to allocate session ID"); 6123a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 6133a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 61477d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey private File buildInternalStageDir(int sessionId) { 61577d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey return new File(mStagingDir, "vmdl" + sessionId + ".tmp"); 61677d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey } 617ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 61877d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey static void prepareInternalStageDir(File stageDir) throws IOException { 61977d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey if (stageDir.exists()) { 62077d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey throw new IOException("Session dir already exists: " + stageDir); 621ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 622ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 623ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey try { 62477d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey Os.mkdir(stageDir.getAbsolutePath(), 0755); 62577d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey Os.chmod(stageDir.getAbsolutePath(), 0755); 626ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } catch (ErrnoException e) { 627ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey // This purposefully throws if directory already exists 62877d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey throw new IOException("Failed to prepare session dir: " + stageDir, e); 629ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 630ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 63177d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey if (!SELinux.restorecon(stageDir)) { 63277d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey throw new IOException("Failed to restorecon session dir: " + stageDir); 633ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 634ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 635ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 63677d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey private String buildExternalStageCid(int sessionId) { 63777d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey return "smdl" + sessionId + ".tmp"; 63877d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey } 639742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 64077d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey static void prepareExternalStageCid(String stageCid, long sizeBytes) throws IOException { 64177d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey if (PackageHelper.createSdDir(sizeBytes, stageCid, PackageManagerService.getEncryptKey(), 642742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey Process.SYSTEM_UID, true) == null) { 64377d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey throw new IOException("Failed to create session cid: " + stageCid); 644742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 645742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 646742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 6473a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 648a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public SessionInfo getSessionInfo(int sessionId) { 64916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey synchronized (mSessions) { 65016c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 65116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey return session != null ? session.generateInfo() : null; 65216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 65316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 65416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 65516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey @Override 656a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public List<SessionInfo> getAllSessions(int userId) { 65716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getAllSessions"); 6583a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 659a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final List<SessionInfo> result = new ArrayList<>(); 6603a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 6613a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 6623a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 663bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey if (session.userId == userId) { 664bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey result.add(session.generateInfo()); 6653a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 6663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 6673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 668bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey return result; 6693a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 6703a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 6713a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 672a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public List<SessionInfo> getMySessions(String installerPackageName, int userId) { 67316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getMySessions"); 67416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mAppOps.checkPackage(Binder.getCallingUid(), installerPackageName); 67516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 676a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final List<SessionInfo> result = new ArrayList<>(); 67716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey synchronized (mSessions) { 67816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 67916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 68016c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey if (Objects.equals(session.installerPackageName, installerPackageName) 68116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey && session.userId == userId) { 68216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey result.add(session.generateInfo()); 68316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 68416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 68516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 68616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey return result; 68716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 68816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 68916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey @Override 690a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void uninstall(String packageName, int flags, IntentSender statusReceiver, int userId) { 691a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "uninstall"); 69216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 693a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext, 694bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey statusReceiver, packageName); 695f06009542390472872da986486d385001e91a2a7Jeff Sharkey if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES) 696f06009542390472872da986486d385001e91a2a7Jeff Sharkey == PackageManager.PERMISSION_GRANTED) { 697f06009542390472872da986486d385001e91a2a7Jeff Sharkey // Sweet, call straight through! 698a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mPm.deletePackage(packageName, adapter.getBinder(), userId, flags); 699f06009542390472872da986486d385001e91a2a7Jeff Sharkey 700f06009542390472872da986486d385001e91a2a7Jeff Sharkey } else { 701f06009542390472872da986486d385001e91a2a7Jeff Sharkey // Take a short detour to confirm with user 702f06009542390472872da986486d385001e91a2a7Jeff Sharkey final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE); 703f06009542390472872da986486d385001e91a2a7Jeff Sharkey intent.setData(Uri.fromParts("package", packageName, null)); 704a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey intent.putExtra(PackageInstaller.EXTRA_CALLBACK, adapter.getBinder().asBinder()); 705a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey adapter.onUserActionRequired(intent); 706f06009542390472872da986486d385001e91a2a7Jeff Sharkey } 7073a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 7083a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 7093a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 7107328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey public void setPermissionsResult(int sessionId, boolean accepted) { 7117328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, TAG); 7127328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey 7137328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey synchronized (mSessions) { 7147328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey mSessions.get(sessionId).setPermissionsResult(accepted); 7157328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey } 7167328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey } 7177328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey 7187328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey @Override 71916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey public void registerCallback(IPackageInstallerCallback callback, int userId) { 72016c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "registerCallback"); 7211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.register(callback, userId); 722bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey } 723bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey 724bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey @Override 72516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey public void unregisterCallback(IPackageInstallerCallback callback) { 72616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mCallbacks.unregister(callback); 727a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 728a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 729f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey private static int getSessionCount(SparseArray<PackageInstallerSession> sessions, 730f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey int installerUid) { 7311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int count = 0; 732f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final int size = sessions.size(); 7331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey for (int i = 0; i < size; i++) { 734f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final PackageInstallerSession session = sessions.valueAt(i); 7351cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (session.installerUid == installerUid) { 7361cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey count++; 7371cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 7381cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 7391cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return count; 7401cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 7411cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 7421cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private boolean isCallingUidOwner(PackageInstallerSession session) { 7431cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int callingUid = Binder.getCallingUid(); 7441cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (callingUid == Process.ROOT_UID) { 7451cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return true; 7461cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } else { 7471cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return (session != null) && (callingUid == session.installerUid); 748a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 749a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 750a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 751a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey static class PackageDeleteObserverAdapter extends PackageDeleteObserver { 752a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey private final Context mContext; 753a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey private final IntentSender mTarget; 754bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey private final String mPackageName; 755a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 756bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey public PackageDeleteObserverAdapter(Context context, IntentSender target, 757bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey String packageName) { 758a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mContext = context; 759a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget = target; 760bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey mPackageName = packageName; 761a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 762a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 763a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey @Override 764a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void onUserActionRequired(Intent intent) { 765a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final Intent fillIn = new Intent(); 766bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName); 767a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS, 768742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey PackageInstaller.STATUS_PENDING_USER_ACTION); 769a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(Intent.EXTRA_INTENT, intent); 770a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey try { 771a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget.sendIntent(mContext, 0, fillIn, null, null); 772a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } catch (SendIntentException ignored) { 773a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 774a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 775a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 776a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey @Override 777a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void onPackageDeleted(String basePackageName, int returnCode, String msg) { 778a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final Intent fillIn = new Intent(); 779bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName); 780a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS, 781a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.deleteStatusToPublicStatus(returnCode)); 782a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, 783a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.deleteStatusToString(returnCode, msg)); 784a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode); 785a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey try { 786a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget.sendIntent(mContext, 0, fillIn, null, null); 787a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } catch (SendIntentException ignored) { 788a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 789a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 790a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 791a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 792a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey static class PackageInstallObserverAdapter extends PackageInstallObserver { 793a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey private final Context mContext; 794a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey private final IntentSender mTarget; 795bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey private final int mSessionId; 796a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 797bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey public PackageInstallObserverAdapter(Context context, IntentSender target, int sessionId) { 798a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mContext = context; 799a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget = target; 800bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey mSessionId = sessionId; 801a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 802a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 803a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey @Override 804a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void onUserActionRequired(Intent intent) { 805a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final Intent fillIn = new Intent(); 806bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId); 807a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS, 808742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey PackageInstaller.STATUS_PENDING_USER_ACTION); 809a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(Intent.EXTRA_INTENT, intent); 810a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey try { 811a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget.sendIntent(mContext, 0, fillIn, null, null); 812a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } catch (SendIntentException ignored) { 813a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 814a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 815a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 816a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey @Override 817a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void onPackageInstalled(String basePackageName, int returnCode, String msg, 818a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey Bundle extras) { 819a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final Intent fillIn = new Intent(); 820bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId); 821a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS, 822a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.installStatusToPublicStatus(returnCode)); 823a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, 824a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.installStatusToString(returnCode, msg)); 825a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode); 826a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey if (extras != null) { 827a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final String existing = extras.getString( 828a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE); 829a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey if (!TextUtils.isEmpty(existing)) { 830941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing); 831a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 832a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 833a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey try { 834a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget.sendIntent(mContext, 0, fillIn, null, null); 835a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } catch (SendIntentException ignored) { 836a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 837a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 838a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 839a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 8401cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static class Callbacks extends Handler { 8411cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final int MSG_SESSION_CREATED = 1; 842ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey private static final int MSG_SESSION_BADGING_CHANGED = 2; 843bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey private static final int MSG_SESSION_ACTIVE_CHANGED = 3; 844ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey private static final int MSG_SESSION_PROGRESS_CHANGED = 4; 845bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey private static final int MSG_SESSION_FINISHED = 5; 8461cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 8471cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final RemoteCallbackList<IPackageInstallerCallback> 8481cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks = new RemoteCallbackList<>(); 8491cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 8501cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public Callbacks(Looper looper) { 8511cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey super(looper); 852a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 853a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 8541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void register(IPackageInstallerCallback callback, int userId) { 8551cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.register(callback, new UserHandle(userId)); 8561cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 8571cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 8581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void unregister(IPackageInstallerCallback callback) { 8591cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.unregister(callback); 8601cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 8611cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 8621cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey @Override 8631cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void handleMessage(Message msg) { 8641cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int userId = msg.arg2; 8651cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int n = mCallbacks.beginBroadcast(); 8661cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey for (int i = 0; i < n; i++) { 8671cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final IPackageInstallerCallback callback = mCallbacks.getBroadcastItem(i); 8681cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final UserHandle user = (UserHandle) mCallbacks.getBroadcastCookie(i); 8691cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // TODO: dispatch notifications for slave profiles 8701cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (userId == user.getIdentifier()) { 8711cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey try { 8721cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey invokeCallback(callback, msg); 8731cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (RemoteException ignored) { 8741cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 875a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 876a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 8771cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.finishBroadcast(); 878a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 879a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 8801cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void invokeCallback(IPackageInstallerCallback callback, Message msg) 8811cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey throws RemoteException { 8821cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int sessionId = msg.arg1; 8831cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey switch (msg.what) { 8841cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_CREATED: 8851cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionCreated(sessionId); 8861cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 887ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey case MSG_SESSION_BADGING_CHANGED: 888ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey callback.onSessionBadgingChanged(sessionId); 889ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey break; 890bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey case MSG_SESSION_ACTIVE_CHANGED: 891bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey callback.onSessionActiveChanged(sessionId, (boolean) msg.obj); 8921cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 8931cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_PROGRESS_CHANGED: 8941cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionProgressChanged(sessionId, (float) msg.obj); 8951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 8961cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_FINISHED: 8971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionFinished(sessionId, (boolean) msg.obj); 8981cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 899a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 900a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 9011cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void notifySessionCreated(int sessionId, int userId) { 9031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_CREATED, sessionId, userId).sendToTarget(); 9041cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 9051cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 906ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey private void notifySessionBadgingChanged(int sessionId, int userId) { 907ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, userId).sendToTarget(); 908ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 909ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey 910bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey private void notifySessionActiveChanged(int sessionId, int userId, boolean active) { 911bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey obtainMessage(MSG_SESSION_ACTIVE_CHANGED, sessionId, userId, active).sendToTarget(); 9121cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 9131cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9141cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void notifySessionProgressChanged(int sessionId, int userId, float progress) { 9151cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, userId, progress).sendToTarget(); 9161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 9171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9181cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void notifySessionFinished(int sessionId, int userId, boolean success) { 9191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_FINISHED, sessionId, userId, success).sendToTarget(); 9201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 921a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 922a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 923a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey void dump(IndentingPrintWriter pw) { 924a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey synchronized (mSessions) { 9259a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println("Active install sessions:"); 9269a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.increaseIndent(); 9279a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey int N = mSessions.size(); 928a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey for (int i = 0; i < N; i++) { 929a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 930a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey session.dump(pw); 931a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey pw.println(); 932a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 9339a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println(); 9349a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.decreaseIndent(); 9359a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey 9369a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println("Historical install sessions:"); 9379a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.increaseIndent(); 9389a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey N = mHistoricalSessions.size(); 9399a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey for (int i = 0; i < N; i++) { 9409a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey final PackageInstallerSession session = mHistoricalSessions.valueAt(i); 9419a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey session.dump(pw); 9429a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println(); 9439a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey } 9449a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println(); 9459a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.decreaseIndent(); 946742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 947742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey pw.println("Legacy install sessions:"); 948742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey pw.increaseIndent(); 949742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey pw.println(mLegacySessions.toString()); 950742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey pw.decreaseIndent(); 951a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 952bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey } 953bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey 9541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey class InternalCallback { 955ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey public void onSessionBadgingChanged(PackageInstallerSession session) { 956ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey mCallbacks.notifySessionBadgingChanged(session.sessionId, session.userId); 957ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey writeSessionsAsync(); 9581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 9591cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 960bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey public void onSessionActiveChanged(PackageInstallerSession session, boolean active) { 961bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey mCallbacks.notifySessionActiveChanged(session.sessionId, session.userId, active); 962742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 963742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 964ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey public void onSessionProgressChanged(PackageInstallerSession session, float progress) { 965ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress); 966ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 967ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey 968a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey public void onSessionFinished(PackageInstallerSession session, boolean success) { 9691cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.notifySessionFinished(session.sessionId, session.userId, success); 970a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey synchronized (mSessions) { 971a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mSessions.remove(session.sessionId); 9729a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey mHistoricalSessions.put(session.sessionId, session); 973a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 9743a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey writeSessionsAsync(); 9753a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 976bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 97777d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey public void onSessionPrepared(PackageInstallerSession session) { 97877d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey // We prepared the destination to write into; we want to persist 97977d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey // this, but it's not critical enough to block for. 98077d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey writeSessionsAsync(); 98177d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey } 98277d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey 983bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey public void onSessionSealed(PackageInstallerSession session) { 984bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // It's very important that we block until we've recorded the 985bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // session as being sealed, since we never want to allow mutation 986bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // after sealing. 987bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey writeSessionsLocked(); 988bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 9893a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 9903a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey} 991