1 /* 2 * Copyright (C) 2021 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.tv.settings.enterprise; 18 19 import android.content.Context; 20 import android.icu.text.MessageFormat; 21 22 import androidx.preference.Preference; 23 24 import com.android.settingslib.core.AbstractPreferenceController; 25 import com.android.tv.settings.R; 26 import com.android.tv.settings.enterprise.apps.ApplicationFeatureProvider; 27 import com.android.tv.settings.overlay.FlavorUtils; 28 29 import java.util.HashMap; 30 import java.util.Locale; 31 import java.util.Map; 32 33 public abstract class AdminGrantedPermissionsPreferenceControllerBase extends 34 AbstractPreferenceController { 35 36 private final String[] mPermissions; 37 private final ApplicationFeatureProvider mFeatureProvider; 38 private final boolean mAsync; 39 private boolean mHasApps; 40 AdminGrantedPermissionsPreferenceControllerBase(Context context, boolean async, String[] permissions)41 public AdminGrantedPermissionsPreferenceControllerBase(Context context, boolean async, 42 String[] permissions) { 43 super(context); 44 mPermissions = permissions; 45 mFeatureProvider = FlavorUtils.getFeatureFactory(context).getApplicationFeatureProvider( 46 context); 47 mAsync = async; 48 mHasApps = false; 49 } 50 51 @Override updateState(Preference preference)52 public void updateState(Preference preference) { 53 mFeatureProvider.calculateNumberOfAppsWithAdminGrantedPermissions(mPermissions, 54 true /* async */, 55 (num) -> { 56 if (num == 0) { 57 mHasApps = false; 58 } else { 59 MessageFormat msgFormat = new MessageFormat( 60 mContext.getResources().getString( 61 R.string.enterprise_privacy_number_packages_lower_bound), 62 Locale.getDefault()); 63 Map<String, Object> arguments = new HashMap<>(); 64 arguments.put("count", num); 65 preference.setSummary(msgFormat.format(arguments)); 66 mHasApps = true; 67 } 68 preference.setVisible(mHasApps); 69 }); 70 } 71 72 @Override isAvailable()73 public boolean isAvailable() { 74 if (mAsync) { 75 // When called on the main UI thread, we must not block. Since calculating the number of 76 // apps that the admin has granted a given permissions takes a bit of time, we always 77 // return true here and determine the pref's actual visibility asynchronously in 78 // updateState(). 79 return true; 80 } 81 82 // When called by the search indexer, we are on a background thread that we can block. Also, 83 // changes to the pref's visibility made in updateState() would not be seen by the indexer. 84 // We block and return synchronously whether the admin has granted the given permissions to 85 // any apps or not. 86 final Boolean[] haveAppsWithAdminGrantedPermissions = {null}; 87 mFeatureProvider.calculateNumberOfAppsWithAdminGrantedPermissions(mPermissions, 88 false /* async */, (num) -> haveAppsWithAdminGrantedPermissions[0] = num > 0); 89 mHasApps = haveAppsWithAdminGrantedPermissions[0]; 90 return mHasApps; 91 } 92 93 @Override handlePreferenceTreeClick(Preference preference)94 public boolean handlePreferenceTreeClick(Preference preference) { 95 if (!getPreferenceKey().equals(preference.getKey())) { 96 return false; 97 } 98 if (!mHasApps) { 99 return false; 100 } 101 return super.handlePreferenceTreeClick(preference); 102 } 103 } 104