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