UsageStatsActivity.java revision 1789f7d236bca1583fd3f7eafcf81bbae915e229
1/**
2 * Copyright (C) 2007 The Android Open Source Project
3 *
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
6 * 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16
17package com.android.settings;
18
19import android.app.Activity;
20import android.app.usage.UsageStats;
21import android.app.usage.UsageStatsManager;
22import android.content.Context;
23import android.content.pm.ApplicationInfo;
24import android.content.pm.PackageManager;
25import android.content.pm.PackageManager.NameNotFoundException;
26import android.os.Bundle;
27
28import java.text.DateFormat;
29import java.util.ArrayList;
30import java.util.Calendar;
31import java.util.Collections;
32import java.util.Comparator;
33import java.util.List;
34import java.util.Map;
35
36import android.text.format.DateUtils;
37import android.util.ArrayMap;
38import android.util.Log;
39import android.view.LayoutInflater;
40import android.view.View;
41import android.view.ViewGroup;
42import android.widget.AdapterView;
43import android.widget.BaseAdapter;
44import android.widget.ListView;
45import android.widget.Spinner;
46import android.widget.TextView;
47import android.widget.AdapterView.OnItemSelectedListener;
48
49/**
50 * Activity to display package usage statistics.
51 */
52public class UsageStatsActivity extends Activity implements OnItemSelectedListener {
53    private static final String TAG = "UsageStatsActivity";
54    private static final boolean localLOGV = false;
55    private UsageStatsManager mUsageStatsManager;
56    private LayoutInflater mInflater;
57    private UsageStatsAdapter mAdapter;
58    private PackageManager mPm;
59
60    public static class AppNameComparator implements Comparator<UsageStats> {
61        private Map<String, String> mAppLabelList;
62
63        AppNameComparator(Map<String, String> appList) {
64            mAppLabelList = appList;
65        }
66
67        @Override
68        public final int compare(UsageStats a, UsageStats b) {
69            String alabel = mAppLabelList.get(a.getPackageName());
70            String blabel = mAppLabelList.get(b.getPackageName());
71            return alabel.compareTo(blabel);
72        }
73    }
74
75    public static class LastTimeUsedComparator implements Comparator<UsageStats> {
76        @Override
77        public final int compare(UsageStats a, UsageStats b) {
78            // return by descending order
79            return (int)(b.getLastTimeUsed() - a.getLastTimeUsed());
80        }
81    }
82
83    public static class UsageTimeComparator implements Comparator<UsageStats> {
84        @Override
85        public final int compare(UsageStats a, UsageStats b) {
86            return (int)(b.getTotalTimeInForeground() - a.getTotalTimeInForeground());
87        }
88    }
89
90    // View Holder used when displaying views
91    static class AppViewHolder {
92        TextView pkgName;
93        TextView lastTimeUsed;
94        TextView usageTime;
95    }
96
97    class UsageStatsAdapter extends BaseAdapter {
98         // Constants defining order for display order
99        private static final int _DISPLAY_ORDER_USAGE_TIME = 0;
100        private static final int _DISPLAY_ORDER_LAST_TIME_USED = 1;
101        private static final int _DISPLAY_ORDER_APP_NAME = 2;
102
103        private int mDisplayOrder = _DISPLAY_ORDER_USAGE_TIME;
104        private LastTimeUsedComparator mLastTimeUsedComparator = new LastTimeUsedComparator();
105        private UsageTimeComparator mUsageTimeComparator = new UsageTimeComparator();
106        private AppNameComparator mAppLabelComparator;
107        private final ArrayMap<String, String> mAppLabelMap = new ArrayMap<>();
108        private final ArrayList<UsageStats> mPackageStats = new ArrayList<>();
109
110        UsageStatsAdapter() {
111            Calendar cal = Calendar.getInstance();
112            cal.add(Calendar.DAY_OF_YEAR, -5);
113
114            final List<UsageStats> stats =
115                    mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST,
116                            cal.getTimeInMillis(), System.currentTimeMillis());
117            if (stats == null) {
118                return;
119            }
120
121            ArrayMap<String, UsageStats> map = new ArrayMap<>();
122            final int statCount = stats.size();
123            for (int i = 0; i < statCount; i++) {
124                final android.app.usage.UsageStats pkgStats = stats.get(i);
125
126                // load application labels for each application
127                try {
128                    ApplicationInfo appInfo = mPm.getApplicationInfo(pkgStats.getPackageName(), 0);
129                    String label = appInfo.loadLabel(mPm).toString();
130                    mAppLabelMap.put(pkgStats.getPackageName(), label);
131
132                    UsageStats existingStats =
133                            map.get(pkgStats.getPackageName());
134                    if (existingStats == null) {
135                        map.put(pkgStats.getPackageName(), pkgStats);
136                    } else {
137                        existingStats.add(pkgStats);
138                    }
139
140                } catch (NameNotFoundException e) {
141                    // This package may be gone.
142                }
143            }
144            mPackageStats.addAll(map.values());
145
146            // Sort list
147            mAppLabelComparator = new AppNameComparator(mAppLabelMap);
148            sortList();
149        }
150
151        @Override
152        public int getCount() {
153            return mPackageStats.size();
154        }
155
156        @Override
157        public Object getItem(int position) {
158            return mPackageStats.get(position);
159        }
160
161        @Override
162        public long getItemId(int position) {
163            return position;
164        }
165
166        @Override
167        public View getView(int position, View convertView, ViewGroup parent) {
168            // A ViewHolder keeps references to children views to avoid unneccessary calls
169            // to findViewById() on each row.
170            AppViewHolder holder;
171
172            // When convertView is not null, we can reuse it directly, there is no need
173            // to reinflate it. We only inflate a new View when the convertView supplied
174            // by ListView is null.
175            if (convertView == null) {
176                convertView = mInflater.inflate(R.layout.usage_stats_item, null);
177
178                // Creates a ViewHolder and store references to the two children views
179                // we want to bind data to.
180                holder = new AppViewHolder();
181                holder.pkgName = (TextView) convertView.findViewById(R.id.package_name);
182                holder.lastTimeUsed = (TextView) convertView.findViewById(R.id.last_time_used);
183                holder.usageTime = (TextView) convertView.findViewById(R.id.usage_time);
184                convertView.setTag(holder);
185            } else {
186                // Get the ViewHolder back to get fast access to the TextView
187                // and the ImageView.
188                holder = (AppViewHolder) convertView.getTag();
189            }
190
191            // Bind the data efficiently with the holder
192            UsageStats pkgStats = mPackageStats.get(position);
193            if (pkgStats != null) {
194                String label = mAppLabelMap.get(pkgStats.getPackageName());
195                holder.pkgName.setText(label);
196                holder.lastTimeUsed.setText(DateUtils.formatSameDayTime(pkgStats.getLastTimeUsed(),
197                        System.currentTimeMillis(), DateFormat.MEDIUM, DateFormat.MEDIUM));
198                holder.usageTime.setText(
199                        DateUtils.formatElapsedTime(pkgStats.getTotalTimeInForeground() / 1000));
200            } else {
201                Log.w(TAG, "No usage stats info for package:" + position);
202            }
203            return convertView;
204        }
205
206        void sortList(int sortOrder) {
207            if (mDisplayOrder == sortOrder) {
208                // do nothing
209                return;
210            }
211            mDisplayOrder= sortOrder;
212            sortList();
213        }
214        private void sortList() {
215            if (mDisplayOrder == _DISPLAY_ORDER_USAGE_TIME) {
216                if (localLOGV) Log.i(TAG, "Sorting by usage time");
217                Collections.sort(mPackageStats, mUsageTimeComparator);
218            } else if (mDisplayOrder == _DISPLAY_ORDER_LAST_TIME_USED) {
219                if (localLOGV) Log.i(TAG, "Sorting by last time used");
220                Collections.sort(mPackageStats, mLastTimeUsedComparator);
221            } else if (mDisplayOrder == _DISPLAY_ORDER_APP_NAME) {
222                if (localLOGV) Log.i(TAG, "Sorting by application name");
223                Collections.sort(mPackageStats, mAppLabelComparator);
224            }
225            notifyDataSetChanged();
226        }
227    }
228
229    /** Called when the activity is first created. */
230    @Override
231    protected void onCreate(Bundle icicle) {
232        super.onCreate(icicle);
233        setContentView(R.layout.usage_stats);
234
235        mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
236        mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
237        mPm = getPackageManager();
238
239        Spinner typeSpinner = (Spinner) findViewById(R.id.typeSpinner);
240        typeSpinner.setOnItemSelectedListener(this);
241
242        ListView listView = (ListView) findViewById(R.id.pkg_list);
243        mAdapter = new UsageStatsAdapter();
244        listView.setAdapter(mAdapter);
245    }
246
247    @Override
248    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
249        mAdapter.sortList(position);
250    }
251
252    @Override
253    public void onNothingSelected(AdapterView<?> parent) {
254        // do nothing
255    }
256}
257