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 26 import java.util.ArrayDeque; 27 import java.util.Queue; 28 29 /** 30 * Utility class containing methods to verify the max allowed size of certain policy types. 31 * 32 * @hide 33 */ 34 public class PolicySizeVerifier { 35 36 // Binary XML serializer doesn't support longer strings 37 public static final int MAX_POLICY_STRING_LENGTH = 65535; 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 Preconditions.checkArgument( 51 str.length() <= MAX_POLICY_STRING_LENGTH, argName + " loo long"); 52 } 53 54 /** 55 * Throw if package name exceeds max size allowed by the system. 56 */ enforceMaxPackageNameLength(String pkg)57 public static void enforceMaxPackageNameLength(String pkg) { 58 Preconditions.checkArgument( 59 pkg.length() <= MAX_PACKAGE_NAME_LENGTH, "Package name too long"); 60 } 61 62 /** 63 * Throw if persistable bundle contains any string that's too long to be serialized. 64 */ enforceMaxStringLength(PersistableBundle bundle, String argName)65 public static void enforceMaxStringLength(PersistableBundle bundle, String argName) { 66 // Persistable bundles can have other persistable bundles as values, traverse with a queue. 67 Queue<PersistableBundle> queue = new ArrayDeque<>(); 68 queue.add(bundle); 69 while (!queue.isEmpty()) { 70 PersistableBundle current = queue.remove(); 71 for (String key : current.keySet()) { 72 enforceMaxStringLength(key, "key in " + argName); 73 Object value = current.get(key); 74 if (value instanceof String str) { 75 enforceMaxStringLength(str, "string value in " + argName); 76 } else if (value instanceof String[] strArray) { 77 for (String str : strArray) { 78 enforceMaxStringLength(str, "string value in " + argName); 79 } 80 } else if (value instanceof PersistableBundle persistableBundle) { 81 queue.add(persistableBundle); 82 } 83 } 84 } 85 } 86 87 /** 88 * Throw if bundle contains any string that's too long to be serialized. This follows the 89 * serialization logic in BundlePolicySerializer#writeBundle. 90 */ enforceMaxBundleFieldsLength(Bundle bundle)91 public static void enforceMaxBundleFieldsLength(Bundle bundle) { 92 Queue<Bundle> queue = new ArrayDeque<>(); 93 queue.add(bundle); 94 while (!queue.isEmpty()) { 95 Bundle current = queue.remove(); 96 for (String key : current.keySet()) { 97 enforceMaxStringLength(key, "key in Bundle"); 98 Object value = current.get(key); 99 if (value instanceof String str) { 100 enforceMaxStringLength(str, "string value in Bundle with " 101 + "key" + key); 102 } else if (value instanceof String[] strArray) { 103 for (String str : strArray) { 104 enforceMaxStringLength(str, "string value in Bundle with" 105 + " key" + key); 106 } 107 } else if (value instanceof Bundle b) { 108 queue.add(b); 109 } 110 else if (value instanceof Parcelable[] parcelableArray) { 111 for (Parcelable parcelable : parcelableArray) { 112 if (!(parcelable instanceof Bundle)) { 113 throw new IllegalArgumentException("bundle-array can only hold " 114 + "Bundles"); 115 } 116 queue.add((Bundle) parcelable); 117 } 118 } 119 } 120 } 121 } 122 123 /** 124 * Throw if ComponentName contains any string that's too long to be serialized. 125 */ enforceMaxComponentNameLength(ComponentName componentName)126 public static void enforceMaxComponentNameLength(ComponentName componentName) { 127 enforceMaxPackageNameLength(componentName.getPackageName()); 128 enforceMaxStringLength(componentName.flattenToString(), "componentName"); 129 } 130 131 /** 132 * Truncates char sequence to maximum length, nulls are ignored. 133 */ truncateIfLonger(CharSequence input, int maxLength)134 public static CharSequence truncateIfLonger(CharSequence input, int maxLength) { 135 return input == null || input.length() <= maxLength 136 ? input 137 : input.subSequence(0, maxLength); 138 } 139 } 140