Home | History | Annotate | Download | only in settings
      1 
      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 
     19 package com.android.settings;
     20 
     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;
     37 import java.util.Map;
     38 
     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;
     49 
     50 /**
     51  * Activity to display package usage statistics.
     52  */
     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;
     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:" + position);
    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 
    250