• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.development;
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.R;
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     public static final String EXTRA_NON_SYSTEM = "com.android.settings.extra.NON_SYSTEM";
49 
50     private String mPermissionName;
51     private boolean mDebuggableOnly;
52     private boolean mNonSystemOnly;
53 
54     @Override
onCreate(Bundle icicle)55     protected void onCreate(Bundle icicle) {
56         super.onCreate(icicle);
57 
58         mPermissionName = getIntent().getStringExtra(EXTRA_REQUESTIING_PERMISSION);
59         mDebuggableOnly = getIntent().getBooleanExtra(EXTRA_DEBUGGABLE, false);
60         mNonSystemOnly = getIntent().getBooleanExtra(EXTRA_NON_SYSTEM, false);
61 
62         mAdapter = new AppListAdapter(this);
63         if (mAdapter.getCount() <= 0) {
64             finish();
65         } else {
66             setListAdapter(mAdapter);
67         }
68     }
69 
70     @Override
onResume()71     protected void onResume() {
72         super.onResume();
73     }
74 
75     @Override
onStop()76     protected void onStop() {
77         super.onStop();
78     }
79 
80     @Override
onListItemClick(ListView l, View v, int position, long id)81     protected void onListItemClick(ListView l, View v, int position, long id) {
82         MyApplicationInfo app = mAdapter.getItem(position);
83         Intent intent = new Intent();
84         if (app.info != null) intent.setAction(app.info.packageName);
85         setResult(RESULT_OK, intent);
86         finish();
87     }
88 
89     class MyApplicationInfo {
90         ApplicationInfo info;
91         CharSequence label;
92     }
93 
94     public class AppListAdapter extends ArrayAdapter<MyApplicationInfo> {
95         private final List<MyApplicationInfo> mPackageInfoList = new ArrayList<MyApplicationInfo>();
96         private final LayoutInflater mInflater;
97 
AppListAdapter(Context context)98         public AppListAdapter(Context context) {
99             super(context, 0);
100             mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
101             List<ApplicationInfo> pkgs = context.getPackageManager().getInstalledApplications(0);
102             for (int i=0; i<pkgs.size(); i++) {
103                 ApplicationInfo ai = pkgs.get(i);
104                 if (ai.uid == Process.SYSTEM_UID) {
105                     continue;
106                 }
107 
108                 // Filter out apps that are not debuggable if required.
109                 if (mDebuggableOnly) {
110                     // On a user build, we only allow debugging of apps that
111                     // are marked as debuggable.  Otherwise (for platform development)
112                     // we allow all apps.
113                     if ((ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0
114                             && "user".equals(Build.TYPE)) {
115                         continue;
116                     }
117                 }
118 
119                 // Filter out apps that are system apps if requested
120                 if (mNonSystemOnly && ai.isSystemApp()) {
121                     continue;
122                 }
123 
124                 // Filter out apps that do not request the permission if required.
125                 if (mPermissionName != null) {
126                     boolean requestsPermission = false;
127                     try {
128                         PackageInfo pi = getPackageManager().getPackageInfo(ai.packageName,
129                                 PackageManager.GET_PERMISSIONS);
130                         if (pi.requestedPermissions == null) {
131                             continue;
132                         }
133                         for (String requestedPermission : pi.requestedPermissions) {
134                             if (requestedPermission.equals(mPermissionName)) {
135                                 requestsPermission = true;
136                                 break;
137                             }
138                         }
139                         if (!requestsPermission) {
140                             continue;
141                         }
142                     } catch (PackageManager.NameNotFoundException e) {
143                         continue;
144                     }
145                 }
146 
147                 MyApplicationInfo info = new MyApplicationInfo();
148                 info.info = ai;
149                 info.label = info.info.loadLabel(getPackageManager()).toString();
150                 mPackageInfoList.add(info);
151             }
152             Collections.sort(mPackageInfoList, sDisplayNameComparator);
153             MyApplicationInfo info = new MyApplicationInfo();
154             info.label = context.getText(R.string.no_application);
155             mPackageInfoList.add(0, info);
156             addAll(mPackageInfoList);
157         }
158 
159         @Override
getView(int position, View convertView, ViewGroup parent)160         public View getView(int position, View convertView, ViewGroup parent) {
161             // A ViewHolder keeps references to children views to avoid unnecessary calls
162             // to findViewById() on each row.
163             AppViewHolder holder = AppViewHolder.createOrRecycle(mInflater, convertView);
164             convertView = holder.rootView;
165             MyApplicationInfo info = getItem(position);
166             holder.appName.setText(info.label);
167             if (info.info != null) {
168                 holder.appIcon.setImageDrawable(info.info.loadIcon(getPackageManager()));
169                 holder.summary.setText(info.info.packageName);
170             } else {
171                 holder.appIcon.setImageDrawable(null);
172                 holder.summary.setText("");
173             }
174             holder.disabled.setVisibility(View.GONE);
175             return convertView;
176         }
177     }
178 
179     private final static Comparator<MyApplicationInfo> sDisplayNameComparator
180             = new Comparator<MyApplicationInfo>() {
181         public final int
182         compare(MyApplicationInfo a, MyApplicationInfo b) {
183             return collator.compare(a.label, b.label);
184         }
185 
186         private final Collator collator = Collator.getInstance();
187     };
188 }
189