• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.safetycenter;
18 
19 import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED;
20 
21 import android.app.PendingIntent;
22 import android.app.settings.SettingsEnums;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.os.UserHandle;
26 import android.os.UserManager;
27 import android.safetycenter.SafetyEvent;
28 import android.safetycenter.SafetySourceData;
29 import android.safetycenter.SafetySourceIssue;
30 import android.safetycenter.SafetySourceStatus;
31 import android.safetycenter.SafetySourceStatus.IconAction;
32 
33 import com.android.settings.R;
34 import com.android.settings.flags.Flags;
35 import com.android.settings.security.ScreenLockPreferenceDetailsUtils;
36 import com.android.settingslib.RestrictedLockUtils;
37 import com.android.settingslib.RestrictedLockUtilsInternal;
38 
39 /** Lock Screen Safety Source for Safety Center. */
40 public final class LockScreenSafetySource {
41 
42     public static final String SAFETY_SOURCE_ID = "AndroidLockScreen";
43     public static final String NO_SCREEN_LOCK_ISSUE_ID = "NoScreenLockIssue";
44     public static final String NO_SCREEN_LOCK_ISSUE_TYPE_ID = "NoScreenLockIssueType";
45     public static final String SET_SCREEN_LOCK_ACTION_ID = "SetScreenLockAction";
46 
47     private static final int REQUEST_CODE_SCREEN_LOCK = 1;
48     private static final int REQUEST_CODE_SCREEN_LOCK_SETTINGS = 2;
49 
LockScreenSafetySource()50     private LockScreenSafetySource() {}
51 
52     /** Sets lock screen safety data for Safety Center. */
setSafetySourceData( Context context, ScreenLockPreferenceDetailsUtils screenLockPreferenceDetailsUtils, SafetyEvent safetyEvent)53     public static void setSafetySourceData(
54             Context context,
55             ScreenLockPreferenceDetailsUtils screenLockPreferenceDetailsUtils,
56             SafetyEvent safetyEvent) {
57         if (!SafetyCenterManagerWrapper.get().isEnabled(context)) {
58             return;
59         }
60 
61         UserManager userManager = context.getSystemService(UserManager.class);
62         if (userManager != null && userManager.isProfile()) {
63             return; // LockScreen source only supports primary profile.
64         }
65 
66         if (!screenLockPreferenceDetailsUtils.isAvailable()) {
67             SafetyCenterManagerWrapper.get()
68                     .setSafetySourceData(
69                             context, SAFETY_SOURCE_ID, /* safetySourceData= */ null, safetyEvent);
70             return;
71         }
72 
73         final int userId = UserHandle.myUserId();
74         final RestrictedLockUtils.EnforcedAdmin admin =
75                 RestrictedLockUtilsInternal.checkIfPasswordQualityIsSet(context, userId);
76         final PendingIntent pendingIntent =
77                 createPendingIntent(
78                         context,
79                         screenLockPreferenceDetailsUtils.getLaunchChooseLockGenericFragmentIntent(
80                                 SettingsEnums.SAFETY_CENTER),
81                         REQUEST_CODE_SCREEN_LOCK);
82         final IconAction gearMenuIconAction =
83                 createGearMenuIconAction(context, screenLockPreferenceDetailsUtils);
84         final boolean lockScreenAllowedByAdmin =
85                 !screenLockPreferenceDetailsUtils.isPasswordQualityManaged(userId, admin);
86         final boolean isLockPatternSecure = screenLockPreferenceDetailsUtils.isLockPatternSecure();
87         final int severityLevel =
88                 lockScreenAllowedByAdmin
89                         ? isLockPatternSecure
90                                 ? SafetySourceData.SEVERITY_LEVEL_INFORMATION
91                                 : SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION
92                         : SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED;
93 
94         final SafetySourceStatus status =
95                 new SafetySourceStatus.Builder(
96                                 context.getString(R.string.unlock_set_unlock_launch_picker_title),
97                                 lockScreenAllowedByAdmin
98                                         ? getScreenLockSummary(screenLockPreferenceDetailsUtils)
99                                         : context.getString(R.string.disabled_by_policy_title),
100                                 severityLevel)
101                         .setPendingIntent(lockScreenAllowedByAdmin ? pendingIntent : null)
102                         .setEnabled(lockScreenAllowedByAdmin)
103                         .setIconAction(lockScreenAllowedByAdmin ? gearMenuIconAction : null)
104                         .build();
105         final SafetySourceData.Builder safetySourceDataBuilder =
106                 new SafetySourceData.Builder().setStatus(status);
107         if (lockScreenAllowedByAdmin && !isLockPatternSecure) {
108             safetySourceDataBuilder.addIssue(createNoScreenLockIssue(context, pendingIntent));
109         }
110         final SafetySourceData safetySourceData = safetySourceDataBuilder.build();
111 
112         SafetyCenterManagerWrapper.get()
113                 .setSafetySourceData(context, SAFETY_SOURCE_ID, safetySourceData, safetyEvent);
114     }
115 
getScreenLockSummary( ScreenLockPreferenceDetailsUtils screenLockPreferenceDetailsUtils)116     private static String getScreenLockSummary(
117             ScreenLockPreferenceDetailsUtils screenLockPreferenceDetailsUtils) {
118         String summary = screenLockPreferenceDetailsUtils.getSummary(UserHandle.myUserId());
119         return summary != null ? summary : "";
120     }
121 
122     /** Notifies Safety Center of a change in lock screen settings. */
onLockScreenChange(Context context)123     public static void onLockScreenChange(Context context) {
124         setSafetySourceData(
125                 context,
126                 new ScreenLockPreferenceDetailsUtils(context),
127                 new SafetyEvent.Builder(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build());
128 
129         // Also send refreshed safety center data for biometrics, since changing lockscreen settings
130         // can unset biometrics.
131         if (Flags.biometricsOnboardingEducation()) {
132             FaceSafetySource.onBiometricsChanged(context);
133             FingerprintSafetySource.onBiometricsChanged(context);
134             WearSafetySource.onBiometricsChanged(context);
135         } else {
136             BiometricsSafetySource.onBiometricsChanged(context);
137         }
138     }
139 
createGearMenuIconAction( Context context, ScreenLockPreferenceDetailsUtils screenLockPreferenceDetailsUtils)140     private static IconAction createGearMenuIconAction(
141             Context context, ScreenLockPreferenceDetailsUtils screenLockPreferenceDetailsUtils) {
142         return screenLockPreferenceDetailsUtils.shouldShowGearMenu()
143                 ? new IconAction(
144                         IconAction.ICON_TYPE_GEAR,
145                         createPendingIntent(
146                                 context,
147                                 screenLockPreferenceDetailsUtils.getLaunchScreenLockSettingsIntent(
148                                         SettingsEnums.SAFETY_CENTER),
149                                 REQUEST_CODE_SCREEN_LOCK_SETTINGS))
150                 : null;
151     }
152 
createPendingIntent( Context context, Intent intent, int requestCode)153     private static PendingIntent createPendingIntent(
154             Context context, Intent intent, int requestCode) {
155         return PendingIntent.getActivity(
156                 context, requestCode, intent, PendingIntent.FLAG_IMMUTABLE);
157     }
158 
createNoScreenLockIssue( Context context, PendingIntent pendingIntent)159     private static SafetySourceIssue createNoScreenLockIssue(
160             Context context, PendingIntent pendingIntent) {
161         final SafetySourceIssue.Action action =
162                 new SafetySourceIssue.Action.Builder(
163                                 SET_SCREEN_LOCK_ACTION_ID,
164                                 context.getString(R.string.no_screen_lock_issue_action_label),
165                                 pendingIntent)
166                         .build();
167         // Custom notification deliberately has zero actions
168         final SafetySourceIssue.Notification customNotification =
169                 new SafetySourceIssue.Notification.Builder(
170                                 context.getString(R.string.no_screen_lock_issue_notification_title),
171                                 context.getString(R.string.no_screen_lock_issue_notification_text))
172                         .build();
173         return new SafetySourceIssue.Builder(
174                         NO_SCREEN_LOCK_ISSUE_ID,
175                         context.getString(R.string.no_screen_lock_issue_title),
176                         context.getString(R.string.no_screen_lock_issue_summary),
177                         SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION,
178                         NO_SCREEN_LOCK_ISSUE_TYPE_ID)
179                 .setIssueCategory(SafetySourceIssue.ISSUE_CATEGORY_DEVICE)
180                 .addAction(action)
181                 .setIssueActionability(SafetySourceIssue.ISSUE_ACTIONABILITY_MANUAL)
182                 .setCustomNotification(customNotification)
183                 .setNotificationBehavior(SafetySourceIssue.NOTIFICATION_BEHAVIOR_DELAYED)
184                 .build();
185     }
186 }
187