Installer.java revision c24fa029bf9a2ee3c3657cb598e1595262ad2eeb
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.pm; 18 19import android.annotation.Nullable; 20import android.content.Context; 21import android.content.pm.PackageStats; 22import android.os.Build; 23import android.os.IInstalld; 24import android.os.RemoteException; 25import android.os.ServiceManager; 26import android.os.ServiceSpecificException; 27import android.util.Slog; 28 29import com.android.internal.os.InstallerConnection; 30import com.android.internal.os.InstallerConnection.InstallerException; 31import com.android.server.SystemService; 32 33import dalvik.system.VMRuntime; 34 35import java.util.Arrays; 36 37public final class Installer extends SystemService { 38 private static final String TAG = "Installer"; 39 40 /* *************************************************************************** 41 * IMPORTANT: These values are passed to native code. Keep them in sync with 42 * frameworks/native/cmds/installd/installd.h 43 * **************************************************************************/ 44 /** Application should be visible to everyone */ 45 public static final int DEXOPT_PUBLIC = 1 << 1; 46 /** Application wants to run in VM safe mode */ 47 public static final int DEXOPT_SAFEMODE = 1 << 2; 48 /** Application wants to allow debugging of its code */ 49 public static final int DEXOPT_DEBUGGABLE = 1 << 3; 50 /** The system boot has finished */ 51 public static final int DEXOPT_BOOTCOMPLETE = 1 << 4; 52 /** Hint that the dexopt type is profile-guided. */ 53 public static final int DEXOPT_PROFILE_GUIDED = 1 << 5; 54 /** This is an OTA update dexopt */ 55 public static final int DEXOPT_OTA = 1 << 6; 56 57 // NOTE: keep in sync with installd 58 public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8; 59 public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9; 60 61 private final InstallerConnection mInstaller; 62 private final IInstalld mInstalld; 63 64 private volatile Object mWarnIfHeld; 65 66 public Installer(Context context) { 67 super(context); 68 mInstaller = new InstallerConnection(); 69 // TODO: reconnect if installd restarts 70 mInstalld = IInstalld.Stub.asInterface(ServiceManager.getService("installd")); 71 } 72 73 // Package-private installer that accepts a custom InstallerConnection. Used for 74 // OtaDexoptService. 75 Installer(Context context, InstallerConnection connection) { 76 super(context); 77 mInstaller = connection; 78 // TODO: reconnect if installd restarts 79 mInstalld = IInstalld.Stub.asInterface(ServiceManager.getService("installd")); 80 } 81 82 /** 83 * Yell loudly if someone tries making future calls while holding a lock on 84 * the given object. 85 */ 86 public void setWarnIfHeld(Object warnIfHeld) { 87 mInstaller.setWarnIfHeld(warnIfHeld); 88 mWarnIfHeld = warnIfHeld; 89 } 90 91 @Override 92 public void onStart() { 93 Slog.i(TAG, "Waiting for installd to be ready."); 94 mInstaller.waitForConnection(); 95 } 96 97 private void checkLock() { 98 if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) { 99 Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x" 100 + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable()); 101 } 102 } 103 104 public void createAppData(String uuid, String packageName, int userId, int flags, int appId, 105 String seInfo, int targetSdkVersion) throws InstallerException { 106 checkLock(); 107 try { 108 mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo, 109 targetSdkVersion); 110 } catch (RemoteException | ServiceSpecificException e) { 111 throw new InstallerException(e.getMessage()); 112 } 113 } 114 115 public void restoreconAppData(String uuid, String pkgname, int userid, int flags, int appid, 116 String seinfo) throws InstallerException { 117 mInstaller.execute("restorecon_app_data", uuid, pkgname, userid, flags, appid, 118 seinfo); 119 } 120 121 public void migrateAppData(String uuid, String pkgname, int userid, int flags) 122 throws InstallerException { 123 mInstaller.execute("migrate_app_data", uuid, pkgname, userid, flags); 124 } 125 126 public void clearAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode) 127 throws InstallerException { 128 mInstaller.execute("clear_app_data", uuid, pkgname, userid, flags, ceDataInode); 129 } 130 131 public void destroyAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode) 132 throws InstallerException { 133 mInstaller.execute("destroy_app_data", uuid, pkgname, userid, flags, ceDataInode); 134 } 135 136 public void moveCompleteApp(String fromUuid, String toUuid, String packageName, 137 String dataAppName, int appId, String seInfo, int targetSdkVersion) 138 throws InstallerException { 139 checkLock(); 140 try { 141 mInstalld.moveCompleteApp(fromUuid, toUuid, packageName, dataAppName, appId, seInfo, 142 targetSdkVersion); 143 } catch (RemoteException | ServiceSpecificException e) { 144 throw new InstallerException(e.getMessage()); 145 } 146 } 147 148 public void getAppSize(String uuid, String pkgname, int userid, int flags, long ceDataInode, 149 String codePath, PackageStats stats) throws InstallerException { 150 final String[] res = mInstaller.execute("get_app_size", uuid, pkgname, userid, flags, 151 ceDataInode, codePath); 152 try { 153 stats.codeSize += Long.parseLong(res[1]); 154 stats.dataSize += Long.parseLong(res[2]); 155 stats.cacheSize += Long.parseLong(res[3]); 156 } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) { 157 throw new InstallerException("Invalid size result: " + Arrays.toString(res)); 158 } 159 } 160 161 public long getAppDataInode(String uuid, String pkgname, int userid, int flags) 162 throws InstallerException { 163 final String[] res = mInstaller.execute("get_app_data_inode", uuid, pkgname, userid, flags); 164 try { 165 return Long.parseLong(res[1]); 166 } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) { 167 throw new InstallerException("Invalid inode result: " + Arrays.toString(res)); 168 } 169 } 170 171 public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded, 172 int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries) 173 throws InstallerException { 174 assertValidInstructionSet(instructionSet); 175 mInstaller.dexopt(apkPath, uid, instructionSet, dexoptNeeded, dexFlags, 176 compilerFilter, volumeUuid, sharedLibraries); 177 } 178 179 public void dexopt(String apkPath, int uid, String pkgName, String instructionSet, 180 int dexoptNeeded, @Nullable String outputPath, int dexFlags, 181 String compilerFilter, String volumeUuid, String sharedLibraries) 182 throws InstallerException { 183 assertValidInstructionSet(instructionSet); 184 mInstaller.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, 185 outputPath, dexFlags, compilerFilter, volumeUuid, sharedLibraries); 186 } 187 188 public boolean mergeProfiles(int uid, String packageName) throws InstallerException { 189 checkLock(); 190 try { 191 return mInstalld.mergeProfiles(uid, packageName); 192 } catch (RemoteException | ServiceSpecificException e) { 193 throw new InstallerException(e.getMessage()); 194 } 195 } 196 197 public boolean dumpProfiles(int uid, String packageName, String codePaths) 198 throws InstallerException { 199 checkLock(); 200 try { 201 return mInstalld.dumpProfiles(uid, packageName, codePaths); 202 } catch (RemoteException | ServiceSpecificException e) { 203 throw new InstallerException(e.getMessage()); 204 } 205 } 206 207 public void idmap(String targetApkPath, String overlayApkPath, int uid) 208 throws InstallerException { 209 checkLock(); 210 try { 211 mInstalld.idmap(targetApkPath, overlayApkPath, uid); 212 } catch (RemoteException | ServiceSpecificException e) { 213 throw new InstallerException(e.getMessage()); 214 } 215 } 216 217 public void rmdex(String codePath, String instructionSet) throws InstallerException { 218 assertValidInstructionSet(instructionSet); 219 checkLock(); 220 try { 221 mInstalld.rmdex(codePath, instructionSet); 222 } catch (RemoteException | ServiceSpecificException e) { 223 throw new InstallerException(e.getMessage()); 224 } 225 } 226 227 public void rmPackageDir(String packageDir) throws InstallerException { 228 checkLock(); 229 try { 230 mInstalld.rmPackageDir(packageDir); 231 } catch (RemoteException | ServiceSpecificException e) { 232 throw new InstallerException(e.getMessage()); 233 } 234 } 235 236 public void clearAppProfiles(String packageName) throws InstallerException { 237 checkLock(); 238 try { 239 mInstalld.clearAppProfiles(packageName); 240 } catch (RemoteException | ServiceSpecificException e) { 241 throw new InstallerException(e.getMessage()); 242 } 243 } 244 245 public void destroyAppProfiles(String packageName) throws InstallerException { 246 checkLock(); 247 try { 248 mInstalld.destroyAppProfiles(packageName); 249 } catch (RemoteException | ServiceSpecificException e) { 250 throw new InstallerException(e.getMessage()); 251 } 252 } 253 254 public void createUserData(String uuid, int userId, int userSerial, int flags) 255 throws InstallerException { 256 mInstaller.execute("create_user_data", uuid, userId, userSerial, flags); 257 } 258 259 public void destroyUserData(String uuid, int userId, int flags) throws InstallerException { 260 mInstaller.execute("destroy_user_data", uuid, userId, flags); 261 } 262 263 public void markBootComplete(String instructionSet) throws InstallerException { 264 assertValidInstructionSet(instructionSet); 265 checkLock(); 266 try { 267 mInstalld.markBootComplete(instructionSet); 268 } catch (RemoteException | ServiceSpecificException e) { 269 throw new InstallerException(e.getMessage()); 270 } 271 } 272 273 public void freeCache(String uuid, long freeStorageSize) throws InstallerException { 274 checkLock(); 275 try { 276 mInstalld.freeCache(uuid, freeStorageSize); 277 } catch (RemoteException | ServiceSpecificException e) { 278 throw new InstallerException(e.getMessage()); 279 } 280 } 281 282 /** 283 * Links the 32 bit native library directory in an application's data 284 * directory to the real location for backward compatibility. Note that no 285 * such symlink is created for 64 bit shared libraries. 286 */ 287 public void linkNativeLibraryDirectory(String uuid, String packageName, String nativeLibPath32, 288 int userId) throws InstallerException { 289 checkLock(); 290 try { 291 mInstalld.linkNativeLibraryDirectory(uuid, packageName, nativeLibPath32, userId); 292 } catch (RemoteException | ServiceSpecificException e) { 293 throw new InstallerException(e.getMessage()); 294 } 295 } 296 297 public void createOatDir(String oatDir, String dexInstructionSet) 298 throws InstallerException { 299 checkLock(); 300 try { 301 mInstalld.createOatDir(oatDir, dexInstructionSet); 302 } catch (RemoteException | ServiceSpecificException e) { 303 throw new InstallerException(e.getMessage()); 304 } 305 } 306 307 public void linkFile(String relativePath, String fromBase, String toBase) 308 throws InstallerException { 309 checkLock(); 310 try { 311 mInstalld.linkFile(relativePath, fromBase, toBase); 312 } catch (RemoteException | ServiceSpecificException e) { 313 throw new InstallerException(e.getMessage()); 314 } 315 } 316 317 public void moveAb(String apkPath, String instructionSet, String outputPath) 318 throws InstallerException { 319 checkLock(); 320 try { 321 mInstalld.moveAb(apkPath, instructionSet, outputPath); 322 } catch (RemoteException | ServiceSpecificException e) { 323 throw new InstallerException(e.getMessage()); 324 } 325 } 326 327 public void deleteOdex(String apkPath, String instructionSet, String outputPath) 328 throws InstallerException { 329 checkLock(); 330 try { 331 mInstalld.deleteOdex(apkPath, instructionSet, outputPath); 332 } catch (RemoteException | ServiceSpecificException e) { 333 throw new InstallerException(e.getMessage()); 334 } 335 } 336 337 private static void assertValidInstructionSet(String instructionSet) 338 throws InstallerException { 339 for (String abi : Build.SUPPORTED_ABIS) { 340 if (VMRuntime.getInstructionSet(abi).equals(instructionSet)) { 341 return; 342 } 343 } 344 throw new InstallerException("Invalid instruction set: " + instructionSet); 345 } 346} 347