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}