blob: 89caa5485ef21cbf844556b4664a3d96ae971b8c [file] [log] [blame]
The Android Open Source Project1feaa852009-02-10 15:44:05 -08001
2
3/**
4 * Copyright (C) 2007 The Android Open Source Project
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
7 * use this file except in compliance with the License. You may obtain a copy
8 * of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 * License for the specific language governing permissions and limitations
16 * under the License.
17 */
18
19package com.android.settings;
20
21import com.android.internal.app.IUsageStats;
22import com.android.settings.R;
23import android.app.Activity;
24import android.content.Context;
25import android.content.pm.ApplicationInfo;
26import android.content.pm.PackageManager;
27import android.content.pm.PackageManager.NameNotFoundException;
28import android.os.Bundle;
29import android.os.RemoteException;
30import android.os.ServiceManager;
31import com.android.internal.os.PkgUsageStats;
32import java.util.ArrayList;
33import java.util.Collections;
34import java.util.Comparator;
35import java.util.HashMap;
36import java.util.List;
37import java.util.Map;
38
39import android.util.Log;
40import android.view.LayoutInflater;
41import android.view.View;
42import android.view.ViewGroup;
43import android.widget.AdapterView;
44import android.widget.BaseAdapter;
45import android.widget.ListView;
46import android.widget.Spinner;
47import android.widget.TextView;
48import android.widget.AdapterView.OnItemSelectedListener;
49
50/**
51 * Activity to display package usage statistics.
52 */
53public class UsageStats extends Activity implements OnItemSelectedListener {
54 private static final String TAG="UsageStatsActivity";
55 private static final boolean localLOGV = true;
56 private Spinner mTypeSpinner;
57 private ListView mListView;
58 private IUsageStats mUsageStatsService;
59 private LayoutInflater mInflater;
60 private UsageStatsAdapter mAdapter;
61 private PackageManager mPm;
62
63 public static class AppNameComparator implements Comparator<PkgUsageStats> {
64 Map<String, CharSequence> mAppLabelList;
65 AppNameComparator(Map<String, CharSequence> appList) {
66 mAppLabelList = appList;
67 }
68 public final int compare(PkgUsageStats a, PkgUsageStats b) {
69 String alabel = mAppLabelList.get(a.packageName).toString();
70 String blabel = mAppLabelList.get(b.packageName).toString();
71 return alabel.compareTo(blabel);
72 }
73 }
74
75 public static class LaunchCountComparator implements Comparator<PkgUsageStats> {
76 public final int compare(PkgUsageStats a, PkgUsageStats b) {
77 // return by descending order
78 return b.launchCount - a.launchCount;
79 }
80 }
81
82 public static class UsageTimeComparator implements Comparator<PkgUsageStats> {
83 public final int compare(PkgUsageStats a, PkgUsageStats b) {
84 long ret = a.usageTime-b.usageTime;
85 if (ret == 0) {
86 return 0;
87 }
88 if (ret < 0) {
89 return 1;
90 }
91 return -1;
92 }
93 }
94
95 // View Holder used when displaying views
96 static class AppViewHolder {
97 TextView pkgName;
98 TextView launchCount;
99 TextView usageTime;
100 }
101
102 class UsageStatsAdapter extends BaseAdapter {
103 // Constants defining order for display order
104 private static final int _DISPLAY_ORDER_USAGE_TIME = 0;
105 private static final int _DISPLAY_ORDER_LAUNCH_COUNT = 1;
106 private static final int _DISPLAY_ORDER_APP_NAME = 2;
107
108 private int mDisplayOrder = _DISPLAY_ORDER_USAGE_TIME;
109 private List<PkgUsageStats> mUsageStats;
110 private LaunchCountComparator mLaunchCountComparator;
111 private UsageTimeComparator mUsageTimeComparator;
112 private AppNameComparator mAppLabelComparator;
113 private HashMap<String, CharSequence> mAppLabelMap;
114
115 UsageStatsAdapter() {
116 mUsageStats = new ArrayList<PkgUsageStats>();
117 mAppLabelMap = new HashMap<String, CharSequence>();
118 PkgUsageStats[] stats;
119 try {
120 stats = mUsageStatsService.getAllPkgUsageStats();
121 } catch (RemoteException e) {
122 Log.e(TAG, "Failed initializing usage stats service");
123 return;
124 }
125 if (stats == null) {
126 return;
127 }
128 for (PkgUsageStats ps : stats) {
129 mUsageStats.add(ps);
130 // load application labels for each application
131 CharSequence label;
132 try {
133 ApplicationInfo appInfo = mPm.getApplicationInfo(ps.packageName, 0);
134 label = appInfo.loadLabel(mPm);
135 } catch (NameNotFoundException e) {
136 label = ps.packageName;
137 }
138 mAppLabelMap.put(ps.packageName, label);
139 }
140 // Sort list
141 mLaunchCountComparator = new LaunchCountComparator();
142 mUsageTimeComparator = new UsageTimeComparator();
143 mAppLabelComparator = new AppNameComparator(mAppLabelMap);
144 sortList();
145 }
146 public int getCount() {
147 return mUsageStats.size();
148 }
149
150 public Object getItem(int position) {
151 return mUsageStats.get(position);
152 }
153
154 public long getItemId(int position) {
155 return position;
156 }
157
158 public View getView(int position, View convertView, ViewGroup parent) {
159 // A ViewHolder keeps references to children views to avoid unneccessary calls
160 // to findViewById() on each row.
161 AppViewHolder holder;
162
163 // When convertView is not null, we can reuse it directly, there is no need
164 // to reinflate it. We only inflate a new View when the convertView supplied
165 // by ListView is null.
166 if (convertView == null) {
167 convertView = mInflater.inflate(R.layout.usage_stats_item, null);
168
169 // Creates a ViewHolder and store references to the two children views
170 // we want to bind data to.
171 holder = new AppViewHolder();
172 holder.pkgName = (TextView) convertView.findViewById(R.id.package_name);
173 holder.launchCount = (TextView) convertView.findViewById(R.id.launch_count);
174 holder.usageTime = (TextView) convertView.findViewById(R.id.usage_time);
175 convertView.setTag(holder);
176 } else {
177 // Get the ViewHolder back to get fast access to the TextView
178 // and the ImageView.
179 holder = (AppViewHolder) convertView.getTag();
180 }
181
182 // Bind the data efficiently with the holder
183 PkgUsageStats pkgStats = mUsageStats.get(position);
184 if (pkgStats != null) {
185 CharSequence label = mAppLabelMap.get(pkgStats.packageName);
186 holder.pkgName.setText(label);
187 holder.launchCount.setText(String.valueOf(pkgStats.launchCount));
188 holder.usageTime.setText(String.valueOf(pkgStats.usageTime)+" ms");
189 } else {
190 Log.w(TAG, "No usage stats info for package:"+pkgStats.packageName);
191 }
192 return convertView;
193 }
194
195 void sortList(int sortOrder) {
196 if (mDisplayOrder == sortOrder) {
197 // do nothing
198 return;
199 }
200 mDisplayOrder= sortOrder;
201 sortList();
202 }
203 private void sortList() {
204 if (mDisplayOrder == _DISPLAY_ORDER_USAGE_TIME) {
205 if (localLOGV) Log.i(TAG, "Sorting by usage time");
206 Collections.sort(mUsageStats, mUsageTimeComparator);
207 } else if (mDisplayOrder == _DISPLAY_ORDER_LAUNCH_COUNT) {
208 if (localLOGV) Log.i(TAG, "Sorting launch count");
209 Collections.sort(mUsageStats, mLaunchCountComparator);
210 } else if (mDisplayOrder == _DISPLAY_ORDER_APP_NAME) {
211 if (localLOGV) Log.i(TAG, "Sorting by application name");
212 Collections.sort(mUsageStats, mAppLabelComparator);
213 }
214 notifyDataSetChanged();
215 }
216 }
217
218 /** Called when the activity is first created. */
219 protected void onCreate(Bundle icicle) {
220 super.onCreate(icicle);
221 mUsageStatsService = IUsageStats.Stub.asInterface(ServiceManager.getService("usagestats"));
222 if (mUsageStatsService == null) {
223 Log.e(TAG, "Failed to retrieve usagestats service");
224 return;
225 }
226 mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
227 mPm = getPackageManager();
228
229 setContentView(R.layout.usage_stats);
230 mTypeSpinner = (Spinner) findViewById(R.id.typeSpinner);
231 mTypeSpinner.setOnItemSelectedListener(this);
232
233 mListView = (ListView) findViewById(R.id.pkg_list);
234 // Initialize the inflater
235
236 mAdapter = new UsageStatsAdapter();
237 mListView.setAdapter(mAdapter);
238 }
239
240 public void onItemSelected(AdapterView<?> parent, View view, int position,
241 long id) {
242 mAdapter.sortList(position);
243 }
244
245 public void onNothingSelected(AdapterView<?> parent) {
246 // do nothing
247 }
248}
249