blob: 9e821067ff3312deae11e2a1b16629e1ccc9e299 [file] [log] [blame]
/*
* Copyright (C) 2015 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.packageinstaller.permission.ui.wear;
import android.Manifest;
import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.SwitchPreference;
import android.support.wearable.view.WearableDialogHelper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.android.packageinstaller.R;
import com.android.packageinstaller.permission.model.AppPermissionGroup;
import com.android.packageinstaller.permission.model.AppPermissions;
import com.android.packageinstaller.permission.utils.LocationUtils;
import com.android.packageinstaller.permission.utils.SafetyNetLogger;
import com.android.packageinstaller.permission.utils.Utils;
import java.util.ArrayList;
import java.util.List;
public final class AppPermissionsFragmentWear extends PreferenceFragment {
private static final String LOG_TAG = "AppPermFragWear";
private static final String KEY_NO_PERMISSIONS = "no_permissions";
public static AppPermissionsFragmentWear newInstance(String packageName) {
return setPackageName(new AppPermissionsFragmentWear(), packageName);
}
private static <T extends Fragment> T setPackageName(T fragment, String packageName) {
Bundle arguments = new Bundle();
arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
fragment.setArguments(arguments);
return fragment;
}
private List<AppPermissionGroup> mToggledGroups;
private AppPermissions mAppPermissions;
private boolean mHasConfirmedRevoke;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME);
Activity activity = getActivity();
PackageManager pm = activity.getPackageManager();
PackageInfo packageInfo;
try {
packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
} catch (PackageManager.NameNotFoundException e) {
Log.i(LOG_TAG, "No package:" + activity.getCallingPackage(), e);
packageInfo = null;
}
if (packageInfo == null) {
Toast.makeText(activity, R.string.app_not_found_dlg_title, Toast.LENGTH_LONG).show();
activity.finish();
return;
}
mAppPermissions = new AppPermissions(
activity, packageInfo, null, true, () -> getActivity().finish());
addPreferencesFromResource(R.xml.watch_permissions);
initializePermissionGroupList();
}
@Override
public void onResume() {
super.onResume();
mAppPermissions.refresh();
// Also refresh the UI
for (final AppPermissionGroup group : mAppPermissions.getPermissionGroups()) {
Preference pref = findPreference(group.getName());
if (pref instanceof SwitchPreference) {
((SwitchPreference) pref).setChecked(group.areRuntimePermissionsGranted());
}
}
}
@Override
public void onPause() {
super.onPause();
logAndClearToggledGroups();
}
private void initializePermissionGroupList() {
final String packageName = mAppPermissions.getPackageInfo().packageName;
List<AppPermissionGroup> groups = mAppPermissions.getPermissionGroups();
List<SwitchPreference> nonSystemGroups = new ArrayList<>();
if (!groups.isEmpty()) {
getPreferenceScreen().removePreference(findPreference(KEY_NO_PERMISSIONS));
}
for (final AppPermissionGroup group : groups) {
if (!Utils.shouldShowPermission(group, packageName)) {
continue;
}
boolean isPlatform = group.getDeclaringPackage().equals(Utils.OS_PKG);
final SwitchPreference pref = new SwitchPreference(getContext());
pref.setKey(group.getName());
pref.setTitle(group.getLabel());
pref.setChecked(group.areRuntimePermissionsGranted());
if (group.isPolicyFixed()) {
pref.setEnabled(false);
} else {
pref.setOnPreferenceChangeListener((p, newVal) -> {
if (LocationUtils.isLocationGroupAndProvider(
group.getName(), group.getApp().packageName)) {
LocationUtils.showLocationDialog(
getContext(), mAppPermissions.getAppLabel());
return false;
}
if ((Boolean) newVal) {
setPermission(group, pref, true);
} else {
final boolean grantedByDefault = group.hasGrantedByDefaultPermission();
if (grantedByDefault
|| (!group.hasRuntimePermission() && !mHasConfirmedRevoke)) {
new WearableDialogHelper.DialogBuilder(getContext())
.setNegativeIcon(R.drawable.confirm_button)
.setPositiveIcon(R.drawable.cancel_button)
.setNegativeButton(R.string.grant_dialog_button_deny_anyway,
(dialog, which) -> {
setPermission(group, pref, false);
if (!group.hasGrantedByDefaultPermission()) {
mHasConfirmedRevoke = true;
}
})
.setPositiveButton(R.string.cancel, (dialog, which) -> {})
.setMessage(grantedByDefault ?
R.string.system_warning : R.string.old_sdk_deny_warning)
.show();
return false;
} else {
setPermission(group, pref, false);
}
}
return true;
});
}
// The UI shows System settings first, then non-system settings
if (isPlatform) {
getPreferenceScreen().addPreference(pref);
} else {
nonSystemGroups.add(pref);
}
}
// Now add the non-system settings to the end of the list
for (SwitchPreference nonSystemGroup : nonSystemGroups) {
getPreferenceScreen().addPreference(nonSystemGroup);
}
}
private void setPermission(AppPermissionGroup group, SwitchPreference pref, boolean grant) {
if (grant) {
group.grantRuntimePermissions(false);
} else {
group.revokeRuntimePermissions(false);
}
addToggledGroup(group);
pref.setChecked(grant);
}
private void addToggledGroup(AppPermissionGroup group) {
if (mToggledGroups == null) {
mToggledGroups = new ArrayList<>();
}
// Double toggle is back to initial state.
if (mToggledGroups.contains(group)) {
mToggledGroups.remove(group);
} else {
mToggledGroups.add(group);
}
}
private void logAndClearToggledGroups() {
if (mToggledGroups != null) {
String packageName = mAppPermissions.getPackageInfo().packageName;
SafetyNetLogger.logPermissionsToggled(packageName, mToggledGroups);
mToggledGroups = null;
}
}
}