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.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.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 
56         // The "Learn more" button appears only if the restriction is enforced by an admin in the
57         // same profile group or by the device owner. Otherwise the admin package and its policies
58         // are not accessible to the current user.
59         if (isSameProfileGroup(context, enforcementAdminUserId)
60                 || isEnforcedByDeviceOwnerOnSystemUserMode(context, enforcementAdminUserId)) {
61             setLearnMoreButton(() -> showAdminPolicies(context, enforcedAdmin));
62         }
63     }
64 
65     /**
66      * Sets up a "learn more" button which launches a help page
67      */
setupLearnMoreButtonToLaunchHelpPage( Context context, String url, UserHandle userHandle)68     public final void setupLearnMoreButtonToLaunchHelpPage(
69             Context context, String url, UserHandle userHandle) {
70         requireNonNull(context, "context cannot be null");
71         requireNonNull(url, "url cannot be null");
72 
73         setLearnMoreButton(() -> showHelpPage(context, url, userHandle));
74     }
75 
76     /**
77      * Sets the "learning more" button.
78      *
79      * @param action action to be run when the button is tapped.
80      */
setLearnMoreButton(Runnable action)81     public abstract void setLearnMoreButton(Runnable action);
82 
83     /**
84      * Launches the settings page with info about the given admin.
85      */
launchShowAdminPolicies(Context context, UserHandle user, ComponentName admin)86     protected abstract void launchShowAdminPolicies(Context context, UserHandle user,
87             ComponentName admin);
88 
89     /**
90      * Launches the settings page that shows all admins.
91      */
launchShowAdminSettings(Context context)92     protected abstract void launchShowAdminSettings(Context context);
93 
94     /**
95      * Callback to finish the activity associated with the launcher.
96      */
finishSelf()97     protected void finishSelf() {
98     }
99 
100     @VisibleForTesting
isSameProfileGroup(Context context, int enforcementAdminUserId)101     protected boolean isSameProfileGroup(Context context, int enforcementAdminUserId) {
102         UserManager um = context.getSystemService(UserManager.class);
103 
104         return um.isSameProfileGroup(enforcementAdminUserId, um.getProcessUserId());
105     }
106 
isEnforcedByDeviceOwnerOnSystemUserMode( Context context, int enforcementAdminUserId)107     private boolean isEnforcedByDeviceOwnerOnSystemUserMode(
108             Context context, int enforcementAdminUserId) {
109         if (enforcementAdminUserId != UserHandle.USER_SYSTEM) {
110             return false;
111         }
112         DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
113         return enforcementAdminUserId == dpm.getDeviceOwnerUserId();
114     }
115 
116     /**
117      * Shows the help page using the given {@code url}.
118      */
119     @VisibleForTesting
showHelpPage(Context context, String url, UserHandle userHandle)120     public void showHelpPage(Context context, String url, UserHandle userHandle) {
121         context.startActivityAsUser(createLearnMoreIntent(url), userHandle);
122         finishSelf();
123     }
124 
canLaunchHelpPage( PackageManager packageManager, String url, UserHandle userHandle, ResolveActivityChecker resolveActivityChecker)125     protected final boolean canLaunchHelpPage(
126             PackageManager packageManager,
127             String url,
128             UserHandle userHandle,
129             ResolveActivityChecker resolveActivityChecker) {
130         return resolveActivityChecker.canResolveActivityAsUser(packageManager, url, userHandle);
131     }
132 
showAdminPolicies(Context context, EnforcedAdmin enforcedAdmin)133     private void showAdminPolicies(Context context, EnforcedAdmin enforcedAdmin) {
134         if (enforcedAdmin != null && enforcedAdmin.component != null) {
135             launchShowAdminPolicies(context, enforcedAdmin.user, enforcedAdmin.component);
136         } else {
137             launchShowAdminSettings(context);
138         }
139         finishSelf();
140     }
141 
createLearnMoreIntent(String url)142     private static Intent createLearnMoreIntent(String url) {
143         return new Intent(Intent.ACTION_VIEW, Uri.parse(url)).setFlags(
144                 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
145     }
146 }
147