PackageInstallerService.java revision f06009542390472872da986486d385001e91a2a7
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; 393a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.Context; 40f06009542390472872da986486d385001e91a2a7Jeff Sharkeyimport android.content.Intent; 41fbd0e9fa37fc17ccd25e4c1f16195bbd27de3c4cJeff Sharkeyimport android.content.pm.IPackageDeleteObserver2; 423a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.pm.IPackageInstaller; 4316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkeyimport android.content.pm.IPackageInstallerCallback; 443a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.pm.IPackageInstallerSession; 45bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport android.content.pm.InstallSessionInfo; 46bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport android.content.pm.InstallSessionParams; 47f06009542390472872da986486d385001e91a2a7Jeff Sharkeyimport android.content.pm.PackageInstaller; 4816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkeyimport android.content.pm.PackageManager; 491cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.graphics.Bitmap; 50f06009542390472872da986486d385001e91a2a7Jeff Sharkeyimport android.net.Uri; 513a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.Binder; 521cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Environment; 533a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.FileUtils; 541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Handler; 553a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.HandlerThread; 561cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Looper; 571cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Message; 583a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.Process; 59a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.os.RemoteCallbackList; 60a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.os.RemoteException; 61ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.os.SELinux; 623a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.UserHandle; 633a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.UserManager; 64ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.system.ErrnoException; 65ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.system.Os; 661cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.text.format.DateUtils; 673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.ArraySet; 681cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.util.AtomicFile; 69a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.util.ExceptionUtils; 701cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.util.Log; 713a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.Slog; 723a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.SparseArray; 731cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.util.Xml; 743a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 753a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.android.internal.annotations.GuardedBy; 761cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport com.android.internal.util.FastXmlSerializer; 77a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter; 783a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.android.server.IoThread; 791cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport com.android.server.pm.PackageInstallerSession.Snapshot; 803a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.google.android.collect.Sets; 813a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 821cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport libcore.io.IoUtils; 831cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 841cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport org.xmlpull.v1.XmlPullParser; 851cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport org.xmlpull.v1.XmlPullParserException; 861cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport org.xmlpull.v1.XmlSerializer; 871cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 883a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport java.io.File; 891cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.io.FileInputStream; 901cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.io.FileNotFoundException; 911cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.io.FileOutputStream; 92ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport java.io.FilenameFilter; 93ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport java.io.IOException; 941cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.security.SecureRandom; 95bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport java.util.ArrayList; 96bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport java.util.List; 9716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkeyimport java.util.Objects; 981cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.util.Random; 993a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1003a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeypublic class PackageInstallerService extends IPackageInstaller.Stub { 1013a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private static final String TAG = "PackageInstaller"; 1021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final boolean LOGD = true; 1033a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1043a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: remove outstanding sessions when installer package goes away 1056c833e07a05c48ca60ee4d72421bf8b1e78dc710Jeff Sharkey // TODO: notify listeners in other users when package has been installed there 1063a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1071cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey /** XML constants used in {@link #mSessionsFile} */ 1081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String TAG_SESSIONS = "sessions"; 1091cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String TAG_SESSION = "session"; 1101cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SESSION_ID = "sessionId"; 1111cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_USER_ID = "userId"; 1121cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_INSTALLER_PACKAGE_NAME = "installerPackageName"; 1131cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_CREATED_MILLIS = "createdMillis"; 1141cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir"; 1151cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SEALED = "sealed"; 1161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_MODE = "mode"; 1171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_INSTALL_FLAGS = "installFlags"; 1181cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_INSTALL_LOCATION = "installLocation"; 1191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SIZE_BYTES = "sizeBytes"; 1201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_APP_PACKAGE_NAME = "appPackageName"; 1211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_APP_ICON = "appIcon"; 1221cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_APP_LABEL = "appLabel"; 1231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_ORIGINATING_URI = "originatingUri"; 1241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_REFERRER_URI = "referrerUri"; 1251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_ABI_OVERRIDE = "abiOverride"; 1261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 127f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey /** Automatically destroy sessions older than this */ 1281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final long MAX_AGE_MILLIS = 3 * DateUtils.DAY_IN_MILLIS; 129f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey /** Upper bound on number of active sessions for a UID */ 1301cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final long MAX_ACTIVE_SESSIONS = 1024; 131f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey /** Upper bound on number of historical sessions for a UID */ 132f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey private static final long MAX_HISTORICAL_SESSIONS = 1048576; 1331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1343a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final Context mContext; 1353a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final PackageManagerService mPm; 1363a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final AppOpsManager mAppOps; 1373a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1383a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final File mStagingDir; 139ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey private final HandlerThread mInstallThread; 1403a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1411cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final Callbacks mCallbacks; 1421cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1431cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey /** 1441cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey * File storing persisted {@link #mSessions}. 1451cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey */ 1461cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final AtomicFile mSessionsFile; 1471cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1481cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final InternalCallback mInternalCallback = new InternalCallback(); 1491cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1501cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey /** 1511cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey * Used for generating session IDs. Since this is created at boot time, 1521cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey * normal random might be predictable. 1531cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey */ 1541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final Random mRandom = new SecureRandom(); 1553a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1563a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @GuardedBy("mSessions") 1573a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>(); 1583a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1599a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey /** Historical sessions kept around for debugging purposes */ 1609a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey @GuardedBy("mSessions") 1619a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey private final SparseArray<PackageInstallerSession> mHistoricalSessions = new SparseArray<>(); 1629a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey 163ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey private static final FilenameFilter sStageFilter = new FilenameFilter() { 164ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey @Override 165ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey public boolean accept(File dir, String name) { 166ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey return name.startsWith("vmdl") && name.endsWith(".tmp"); 167ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 168ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey }; 169ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 1703a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public PackageInstallerService(Context context, PackageManagerService pm, File stagingDir) { 1713a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mContext = context; 1723a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mPm = pm; 1733a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 1743a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1753a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mStagingDir = stagingDir; 176ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 177ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mInstallThread = new HandlerThread(TAG); 178ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mInstallThread.start(); 1793a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1801cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks = new Callbacks(mInstallThread.getLooper()); 1811cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1821cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessionsFile = new AtomicFile( 1831cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey new File(Environment.getSystemSecureDirectory(), "install_sessions.xml")); 1841cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1853a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 1863a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey readSessionsLocked(); 1873a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1883a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // Clean up orphaned staging directories 189ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final ArraySet<File> stages = Sets.newArraySet(mStagingDir.listFiles(sStageFilter)); 1903a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 191ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 192ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey stages.remove(session.sessionStageDir); 193ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 194ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey for (File stage : stages) { 195ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey Slog.w(TAG, "Deleting orphan stage " + stage); 196ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey if (stage.isDirectory()) { 197ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey FileUtils.deleteContents(stage); 198ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 199ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey stage.delete(); 2003a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 201ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 202ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 203ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 2047328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey public static boolean isStageFile(File file) { 2057328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey return sStageFilter.accept(null, file.getName()); 2067328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey } 2077328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey 208ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey @Deprecated 209ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey public File allocateSessionDir() throws IOException { 210ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey synchronized (mSessions) { 211ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey try { 212ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final int sessionId = allocateSessionIdLocked(); 213ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey return prepareSessionStageDir(sessionId); 214ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } catch (IllegalStateException e) { 215ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey throw new IOException(e); 2163a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2173a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2183a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2193a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 2203a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void readSessionsLocked() { 2211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (LOGD) Slog.v(TAG, "readSessionsLocked()"); 2221cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2233a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mSessions.clear(); 2241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey FileInputStream fis = null; 2261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey try { 2271cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey fis = mSessionsFile.openRead(); 2281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final XmlPullParser in = Xml.newPullParser(); 2291cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey in.setInput(fis, null); 2301cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int type; 2321cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey while ((type = in.next()) != END_DOCUMENT) { 2331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (type == START_TAG) { 2341cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final String tag = in.getName(); 2351cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (TAG_SESSION.equals(tag)) { 2361cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final PackageInstallerSession session = readSessionLocked(in); 2371cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final long age = System.currentTimeMillis() - session.createdMillis; 2381cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2391cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final boolean valid; 2401cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (age >= MAX_AGE_MILLIS) { 2411cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Slog.w(TAG, "Abandoning old session first created at " 2421cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey + session.createdMillis); 2431cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey valid = false; 2441cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } else if (!session.sessionStageDir.exists()) { 2451cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Slog.w(TAG, "Abandoning session with missing stage " 2461cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey + session.sessionStageDir); 2471cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey valid = false; 2481cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } else { 2491cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey valid = true; 2501cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 2511cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2521cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (valid) { 2531cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessions.put(session.sessionId, session); 2541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } else { 2551cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Since this is early during boot we don't send 2561cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // any observer events about the session, but we 2571cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // keep details around for dumpsys. 2581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mHistoricalSessions.put(session.sessionId, session); 2591cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 2601cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 2611cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 2621cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 2631cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (FileNotFoundException e) { 2641cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Missing sessions are okay, probably first boot 2651cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (IOException e) { 2661cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Log.wtf(TAG, "Failed reading install sessions", e); 2671cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (XmlPullParserException e) { 2681cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Log.wtf(TAG, "Failed reading install sessions", e); 2691cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } finally { 2701cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey IoUtils.closeQuietly(fis); 2711cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 2721cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 2731cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2741cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private PackageInstallerSession readSessionLocked(XmlPullParser in) throws IOException { 2751cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int sessionId = readIntAttribute(in, ATTR_SESSION_ID); 2761cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int userId = readIntAttribute(in, ATTR_USER_ID); 2771cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final String installerPackageName = readStringAttribute(in, ATTR_INSTALLER_PACKAGE_NAME); 2781cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS); 2791cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final File sessionStageDir = new File(readStringAttribute(in, ATTR_SESSION_STAGE_DIR)); 2801cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final boolean sealed = readBooleanAttribute(in, ATTR_SEALED); 2811cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2821cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final InstallSessionParams params = new InstallSessionParams( 2831cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey InstallSessionParams.MODE_INVALID); 2841cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.mode = readIntAttribute(in, ATTR_MODE); 2851cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.installFlags = readIntAttribute(in, ATTR_INSTALL_FLAGS); 2861cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.installLocation = readIntAttribute(in, ATTR_INSTALL_LOCATION); 2871cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.sizeBytes = readLongAttribute(in, ATTR_SIZE_BYTES); 2881cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appPackageName = readStringAttribute(in, ATTR_APP_PACKAGE_NAME); 2891cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appIcon = readBitmapAttribute(in, ATTR_APP_ICON); 2901cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appLabel = readStringAttribute(in, ATTR_APP_LABEL); 2911cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.originatingUri = readUriAttribute(in, ATTR_ORIGINATING_URI); 2921cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.referrerUri = readUriAttribute(in, ATTR_REFERRER_URI); 2931cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.abiOverride = readStringAttribute(in, ATTR_ABI_OVERRIDE); 2941cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return new PackageInstallerSession(mInternalCallback, mPm, mInstallThread.getLooper(), 2961cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey sessionId, userId, installerPackageName, params, createdMillis, sessionStageDir, 2971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey sealed); 2983a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2993a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 3003a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void writeSessionsLocked() { 3011cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (LOGD) Slog.v(TAG, "writeSessionsLocked()"); 3021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey FileOutputStream fos = null; 3041cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey try { 3051cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey fos = mSessionsFile.startWrite(); 3061cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3071cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey XmlSerializer out = new FastXmlSerializer(); 3081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.setOutput(fos, "utf-8"); 3091cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.startDocument(null, true); 3101cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.startTag(null, TAG_SESSIONS); 3111cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int size = mSessions.size(); 3121cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey for (int i = 0; i < size; i++) { 3131cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 3141cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeSessionLocked(out, session); 3151cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.endTag(null, TAG_SESSIONS); 3171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.endDocument(); 3181cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessionsFile.finishWrite(fos); 3201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (IOException e) { 3211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (fos != null) { 3221cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessionsFile.failWrite(fos); 3231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3271cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void writeSessionLocked(XmlSerializer out, PackageInstallerSession session) 3281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey throws IOException { 3291cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final InstallSessionParams params = session.params; 3301cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final Snapshot snapshot = session.snapshot(); 3311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3321cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.startTag(null, TAG_SESSION); 3331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3341cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_SESSION_ID, session.sessionId); 3351cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_USER_ID, session.userId); 3361cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME, 3371cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey session.installerPackageName); 3381cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeLongAttribute(out, ATTR_CREATED_MILLIS, session.createdMillis); 3391cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeStringAttribute(out, ATTR_SESSION_STAGE_DIR, 3401cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey session.sessionStageDir.getAbsolutePath()); 3411cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeBooleanAttribute(out, ATTR_SEALED, snapshot.sealed); 3421cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3431cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_MODE, params.mode); 3441cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_INSTALL_FLAGS, params.installFlags); 3451cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_INSTALL_LOCATION, params.installLocation); 3461cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeLongAttribute(out, ATTR_SIZE_BYTES, params.sizeBytes); 3471cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeStringAttribute(out, ATTR_APP_PACKAGE_NAME, params.appPackageName); 3481cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeBitmapAttribute(out, ATTR_APP_ICON, params.appIcon); 3491cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeStringAttribute(out, ATTR_APP_LABEL, params.appLabel); 3501cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeUriAttribute(out, ATTR_ORIGINATING_URI, params.originatingUri); 3511cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeUriAttribute(out, ATTR_REFERRER_URI, params.referrerUri); 3521cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeStringAttribute(out, ATTR_ABI_OVERRIDE, params.abiOverride); 3531cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.endTag(null, TAG_SESSION); 3553a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 3563a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 3573a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void writeSessionsAsync() { 3583a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey IoThread.getHandler().post(new Runnable() { 3593a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 3603a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public void run() { 3613a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 3623a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey writeSessionsLocked(); 3633a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 3643a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 3653a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey }); 3663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 3673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 3683a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 36916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey public int createSession(InstallSessionParams params, String installerPackageName, int userId) { 3703a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final int callingUid = Binder.getCallingUid(); 371a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mPm.enforceCrossUserPermission(callingUid, userId, true, "createSession"); 3723a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 3733a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if (mPm.isUserRestricted(UserHandle.getUserId(callingUid), 3743a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey UserManager.DISALLOW_INSTALL_APPS)) { 3753a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new SecurityException("User restriction prevents installing"); 3763a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 3773a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 3781cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) { 3791cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey installerPackageName = "com.android.shell"; 3801cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3813a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags |= INSTALL_FROM_ADB; 3821cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3833a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } else { 384ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mAppOps.checkPackage(callingUid, installerPackageName); 385ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 3863a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags &= ~INSTALL_FROM_ADB; 3873a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags &= ~INSTALL_ALL_USERS; 3883a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags |= INSTALL_REPLACE_EXISTING; 3893a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 3903a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 39116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey switch (params.mode) { 39216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey case InstallSessionParams.MODE_FULL_INSTALL: 39316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey case InstallSessionParams.MODE_INHERIT_EXISTING: 39416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey break; 39516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey default: 39616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey throw new IllegalArgumentException("Params must have valid mode set"); 3976c833e07a05c48ca60ee4d72421bf8b1e78dc710Jeff Sharkey } 3986c833e07a05c48ca60ee4d72421bf8b1e78dc710Jeff Sharkey 3991cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Defensively resize giant app icons 4001cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (params.appIcon != null) { 4011cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final ActivityManager am = (ActivityManager) mContext.getSystemService( 4021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Context.ACTIVITY_SERVICE); 4031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int iconSize = am.getLauncherLargeIconSize(); 4041cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if ((params.appIcon.getWidth() > iconSize * 2) 4051cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey || (params.appIcon.getHeight() > iconSize * 2)) { 4061cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize, 4071cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey true); 4081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 4091cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 4101cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 411a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey // Sanity check that install could fit 41216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey if (params.sizeBytes > 0) { 413a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey try { 41416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mPm.freeStorage(params.sizeBytes); 415a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } catch (IOException e) { 416a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey throw ExceptionUtils.wrap(e); 417a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 418a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 419a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 420a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final int sessionId; 421a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final PackageInstallerSession session; 4223a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 4231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Sanity check that installer isn't going crazy 424f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final int activeCount = getSessionCount(mSessions, callingUid); 4251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (activeCount >= MAX_ACTIVE_SESSIONS) { 426f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey throw new IllegalStateException( 427f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey "Too many active sessions for UID " + callingUid); 428f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey } 429f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final int historicalCount = getSessionCount(mHistoricalSessions, callingUid); 430f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey if (historicalCount >= MAX_HISTORICAL_SESSIONS) { 431f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey throw new IllegalStateException( 432f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey "Too many historical sessions for UID " + callingUid); 4331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 4341cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 435a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey sessionId = allocateSessionIdLocked(); 436a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 4373a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final long createdMillis = System.currentTimeMillis(); 438ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final File sessionStageDir = prepareSessionStageDir(sessionId); 4393a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 4401cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey session = new PackageInstallerSession(mInternalCallback, mPm, 4411cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mInstallThread.getLooper(), sessionId, userId, installerPackageName, params, 4421cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey createdMillis, sessionStageDir, false); 4433a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mSessions.put(sessionId, session); 4443a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 445a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 4461cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.notifySessionCreated(session.sessionId, session.userId); 447a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey writeSessionsAsync(); 448a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey return sessionId; 4493a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4503a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 4513a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 4523a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public IPackageInstallerSession openSession(int sessionId) { 4533a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 4543a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 4553a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if (session == null) { 4563a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new IllegalStateException("Missing session " + sessionId); 4573a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (!isCallingUidOwner(session)) { 4593a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new SecurityException("Caller has no access to session " + sessionId); 4603a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4611cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (session.openCount.getAndIncrement() == 0) { 4621cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.notifySessionOpened(sessionId, session.userId); 4631cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 4643a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey return session; 4653a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 4683a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private int allocateSessionIdLocked() { 4691cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int n = 0; 4701cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int sessionId; 4711cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey do { 472f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey sessionId = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1; 473f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey if (mSessions.get(sessionId) == null && mHistoricalSessions.get(sessionId) == null) { 4741cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return sessionId; 4751cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 4761cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } while (n++ < 32); 4771cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 4781cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey throw new IllegalStateException("Failed to allocate session ID"); 4793a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4803a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 481ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey private File prepareSessionStageDir(int sessionId) { 482ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final File file = new File(mStagingDir, "vmdl" + sessionId + ".tmp"); 483ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 484ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey if (file.exists()) { 4851cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey throw new IllegalStateException("Session dir already exists: " + file); 486ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 487ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 488ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey try { 489ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey Os.mkdir(file.getAbsolutePath(), 0755); 490ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey Os.chmod(file.getAbsolutePath(), 0755); 491ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } catch (ErrnoException e) { 492ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey // This purposefully throws if directory already exists 493ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey throw new IllegalStateException("Failed to prepare session dir", e); 494ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 495ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 496ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey if (!SELinux.restorecon(file)) { 4971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey throw new IllegalStateException("Failed to restorecon session dir"); 498ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 499ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 500ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey return file; 501ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 502ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 5033a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 50416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey public InstallSessionInfo getSessionInfo(int sessionId) { 50516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey synchronized (mSessions) { 50616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 5071cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (!isCallingUidOwner(session)) { 50816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey enforceCallerCanReadSessions(); 50916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 51016c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey return session != null ? session.generateInfo() : null; 51116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 51216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 51316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 51416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey @Override 51516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey public List<InstallSessionInfo> getAllSessions(int userId) { 51616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getAllSessions"); 51716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey enforceCallerCanReadSessions(); 5183a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 519bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey final List<InstallSessionInfo> result = new ArrayList<>(); 5203a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 5213a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 5223a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 523bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey if (session.userId == userId) { 524bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey result.add(session.generateInfo()); 5253a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5263a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5273a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 528bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey return result; 5293a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5303a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 5313a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 53216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey public List<InstallSessionInfo> getMySessions(String installerPackageName, int userId) { 53316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getMySessions"); 53416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mAppOps.checkPackage(Binder.getCallingUid(), installerPackageName); 53516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 53616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey final List<InstallSessionInfo> result = new ArrayList<>(); 53716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey synchronized (mSessions) { 53816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 53916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 54016c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey if (Objects.equals(session.installerPackageName, installerPackageName) 54116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey && session.userId == userId) { 54216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey result.add(session.generateInfo()); 54316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 54416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 54516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 54616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey return result; 54716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 54816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 54916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey @Override 550fbd0e9fa37fc17ccd25e4c1f16195bbd27de3c4cJeff Sharkey public void uninstall(String packageName, int flags, IPackageDeleteObserver2 observer, 551ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey int userId) { 552a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "uninstall"); 55316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 554f06009542390472872da986486d385001e91a2a7Jeff Sharkey if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES) 555f06009542390472872da986486d385001e91a2a7Jeff Sharkey == PackageManager.PERMISSION_GRANTED) { 556f06009542390472872da986486d385001e91a2a7Jeff Sharkey // Sweet, call straight through! 557f06009542390472872da986486d385001e91a2a7Jeff Sharkey mPm.deletePackage(packageName, observer, userId, flags); 558f06009542390472872da986486d385001e91a2a7Jeff Sharkey 559f06009542390472872da986486d385001e91a2a7Jeff Sharkey } else { 560f06009542390472872da986486d385001e91a2a7Jeff Sharkey // Take a short detour to confirm with user 561f06009542390472872da986486d385001e91a2a7Jeff Sharkey final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE); 562f06009542390472872da986486d385001e91a2a7Jeff Sharkey intent.setData(Uri.fromParts("package", packageName, null)); 563f06009542390472872da986486d385001e91a2a7Jeff Sharkey intent.putExtra(PackageInstaller.EXTRA_CALLBACK, observer.asBinder()); 564f06009542390472872da986486d385001e91a2a7Jeff Sharkey try { 565f06009542390472872da986486d385001e91a2a7Jeff Sharkey observer.onUserActionRequired(intent); 566f06009542390472872da986486d385001e91a2a7Jeff Sharkey } catch (RemoteException ignored) { 567f06009542390472872da986486d385001e91a2a7Jeff Sharkey } 568f06009542390472872da986486d385001e91a2a7Jeff Sharkey } 5693a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5703a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 5713a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 572ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey public void uninstallSplit(String basePackageName, String overlayName, int flags, 573fbd0e9fa37fc17ccd25e4c1f16195bbd27de3c4cJeff Sharkey IPackageDeleteObserver2 observer, int userId) { 574a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "uninstallSplit"); 575a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 5763a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: flesh out once PM has split support 5773a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new UnsupportedOperationException(); 5783a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5793a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 580bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey @Override 5817328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey public void setPermissionsResult(int sessionId, boolean accepted) { 5827328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, TAG); 5837328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey 5847328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey synchronized (mSessions) { 5857328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey mSessions.get(sessionId).setPermissionsResult(accepted); 5867328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey } 5877328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey } 5887328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey 5897328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey @Override 59016c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey public void registerCallback(IPackageInstallerCallback callback, int userId) { 59116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "registerCallback"); 59216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey enforceCallerCanReadSessions(); 593a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 5941cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.register(callback, userId); 595bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey } 596bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey 597bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey @Override 59816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey public void unregisterCallback(IPackageInstallerCallback callback) { 59916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mCallbacks.unregister(callback); 600a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 601a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 602f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey private static int getSessionCount(SparseArray<PackageInstallerSession> sessions, 603f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey int installerUid) { 6041cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int count = 0; 605f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final int size = sessions.size(); 6061cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey for (int i = 0; i < size; i++) { 607f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final PackageInstallerSession session = sessions.valueAt(i); 6081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (session.installerUid == installerUid) { 6091cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey count++; 6101cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 6111cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 6121cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return count; 6131cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 6141cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 6151cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private boolean isCallingUidOwner(PackageInstallerSession session) { 6161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int callingUid = Binder.getCallingUid(); 6171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (callingUid == Process.ROOT_UID) { 6181cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return true; 6191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } else { 6201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return (session != null) && (callingUid == session.installerUid); 621a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 622a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 623a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 62416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey /** 62516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey * We allow those with permission, or the current home app. 62616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey */ 62716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey private void enforceCallerCanReadSessions() { 62816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey final boolean hasPermission = (mContext.checkCallingOrSelfPermission( 62916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey android.Manifest.permission.READ_INSTALL_SESSIONS) 63016c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey == PackageManager.PERMISSION_GRANTED); 63116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey final boolean isHomeApp = mPm.checkCallerIsHomeApp(); 63216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey if (hasPermission || isHomeApp) { 63316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey return; 63416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } else { 63516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey throw new SecurityException("Caller must be current home app to read install sessions"); 63616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 63716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 63816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 6391cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static class Callbacks extends Handler { 6401cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final int MSG_SESSION_CREATED = 1; 6411cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final int MSG_SESSION_OPENED = 2; 6421cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final int MSG_SESSION_PROGRESS_CHANGED = 3; 6431cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final int MSG_SESSION_CLOSED = 4; 6441cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final int MSG_SESSION_FINISHED = 5; 6451cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 6461cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final RemoteCallbackList<IPackageInstallerCallback> 6471cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks = new RemoteCallbackList<>(); 6481cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 6491cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public Callbacks(Looper looper) { 6501cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey super(looper); 651a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 652a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 6531cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void register(IPackageInstallerCallback callback, int userId) { 6541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.register(callback, new UserHandle(userId)); 6551cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 6561cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 6571cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void unregister(IPackageInstallerCallback callback) { 6581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.unregister(callback); 6591cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 6601cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 6611cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey @Override 6621cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void handleMessage(Message msg) { 6631cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int userId = msg.arg2; 6641cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int n = mCallbacks.beginBroadcast(); 6651cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey for (int i = 0; i < n; i++) { 6661cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final IPackageInstallerCallback callback = mCallbacks.getBroadcastItem(i); 6671cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final UserHandle user = (UserHandle) mCallbacks.getBroadcastCookie(i); 6681cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // TODO: dispatch notifications for slave profiles 6691cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (userId == user.getIdentifier()) { 6701cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey try { 6711cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey invokeCallback(callback, msg); 6721cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (RemoteException ignored) { 6731cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 674a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 675a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 6761cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.finishBroadcast(); 677a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 678a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 6791cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void invokeCallback(IPackageInstallerCallback callback, Message msg) 6801cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey throws RemoteException { 6811cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int sessionId = msg.arg1; 6821cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey switch (msg.what) { 6831cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_CREATED: 6841cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionCreated(sessionId); 6851cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 6861cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_OPENED: 6871cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionOpened(sessionId); 6881cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 6891cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_PROGRESS_CHANGED: 6901cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionProgressChanged(sessionId, (float) msg.obj); 6911cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 6921cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_CLOSED: 6931cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionClosed(sessionId); 6941cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 6951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_FINISHED: 6961cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionFinished(sessionId, (boolean) msg.obj); 6971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 698a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 699a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 7001cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 7011cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void notifySessionCreated(int sessionId, int userId) { 7021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_CREATED, sessionId, userId).sendToTarget(); 7031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 7041cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 7051cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void notifySessionOpened(int sessionId, int userId) { 7061cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_OPENED, sessionId, userId).sendToTarget(); 7071cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 7081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 7091cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void notifySessionProgressChanged(int sessionId, int userId, float progress) { 7101cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, userId, progress).sendToTarget(); 7111cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 7121cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 7131cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void notifySessionClosed(int sessionId, int userId) { 7141cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_CLOSED, sessionId, userId).sendToTarget(); 7151cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 7161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 7171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void notifySessionFinished(int sessionId, int userId, boolean success) { 7181cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_FINISHED, sessionId, userId, success).sendToTarget(); 7191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 720a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 721a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 722a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey void dump(IndentingPrintWriter pw) { 723a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey synchronized (mSessions) { 7249a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println("Active install sessions:"); 7259a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.increaseIndent(); 7269a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey int N = mSessions.size(); 727a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey for (int i = 0; i < N; i++) { 728a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 729a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey session.dump(pw); 730a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey pw.println(); 731a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 7329a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println(); 7339a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.decreaseIndent(); 7349a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey 7359a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println("Historical install sessions:"); 7369a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.increaseIndent(); 7379a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey N = mHistoricalSessions.size(); 7389a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey for (int i = 0; i < N; i++) { 7399a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey final PackageInstallerSession session = mHistoricalSessions.valueAt(i); 7409a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey session.dump(pw); 7419a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println(); 7429a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey } 7439a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println(); 7449a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.decreaseIndent(); 745a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 746bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey } 747bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey 7481cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey class InternalCallback { 74916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey public void onSessionProgressChanged(PackageInstallerSession session, float progress) { 7501cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress); 7511cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 7521cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 7531cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void onSessionClosed(PackageInstallerSession session) { 7541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.notifySessionClosed(session.sessionId, session.userId); 7553a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 7563a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 757a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey public void onSessionFinished(PackageInstallerSession session, boolean success) { 7581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.notifySessionFinished(session.sessionId, session.userId, success); 759a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey synchronized (mSessions) { 760a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mSessions.remove(session.sessionId); 7619a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey mHistoricalSessions.put(session.sessionId, session); 762a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 7633a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey writeSessionsAsync(); 7643a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 7653a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 7663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey} 767