1/*
2 * Copyright (C) 2011 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 static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
20import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
21import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
22
23import android.content.pm.ApplicationInfo;
24import android.content.pm.PackageUserState;
25import android.content.pm.UserInfo;
26import android.util.SparseArray;
27
28import java.io.File;
29import java.util.HashSet;
30import java.util.List;
31
32/**
33 * Settings base class for pending and resolved classes.
34 */
35class PackageSettingBase extends GrantedPermissions {
36    /**
37     * Indicates the state of installation. Used by PackageManager to figure out
38     * incomplete installations. Say a package is being installed (the state is
39     * set to PKG_INSTALL_INCOMPLETE) and remains so till the package
40     * installation is successful or unsuccessful in which case the
41     * PackageManager will no longer maintain state information associated with
42     * the package. If some exception(like device freeze or battery being pulled
43     * out) occurs during installation of a package, the PackageManager needs
44     * this information to clean up the previously failed installation.
45     */
46    static final int PKG_INSTALL_COMPLETE = 1;
47    static final int PKG_INSTALL_INCOMPLETE = 0;
48
49    final String name;
50    final String realName;
51    File codePath;
52    String codePathString;
53    File resourcePath;
54    String resourcePathString;
55    String nativeLibraryPathString;
56    long timeStamp;
57    long firstInstallTime;
58    long lastUpdateTime;
59    int versionCode;
60
61    boolean uidError;
62
63    PackageSignatures signatures = new PackageSignatures();
64
65    boolean permissionsFixed;
66    boolean haveGids;
67
68    private static final PackageUserState DEFAULT_USER_STATE = new PackageUserState();
69
70    // Whether this package is currently stopped, thus can not be
71    // started until explicitly launched by the user.
72    private final SparseArray<PackageUserState> userState = new SparseArray<PackageUserState>();
73
74    int installStatus = PKG_INSTALL_COMPLETE;
75
76    PackageSettingBase origPackage;
77
78    /* package name of the app that installed this package */
79    String installerPackageName;
80    PackageSettingBase(String name, String realName, File codePath, File resourcePath,
81            String nativeLibraryPathString, int pVersionCode, int pkgFlags) {
82        super(pkgFlags);
83        this.name = name;
84        this.realName = realName;
85        init(codePath, resourcePath, nativeLibraryPathString, pVersionCode);
86    }
87
88    /**
89     * New instance of PackageSetting with one-level-deep cloning.
90     */
91    @SuppressWarnings("unchecked")
92    PackageSettingBase(PackageSettingBase base) {
93        super(base);
94
95        name = base.name;
96        realName = base.realName;
97        codePath = base.codePath;
98        codePathString = base.codePathString;
99        resourcePath = base.resourcePath;
100        resourcePathString = base.resourcePathString;
101        nativeLibraryPathString = base.nativeLibraryPathString;
102        timeStamp = base.timeStamp;
103        firstInstallTime = base.firstInstallTime;
104        lastUpdateTime = base.lastUpdateTime;
105        versionCode = base.versionCode;
106
107        uidError = base.uidError;
108
109        signatures = new PackageSignatures(base.signatures);
110
111        permissionsFixed = base.permissionsFixed;
112        haveGids = base.haveGids;
113        userState.clear();
114        for (int i=0; i<base.userState.size(); i++) {
115            userState.put(base.userState.keyAt(i),
116                    new PackageUserState(base.userState.valueAt(i)));
117        }
118        installStatus = base.installStatus;
119
120        origPackage = base.origPackage;
121
122        installerPackageName = base.installerPackageName;
123    }
124
125    void init(File codePath, File resourcePath, String nativeLibraryPathString,
126            int pVersionCode) {
127        this.codePath = codePath;
128        this.codePathString = codePath.toString();
129        this.resourcePath = resourcePath;
130        this.resourcePathString = resourcePath.toString();
131        this.nativeLibraryPathString = nativeLibraryPathString;
132        this.versionCode = pVersionCode;
133    }
134
135    public void setInstallerPackageName(String packageName) {
136        installerPackageName = packageName;
137    }
138
139    String getInstallerPackageName() {
140        return installerPackageName;
141    }
142
143    public void setInstallStatus(int newStatus) {
144        installStatus = newStatus;
145    }
146
147    public int getInstallStatus() {
148        return installStatus;
149    }
150
151    public void setTimeStamp(long newStamp) {
152        timeStamp = newStamp;
153    }
154
155    /**
156     * Make a shallow copy of this package settings.
157     */
158    public void copyFrom(PackageSettingBase base) {
159        grantedPermissions = base.grantedPermissions;
160        gids = base.gids;
161
162        timeStamp = base.timeStamp;
163        firstInstallTime = base.firstInstallTime;
164        lastUpdateTime = base.lastUpdateTime;
165        signatures = base.signatures;
166        permissionsFixed = base.permissionsFixed;
167        haveGids = base.haveGids;
168        userState.clear();
169        for (int i=0; i<base.userState.size(); i++) {
170            userState.put(base.userState.keyAt(i), base.userState.valueAt(i));
171        }
172        installStatus = base.installStatus;
173    }
174
175    private PackageUserState modifyUserState(int userId) {
176        PackageUserState state = userState.get(userId);
177        if (state == null) {
178            state = new PackageUserState();
179            userState.put(userId, state);
180        }
181        return state;
182    }
183
184    public PackageUserState readUserState(int userId) {
185        PackageUserState state = userState.get(userId);
186        if (state != null) {
187            return state;
188        }
189        return DEFAULT_USER_STATE;
190    }
191
192    void setEnabled(int state, int userId) {
193        modifyUserState(userId).enabled = state;
194    }
195
196    int getEnabled(int userId) {
197        return readUserState(userId).enabled;
198    }
199
200    void setInstalled(boolean inst, int userId) {
201        modifyUserState(userId).installed = inst;
202    }
203
204    boolean getInstalled(int userId) {
205        return readUserState(userId).installed;
206    }
207
208    boolean isAnyInstalled(int[] users) {
209        for (int user: users) {
210            if (readUserState(user).installed) {
211                return true;
212            }
213        }
214        return false;
215    }
216
217    int[] queryInstalledUsers(int[] users, boolean installed) {
218        int num = 0;
219        for (int user : users) {
220            if (getInstalled(user) == installed) {
221                num++;
222            }
223        }
224        int[] res = new int[num];
225        num = 0;
226        for (int user : users) {
227            if (getInstalled(user) == installed) {
228                res[num] = user;
229                num++;
230            }
231        }
232        return res;
233    }
234
235    boolean getStopped(int userId) {
236        return readUserState(userId).stopped;
237    }
238
239    void setStopped(boolean stop, int userId) {
240        modifyUserState(userId).stopped = stop;
241    }
242
243    boolean getNotLaunched(int userId) {
244        return readUserState(userId).notLaunched;
245    }
246
247    void setNotLaunched(boolean stop, int userId) {
248        modifyUserState(userId).notLaunched = stop;
249    }
250
251    void setUserState(int userId, int enabled, boolean installed, boolean stopped,
252            boolean notLaunched, HashSet<String> enabledComponents,
253            HashSet<String> disabledComponents) {
254        PackageUserState state = modifyUserState(userId);
255        state.enabled = enabled;
256        state.installed = installed;
257        state.stopped = stopped;
258        state.notLaunched = notLaunched;
259        state.enabledComponents = enabledComponents;
260        state.disabledComponents = disabledComponents;
261    }
262
263    HashSet<String> getEnabledComponents(int userId) {
264        return readUserState(userId).enabledComponents;
265    }
266
267    HashSet<String> getDisabledComponents(int userId) {
268        return readUserState(userId).disabledComponents;
269    }
270
271    void setEnabledComponents(HashSet<String> components, int userId) {
272        modifyUserState(userId).enabledComponents = components;
273    }
274
275    void setDisabledComponents(HashSet<String> components, int userId) {
276        modifyUserState(userId).disabledComponents = components;
277    }
278
279    void setEnabledComponentsCopy(HashSet<String> components, int userId) {
280        modifyUserState(userId).enabledComponents = components != null
281                ? new HashSet<String>(components) : null;
282    }
283
284    void setDisabledComponentsCopy(HashSet<String> components, int userId) {
285        modifyUserState(userId).disabledComponents = components != null
286                ? new HashSet<String>(components) : null;
287    }
288
289    PackageUserState modifyUserStateComponents(int userId, boolean disabled, boolean enabled) {
290        PackageUserState state = modifyUserState(userId);
291        if (disabled && state.disabledComponents == null) {
292            state.disabledComponents = new HashSet<String>(1);
293        }
294        if (enabled && state.enabledComponents == null) {
295            state.enabledComponents = new HashSet<String>(1);
296        }
297        return state;
298    }
299
300    void addDisabledComponent(String componentClassName, int userId) {
301        modifyUserStateComponents(userId, true, false).disabledComponents.add(componentClassName);
302    }
303
304    void addEnabledComponent(String componentClassName, int userId) {
305        modifyUserStateComponents(userId, false, true).enabledComponents.add(componentClassName);
306    }
307
308    boolean enableComponentLPw(String componentClassName, int userId) {
309        PackageUserState state = modifyUserStateComponents(userId, false, true);
310        boolean changed = state.disabledComponents != null
311                ? state.disabledComponents.remove(componentClassName) : false;
312        changed |= state.enabledComponents.add(componentClassName);
313        return changed;
314    }
315
316    boolean disableComponentLPw(String componentClassName, int userId) {
317        PackageUserState state = modifyUserStateComponents(userId, true, false);
318        boolean changed = state.enabledComponents != null
319                ? state.enabledComponents.remove(componentClassName) : false;
320        changed |= state.disabledComponents.add(componentClassName);
321        return changed;
322    }
323
324    boolean restoreComponentLPw(String componentClassName, int userId) {
325        PackageUserState state = modifyUserStateComponents(userId, true, true);
326        boolean changed = state.disabledComponents != null
327                ? state.disabledComponents.remove(componentClassName) : false;
328        changed |= state.enabledComponents != null
329                ? state.enabledComponents.remove(componentClassName) : false;
330        return changed;
331    }
332
333    int getCurrentEnabledStateLPr(String componentName, int userId) {
334        PackageUserState state = readUserState(userId);
335        if (state.enabledComponents != null && state.enabledComponents.contains(componentName)) {
336            return COMPONENT_ENABLED_STATE_ENABLED;
337        } else if (state.disabledComponents != null
338                && state.disabledComponents.contains(componentName)) {
339            return COMPONENT_ENABLED_STATE_DISABLED;
340        } else {
341            return COMPONENT_ENABLED_STATE_DEFAULT;
342        }
343    }
344
345    void removeUser(int userId) {
346        userState.delete(userId);
347    }
348}
349