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