OverlayInfo.java revision 3e9331125af5a71d9a22df453558284e976d7a29
1/*
2 * Copyright (C) 2015 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 android.content.om;
18
19import android.annotation.IntDef;
20import android.annotation.NonNull;
21import android.annotation.Nullable;
22import android.os.Parcel;
23import android.os.Parcelable;
24
25import java.lang.annotation.Retention;
26import java.lang.annotation.RetentionPolicy;
27
28/**
29 * Immutable overlay information about a package. All PackageInfos that
30 * represent an overlay package will have a corresponding OverlayInfo.
31 *
32 * @hide
33 */
34public final class OverlayInfo implements Parcelable {
35
36    @IntDef(prefix = "STATE_", value = {
37            STATE_UNKNOWN,
38            STATE_MISSING_TARGET,
39            STATE_NO_IDMAP,
40            STATE_DISABLED,
41            STATE_ENABLED,
42            STATE_TARGET_UPGRADING,
43            STATE_OVERLAY_UPGRADING,
44    })
45    @Retention(RetentionPolicy.SOURCE)
46    public @interface State {}
47
48    /**
49     * An internal state used as the initial state of an overlay. OverlayInfo
50     * objects exposed outside the {@link
51     * com.android.server.om.OverlayManagerService} should never have this
52     * state.
53     */
54    public static final int STATE_UNKNOWN = -1;
55
56    /**
57     * The target package of the overlay is not installed. The overlay cannot be enabled.
58     */
59    public static final int STATE_MISSING_TARGET = 0;
60
61    /**
62     * Creation of idmap file failed (e.g. no matching resources). The overlay
63     * cannot be enabled.
64     */
65    public static final int STATE_NO_IDMAP = 1;
66
67    /**
68     * The overlay is currently disabled. It can be enabled.
69     *
70     * @see IOverlayManager#setEnabled
71     */
72    public static final int STATE_DISABLED = 2;
73
74    /**
75     * The overlay is currently enabled. It can be disabled.
76     *
77     * @see IOverlayManager#setEnabled
78     */
79    public static final int STATE_ENABLED = 3;
80
81    /**
82     * The target package is currently being upgraded; the state will change
83     * once the package installation has finished.
84     */
85    public static final int STATE_TARGET_UPGRADING = 4;
86
87    /**
88     * The overlay package is currently being upgraded; the state will change
89     * once the package installation has finished.
90     */
91    public static final int STATE_OVERLAY_UPGRADING = 5;
92
93    /**
94     * Category for theme overlays.
95     */
96    public static final String CATEGORY_THEME = "android.theme";
97
98    /**
99     * Package name of the overlay package
100     */
101    public final String packageName;
102
103    /**
104     * Package name of the target package
105     */
106    public final String targetPackageName;
107
108    /**
109     * Category of the overlay package
110     */
111    public final String category;
112
113    /**
114     * Full path to the base APK for this overlay package
115     */
116    public final String baseCodePath;
117
118    /**
119     * The state of this OverlayInfo as defined by the STATE_* constants in this class.
120     */
121    public final @State int state;
122
123    /**
124     * User handle for which this overlay applies
125     */
126    public final int userId;
127
128    /**
129     * Create a new OverlayInfo based on source with an updated state.
130     *
131     * @param source the source OverlayInfo to base the new instance on
132     * @param state the new state for the source OverlayInfo
133     */
134    public OverlayInfo(@NonNull OverlayInfo source, @State int state) {
135        this(source.packageName, source.targetPackageName, source.category, source.baseCodePath,
136                state, source.userId);
137    }
138
139    public OverlayInfo(@NonNull String packageName, @NonNull String targetPackageName,
140            @Nullable String category, @NonNull String baseCodePath, int state, int userId) {
141        this.packageName = packageName;
142        this.targetPackageName = targetPackageName;
143        this.category = category;
144        this.baseCodePath = baseCodePath;
145        this.state = state;
146        this.userId = userId;
147        ensureValidState();
148    }
149
150    public OverlayInfo(Parcel source) {
151        packageName = source.readString();
152        targetPackageName = source.readString();
153        category = source.readString();
154        baseCodePath = source.readString();
155        state = source.readInt();
156        userId = source.readInt();
157        ensureValidState();
158    }
159
160    private void ensureValidState() {
161        if (packageName == null) {
162            throw new IllegalArgumentException("packageName must not be null");
163        }
164        if (targetPackageName == null) {
165            throw new IllegalArgumentException("targetPackageName must not be null");
166        }
167        if (baseCodePath == null) {
168            throw new IllegalArgumentException("baseCodePath must not be null");
169        }
170        switch (state) {
171            case STATE_UNKNOWN:
172            case STATE_MISSING_TARGET:
173            case STATE_NO_IDMAP:
174            case STATE_DISABLED:
175            case STATE_ENABLED:
176            case STATE_TARGET_UPGRADING:
177            case STATE_OVERLAY_UPGRADING:
178                break;
179            default:
180                throw new IllegalArgumentException("State " + state + " is not a valid state");
181        }
182    }
183
184    @Override
185    public int describeContents() {
186        return 0;
187    }
188
189    @Override
190    public void writeToParcel(Parcel dest, int flags) {
191        dest.writeString(packageName);
192        dest.writeString(targetPackageName);
193        dest.writeString(category);
194        dest.writeString(baseCodePath);
195        dest.writeInt(state);
196        dest.writeInt(userId);
197    }
198
199    public static final Parcelable.Creator<OverlayInfo> CREATOR =
200            new Parcelable.Creator<OverlayInfo>() {
201        @Override
202        public OverlayInfo createFromParcel(Parcel source) {
203            return new OverlayInfo(source);
204        }
205
206        @Override
207        public OverlayInfo[] newArray(int size) {
208            return new OverlayInfo[size];
209        }
210    };
211
212    /**
213     * Return true if this overlay is enabled, i.e. should be used to overlay
214     * the resources in the target package.
215     *
216     * Disabled overlay packages are installed but are currently not in use.
217     *
218     * @return true if the overlay is enabled, else false.
219     */
220    public boolean isEnabled() {
221        switch (state) {
222            case STATE_ENABLED:
223                return true;
224            default:
225                return false;
226        }
227    }
228
229    /**
230     * Translate a state to a human readable string. Only intended for
231     * debugging purposes.
232     *
233     * @return a human readable String representing the state.
234     */
235    public static String stateToString(@State int state) {
236        switch (state) {
237            case STATE_UNKNOWN:
238                return "STATE_UNKNOWN";
239            case STATE_MISSING_TARGET:
240                return "STATE_MISSING_TARGET";
241            case STATE_NO_IDMAP:
242                return "STATE_NO_IDMAP";
243            case STATE_DISABLED:
244                return "STATE_DISABLED";
245            case STATE_ENABLED:
246                return "STATE_ENABLED";
247            case STATE_TARGET_UPGRADING:
248                return "STATE_TARGET_UPGRADING";
249            case STATE_OVERLAY_UPGRADING:
250                return "STATE_OVERLAY_UPGRADING";
251            default:
252                return "<unknown state>";
253        }
254    }
255
256    @Override
257    public int hashCode() {
258        final int prime = 31;
259        int result = 1;
260        result = prime * result + userId;
261        result = prime * result + state;
262        result = prime * result + ((packageName == null) ? 0 : packageName.hashCode());
263        result = prime * result + ((targetPackageName == null) ? 0 : targetPackageName.hashCode());
264        result = prime * result + ((category == null) ? 0 : category.hashCode());
265        result = prime * result + ((baseCodePath == null) ? 0 : baseCodePath.hashCode());
266        return result;
267    }
268
269    @Override
270    public boolean equals(Object obj) {
271        if (this == obj) {
272            return true;
273        }
274        if (obj == null) {
275            return false;
276        }
277        if (getClass() != obj.getClass()) {
278            return false;
279        }
280        OverlayInfo other = (OverlayInfo) obj;
281        if (userId != other.userId) {
282            return false;
283        }
284        if (state != other.state) {
285            return false;
286        }
287        if (!packageName.equals(other.packageName)) {
288            return false;
289        }
290        if (!targetPackageName.equals(other.targetPackageName)) {
291            return false;
292        }
293        if (!category.equals(other.category)) {
294            return false;
295        }
296        if (!baseCodePath.equals(other.baseCodePath)) {
297            return false;
298        }
299        return true;
300    }
301
302    @Override
303    public String toString() {
304        return "OverlayInfo { overlay=" + packageName + ", target=" + targetPackageName + ", state="
305                + state + " (" + stateToString(state) + "), userId=" + userId + " }";
306    }
307}
308