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.permissioncontroller.safetycenter.ui;
18 
19 import static android.os.Build.VERSION_CODES.TIRAMISU;
20 
21 import static com.android.permissioncontroller.safetycenter.SafetyCenterConstants.PERSONAL_PROFILE_SUFFIX;
22 import static com.android.permissioncontroller.safetycenter.SafetyCenterConstants.PRIVATE_PROFILE_SUFFIX;
23 import static com.android.permissioncontroller.safetycenter.SafetyCenterConstants.WORK_PROFILE_SUFFIX;
24 
25 import android.content.Context;
26 import android.os.UserHandle;
27 import android.os.UserManager;
28 import android.safetycenter.SafetyCenterStaticEntry;
29 import android.text.TextUtils;
30 import android.util.Log;
31 
32 import androidx.annotation.Nullable;
33 import androidx.annotation.RequiresApi;
34 import androidx.preference.Preference;
35 
36 import com.android.modules.utils.build.SdkLevel;
37 import com.android.permissioncontroller.safetycenter.ui.model.SafetyCenterViewModel;
38 import com.android.safetycenter.internaldata.SafetyCenterEntryId;
39 
40 /** A preference which displays a visual representation of a {@link SafetyCenterStaticEntry}. */
41 @RequiresApi(TIRAMISU)
42 public class StaticSafetyEntryPreference extends Preference implements ComparablePreference {
43 
44     private static final String TAG = StaticSafetyEntryPreference.class.getSimpleName();
45 
46     private final SafetyCenterStaticEntry mEntry;
47     private final SafetyCenterViewModel mViewModel;
48 
StaticSafetyEntryPreference( Context context, @Nullable Integer launchTaskId, SafetyCenterStaticEntry entry, @Nullable SafetyCenterEntryId entryId, SafetyCenterViewModel viewModel)49     public StaticSafetyEntryPreference(
50             Context context,
51             @Nullable Integer launchTaskId,
52             SafetyCenterStaticEntry entry,
53             @Nullable SafetyCenterEntryId entryId,
54             SafetyCenterViewModel viewModel) {
55         super(context);
56         mEntry = entry;
57         mViewModel = viewModel;
58         setTitle(entry.getTitle());
59         setSummary(entry.getSummary());
60         if (entry.getPendingIntent() != null) {
61             setOnPreferenceClickListener(
62                     unused -> {
63                         try {
64                             PendingIntentSender.send(mEntry.getPendingIntent(), launchTaskId);
65                         } catch (Exception ex) {
66                             Log.e(
67                                     TAG,
68                                     String.format(
69                                             "Failed to execute pending intent for static entry: %s",
70                                             mEntry),
71                                     ex);
72                         }
73 
74                         // SafetyCenterStaticEntry does not expose an ID, so we're unable to log
75                         // what source this static entry belonged to.
76                         mViewModel.getInteractionLogger().record(Action.STATIC_ENTRY_CLICKED);
77 
78                         return true;
79                     });
80         }
81         if (entryId != null) {
82             setupPreferenceKey(entryId);
83         }
84     }
85 
setupPreferenceKey(SafetyCenterEntryId entryId)86     private void setupPreferenceKey(SafetyCenterEntryId entryId) {
87         Context userContext = getContext()
88                 .createContextAsUser(UserHandle.of(entryId.getUserId()), /* flags= */ 0);
89         UserManager userUserManager = userContext.getSystemService(UserManager.class);
90         if (userUserManager.isManagedProfile()) {
91             setKey(String.format("%s_%s", entryId.getSafetySourceId(), WORK_PROFILE_SUFFIX));
92         } else if (isPrivateProfileSupported() && userUserManager.isPrivateProfile()) {
93             setKey(String.format("%s_%s", entryId.getSafetySourceId(), PRIVATE_PROFILE_SUFFIX));
94         } else {
95             setKey(String.format("%s_%s", entryId.getSafetySourceId(), PERSONAL_PROFILE_SUFFIX));
96         }
97     }
98 
isPrivateProfileSupported()99     private Boolean isPrivateProfileSupported() {
100         return SdkLevel.isAtLeastV()
101                 && com.android.permission.flags.Flags.privateProfileSupported()
102                 && android.os.Flags.allowPrivateProfile();
103     }
104 
105     @Override
isSameItem(Preference preference)106     public boolean isSameItem(Preference preference) {
107         return preference instanceof StaticSafetyEntryPreference
108                 && TextUtils.equals(
109                         mEntry.getTitle(),
110                         ((StaticSafetyEntryPreference) preference).mEntry.getTitle());
111     }
112 
113     @Override
hasSameContents(Preference preference)114     public boolean hasSameContents(Preference preference) {
115         return preference instanceof StaticSafetyEntryPreference
116                 && mEntry.equals(((StaticSafetyEntryPreference) preference).mEntry);
117     }
118 }
119