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