2 * Copyright (C) 2007 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
17 package com.android.settings;
19 import android.app.Activity;
20 import android.app.usage.UsageStats;
21 import android.app.usage.UsageStatsManager;
22 import android.content.Context;
23 import android.content.pm.ApplicationInfo;
24 import android.content.pm.PackageManager;
25 import android.content.pm.PackageManager.NameNotFoundException;
26 import android.os.Bundle;
27 import android.text.format.DateUtils;
28 import android.util.ArrayMap;
29 import android.util.Log;
30 import android.view.LayoutInflater;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import android.widget.AdapterView;
34 import android.widget.AdapterView.OnItemSelectedListener;
35 import android.widget.BaseAdapter;
36 import android.widget.ListView;
37 import android.widget.Spinner;
38 import android.widget.TextView;
40 import java.text.DateFormat;
41 import java.util.ArrayList;
42 import java.util.Calendar;
43 import java.util.Collections;
44 import java.util.Comparator;
45 import java.util.List;
49 * Activity to display package usage statistics.
51 public class UsageStatsActivity extends Activity implements OnItemSelectedListener {
52 private static final String TAG = "UsageStatsActivity";
53 private static final boolean localLOGV = false;
54 private UsageStatsManager mUsageStatsManager;
55 private LayoutInflater mInflater;
56 private UsageStatsAdapter mAdapter;
57 private PackageManager mPm;
59 public static class AppNameComparator implements Comparator<UsageStats> {
60 private Map<String, String> mAppLabelList;
62 AppNameComparator(Map<String, String> appList) {
63 mAppLabelList = appList;
67 public final int compare(UsageStats a, UsageStats b) {
68 String alabel = mAppLabelList.get(a.getPackageName());
69 String blabel = mAppLabelList.get(b.getPackageName());
70 return alabel.compareTo(blabel);
74 public static class LastTimeUsedComparator implements Comparator<UsageStats> {
76 public final int compare(UsageStats a, UsageStats b) {
77 // return by descending order
78 return Long.compare(b.getLastTimeUsed(), a.getLastTimeUsed());
82 public static class UsageTimeComparator implements Comparator<UsageStats> {
84 public final int compare(UsageStats a, UsageStats b) {
85 return Long.compare(b.getTotalTimeInForeground(), a.getTotalTimeInForeground());
89 // View Holder used when displaying views
90 static class AppViewHolder {
92 TextView lastTimeUsed;
96 class UsageStatsAdapter extends BaseAdapter {
97 // Constants defining order for display order
98 private static final int _DISPLAY_ORDER_USAGE_TIME = 0;
99 private static final int _DISPLAY_ORDER_LAST_TIME_USED = 1;
100 private static final int _DISPLAY_ORDER_APP_NAME = 2;
102 private int mDisplayOrder = _DISPLAY_ORDER_USAGE_TIME;
103 private LastTimeUsedComparator mLastTimeUsedComparator = new LastTimeUsedComparator();
104 private UsageTimeComparator mUsageTimeComparator = new UsageTimeComparator();
105 private AppNameComparator mAppLabelComparator;
106 private final ArrayMap<String, String> mAppLabelMap = new ArrayMap<>();
107 private final ArrayList<UsageStats> mPackageStats = new ArrayList<>();
109 UsageStatsAdapter() {
110 Calendar cal = Calendar.getInstance();
111 cal.add(Calendar.DAY_OF_YEAR, -5);
113 final List<UsageStats> stats =
114 mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST,
115 cal.getTimeInMillis(), System.currentTimeMillis());
120 ArrayMap<String, UsageStats> map = new ArrayMap<>();
121 final int statCount = stats.size();
122 for (int i = 0; i < statCount; i++) {
123 final android.app.usage.UsageStats pkgStats = stats.get(i);
125 // load application labels for each application
127 ApplicationInfo appInfo = mPm.getApplicationInfo(pkgStats.getPackageName(), 0);
128 String label = appInfo.loadLabel(mPm).toString();
129 mAppLabelMap.put(pkgStats.getPackageName(), label);
131 UsageStats existingStats =
132 map.get(pkgStats.getPackageName());
133 if (existingStats == null) {
134 map.put(pkgStats.getPackageName(), pkgStats);
136 existingStats.add(pkgStats);
139 } catch (NameNotFoundException e) {
140 // This package may be gone.
143 mPackageStats.addAll(map.values());
146 mAppLabelComparator = new AppNameComparator(mAppLabelMap);
151 public int getCount() {
152 return mPackageStats.size();
156 public Object getItem(int position) {
157 return mPackageStats.get(position);
161 public long getItemId(int position) {
166 public View getView(int position, View convertView, ViewGroup parent) {
167 // A ViewHolder keeps references to children views to avoid unneccessary calls
168 // to findViewById() on each row.
169 AppViewHolder holder;
171 // When convertView is not null, we can reuse it directly, there is no need
172 // to reinflate it. We only inflate a new View when the convertView supplied
173 // by ListView is null.
174 if (convertView == null) {
175 convertView = mInflater.inflate(R.layout.usage_stats_item, null);
177 // Creates a ViewHolder and store references to the two children views
178 // we want to bind data to.
179 holder = new AppViewHolder();
180 holder.pkgName = (TextView) convertView.findViewById(R.id.package_name);
181 holder.lastTimeUsed = (TextView) convertView.findViewById(R.id.last_time_used);
182 holder.usageTime = (TextView) convertView.findViewById(R.id.usage_time);
183 convertView.setTag(holder);
185 // Get the ViewHolder back to get fast access to the TextView
186 // and the ImageView.
187 holder = (AppViewHolder) convertView.getTag();
190 // Bind the data efficiently with the holder
191 UsageStats pkgStats = mPackageStats.get(position);
192 if (pkgStats != null) {
193 String label = mAppLabelMap.get(pkgStats.getPackageName());
194 holder.pkgName.setText(label);
195 holder.lastTimeUsed.setText(DateUtils.formatSameDayTime(pkgStats.getLastTimeUsed(),
196 System.currentTimeMillis(), DateFormat.MEDIUM, DateFormat.MEDIUM));
197 holder.usageTime.setText(
198 DateUtils.formatElapsedTime(pkgStats.getTotalTimeInForeground() / 1000));
200 Log.w(TAG, "No usage stats info for package:" + position);
205 void sortList(int sortOrder) {
206 if (mDisplayOrder == sortOrder) {
210 mDisplayOrder= sortOrder;
213 private void sortList() {
214 if (mDisplayOrder == _DISPLAY_ORDER_USAGE_TIME) {
215 if (localLOGV) Log.i(TAG, "Sorting by usage time");
216 Collections.sort(mPackageStats, mUsageTimeComparator);
217 } else if (mDisplayOrder == _DISPLAY_ORDER_LAST_TIME_USED) {
218 if (localLOGV) Log.i(TAG, "Sorting by last time used");
219 Collections.sort(mPackageStats, mLastTimeUsedComparator);
220 } else if (mDisplayOrder == _DISPLAY_ORDER_APP_NAME) {
221 if (localLOGV) Log.i(TAG, "Sorting by application name");
222 Collections.sort(mPackageStats, mAppLabelComparator);
224 notifyDataSetChanged();
228 /** Called when the activity is first created. */
230 protected void onCreate(Bundle icicle) {
231 super.onCreate(icicle);
232 setContentView(R.layout.usage_stats);
234 mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
235 mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
236 mPm = getPackageManager();
238 Spinner typeSpinner = (Spinner) findViewById(R.id.typeSpinner);
239 typeSpinner.setOnItemSelectedListener(this);
241 ListView listView = (ListView) findViewById(R.id.pkg_list);
242 mAdapter = new UsageStatsAdapter();
243 listView.setAdapter(mAdapter);
247 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
248 mAdapter.sortList(position);
252 public void onNothingSelected(AdapterView<?> parent) {