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.server.utils; 18 19 import android.annotation.Nullable; 20 import android.provider.DeviceConfig; 21 22 import com.android.internal.annotations.VisibleForTesting; 23 import com.android.server.RescueParty; 24 25 import java.util.ArrayList; 26 import java.util.Arrays; 27 import java.util.List; 28 29 /** 30 * Utilities for interacting with the {@link android.provider.DeviceConfig}. 31 * 32 * @hide 33 */ 34 public final class FlagNamespaceUtils { 35 /** 36 * Special String used for communicating through {@link #RESET_PLATFORM_PACKAGE_FLAG} that 37 * Settings were reset by the RescueParty, no actual namespace with this name exists in 38 * {@link DeviceConfig}. 39 */ 40 public static final String NAMESPACE_NO_PACKAGE = "no_package"; 41 42 /** 43 * Name of the special namespace in DeviceConfig table used for communicating resets. 44 */ 45 @VisibleForTesting 46 public static final String NAMESPACE_RESCUE_PARTY = "rescue_party_namespace"; 47 /** 48 * Flag in the {@link DeviceConfig} in {@link #NAMESPACE_RESCUE_PARTY}, holding all known {@link 49 * DeviceConfig} namespaces, as a {@link #DELIMITER} separated String. It's updated after the 50 * first time flags are written to the new namespace in the {@link DeviceConfig}. 51 */ 52 @VisibleForTesting 53 public static final String ALL_KNOWN_NAMESPACES_FLAG = "all_known_namespaces"; 54 /** 55 * Flag in the {@link DeviceConfig} in {@link #NAMESPACE_RESCUE_PARTY} with integer counter 56 * suffix added to it, holding {@link DeviceConfig} namespace value whose flags were recently 57 * reset by the {@link RescueParty}. It's updated by {@link RescueParty} every time given 58 * namespace flags are reset. 59 */ 60 @VisibleForTesting 61 public static final String RESET_PLATFORM_PACKAGE_FLAG = "reset_platform_package"; 62 private static final String DELIMITER = ":"; 63 /** 64 * Maximum value of the counter used in combination with {@link #RESET_PLATFORM_PACKAGE_FLAG} 65 * when communicating recently reset by the RescueParty namespace values. 66 */ 67 private static final int MAX_COUNTER_VALUE = 50; 68 69 private static int sKnownResetNamespacesFlagCounter = -1; 70 71 /** 72 * Sets the union of {@link #RESET_PLATFORM_PACKAGE_FLAG} with 73 * {@link #sKnownResetNamespacesFlagCounter} in the DeviceConfig for each namespace 74 * in the consumed namespacesList. These flags are used for communicating the namespaces 75 * (aka platform packages) whose flags in {@link DeviceConfig} were just reset 76 * by the RescueParty. 77 */ addToKnownResetNamespaces(@ullable List<String> namespacesList)78 public static void addToKnownResetNamespaces(@Nullable List<String> namespacesList) { 79 if (namespacesList == null) { 80 return; 81 } 82 for (String namespace : namespacesList) { 83 addToKnownResetNamespaces(namespace); 84 } 85 } 86 87 /** 88 * Sets the union of {@link #RESET_PLATFORM_PACKAGE_FLAG} with 89 * {@link #sKnownResetNamespacesFlagCounter} in the DeviceConfig for the consumed namespace. 90 * This flag is used for communicating the namespace (aka platform package) whose flags 91 * in {@link DeviceConfig} were just reset by the RescueParty. 92 */ addToKnownResetNamespaces(String namespace)93 public static void addToKnownResetNamespaces(String namespace) { 94 int nextFlagCounter = incrementAndRetrieveResetNamespacesFlagCounter(); 95 DeviceConfig.setProperty(NAMESPACE_RESCUE_PARTY, 96 RESET_PLATFORM_PACKAGE_FLAG + nextFlagCounter, 97 namespace, /*makeDefault=*/ true); 98 } 99 100 /** 101 * Reset all namespaces in DeviceConfig with consumed resetMode. 102 */ resetDeviceConfig(int resetMode)103 public static void resetDeviceConfig(int resetMode) { 104 resetDeviceConfig(resetMode, getAllKnownDeviceConfigNamespacesList()); 105 } 106 107 /** 108 * Reset all consumed namespaces in DeviceConfig with consumed resetMode. 109 */ resetDeviceConfig(int resetMode, List<String> namespacesList)110 public static void resetDeviceConfig(int resetMode, List<String> namespacesList) { 111 for (String namespace : namespacesList) { 112 DeviceConfig.resetToDefaults(resetMode, namespace); 113 } 114 addToKnownResetNamespaces(namespacesList); 115 } 116 117 /** 118 * Resets known reset namespaces flag counter for tests only. 119 */ 120 @VisibleForTesting resetKnownResetNamespacesFlagCounterForTest()121 public static void resetKnownResetNamespacesFlagCounterForTest() { 122 sKnownResetNamespacesFlagCounter = -1; 123 } 124 125 /** 126 * Returns a list of all known DeviceConfig namespaces, except for the special {@link 127 * #NAMESPACE_RESCUE_PARTY} 128 */ getAllKnownDeviceConfigNamespacesList()129 private static List<String> getAllKnownDeviceConfigNamespacesList() { 130 String namespacesStr = DeviceConfig.getProperty(NAMESPACE_RESCUE_PARTY, 131 ALL_KNOWN_NAMESPACES_FLAG); 132 List<String> namespacesList = toStringList(namespacesStr); 133 namespacesList.remove(NAMESPACE_RESCUE_PARTY); 134 return namespacesList; 135 } 136 toStringList(String serialized)137 private static List<String> toStringList(String serialized) { 138 if (serialized == null || serialized.length() == 0) { 139 return new ArrayList<>(); 140 } 141 return Arrays.asList(serialized.split(DELIMITER)); 142 } 143 incrementAndRetrieveResetNamespacesFlagCounter()144 private static int incrementAndRetrieveResetNamespacesFlagCounter() { 145 sKnownResetNamespacesFlagCounter++; 146 if (sKnownResetNamespacesFlagCounter == MAX_COUNTER_VALUE) { 147 sKnownResetNamespacesFlagCounter = 0; 148 } 149 return sKnownResetNamespacesFlagCounter; 150 } 151 } 152