Define a new activity that lists permissions and apps using that permission with some additional details as well
First pass.
This commit is contained in:
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
**
|
||||
** Copyright 2006, 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.development;
|
||||
|
||||
import com.android.development.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PermissionInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
|
||||
/**
|
||||
* This activity displays permission details including
|
||||
* the list of apps using a permission.
|
||||
*/
|
||||
public class PermissionDetails extends Activity implements OnCancelListener, OnItemClickListener {
|
||||
private static final String TAG = "PermissionDetails";
|
||||
PackageManager mPm;
|
||||
// layout inflater object used to inflate views
|
||||
private LayoutInflater mInflater;
|
||||
private AppListAdapter mAdapter;
|
||||
|
||||
// Dialog related
|
||||
private static final int DLG_BASE = 0;
|
||||
private static final int DLG_ERROR = DLG_BASE + 1;
|
||||
private static final String PROTECTION_NORMAL="Normal";
|
||||
private static final String PROTECTION_DANGEROUS="Dangerous";
|
||||
private static final String PROTECTION_SIGNATURE="Signature";
|
||||
private static final String PROTECTION_SIGNATURE_OR_SYSTEM="SignatureOrSystem";
|
||||
|
||||
private static final String KEY_APPS_USING_PERM="AppsUsingPerm";
|
||||
|
||||
private static final int HANDLER_MSG_BASE = 0;
|
||||
private static final int HANDLER_MSG_GET_APPS = HANDLER_MSG_BASE + 1;
|
||||
private Handler mHandler = new Handler() {
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case HANDLER_MSG_GET_APPS:
|
||||
ArrayList<PackageInfo> appList = msg.getData().getParcelableArrayList(KEY_APPS_USING_PERM);
|
||||
createAppList(appList);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// View Holder used when displaying views
|
||||
static class AppViewHolder {
|
||||
TextView pkgName;
|
||||
}
|
||||
|
||||
class AppListAdapter extends BaseAdapter {
|
||||
private List<PackageInfo> mList;
|
||||
|
||||
AppListAdapter(List<PackageInfo> list) {
|
||||
mList = list;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return mList.size();
|
||||
}
|
||||
|
||||
public Object getItem(int position) {
|
||||
return mList.get(position);
|
||||
}
|
||||
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
public PackageInfo getPkg(int position) {
|
||||
return mList.get(position);
|
||||
}
|
||||
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
// A ViewHolder keeps references to children views to avoid unneccessary calls
|
||||
// to findViewById() on each row.
|
||||
AppViewHolder holder;
|
||||
|
||||
// When convertView is not null, we can reuse it directly, there is no need
|
||||
// to reinflate it. We only inflate a new View when the convertView supplied
|
||||
// by ListView is null.
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(R.layout.pkg_list_item, null);
|
||||
|
||||
// Creates a ViewHolder and store references to the two children views
|
||||
// we want to bind data to.
|
||||
holder = new AppViewHolder();
|
||||
holder.pkgName = (TextView) convertView.findViewById(R.id.pkg_name);
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
// Get the ViewHolder back to get fast access to the TextView
|
||||
// and the ImageView.
|
||||
holder = (AppViewHolder) convertView.getTag();
|
||||
}
|
||||
// Bind the data efficiently with the holder
|
||||
PackageInfo pInfo = mList.get(position);
|
||||
holder.pkgName.setText(pInfo.packageName);
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
||||
private void createAppList(List<PackageInfo> list) {
|
||||
Log.i(TAG, "list.size=" + list.size());
|
||||
for (PackageInfo pkg : list) {
|
||||
Log.i(TAG, "Adding pkg : " + pkg.packageName);
|
||||
}
|
||||
ListView listView = (ListView)findViewById(android.R.id.list);
|
||||
mAdapter = new AppListAdapter(list);
|
||||
ListView lv= (ListView) findViewById(android.R.id.list);
|
||||
lv.setOnItemClickListener(this);
|
||||
lv.setSaveEnabled(true);
|
||||
lv.setItemsCanFocus(true);
|
||||
listView.setAdapter(mAdapter);
|
||||
}
|
||||
|
||||
private void getAppsUsingPerm(PermissionInfo pInfo) {
|
||||
List<PackageInfo> list = mPm.getInstalledPackages(PackageManager.GET_PERMISSIONS);
|
||||
HashSet<PackageInfo> set = new HashSet<PackageInfo>();
|
||||
for (PackageInfo pkg : list) {
|
||||
if (pkg.requestedPermissions == null) {
|
||||
continue;
|
||||
}
|
||||
for (String perm : pkg.requestedPermissions) {
|
||||
if (perm.equalsIgnoreCase(pInfo.name)) {
|
||||
Log.i(TAG, "Pkg:" + pkg.packageName+" uses permission");
|
||||
set.add(pkg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ArrayList<PackageInfo> retList = new ArrayList<PackageInfo>();
|
||||
for (PackageInfo pkg : set) {
|
||||
retList.add(pkg);
|
||||
}
|
||||
Message msg = mHandler.obtainMessage(HANDLER_MSG_GET_APPS);
|
||||
Bundle data = msg.getData();
|
||||
data.putParcelableArrayList(KEY_APPS_USING_PERM, retList);
|
||||
mHandler.dispatchMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
setContentView(R.layout.permission_details);
|
||||
Intent intent = getIntent();
|
||||
String permName = intent.getStringExtra("permission");
|
||||
if(permName == null) {
|
||||
showDialogInner(DLG_ERROR);
|
||||
}
|
||||
mPm = getPackageManager();
|
||||
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
PermissionInfo pInfo = null;
|
||||
try {
|
||||
pInfo = mPm.getPermissionInfo(permName,
|
||||
PackageManager.GET_PERMISSIONS);
|
||||
} catch (NameNotFoundException e) {
|
||||
showDialogInner(DLG_ERROR);
|
||||
}
|
||||
setTextView(R.id.perm_name, pInfo.name);
|
||||
setTextView(R.id.perm_desc, pInfo.descriptionRes);
|
||||
setTextView(R.id.perm_group, pInfo.group);
|
||||
setProtectionLevel(R.id.perm_protection, pInfo.protectionLevel);
|
||||
setTextView(R.id.perm_source, pInfo.packageName);
|
||||
ApplicationInfo appInfo = null;
|
||||
try {
|
||||
appInfo = mPm.getApplicationInfo(pInfo.packageName, 0);
|
||||
String uidStr = mPm.getNameForUid(appInfo.uid);
|
||||
setTextView(R.id.source_uid, uidStr);
|
||||
} catch (NameNotFoundException e) {
|
||||
}
|
||||
boolean sharedVisibility = false;
|
||||
// List of apps acquiring access via shared user id
|
||||
LinearLayout sharedPanel = (LinearLayout) findViewById(R.id.shared_pkgs_panel);
|
||||
if (appInfo != null) {
|
||||
String[] sharedList = mPm.getPackagesForUid(appInfo.uid);
|
||||
if ((sharedList != null) && (sharedList.length > 1)) {
|
||||
sharedVisibility = true;
|
||||
TextView label = (TextView) sharedPanel.findViewById(R.id.shared_pkgs_label);
|
||||
TextView sharedView = (TextView) sharedPanel.findViewById(R.id.shared_pkgs);
|
||||
label.setVisibility(View.VISIBLE);
|
||||
StringBuilder buff = new StringBuilder();
|
||||
buff.append(sharedList[0]);
|
||||
for (int i = 1; i < sharedList.length; i++) {
|
||||
buff.append(", ");
|
||||
buff.append(sharedList[i]);
|
||||
}
|
||||
sharedView.setText(buff.toString());
|
||||
}
|
||||
}
|
||||
if (sharedVisibility) {
|
||||
sharedPanel.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
sharedPanel.setVisibility(View.GONE);
|
||||
}
|
||||
getAppsUsingPerm(pInfo);
|
||||
}
|
||||
|
||||
private void setProtectionLevel(int viewId, int protectionLevel) {
|
||||
String levelStr = "";
|
||||
if (protectionLevel == PermissionInfo.PROTECTION_NORMAL) {
|
||||
levelStr = PROTECTION_NORMAL;
|
||||
} else if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
|
||||
levelStr = PROTECTION_DANGEROUS;
|
||||
} else if (protectionLevel == PermissionInfo.PROTECTION_SIGNATURE) {
|
||||
levelStr = PROTECTION_SIGNATURE;
|
||||
} else if (protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
|
||||
levelStr = PROTECTION_SIGNATURE_OR_SYSTEM;
|
||||
} else {
|
||||
levelStr = "Invalid";
|
||||
}
|
||||
setTextView(viewId, levelStr);
|
||||
}
|
||||
|
||||
private void setTextView(int viewId, int textId) {
|
||||
TextView view = (TextView)findViewById(viewId);
|
||||
view.setText(textId);
|
||||
}
|
||||
|
||||
private void setTextView(int viewId, String text) {
|
||||
TextView view = (TextView)findViewById(viewId);
|
||||
view.setText(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(int id) {
|
||||
if (id == DLG_ERROR) {
|
||||
return new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
finish();
|
||||
}})
|
||||
.setMessage(R.string.invalid_perm_name)
|
||||
.setOnCancelListener(this)
|
||||
.create();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void showDialogInner(int id) {
|
||||
// TODO better fix for this? Remove dialog so that it gets created again
|
||||
removeDialog(id);
|
||||
showDialog(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
finish();
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position,
|
||||
long id) {
|
||||
// TODO Launch app details activity
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user