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 191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readBitmapAttribute; 201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readBooleanAttribute; 211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readIntAttribute; 221cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readLongAttribute; 231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readStringAttribute; 241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readUriAttribute; 251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeBooleanAttribute; 261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeIntAttribute; 271cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeLongAttribute; 281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeStringAttribute; 291cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeUriAttribute; 301cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; 311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.START_TAG; 321cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.app.ActivityManager; 343a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.app.AppOpsManager; 35a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.app.PackageDeleteObserver; 36a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.app.PackageInstallObserver; 373a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.Context; 38f06009542390472872da986486d385001e91a2a7Jeff Sharkeyimport android.content.Intent; 39a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.content.IntentSender; 40a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.content.IntentSender.SendIntentException; 413a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.pm.IPackageInstaller; 4216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkeyimport android.content.pm.IPackageInstallerCallback; 433a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.pm.IPackageInstallerSession; 44f06009542390472872da986486d385001e91a2a7Jeff Sharkeyimport android.content.pm.PackageInstaller; 45a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.content.pm.PackageInstaller.SessionInfo; 46a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.content.pm.PackageInstaller.SessionParams; 47ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkeyimport android.content.pm.PackageManager; 4897d47ed036ff7bd3d7d2ddc1c6df1104ec237559Jeff Sharkeyimport android.content.pm.ParceledListSlice; 491cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.graphics.Bitmap; 5002bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkeyimport android.graphics.Bitmap.CompressFormat; 5102bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkeyimport android.graphics.BitmapFactory; 52f06009542390472872da986486d385001e91a2a7Jeff Sharkeyimport android.net.Uri; 533a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.Binder; 54a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.os.Bundle; 551cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Environment; 563a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.FileUtils; 571cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Handler; 583a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.HandlerThread; 591cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Looper; 601cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.os.Message; 613a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.Process; 62a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.os.RemoteCallbackList; 63a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.os.RemoteException; 64ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.os.SELinux; 653a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.UserHandle; 663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.UserManager; 67ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.system.ErrnoException; 68ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.system.Os; 69a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyimport android.text.TextUtils; 701cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.text.format.DateUtils; 713a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.ArraySet; 721cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.util.AtomicFile; 73a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.util.ExceptionUtils; 743a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.Slog; 753a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.SparseArray; 76742e790294b3441b79f715fe447069b63c6065dbJeff Sharkeyimport android.util.SparseBooleanArray; 771cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport android.util.Xml; 783a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 793a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.android.internal.annotations.GuardedBy; 80742e790294b3441b79f715fe447069b63c6065dbJeff Sharkeyimport com.android.internal.content.PackageHelper; 811cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport com.android.internal.util.FastXmlSerializer; 82a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter; 833a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.android.server.IoThread; 843a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.google.android.collect.Sets; 853a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 861cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport libcore.io.IoUtils; 871cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 881cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport org.xmlpull.v1.XmlPullParser; 891cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport org.xmlpull.v1.XmlPullParserException; 901cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport org.xmlpull.v1.XmlSerializer; 911cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 923a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport java.io.File; 931cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.io.FileInputStream; 941cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.io.FileNotFoundException; 951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.io.FileOutputStream; 96ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport java.io.FilenameFilter; 97ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport java.io.IOException; 981cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.security.SecureRandom; 99bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport java.util.ArrayList; 100bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport java.util.List; 10116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkeyimport java.util.Objects; 1021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkeyimport java.util.Random; 1033a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1043a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeypublic class PackageInstallerService extends IPackageInstaller.Stub { 1053a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private static final String TAG = "PackageInstaller"; 106e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey private static final boolean LOGD = false; 1073a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1083a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: remove outstanding sessions when installer package goes away 1096c833e07a05c48ca60ee4d72421bf8b1e78dc710Jeff Sharkey // TODO: notify listeners in other users when package has been installed there 110742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // TODO: purge expired sessions periodically in addition to at reboot 1113a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1121cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey /** XML constants used in {@link #mSessionsFile} */ 1131cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String TAG_SESSIONS = "sessions"; 1141cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String TAG_SESSION = "session"; 1151cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SESSION_ID = "sessionId"; 1161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_USER_ID = "userId"; 1171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_INSTALLER_PACKAGE_NAME = "installerPackageName"; 118e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey private static final String ATTR_INSTALLER_UID = "installerUid"; 1191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_CREATED_MILLIS = "createdMillis"; 1201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir"; 121742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid"; 12277d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey private static final String ATTR_PREPARED = "prepared"; 1231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SEALED = "sealed"; 1241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_MODE = "mode"; 1251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_INSTALL_FLAGS = "installFlags"; 1261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_INSTALL_LOCATION = "installLocation"; 1271cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_SIZE_BYTES = "sizeBytes"; 1281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final String ATTR_APP_PACKAGE_NAME = "appPackageName"; 12902bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey @Deprecated 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; 149cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey private final Handler mInstallHandler; 1503a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1511cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final Callbacks mCallbacks; 1521cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1531cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey /** 15402bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey * File storing persisted {@link #mSessions} metadata. 1551cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey */ 1561cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final AtomicFile mSessionsFile; 1571cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 15802bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey /** 15902bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey * Directory storing persisted {@link #mSessions} metadata which is too 16002bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey * heavy to store directly in {@link #mSessionsFile}. 16102bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey */ 16202bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey private final File mSessionsDir; 16302bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey 1641cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final InternalCallback mInternalCallback = new InternalCallback(); 1651cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1661cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey /** 1671cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey * Used for generating session IDs. Since this is created at boot time, 1681cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey * normal random might be predictable. 1691cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey */ 1701cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final Random mRandom = new SecureRandom(); 1713a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1723a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @GuardedBy("mSessions") 1733a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>(); 1743a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1759a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey /** Historical sessions kept around for debugging purposes */ 1769a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey @GuardedBy("mSessions") 1779a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey private final SparseArray<PackageInstallerSession> mHistoricalSessions = new SparseArray<>(); 1789a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey 179742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey /** Sessions allocated to legacy users */ 180742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey @GuardedBy("mSessions") 181742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey private final SparseBooleanArray mLegacySessions = new SparseBooleanArray(); 182742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 183ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey private static final FilenameFilter sStageFilter = new FilenameFilter() { 184ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey @Override 185ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey public boolean accept(File dir, String name) { 186742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey return isStageName(name); 187ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 188ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey }; 189ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 1903a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public PackageInstallerService(Context context, PackageManagerService pm, File stagingDir) { 1913a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mContext = context; 1923a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mPm = pm; 1933a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 1943a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1953a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mStagingDir = stagingDir; 196ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 197ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mInstallThread = new HandlerThread(TAG); 198ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mInstallThread.start(); 1993a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 200cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey mInstallHandler = new Handler(mInstallThread.getLooper()); 201cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey 2021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks = new Callbacks(mInstallThread.getLooper()); 2031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2041cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessionsFile = new AtomicFile( 2051cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey new File(Environment.getSystemSecureDirectory(), "install_sessions.xml")); 20602bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey mSessionsDir = new File(Environment.getSystemSecureDirectory(), "install_sessions"); 20702bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey mSessionsDir.mkdirs(); 2081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 2093a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 2103a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey readSessionsLocked(); 2113a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 21202bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey final ArraySet<File> unclaimedStages = Sets.newArraySet( 21302bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey mStagingDir.listFiles(sStageFilter)); 21402bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey final ArraySet<File> unclaimedIcons = Sets.newArraySet( 21502bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey mSessionsDir.listFiles()); 216742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 21702bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey // Ignore stages and icons claimed by active sessions 2183a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 219ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 22002bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey unclaimedStages.remove(session.stageDir); 22102bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey unclaimedIcons.remove(buildAppIconFile(session.sessionId)); 222ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 223742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 224742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Clean up orphaned staging directories 22502bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey for (File stage : unclaimedStages) { 226ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey Slog.w(TAG, "Deleting orphan stage " + stage); 227ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey if (stage.isDirectory()) { 228ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey FileUtils.deleteContents(stage); 229ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 230ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey stage.delete(); 2313a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 23202bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey 23302bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey // Clean up orphaned icons 23402bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey for (File icon : unclaimedIcons) { 23502bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey Slog.w(TAG, "Deleting orphan icon " + icon); 23602bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey icon.delete(); 23702bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey } 238ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 239ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 240ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 241742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey public void onSecureContainersAvailable() { 242742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey synchronized (mSessions) { 243742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final ArraySet<String> unclaimed = new ArraySet<>(); 244742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey for (String cid : PackageHelper.getSecureContainerList()) { 245742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (isStageName(cid)) { 246742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey unclaimed.add(cid); 247742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 248742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 249742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 250742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Ignore stages claimed by active sessions 251742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 252742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 253941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey final String cid = session.stageCid; 254742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 255742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (unclaimed.remove(cid)) { 256742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Claimed by active session, mount it 257742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey PackageHelper.mountSdDir(cid, PackageManagerService.getEncryptKey(), 258742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey Process.SYSTEM_UID); 259742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 260742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 261742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 262742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // Clean up orphaned staging containers 263742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey for (String cid : unclaimed) { 264742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey Slog.w(TAG, "Deleting orphan container " + cid); 265742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey PackageHelper.destroySdDir(cid); 266742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 267742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 268742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 269742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 270742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey public static boolean isStageName(String name) { 271742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final boolean isFile = name.startsWith("vmdl") && name.endsWith(".tmp"); 272742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final boolean isContainer = name.startsWith("smdl") && name.endsWith(".tmp"); 273742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final boolean isLegacyContainer = name.startsWith("smdl2tmp"); 274742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey return isFile || isContainer || isLegacyContainer; 2757328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey } 2767328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey 277ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey @Deprecated 278742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey public File allocateInternalStageDirLegacy() throws IOException { 279ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey synchronized (mSessions) { 280ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey try { 281ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final int sessionId = allocateSessionIdLocked(); 282742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey mLegacySessions.put(sessionId, true); 28377d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey final File stageDir = buildInternalStageDir(sessionId); 28477d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey prepareInternalStageDir(stageDir); 28577d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey return stageDir; 286ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } catch (IllegalStateException e) { 287ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey throw new IOException(e); 2883a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2893a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2903a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2913a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 292742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey @Deprecated 293742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey public String allocateExternalStageCidLegacy() { 294742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey synchronized (mSessions) { 295742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final int sessionId = allocateSessionIdLocked(); 296742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey mLegacySessions.put(sessionId, true); 297742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey return "smdl" + sessionId + ".tmp"; 298742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 299742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 300742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 3013a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void readSessionsLocked() { 3021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (LOGD) Slog.v(TAG, "readSessionsLocked()"); 3031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3043a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mSessions.clear(); 3051cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3061cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey FileInputStream fis = null; 3071cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey try { 3081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey fis = mSessionsFile.openRead(); 3091cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final XmlPullParser in = Xml.newPullParser(); 3101cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey in.setInput(fis, null); 3111cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3121cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int type; 3131cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey while ((type = in.next()) != END_DOCUMENT) { 3141cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (type == START_TAG) { 3151cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final String tag = in.getName(); 3161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (TAG_SESSION.equals(tag)) { 3171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final PackageInstallerSession session = readSessionLocked(in); 3181cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final long age = System.currentTimeMillis() - session.createdMillis; 3191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final boolean valid; 3211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (age >= MAX_AGE_MILLIS) { 3221cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Slog.w(TAG, "Abandoning old session first created at " 3231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey + session.createdMillis); 3241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey valid = false; 325941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey } else if (session.stageDir != null 326941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey && !session.stageDir.exists()) { 327742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey Slog.w(TAG, "Abandoning internal session with missing stage " 328941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey + session.stageDir); 3291cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey valid = false; 3301cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } else { 3311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey valid = true; 3321cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3341cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (valid) { 3351cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessions.put(session.sessionId, session); 3361cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } else { 3371cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Since this is early during boot we don't send 3381cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // any observer events about the session, but we 3391cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // keep details around for dumpsys. 3401cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mHistoricalSessions.put(session.sessionId, session); 3411cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3421cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3431cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3441cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3451cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (FileNotFoundException e) { 3461cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Missing sessions are okay, probably first boot 3471cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (IOException e) { 3488d05172112436a81bed6e4a0810f8914509d8a4dDianne Hackborn Slog.wtf(TAG, "Failed reading install sessions", e); 3491cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (XmlPullParserException e) { 3508d05172112436a81bed6e4a0810f8914509d8a4dDianne Hackborn Slog.wtf(TAG, "Failed reading install sessions", e); 3511cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } finally { 3521cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey IoUtils.closeQuietly(fis); 3531cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 3551cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3561cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private PackageInstallerSession readSessionLocked(XmlPullParser in) throws IOException { 3571cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int sessionId = readIntAttribute(in, ATTR_SESSION_ID); 3581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int userId = readIntAttribute(in, ATTR_USER_ID); 3591cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final String installerPackageName = readStringAttribute(in, ATTR_INSTALLER_PACKAGE_NAME); 360e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey final int installerUid = readIntAttribute(in, ATTR_INSTALLER_UID, 361e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey mPm.getPackageUid(installerPackageName, userId)); 3621cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS); 363742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR); 364742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null; 365742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID); 36677d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey final boolean prepared = readBooleanAttribute(in, ATTR_PREPARED, true); 3671cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final boolean sealed = readBooleanAttribute(in, ATTR_SEALED); 3681cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 369a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final SessionParams params = new SessionParams( 370a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey SessionParams.MODE_INVALID); 3711cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.mode = readIntAttribute(in, ATTR_MODE); 3721cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.installFlags = readIntAttribute(in, ATTR_INSTALL_FLAGS); 3731cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.installLocation = readIntAttribute(in, ATTR_INSTALL_LOCATION); 3741cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.sizeBytes = readLongAttribute(in, ATTR_SIZE_BYTES); 3751cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appPackageName = readStringAttribute(in, ATTR_APP_PACKAGE_NAME); 3761cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appIcon = readBitmapAttribute(in, ATTR_APP_ICON); 3771cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appLabel = readStringAttribute(in, ATTR_APP_LABEL); 3781cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.originatingUri = readUriAttribute(in, ATTR_ORIGINATING_URI); 3791cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.referrerUri = readUriAttribute(in, ATTR_REFERRER_URI); 3801cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.abiOverride = readStringAttribute(in, ATTR_ABI_OVERRIDE); 3811cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 38202bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey final File appIconFile = buildAppIconFile(sessionId); 38302bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey if (appIconFile.exists()) { 38402bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey params.appIcon = BitmapFactory.decodeFile(appIconFile.getAbsolutePath()); 38502bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey params.appIconLastModified = appIconFile.lastModified(); 38602bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey } 38702bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey 388a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey return new PackageInstallerSession(mInternalCallback, mContext, mPm, 389e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey mInstallThread.getLooper(), sessionId, userId, installerPackageName, installerUid, 390e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey params, createdMillis, stageDir, stageCid, prepared, sealed); 3913a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 3923a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 3933a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void writeSessionsLocked() { 3941cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (LOGD) Slog.v(TAG, "writeSessionsLocked()"); 3951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 3961cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey FileOutputStream fos = null; 3971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey try { 3981cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey fos = mSessionsFile.startWrite(); 3991cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 4001cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey XmlSerializer out = new FastXmlSerializer(); 4011cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.setOutput(fos, "utf-8"); 4021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.startDocument(null, true); 4031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.startTag(null, TAG_SESSIONS); 4041cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int size = mSessions.size(); 4051cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey for (int i = 0; i < size; i++) { 4061cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 4071cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeSessionLocked(out, session); 4081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 4091cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.endTag(null, TAG_SESSIONS); 4101cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.endDocument(); 4111cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 4121cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessionsFile.finishWrite(fos); 4131cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (IOException e) { 4141cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (fos != null) { 4151cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mSessionsFile.failWrite(fos); 4161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 4171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 4181cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 4191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 4201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void writeSessionLocked(XmlSerializer out, PackageInstallerSession session) 4211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey throws IOException { 422a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final SessionParams params = session.params; 4231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 4241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.startTag(null, TAG_SESSION); 4251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 4261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_SESSION_ID, session.sessionId); 4271cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_USER_ID, session.userId); 4281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME, 4291cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey session.installerPackageName); 430e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey writeIntAttribute(out, ATTR_INSTALLER_UID, session.installerUid); 4311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeLongAttribute(out, ATTR_CREATED_MILLIS, session.createdMillis); 432941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey if (session.stageDir != null) { 433742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey writeStringAttribute(out, ATTR_SESSION_STAGE_DIR, 434941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey session.stageDir.getAbsolutePath()); 435742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 436941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey if (session.stageCid != null) { 437941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey writeStringAttribute(out, ATTR_SESSION_STAGE_CID, session.stageCid); 438742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 43977d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey writeBooleanAttribute(out, ATTR_PREPARED, session.isPrepared()); 440742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey writeBooleanAttribute(out, ATTR_SEALED, session.isSealed()); 4411cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 4421cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_MODE, params.mode); 4431cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_INSTALL_FLAGS, params.installFlags); 4441cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeIntAttribute(out, ATTR_INSTALL_LOCATION, params.installLocation); 4451cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeLongAttribute(out, ATTR_SIZE_BYTES, params.sizeBytes); 4461cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeStringAttribute(out, ATTR_APP_PACKAGE_NAME, params.appPackageName); 4471cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeStringAttribute(out, ATTR_APP_LABEL, params.appLabel); 4481cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeUriAttribute(out, ATTR_ORIGINATING_URI, params.originatingUri); 4491cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeUriAttribute(out, ATTR_REFERRER_URI, params.referrerUri); 4501cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey writeStringAttribute(out, ATTR_ABI_OVERRIDE, params.abiOverride); 4511cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 45202bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey // Persist app icon if changed since last written 45302bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey final File appIconFile = buildAppIconFile(session.sessionId); 45402bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey if (params.appIcon == null && appIconFile.exists()) { 45502bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey appIconFile.delete(); 45602bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey } else if (params.appIcon != null 45702bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey && appIconFile.lastModified() != params.appIconLastModified) { 45802bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey if (LOGD) Slog.w(TAG, "Writing changed icon " + appIconFile); 45902bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey FileOutputStream os = null; 46002bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey try { 46102bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey os = new FileOutputStream(appIconFile); 46202bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey params.appIcon.compress(CompressFormat.PNG, 90, os); 46302bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey } catch (IOException e) { 46402bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey Slog.w(TAG, "Failed to write icon " + appIconFile + ": " + e.getMessage()); 46502bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey } finally { 46602bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey IoUtils.closeQuietly(os); 46702bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey } 46802bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey 46902bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey params.appIconLastModified = appIconFile.lastModified(); 47002bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey } 47102bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey 4721cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey out.endTag(null, TAG_SESSION); 4733a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4743a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 47502bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey private File buildAppIconFile(int sessionId) { 47602bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey return new File(mSessionsDir, "app_icon." + sessionId + ".png"); 47702bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey } 47802bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey 4793a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void writeSessionsAsync() { 4803a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey IoThread.getHandler().post(new Runnable() { 4813a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 4823a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public void run() { 4833a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 4843a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey writeSessionsLocked(); 4853a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4863a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4873a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey }); 4883a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 4893a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 4903a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 491a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public int createSession(SessionParams params, String installerPackageName, int userId) { 492742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey try { 493742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey return createSessionInternal(params, installerPackageName, userId); 494742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } catch (IOException e) { 495742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throw ExceptionUtils.wrap(e); 496742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 497742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 498742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 499742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey private int createSessionInternal(SessionParams params, String installerPackageName, int userId) 500742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throws IOException { 5013a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final int callingUid = Binder.getCallingUid(); 502e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey mPm.enforceCrossUserPermission(callingUid, userId, true, true, "createSession"); 5033a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 504e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey if (mPm.isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) { 5053a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new SecurityException("User restriction prevents installing"); 5063a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5073a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 5081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) { 509e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey params.installFlags |= PackageManager.INSTALL_FROM_ADB; 5101cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 5113a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } else { 512ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mAppOps.checkPackage(callingUid, installerPackageName); 513ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 514e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey params.installFlags &= ~PackageManager.INSTALL_FROM_ADB; 515e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey params.installFlags &= ~PackageManager.INSTALL_ALL_USERS; 516e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; 5173a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5183a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 5191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Defensively resize giant app icons 5201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (params.appIcon != null) { 5211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final ActivityManager am = (ActivityManager) mContext.getSystemService( 5221cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey Context.ACTIVITY_SERVICE); 5231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int iconSize = am.getLauncherLargeIconSize(); 5241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if ((params.appIcon.getWidth() > iconSize * 2) 5251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey || (params.appIcon.getHeight() > iconSize * 2)) { 5261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize, 5271cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey true); 5281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 5291cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 5301cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 53177d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey if (params.mode == SessionParams.MODE_FULL_INSTALL 53277d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey || params.mode == SessionParams.MODE_INHERIT_EXISTING) { 53377d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey // Resolve best location for install, based on combination of 53477d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey // requested install flags, delta size, and manifest settings. 535e812d9096915ad165de125520ed7371009587d1fRobin Lee final long ident = Binder.clearCallingIdentity(); 536e812d9096915ad165de125520ed7371009587d1fRobin Lee try { 537e812d9096915ad165de125520ed7371009587d1fRobin Lee final int resolved = PackageHelper.resolveInstallLocation(mContext, 538e812d9096915ad165de125520ed7371009587d1fRobin Lee params.appPackageName, params.installLocation, params.sizeBytes, 539e812d9096915ad165de125520ed7371009587d1fRobin Lee params.installFlags); 540e812d9096915ad165de125520ed7371009587d1fRobin Lee 541e812d9096915ad165de125520ed7371009587d1fRobin Lee if (resolved == PackageHelper.RECOMMEND_INSTALL_INTERNAL) { 54277d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey params.setInstallFlagsInternal(); 543e812d9096915ad165de125520ed7371009587d1fRobin Lee } else if (resolved == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) { 54477d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey params.setInstallFlagsExternal(); 545e812d9096915ad165de125520ed7371009587d1fRobin Lee } else { 546e812d9096915ad165de125520ed7371009587d1fRobin Lee throw new IOException("No storage with enough free space; res=" + resolved); 547e812d9096915ad165de125520ed7371009587d1fRobin Lee } 548e812d9096915ad165de125520ed7371009587d1fRobin Lee } finally { 549e812d9096915ad165de125520ed7371009587d1fRobin Lee Binder.restoreCallingIdentity(ident); 550a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 551742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } else { 552742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey throw new IllegalArgumentException("Invalid install mode: " + params.mode); 553a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 554a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 555a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final int sessionId; 556a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final PackageInstallerSession session; 5573a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 5581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // Sanity check that installer isn't going crazy 559f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final int activeCount = getSessionCount(mSessions, callingUid); 5601cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (activeCount >= MAX_ACTIVE_SESSIONS) { 561f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey throw new IllegalStateException( 562f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey "Too many active sessions for UID " + callingUid); 563f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey } 564f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final int historicalCount = getSessionCount(mHistoricalSessions, callingUid); 565f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey if (historicalCount >= MAX_HISTORICAL_SESSIONS) { 566f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey throw new IllegalStateException( 567f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey "Too many historical sessions for UID " + callingUid); 5681cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 5691cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 570742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final long createdMillis = System.currentTimeMillis(); 571a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey sessionId = allocateSessionIdLocked(); 572a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 573742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey // We're staging to exactly one location 574742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey File stageDir = null; 575742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey String stageCid = null; 57677d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) { 57777d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey stageDir = buildInternalStageDir(sessionId); 578742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } else { 57977d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey stageCid = buildExternalStageCid(sessionId); 580742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 5813a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 582a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey session = new PackageInstallerSession(mInternalCallback, mContext, mPm, 583e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid, 584e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey params, createdMillis, stageDir, stageCid, false, false); 5853a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mSessions.put(sessionId, session); 5863a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 587a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 5881cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.notifySessionCreated(session.sessionId, session.userId); 589a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey writeSessionsAsync(); 590a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey return sessionId; 5913a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 5923a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 593381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey @Override 594ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey public void updateSessionAppIcon(int sessionId, Bitmap appIcon) { 595ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey synchronized (mSessions) { 596ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 597ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey if (session == null || !isCallingUidOwner(session)) { 598ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey throw new SecurityException("Caller has no access to session " + sessionId); 599ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 60002bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey 60102bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey // Defensively resize giant app icons 60202bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey if (appIcon != null) { 60302bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey final ActivityManager am = (ActivityManager) mContext.getSystemService( 60402bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey Context.ACTIVITY_SERVICE); 60502bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey final int iconSize = am.getLauncherLargeIconSize(); 60602bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey if ((appIcon.getWidth() > iconSize * 2) 60702bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey || (appIcon.getHeight() > iconSize * 2)) { 60802bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey appIcon = Bitmap.createScaledBitmap(appIcon, iconSize, iconSize, true); 60902bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey } 61002bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey } 61102bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey 612ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey session.params.appIcon = appIcon; 61302bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey session.params.appIconLastModified = -1; 61402bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey 615ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey mInternalCallback.onSessionBadgingChanged(session); 616ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 617ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 618ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey 619ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey @Override 620ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey public void updateSessionAppLabel(int sessionId, String appLabel) { 621ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey synchronized (mSessions) { 622ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 623ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey if (session == null || !isCallingUidOwner(session)) { 624ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey throw new SecurityException("Caller has no access to session " + sessionId); 625ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 626ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey session.params.appLabel = appLabel; 627ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey mInternalCallback.onSessionBadgingChanged(session); 628ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 629ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 630ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey 631ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey @Override 632381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey public void abandonSession(int sessionId) { 633381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey synchronized (mSessions) { 634381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 635381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey if (session == null || !isCallingUidOwner(session)) { 636381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey throw new SecurityException("Caller has no access to session " + sessionId); 637381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey } 638381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey session.abandon(); 639381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey } 640381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey } 641381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey 64277d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey @Override 64377d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey public IPackageInstallerSession openSession(int sessionId) { 64477d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey try { 64577d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey return openSessionInternal(sessionId); 64677d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey } catch (IOException e) { 64777d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey throw ExceptionUtils.wrap(e); 648742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 649742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 650742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 65177d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey private IPackageInstallerSession openSessionInternal(int sessionId) throws IOException { 6523a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 6533a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 654381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkey if (session == null || !isCallingUidOwner(session)) { 6553a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new SecurityException("Caller has no access to session " + sessionId); 6563a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 657742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey session.open(); 6583a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey return session; 6593a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 6603a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 6613a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 6623a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private int allocateSessionIdLocked() { 6631cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int n = 0; 6641cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int sessionId; 6651cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey do { 666f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey sessionId = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1; 667742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey if (mSessions.get(sessionId) == null && mHistoricalSessions.get(sessionId) == null 668742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey && !mLegacySessions.get(sessionId, false)) { 6691cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return sessionId; 6701cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 6711cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } while (n++ < 32); 6721cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 6731cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey throw new IllegalStateException("Failed to allocate session ID"); 6743a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 6753a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 67677d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey private File buildInternalStageDir(int sessionId) { 67777d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey return new File(mStagingDir, "vmdl" + sessionId + ".tmp"); 67877d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey } 679ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 68077d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey static void prepareInternalStageDir(File stageDir) throws IOException { 68177d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey if (stageDir.exists()) { 68277d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey throw new IOException("Session dir already exists: " + stageDir); 683ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 684ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 685ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey try { 68677d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey Os.mkdir(stageDir.getAbsolutePath(), 0755); 68777d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey Os.chmod(stageDir.getAbsolutePath(), 0755); 688ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } catch (ErrnoException e) { 689ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey // This purposefully throws if directory already exists 69077d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey throw new IOException("Failed to prepare session dir: " + stageDir, e); 691ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 692ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 69377d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey if (!SELinux.restorecon(stageDir)) { 69477d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey throw new IOException("Failed to restorecon session dir: " + stageDir); 695ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 696ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 697ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 69877d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey private String buildExternalStageCid(int sessionId) { 69977d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey return "smdl" + sessionId + ".tmp"; 70077d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey } 701742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 70277d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey static void prepareExternalStageCid(String stageCid, long sizeBytes) throws IOException { 70377d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey if (PackageHelper.createSdDir(sizeBytes, stageCid, PackageManagerService.getEncryptKey(), 704742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey Process.SYSTEM_UID, true) == null) { 70577d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey throw new IOException("Failed to create session cid: " + stageCid); 706742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 707742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 708742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 7093a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 710a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public SessionInfo getSessionInfo(int sessionId) { 71116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey synchronized (mSessions) { 71216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 71316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey return session != null ? session.generateInfo() : null; 71416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 71516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 71616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 71716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey @Override 71897d47ed036ff7bd3d7d2ddc1c6df1104ec237559Jeff Sharkey public ParceledListSlice<SessionInfo> getAllSessions(int userId) { 7198cd28b57ed732656d002d97879e15c5695b54fffAmith Yamasani mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "getAllSessions"); 7203a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 721a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final List<SessionInfo> result = new ArrayList<>(); 7223a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 7233a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 7243a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 725bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey if (session.userId == userId) { 726bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey result.add(session.generateInfo()); 7273a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 7283a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 7293a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 73097d47ed036ff7bd3d7d2ddc1c6df1104ec237559Jeff Sharkey return new ParceledListSlice<>(result); 7313a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 7323a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 7333a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 73497d47ed036ff7bd3d7d2ddc1c6df1104ec237559Jeff Sharkey public ParceledListSlice<SessionInfo> getMySessions(String installerPackageName, int userId) { 7358cd28b57ed732656d002d97879e15c5695b54fffAmith Yamasani mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "getMySessions"); 73616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mAppOps.checkPackage(Binder.getCallingUid(), installerPackageName); 73716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 738a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final List<SessionInfo> result = new ArrayList<>(); 73916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey synchronized (mSessions) { 74016c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 74116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 74216c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey if (Objects.equals(session.installerPackageName, installerPackageName) 74316c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey && session.userId == userId) { 74416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey result.add(session.generateInfo()); 74516c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 74616c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 74716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 74897d47ed036ff7bd3d7d2ddc1c6df1104ec237559Jeff Sharkey return new ParceledListSlice<>(result); 74916c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey } 75016c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 75116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey @Override 752a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void uninstall(String packageName, int flags, IntentSender statusReceiver, int userId) { 753e980804df16c968c14a56b8853886bf5f049f46eJeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, true, "uninstall"); 75416c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey 755a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext, 756bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey statusReceiver, packageName); 757f06009542390472872da986486d385001e91a2a7Jeff Sharkey if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES) 758f06009542390472872da986486d385001e91a2a7Jeff Sharkey == PackageManager.PERMISSION_GRANTED) { 759f06009542390472872da986486d385001e91a2a7Jeff Sharkey // Sweet, call straight through! 760a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mPm.deletePackage(packageName, adapter.getBinder(), userId, flags); 761f06009542390472872da986486d385001e91a2a7Jeff Sharkey 762f06009542390472872da986486d385001e91a2a7Jeff Sharkey } else { 763f06009542390472872da986486d385001e91a2a7Jeff Sharkey // Take a short detour to confirm with user 764f06009542390472872da986486d385001e91a2a7Jeff Sharkey final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE); 765f06009542390472872da986486d385001e91a2a7Jeff Sharkey intent.setData(Uri.fromParts("package", packageName, null)); 766a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey intent.putExtra(PackageInstaller.EXTRA_CALLBACK, adapter.getBinder().asBinder()); 767a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey adapter.onUserActionRequired(intent); 768f06009542390472872da986486d385001e91a2a7Jeff Sharkey } 7693a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 7703a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 7713a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 7727328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey public void setPermissionsResult(int sessionId, boolean accepted) { 7737328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, TAG); 7747328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey 7757328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey synchronized (mSessions) { 7767328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey mSessions.get(sessionId).setPermissionsResult(accepted); 7777328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey } 7787328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey } 7797328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey 7807328a1b39b3dae1c0cd390c0a3695c6a46b8e9d8Jeff Sharkey @Override 78116c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey public void registerCallback(IPackageInstallerCallback callback, int userId) { 7828cd28b57ed732656d002d97879e15c5695b54fffAmith Yamasani mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "registerCallback"); 7831cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.register(callback, userId); 784bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey } 785bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey 786bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey @Override 78716c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey public void unregisterCallback(IPackageInstallerCallback callback) { 78816c8e3f49497b6046972ae650772f65768366be8Jeff Sharkey mCallbacks.unregister(callback); 789a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 790a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 791f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey private static int getSessionCount(SparseArray<PackageInstallerSession> sessions, 792f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey int installerUid) { 7931cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey int count = 0; 794f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final int size = sessions.size(); 7951cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey for (int i = 0; i < size; i++) { 796f174c6e6de6ba863179401aa7b3d55d91ceed707Jeff Sharkey final PackageInstallerSession session = sessions.valueAt(i); 7971cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (session.installerUid == installerUid) { 7981cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey count++; 7991cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 8001cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 8011cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return count; 8021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 8031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 8041cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private boolean isCallingUidOwner(PackageInstallerSession session) { 8051cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int callingUid = Binder.getCallingUid(); 8061cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (callingUid == Process.ROOT_UID) { 8071cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return true; 8081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } else { 8091cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey return (session != null) && (callingUid == session.installerUid); 810a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 811a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 812a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 813a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey static class PackageDeleteObserverAdapter extends PackageDeleteObserver { 814a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey private final Context mContext; 815a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey private final IntentSender mTarget; 816bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey private final String mPackageName; 817a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 818bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey public PackageDeleteObserverAdapter(Context context, IntentSender target, 819bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey String packageName) { 820a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mContext = context; 821a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget = target; 822bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey mPackageName = packageName; 823a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 824a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 825a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey @Override 826a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void onUserActionRequired(Intent intent) { 827a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final Intent fillIn = new Intent(); 828bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName); 829a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS, 830742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey PackageInstaller.STATUS_PENDING_USER_ACTION); 831a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(Intent.EXTRA_INTENT, intent); 832a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey try { 833a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget.sendIntent(mContext, 0, fillIn, null, null); 834a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } catch (SendIntentException ignored) { 835a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 836a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 837a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 838a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey @Override 839a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void onPackageDeleted(String basePackageName, int returnCode, String msg) { 840a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final Intent fillIn = new Intent(); 841bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName); 842a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS, 843a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.deleteStatusToPublicStatus(returnCode)); 844a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, 845a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.deleteStatusToString(returnCode, msg)); 846a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode); 847a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey try { 848a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget.sendIntent(mContext, 0, fillIn, null, null); 849a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } catch (SendIntentException ignored) { 850a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 851a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 852a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 853a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 854a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey static class PackageInstallObserverAdapter extends PackageInstallObserver { 855a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey private final Context mContext; 856a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey private final IntentSender mTarget; 857bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey private final int mSessionId; 858a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 859bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey public PackageInstallObserverAdapter(Context context, IntentSender target, int sessionId) { 860a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mContext = context; 861a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget = target; 862bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey mSessionId = sessionId; 863a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 864a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 865a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey @Override 866a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void onUserActionRequired(Intent intent) { 867a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final Intent fillIn = new Intent(); 868bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId); 869a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS, 870742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey PackageInstaller.STATUS_PENDING_USER_ACTION); 871a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(Intent.EXTRA_INTENT, intent); 872a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey try { 873a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget.sendIntent(mContext, 0, fillIn, null, null); 874a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } catch (SendIntentException ignored) { 875a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 876a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 877a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 878a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey @Override 879a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey public void onPackageInstalled(String basePackageName, int returnCode, String msg, 880a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey Bundle extras) { 881a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final Intent fillIn = new Intent(); 882bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId); 883a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS, 884a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.installStatusToPublicStatus(returnCode)); 885a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, 886a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.installStatusToString(returnCode, msg)); 887a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode); 888a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey if (extras != null) { 889a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey final String existing = extras.getString( 890a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE); 891a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey if (!TextUtils.isEmpty(existing)) { 892941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing); 893a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 894a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 895a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey try { 896a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey mTarget.sendIntent(mContext, 0, fillIn, null, null); 897a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } catch (SendIntentException ignored) { 898a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 899a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 900a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey } 901a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkey 9021cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static class Callbacks extends Handler { 9031cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private static final int MSG_SESSION_CREATED = 1; 904ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey private static final int MSG_SESSION_BADGING_CHANGED = 2; 905bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey private static final int MSG_SESSION_ACTIVE_CHANGED = 3; 906ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey private static final int MSG_SESSION_PROGRESS_CHANGED = 4; 907bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey private static final int MSG_SESSION_FINISHED = 5; 9081cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9091cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private final RemoteCallbackList<IPackageInstallerCallback> 9101cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks = new RemoteCallbackList<>(); 9111cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9121cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public Callbacks(Looper looper) { 9131cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey super(looper); 914a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 915a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 9161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void register(IPackageInstallerCallback callback, int userId) { 9171cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.register(callback, new UserHandle(userId)); 9181cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 9191cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void unregister(IPackageInstallerCallback callback) { 9211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.unregister(callback); 9221cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 9231cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9241cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey @Override 9251cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void handleMessage(Message msg) { 9261cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int userId = msg.arg2; 9271cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int n = mCallbacks.beginBroadcast(); 9281cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey for (int i = 0; i < n; i++) { 9291cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final IPackageInstallerCallback callback = mCallbacks.getBroadcastItem(i); 9301cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final UserHandle user = (UserHandle) mCallbacks.getBroadcastCookie(i); 9311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey // TODO: dispatch notifications for slave profiles 9321cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey if (userId == user.getIdentifier()) { 9331cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey try { 9341cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey invokeCallback(callback, msg); 9351cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } catch (RemoteException ignored) { 9361cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 937a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 938a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 9391cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.finishBroadcast(); 940a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 941a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 9421cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void invokeCallback(IPackageInstallerCallback callback, Message msg) 9431cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey throws RemoteException { 9441cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey final int sessionId = msg.arg1; 9451cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey switch (msg.what) { 9461cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_CREATED: 9471cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionCreated(sessionId); 9481cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 949ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey case MSG_SESSION_BADGING_CHANGED: 950ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey callback.onSessionBadgingChanged(sessionId); 951ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey break; 952bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey case MSG_SESSION_ACTIVE_CHANGED: 953bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey callback.onSessionActiveChanged(sessionId, (boolean) msg.obj); 9541cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 9551cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_PROGRESS_CHANGED: 9561cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionProgressChanged(sessionId, (float) msg.obj); 9571cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 9581cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey case MSG_SESSION_FINISHED: 9591cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey callback.onSessionFinished(sessionId, (boolean) msg.obj); 9601cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey break; 961a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 962a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 9631cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9641cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void notifySessionCreated(int sessionId, int userId) { 9651cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_CREATED, sessionId, userId).sendToTarget(); 9661cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 9671cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 968ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey private void notifySessionBadgingChanged(int sessionId, int userId) { 969ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, userId).sendToTarget(); 970ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 971ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey 972bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey private void notifySessionActiveChanged(int sessionId, int userId, boolean active) { 973bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey obtainMessage(MSG_SESSION_ACTIVE_CHANGED, sessionId, userId, active).sendToTarget(); 9741cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 9751cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9761cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey private void notifySessionProgressChanged(int sessionId, int userId, float progress) { 9771cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, userId, progress).sendToTarget(); 9781cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 9791cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 9801cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey public void notifySessionFinished(int sessionId, int userId, boolean success) { 9811cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey obtainMessage(MSG_SESSION_FINISHED, sessionId, userId, success).sendToTarget(); 9821cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 983a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 984a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 985a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey void dump(IndentingPrintWriter pw) { 986a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey synchronized (mSessions) { 9879a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println("Active install sessions:"); 9889a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.increaseIndent(); 9899a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey int N = mSessions.size(); 990a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey for (int i = 0; i < N; i++) { 991a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 992a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey session.dump(pw); 993a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey pw.println(); 994a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 9959a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println(); 9969a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.decreaseIndent(); 9979a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey 9989a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println("Historical install sessions:"); 9999a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.increaseIndent(); 10009a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey N = mHistoricalSessions.size(); 10019a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey for (int i = 0; i < N; i++) { 10029a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey final PackageInstallerSession session = mHistoricalSessions.valueAt(i); 10039a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey session.dump(pw); 10049a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println(); 10059a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey } 10069a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.println(); 10079a445771f57dd15b06db0dbefd66c368d84eec2dJeff Sharkey pw.decreaseIndent(); 1008742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 1009742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey pw.println("Legacy install sessions:"); 1010742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey pw.increaseIndent(); 1011742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey pw.println(mLegacySessions.toString()); 1012742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey pw.decreaseIndent(); 1013a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 1014bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey } 1015bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey 10161cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey class InternalCallback { 1017ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey public void onSessionBadgingChanged(PackageInstallerSession session) { 1018ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey mCallbacks.notifySessionBadgingChanged(session.sessionId, session.userId); 1019ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey writeSessionsAsync(); 10201cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey } 10211cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey 1022bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey public void onSessionActiveChanged(PackageInstallerSession session, boolean active) { 1023bc7bce38b2e4733a14f6296c75f983bd50f996d1Jeff Sharkey mCallbacks.notifySessionActiveChanged(session.sessionId, session.userId, active); 1024742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } 1025742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey 1026ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey public void onSessionProgressChanged(PackageInstallerSession session, float progress) { 1027ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress); 1028ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey } 1029ec9bad2015c6d3bc91bab66f0824043c1e24d013Jeff Sharkey 1030cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey public void onSessionFinished(final PackageInstallerSession session, boolean success) { 10311cb2d0d4bba387665128c62c342e59103ea4be26Jeff Sharkey mCallbacks.notifySessionFinished(session.sessionId, session.userId, success); 1032cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey 1033cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey mInstallHandler.post(new Runnable() { 1034cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey @Override 1035cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey public void run() { 1036cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey synchronized (mSessions) { 1037cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey mSessions.remove(session.sessionId); 1038cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey mHistoricalSessions.put(session.sessionId, session); 103902bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey 104002bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey final File appIconFile = buildAppIconFile(session.sessionId); 104102bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey if (appIconFile.exists()) { 104202bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey appIconFile.delete(); 104302bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey } 104402bd78490d8594d225ecc70a74b2058cb968a657Jeff Sharkey 1045cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey writeSessionsLocked(); 1046cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey } 1047cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey } 1048cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey }); 10493a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1050bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 105177d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey public void onSessionPrepared(PackageInstallerSession session) { 105277d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey // We prepared the destination to write into; we want to persist 105377d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey // this, but it's not critical enough to block for. 105477d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey writeSessionsAsync(); 105577d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey } 105677d218e1869e69c8d436b09cd11dcfe45e50b2cfJeff Sharkey 1057cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey public void onSessionSealedBlocking(PackageInstallerSession session) { 1058bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // It's very important that we block until we've recorded the 1059bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // session as being sealed, since we never want to allow mutation 1060bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // after sealing. 1061cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey synchronized (mSessions) { 1062cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey writeSessionsLocked(); 1063cbf47916b3e7a971c3a61035eb2633f96fc043cbJeff Sharkey } 1064bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 10653a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 10663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey} 1067