1 /* 2 * Copyright (C) 2019 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 17 package com.android.internal.compat; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 24 import java.lang.annotation.Retention; 25 import java.lang.annotation.RetentionPolicy; 26 27 /** 28 * This class contains all the possible override allowed states. 29 */ 30 @android.ravenwood.annotation.RavenwoodKeepWholeClass 31 public final class OverrideAllowedState implements Parcelable { 32 @IntDef({ 33 ALLOWED, 34 DISABLED_NOT_DEBUGGABLE, 35 DISABLED_NON_TARGET_SDK, 36 DISABLED_TARGET_SDK_TOO_HIGH, 37 DEFERRED_VERIFICATION, 38 LOGGING_ONLY_CHANGE, 39 PLATFORM_TOO_OLD 40 }) 41 @Retention(RetentionPolicy.SOURCE) 42 public @interface State { 43 } 44 45 /** 46 * Change can be overridden. 47 */ 48 public static final int ALLOWED = 0; 49 /** 50 * Change cannot be overridden, due to the app not being debuggable. 51 */ 52 public static final int DISABLED_NOT_DEBUGGABLE = 1; 53 /** 54 * Change cannot be overridden, due to the build being non-debuggable and the change being 55 * enabled regardless of targetSdk. 56 */ 57 public static final int DISABLED_NON_TARGET_SDK = 2; 58 /** 59 * Change cannot be overridden, due to the app's targetSdk being above the change's targetSdk. 60 */ 61 public static final int DISABLED_TARGET_SDK_TOO_HIGH = 3; 62 /** 63 * Change override decision is currently being deferred, due to the app not being installed yet. 64 */ 65 public static final int DEFERRED_VERIFICATION = 4; 66 /** 67 * Change is marked as logging only, and cannot be toggled. 68 */ 69 public static final int LOGGING_ONLY_CHANGE = 5; 70 /** 71 * Change is gated by a target sdk version newer than the current platform sdk version. 72 */ 73 public static final int PLATFORM_TOO_OLD = 6; 74 75 @State 76 public final int state; 77 public final int appTargetSdk; 78 public final int changeIdTargetSdk; 79 OverrideAllowedState(Parcel parcel)80 private OverrideAllowedState(Parcel parcel) { 81 state = parcel.readInt(); 82 appTargetSdk = parcel.readInt(); 83 changeIdTargetSdk = parcel.readInt(); 84 } 85 OverrideAllowedState(@tate int state, int appTargetSdk, int changeIdTargetSdk)86 public OverrideAllowedState(@State int state, int appTargetSdk, int changeIdTargetSdk) { 87 this.state = state; 88 this.appTargetSdk = appTargetSdk; 89 this.changeIdTargetSdk = changeIdTargetSdk; 90 } 91 92 @Override describeContents()93 public int describeContents() { 94 return 0; 95 } 96 97 @Override writeToParcel(Parcel out, int flags)98 public void writeToParcel(Parcel out, int flags) { 99 out.writeInt(state); 100 out.writeInt(appTargetSdk); 101 out.writeInt(changeIdTargetSdk); 102 } 103 104 /** 105 * Enforces the policy for overriding compat changes. 106 * 107 * @param changeId the change id that was attempted to be overridden. 108 * @param packageName the package for which the attempt was made. 109 * @throws SecurityException if the policy forbids this operation. 110 */ enforce(long changeId, String packageName)111 public void enforce(long changeId, String packageName) 112 throws SecurityException { 113 switch (state) { 114 case ALLOWED: 115 case DEFERRED_VERIFICATION: 116 return; 117 case DISABLED_NOT_DEBUGGABLE: 118 throw new SecurityException( 119 "Cannot override a change on a non-debuggable app and user build."); 120 case DISABLED_NON_TARGET_SDK: 121 throw new SecurityException( 122 "Cannot override a default enabled/disabled change on a user build."); 123 case DISABLED_TARGET_SDK_TOO_HIGH: 124 throw new SecurityException(String.format( 125 "Cannot override %1$d for %2$s because the app's targetSdk (%3$d) is " 126 + "above the change's targetSdk threshold (%4$d)", 127 changeId, packageName, appTargetSdk, changeIdTargetSdk)); 128 case LOGGING_ONLY_CHANGE: 129 throw new SecurityException(String.format( 130 "Cannot override %1$d because it is marked as a logging-only change.", 131 changeId)); 132 case PLATFORM_TOO_OLD: 133 throw new SecurityException(String.format( 134 "Cannot override %1$d for %2$s because the change's targetSdk threshold " 135 + "(%3$d) is above the platform sdk.", 136 changeId, packageName, changeIdTargetSdk)); 137 } 138 } 139 140 public static final @NonNull 141 Parcelable.Creator<OverrideAllowedState> CREATOR = 142 new Parcelable.Creator<OverrideAllowedState>() { 143 public OverrideAllowedState createFromParcel(Parcel parcel) { 144 OverrideAllowedState info = new OverrideAllowedState(parcel); 145 return info; 146 } 147 148 public OverrideAllowedState[] newArray(int size) { 149 return new OverrideAllowedState[size]; 150 } 151 }; 152 153 @Override equals(Object obj)154 public boolean equals(Object obj) { 155 if (this == obj) { 156 return true; 157 } 158 if (obj == null) { 159 return false; 160 } 161 if (!(obj instanceof OverrideAllowedState)) { 162 return false; 163 } 164 OverrideAllowedState otherState = (OverrideAllowedState) obj; 165 return state == otherState.state 166 && appTargetSdk == otherState.appTargetSdk 167 && changeIdTargetSdk == otherState.changeIdTargetSdk; 168 } 169 stateName()170 private String stateName() { 171 switch (state) { 172 case ALLOWED: 173 return "ALLOWED"; 174 case DISABLED_NOT_DEBUGGABLE: 175 return "DISABLED_NOT_DEBUGGABLE"; 176 case DISABLED_NON_TARGET_SDK: 177 return "DISABLED_NON_TARGET_SDK"; 178 case DISABLED_TARGET_SDK_TOO_HIGH: 179 return "DISABLED_TARGET_SDK_TOO_HIGH"; 180 case DEFERRED_VERIFICATION: 181 return "DEFERRED_VERIFICATION"; 182 case LOGGING_ONLY_CHANGE: 183 return "LOGGING_ONLY_CHANGE"; 184 case PLATFORM_TOO_OLD: 185 return "PLATFORM_TOO_OLD"; 186 } 187 return "UNKNOWN"; 188 } 189 190 @Override toString()191 public String toString() { 192 return "OverrideAllowedState(state=" + stateName() + "; appTargetSdk=" + appTargetSdk 193 + "; changeIdTargetSdk=" + changeIdTargetSdk + ")"; 194 } 195 } 196