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:
Suchi Amalapurapu
2009-06-11 16:05:10 -07:00
parent 38ea6d2afe
commit 25be4bad76
5 changed files with 498 additions and 0 deletions

View File

@@ -131,5 +131,11 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="PermissionDetails" android:label="Permission Info">
<intent-filter>
<action android:name="com.android.development.VIEW_PERMISSION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2007 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.
-->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:fillViewport="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="4dip" >
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dip" >
<TextView android:id="@+id/perm_name_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/perm_name_text"
android:textStyle="bold" />
<TextView android:id="@+id/perm_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dip" >
<TextView android:id="@+id/perm_desc_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/perm_desc_text"
android:textStyle="bold" />
<TextView android:id="@+id/perm_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dip" >
<TextView android:id="@+id/perm_group_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/perm_group_text"
android:textStyle="bold" />
<TextView android:id="@+id/perm_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dip" >
<TextView android:id="@+id/perm_protection_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/perm_protection_text"
android:textStyle="bold" />
<TextView android:id="@+id/perm_protection"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dip" >
<TextView android:id="@+id/perm_source_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/perm_source_text"
android:textStyle="bold" />
<TextView android:id="@+id/perm_source"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dip" >
<TextView android:id="@+id/source_uid_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/source_uid_text"
android:textStyle="bold" />
<TextView android:id="@+id/source_uid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout android:id="@+id/shared_pkgs_panel"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dip" >
<TextView android:id="@+id/shared_pkgs_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/shared_pkgs_text"
android:textStyle="bold" />
<TextView android:id="@+id/shared_pkgs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<TextView android:id="@+id/perm_list_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="3dip"
android:text="@string/perm_list_header_text"
android:textStyle="bold" />
<ListView android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2008, 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.
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="horizontal"
android:paddingRight="6dip"
android:paddingLeft="6dip"
android:paddingTop="5dip"
android:paddingBottom="5dip"
android:gravity="center_vertical" >
<TextView android:id="@+id/pkg_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textStyle="bold"
android:singleLine="true"
android:ellipsize="marquee"
android:layout_marginBottom="2dip" />
</LinearLayout>

View File

@@ -120,4 +120,17 @@
<string name="navigation_label">navigation:</string>
<string name="five_way_nav_label">five way nav:</string>
<string name="gles_version_label">GLES Version:</string>
<!-- Permission details related string attribtues -->
<string name="perm_name_text">Name : </string>
<string name="dialog_title_error">Error</string>
<string name="invalid_perm_name">Invalid Permission Name</string>
<string name="ok">Ok</string>
<string name="perm_desc_text">Desc : </string>
<string name="perm_group_text">Group : </string>
<string name="perm_protection_text">Protection Level : </string>
<string name="perm_source_text">Source package : </string>
<string name="perm_list_header_text">Apps using permission </string>
<string name="source_uid_text">Source uid : </string>
<string name="shared_pkgs_text">Packages accessing via shared uid : </string>
</resources>

View File

@@ -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
}
}