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.enterprise; 18 19 import static java.util.Objects.requireNonNull; 20 21 import android.app.admin.DevicePolicyManager; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.PackageManager; 26 import android.net.Uri; 27 import android.os.UserHandle; 28 import android.os.UserManager; 29 30 import com.android.internal.annotations.VisibleForTesting; 31 import com.android.tv.settings.library.settingslib.RestrictedLockUtils.EnforcedAdmin; 32 33 /** 34 * Helper class meant to set up the "Learn more" button in the action disabled dialog. 35 */ 36 public abstract class ActionDisabledLearnMoreButtonLauncher { 37 38 public static ResolveActivityChecker DEFAULT_RESOLVE_ACTIVITY_CHECKER = 39 (packageManager, url, userHandle) -> packageManager.resolveActivityAsUser( 40 createLearnMoreIntent(url), 41 PackageManager.MATCH_DEFAULT_ONLY, 42 userHandle.getIdentifier()) != null; 43 44 interface ResolveActivityChecker { canResolveActivityAsUser( PackageManager packageManager, String url, UserHandle userHandle)45 boolean canResolveActivityAsUser( 46 PackageManager packageManager, String url, UserHandle userHandle); 47 } 48 49 /** 50 * Sets up a "learn more" button which shows a screen with device policy settings 51 */ setupLearnMoreButtonToShowAdminPolicies(Context context, int enforcementAdminUserId, EnforcedAdmin enforcedAdmin)52 public final void setupLearnMoreButtonToShowAdminPolicies(Context context, 53 int enforcementAdminUserId, EnforcedAdmin enforcedAdmin) { 54 requireNonNull(context, "context cannot be null"); 55 requireNonNull(enforcedAdmin, "enforcedAdmin cannot be null"); 56 57 // The "Learn more" button appears only if the restriction is enforced by an admin in the 58 // same profile group or by the device owner. Otherwise the admin package and its policies 59 // are not accessible to the current user. 60 if (isSameProfileGroup(context, enforcementAdminUserId) 61 || isEnforcedByDeviceOwnerOnSystemUserMode(context, enforcementAdminUserId)) { 62 setLearnMoreButton(() -> showAdminPolicies(context, enforcedAdmin)); 63 } 64 } 65 66 /** 67 * Sets up a "learn more" button which launches a help page 68 */ setupLearnMoreButtonToLaunchHelpPage( Context context, String url, UserHandle userHandle)69 public final void setupLearnMoreButtonToLaunchHelpPage( 70 Context context, String url, UserHandle userHandle) { 71 requireNonNull(context, "context cannot be null"); 72 requireNonNull(url, "url cannot be null"); 73 74 setLearnMoreButton(() -> showHelpPage(context, url, userHandle)); 75 } 76 77 /** 78 * Sets the "learning more" button. 79 * 80 * @param action action to be run when the button is tapped. 81 */ setLearnMoreButton(Runnable action)82 public abstract void setLearnMoreButton(Runnable action); 83 84 /** 85 * Launches the settings page with info about the given admin. 86 */ launchShowAdminPolicies(Context context, UserHandle user, ComponentName admin)87 protected abstract void launchShowAdminPolicies(Context context, UserHandle user, 88 ComponentName admin); 89 90 /** 91 * Launches the settings page that shows all admins. 92 */ launchShowAdminSettings(Context context)93 protected abstract void launchShowAdminSettings(Context context); 94 95 /** 96 * Callback to finish the activity associated with the launcher. 97 */ finishSelf()98 protected void finishSelf() { 99 } 100 101 @VisibleForTesting isSameProfileGroup(Context context, int enforcementAdminUserId)102 protected boolean isSameProfileGroup(Context context, int enforcementAdminUserId) { 103 UserManager um = context.getSystemService(UserManager.class); 104 105 return um.isSameProfileGroup(enforcementAdminUserId, um.getProcessUserId()); 106 } 107 isEnforcedByDeviceOwnerOnSystemUserMode( Context context, int enforcementAdminUserId)108 private boolean isEnforcedByDeviceOwnerOnSystemUserMode( 109 Context context, int enforcementAdminUserId) { 110 if (enforcementAdminUserId != UserHandle.USER_SYSTEM) { 111 return false; 112 } 113 DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 114 return enforcementAdminUserId == dpm.getDeviceOwnerUserId(); 115 } 116 117 /** 118 * Shows the help page using the given {@code url}. 119 */ 120 @VisibleForTesting showHelpPage(Context context, String url, UserHandle userHandle)121 public void showHelpPage(Context context, String url, UserHandle userHandle) { 122 context.startActivityAsUser(createLearnMoreIntent(url), userHandle); 123 finishSelf(); 124 } 125 canLaunchHelpPage( PackageManager packageManager, String url, UserHandle userHandle, ResolveActivityChecker resolveActivityChecker)126 protected final boolean canLaunchHelpPage( 127 PackageManager packageManager, 128 String url, 129 UserHandle userHandle, 130 ResolveActivityChecker resolveActivityChecker) { 131 return resolveActivityChecker.canResolveActivityAsUser(packageManager, url, userHandle); 132 } 133 showAdminPolicies(Context context, EnforcedAdmin enforcedAdmin)134 private void showAdminPolicies(Context context, EnforcedAdmin enforcedAdmin) { 135 if (enforcedAdmin.component != null) { 136 launchShowAdminPolicies(context, enforcedAdmin.user, enforcedAdmin.component); 137 } else { 138 launchShowAdminSettings(context); 139 } 140 finishSelf(); 141 } 142 createLearnMoreIntent(String url)143 private static Intent createLearnMoreIntent(String url) { 144 return new Intent(Intent.ACTION_VIEW, Uri.parse(url)).setFlags( 145 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 146 } 147 } 148