1/**
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy
6 * of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16package com.android.tests.usagestats;
17
18import android.app.ListActivity;
19import android.app.usage.UsageEvents;
20import android.app.usage.UsageStatsManager;
21import android.content.Context;
22import android.os.Bundle;
23import android.os.Handler;
24import android.support.v4.util.CircularArray;
25import android.view.LayoutInflater;
26import android.view.View;
27import android.view.ViewGroup;
28import android.widget.BaseAdapter;
29import android.widget.TextView;
30
31import java.util.ArrayList;
32
33public class UsageLogActivity extends ListActivity implements Runnable {
34    private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14;
35
36    private UsageStatsManager mUsageStatsManager;
37    private Adapter mAdapter;
38    private Handler mHandler = new Handler();
39    private long mLastTime;
40
41    @Override
42    protected void onCreate(Bundle savedInstanceState) {
43        super.onCreate(savedInstanceState);
44        mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
45        mLastTime = System.currentTimeMillis() - USAGE_STATS_PERIOD;
46
47        mAdapter = new Adapter();
48        setListAdapter(mAdapter);
49    }
50
51    @Override
52    protected void onResume() {
53        super.onResume();
54        run();
55    }
56
57    @Override
58    protected void onPause() {
59        super.onPause();
60        mHandler.removeCallbacks(this);
61    }
62
63    @Override
64    public void run() {
65        long now = System.currentTimeMillis();
66        UsageEvents events = mUsageStatsManager.queryEvents(mLastTime, now);
67        long lastEventTime = mAdapter.update(events);
68        if (lastEventTime >= 0) {
69            mLastTime = lastEventTime + 1;
70        }
71        mHandler.postDelayed(this, 1000 * 5);
72    }
73
74    private class Adapter extends BaseAdapter {
75        private static final int MAX_EVENTS = 50;
76        private final CircularArray<UsageEvents.Event> mEvents = new CircularArray<>(MAX_EVENTS);
77
78        public long update(UsageEvents results) {
79            long lastTimeStamp = -1;
80            while (results.hasNextEvent()) {
81                UsageEvents.Event event = new UsageEvents.Event();
82                results.getNextEvent(event);
83                lastTimeStamp = event.getTimeStamp();
84                if (mEvents.size() == MAX_EVENTS) {
85                    mEvents.popLast();
86                }
87                mEvents.addFirst(event);
88            }
89
90            if (lastTimeStamp != 0) {
91                notifyDataSetChanged();
92            }
93            return lastTimeStamp;
94        }
95
96        @Override
97        public int getCount() {
98            return mEvents.size();
99        }
100
101        @Override
102        public UsageEvents.Event getItem(int position) {
103            return mEvents.get(position);
104        }
105
106        @Override
107        public long getItemId(int position) {
108            return position;
109        }
110
111        @Override
112        public int getItemViewType(int position) {
113            final int eventType = getItem(position).getEventType();
114            if (eventType == UsageEvents.Event.CONFIGURATION_CHANGE) {
115                return 1;
116            }
117            return 0;
118        }
119
120        @Override
121        public View getView(int position, View convertView, ViewGroup parent) {
122            final UsageEvents.Event event = getItem(position);
123
124            final ViewHolder holder;
125            if (convertView == null) {
126                holder = new ViewHolder();
127
128                if (event.getEventType() == UsageEvents.Event.CONFIGURATION_CHANGE) {
129                    convertView = LayoutInflater.from(UsageLogActivity.this)
130                            .inflate(R.layout.config_row_item, parent, false);
131                    holder.config = (TextView) convertView.findViewById(android.R.id.text1);
132                } else {
133                    convertView = LayoutInflater.from(UsageLogActivity.this)
134                            .inflate(R.layout.row_item, parent, false);
135                    holder.packageName = (TextView) convertView.findViewById(android.R.id.text1);
136                    holder.state = (TextView) convertView.findViewById(android.R.id.text2);
137                }
138                convertView.setTag(holder);
139            } else {
140                holder = (ViewHolder) convertView.getTag();
141            }
142
143            if (holder.packageName != null) {
144                holder.packageName.setText(event.getPackageName());
145            }
146
147            if (holder.state != null) {
148                holder.state.setText(eventToString(event.getEventType()));
149            }
150
151            if (holder.config != null &&
152                    event.getEventType() == UsageEvents.Event.CONFIGURATION_CHANGE) {
153                holder.config.setText(event.getConfiguration().toString());
154            }
155            return convertView;
156        }
157
158        private String eventToString(int eventType) {
159            switch (eventType) {
160                case UsageEvents.Event.MOVE_TO_FOREGROUND:
161                    return "Foreground";
162
163                case UsageEvents.Event.MOVE_TO_BACKGROUND:
164                    return "Background";
165
166                case UsageEvents.Event.CONFIGURATION_CHANGE:
167                    return "Config change";
168
169                default:
170                    return "Unknown: " + eventType;
171            }
172        }
173    }
174
175    static class ViewHolder {
176        public TextView packageName;
177        public TextView state;
178        public TextView config;
179    }
180}
181