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 17 package com.android.server.pm; 18 19 import android.annotation.Nullable; 20 import android.content.Context; 21 import android.content.pm.PackageStats; 22 import android.os.Build; 23 import android.util.Slog; 24 25 import com.android.internal.os.InstallerConnection; 26 import com.android.internal.os.InstallerConnection.InstallerException; 27 import com.android.server.SystemService; 28 29 import dalvik.system.VMRuntime; 30 31 import java.util.Arrays; 32 33 public final class Installer extends SystemService { 34 private static final String TAG = "Installer"; 35 36 /* *************************************************************************** 37 * IMPORTANT: These values are passed to native code. Keep them in sync with 38 * frameworks/native/cmds/installd/installd.h 39 * **************************************************************************/ 40 /** Application should be visible to everyone */ 41 public static final int DEXOPT_PUBLIC = 1 << 1; 42 /** Application wants to run in VM safe mode */ 43 public static final int DEXOPT_SAFEMODE = 1 << 2; 44 /** Application wants to allow debugging of its code */ 45 public static final int DEXOPT_DEBUGGABLE = 1 << 3; 46 /** The system boot has finished */ 47 public static final int DEXOPT_BOOTCOMPLETE = 1 << 4; 48 /** Hint that the dexopt type is profile-guided. */ 49 public static final int DEXOPT_PROFILE_GUIDED = 1 << 5; 50 /** This is an OTA update dexopt */ 51 public static final int DEXOPT_OTA = 1 << 6; 52 53 // NOTE: keep in sync with installd 54 public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8; 55 public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9; 56 57 private final InstallerConnection mInstaller; 58 Installer(Context context)59 public Installer(Context context) { 60 super(context); 61 mInstaller = new InstallerConnection(); 62 } 63 64 // Package-private installer that accepts a custom InstallerConnection. Used for 65 // OtaDexoptService. Installer(Context context, InstallerConnection connection)66 Installer(Context context, InstallerConnection connection) { 67 super(context); 68 mInstaller = connection; 69 } 70 71 /** 72 * Yell loudly if someone tries making future calls while holding a lock on 73 * the given object. 74 */ setWarnIfHeld(Object warnIfHeld)75 public void setWarnIfHeld(Object warnIfHeld) { 76 mInstaller.setWarnIfHeld(warnIfHeld); 77 } 78 79 @Override onStart()80 public void onStart() { 81 Slog.i(TAG, "Waiting for installd to be ready."); 82 mInstaller.waitForConnection(); 83 } 84 createAppData(String uuid, String pkgname, int userid, int flags, int appid, String seinfo, int targetSdkVersion)85 public void createAppData(String uuid, String pkgname, int userid, int flags, int appid, 86 String seinfo, int targetSdkVersion) throws InstallerException { 87 mInstaller.execute("create_app_data", uuid, pkgname, userid, flags, appid, seinfo, 88 targetSdkVersion); 89 } 90 restoreconAppData(String uuid, String pkgname, int userid, int flags, int appid, String seinfo)91 public void restoreconAppData(String uuid, String pkgname, int userid, int flags, int appid, 92 String seinfo) throws InstallerException { 93 mInstaller.execute("restorecon_app_data", uuid, pkgname, userid, flags, appid, 94 seinfo); 95 } 96 migrateAppData(String uuid, String pkgname, int userid, int flags)97 public void migrateAppData(String uuid, String pkgname, int userid, int flags) 98 throws InstallerException { 99 mInstaller.execute("migrate_app_data", uuid, pkgname, userid, flags); 100 } 101 clearAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode)102 public void clearAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode) 103 throws InstallerException { 104 mInstaller.execute("clear_app_data", uuid, pkgname, userid, flags, ceDataInode); 105 } 106 destroyAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode)107 public void destroyAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode) 108 throws InstallerException { 109 mInstaller.execute("destroy_app_data", uuid, pkgname, userid, flags, ceDataInode); 110 } 111 moveCompleteApp(String from_uuid, String to_uuid, String package_name, String data_app_name, int appid, String seinfo, int targetSdkVersion)112 public void moveCompleteApp(String from_uuid, String to_uuid, String package_name, 113 String data_app_name, int appid, String seinfo, int targetSdkVersion) 114 throws InstallerException { 115 mInstaller.execute("move_complete_app", from_uuid, to_uuid, package_name, 116 data_app_name, appid, seinfo, targetSdkVersion); 117 } 118 getAppSize(String uuid, String pkgname, int userid, int flags, long ceDataInode, String codePath, PackageStats stats)119 public void getAppSize(String uuid, String pkgname, int userid, int flags, long ceDataInode, 120 String codePath, PackageStats stats) throws InstallerException { 121 final String[] res = mInstaller.execute("get_app_size", uuid, pkgname, userid, flags, 122 ceDataInode, codePath); 123 try { 124 stats.codeSize += Long.parseLong(res[1]); 125 stats.dataSize += Long.parseLong(res[2]); 126 stats.cacheSize += Long.parseLong(res[3]); 127 } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) { 128 throw new InstallerException("Invalid size result: " + Arrays.toString(res)); 129 } 130 } 131 getAppDataInode(String uuid, String pkgname, int userid, int flags)132 public long getAppDataInode(String uuid, String pkgname, int userid, int flags) 133 throws InstallerException { 134 final String[] res = mInstaller.execute("get_app_data_inode", uuid, pkgname, userid, flags); 135 try { 136 return Long.parseLong(res[1]); 137 } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) { 138 throw new InstallerException("Invalid inode result: " + Arrays.toString(res)); 139 } 140 } 141 dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded, int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries)142 public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded, 143 int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries) 144 throws InstallerException { 145 assertValidInstructionSet(instructionSet); 146 mInstaller.dexopt(apkPath, uid, instructionSet, dexoptNeeded, dexFlags, 147 compilerFilter, volumeUuid, sharedLibraries); 148 } 149 dexopt(String apkPath, int uid, String pkgName, String instructionSet, int dexoptNeeded, @Nullable String outputPath, int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries)150 public void dexopt(String apkPath, int uid, String pkgName, String instructionSet, 151 int dexoptNeeded, @Nullable String outputPath, int dexFlags, 152 String compilerFilter, String volumeUuid, String sharedLibraries) 153 throws InstallerException { 154 assertValidInstructionSet(instructionSet); 155 mInstaller.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, 156 outputPath, dexFlags, compilerFilter, volumeUuid, sharedLibraries); 157 } 158 mergeProfiles(int uid, String pkgName)159 public boolean mergeProfiles(int uid, String pkgName) throws InstallerException { 160 return mInstaller.mergeProfiles(uid, pkgName); 161 } 162 dumpProfiles(String gid, String packageName, String codePaths)163 public boolean dumpProfiles(String gid, String packageName, String codePaths) 164 throws InstallerException { 165 return mInstaller.dumpProfiles(gid, packageName, codePaths); 166 } 167 idmap(String targetApkPath, String overlayApkPath, int uid)168 public void idmap(String targetApkPath, String overlayApkPath, int uid) 169 throws InstallerException { 170 mInstaller.execute("idmap", targetApkPath, overlayApkPath, uid); 171 } 172 rmdex(String codePath, String instructionSet)173 public void rmdex(String codePath, String instructionSet) throws InstallerException { 174 assertValidInstructionSet(instructionSet); 175 mInstaller.execute("rmdex", codePath, instructionSet); 176 } 177 rmPackageDir(String packageDir)178 public void rmPackageDir(String packageDir) throws InstallerException { 179 mInstaller.execute("rmpackagedir", packageDir); 180 } 181 clearAppProfiles(String pkgName)182 public void clearAppProfiles(String pkgName) throws InstallerException { 183 mInstaller.execute("clear_app_profiles", pkgName); 184 } 185 destroyAppProfiles(String pkgName)186 public void destroyAppProfiles(String pkgName) throws InstallerException { 187 mInstaller.execute("destroy_app_profiles", pkgName); 188 } 189 createUserData(String uuid, int userId, int userSerial, int flags)190 public void createUserData(String uuid, int userId, int userSerial, int flags) 191 throws InstallerException { 192 mInstaller.execute("create_user_data", uuid, userId, userSerial, flags); 193 } 194 destroyUserData(String uuid, int userId, int flags)195 public void destroyUserData(String uuid, int userId, int flags) throws InstallerException { 196 mInstaller.execute("destroy_user_data", uuid, userId, flags); 197 } 198 markBootComplete(String instructionSet)199 public void markBootComplete(String instructionSet) throws InstallerException { 200 assertValidInstructionSet(instructionSet); 201 mInstaller.execute("markbootcomplete", instructionSet); 202 } 203 freeCache(String uuid, long freeStorageSize)204 public void freeCache(String uuid, long freeStorageSize) throws InstallerException { 205 mInstaller.execute("freecache", uuid, freeStorageSize); 206 } 207 208 /** 209 * Links the 32 bit native library directory in an application's data 210 * directory to the real location for backward compatibility. Note that no 211 * such symlink is created for 64 bit shared libraries. 212 */ linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32, int userId)213 public void linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32, 214 int userId) throws InstallerException { 215 mInstaller.execute("linklib", uuid, dataPath, nativeLibPath32, userId); 216 } 217 createOatDir(String oatDir, String dexInstructionSet)218 public void createOatDir(String oatDir, String dexInstructionSet) 219 throws InstallerException { 220 mInstaller.execute("createoatdir", oatDir, dexInstructionSet); 221 } 222 linkFile(String relativePath, String fromBase, String toBase)223 public void linkFile(String relativePath, String fromBase, String toBase) 224 throws InstallerException { 225 mInstaller.execute("linkfile", relativePath, fromBase, toBase); 226 } 227 moveAb(String apkPath, String instructionSet, String outputPath)228 public void moveAb(String apkPath, String instructionSet, String outputPath) 229 throws InstallerException { 230 mInstaller.execute("move_ab", apkPath, instructionSet, outputPath); 231 } 232 assertValidInstructionSet(String instructionSet)233 private static void assertValidInstructionSet(String instructionSet) 234 throws InstallerException { 235 for (String abi : Build.SUPPORTED_ABIS) { 236 if (VMRuntime.getInstructionSet(abi).equals(instructionSet)) { 237 return; 238 } 239 } 240 throw new InstallerException("Invalid instruction set: " + instructionSet); 241 } 242 } 243