1 /*
2  * Copyright (C) 2021 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.tv.settings.library.settingslib;
18 
19 import android.app.admin.DevicePolicyManager;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.pm.PackageManager;
24 import android.os.UserHandle;
25 import android.os.UserManager;
26 import android.provider.Settings;
27 
28 import androidx.annotation.Nullable;
29 
30 import java.util.Objects;
31 
32 /**
33  * Utility class to host methods usable in adding a restricted padlock icon and showing admin
34  * support message dialog.
35  */
36 public class RestrictedLockUtils {
getProfileOrDeviceOwner( Context context, UserHandle user)37     public static EnforcedAdmin getProfileOrDeviceOwner(
38             Context context, UserHandle user) {
39         return getProfileOrDeviceOwner(context, null, user);
40     }
41 
getProfileOrDeviceOwner( Context context, String enforcedRestriction, UserHandle user)42     public static RestrictedLockUtils.EnforcedAdmin getProfileOrDeviceOwner(
43             Context context, String enforcedRestriction, UserHandle user) {
44         if (user == null) {
45             return null;
46         }
47         final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
48         if (dpm == null) {
49             return null;
50         }
51 
52         Context userContext;
53         try {
54             userContext = context.createPackageContextAsUser(context.getPackageName(), 0, user);
55         } catch (PackageManager.NameNotFoundException e) {
56             throw new IllegalStateException(e);
57         }
58 
59         ComponentName adminComponent = userContext.getSystemService(
60                 DevicePolicyManager.class).getProfileOwner();
61         if (adminComponent != null) {
62             return new EnforcedAdmin(adminComponent, enforcedRestriction, user);
63         }
64         if (Objects.equals(dpm.getDeviceOwnerUser(), user)) {
65             adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();
66             if (adminComponent != null) {
67                 return new EnforcedAdmin(adminComponent, enforcedRestriction, user);
68             }
69         }
70         return null;
71     }
72 
73     /**
74      * Send the intent to trigger the {@code android.settings.ShowAdminSupportDetailsDialog}.
75      */
sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin)76     public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
77         final Intent intent = getShowAdminSupportDetailsIntent(context, admin);
78         int targetUserId = UserHandle.myUserId();
79         if (admin != null) {
80             if (admin.user != null
81                     && isCurrentUserOrProfile(context, admin.user.getIdentifier())) {
82                 targetUserId = admin.user.getIdentifier();
83             }
84             intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, admin.enforcedRestriction);
85         }
86         context.startActivityAsUser(intent, UserHandle.of(targetUserId));
87     }
88 
getShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin)89     public static Intent getShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
90         final Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
91         if (admin != null) {
92             if (admin.component != null) {
93                 intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin.component);
94             }
95             intent.putExtra(Intent.EXTRA_USER, admin.user);
96         }
97         return intent;
98     }
99 
isCurrentUserOrProfile(Context context, int userId)100     public static boolean isCurrentUserOrProfile(Context context, int userId) {
101         UserManager um = context.getSystemService(UserManager.class);
102         return um.getUserProfiles().contains(UserHandle.of(userId));
103     }
104 
105     public static class EnforcedAdmin {
106         @Nullable
107         public ComponentName component = null;
108         /**
109          * The restriction enforced by admin. It could be any user restriction or policy like
110          * {@link DevicePolicyManager#POLICY_DISABLE_CAMERA}.
111          */
112         @Nullable
113         public String enforcedRestriction = null;
114         @Nullable
115         public UserHandle user = null;
116 
117         // We use this to represent the case where a policy is enforced by multiple admins.
118         public final static RestrictedLockUtils.EnforcedAdmin MULTIPLE_ENFORCED_ADMIN =
119                 new EnforcedAdmin();
120 
createDefaultEnforcedAdminWithRestriction( String enforcedRestriction)121         public static EnforcedAdmin createDefaultEnforcedAdminWithRestriction(
122                 String enforcedRestriction) {
123             EnforcedAdmin enforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
124             enforcedAdmin.enforcedRestriction = enforcedRestriction;
125             return enforcedAdmin;
126         }
127 
EnforcedAdmin(ComponentName component, UserHandle user)128         public EnforcedAdmin(ComponentName component, UserHandle user) {
129             this.component = component;
130             this.user = user;
131         }
132 
EnforcedAdmin(ComponentName component, String enforcedRestriction, UserHandle user)133         public EnforcedAdmin(ComponentName component, String enforcedRestriction, UserHandle user) {
134             this.component = component;
135             this.enforcedRestriction = enforcedRestriction;
136             this.user = user;
137         }
138 
EnforcedAdmin(EnforcedAdmin other)139         public EnforcedAdmin(EnforcedAdmin other) {
140             if (other == null) {
141                 throw new IllegalArgumentException();
142             }
143             this.component = other.component;
144             this.enforcedRestriction = other.enforcedRestriction;
145             this.user = other.user;
146         }
147 
EnforcedAdmin()148         public EnforcedAdmin() {
149         }
150 
151         /**
152          * Combines two {@link EnforcedAdmin} into one: if one of them is null, then just return
153          * the other. If both of them are the same, then return that. Otherwise return the symbolic
154          * {@link #MULTIPLE_ENFORCED_ADMIN}
155          */
combine(EnforcedAdmin admin1, EnforcedAdmin admin2)156         public static EnforcedAdmin combine(EnforcedAdmin admin1, EnforcedAdmin admin2) {
157             if (admin1 == null) {
158                 return admin2;
159             }
160             if (admin2 == null) {
161                 return admin1;
162             }
163             if (admin1.equals(admin2)) {
164                 return admin1;
165             }
166             if (!admin1.enforcedRestriction.equals(admin2.enforcedRestriction)) {
167                 throw new IllegalArgumentException(
168                         "Admins with different restriction cannot be combined");
169             }
170             return MULTIPLE_ENFORCED_ADMIN;
171         }
172 
173         @Override
equals(Object o)174         public boolean equals(Object o) {
175             if (this == o) return true;
176             if (o == null || getClass() != o.getClass()) return false;
177             EnforcedAdmin that = (EnforcedAdmin) o;
178             return Objects.equals(user, that.user) &&
179                     Objects.equals(component, that.component) &&
180                     Objects.equals(enforcedRestriction, that.enforcedRestriction);
181         }
182 
183         @Override
hashCode()184         public int hashCode() {
185             return Objects.hash(component, enforcedRestriction, user);
186         }
187 
188         @Override
toString()189         public String toString() {
190             return "EnforcedAdmin{" +
191                     "component=" + component +
192                     ", enforcedRestriction='" + enforcedRestriction +
193                     ", user=" + user +
194                     '}';
195         }
196     }
197 }
198 
199