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