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 19ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onukiimport android.app.AlertDialog; 20e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.app.ListActivity; 2162ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasaniimport android.app.PendingIntent; 22e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.app.usage.UsageStats; 23e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.app.usage.UsageStatsManager; 24e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.content.Context; 25ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onukiimport android.content.DialogInterface; 263516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.content.Intent; 27e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.os.Bundle; 28ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onukiimport android.text.InputType; 29ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onukiimport android.text.TextUtils; 30e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.text.format.DateUtils; 31e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.view.LayoutInflater; 323516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.view.Menu; 333516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.view.MenuInflater; 343516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.view.MenuItem; 35e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.view.View; 36e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.view.ViewGroup; 37e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.widget.BaseAdapter; 38ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onukiimport android.widget.EditText; 39e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport android.widget.TextView; 4062ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasaniimport android.widget.Toast; 41e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 42e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport java.util.ArrayList; 43e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport java.util.Collections; 44e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskiimport java.util.Comparator; 45cc562a811da508b275254f275d6e0c1758a47d07Adam Lesinskiimport java.util.Map; 4662ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasaniimport java.util.concurrent.TimeUnit; 47e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 48e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinskipublic class UsageStatsActivity extends ListActivity { 493516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14; 5062ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani private static final String EXTRA_KEY_TIMEOUT = "com.android.tests.usagestats.extra.TIMEOUT"; 51e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski private UsageStatsManager mUsageStatsManager; 52e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski private Adapter mAdapter; 533516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private Comparator<UsageStats> mComparator = new Comparator<UsageStats>() { 54e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski @Override 553516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public int compare(UsageStats o1, UsageStats o2) { 563516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return Long.compare(o2.getTotalTimeInForeground(), o1.getTotalTimeInForeground()); 57e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 58e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski }; 59e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 60e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski @Override 61e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski protected void onCreate(Bundle savedInstanceState) { 62e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski super.onCreate(savedInstanceState); 63e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE); 64e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski mAdapter = new Adapter(); 65e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski setListAdapter(mAdapter); 6662ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani Bundle extras = getIntent().getExtras(); 6762ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani if (extras != null && extras.containsKey(UsageStatsManager.EXTRA_TIME_USED)) { 6862ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani System.err.println("UsageStatsActivity " + extras); 6962ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani Toast.makeText(this, "Timeout of observed app\n" + extras, Toast.LENGTH_SHORT).show(); 7062ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani } 7162ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani } 7262ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani 7362ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani @Override 7462ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani public void onNewIntent(Intent intent) { 7562ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani Bundle extras = intent.getExtras(); 7662ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani if (extras != null && extras.containsKey(UsageStatsManager.EXTRA_TIME_USED)) { 7762ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani System.err.println("UsageStatsActivity " + extras); 7862ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani Toast.makeText(this, "Timeout of observed app\n" + extras, Toast.LENGTH_SHORT).show(); 7962ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani } 80e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 81e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 82e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski @Override 833516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public boolean onCreateOptionsMenu(Menu menu) { 843516800b611a79339a3c188332d13a26e9086b09Adam Lesinski MenuInflater inflater = getMenuInflater(); 853516800b611a79339a3c188332d13a26e9086b09Adam Lesinski inflater.inflate(R.menu.main, menu); 863516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return super.onCreateOptionsMenu(menu); 873516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 883516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 893516800b611a79339a3c188332d13a26e9086b09Adam Lesinski @Override 903516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public boolean onOptionsItemSelected(MenuItem item) { 913516800b611a79339a3c188332d13a26e9086b09Adam Lesinski switch (item.getItemId()) { 923516800b611a79339a3c188332d13a26e9086b09Adam Lesinski case R.id.log: 933516800b611a79339a3c188332d13a26e9086b09Adam Lesinski startActivity(new Intent(this, UsageLogActivity.class)); 943516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return true; 95ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki case R.id.call_is_app_inactive: 96ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki callIsAppInactive(); 97ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki return true; 9862ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani case R.id.set_app_limit: 9962ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani callSetAppLimit(); 10062ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani return true; 1013516800b611a79339a3c188332d13a26e9086b09Adam Lesinski default: 1023516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return super.onOptionsItemSelected(item); 1033516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1043516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1053516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1063516800b611a79339a3c188332d13a26e9086b09Adam Lesinski @Override 107e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski protected void onResume() { 108e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski super.onResume(); 109e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski updateAdapter(); 110e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 111e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 112ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki private void callIsAppInactive() { 113ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki final AlertDialog.Builder builder = new AlertDialog.Builder(this); 114ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki builder.setTitle("Enter package name"); 115ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki final EditText input = new EditText(this); 116ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki input.setInputType(InputType.TYPE_CLASS_TEXT); 117ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki input.setHint("com.android.tests.usagestats"); 118ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki builder.setView(input); 119ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki 120ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki builder.setPositiveButton("OK", new DialogInterface.OnClickListener() { 121ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki @Override 122ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki public void onClick(DialogInterface dialog, int which) { 123ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki final String packageName = input.getText().toString().trim(); 124ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki if (!TextUtils.isEmpty(packageName)) { 125ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki showInactive(packageName); 126ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki } 127ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki } 128ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki }); 129ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 130ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki @Override 131ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki public void onClick(DialogInterface dialog, int which) { 132ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki dialog.cancel(); 133ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki } 134ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki }); 135ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki 136ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki builder.show(); 137ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki } 138ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki 13962ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani private void callSetAppLimit() { 14062ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani final AlertDialog.Builder builder = new AlertDialog.Builder(this); 14162ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani builder.setTitle("Enter package name"); 14262ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani final EditText input = new EditText(this); 14362ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani input.setInputType(InputType.TYPE_CLASS_TEXT); 14462ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani input.setHint("com.android.tests.usagestats"); 14562ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani builder.setView(input); 14662ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani 14762ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani builder.setPositiveButton("OK", new DialogInterface.OnClickListener() { 14862ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani @Override 14962ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani public void onClick(DialogInterface dialog, int which) { 15062ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani final String packageName = input.getText().toString().trim(); 15162ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani if (!TextUtils.isEmpty(packageName)) { 15262ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani String[] packages = packageName.split(","); 15362ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani Intent intent = new Intent(Intent.ACTION_MAIN); 15462ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani intent.setClass(UsageStatsActivity.this, UsageStatsActivity.class); 15562ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani intent.setPackage(getPackageName()); 15662ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani intent.putExtra(EXTRA_KEY_TIMEOUT, true); 15762ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani mUsageStatsManager.registerAppUsageObserver(1, packages, 15862ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani 30, TimeUnit.SECONDS, PendingIntent.getActivity(UsageStatsActivity.this, 15962ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani 1, intent, 0)); 16062ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani } 16162ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani } 16262ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani }); 16362ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 16462ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani @Override 16562ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani public void onClick(DialogInterface dialog, int which) { 16662ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani dialog.cancel(); 16762ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani } 16862ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani }); 16962ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani 17062ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani builder.show(); 17162ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani } 17262ec27e97f68513c5637383fb72de469c5e903c1Amith Yamasani 173ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki private void showInactive(String packageName) { 174ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki final AlertDialog.Builder builder = new AlertDialog.Builder(this); 175ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki builder.setMessage( 176ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki "isAppInactive(\"" + packageName + "\") = " 177ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki + (mUsageStatsManager.isAppInactive(packageName) ? "true" : "false")); 178ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki builder.show(); 179ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki } 180ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki 181e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski private void updateAdapter() { 1823516800b611a79339a3c188332d13a26e9086b09Adam Lesinski long now = System.currentTimeMillis(); 1833516800b611a79339a3c188332d13a26e9086b09Adam Lesinski long beginTime = now - USAGE_STATS_PERIOD; 184cc562a811da508b275254f275d6e0c1758a47d07Adam Lesinski Map<String, UsageStats> stats = mUsageStatsManager.queryAndAggregateUsageStats( 1853516800b611a79339a3c188332d13a26e9086b09Adam Lesinski beginTime, now); 186e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski mAdapter.update(stats); 187e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 188e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 189e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski private class Adapter extends BaseAdapter { 1903516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private ArrayList<UsageStats> mStats = new ArrayList<>(); 191e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 192cc562a811da508b275254f275d6e0c1758a47d07Adam Lesinski public void update(Map<String, UsageStats> stats) { 193e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski mStats.clear(); 194e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski if (stats == null) { 195e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski return; 196e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 197e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 198cc562a811da508b275254f275d6e0c1758a47d07Adam Lesinski mStats.addAll(stats.values()); 199e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski Collections.sort(mStats, mComparator); 200e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski notifyDataSetChanged(); 201e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 202e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 203e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski @Override 204e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski public int getCount() { 205e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski return mStats.size(); 206e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 207e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 208e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski @Override 209e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski public Object getItem(int position) { 210e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski return mStats.get(position); 211e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 212e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 213e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski @Override 214e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski public long getItemId(int position) { 215e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski return position; 216e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 217e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 218e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski @Override 219e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski public View getView(int position, View convertView, ViewGroup parent) { 220e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski final ViewHolder holder; 221e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski if (convertView == null) { 222e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski convertView = LayoutInflater.from(UsageStatsActivity.this) 223e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski .inflate(R.layout.row_item, parent, false); 224e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski holder = new ViewHolder(); 225e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski holder.packageName = (TextView) convertView.findViewById(android.R.id.text1); 226e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski holder.usageTime = (TextView) convertView.findViewById(android.R.id.text2); 227e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski convertView.setTag(holder); 228e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } else { 229e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski holder = (ViewHolder) convertView.getTag(); 230e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 231e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 232e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski holder.packageName.setText(mStats.get(position).getPackageName()); 233e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski holder.usageTime.setText(DateUtils.formatDuration( 2343516800b611a79339a3c188332d13a26e9086b09Adam Lesinski mStats.get(position).getTotalTimeInForeground())); 235e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski return convertView; 236e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 237e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 238e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski 239e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski private static class ViewHolder { 240e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski TextView packageName; 241e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski TextView usageTime; 242e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski } 243e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski}