• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 android.app.admin;
18 
19 import android.content.ComponentName;
20 import android.os.Bundle;
21 import android.os.Parcelable;
22 import android.os.PersistableBundle;
23 
24 import com.android.internal.util.Preconditions;
25 import com.android.modules.utils.ModifiedUtf8;
26 
27 import java.io.UTFDataFormatException;
28 import java.util.ArrayDeque;
29 import java.util.Queue;
30 
31 /**
32  * Utility class containing methods to verify the max allowed size of certain policy types.
33  *
34  * @hide
35  */
36 public class PolicySizeVerifier {
37 
38     // FrameworkParsingPackageUtils#MAX_FILE_NAME_SIZE, Android packages are used in dir names.
39     public static final int MAX_PACKAGE_NAME_LENGTH = 223;
40 
41     public static final int MAX_PROFILE_NAME_LENGTH = 200;
42     public static final int MAX_LONG_SUPPORT_MESSAGE_LENGTH = 20000;
43     public static final int MAX_SHORT_SUPPORT_MESSAGE_LENGTH = 200;
44     public static final int MAX_ORG_NAME_LENGTH = 200;
45 
46     /**
47      * Throw if string argument is too long to be serialized.
48      */
enforceMaxStringLength(String str, String argName)49     public static void enforceMaxStringLength(String str, String argName) {
50         try {
51             long len = ModifiedUtf8.countBytes(str, /* throw error if too long */ true);
52         } catch (UTFDataFormatException e) {
53             throw new IllegalArgumentException(argName + " too long");
54         }
55     }
56 
57     /**
58      * Throw if package name exceeds max size allowed by the system.
59      */
enforceMaxPackageNameLength(String pkg)60     public static void enforceMaxPackageNameLength(String pkg) {
61         Preconditions.checkArgument(
62                 pkg.length() <= MAX_PACKAGE_NAME_LENGTH, "Package name too long");
63     }
64 
65     /**
66      * Throw if persistable bundle contains any string that's too long to be serialized.
67      */
enforceMaxStringLength(PersistableBundle bundle, String argName)68     public static void enforceMaxStringLength(PersistableBundle bundle, String argName) {
69         // Persistable bundles can have other persistable bundles as values, traverse with a queue.
70         Queue<PersistableBundle> queue = new ArrayDeque<>();
71         queue.add(bundle);
72         while (!queue.isEmpty()) {
73             PersistableBundle current = queue.remove();
74             for (String key : current.keySet()) {
75                 enforceMaxStringLength(key, "key in " + argName);
76                 Object value = current.get(key);
77                 if (value instanceof String str) {
78                     enforceMaxStringLength(str, "string value in " + argName);
79                 } else if (value instanceof String[] strArray) {
80                     for (String str : strArray) {
81                         enforceMaxStringLength(str, "string value in " + argName);
82                     }
83                 } else if (value instanceof PersistableBundle persistableBundle) {
84                     queue.add(persistableBundle);
85                 }
86             }
87         }
88     }
89 
90     /**
91      * Throw if bundle contains any string that's too long to be serialized. This follows the
92      * serialization logic in BundlePolicySerializer#writeBundle.
93      */
enforceMaxBundleFieldsLength(Bundle bundle)94     public static void enforceMaxBundleFieldsLength(Bundle bundle) {
95         Queue<Bundle> queue = new ArrayDeque<>();
96         queue.add(bundle);
97         while (!queue.isEmpty()) {
98             Bundle current = queue.remove();
99             for (String key : current.keySet()) {
100                 enforceMaxStringLength(key, "key in Bundle");
101                 Object value = current.get(key);
102                 if (value instanceof String str) {
103                     enforceMaxStringLength(str, "string value in Bundle with "
104                             + "key" + key);
105                 } else if (value instanceof String[] strArray) {
106                     for (String str : strArray) {
107                         enforceMaxStringLength(str, "string value in Bundle with"
108                                 + " key" + key);
109                     }
110                 } else if (value instanceof Bundle b) {
111                     queue.add(b);
112                 }
113                 else if (value instanceof Parcelable[] parcelableArray) {
114                     for (Parcelable parcelable : parcelableArray) {
115                         if (!(parcelable instanceof Bundle)) {
116                             throw new IllegalArgumentException("bundle-array can only hold "
117                                     + "Bundles");
118                         }
119                         queue.add((Bundle) parcelable);
120                     }
121                 }
122             }
123         }
124     }
125 
126     /**
127      * Throw if ComponentName contains any string that's too long to be serialized.
128      */
enforceMaxComponentNameLength(ComponentName componentName)129     public static void enforceMaxComponentNameLength(ComponentName componentName) {
130         enforceMaxPackageNameLength(componentName.getPackageName());
131         enforceMaxStringLength(componentName.flattenToString(), "componentName");
132     }
133 
134     /**
135      * Truncates char sequence to maximum length, nulls are ignored.
136      */
truncateIfLonger(CharSequence input, int maxLength)137     public static CharSequence truncateIfLonger(CharSequence input, int maxLength) {
138         return input == null || input.length() <= maxLength
139                 ? input
140                 : input.subSequence(0, maxLength);
141     }
142 }
143