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