| /** | |
| * Copyright (C) 2007 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not | |
| * use this file except in compliance with the License. You may obtain a copy | |
| * of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |
| * License for the specific language governing permissions and limitations | |
| * under the License. | |
| */ | |
| package com.android.settings; | |
| import android.app.Activity; | |
| import android.app.usage.UsageStats; | |
| import android.app.usage.UsageStatsManager; | |
| import android.content.Context; | |
| import android.content.pm.ApplicationInfo; | |
| import android.content.pm.PackageManager; | |
| import android.content.pm.PackageManager.NameNotFoundException; | |
| import android.os.Bundle; | |
| import android.text.format.DateUtils; | |
| import android.util.ArrayMap; | |
| import android.util.Log; | |
| import android.view.LayoutInflater; | |
| import android.view.View; | |
| import android.view.ViewGroup; | |
| import android.widget.AdapterView; | |
| import android.widget.AdapterView.OnItemSelectedListener; | |
| import android.widget.BaseAdapter; | |
| import android.widget.ListView; | |
| import android.widget.Spinner; | |
| import android.widget.TextView; | |
| import java.text.DateFormat; | |
| import java.util.ArrayList; | |
| import java.util.Calendar; | |
| import java.util.Collections; | |
| import java.util.Comparator; | |
| import java.util.List; | |
| import java.util.Map; | |
| /** | |
| * Activity to display package usage statistics. | |
| */ | |
| public class UsageStatsActivity extends Activity implements OnItemSelectedListener { | |
| private static final String TAG = "UsageStatsActivity"; | |
| private static final boolean localLOGV = false; | |
| private UsageStatsManager mUsageStatsManager; | |
| private LayoutInflater mInflater; | |
| private UsageStatsAdapter mAdapter; | |
| private PackageManager mPm; | |
| public static class AppNameComparator implements Comparator<UsageStats> { | |
| private Map<String, String> mAppLabelList; | |
| AppNameComparator(Map<String, String> appList) { | |
| mAppLabelList = appList; | |
| } | |
| @Override | |
| public final int compare(UsageStats a, UsageStats b) { | |
| String alabel = mAppLabelList.get(a.getPackageName()); | |
| String blabel = mAppLabelList.get(b.getPackageName()); | |
| return alabel.compareTo(blabel); | |
| } | |
| } | |
| public static class LastTimeUsedComparator implements Comparator<UsageStats> { | |
| @Override | |
| public final int compare(UsageStats a, UsageStats b) { | |
| // return by descending order | |
| return (int)(b.getLastTimeUsed() - a.getLastTimeUsed()); | |
| } | |
| } | |
| public static class UsageTimeComparator implements Comparator<UsageStats> { | |
| @Override | |
| public final int compare(UsageStats a, UsageStats b) { | |
| return (int)(b.getTotalTimeInForeground() - a.getTotalTimeInForeground()); | |
| } | |
| } | |
| // View Holder used when displaying views | |
| static class AppViewHolder { | |
| TextView pkgName; | |
| TextView lastTimeUsed; | |
| TextView usageTime; | |
| } | |
| class UsageStatsAdapter extends BaseAdapter { | |
| // Constants defining order for display order | |
| private static final int _DISPLAY_ORDER_USAGE_TIME = 0; | |
| private static final int _DISPLAY_ORDER_LAST_TIME_USED = 1; | |
| private static final int _DISPLAY_ORDER_APP_NAME = 2; | |
| private int mDisplayOrder = _DISPLAY_ORDER_USAGE_TIME; | |
| private LastTimeUsedComparator mLastTimeUsedComparator = new LastTimeUsedComparator(); | |
| private UsageTimeComparator mUsageTimeComparator = new UsageTimeComparator(); | |
| private AppNameComparator mAppLabelComparator; | |
| private final ArrayMap<String, String> mAppLabelMap = new ArrayMap<>(); | |
| private final ArrayList<UsageStats> mPackageStats = new ArrayList<>(); | |
| UsageStatsAdapter() { | |
| Calendar cal = Calendar.getInstance(); | |
| cal.add(Calendar.DAY_OF_YEAR, -5); | |
| final List<UsageStats> stats = | |
| mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, | |
| cal.getTimeInMillis(), System.currentTimeMillis()); | |
| if (stats == null) { | |
| return; | |
| } | |
| ArrayMap<String, UsageStats> map = new ArrayMap<>(); | |
| final int statCount = stats.size(); | |
| for (int i = 0; i < statCount; i++) { | |
| final android.app.usage.UsageStats pkgStats = stats.get(i); | |
| // load application labels for each application | |
| try { | |
| ApplicationInfo appInfo = mPm.getApplicationInfo(pkgStats.getPackageName(), 0); | |
| String label = appInfo.loadLabel(mPm).toString(); | |
| mAppLabelMap.put(pkgStats.getPackageName(), label); | |
| UsageStats existingStats = | |
| map.get(pkgStats.getPackageName()); | |
| if (existingStats == null) { | |
| map.put(pkgStats.getPackageName(), pkgStats); | |
| } else { | |
| existingStats.add(pkgStats); | |
| } | |
| } catch (NameNotFoundException e) { | |
| // This package may be gone. | |
| } | |
| } | |
| mPackageStats.addAll(map.values()); | |
| // Sort list | |
| mAppLabelComparator = new AppNameComparator(mAppLabelMap); | |
| sortList(); | |
| } | |
| @Override | |
| public int getCount() { | |
| return mPackageStats.size(); | |
| } | |
| @Override | |
| public Object getItem(int position) { | |
| return mPackageStats.get(position); | |
| } | |
| @Override | |
| public long getItemId(int position) { | |
| return position; | |
| } | |
| @Override | |
| public View getView(int position, View convertView, ViewGroup parent) { | |
| // A ViewHolder keeps references to children views to avoid unneccessary calls | |
| // to findViewById() on each row. | |
| AppViewHolder holder; | |
| // When convertView is not null, we can reuse it directly, there is no need | |
| // to reinflate it. We only inflate a new View when the convertView supplied | |
| // by ListView is null. | |
| if (convertView == null) { | |
| convertView = mInflater.inflate(R.layout.usage_stats_item, null); | |
| // Creates a ViewHolder and store references to the two children views | |
| // we want to bind data to. | |
| holder = new AppViewHolder(); | |
| holder.pkgName = (TextView) convertView.findViewById(R.id.package_name); | |
| holder.lastTimeUsed = (TextView) convertView.findViewById(R.id.last_time_used); | |
| holder.usageTime = (TextView) convertView.findViewById(R.id.usage_time); | |
| convertView.setTag(holder); | |
| } else { | |
| // Get the ViewHolder back to get fast access to the TextView | |
| // and the ImageView. | |
| holder = (AppViewHolder) convertView.getTag(); | |
| } | |
| // Bind the data efficiently with the holder | |
| UsageStats pkgStats = mPackageStats.get(position); | |
| if (pkgStats != null) { | |
| String label = mAppLabelMap.get(pkgStats.getPackageName()); | |
| holder.pkgName.setText(label); | |
| holder.lastTimeUsed.setText(DateUtils.formatSameDayTime(pkgStats.getLastTimeUsed(), | |
| System.currentTimeMillis(), DateFormat.MEDIUM, DateFormat.MEDIUM)); | |
| holder.usageTime.setText( | |
| DateUtils.formatElapsedTime(pkgStats.getTotalTimeInForeground() / 1000)); | |
| } else { | |
| Log.w(TAG, "No usage stats info for package:" + position); | |
| } | |
| return convertView; | |
| } | |
| void sortList(int sortOrder) { | |
| if (mDisplayOrder == sortOrder) { | |
| // do nothing | |
| return; | |
| } | |
| mDisplayOrder= sortOrder; | |
| sortList(); | |
| } | |
| private void sortList() { | |
| if (mDisplayOrder == _DISPLAY_ORDER_USAGE_TIME) { | |
| if (localLOGV) Log.i(TAG, "Sorting by usage time"); | |
| Collections.sort(mPackageStats, mUsageTimeComparator); | |
| } else if (mDisplayOrder == _DISPLAY_ORDER_LAST_TIME_USED) { | |
| if (localLOGV) Log.i(TAG, "Sorting by last time used"); | |
| Collections.sort(mPackageStats, mLastTimeUsedComparator); | |
| } else if (mDisplayOrder == _DISPLAY_ORDER_APP_NAME) { | |
| if (localLOGV) Log.i(TAG, "Sorting by application name"); | |
| Collections.sort(mPackageStats, mAppLabelComparator); | |
| } | |
| notifyDataSetChanged(); | |
| } | |
| } | |
| /** Called when the activity is first created. */ | |
| @Override | |
| protected void onCreate(Bundle icicle) { | |
| super.onCreate(icicle); | |
| setContentView(R.layout.usage_stats); | |
| mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE); | |
| mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); | |
| mPm = getPackageManager(); | |
| Spinner typeSpinner = (Spinner) findViewById(R.id.typeSpinner); | |
| typeSpinner.setOnItemSelectedListener(this); | |
| ListView listView = (ListView) findViewById(R.id.pkg_list); | |
| mAdapter = new UsageStatsAdapter(); | |
| listView.setAdapter(mAdapter); | |
| } | |
| @Override | |
| public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { | |
| mAdapter.sortList(position); | |
| } | |
| @Override | |
| public void onNothingSelected(AdapterView<?> parent) { | |
| // do nothing | |
| } | |
| } |