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.settings.enterprise; 18 19 import android.annotation.NonNull; 20 import android.annotation.UserIdInt; 21 import android.app.Activity; 22 import android.app.admin.DevicePolicyManager; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.res.ColorStateList; 27 import android.content.res.TypedArray; 28 import android.graphics.drawable.Drawable; 29 import android.os.Process; 30 import android.os.UserHandle; 31 import android.os.UserManager; 32 import android.util.IconDrawableFactory; 33 import android.view.LayoutInflater; 34 import android.view.View; 35 import android.view.ViewGroup; 36 import android.widget.ImageView; 37 import android.widget.TextView; 38 39 import androidx.annotation.VisibleForTesting; 40 import androidx.appcompat.app.AlertDialog; 41 42 import com.android.settings.R; 43 import com.android.settings.Settings; 44 import com.android.settings.Utils; 45 import com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminAdd; 46 import com.android.settingslib.RestrictedLockUtils; 47 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 48 import com.android.settingslib.RestrictedLockUtilsInternal; 49 50 import java.util.Objects; 51 52 /** 53 * Helper class for {@link ActionDisabledByAdminDialog} which sets up the dialog. 54 */ 55 public class ActionDisabledByAdminDialogHelper { 56 57 private static final String TAG = ActionDisabledByAdminDialogHelper.class.getName(); 58 @VisibleForTesting EnforcedAdmin mEnforcedAdmin; 59 private ViewGroup mDialogView; 60 private String mRestriction = null; 61 private Activity mActivity; 62 ActionDisabledByAdminDialogHelper(Activity activity)63 public ActionDisabledByAdminDialogHelper(Activity activity) { 64 mActivity = activity; 65 } 66 getEnforcementAdminUserId(@onNull EnforcedAdmin admin)67 private @UserIdInt int getEnforcementAdminUserId(@NonNull EnforcedAdmin admin) { 68 if (admin.user == null) { 69 return UserHandle.USER_NULL; 70 } else { 71 return admin.user.getIdentifier(); 72 } 73 } 74 getEnforcementAdminUserId()75 private @UserIdInt int getEnforcementAdminUserId() { 76 return getEnforcementAdminUserId(mEnforcedAdmin); 77 } 78 prepareDialogBuilder(String restriction, EnforcedAdmin enforcedAdmin)79 public AlertDialog.Builder prepareDialogBuilder(String restriction, 80 EnforcedAdmin enforcedAdmin) { 81 mEnforcedAdmin = enforcedAdmin; 82 mRestriction = restriction; 83 final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); 84 mDialogView = (ViewGroup) LayoutInflater.from(builder.getContext()).inflate( 85 R.layout.admin_support_details_dialog, null); 86 initializeDialogViews(mDialogView, mEnforcedAdmin.component, getEnforcementAdminUserId(), 87 mRestriction); 88 builder.setPositiveButton(R.string.okay, null).setView(mDialogView); 89 maybeSetLearnMoreButton(builder); 90 return builder; 91 } 92 93 @VisibleForTesting maybeSetLearnMoreButton(AlertDialog.Builder builder)94 void maybeSetLearnMoreButton(AlertDialog.Builder builder) { 95 // The "Learn more" button appears only if the restriction is enforced by an admin in the 96 // same profile group. Otherwise the admin package and its policies are not accessible to 97 // the current user. 98 final UserManager um = UserManager.get(mActivity.getApplicationContext()); 99 if (um.isSameProfileGroup(getEnforcementAdminUserId(mEnforcedAdmin), um.getUserHandle())) { 100 builder.setNeutralButton(R.string.learn_more, (dialog, which) -> { 101 showAdminPolicies(mEnforcedAdmin, mActivity); 102 mActivity.finish(); 103 }); 104 } 105 } 106 updateDialog(String restriction, EnforcedAdmin admin)107 public void updateDialog(String restriction, EnforcedAdmin admin) { 108 if (mEnforcedAdmin.equals(admin) && Objects.equals(mRestriction, restriction)) { 109 return; 110 } 111 mEnforcedAdmin = admin; 112 mRestriction = restriction; 113 initializeDialogViews(mDialogView, mEnforcedAdmin.component, getEnforcementAdminUserId(), 114 mRestriction); 115 } 116 initializeDialogViews(View root, ComponentName admin, int userId, String restriction)117 private void initializeDialogViews(View root, ComponentName admin, int userId, 118 String restriction) { 119 if (admin == null) { 120 return; 121 } 122 ImageView supportIconView = root.requireViewById(R.id.admin_support_icon); 123 if (!RestrictedLockUtilsInternal.isAdminInCurrentUserOrProfile(mActivity, admin) 124 || !RestrictedLockUtils.isCurrentUserOrProfile(mActivity, userId)) { 125 admin = null; 126 127 supportIconView.setImageDrawable( 128 mActivity.getDrawable(com.android.internal.R.drawable.ic_info)); 129 130 TypedArray ta = mActivity.obtainStyledAttributes(new int[]{android.R.attr.colorAccent}); 131 supportIconView.setImageTintList(ColorStateList.valueOf(ta.getColor(0, 0))); 132 ta.recycle(); 133 } else { 134 final Drawable badgedIcon = Utils.getBadgedIcon( 135 IconDrawableFactory.newInstance(mActivity), 136 mActivity.getPackageManager(), 137 admin.getPackageName(), 138 userId); 139 supportIconView.setImageDrawable(badgedIcon); 140 } 141 142 setAdminSupportTitle(root, restriction); 143 144 final UserHandle user; 145 if (userId == UserHandle.USER_NULL) { 146 user = null; 147 } else { 148 user = UserHandle.of(userId); 149 } 150 151 setAdminSupportDetails(mActivity, root, new EnforcedAdmin(admin, user)); 152 } 153 154 @VisibleForTesting setAdminSupportTitle(View root, String restriction)155 void setAdminSupportTitle(View root, String restriction) { 156 final TextView titleView = root.findViewById(R.id.admin_support_dialog_title); 157 if (titleView == null) { 158 return; 159 } 160 if (restriction == null) { 161 titleView.setText(R.string.disabled_by_policy_title); 162 return; 163 } 164 switch (restriction) { 165 case UserManager.DISALLOW_ADJUST_VOLUME: 166 titleView.setText(R.string.disabled_by_policy_title_adjust_volume); 167 break; 168 case UserManager.DISALLOW_OUTGOING_CALLS: 169 titleView.setText(R.string.disabled_by_policy_title_outgoing_calls); 170 break; 171 case UserManager.DISALLOW_SMS: 172 titleView.setText(R.string.disabled_by_policy_title_sms); 173 break; 174 case DevicePolicyManager.POLICY_DISABLE_CAMERA: 175 titleView.setText(R.string.disabled_by_policy_title_camera); 176 break; 177 case DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE: 178 titleView.setText(R.string.disabled_by_policy_title_screen_capture); 179 break; 180 case DevicePolicyManager.POLICY_SUSPEND_PACKAGES: 181 titleView.setText(R.string.disabled_by_policy_title_suspend_packages); 182 break; 183 default: 184 // Use general text if no specialized title applies 185 titleView.setText(R.string.disabled_by_policy_title); 186 } 187 } 188 189 @VisibleForTesting setAdminSupportDetails(final Activity activity, final View root, final EnforcedAdmin enforcedAdmin)190 void setAdminSupportDetails(final Activity activity, final View root, 191 final EnforcedAdmin enforcedAdmin) { 192 if (enforcedAdmin == null || enforcedAdmin.component == null) { 193 return; 194 } 195 196 final DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService( 197 Context.DEVICE_POLICY_SERVICE); 198 if (!RestrictedLockUtilsInternal.isAdminInCurrentUserOrProfile(activity, 199 enforcedAdmin.component) || !RestrictedLockUtils.isCurrentUserOrProfile( 200 activity, getEnforcementAdminUserId(enforcedAdmin))) { 201 enforcedAdmin.component = null; 202 } else { 203 if (enforcedAdmin.user == null) { 204 enforcedAdmin.user = UserHandle.of(UserHandle.myUserId()); 205 } 206 CharSequence supportMessage = null; 207 if (UserHandle.isSameApp(Process.myUid(), Process.SYSTEM_UID)) { 208 supportMessage = dpm.getShortSupportMessageForUser(enforcedAdmin.component, 209 getEnforcementAdminUserId(enforcedAdmin)); 210 } 211 if (supportMessage != null) { 212 final TextView textView = root.findViewById(R.id.admin_support_msg); 213 textView.setText(supportMessage); 214 } 215 } 216 } 217 218 @VisibleForTesting showAdminPolicies(final EnforcedAdmin enforcedAdmin, final Activity activity)219 void showAdminPolicies(final EnforcedAdmin enforcedAdmin, final Activity activity) { 220 final Intent intent = new Intent(); 221 if (enforcedAdmin.component != null) { 222 intent.setClass(activity, DeviceAdminAdd.class); 223 intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, 224 enforcedAdmin.component); 225 intent.putExtra(DeviceAdminAdd.EXTRA_CALLED_FROM_SUPPORT_DIALOG, true); 226 // DeviceAdminAdd class may need to run as managed profile. 227 activity.startActivityAsUser(intent, enforcedAdmin.user); 228 } else { 229 intent.setClass(activity, Settings.DeviceAdminSettingsActivity.class); 230 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 231 // Activity merges both managed profile and parent users 232 // admins so show as same user as this activity. 233 activity.startActivity(intent); 234 } 235 } 236 } 237