Installer.java revision c8ddc2d56ee8beab6534853007d7c05dea7f62da
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 pkgName) throws InstallerException { 189 return mInstaller.mergeProfiles(uid, pkgName); 190 } 191 192 public boolean dumpProfiles(String gid, String packageName, String codePaths) 193 throws InstallerException { 194 return mInstaller.dumpProfiles(gid, packageName, codePaths); 195 } 196 197 public void idmap(String targetApkPath, String overlayApkPath, int uid) 198 throws InstallerException { 199 mInstaller.execute("idmap", targetApkPath, overlayApkPath, uid); 200 } 201 202 public void rmdex(String codePath, String instructionSet) throws InstallerException { 203 assertValidInstructionSet(instructionSet); 204 mInstaller.execute("rmdex", codePath, instructionSet); 205 } 206 207 public void rmPackageDir(String packageDir) throws InstallerException { 208 mInstaller.execute("rmpackagedir", packageDir); 209 } 210 211 public void clearAppProfiles(String pkgName) throws InstallerException { 212 mInstaller.execute("clear_app_profiles", pkgName); 213 } 214 215 public void destroyAppProfiles(String pkgName) throws InstallerException { 216 mInstaller.execute("destroy_app_profiles", pkgName); 217 } 218 219 public void createUserData(String uuid, int userId, int userSerial, int flags) 220 throws InstallerException { 221 mInstaller.execute("create_user_data", uuid, userId, userSerial, flags); 222 } 223 224 public void destroyUserData(String uuid, int userId, int flags) throws InstallerException { 225 mInstaller.execute("destroy_user_data", uuid, userId, flags); 226 } 227 228 public void markBootComplete(String instructionSet) throws InstallerException { 229 assertValidInstructionSet(instructionSet); 230 mInstaller.execute("markbootcomplete", instructionSet); 231 } 232 233 public void freeCache(String uuid, long freeStorageSize) throws InstallerException { 234 mInstaller.execute("freecache", uuid, freeStorageSize); 235 } 236 237 /** 238 * Links the 32 bit native library directory in an application's data 239 * directory to the real location for backward compatibility. Note that no 240 * such symlink is created for 64 bit shared libraries. 241 */ 242 public void linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32, 243 int userId) throws InstallerException { 244 mInstaller.execute("linklib", uuid, dataPath, nativeLibPath32, userId); 245 } 246 247 public void createOatDir(String oatDir, String dexInstructionSet) 248 throws InstallerException { 249 mInstaller.execute("createoatdir", oatDir, dexInstructionSet); 250 } 251 252 public void linkFile(String relativePath, String fromBase, String toBase) 253 throws InstallerException { 254 mInstaller.execute("linkfile", relativePath, fromBase, toBase); 255 } 256 257 public void moveAb(String apkPath, String instructionSet, String outputPath) 258 throws InstallerException { 259 mInstaller.execute("move_ab", apkPath, instructionSet, outputPath); 260 } 261 262 public void deleteOdex(String apkPath, String instructionSet, String outputPath) 263 throws InstallerException { 264 mInstaller.execute("delete_odex", apkPath, instructionSet, outputPath); 265 } 266 267 private static void assertValidInstructionSet(String instructionSet) 268 throws InstallerException { 269 for (String abi : Build.SUPPORTED_ABIS) { 270 if (VMRuntime.getInstructionSet(abi).equals(instructionSet)) { 271 return; 272 } 273 } 274 throw new InstallerException("Invalid instruction set: " + instructionSet); 275 } 276} 277