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