PackageInstallerService.java revision 6c833e07a05c48ca60ee4d72421bf8b1e78dc710
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; 223a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 233a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.app.AppOpsManager; 243a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.Context; 253a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.pm.IPackageDeleteObserver; 263a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.pm.IPackageInstaller; 27bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport android.content.pm.IPackageInstallerObserver; 283a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.pm.IPackageInstallerSession; 29bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport android.content.pm.InstallSessionInfo; 30bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport android.content.pm.InstallSessionParams; 313a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.Binder; 323a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.FileUtils; 333a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.HandlerThread; 343a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.Process; 35a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.os.RemoteCallbackList; 36a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.os.RemoteException; 37ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.os.SELinux; 383a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.UserHandle; 393a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.UserManager; 40ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.system.ErrnoException; 41ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport android.system.Os; 423a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.ArraySet; 43a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport android.util.ExceptionUtils; 443a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.Slog; 453a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.SparseArray; 463a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 473a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.android.internal.annotations.GuardedBy; 48a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter; 493a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.android.server.IoThread; 503a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.google.android.collect.Sets; 513a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 523a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport java.io.File; 53ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport java.io.FilenameFilter; 54ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport java.io.IOException; 55bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport java.util.ArrayList; 56bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkeyimport java.util.List; 573a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 583a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeypublic class PackageInstallerService extends IPackageInstaller.Stub { 593a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private static final String TAG = "PackageInstaller"; 603a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 613a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: destroy sessions with old timestamps 623a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: remove outstanding sessions when installer package goes away 636c833e07a05c48ca60ee4d72421bf8b1e78dc710Jeff Sharkey // TODO: notify listeners in other users when package has been installed there 643a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 653a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final Context mContext; 663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final PackageManagerService mPm; 673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final AppOpsManager mAppOps; 683a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 693a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final File mStagingDir; 70ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey private final HandlerThread mInstallThread; 713a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 723a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final Callback mCallback = new Callback(); 733a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 743a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @GuardedBy("mSessions") 753a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private int mNextSessionId; 763a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @GuardedBy("mSessions") 773a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>(); 783a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 79a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey private RemoteCallbackList<IPackageInstallerObserver> mObservers = new RemoteCallbackList<>(); 80a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 81ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey private static final FilenameFilter sStageFilter = new FilenameFilter() { 82ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey @Override 83ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey public boolean accept(File dir, String name) { 84ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey return name.startsWith("vmdl") && name.endsWith(".tmp"); 85ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 86ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey }; 87ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 883a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public PackageInstallerService(Context context, PackageManagerService pm, File stagingDir) { 893a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mContext = context; 903a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mPm = pm; 913a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 923a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 933a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mStagingDir = stagingDir; 94ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 95ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mInstallThread = new HandlerThread(TAG); 96ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mInstallThread.start(); 973a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 983a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 993a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey readSessionsLocked(); 1003a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1013a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // Clean up orphaned staging directories 102ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final ArraySet<File> stages = Sets.newArraySet(mStagingDir.listFiles(sStageFilter)); 1033a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 104ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 105ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey stages.remove(session.sessionStageDir); 106ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 107ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey for (File stage : stages) { 108ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey Slog.w(TAG, "Deleting orphan stage " + stage); 109ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey if (stage.isDirectory()) { 110ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey FileUtils.deleteContents(stage); 111ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 112ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey stage.delete(); 1133a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 114ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 115ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 116ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 117ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey @Deprecated 118ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey public File allocateSessionDir() throws IOException { 119ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey synchronized (mSessions) { 120ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey try { 121ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final int sessionId = allocateSessionIdLocked(); 122ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey return prepareSessionStageDir(sessionId); 123ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } catch (IllegalStateException e) { 124ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey throw new IOException(e); 1253a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1263a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1273a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1283a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1293a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void readSessionsLocked() { 1303a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: implement persisting 1313a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mSessions.clear(); 1323a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mNextSessionId = 1; 1333a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1343a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1353a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void writeSessionsLocked() { 1363a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: implement persisting 1373a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1383a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1393a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void writeSessionsAsync() { 1403a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey IoThread.getHandler().post(new Runnable() { 1413a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 1423a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public void run() { 1433a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 1443a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey writeSessionsLocked(); 1453a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1463a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1473a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey }); 1483a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1493a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1503a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 151bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey public int createSession(String installerPackageName, InstallSessionParams params, 152ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey int userId) { 1533a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final int callingUid = Binder.getCallingUid(); 154a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mPm.enforceCrossUserPermission(callingUid, userId, true, "createSession"); 1553a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1563a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if (mPm.isUserRestricted(UserHandle.getUserId(callingUid), 1573a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey UserManager.DISALLOW_INSTALL_APPS)) { 1583a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new SecurityException("User restriction prevents installing"); 1593a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1603a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1613a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if ((callingUid == Process.SHELL_UID) || (callingUid == 0)) { 1623a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags |= INSTALL_FROM_ADB; 1633a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } else { 164ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey mAppOps.checkPackage(callingUid, installerPackageName); 165ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 1663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags &= ~INSTALL_FROM_ADB; 1673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags &= ~INSTALL_ALL_USERS; 1683a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags |= INSTALL_REPLACE_EXISTING; 1693a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1703a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1716c833e07a05c48ca60ee4d72421bf8b1e78dc710Jeff Sharkey if (params.mode == InstallSessionParams.MODE_INVALID) { 1726c833e07a05c48ca60ee4d72421bf8b1e78dc710Jeff Sharkey throw new IllegalArgumentException("Params must have valid mode set"); 1736c833e07a05c48ca60ee4d72421bf8b1e78dc710Jeff Sharkey } 1746c833e07a05c48ca60ee4d72421bf8b1e78dc710Jeff Sharkey 175a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey // Sanity check that install could fit 176a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey if (params.deltaSize > 0) { 177a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey try { 178a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mPm.freeStorage(params.deltaSize); 179a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } catch (IOException e) { 180a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey throw ExceptionUtils.wrap(e); 181a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 182a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 183a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 184a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final int sessionId; 185a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final PackageInstallerSession session; 1863a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 187a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey sessionId = allocateSessionIdLocked(); 188a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 1893a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final long createdMillis = System.currentTimeMillis(); 190ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final File sessionStageDir = prepareSessionStageDir(sessionId); 1913a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 192a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey session = new PackageInstallerSession(mCallback, mPm, sessionId, userId, 193a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey installerPackageName, callingUid, params, createdMillis, sessionStageDir, 194a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mInstallThread.getLooper()); 1953a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mSessions.put(sessionId, session); 1963a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 197a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 198a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey notifySessionCreated(session.generateInfo()); 199a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey writeSessionsAsync(); 200a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey return sessionId; 2013a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2023a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 2033a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 2043a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public IPackageInstallerSession openSession(int sessionId) { 2053a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 2063a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 2073a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if (session == null) { 2083a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new IllegalStateException("Missing session " + sessionId); 2093a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2103a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if (Binder.getCallingUid() != session.installerUid) { 2113a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new SecurityException("Caller has no access to session " + sessionId); 2123a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2133a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey return session; 2143a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2153a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2163a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 2173a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private int allocateSessionIdLocked() { 2183a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if (mSessions.get(mNextSessionId) != null) { 2193a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new IllegalStateException("Next session already allocated"); 2203a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2213a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey return mNextSessionId++; 2223a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2233a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 224ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey private File prepareSessionStageDir(int sessionId) { 225ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey final File file = new File(mStagingDir, "vmdl" + sessionId + ".tmp"); 226ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 227ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey if (file.exists()) { 228ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey throw new IllegalStateException(); 229ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 230ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 231ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey try { 232ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey Os.mkdir(file.getAbsolutePath(), 0755); 233ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey Os.chmod(file.getAbsolutePath(), 0755); 234ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } catch (ErrnoException e) { 235ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey // This purposefully throws if directory already exists 236ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey throw new IllegalStateException("Failed to prepare session dir", e); 237ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 238ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 239ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey if (!SELinux.restorecon(file)) { 240ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey throw new IllegalStateException("Failed to prepare session dir"); 241ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 242ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 243ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey return file; 244ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey } 245ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey 2463a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 247bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey public List<InstallSessionInfo> getSessions(int userId) { 248a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getSessions"); 2493a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 250bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey final List<InstallSessionInfo> result = new ArrayList<>(); 2513a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 2523a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 2533a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 254bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey if (session.userId == userId) { 255bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey result.add(session.generateInfo()); 2563a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2573a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2583a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 259bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey return result; 2603a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2613a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 2623a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 263bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey public void uninstall(String packageName, int flags, IPackageDeleteObserver observer, 264ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey int userId) { 265a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "uninstall"); 266bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey mPm.deletePackageAsUser(packageName, observer, userId, flags); 2673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2683a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 2693a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 270ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey public void uninstallSplit(String basePackageName, String overlayName, int flags, 271ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey IPackageDeleteObserver observer, int userId) { 272a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "uninstallSplit"); 273a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 2743a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: flesh out once PM has split support 2753a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new UnsupportedOperationException(); 2763a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2773a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 278bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey @Override 279bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey public void registerObserver(IPackageInstallerObserver observer, int userId) { 280a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "registerObserver"); 281a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 282a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey // TODO: consider restricting to active launcher app only 283a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mObservers.register(observer, new UserHandle(userId)); 284bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey } 285bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey 286bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey @Override 287bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey public void unregisterObserver(IPackageInstallerObserver observer, int userId) { 288a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "unregisterObserver"); 289a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mObservers.unregister(observer); 290a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 291a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 292a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey private int getSessionUserId(int sessionId) { 293a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey synchronized (mSessions) { 294a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey return UserHandle.getUserId(mSessions.get(sessionId).installerUid); 295a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 296a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 297a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 298a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey private void notifySessionCreated(InstallSessionInfo info) { 299a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final int userId = getSessionUserId(info.sessionId); 300a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final int n = mObservers.beginBroadcast(); 301a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey for (int i = 0; i < n; i++) { 302a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final IPackageInstallerObserver observer = mObservers.getBroadcastItem(i); 303a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final UserHandle user = (UserHandle) mObservers.getBroadcastCookie(i); 304a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey if (userId == user.getIdentifier()) { 305a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey try { 306a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey observer.onSessionCreated(info); 307a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } catch (RemoteException ignored) { 308a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 309a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 310a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 311a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mObservers.finishBroadcast(); 312a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 313a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 314a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey private void notifySessionProgress(int sessionId, int progress) { 315a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final int userId = getSessionUserId(sessionId); 316a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final int n = mObservers.beginBroadcast(); 317a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey for (int i = 0; i < n; i++) { 318a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final IPackageInstallerObserver observer = mObservers.getBroadcastItem(i); 319a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final UserHandle user = (UserHandle) mObservers.getBroadcastCookie(i); 320a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey if (userId == user.getIdentifier()) { 321a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey try { 322a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey observer.onSessionProgress(sessionId, progress); 323a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } catch (RemoteException ignored) { 324a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 325a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 326a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 327a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mObservers.finishBroadcast(); 328a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 329a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 330a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey private void notifySessionFinished(int sessionId, boolean success) { 331a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final int userId = getSessionUserId(sessionId); 332a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final int n = mObservers.beginBroadcast(); 333a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey for (int i = 0; i < n; i++) { 334a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final IPackageInstallerObserver observer = mObservers.getBroadcastItem(i); 335a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final UserHandle user = (UserHandle) mObservers.getBroadcastCookie(i); 336a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey if (userId == user.getIdentifier()) { 337a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey try { 338a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey observer.onSessionFinished(sessionId, success); 339a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } catch (RemoteException ignored) { 340a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 341a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 342a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 343a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mObservers.finishBroadcast(); 344a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 345a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey 346a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey void dump(IndentingPrintWriter pw) { 347a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey pw.println("Active install sessions:"); 348a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey pw.increaseIndent(); 349a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey synchronized (mSessions) { 350a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final int N = mSessions.size(); 351a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey for (int i = 0; i < N; i++) { 352a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 353a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey session.dump(pw); 354a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey pw.println(); 355a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 356a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 357a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey pw.println(); 358a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey pw.decreaseIndent(); 359bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey } 360bb580670350b76fa2fcc5ee873f99b7970759cbfJeff Sharkey 3613a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey class Callback { 362a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey public void onSessionProgress(PackageInstallerSession session, int progress) { 363a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey notifySessionProgress(session.sessionId, progress); 3643a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 3653a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 366a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey public void onSessionFinished(PackageInstallerSession session, boolean success) { 367a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey notifySessionFinished(session.sessionId, success); 368a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey synchronized (mSessions) { 369a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey mSessions.remove(session.sessionId); 370a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkey } 3713a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey writeSessionsAsync(); 3723a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 3733a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 3743a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey} 375