4 * Copyright (C) 2007 The Android Open Source Project
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
19 package com.android.settings;
21 import com.android.internal.app.IUsageStats;
22 import com.android.settings.R;
23 import android.app.Activity;
24 import android.content.Context;
25 import android.content.pm.ApplicationInfo;
26 import android.content.pm.PackageManager;
27 import android.content.pm.PackageManager.NameNotFoundException;
28 import android.os.Bundle;
29 import android.os.RemoteException;
30 import android.os.ServiceManager;
31 import com.android.internal.os.PkgUsageStats;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.Comparator;
35 import java.util.HashMap;
36 import java.util.List;
39 import android.util.Log;
40 import android.view.LayoutInflater;
41 import android.view.View;
42 import android.view.ViewGroup;
43 import android.widget.AdapterView;
44 import android.widget.BaseAdapter;
45 import android.widget.ListView;
46 import android.widget.Spinner;
47 import android.widget.TextView;
48 import android.widget.AdapterView.OnItemSelectedListener;
51 * Activity to display package usage statistics.
53 public class UsageStats extends Activity implements OnItemSelectedListener {
54 private static final String TAG="UsageStatsActivity";
55 private static final boolean localLOGV = false;
56 private Spinner mTypeSpinner;
57 private ListView mListView;
58 private IUsageStats mUsageStatsService;
59 private LayoutInflater mInflater;
60 private UsageStatsAdapter mAdapter;
61 private PackageManager mPm;
63 public static class AppNameComparator implements Comparator<PkgUsageStats> {
64 Map<String, CharSequence> mAppLabelList;
65 AppNameComparator(Map<String, CharSequence> appList) {
66 mAppLabelList = appList;
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);
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;
82 public static class UsageTimeComparator implements Comparator<PkgUsageStats> {
83 public final int compare(PkgUsageStats a, PkgUsageStats b) {
84 long ret = a.usageTime-b.usageTime;
95 // View Holder used when displaying views
96 static class AppViewHolder {
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;
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;
115 UsageStatsAdapter() {
116 mUsageStats = new ArrayList<PkgUsageStats>();
117 mAppLabelMap = new HashMap<String, CharSequence>();
118 PkgUsageStats[] stats;
120 stats = mUsageStatsService.getAllPkgUsageStats();
121 } catch (RemoteException e) {
122 Log.e(TAG, "Failed initializing usage stats service");
128 for (PkgUsageStats ps : stats) {
130 // load application labels for each application
133 ApplicationInfo appInfo = mPm.getApplicationInfo(ps.packageName, 0);
134 label = appInfo.loadLabel(mPm);
135 } catch (NameNotFoundException e) {
136 label = ps.packageName;
138 mAppLabelMap.put(ps.packageName, label);
141 mLaunchCountComparator = new LaunchCountComparator();
142 mUsageTimeComparator = new UsageTimeComparator();
143 mAppLabelComparator = new AppNameComparator(mAppLabelMap);
146 public int getCount() {
147 return mUsageStats.size();
150 public Object getItem(int position) {
151 return mUsageStats.get(position);
154 public long getItemId(int position) {
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;
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);
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);
177 // Get the ViewHolder back to get fast access to the TextView
178 // and the ImageView.
179 holder = (AppViewHolder) convertView.getTag();
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");
190 Log.w(TAG, "No usage stats info for package:" + position);
195 void sortList(int sortOrder) {
196 if (mDisplayOrder == sortOrder) {
200 mDisplayOrder= sortOrder;
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);
214 notifyDataSetChanged();
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");
226 mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
227 mPm = getPackageManager();
229 setContentView(R.layout.usage_stats);
230 mTypeSpinner = (Spinner) findViewById(R.id.typeSpinner);
231 mTypeSpinner.setOnItemSelectedListener(this);
233 mListView = (ListView) findViewById(R.id.pkg_list);
234 // Initialize the inflater
236 mAdapter = new UsageStatsAdapter();
237 mListView.setAdapter(mAdapter);
240 public void onItemSelected(AdapterView<?> parent, View view, int position,
242 mAdapter.sortList(position);
245 public void onNothingSelected(AdapterView<?> parent) {