1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings;
18 
19 import android.app.ListActivity;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.pm.ApplicationInfo;
23 import android.content.pm.PackageInfo;
24 import android.content.pm.PackageManager;
25 import android.os.Build;
26 import android.os.Bundle;
27 import android.os.Process;
28 import android.view.LayoutInflater;
29 import android.view.View;
30 import android.view.ViewGroup;
31 import android.widget.ArrayAdapter;
32 import android.widget.ListView;
33 
34 import com.android.settings.applications.AppViewHolder;
35 
36 import java.text.Collator;
37 import java.util.ArrayList;
38 import java.util.Collections;
39 import java.util.Comparator;
40 import java.util.List;
41 
42 public class AppPicker extends ListActivity {
43     private AppListAdapter mAdapter;
44 
45     public static final String EXTRA_REQUESTIING_PERMISSION
46             = "com.android.settings.extra.REQUESTIING_PERMISSION";
47     public static final String EXTRA_DEBUGGABLE = "com.android.settings.extra.DEBUGGABLE";
48 
49     private String mPermissionName;
50     private boolean mDebuggableOnly;
51 
52     @Override
onCreate(Bundle icicle)53     protected void onCreate(Bundle icicle) {
54         super.onCreate(icicle);
55 
56         mPermissionName = getIntent().getStringExtra(EXTRA_REQUESTIING_PERMISSION);
57         mDebuggableOnly = getIntent().getBooleanExtra(EXTRA_DEBUGGABLE, false);
58 
59         mAdapter = new AppListAdapter(this);
60         if (mAdapter.getCount() <= 0) {
61             finish();
62         } else {
63             setListAdapter(mAdapter);
64         }
65     }
66 
67     @Override
onResume()68     protected void onResume() {
69         super.onResume();
70     }
71 
72     @Override
onStop()73     protected void onStop() {
74         super.onStop();
75     }
76 
77     @Override
onListItemClick(ListView l, View v, int position, long id)78     protected void onListItemClick(ListView l, View v, int position, long id) {
79         MyApplicationInfo app = mAdapter.getItem(position);
80         Intent intent = new Intent();
81         if (app.info != null) intent.setAction(app.info.packageName);
82         setResult(RESULT_OK, intent);
83         finish();
84     }
85 
86     class MyApplicationInfo {
87         ApplicationInfo info;
88         CharSequence label;
89     }
90 
91     public class AppListAdapter extends ArrayAdapter<MyApplicationInfo> {
92         private final List<MyApplicationInfo> mPackageInfoList = new ArrayList<MyApplicationInfo>();
93         private final LayoutInflater mInflater;
94 
AppListAdapter(Context context)95         public AppListAdapter(Context context) {
96             super(context, 0);
97             mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
98             List<ApplicationInfo> pkgs = context.getPackageManager().getInstalledApplications(0);
99             for (int i=0; i<pkgs.size(); i++) {
100                 ApplicationInfo ai = pkgs.get(i);
101                 if (ai.uid == Process.SYSTEM_UID) {
102                     continue;
103                 }
104 
105                 // Filter out apps that are not debuggable if required.
106                 if (mDebuggableOnly) {
107                     // On a user build, we only allow debugging of apps that
108                     // are marked as debuggable.  Otherwise (for platform development)
109                     // we allow all apps.
110                     if ((ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0
111                             && "user".equals(Build.TYPE)) {
112                         continue;
113                     }
114                 }
115 
116                 // Filter out apps that do not request the permission if required.
117                 if (mPermissionName != null) {
118                     boolean requestsPermission = false;
119                     try {
120                         PackageInfo pi = getPackageManager().getPackageInfo(ai.packageName,
121                                 PackageManager.GET_PERMISSIONS);
122                         if (pi.requestedPermissions == null) {
123                             continue;
124                         }
125                         for (String requestedPermission : pi.requestedPermissions) {
126                             if (requestedPermission.equals(mPermissionName)) {
127                                 requestsPermission = true;
128                                 break;
129                             }
130                         }
131                         if (!requestsPermission) {
132                             continue;
133                         }
134                     } catch (PackageManager.NameNotFoundException e) {
135                         continue;
136                     }
137                 }
138 
139                 MyApplicationInfo info = new MyApplicationInfo();
140                 info.info = ai;
141                 info.label = info.info.loadLabel(getPackageManager()).toString();
142                 mPackageInfoList.add(info);
143             }
144             Collections.sort(mPackageInfoList, sDisplayNameComparator);
145             MyApplicationInfo info = new MyApplicationInfo();
146             info.label = context.getText(R.string.no_application);
147             mPackageInfoList.add(0, info);
148             addAll(mPackageInfoList);
149         }
150 
151         @Override
getView(int position, View convertView, ViewGroup parent)152         public View getView(int position, View convertView, ViewGroup parent) {
153             // A ViewHolder keeps references to children views to avoid unnecessary calls
154             // to findViewById() on each row.
155             AppViewHolder holder = AppViewHolder.createOrRecycle(mInflater, convertView);
156             convertView = holder.rootView;
157             MyApplicationInfo info = getItem(position);
158             holder.appName.setText(info.label);
159             if (info.info != null) {
160                 holder.appIcon.setImageDrawable(info.info.loadIcon(getPackageManager()));
161                 holder.summary.setText(info.info.packageName);
162             } else {
163                 holder.appIcon.setImageDrawable(null);
164                 holder.summary.setText("");
165             }
166             holder.disabled.setVisibility(View.GONE);
167             return convertView;
168         }
169     }
170 
171     private final static Comparator<MyApplicationInfo> sDisplayNameComparator
172             = new Comparator<MyApplicationInfo>() {
173         public final int
174         compare(MyApplicationInfo a, MyApplicationInfo b) {
175             return collator.compare(a.label, b.label);
176         }
177 
178         private final Collator collator = Collator.getInstance();
179     };
180 }
181