blob: f8c7447fc55d4d48bec754ebbeef5c739fa99e8a [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
bpetrivs93075f42019-02-28 12:08:12 +000022import com.android.internal.annotations.VisibleForTesting;
bpetrivs62f15982019-02-13 17:18:16 +000023import com.android.server.RescueParty;
24
25import java.util.ArrayList;
26import java.util.Arrays;
27import java.util.List;
28
29/**
30 * Utilities for interacting with the {@link android.provider.DeviceConfig}.
31 *
32 * @hide
33 */
34public 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 */
bpetrivs93075f42019-02-28 12:08:12 +000045 @VisibleForTesting
46 public static final String NAMESPACE_RESCUE_PARTY = "rescue_party_namespace";
bpetrivs62f15982019-02-13 17:18:16 +000047 /**
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 */
bpetrivs93075f42019-02-28 12:08:12 +000052 @VisibleForTesting
53 public static final String ALL_KNOWN_NAMESPACES_FLAG = "all_known_namespaces";
bpetrivs62f15982019-02-13 17:18:16 +000054 /**
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 */
bpetrivs93075f42019-02-28 12:08:12 +000060 @VisibleForTesting
61 public static final String RESET_PLATFORM_PACKAGE_FLAG = "reset_platform_package";
bpetrivs62f15982019-02-13 17:18:16 +000062 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 */
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 */
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 */
103 public static void resetDeviceConfig(int resetMode) {
bpetrivs93075f42019-02-28 12:08:12 +0000104 resetDeviceConfig(resetMode, getAllKnownDeviceConfigNamespacesList());
105 }
106
107 /**
108 * Reset all consumed namespaces in DeviceConfig with consumed resetMode.
109 */
110 public static void resetDeviceConfig(int resetMode, List<String> namespacesList) {
111 for (String namespace : namespacesList) {
bpetrivs62f15982019-02-13 17:18:16 +0000112 DeviceConfig.resetToDefaults(resetMode, namespace);
113 }
bpetrivs93075f42019-02-28 12:08:12 +0000114 addToKnownResetNamespaces(namespacesList);
115 }
116
117 /**
118 * Resets known reset namespaces flag counter for tests only.
119 */
120 @VisibleForTesting
121 public static void resetKnownResetNamespacesFlagCounterForTest() {
122 sKnownResetNamespacesFlagCounter = -1;
bpetrivs62f15982019-02-13 17:18:16 +0000123 }
124
125 /**
126 * Returns a list of all known DeviceConfig namespaces, except for the special {@link
127 * #NAMESPACE_RESCUE_PARTY}
128 */
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
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
144 private static int incrementAndRetrieveResetNamespacesFlagCounter() {
145 sKnownResetNamespacesFlagCounter++;
146 if (sKnownResetNamespacesFlagCounter == MAX_COUNTER_VALUE) {
147 sKnownResetNamespacesFlagCounter = 0;
148 }
149 return sKnownResetNamespacesFlagCounter;
150 }
151}