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