Installer.java revision a9aa24974ee4620b42a0573189b68c9af50926c5
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.IntDef;
20import android.annotation.Nullable;
21import android.content.Context;
22import android.content.pm.PackageStats;
23import android.os.Build;
24import android.util.Slog;
25
26import com.android.internal.os.InstallerConnection;
27import com.android.internal.os.InstallerConnection.InstallerException;
28import com.android.server.SystemService;
29
30import dalvik.system.VMRuntime;
31
32import java.lang.annotation.Retention;
33import java.lang.annotation.RetentionPolicy;
34
35public final class Installer extends SystemService {
36    private static final String TAG = "Installer";
37
38    /* ***************************************************************************
39     * IMPORTANT: These values are passed to native code. Keep them in sync with
40     * frameworks/native/cmds/installd/installd.h
41     * **************************************************************************/
42    /** Application should be visible to everyone */
43    public static final int DEXOPT_PUBLIC       = 1 << 1;
44    /** Application wants to run in VM safe mode */
45    public static final int DEXOPT_SAFEMODE     = 1 << 2;
46    /** Application wants to allow debugging of its code */
47    public static final int DEXOPT_DEBUGGABLE   = 1 << 3;
48    /** The system boot has finished */
49    public static final int DEXOPT_BOOTCOMPLETE = 1 << 4;
50    /** Do not compile, only extract bytecode into an OAT file */
51    public static final int DEXOPT_EXTRACTONLY  = 1 << 5;
52
53    /** @hide */
54    @IntDef(flag = true, value = {
55            FLAG_DE_STORAGE,
56            FLAG_CE_STORAGE,
57    })
58    @Retention(RetentionPolicy.SOURCE)
59    public @interface StorageFlags {}
60
61    public static final int FLAG_DE_STORAGE = 1 << 0;
62    public static final int FLAG_CE_STORAGE = 1 << 1;
63
64    public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 2;
65    public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 3;
66
67    private final InstallerConnection mInstaller;
68
69    public Installer(Context context) {
70        super(context);
71        mInstaller = new InstallerConnection();
72    }
73
74    /**
75     * Yell loudly if someone tries making future calls while holding a lock on
76     * the given object.
77     */
78    public void setWarnIfHeld(Object warnIfHeld) {
79        mInstaller.setWarnIfHeld(warnIfHeld);
80    }
81
82    @Override
83    public void onStart() {
84        Slog.i(TAG, "Waiting for installd to be ready.");
85        mInstaller.waitForConnection();
86    }
87
88    public void createAppData(String uuid, String pkgname, int userid, int flags, int appid,
89            String seinfo, int targetSdkVersion) throws InstallerException {
90        mInstaller.execute("create_app_data", uuid, pkgname, userid, flags, appid, seinfo,
91            targetSdkVersion);
92    }
93
94    public void restoreconAppData(String uuid, String pkgname, int userid, int flags, int appid,
95            String seinfo) throws InstallerException {
96        mInstaller.execute("restorecon_app_data", uuid, pkgname, userid, flags, appid,
97                seinfo);
98    }
99
100    public void clearAppData(String uuid, String pkgname, int userid, int flags)
101            throws InstallerException {
102        mInstaller.execute("clear_app_data", uuid, pkgname, userid, flags);
103    }
104
105    public void destroyAppData(String uuid, String pkgname, int userid, int flags)
106            throws InstallerException {
107        mInstaller.execute("destroy_app_data", uuid, pkgname, userid, flags);
108    }
109
110    public void moveCompleteApp(String from_uuid, String to_uuid, String package_name,
111            String data_app_name, int appid, String seinfo, int targetSdkVersion)
112            throws InstallerException {
113        mInstaller.execute("move_complete_app", from_uuid, to_uuid, package_name,
114                data_app_name, appid, seinfo, targetSdkVersion);
115    }
116
117    public void getAppSize(String uuid, String pkgname, int userid, int flags, String apkPath,
118            String libDirPath, String fwdLockApkPath, String asecPath, String[] instructionSets,
119            PackageStats pStats) throws InstallerException {
120        for (String instructionSet : instructionSets) {
121            assertValidInstructionSet(instructionSet);
122        }
123
124        // TODO: Extend getSizeInfo to look at the full subdirectory tree,
125        // not just the first level.
126        // TODO: Extend getSizeInfo to look at *all* instrution sets, not
127        // just the primary.
128        final String rawRes = mInstaller.executeForResult("get_app_size", uuid, pkgname, userid,
129                flags, apkPath, libDirPath, fwdLockApkPath, asecPath, instructionSets[0]);
130        final String res[] = rawRes.split(" ");
131
132        if ((res == null) || (res.length != 5)) {
133            throw new InstallerException("Invalid size result: " + rawRes);
134        }
135        try {
136            pStats.codeSize = Long.parseLong(res[1]);
137            pStats.dataSize = Long.parseLong(res[2]);
138            pStats.cacheSize = Long.parseLong(res[3]);
139            pStats.externalCodeSize = Long.parseLong(res[4]);
140        } catch (NumberFormatException e) {
141            throw new InstallerException("Invalid size result: " + rawRes);
142        }
143    }
144
145    public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
146            int dexFlags, String volumeUuid, boolean useProfiles) throws InstallerException {
147        assertValidInstructionSet(instructionSet);
148        mInstaller.dexopt(apkPath, uid, instructionSet, dexoptNeeded, dexFlags,
149                volumeUuid, useProfiles);
150    }
151
152    public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
153            int dexoptNeeded, @Nullable String outputPath, int dexFlags,
154            String volumeUuid, boolean useProfiles)
155                    throws InstallerException {
156        assertValidInstructionSet(instructionSet);
157        mInstaller.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded,
158                outputPath, dexFlags, volumeUuid, useProfiles);
159    }
160
161    public void idmap(String targetApkPath, String overlayApkPath, int uid)
162            throws InstallerException {
163        mInstaller.execute("idmap", targetApkPath, overlayApkPath, uid);
164    }
165
166    public void rmdex(String codePath, String instructionSet) throws InstallerException {
167        assertValidInstructionSet(instructionSet);
168        mInstaller.execute("rmdex", codePath, instructionSet);
169    }
170
171    public void rmPackageDir(String packageDir) throws InstallerException {
172        mInstaller.execute("rmpackagedir", packageDir);
173    }
174
175    public void createUserConfig(int userid) throws InstallerException {
176        mInstaller.execute("mkuserconfig", userid);
177    }
178
179    public void removeUserDataDirs(String uuid, int userid) throws InstallerException {
180        mInstaller.execute("rmuser", uuid, userid);
181    }
182
183    public void markBootComplete(String instructionSet) throws InstallerException {
184        assertValidInstructionSet(instructionSet);
185        mInstaller.execute("markbootcomplete", instructionSet);
186    }
187
188    public void freeCache(String uuid, long freeStorageSize) throws InstallerException {
189        mInstaller.execute("freecache", uuid, freeStorageSize);
190    }
191
192    /**
193     * Links the 32 bit native library directory in an application's data
194     * directory to the real location for backward compatibility. Note that no
195     * such symlink is created for 64 bit shared libraries.
196     */
197    public void linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32,
198            int userId) throws InstallerException {
199        mInstaller.execute("linklib", uuid, dataPath, nativeLibPath32, userId);
200    }
201
202    public void createOatDir(String oatDir, String dexInstructionSet)
203            throws InstallerException {
204        mInstaller.execute("createoatdir", oatDir, dexInstructionSet);
205    }
206
207    public void linkFile(String relativePath, String fromBase, String toBase)
208            throws InstallerException {
209        mInstaller.execute("linkfile", relativePath, fromBase, toBase);
210    }
211
212    private static void assertValidInstructionSet(String instructionSet)
213            throws InstallerException {
214        for (String abi : Build.SUPPORTED_ABIS) {
215            if (VMRuntime.getInstructionSet(abi).equals(instructionSet)) {
216                return;
217            }
218        }
219        throw new InstallerException("Invalid instruction set: " + instructionSet);
220    }
221}
222