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
31public class UsageLogActivity extends ListActivity implements Runnable {
32    private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14;
33
34    private UsageStatsManager mUsageStatsManager;
35    private Adapter mAdapter;
36    private Handler mHandler = new Handler();
37    private long mLastTime;
38
39    @Override
40    protected void onCreate(Bundle savedInstanceState) {
41        super.onCreate(savedInstanceState);
42        mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
43        mLastTime = System.currentTimeMillis() - USAGE_STATS_PERIOD;
44
45        mAdapter = new Adapter();
46        setListAdapter(mAdapter);
47    }
48
49    @Override
50    protected void onResume() {
51        super.onResume();
52        run();
53    }
54
55    @Override
56    protected void onPause() {
57        super.onPause();
58        mHandler.removeCallbacks(this);
59    }
60
61    @Override
62    public void run() {
63        long now = System.currentTimeMillis();
64        UsageEvents events = mUsageStatsManager.queryEvents(mLastTime, now);
65        long lastEventTime = mAdapter.update(events);
66        if (lastEventTime >= 0) {
67            mLastTime = lastEventTime + 1;
68        }
69        mHandler.postDelayed(this, 1000 * 5);
70    }
71
72    private class Adapter extends BaseAdapter {
73        private static final int MAX_EVENTS = 50;
74        private final CircularArray<UsageEvents.Event> mEvents = new CircularArray<>(MAX_EVENTS);
75
76        public long update(UsageEvents results) {
77            long lastTimeStamp = -1;
78            while (results.hasNextEvent()) {
79                UsageEvents.Event event = new UsageEvents.Event();
80                results.getNextEvent(event);
81                lastTimeStamp = event.getTimeStamp();
82                if (mEvents.size() == MAX_EVENTS) {
83                    mEvents.popLast();
84                }
85                mEvents.addFirst(event);
86            }
87
88            if (lastTimeStamp != 0) {
89                notifyDataSetChanged();
90            }
91            return lastTimeStamp;
92        }
93
94        @Override
95        public int getCount() {
96            return mEvents.size();
97        }
98
99        @Override
100        public UsageEvents.Event getItem(int position) {
101            return mEvents.get(position);
102        }
103
104        @Override
105        public long getItemId(int position) {
106            return position;
107        }
108
109        @Override
110        public int getItemViewType(int position) {
111            final int eventType = getItem(position).getEventType();
112            if (eventType == UsageEvents.Event.CONFIGURATION_CHANGE) {
113                return 1;
114            }
115            return 0;
116        }
117
118        @Override
119        public View getView(int position, View convertView, ViewGroup parent) {
120            final UsageEvents.Event event = getItem(position);
121
122            final ViewHolder holder;
123            if (convertView == null) {
124                holder = new ViewHolder();
125
126                if (event.getEventType() == UsageEvents.Event.CONFIGURATION_CHANGE) {
127                    convertView = LayoutInflater.from(UsageLogActivity.this)
128                            .inflate(R.layout.config_row_item, parent, false);
129                    holder.config = (TextView) convertView.findViewById(android.R.id.text1);
130                } else {
131                    convertView = LayoutInflater.from(UsageLogActivity.this)
132                            .inflate(R.layout.row_item, parent, false);
133                    holder.packageName = (TextView) convertView.findViewById(android.R.id.text1);
134                    holder.state = (TextView) convertView.findViewById(android.R.id.text2);
135                }
136                convertView.setTag(holder);
137            } else {
138                holder = (ViewHolder) convertView.getTag();
139            }
140
141            if (holder.packageName != null) {
142                holder.packageName.setText(event.getPackageName());
143            }
144
145            if (holder.state != null) {
146                holder.state.setText(eventToString(event.getEventType()));
147            }
148
149            if (holder.config != null &&
150                    event.getEventType() == UsageEvents.Event.CONFIGURATION_CHANGE) {
151                holder.config.setText(event.getConfiguration().toString());
152            }
153            return convertView;
154        }
155
156        private String eventToString(int eventType) {
157            switch (eventType) {
158                case UsageEvents.Event.MOVE_TO_FOREGROUND:
159                    return "Foreground";
160
161                case UsageEvents.Event.MOVE_TO_BACKGROUND:
162                    return "Background";
163
164                case UsageEvents.Event.CONFIGURATION_CHANGE:
165                    return "Config change";
166
167                case UsageEvents.Event.USER_INTERACTION:
168                    return "User Interaction";
169
170                default:
171                    return "Unknown: " + eventType;
172            }
173        }
174    }
175
176    static class ViewHolder {
177        public TextView packageName;
178        public TextView state;
179        public TextView config;
180    }
181}
182