Installer.java revision 7b08b35bde3df58816b171b88712bcc6d21dcbe8
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.util.Slog; 24import dalvik.system.VMRuntime; 25 26import com.android.internal.os.InstallerConnection; 27import com.android.server.SystemService; 28 29public final class Installer extends SystemService { 30 private static final String TAG = "Installer"; 31 32 private final InstallerConnection mInstaller; 33 34 public Installer(Context context) { 35 super(context); 36 mInstaller = new InstallerConnection(); 37 } 38 39 @Override 40 public void onStart() { 41 Slog.i(TAG, "Waiting for installd to be ready."); 42 ping(); 43 } 44 45 public int install(String name, int uid, int gid, String seinfo) { 46 StringBuilder builder = new StringBuilder("install"); 47 builder.append(' '); 48 builder.append(name); 49 builder.append(' '); 50 builder.append(uid); 51 builder.append(' '); 52 builder.append(gid); 53 builder.append(' '); 54 builder.append(seinfo != null ? seinfo : "!"); 55 return mInstaller.execute(builder.toString()); 56 } 57 58 public int dexopt(String apkPath, int uid, boolean isPublic, 59 String instructionSet, int dexoptNeeded) { 60 if (!isValidInstructionSet(instructionSet)) { 61 Slog.e(TAG, "Invalid instruction set: " + instructionSet); 62 return -1; 63 } 64 65 return mInstaller.dexopt(apkPath, uid, isPublic, instructionSet, dexoptNeeded); 66 } 67 68 public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName, 69 String instructionSet, int dexoptNeeded, boolean vmSafeMode, 70 boolean debuggable, @Nullable String outputPath) { 71 if (!isValidInstructionSet(instructionSet)) { 72 Slog.e(TAG, "Invalid instruction set: " + instructionSet); 73 return -1; 74 } 75 return mInstaller.dexopt(apkPath, uid, isPublic, pkgName, 76 instructionSet, dexoptNeeded, vmSafeMode, 77 debuggable, outputPath); 78 } 79 80 public int idmap(String targetApkPath, String overlayApkPath, int uid) { 81 StringBuilder builder = new StringBuilder("idmap"); 82 builder.append(' '); 83 builder.append(targetApkPath); 84 builder.append(' '); 85 builder.append(overlayApkPath); 86 builder.append(' '); 87 builder.append(uid); 88 return mInstaller.execute(builder.toString()); 89 } 90 91 public int movedex(String srcPath, String dstPath, String instructionSet) { 92 if (!isValidInstructionSet(instructionSet)) { 93 Slog.e(TAG, "Invalid instruction set: " + instructionSet); 94 return -1; 95 } 96 97 StringBuilder builder = new StringBuilder("movedex"); 98 builder.append(' '); 99 builder.append(srcPath); 100 builder.append(' '); 101 builder.append(dstPath); 102 builder.append(' '); 103 builder.append(instructionSet); 104 return mInstaller.execute(builder.toString()); 105 } 106 107 public int rmdex(String codePath, String instructionSet) { 108 if (!isValidInstructionSet(instructionSet)) { 109 Slog.e(TAG, "Invalid instruction set: " + instructionSet); 110 return -1; 111 } 112 113 StringBuilder builder = new StringBuilder("rmdex"); 114 builder.append(' '); 115 builder.append(codePath); 116 builder.append(' '); 117 builder.append(instructionSet); 118 return mInstaller.execute(builder.toString()); 119 } 120 121 /** 122 * Removes packageDir or its subdirectory 123 */ 124 public int rmPackageDir(String packageDir) { 125 StringBuilder builder = new StringBuilder("rmpackagedir"); 126 builder.append(' '); 127 builder.append(packageDir); 128 return mInstaller.execute(builder.toString()); 129 } 130 131 public int remove(String name, int userId) { 132 StringBuilder builder = new StringBuilder("remove"); 133 builder.append(' '); 134 builder.append(name); 135 builder.append(' '); 136 builder.append(userId); 137 return mInstaller.execute(builder.toString()); 138 } 139 140 public int rename(String oldname, String newname) { 141 StringBuilder builder = new StringBuilder("rename"); 142 builder.append(' '); 143 builder.append(oldname); 144 builder.append(' '); 145 builder.append(newname); 146 return mInstaller.execute(builder.toString()); 147 } 148 149 public int fixUid(String name, int uid, int gid) { 150 StringBuilder builder = new StringBuilder("fixuid"); 151 builder.append(' '); 152 builder.append(name); 153 builder.append(' '); 154 builder.append(uid); 155 builder.append(' '); 156 builder.append(gid); 157 return mInstaller.execute(builder.toString()); 158 } 159 160 public int deleteCacheFiles(String name, int userId) { 161 StringBuilder builder = new StringBuilder("rmcache"); 162 builder.append(' '); 163 builder.append(name); 164 builder.append(' '); 165 builder.append(userId); 166 return mInstaller.execute(builder.toString()); 167 } 168 169 public int deleteCodeCacheFiles(String name, int userId) { 170 StringBuilder builder = new StringBuilder("rmcodecache"); 171 builder.append(' '); 172 builder.append(name); 173 builder.append(' '); 174 builder.append(userId); 175 return mInstaller.execute(builder.toString()); 176 } 177 178 public int createUserData(String name, int uid, int userId, String seinfo) { 179 StringBuilder builder = new StringBuilder("mkuserdata"); 180 builder.append(' '); 181 builder.append(name); 182 builder.append(' '); 183 builder.append(uid); 184 builder.append(' '); 185 builder.append(userId); 186 builder.append(' '); 187 builder.append(seinfo != null ? seinfo : "!"); 188 return mInstaller.execute(builder.toString()); 189 } 190 191 public int createUserConfig(int userId) { 192 StringBuilder builder = new StringBuilder("mkuserconfig"); 193 builder.append(' '); 194 builder.append(userId); 195 return mInstaller.execute(builder.toString()); 196 } 197 198 public int removeUserDataDirs(int userId) { 199 StringBuilder builder = new StringBuilder("rmuser"); 200 builder.append(' '); 201 builder.append(userId); 202 return mInstaller.execute(builder.toString()); 203 } 204 205 public int clearUserData(String name, int userId) { 206 StringBuilder builder = new StringBuilder("rmuserdata"); 207 builder.append(' '); 208 builder.append(name); 209 builder.append(' '); 210 builder.append(userId); 211 return mInstaller.execute(builder.toString()); 212 } 213 214 public int markBootComplete(String instructionSet) { 215 if (!isValidInstructionSet(instructionSet)) { 216 Slog.e(TAG, "Invalid instruction set: " + instructionSet); 217 return -1; 218 } 219 220 StringBuilder builder = new StringBuilder("markbootcomplete"); 221 builder.append(' '); 222 builder.append(instructionSet); 223 return mInstaller.execute(builder.toString()); 224 } 225 226 public boolean ping() { 227 if (mInstaller.execute("ping") < 0) { 228 return false; 229 } else { 230 return true; 231 } 232 } 233 234 public int freeCache(long freeStorageSize) { 235 StringBuilder builder = new StringBuilder("freecache"); 236 builder.append(' '); 237 builder.append(String.valueOf(freeStorageSize)); 238 return mInstaller.execute(builder.toString()); 239 } 240 241 public int getSizeInfo(String pkgName, int persona, String apkPath, String libDirPath, 242 String fwdLockApkPath, String asecPath, String[] instructionSets, PackageStats pStats) { 243 for (String instructionSet : instructionSets) { 244 if (!isValidInstructionSet(instructionSet)) { 245 Slog.e(TAG, "Invalid instruction set: " + instructionSet); 246 return -1; 247 } 248 } 249 250 StringBuilder builder = new StringBuilder("getsize"); 251 builder.append(' '); 252 builder.append(pkgName); 253 builder.append(' '); 254 builder.append(persona); 255 builder.append(' '); 256 builder.append(apkPath); 257 builder.append(' '); 258 // TODO: Extend getSizeInfo to look at the full subdirectory tree, 259 // not just the first level. 260 builder.append(libDirPath != null ? libDirPath : "!"); 261 builder.append(' '); 262 builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!"); 263 builder.append(' '); 264 builder.append(asecPath != null ? asecPath : "!"); 265 builder.append(' '); 266 // TODO: Extend getSizeInfo to look at *all* instrution sets, not 267 // just the primary. 268 builder.append(instructionSets[0]); 269 270 String s = mInstaller.transact(builder.toString()); 271 String res[] = s.split(" "); 272 273 if ((res == null) || (res.length != 5)) { 274 return -1; 275 } 276 try { 277 pStats.codeSize = Long.parseLong(res[1]); 278 pStats.dataSize = Long.parseLong(res[2]); 279 pStats.cacheSize = Long.parseLong(res[3]); 280 pStats.externalCodeSize = Long.parseLong(res[4]); 281 return Integer.parseInt(res[0]); 282 } catch (NumberFormatException e) { 283 return -1; 284 } 285 } 286 287 public int moveFiles() { 288 return mInstaller.execute("movefiles"); 289 } 290 291 /** 292 * Links the 32 bit native library directory in an application's data directory to the 293 * real location for backward compatibility. Note that no such symlink is created for 294 * 64 bit shared libraries. 295 * 296 * @return -1 on error 297 */ 298 public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath32, int userId) { 299 if (dataPath == null) { 300 Slog.e(TAG, "linkNativeLibraryDirectory dataPath is null"); 301 return -1; 302 } else if (nativeLibPath32 == null) { 303 Slog.e(TAG, "linkNativeLibraryDirectory nativeLibPath is null"); 304 return -1; 305 } 306 307 StringBuilder builder = new StringBuilder("linklib "); 308 builder.append(dataPath); 309 builder.append(' '); 310 builder.append(nativeLibPath32); 311 builder.append(' '); 312 builder.append(userId); 313 314 return mInstaller.execute(builder.toString()); 315 } 316 317 public boolean restoreconData(String pkgName, String seinfo, int uid) { 318 StringBuilder builder = new StringBuilder("restorecondata"); 319 builder.append(' '); 320 builder.append(pkgName); 321 builder.append(' '); 322 builder.append(seinfo != null ? seinfo : "!"); 323 builder.append(' '); 324 builder.append(uid); 325 return (mInstaller.execute(builder.toString()) == 0); 326 } 327 328 public int createOatDir(String oatDir, String dexInstructionSet) { 329 StringBuilder builder = new StringBuilder("createoatdir"); 330 builder.append(' '); 331 builder.append(oatDir); 332 builder.append(' '); 333 builder.append(dexInstructionSet); 334 return mInstaller.execute(builder.toString()); 335 } 336 337 /** 338 * Returns true iff. {@code instructionSet} is a valid instruction set. 339 */ 340 private static boolean isValidInstructionSet(String instructionSet) { 341 if (instructionSet == null) { 342 return false; 343 } 344 345 for (String abi : Build.SUPPORTED_ABIS) { 346 if (instructionSet.equals(VMRuntime.getInstructionSet(abi))) { 347 return true; 348 } 349 } 350 351 return false; 352 } 353} 354