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