• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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