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