blob: dfd536192b7830fc658bceb3fc945534f16c335c [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.permissioncontroller.permission.ui.auto;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.ArrayMap;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceGroup;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.auto.AutoSettingsFrameFragment;
import com.android.permissioncontroller.permission.model.AppPermissionGroup;
import com.android.permissioncontroller.permission.model.legacy.PermissionApps;
import com.android.permissioncontroller.permission.model.legacy.PermissionApps.Callback;
import com.android.permissioncontroller.permission.ui.handheld.PermissionAppsFragment;
import com.android.permissioncontroller.permission.ui.handheld.PermissionControlPreference;
import com.android.permissioncontroller.permission.utils.Utils;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Map;
/** Shows the list of applications which have (or do not have) the given permission. */
public class AutoPermissionAppsFragment extends AutoSettingsFrameFragment implements Callback {
private static final String KEY_SHOW_SYSTEM_PREFS = "_showSystem";
private static final String KEY_ALLOWED_PERMISSIONS_GROUP = "allowed_permissions_group";
private static final String KEY_ALLOWED_FOREGROUND_PERMISSIONS_GROUP =
"allowed_foreground_permissions_group";
private static final String KEY_DENIED_PERMISSIONS_GROUP = "denied_permissions_group";
private static final String SHOW_SYSTEM_KEY = AutoPermissionAppsFragment.class.getName()
+ KEY_SHOW_SYSTEM_PREFS;
/** Creates a new instance of {@link AutoPermissionAppsFragment} for the given permission. */
public static AutoPermissionAppsFragment newInstance(String permissionName) {
return setPermissionName(new AutoPermissionAppsFragment(), permissionName);
}
private static <T extends Fragment> T setPermissionName(T fragment, String permissionName) {
Bundle arguments = new Bundle();
arguments.putString(Intent.EXTRA_PERMISSION_NAME, permissionName);
fragment.setArguments(arguments);
return fragment;
}
private PermissionApps mPermissionApps;
private boolean mShowSystem;
private boolean mHasSystemApps;
private Collator mCollator;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mShowSystem = savedInstanceState.getBoolean(SHOW_SYSTEM_KEY);
}
setLoading(true);
String groupName = getArguments().getString(Intent.EXTRA_PERMISSION_NAME);
mPermissionApps = new PermissionApps(getActivity(), groupName, /* callback= */ this);
mPermissionApps.refresh(/* getUiInfo= */ true);
mCollator = Collator.getInstance(
getContext().getResources().getConfiguration().getLocales().get(0));
setShowSystemAppsToggle();
bindUi(mPermissionApps, groupName);
}
@Override
public void onCreatePreferences(Bundle bundle, String s) {
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext()));
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SHOW_SYSTEM_KEY, mShowSystem);
}
@Override
public void onStart() {
super.onStart();
mPermissionApps.refresh(/* getUiInfo= */ true);
}
private void setShowSystemAppsToggle() {
if (!mHasSystemApps) {
setAction(/* label= */ null, /* onClickListener= */ null);
return;
}
// Show the opposite label from the current state.
String label;
if (mShowSystem) {
label = getString(R.string.menu_hide_system);
} else {
label = getString(R.string.menu_show_system);
}
setAction(label, v -> {
mShowSystem = !mShowSystem;
if (mPermissionApps.getApps() != null) {
onPermissionsLoaded(mPermissionApps);
}
setShowSystemAppsToggle();
});
}
private void bindUi(PermissionApps permissionApps, @NonNull String groupName) {
CharSequence label = permissionApps.getFullLabel();
setHeaderLabel(label);
Drawable icon = permissionApps.getIcon();
Preference header = new Preference(getContext());
header.setTitle(label);
header.setIcon(icon);
header.setSummary(Utils.getPermissionGroupDescriptionString(getContext(), groupName,
permissionApps.getDescription()));
getPreferenceScreen().addPreference(header);
PreferenceGroup allowed = new PreferenceCategory(getContext());
allowed.setKey(KEY_ALLOWED_PERMISSIONS_GROUP);
allowed.setTitle(R.string.allowed_header);
allowed.setVisible(false);
getPreferenceScreen().addPreference(allowed);
PreferenceGroup foreground = new PreferenceCategory(getContext());
foreground.setKey(KEY_ALLOWED_FOREGROUND_PERMISSIONS_GROUP);
foreground.setTitle(R.string.allowed_foreground_header);
foreground.setVisible(false);
getPreferenceScreen().addPreference(foreground);
PreferenceGroup denied = new PreferenceCategory(getContext());
denied.setKey(KEY_DENIED_PERMISSIONS_GROUP);
denied.setTitle(R.string.denied_header);
denied.setVisible(false);
getPreferenceScreen().addPreference(denied);
}
@Override
public void onPermissionsLoaded(PermissionApps permissionApps) {
Context context = getPreferenceManager().getContext();
if (context == null || getActivity() == null) {
return;
}
PreferenceCategory allowed = findPreference(KEY_ALLOWED_PERMISSIONS_GROUP);
PreferenceCategory allowedForeground = findPreference(
KEY_ALLOWED_FOREGROUND_PERMISSIONS_GROUP);
PreferenceCategory denied = findPreference(KEY_DENIED_PERMISSIONS_GROUP);
allowed.setOrderingAsAdded(true);
allowedForeground.setOrderingAsAdded(true);
denied.setOrderingAsAdded(true);
Map<String, Preference> existingPrefs = new ArrayMap<>();
int numPreferences = allowed.getPreferenceCount();
for (int i = 0; i < numPreferences; i++) {
Preference preference = allowed.getPreference(i);
existingPrefs.put(preference.getKey(), preference);
}
allowed.removeAll();
numPreferences = allowedForeground.getPreferenceCount();
for (int i = 0; i < numPreferences; i++) {
Preference preference = allowedForeground.getPreference(i);
existingPrefs.put(preference.getKey(), preference);
}
allowedForeground.removeAll();
numPreferences = denied.getPreferenceCount();
for (int i = 0; i < numPreferences; i++) {
Preference preference = denied.getPreference(i);
existingPrefs.put(preference.getKey(), preference);
}
denied.removeAll();
mHasSystemApps = false;
boolean hasPermissionWithBackgroundMode = false;
ArrayList<PermissionApps.PermissionApp> sortedApps = new ArrayList<>(
permissionApps.getApps());
sortedApps.sort((x, y) -> {
int result = mCollator.compare(x.getLabel(), y.getLabel());
if (result == 0) {
result = x.getUid() - y.getUid();
}
return result;
});
for (int i = 0; i < sortedApps.size(); i++) {
PermissionApps.PermissionApp app = sortedApps.get(i);
AppPermissionGroup group = app.getPermissionGroup();
hasPermissionWithBackgroundMode =
hasPermissionWithBackgroundMode || group.hasPermissionWithBackgroundMode();
if (!Utils.shouldShowPermission(getContext(), group)) {
continue;
}
if (!app.getAppInfo().enabled) {
continue;
}
String key = app.getKey();
Preference existingPref = existingPrefs.get(key);
if (existingPref != null) {
// Without this, existing preferences remember their old order.
existingPref.setOrder(Preference.DEFAULT_ORDER);
}
boolean isSystemApp = !Utils.isGroupOrBgGroupUserSensitive(group);
if (isSystemApp) {
mHasSystemApps = true;
}
if (isSystemApp && !mShowSystem) {
continue;
}
PreferenceCategory category;
if (group.areRuntimePermissionsGranted()) {
if (!group.hasPermissionWithBackgroundMode()
|| (group.getBackgroundPermissions() != null
&& group.getBackgroundPermissions().areRuntimePermissionsGranted())) {
category = allowed;
} else {
category = allowedForeground;
}
} else {
category = denied;
}
if (existingPref != null) {
category.addPreference(existingPref);
continue;
}
PermissionControlPreference pref = new PermissionControlPreference(context, group,
PermissionAppsFragment.class.getName());
pref.setKey(key);
pref.setIcon(app.getIcon());
pref.setTitle(Utils.getFullAppLabel(app.getAppInfo(), context));
pref.setEllipsizeEnd();
pref.useSmallerIcon();
category.addPreference(pref);
}
if (hasPermissionWithBackgroundMode) {
allowed.setTitle(R.string.allowed_always_header);
}
if (allowed.getPreferenceCount() == 0) {
Preference empty = new Preference(context);
empty.setTitle(R.string.no_apps_allowed);
empty.setSelectable(false);
allowed.addPreference(empty);
}
allowed.setVisible(true);
allowedForeground.setVisible(allowedForeground.getPreferenceCount() > 0);
if (denied.getPreferenceCount() == 0) {
Preference empty = new Preference(context);
empty.setTitle(R.string.no_apps_denied);
empty.setSelectable(false);
denied.addPreference(empty);
}
denied.setVisible(true);
setShowSystemAppsToggle();
setLoading(false);
}
}