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