1e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski/* 2e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski * Copyright (C) 2014 The Android Open Source Project 3e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski * 4e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski * you may not use this file except in compliance with the License. 6e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski * You may obtain a copy of the License at 7e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski * 8e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski * 10e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski * Unless required by applicable law or agreed to in writing, software 11e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski * See the License for the specific language governing permissions and 14e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski * limitations under the License. 15e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski */ 16e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 17e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskipackage com.android.tests.usagestats; 18e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 19e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.app.ListActivity; 20e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.app.usage.UsageStats; 21e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.app.usage.UsageStatsManager; 22e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.content.Context; 233516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.content.Intent; 24e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.os.Bundle; 25e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.text.format.DateUtils; 26e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.view.LayoutInflater; 273516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.view.Menu; 283516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.view.MenuInflater; 293516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.view.MenuItem; 30e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.view.View; 31e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.view.ViewGroup; 32e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.widget.BaseAdapter; 33e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.widget.TextView; 34e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 35e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport java.util.ArrayList; 36e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport java.util.Collections; 37e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport java.util.Comparator; 38cc562a811da508b275254f275d6e0c1758a47d07Adam Lesinskiimport java.util.Map; 39e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 40e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskipublic class UsageStatsActivity extends ListActivity { 413516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14; 42e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski private UsageStatsManager mUsageStatsManager; 43e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski private Adapter mAdapter; 443516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private Comparator<UsageStats> mComparator = new Comparator<UsageStats>() { 45e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski @Override 463516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public int compare(UsageStats o1, UsageStats o2) { 473516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return Long.compare(o2.getTotalTimeInForeground(), o1.getTotalTimeInForeground()); 48e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 49e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski }; 50e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 51e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski @Override 52e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski protected void onCreate(Bundle savedInstanceState) { 53e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski super.onCreate(savedInstanceState); 54e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE); 55e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski mAdapter = new Adapter(); 56e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski setListAdapter(mAdapter); 57e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 58e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 59e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski @Override 603516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public boolean onCreateOptionsMenu(Menu menu) { 613516800b611a79339a3c188332d13a26e9086b09Adam Lesinski MenuInflater inflater = getMenuInflater(); 623516800b611a79339a3c188332d13a26e9086b09Adam Lesinski inflater.inflate(R.menu.main, menu); 633516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return super.onCreateOptionsMenu(menu); 643516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 653516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 663516800b611a79339a3c188332d13a26e9086b09Adam Lesinski @Override 673516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public boolean onOptionsItemSelected(MenuItem item) { 683516800b611a79339a3c188332d13a26e9086b09Adam Lesinski switch (item.getItemId()) { 693516800b611a79339a3c188332d13a26e9086b09Adam Lesinski case R.id.log: 703516800b611a79339a3c188332d13a26e9086b09Adam Lesinski startActivity(new Intent(this, UsageLogActivity.class)); 713516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return true; 723516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 733516800b611a79339a3c188332d13a26e9086b09Adam Lesinski default: 743516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return super.onOptionsItemSelected(item); 753516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 763516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 773516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 783516800b611a79339a3c188332d13a26e9086b09Adam Lesinski @Override 79e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski protected void onResume() { 80e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski super.onResume(); 81e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski updateAdapter(); 82e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 83e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 84e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski private void updateAdapter() { 853516800b611a79339a3c188332d13a26e9086b09Adam Lesinski long now = System.currentTimeMillis(); 863516800b611a79339a3c188332d13a26e9086b09Adam Lesinski long beginTime = now - USAGE_STATS_PERIOD; 87cc562a811da508b275254f275d6e0c1758a47d07Adam Lesinski Map<String, UsageStats> stats = mUsageStatsManager.queryAndAggregateUsageStats( 883516800b611a79339a3c188332d13a26e9086b09Adam Lesinski beginTime, now); 89e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski mAdapter.update(stats); 90e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 91e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 92e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski private class Adapter extends BaseAdapter { 933516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private ArrayList<UsageStats> mStats = new ArrayList<>(); 94e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 95cc562a811da508b275254f275d6e0c1758a47d07Adam Lesinski public void update(Map<String, UsageStats> stats) { 96e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski mStats.clear(); 97e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski if (stats == null) { 98e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski return; 99e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 100e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 101cc562a811da508b275254f275d6e0c1758a47d07Adam Lesinski mStats.addAll(stats.values()); 102e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski Collections.sort(mStats, mComparator); 103e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski notifyDataSetChanged(); 104e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 105e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 106e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski @Override 107e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski public int getCount() { 108e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski return mStats.size(); 109e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 110e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 111e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski @Override 112e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski public Object getItem(int position) { 113e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski return mStats.get(position); 114e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 115e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 116e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski @Override 117e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski public long getItemId(int position) { 118e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski return position; 119e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 120e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 121e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski @Override 122e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski public View getView(int position, View convertView, ViewGroup parent) { 123e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski final ViewHolder holder; 124e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski if (convertView == null) { 125e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski convertView = LayoutInflater.from(UsageStatsActivity.this) 126e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski .inflate(R.layout.row_item, parent, false); 127e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski holder = new ViewHolder(); 128e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski holder.packageName = (TextView) convertView.findViewById(android.R.id.text1); 129e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski holder.usageTime = (TextView) convertView.findViewById(android.R.id.text2); 130e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski convertView.setTag(holder); 131e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } else { 132e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski holder = (ViewHolder) convertView.getTag(); 133e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 134e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 135e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski holder.packageName.setText(mStats.get(position).getPackageName()); 136e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski holder.usageTime.setText(DateUtils.formatDuration( 1373516800b611a79339a3c188332d13a26e9086b09Adam Lesinski mStats.get(position).getTotalTimeInForeground())); 138e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski return convertView; 139e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 140e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 141e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 142e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski private static class ViewHolder { 143e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski TextView packageName; 144e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski TextView usageTime; 145e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 146e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski}