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