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 package android.car.content.pm; 17 18 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.BOILERPLATE_CODE; 19 20 import android.annotation.IntDef; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.car.annotation.AddedInOrBefore; 24 import android.content.pm.Signature; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 28 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport; 29 30 import java.lang.annotation.Retention; 31 import java.lang.annotation.RetentionPolicy; 32 import java.util.Arrays; 33 34 /** 35 * Parcelable to hold information on app blocking allowlist or denylist for a package. 36 * @hide 37 */ 38 @SystemApi 39 public final class AppBlockingPackageInfo implements Parcelable { 40 41 /** Package name for the package to block or allow. */ 42 @AddedInOrBefore(majorVersion = 33) 43 public final String packageName; 44 45 /** Represents system app which does not need {@link #signature}. */ 46 @AddedInOrBefore(majorVersion = 33) 47 public static final int FLAG_SYSTEM_APP = 0x1; 48 /** Denylist or allowlist every Activities in the package. When this is set, 49 * {@link #activities} may be null. */ 50 @AddedInOrBefore(majorVersion = 33) 51 public static final int FLAG_WHOLE_ACTIVITY = 0x2; 52 /** @hide */ 53 @IntDef(flag = true, 54 value = {FLAG_SYSTEM_APP, FLAG_WHOLE_ACTIVITY}) 55 @Retention(RetentionPolicy.SOURCE) 56 public @interface ConstructorFlags {} 57 58 /** 59 * flags to give additional information on the package. 60 * @see #FLAG_SYSTEM_APP 61 * @see #FLAG_WHOLE_ACTIVITY 62 */ 63 @AddedInOrBefore(majorVersion = 33) 64 public final int flags; 65 66 /** 67 * Package version should be bigger than this to block or allow. 68 * (package version > minRevisionCode) 69 * 0 means do not care min version. 70 */ 71 @AddedInOrBefore(majorVersion = 33) 72 public final int minRevisionCode; 73 74 /** 75 * Package version should be smaller than this to block or allow. 76 * (package version < minRevisionCode) 77 * 0 means do not care max version. 78 */ 79 @AddedInOrBefore(majorVersion = 33) 80 public final int maxRevisionCode; 81 82 /** 83 * Signature of package. This can be null if target package is from system so that package 84 * name is enough to uniquely identify it (= {@link #flags} having {@link #FLAG_SYSTEM_APP}. 85 * Matching any member of array is considered as matching package. 86 */ 87 @AddedInOrBefore(majorVersion = 33) 88 public final Signature[] signatures; 89 90 /** List of activities (full class name). This can be null if Activity is not blocked or 91 * allowed. Additionally, {@link #FLAG_WHOLE_ACTIVITY} set in {@link #flags} shall have 92 * null for this. */ 93 @AddedInOrBefore(majorVersion = 33) 94 public final String[] activities; 95 96 AppBlockingPackageInfo(String packageName, int minRevisionCode, int maxRevisionCode, @ConstructorFlags int flags, @Nullable Signature[] signatures, @Nullable String[] activities)97 public AppBlockingPackageInfo(String packageName, int minRevisionCode, int maxRevisionCode, 98 @ConstructorFlags int flags, @Nullable Signature[] signatures, 99 @Nullable String[] activities) { 100 if (packageName == null) { 101 throw new IllegalArgumentException("packageName cannot be null"); 102 } 103 this.packageName = packageName; 104 this.flags = flags; 105 this.minRevisionCode = minRevisionCode; 106 this.maxRevisionCode = maxRevisionCode; 107 this.signatures = signatures; 108 this.activities = activities; 109 verify(); 110 } 111 AppBlockingPackageInfo(Parcel in)112 public AppBlockingPackageInfo(Parcel in) { 113 packageName = in.readString(); 114 flags = in.readInt(); 115 minRevisionCode = in.readInt(); 116 maxRevisionCode = in.readInt(); 117 signatures = in.createTypedArray(Signature.CREATOR); 118 activities = in.createStringArray(); 119 verify(); 120 } 121 122 @Override 123 @ExcludeFromCodeCoverageGeneratedReport(reason = BOILERPLATE_CODE) 124 @AddedInOrBefore(majorVersion = 33) describeContents()125 public int describeContents() { 126 return 0; 127 } 128 129 @Override 130 @AddedInOrBefore(majorVersion = 33) writeToParcel(Parcel dest, int flags)131 public void writeToParcel(Parcel dest, int flags) { 132 dest.writeString(packageName); 133 dest.writeInt(this.flags); 134 dest.writeInt(minRevisionCode); 135 dest.writeInt(maxRevisionCode); 136 dest.writeTypedArray(signatures, 0); 137 dest.writeStringArray(activities); 138 } 139 140 @AddedInOrBefore(majorVersion = 33) 141 public static final Parcelable.Creator<AppBlockingPackageInfo> CREATOR = 142 new Parcelable.Creator<AppBlockingPackageInfo>() { 143 144 @Override 145 public AppBlockingPackageInfo createFromParcel(Parcel in) { 146 return new AppBlockingPackageInfo(in); 147 } 148 149 @Override 150 public AppBlockingPackageInfo[] newArray(int size) { 151 return new AppBlockingPackageInfo[size]; 152 } 153 }; 154 155 /** @hide */ 156 @AddedInOrBefore(majorVersion = 33) verify()157 public void verify() throws IllegalArgumentException { 158 if (signatures == null && (flags & FLAG_SYSTEM_APP) == 0) { 159 throw new IllegalArgumentException( 160 "Only system package with FLAG_SYSTEM_APP can have null signatures"); 161 } 162 } 163 164 /** @hide */ 165 @AddedInOrBefore(majorVersion = 33) isActivityCovered(String className)166 public boolean isActivityCovered(String className) { 167 if ((flags & FLAG_WHOLE_ACTIVITY) != 0) { 168 return true; 169 } 170 if (activities == null) { 171 return false; 172 } 173 for (String activityName : activities) { 174 if (activityName.equals(className)) { 175 return true; 176 } 177 } 178 return false; 179 } 180 181 @Override 182 @AddedInOrBefore(majorVersion = 33) hashCode()183 public int hashCode() { 184 final int prime = 31; 185 int result = 1; 186 result = prime * result + Arrays.hashCode(activities); 187 result = prime * result + flags; 188 result = prime * result + maxRevisionCode; 189 result = prime * result + minRevisionCode; 190 result = prime * result + ((packageName == null) ? 0 : packageName.hashCode()); 191 result = prime * result + Arrays.hashCode(signatures); 192 return result; 193 } 194 195 @Override 196 @AddedInOrBefore(majorVersion = 33) equals(Object obj)197 public boolean equals(Object obj) { 198 if (this == obj) { 199 return true; 200 } 201 if (obj == null) { 202 return false; 203 } 204 if (getClass() != obj.getClass()) { 205 return false; 206 } 207 AppBlockingPackageInfo other = (AppBlockingPackageInfo) obj; 208 if (!Arrays.equals(activities, other.activities)) { 209 return false; 210 } 211 if (flags != other.flags) { 212 return false; 213 } 214 if (maxRevisionCode != other.maxRevisionCode) { 215 return false; 216 } 217 if (minRevisionCode != other.minRevisionCode) { 218 return false; 219 } 220 if (packageName == null) { 221 if (other.packageName != null) { 222 return false; 223 } 224 } else if (!packageName.equals(other.packageName)) { 225 return false; 226 } 227 if (!Arrays.equals(signatures, other.signatures)) { 228 return false; 229 } 230 return true; 231 } 232 233 @Override 234 @AddedInOrBefore(majorVersion = 33) toString()235 public String toString() { 236 return "AppBlockingPackageInfo [packageName=" + packageName + ", flags=" + flags 237 + ", minRevisionCode=" + minRevisionCode + ", maxRevisionCode=" + maxRevisionCode 238 + ", signatures=" + Arrays.toString(signatures) + ", activities=" 239 + Arrays.toString(activities) + "]"; 240 } 241 } 242