blob: 28df9f673ed0df5420380c790556a01288e5f0e3 [file] [log] [blame]
Makoto Onukia4f11972015-10-01 13:19:58 -07001/*
2 * Copyright (C) 2015 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.pm;
18
19import com.google.android.collect.Sets;
20
Makoto Onuki4f160732015-10-27 17:15:38 -070021import android.annotation.Nullable;
22import android.content.ContentResolver;
23import android.content.Context;
24import android.media.IAudioService;
25import android.net.Uri;
26import android.os.Binder;
Makoto Onukia4f11972015-10-01 13:19:58 -070027import android.os.Bundle;
Makoto Onuki4f160732015-10-27 17:15:38 -070028import android.os.RemoteException;
29import android.os.ServiceManager;
30import android.os.SystemProperties;
31import android.os.UserHandle;
Makoto Onukia4f11972015-10-01 13:19:58 -070032import android.os.UserManager;
Makoto Onuki4f160732015-10-27 17:15:38 -070033import android.util.Slog;
Makoto Onukia4f11972015-10-01 13:19:58 -070034
35import org.xmlpull.v1.XmlPullParser;
36import org.xmlpull.v1.XmlSerializer;
37
38import java.io.IOException;
39import java.io.PrintWriter;
40import java.util.Set;
41
42public class UserRestrictionsUtils {
Makoto Onuki4f160732015-10-27 17:15:38 -070043 private static final String TAG = "UserRestrictionsUtils";
44
Makoto Onukia4f11972015-10-01 13:19:58 -070045 private UserRestrictionsUtils() {
46 }
47
48 public static final String[] USER_RESTRICTIONS = {
49 UserManager.DISALLOW_CONFIG_WIFI,
50 UserManager.DISALLOW_MODIFY_ACCOUNTS,
51 UserManager.DISALLOW_INSTALL_APPS,
52 UserManager.DISALLOW_UNINSTALL_APPS,
53 UserManager.DISALLOW_SHARE_LOCATION,
54 UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
55 UserManager.DISALLOW_CONFIG_BLUETOOTH,
56 UserManager.DISALLOW_USB_FILE_TRANSFER,
57 UserManager.DISALLOW_CONFIG_CREDENTIALS,
58 UserManager.DISALLOW_REMOVE_USER,
59 UserManager.DISALLOW_DEBUGGING_FEATURES,
60 UserManager.DISALLOW_CONFIG_VPN,
61 UserManager.DISALLOW_CONFIG_TETHERING,
62 UserManager.DISALLOW_NETWORK_RESET,
63 UserManager.DISALLOW_FACTORY_RESET,
64 UserManager.DISALLOW_ADD_USER,
65 UserManager.ENSURE_VERIFY_APPS,
66 UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
67 UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
68 UserManager.DISALLOW_APPS_CONTROL,
69 UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
70 UserManager.DISALLOW_UNMUTE_MICROPHONE,
71 UserManager.DISALLOW_ADJUST_VOLUME,
72 UserManager.DISALLOW_OUTGOING_CALLS,
73 UserManager.DISALLOW_SMS,
74 UserManager.DISALLOW_FUN,
75 UserManager.DISALLOW_CREATE_WINDOWS,
76 UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE,
77 UserManager.DISALLOW_OUTGOING_BEAM,
78 UserManager.DISALLOW_WALLPAPER,
79 UserManager.DISALLOW_SAFE_BOOT,
80 UserManager.ALLOW_PARENT_PROFILE_APP_LINKING,
81 UserManager.DISALLOW_RECORD_AUDIO,
82 };
83
84 /**
85 * Set of user restrictions, which can only be enforced by the system.
86 */
87 public static final Set<String> SYSTEM_CONTROLLED_USER_RESTRICTIONS = Sets.newArraySet(
88 UserManager.DISALLOW_RECORD_AUDIO);
89
90 /**
91 * Set of user restriction which we don't want to persist.
92 */
93 public static final Set<String> NON_PERSIST_USER_RESTRICTIONS = Sets.newArraySet(
94 UserManager.DISALLOW_RECORD_AUDIO);
95
96 public static void writeRestrictions(XmlSerializer serializer, Bundle restrictions,
97 String tag) throws IOException {
98 serializer.startTag(null, tag);
99 for (String key : USER_RESTRICTIONS) {
Makoto Onukia4f11972015-10-01 13:19:58 -0700100 if (restrictions.getBoolean(key)
101 && !NON_PERSIST_USER_RESTRICTIONS.contains(key)) {
102 serializer.attribute(null, key, "true");
103 }
104 }
105 serializer.endTag(null, tag);
106 }
107
108 public static void readRestrictions(XmlPullParser parser, Bundle restrictions)
109 throws IOException {
110 for (String key : USER_RESTRICTIONS) {
111 final String value = parser.getAttributeValue(null, key);
112 if (value != null) {
113 restrictions.putBoolean(key, Boolean.parseBoolean(value));
114 }
115 }
116 }
117
Makoto Onuki068c54a2015-10-13 14:34:03 -0700118 public static void merge(Bundle dest, Bundle in) {
119 if (in == null) {
120 return;
121 }
122 for (String key : in.keySet()) {
123 if (in.getBoolean(key, false)) {
124 dest.putBoolean(key, true);
125 }
126 }
127 }
128
Makoto Onuki4f160732015-10-27 17:15:38 -0700129 /**
130 * Takes a new use restriction set and the previous set, and apply the restrictions that have
131 * changed.
132 */
133 public static void applyUserRestrictions(Context context, int userId,
134 @Nullable Bundle newRestrictions, @Nullable Bundle prevRestrictions) {
135 if (newRestrictions == null) {
136 newRestrictions = Bundle.EMPTY;
137 }
138 if (prevRestrictions == null) {
139 prevRestrictions = Bundle.EMPTY;
140 }
141 for (String key : USER_RESTRICTIONS) {
142 final boolean newValue = newRestrictions.getBoolean(key);
143 final boolean prevValue = prevRestrictions.getBoolean(key);
144
145 if (newValue != prevValue) {
146 applyUserRestriction(context, userId, key, newValue);
147 }
148 }
149 }
150
151 private static void applyUserRestriction(Context context, int userId, String key,
152 boolean newValue) {
153 // When certain restrictions are cleared, we don't update the system settings,
154 // because these settings are changeable on the Settings UI and we don't know the original
155 // value -- for example LOCATION_MODE might have been off already when the restriction was
156 // set, and in that case even if the restriction is lifted, changing it to ON would be
157 // wrong. So just don't do anything in such a case. If the user hopes to enable location
158 // later, they can do it on the Settings UI.
159
160 final ContentResolver cr = context.getContentResolver();
161 final long id = Binder.clearCallingIdentity();
162 try {
163 switch (key) {
164 case UserManager.DISALLOW_UNMUTE_MICROPHONE:
165 IAudioService.Stub.asInterface(ServiceManager.getService(Context.AUDIO_SERVICE))
166 .setMicrophoneMute(newValue, context.getPackageName(), userId);
167 break;
168 case UserManager.DISALLOW_ADJUST_VOLUME:
169 IAudioService.Stub.asInterface(ServiceManager.getService(Context.AUDIO_SERVICE))
170 .setMasterMute(newValue, 0, context.getPackageName(), userId);
171 break;
172 case UserManager.DISALLOW_CONFIG_WIFI:
173 if (newValue) {
174 android.provider.Settings.Secure.putIntForUser(cr,
175 android.provider.Settings.Secure
176 .WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0, userId);
177 }
178 break;
179 case UserManager.DISALLOW_SHARE_LOCATION:
180 if (newValue) {
181 android.provider.Settings.Secure.putIntForUser(cr,
182 android.provider.Settings.Secure.LOCATION_MODE,
183 android.provider.Settings.Secure.LOCATION_MODE_OFF,
184 userId);
185 android.provider.Settings.Secure.putStringForUser(cr,
186 android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "",
187 userId);
188 }
189 // Send out notifications as some clients may want to reread the
190 // value which actually changed due to a restriction having been
191 // applied.
192 final String property =
193 android.provider.Settings.Secure.SYS_PROP_SETTING_VERSION;
194 long version = SystemProperties.getLong(property, 0) + 1;
195 SystemProperties.set(property, Long.toString(version));
196
197 final String name = android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
198 final Uri url = Uri.withAppendedPath(
199 android.provider.Settings.Secure.CONTENT_URI, name);
200 context.getContentResolver().notifyChange(url, null, true, userId);
201
202 break;
203 case UserManager.DISALLOW_DEBUGGING_FEATURES:
204 if (newValue) {
205 // Only disable adb if changing for system user, since it is global
206 // TODO: should this be admin user?
207 if (userId == UserHandle.USER_SYSTEM) {
208 android.provider.Settings.Global.putStringForUser(cr,
209 android.provider.Settings.Global.ADB_ENABLED, "0",
210 userId);
211 }
212 }
213 break;
214 case UserManager.ENSURE_VERIFY_APPS:
215 if (newValue) {
216 android.provider.Settings.Global.putStringForUser(
217 context.getContentResolver(),
218 android.provider.Settings.Global.PACKAGE_VERIFIER_ENABLE, "1",
219 userId);
220 android.provider.Settings.Global.putStringForUser(
221 context.getContentResolver(),
222 android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, "1",
223 userId);
224 }
225 break;
226 case UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES:
227 if (newValue) {
228 android.provider.Settings.Secure.putIntForUser(cr,
229 android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS, 0,
230 userId);
231 }
232 break;
233 }
234 } catch (RemoteException re) {
235 Slog.e(TAG, "Failed to talk to AudioService.", re);
236 } finally {
237 Binder.restoreCallingIdentity(id);
238 }
239 }
240
Makoto Onukia4f11972015-10-01 13:19:58 -0700241 public static void dumpRestrictions(PrintWriter pw, String prefix, Bundle restrictions) {
242 boolean noneSet = true;
243 if (restrictions != null) {
244 for (String key : restrictions.keySet()) {
245 if (restrictions.getBoolean(key, false)) {
246 pw.println(prefix + key);
247 noneSet = false;
248 }
249 }
Makoto Onuki068c54a2015-10-13 14:34:03 -0700250 if (noneSet) {
251 pw.println(prefix + "none");
252 }
253 } else {
254 pw.println(prefix + "null");
Makoto Onukia4f11972015-10-01 13:19:58 -0700255 }
256 }
257}