PackageInstallerService.java revision 3a44f3f1b446315ef894e01d2ab9b5388c2bd8c4
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; 273a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.pm.IPackageInstallerSession; 283a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.content.pm.PackageInstallerParams; 293a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.Binder; 303a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.FileUtils; 313a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.HandlerThread; 323a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.Process; 333a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.UserHandle; 343a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.os.UserManager; 353a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.ArraySet; 363a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.Slog; 373a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport android.util.SparseArray; 383a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 393a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.android.internal.annotations.GuardedBy; 403a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.android.internal.util.ArrayUtils; 413a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.android.server.IoThread; 423a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport com.google.android.collect.Sets; 433a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 443a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeyimport java.io.File; 453a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 463a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkeypublic class PackageInstallerService extends IPackageInstaller.Stub { 473a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private static final String TAG = "PackageInstaller"; 483a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 493a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: destroy sessions with old timestamps 503a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: remove outstanding sessions when installer package goes away 513a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 523a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final Context mContext; 533a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final PackageManagerService mPm; 543a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final AppOpsManager mAppOps; 553a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 563a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final File mStagingDir; 573a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 583a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final HandlerThread mInstallThread = new HandlerThread(TAG); 593a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final Callback mCallback = new Callback(); 603a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 613a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @GuardedBy("mSessions") 623a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private int mNextSessionId; 633a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @GuardedBy("mSessions") 643a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>(); 653a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public PackageInstallerService(Context context, PackageManagerService pm, File stagingDir) { 673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mContext = context; 683a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mPm = pm; 693a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 703a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 713a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mStagingDir = stagingDir; 723a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mStagingDir.mkdirs(); 733a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 743a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 753a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey readSessionsLocked(); 763a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 773a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // Clean up orphaned staging directories 783a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final ArraySet<String> dirs = Sets.newArraySet(mStagingDir.list()); 793a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 803a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey dirs.remove(Integer.toString(mSessions.keyAt(i))); 813a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 823a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey for (String dirName : dirs) { 833a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey Slog.w(TAG, "Deleting orphan session " + dirName); 843a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final File dir = new File(mStagingDir, dirName); 853a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey FileUtils.deleteContents(dir); 863a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey dir.delete(); 873a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 883a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 893a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 903a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 913a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void readSessionsLocked() { 923a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: implement persisting 933a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mSessions.clear(); 943a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mNextSessionId = 1; 953a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 963a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 973a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void writeSessionsLocked() { 983a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: implement persisting 993a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1003a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1013a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private void writeSessionsAsync() { 1023a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey IoThread.getHandler().post(new Runnable() { 1033a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 1043a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public void run() { 1053a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 1063a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey writeSessionsLocked(); 1073a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1083a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1093a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey }); 1103a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1113a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1123a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 1133a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public int createSession(int userId, String installerPackageName, 1143a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey PackageInstallerParams params) { 1153a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final int callingUid = Binder.getCallingUid(); 1163a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mPm.enforceCrossUserPermission(callingUid, userId, false, TAG); 1173a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mAppOps.checkPackage(callingUid, installerPackageName); 1183a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1193a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if (mPm.isUserRestricted(UserHandle.getUserId(callingUid), 1203a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey UserManager.DISALLOW_INSTALL_APPS)) { 1213a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new SecurityException("User restriction prevents installing"); 1223a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1233a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1243a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if ((callingUid == Process.SHELL_UID) || (callingUid == 0)) { 1253a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags |= INSTALL_FROM_ADB; 1263a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } else { 1273a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags &= ~INSTALL_FROM_ADB; 1283a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags &= ~INSTALL_ALL_USERS; 1293a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey params.installFlags |= INSTALL_REPLACE_EXISTING; 1303a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1313a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1323a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 1333a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final int sessionId = allocateSessionIdLocked(); 1343a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final long createdMillis = System.currentTimeMillis(); 1353a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final File sessionDir = new File(mStagingDir, Integer.toString(sessionId)); 1363a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey sessionDir.mkdirs(); 1373a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1383a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final PackageInstallerSession session = new PackageInstallerSession(mCallback, mPm, 1393a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey sessionId, userId, installerPackageName, callingUid, params, createdMillis, 1403a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey sessionDir, mInstallThread.getLooper()); 1413a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mSessions.put(sessionId, session); 1423a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1433a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey writeSessionsAsync(); 1443a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey return sessionId; 1453a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1463a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1473a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1483a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 1493a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public IPackageInstallerSession openSession(int sessionId) { 1503a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 1513a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final PackageInstallerSession session = mSessions.get(sessionId); 1523a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if (session == null) { 1533a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new IllegalStateException("Missing session " + sessionId); 1543a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1553a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if (Binder.getCallingUid() != session.installerUid) { 1563a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new SecurityException("Caller has no access to session " + sessionId); 1573a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1583a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey return session; 1593a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1603a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1613a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1623a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey private int allocateSessionIdLocked() { 1633a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if (mSessions.get(mNextSessionId) != null) { 1643a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new IllegalStateException("Next session already allocated"); 1653a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1663a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey return mNextSessionId++; 1673a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1683a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1693a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 1703a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public int[] getSessions(int userId, String installerPackageName) { 1713a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final int callingUid = Binder.getCallingUid(); 1723a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mPm.enforceCrossUserPermission(callingUid, userId, false, TAG); 1733a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mAppOps.checkPackage(callingUid, installerPackageName); 1743a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1753a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey int[] matching = new int[0]; 1763a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey synchronized (mSessions) { 1773a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey for (int i = 0; i < mSessions.size(); i++) { 1783a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final int key = mSessions.keyAt(i); 1793a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey final PackageInstallerSession session = mSessions.valueAt(i); 1803a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey if (session.userId == userId 1813a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey && session.installerPackageName.equals(installerPackageName)) { 1823a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey matching = ArrayUtils.appendInt(matching, key); 1833a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1843a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1853a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1863a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey return matching; 1873a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1883a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1893a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 1903a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public void uninstall(int userId, String basePackageName, IPackageDeleteObserver observer) { 1913a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey mPm.deletePackageAsUser(basePackageName, observer, userId, 0); 1923a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 1933a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 1943a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey @Override 1953a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public void uninstallSplit(int userId, String basePackageName, String overlayName, 1963a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey IPackageDeleteObserver observer) { 1973a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: flesh out once PM has split support 1983a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey throw new UnsupportedOperationException(); 1993a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2003a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 2013a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey class Callback { 2023a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public void onProgressChanged(PackageInstallerSession session) { 2033a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey // TODO: notify listeners 2043a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2053a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey 2063a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey public void onSessionInvalid(PackageInstallerSession session) { 2073a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey writeSessionsAsync(); 2083a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2093a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey } 2103a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey} 211