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.car.settings.privacy;
18 
19 import android.car.drivingstate.CarUxRestrictions;
20 import android.content.Context;
21 import android.hardware.SensorPrivacyManager;
22 
23 import androidx.preference.PreferenceCategory;
24 
25 import com.android.car.settings.R;
26 import com.android.car.settings.common.FragmentController;
27 import com.android.car.ui.preference.CarUiPreference;
28 import com.android.internal.annotations.VisibleForTesting;
29 import com.android.settingslib.applications.RecentAppOpsAccess;
30 
31 import java.util.HashSet;
32 import java.util.List;
33 import java.util.Set;
34 
35 /**
36  * This controller displays a list of apps that recently access the camera. Only non-system apps
37  * are displayed.
38  */
39 public class CameraRecentAccessesPreferenceController extends
40         CameraPrivacyBasePreferenceController<PreferenceCategory> {
41 
42     private final Set<CarUiPreference> mAddedPreferences = new HashSet<>();
43 
44     private final RecentAppOpsAccess mRecentCameraAccesses;
45     private final int mRecentAppsMaxCount;
46 
CameraRecentAccessesPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)47     public CameraRecentAccessesPreferenceController(Context context, String preferenceKey,
48             FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
49         this(context, preferenceKey, fragmentController, uxRestrictions,
50                 RecentAppOpsAccess.createForCamera(context),
51                 context.getResources()
52                         .getInteger(R.integer.recent_camera_access_apps_list_count),
53                 SensorPrivacyManager.getInstance(context));
54     }
55 
56 
57     @VisibleForTesting
CameraRecentAccessesPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions, RecentAppOpsAccess recentCameraAccesses, int recentAppsMaxCount, SensorPrivacyManager sensorPrivacyManager)58     CameraRecentAccessesPreferenceController(Context context, String preferenceKey,
59             FragmentController fragmentController, CarUxRestrictions uxRestrictions,
60             RecentAppOpsAccess recentCameraAccesses, int recentAppsMaxCount,
61             SensorPrivacyManager sensorPrivacyManager) {
62         super(context, preferenceKey, fragmentController, uxRestrictions, sensorPrivacyManager);
63         mRecentCameraAccesses = recentCameraAccesses;
64         mRecentAppsMaxCount = recentAppsMaxCount;
65     }
66 
67 
68     @Override
getPreferenceType()69     protected Class<PreferenceCategory> getPreferenceType() {
70         return PreferenceCategory.class;
71     }
72 
73     @Override
updateState(PreferenceCategory preference)74     public void updateState(PreferenceCategory preference) {
75         super.updateState(preference);
76         if (getSensorPrivacyManager().isSensorPrivacyEnabled(
77                 SensorPrivacyManager.Sensors.CAMERA)) {
78             getPreference().setVisible(false);
79             return;
80         }
81         getPreference().setVisible(true);
82         List<RecentAppOpsAccess.Access> sortedRecentCameraAccesses = loadData();
83         updateUi(sortedRecentCameraAccesses);
84     }
85 
loadData()86     private List<RecentAppOpsAccess.Access> loadData() {
87         return mRecentCameraAccesses.getAppListSorted(/* showSystem= */ false);
88     }
89 
hasAtLeastOneRecentAppAccess()90     private boolean hasAtLeastOneRecentAppAccess() {
91         return !mRecentCameraAccesses.getAppListSorted(/* showSystem= */ true).isEmpty();
92     }
93 
updateUi(List<RecentAppOpsAccess.Access> sortedRecentCameraAccesses)94     private void updateUi(List<RecentAppOpsAccess.Access> sortedRecentCameraAccesses) {
95         // remove any already added preferences
96         for (CarUiPreference addedPreference : mAddedPreferences) {
97             getPreference().removePreference(addedPreference);
98         }
99         mAddedPreferences.clear();
100 
101         if (sortedRecentCameraAccesses.isEmpty()) {
102             CarUiPreference emptyPreference = createNoRecentAccessPreference();
103             getPreference().addPreference(emptyPreference);
104             mAddedPreferences.add(emptyPreference);
105         } else {
106             int count = Math.min(sortedRecentCameraAccesses.size(), mRecentAppsMaxCount);
107             for (int i = 0; i < count; i++) {
108                 RecentAppOpsAccess.Access request = sortedRecentCameraAccesses.get(i);
109                 CarUiPreference appPreference = CameraRecentAccessUtil.createAppPreference(
110                         getContext(),
111                         request);
112                 getPreference().addPreference(appPreference);
113                 mAddedPreferences.add(appPreference);
114             }
115         }
116 
117         if (hasAtLeastOneRecentAppAccess()) {
118             CarUiPreference viewAllPreference = createViewAllPreference();
119             getPreference().addPreference(viewAllPreference);
120             mAddedPreferences.add(viewAllPreference);
121         }
122     }
123 
createNoRecentAccessPreference()124     private CarUiPreference createNoRecentAccessPreference() {
125         CarUiPreference preference = new CarUiPreference(getContext());
126         preference.setTitle(R.string.camera_no_recent_access);
127         preference.setSelectable(false);
128         return preference;
129     }
130 
createViewAllPreference()131     private CarUiPreference createViewAllPreference() {
132         CarUiPreference preference = new CarUiPreference(getContext());
133         preference.setTitle(R.string.camera_settings_recent_requests_view_all_title);
134         preference.setIcon(R.drawable.ic_apps);
135         preference.setOnPreferenceClickListener(p -> {
136             getFragmentController().launchFragment(new CameraRecentAccessViewAllFragment());
137             return true;
138         });
139         return preference;
140     }
141 }
142