1 /*
2  * Copyright (C) 2018 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.car.settings.development;
18 
19 import android.app.ActivityManager;
20 import android.car.userlib.CarUserManagerHelper;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.content.pm.PackageManager;
24 import android.os.Build;
25 import android.os.UserHandle;
26 import android.os.UserManager;
27 import android.provider.Settings;
28 
29 import com.android.car.settings.R;
30 import com.android.settingslib.development.DevelopmentSettingsEnabler;
31 
32 /**
33  * A utility to set/check development settings mode.
34  *
35  * <p>Shared logic with {@link com.android.settingslib.development.DevelopmentSettingsEnabler} with
36  * modifications to use CarUserManagerHelper instead of UserManager.
37  */
38 public class DevelopmentSettingsUtil {
39 
DevelopmentSettingsUtil()40     private DevelopmentSettingsUtil() {
41     }
42 
43     /**
44      * Sets the global toggle for developer settings and sends out a local broadcast to notify other
45      * of this change.
46      */
setDevelopmentSettingsEnabled(Context context, boolean enable)47     public static void setDevelopmentSettingsEnabled(Context context, boolean enable) {
48         Settings.Global.putInt(context.getContentResolver(),
49                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, enable ? 1 : 0);
50 
51         // Used to enable developer options module.
52         ComponentName targetName = ComponentName.unflattenFromString(
53                 context.getString(R.string.config_dev_options_module));
54         setDeveloperOptionsEnabledState(context, targetName, showDeveloperOptions(context));
55     }
56 
57     /**
58      * Checks that the development settings should be enabled. Returns true if global toggle is set,
59      * debugging is allowed for user, and the user is an admin or a demo user.
60      */
isDevelopmentSettingsEnabled(Context context, CarUserManagerHelper carUserManagerHelper)61     public static boolean isDevelopmentSettingsEnabled(Context context,
62             CarUserManagerHelper carUserManagerHelper) {
63         boolean settingEnabled = Settings.Global.getInt(context.getContentResolver(),
64                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, Build.IS_ENG ? 1 : 0) != 0;
65         boolean hasRestriction = carUserManagerHelper.hasUserRestriction(
66                 UserManager.DISALLOW_DEBUGGING_FEATURES,
67                 carUserManagerHelper.getCurrentProcessUserInfo());
68         boolean isAdminOrDemo = carUserManagerHelper.isCurrentProcessAdminUser()
69                 || carUserManagerHelper.isCurrentProcessDemoUser();
70         return isAdminOrDemo && !hasRestriction && settingEnabled;
71     }
72 
73     /** Checks whether the device is provisioned or not. */
isDeviceProvisioned(Context context)74     public static boolean isDeviceProvisioned(Context context) {
75         return Settings.Global.getInt(context.getContentResolver(),
76                 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
77     }
78 
showDeveloperOptions(Context context)79     private static boolean showDeveloperOptions(Context context) {
80         CarUserManagerHelper carUserManagerHelper = new CarUserManagerHelper(context);
81         boolean showDev = DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context)
82                 && !isMonkeyRunning();
83         boolean isAdminOrDemo = carUserManagerHelper.isCurrentProcessAdminUser()
84                 || carUserManagerHelper.isCurrentProcessDemoUser();
85         if (UserHandle.MU_ENABLED && !isAdminOrDemo) {
86             showDev = false;
87         }
88 
89         return showDev;
90     }
91 
setDeveloperOptionsEnabledState(Context context, ComponentName component, boolean enabled)92     private static void setDeveloperOptionsEnabledState(Context context, ComponentName component,
93             boolean enabled) {
94         PackageManager pm = context.getPackageManager();
95         int state = pm.getComponentEnabledSetting(component);
96         boolean isEnabled = state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
97         if (isEnabled != enabled || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
98             pm.setComponentEnabledSetting(component, enabled
99                             ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
100                             : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
101                     PackageManager.DONT_KILL_APP);
102         }
103     }
104 
isMonkeyRunning()105     private static boolean isMonkeyRunning() {
106         return ActivityManager.isUserAMonkey();
107     }
108 }
109