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