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