Home | History | Annotate | Download | only in development
      1 /*
      2 **
      3 ** Copyright 2006, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 package com.android.development;
     19 
     20 import com.android.development.R;
     21 
     22 import java.util.ArrayList;
     23 import java.util.HashSet;
     24 import java.util.List;
     25 
     26 import android.app.Activity;
     27 import android.app.AlertDialog;
     28 import android.app.Dialog;
     29 import android.content.Context;
     30 import android.content.DialogInterface;
     31 import android.content.Intent;
     32 import android.content.DialogInterface.OnCancelListener;
     33 import android.content.pm.ApplicationInfo;
     34 import android.content.pm.PackageInfo;
     35 import android.content.pm.PackageManager;
     36 import android.content.pm.PermissionInfo;
     37 import android.content.pm.PackageManager.NameNotFoundException;
     38 import android.os.Bundle;
     39 import android.os.Handler;
     40 import android.os.Message;
     41 import android.util.Log;
     42 import android.view.LayoutInflater;
     43 import android.view.View;
     44 import android.view.ViewGroup;
     45 import android.widget.AdapterView;
     46 import android.widget.BaseAdapter;
     47 import android.widget.ImageView;
     48 import android.widget.LinearLayout;
     49 import android.widget.ListView;
     50 import android.widget.TextView;
     51 import android.widget.AdapterView.OnItemClickListener;
     52 
     53 /**
     54  * This activity displays permission details including
     55  * the list of apps using a permission.
     56  */
     57 public class PermissionDetails extends Activity implements OnCancelListener, OnItemClickListener {
     58     private static final String TAG = "PermissionDetails";
     59     PackageManager mPm;
     60     // layout inflater object used to inflate views
     61     private LayoutInflater mInflater;
     62     private AppListAdapter mAdapter;
     63 
     64     // Dialog related
     65     private static final int DLG_BASE = 0;
     66     private static final int DLG_ERROR = DLG_BASE + 1;
     67     private static final String PROTECTION_NORMAL="Normal";
     68     private static final String PROTECTION_DANGEROUS="Dangerous";
     69     private static final String PROTECTION_SIGNATURE="Signature";
     70     private static final String PROTECTION_SIGNATURE_OR_SYSTEM="SignatureOrSystem";
     71 
     72     private static final String KEY_APPS_USING_PERM="AppsUsingPerm";
     73 
     74     private static final int HANDLER_MSG_BASE = 0;
     75     private static final int HANDLER_MSG_GET_APPS = HANDLER_MSG_BASE + 1;
     76     private Handler mHandler = new Handler() {
     77         public void handleMessage(Message msg) {
     78             switch (msg.what) {
     79             case HANDLER_MSG_GET_APPS:
     80                 ArrayList<PackageInfo> appList = msg.getData().getParcelableArrayList(KEY_APPS_USING_PERM);
     81                 createAppList(appList);
     82                 break;
     83             }
     84         }
     85     };
     86 
     87     // View Holder used when displaying views
     88     static class AppViewHolder {
     89         TextView pkgName;
     90     }
     91 
     92     class AppListAdapter extends BaseAdapter {
     93         private List<PackageInfo> mList;
     94 
     95         AppListAdapter(List<PackageInfo> list) {
     96             mList = list;
     97         }
     98 
     99         public int getCount() {
    100             return mList.size();
    101         }
    102 
    103         public Object getItem(int position) {
    104             return mList.get(position);
    105         }
    106 
    107         public long getItemId(int position) {
    108             return position;
    109         }
    110 
    111         public PackageInfo getPkg(int position) {
    112             return mList.get(position);
    113         }
    114 
    115         public View getView(int position, View convertView, ViewGroup parent) {
    116             // A ViewHolder keeps references to children views to avoid unneccessary calls
    117             // to findViewById() on each row.
    118             AppViewHolder holder;
    119 
    120             // When convertView is not null, we can reuse it directly, there is no need
    121             // to reinflate it. We only inflate a new View when the convertView supplied
    122             // by ListView is null.
    123             if (convertView == null) {
    124                 convertView = mInflater.inflate(R.layout.pkg_list_item, null);
    125 
    126                 // Creates a ViewHolder and store references to the two children views
    127                 // we want to bind data to.
    128                 holder = new AppViewHolder();
    129                 holder.pkgName = (TextView) convertView.findViewById(R.id.pkg_name);
    130                 convertView.setTag(holder);
    131             } else {
    132                 // Get the ViewHolder back to get fast access to the TextView
    133                 // and the ImageView.
    134                 holder = (AppViewHolder) convertView.getTag();
    135             }
    136             // Bind the data efficiently with the holder
    137             PackageInfo pInfo = mList.get(position);
    138             holder.pkgName.setText(pInfo.packageName);
    139             return convertView;
    140         }
    141     }
    142 
    143     private void createAppList(List<PackageInfo> list) {
    144         Log.i(TAG, "list.size=" + list.size());
    145         for (PackageInfo pkg : list) {
    146             Log.i(TAG, "Adding pkg : " +  pkg.packageName);
    147         }
    148         ListView listView = (ListView)findViewById(android.R.id.list);
    149         mAdapter = new AppListAdapter(list);
    150         ListView lv= (ListView) findViewById(android.R.id.list);
    151         lv.setOnItemClickListener(this);
    152         lv.setSaveEnabled(true);
    153         lv.setItemsCanFocus(true);
    154         listView.setAdapter(mAdapter);
    155     }
    156 
    157     private  void getAppsUsingPerm(PermissionInfo pInfo) {
    158         List<PackageInfo> list = mPm.getInstalledPackages(PackageManager.GET_PERMISSIONS);
    159         HashSet<PackageInfo> set = new HashSet<PackageInfo>();
    160         for (PackageInfo pkg : list) {
    161             if (pkg.requestedPermissions == null) {
    162                 continue;
    163             }
    164             for (String perm : pkg.requestedPermissions) {
    165                 if (perm.equalsIgnoreCase(pInfo.name)) {
    166                     Log.i(TAG, "Pkg:" + pkg.packageName+" uses permission");
    167                     set.add(pkg);
    168                     break;
    169                 }
    170             }
    171         }
    172         ArrayList<PackageInfo> retList = new ArrayList<PackageInfo>();
    173         for (PackageInfo pkg : set) {
    174             retList.add(pkg);
    175         }
    176         Message msg = mHandler.obtainMessage(HANDLER_MSG_GET_APPS);
    177         Bundle data = msg.getData();
    178         data.putParcelableArrayList(KEY_APPS_USING_PERM, retList);
    179         mHandler.dispatchMessage(msg);
    180     }
    181 
    182     @Override
    183     protected void onCreate(Bundle icicle) {
    184         super.onCreate(icicle);
    185         setContentView(R.layout.permission_details);
    186         Intent intent = getIntent();
    187         String permName = intent.getStringExtra("permission");
    188         if(permName == null) {
    189             showDialogInner(DLG_ERROR);
    190         }
    191         mPm = getPackageManager();
    192         mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    193         PermissionInfo pInfo = null;
    194         try {
    195             pInfo = mPm.getPermissionInfo(permName,
    196                 PackageManager.GET_PERMISSIONS);
    197         } catch (NameNotFoundException e) {
    198             showDialogInner(DLG_ERROR);
    199         }
    200         setTextView(R.id.perm_name, pInfo.name);
    201         setTextView(R.id.perm_desc, pInfo.descriptionRes);
    202         setTextView(R.id.perm_group, pInfo.group);
    203         setProtectionLevel(R.id.perm_protection, pInfo.protectionLevel);
    204         setTextView(R.id.perm_source, pInfo.packageName);
    205         ApplicationInfo appInfo = null;
    206         try {
    207             appInfo =  mPm.getApplicationInfo(pInfo.packageName, 0);
    208             String uidStr = mPm.getNameForUid(appInfo.uid);
    209             setTextView(R.id.source_uid, uidStr);
    210         } catch (NameNotFoundException e) {
    211         }
    212         boolean sharedVisibility = false;
    213         // List of apps acquiring access via shared user id
    214         LinearLayout sharedPanel = (LinearLayout) findViewById(R.id.shared_pkgs_panel);
    215         if (appInfo != null) {
    216             String[] sharedList = mPm.getPackagesForUid(appInfo.uid);
    217             if ((sharedList != null) && (sharedList.length > 1)) {
    218                 sharedVisibility = true;
    219                 TextView label = (TextView) sharedPanel.findViewById(R.id.shared_pkgs_label);
    220                 TextView sharedView = (TextView) sharedPanel.findViewById(R.id.shared_pkgs);
    221                 label.setVisibility(View.VISIBLE);
    222                 StringBuilder buff = new StringBuilder();
    223                 buff.append(sharedList[0]);
    224                 for (int i = 1; i < sharedList.length; i++) {
    225                     buff.append(", ");
    226                     buff.append(sharedList[i]);
    227                 }
    228                 sharedView.setText(buff.toString());
    229             }
    230         }
    231         if (sharedVisibility) {
    232             sharedPanel.setVisibility(View.VISIBLE);
    233         } else {
    234             sharedPanel.setVisibility(View.GONE);
    235         }
    236         getAppsUsingPerm(pInfo);
    237     }
    238 
    239     private void setProtectionLevel(int viewId, int protectionLevel) {
    240         String levelStr = "";
    241         if (protectionLevel == PermissionInfo.PROTECTION_NORMAL) {
    242             levelStr = PROTECTION_NORMAL;
    243         } else if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
    244             levelStr = PROTECTION_DANGEROUS;
    245         } else if (protectionLevel == PermissionInfo.PROTECTION_SIGNATURE) {
    246             levelStr = PROTECTION_SIGNATURE;
    247         } else if (protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
    248             levelStr = PROTECTION_SIGNATURE_OR_SYSTEM;
    249         } else {
    250             levelStr = "Invalid";
    251         }
    252         setTextView(viewId, levelStr);
    253     }
    254 
    255     private void setTextView(int viewId, int textId) {
    256         TextView view = (TextView)findViewById(viewId);
    257         view.setText(textId);
    258     }
    259 
    260     private void setTextView(int viewId, String text) {
    261         TextView view = (TextView)findViewById(viewId);
    262         view.setText(text);
    263     }
    264 
    265     @Override
    266     public Dialog onCreateDialog(int id) {
    267         if (id == DLG_ERROR) {
    268             return new AlertDialog.Builder(this)
    269             .setTitle(R.string.dialog_title_error)
    270             .setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() {
    271                 public void onClick(DialogInterface dialog, int which) {
    272                     finish();
    273                 }})
    274             .setMessage(R.string.invalid_perm_name)
    275             .setOnCancelListener(this)
    276             .create();
    277         }
    278         return null;
    279     }
    280 
    281     private void showDialogInner(int id) {
    282         // TODO better fix for this? Remove dialog so that it gets created again
    283         removeDialog(id);
    284         showDialog(id);
    285     }
    286 
    287     @Override
    288     protected void onResume() {
    289         super.onResume();
    290     }
    291 
    292     @Override
    293     protected void onStop() {
    294         super.onStop();
    295     }
    296 
    297     public void onCancel(DialogInterface dialog) {
    298         finish();
    299     }
    300 
    301     public void onItemClick(AdapterView<?> parent, View view, int position,
    302             long id) {
    303         // TODO Launch app details activity
    304     }
    305 }
    306