package de.robv.android.xposed.mods.appsettings.settings;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PermissionInfo;
import android.graphics.Color;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.Switch;
import de.robv.android.xposed.mods.appsettings.R;
/**
* Manages a popup dialog for editing the Permission Revoking settings for a package
*/
public class PermissionSettings {
private Dialog dialog;
private OnDismissListener onOkListener;
private OnDismissListener onCancelListener;
boolean revokeActive;
private Set<String> disabledPerms;
private List<PermissionInfo> permsList = new LinkedList<PermissionInfo>();
/**
* Prepare a dialog for editing the permissions for the supplied package,
* with the provided owner activity and initial settings
*/
public PermissionSettings(Activity owner, String pkgName, boolean revoking, Set<String> disabledPermissions) throws NameNotFoundException {
dialog = new Dialog(owner);
dialog.setContentView(R.layout.permissions_dialog);
dialog.setTitle(R.string.perms_title);
dialog.setCancelable(true);
dialog.setOwnerActivity(owner);
revokeActive = revoking;
if (disabledPermissions != null)
disabledPerms = new HashSet<String>(disabledPermissions);
else
disabledPerms = new HashSet<String>();
Switch swtRevoke = (Switch) dialog.findViewById(R.id.swtRevokePerms);
swtRevoke.setChecked(revokeActive);
// Load the list of permissions for the package and present them
loadPermissionsList(pkgName);
final PermissionsListAdapter appListAdapter = new PermissionsListAdapter(owner, permsList, disabledPerms, true);
appListAdapter.setCanEdit(revokeActive);
((ListView) dialog.findViewById(R.id.lstPermissions)).setAdapter(appListAdapter);
// Track changes to the Revoke checkbox to lock or unlock the list of
// permissions
swtRevoke.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
revokeActive = isChecked;
dialog.findViewById(R.id.lstPermissions).setBackgroundColor(revokeActive ? Color.BLACK : Color.DKGRAY);
appListAdapter.setCanEdit(revokeActive);
}
});
dialog.findViewById(R.id.lstPermissions).setBackgroundColor(revokeActive ? Color.BLACK : Color.DKGRAY);
((Button) dialog.findViewById(R.id.btnPermsCancel)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onCancelListener != null)
onCancelListener.onDismiss(PermissionSettings.this);
dialog.dismiss();
}
});
((Button) dialog.findViewById(R.id.btnPermsOk)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onOkListener != null)
onOkListener.onDismiss(PermissionSettings.this);
dialog.dismiss();
}
});
}
/**
* Display the editor dialog
*/
public void display() {
dialog.show();
}
/**
* Register a listener to be invoked when the editor is dismissed with the
* Ok button
*/
public void setOnOkListener(OnDismissListener listener) {
onOkListener = listener;
}
/**
* Register a listener to be invoked when the editor is dismissed with the
* Cancel button
*/
public void setOnCancelListener(OnDismissListener listener) {
onCancelListener = listener;
}
/**
* Get the state of the Active switch
*/
public boolean getRevokeActive() {
return revokeActive;
}
/**
* Get the list of permissions in the disabled state
*/
public Set<String> getDisabledPermissions() {
return new HashSet<String>(disabledPerms);
}
/*
* Populate the list of permissions requested by this package
*/
@SuppressLint("DefaultLocale")
private void loadPermissionsList(String pkgName) throws NameNotFoundException {
permsList.clear();
PackageManager pm = dialog.getContext().getPackageManager();
PackageInfo pkgInfo = pm.getPackageInfo(pkgName, PackageManager.GET_PERMISSIONS);
if (pkgInfo.sharedUserId != null) {
Switch swtRevoke = (Switch) dialog.findViewById(R.id.swtRevokePerms);
swtRevoke.setText(R.string.perms_shared_warning);
swtRevoke.setTextColor(Color.RED);
}
String[] permissions = pkgInfo.requestedPermissions;
if (permissions == null) {
permissions = new String[0];
}
for (String perm : permissions) {
try {
permsList.add(pm.getPermissionInfo(perm, 0));
} catch (NameNotFoundException e) {
PermissionInfo unknownPerm = new PermissionInfo();
unknownPerm.name = perm;
permsList.add(unknownPerm);
}
}
Collections.sort(permsList, new Comparator<PermissionInfo>() {
@Override
public int compare(PermissionInfo lhs, PermissionInfo rhs) {
if (lhs.name == null) {
return -1;
} else if (rhs.name == null) {
return 1;
} else {
return lhs.name.toUpperCase().compareTo(rhs.name.toUpperCase());
}
}
});
}
/**
* Interface for the listeners of Ok/Cancel dismiss actions
*/
public static interface OnDismissListener {
public abstract void onDismiss(PermissionSettings obj);
}
}