13516800b611a79339a3c188332d13a26e9086b09Adam Lesinski/** 23516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * Copyright (C) 2014 The Android Open Source Project 33516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * 43516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); you may not 53516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * use this file except in compliance with the License. You may obtain a copy 63516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * of the License at 73516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * 83516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 93516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * 103516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * Unless required by applicable law or agreed to in writing, software 113516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 123516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 133516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * License for the specific language governing permissions and limitations 143516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * under the License. 153516800b611a79339a3c188332d13a26e9086b09Adam Lesinski */ 163516800b611a79339a3c188332d13a26e9086b09Adam Lesinskipackage com.android.tests.usagestats; 173516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 183516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.app.ListActivity; 193516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.app.usage.UsageEvents; 203516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.app.usage.UsageStatsManager; 213516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.content.Context; 223516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.os.Bundle; 233516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.os.Handler; 247f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinskiimport android.support.v4.util.CircularArray; 253516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.view.LayoutInflater; 263516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.view.View; 273516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.view.ViewGroup; 283516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.widget.BaseAdapter; 293516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.widget.TextView; 303516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 313516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport java.util.ArrayList; 323516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 333516800b611a79339a3c188332d13a26e9086b09Adam Lesinskipublic class UsageLogActivity extends ListActivity implements Runnable { 343516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14; 353516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 363516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private UsageStatsManager mUsageStatsManager; 373516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private Adapter mAdapter; 383516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private Handler mHandler = new Handler(); 397f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski private long mLastTime; 403516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 413516800b611a79339a3c188332d13a26e9086b09Adam Lesinski @Override 423516800b611a79339a3c188332d13a26e9086b09Adam Lesinski protected void onCreate(Bundle savedInstanceState) { 433516800b611a79339a3c188332d13a26e9086b09Adam Lesinski super.onCreate(savedInstanceState); 443516800b611a79339a3c188332d13a26e9086b09Adam Lesinski mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE); 457f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski mLastTime = System.currentTimeMillis() - USAGE_STATS_PERIOD; 467f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 473516800b611a79339a3c188332d13a26e9086b09Adam Lesinski mAdapter = new Adapter(); 483516800b611a79339a3c188332d13a26e9086b09Adam Lesinski setListAdapter(mAdapter); 493516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 503516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 513516800b611a79339a3c188332d13a26e9086b09Adam Lesinski @Override 523516800b611a79339a3c188332d13a26e9086b09Adam Lesinski protected void onResume() { 533516800b611a79339a3c188332d13a26e9086b09Adam Lesinski super.onResume(); 543516800b611a79339a3c188332d13a26e9086b09Adam Lesinski run(); 553516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 563516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 573516800b611a79339a3c188332d13a26e9086b09Adam Lesinski @Override 583516800b611a79339a3c188332d13a26e9086b09Adam Lesinski protected void onPause() { 593516800b611a79339a3c188332d13a26e9086b09Adam Lesinski super.onPause(); 603516800b611a79339a3c188332d13a26e9086b09Adam Lesinski mHandler.removeCallbacks(this); 613516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 623516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 633516800b611a79339a3c188332d13a26e9086b09Adam Lesinski @Override 643516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public void run() { 653516800b611a79339a3c188332d13a26e9086b09Adam Lesinski long now = System.currentTimeMillis(); 667f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski UsageEvents events = mUsageStatsManager.queryEvents(mLastTime, now); 677f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski long lastEventTime = mAdapter.update(events); 687f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski if (lastEventTime >= 0) { 697f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski mLastTime = lastEventTime + 1; 707f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 713516800b611a79339a3c188332d13a26e9086b09Adam Lesinski mHandler.postDelayed(this, 1000 * 5); 723516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 733516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 743516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private class Adapter extends BaseAdapter { 757f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski private static final int MAX_EVENTS = 50; 767f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski private final CircularArray<UsageEvents.Event> mEvents = new CircularArray<>(MAX_EVENTS); 773516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 787f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski public long update(UsageEvents results) { 797f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski long lastTimeStamp = -1; 803516800b611a79339a3c188332d13a26e9086b09Adam Lesinski while (results.hasNextEvent()) { 813516800b611a79339a3c188332d13a26e9086b09Adam Lesinski UsageEvents.Event event = new UsageEvents.Event(); 823516800b611a79339a3c188332d13a26e9086b09Adam Lesinski results.getNextEvent(event); 837f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski lastTimeStamp = event.getTimeStamp(); 847f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski if (mEvents.size() == MAX_EVENTS) { 857f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski mEvents.popLast(); 867f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 877f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski mEvents.addFirst(event); 883516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 8966143fa5b34eea7413335111838fb692987b611aAdam Lesinski 9066143fa5b34eea7413335111838fb692987b611aAdam Lesinski if (lastTimeStamp != 0) { 9166143fa5b34eea7413335111838fb692987b611aAdam Lesinski notifyDataSetChanged(); 9266143fa5b34eea7413335111838fb692987b611aAdam Lesinski } 937f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski return lastTimeStamp; 943516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 953516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 963516800b611a79339a3c188332d13a26e9086b09Adam Lesinski @Override 973516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public int getCount() { 983516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return mEvents.size(); 993516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1003516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1013516800b611a79339a3c188332d13a26e9086b09Adam Lesinski @Override 1027f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski public UsageEvents.Event getItem(int position) { 1033516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return mEvents.get(position); 1043516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1053516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1063516800b611a79339a3c188332d13a26e9086b09Adam Lesinski @Override 1073516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public long getItemId(int position) { 1083516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return position; 1093516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1103516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1113516800b611a79339a3c188332d13a26e9086b09Adam Lesinski @Override 1127f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski public int getItemViewType(int position) { 1137f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski final int eventType = getItem(position).getEventType(); 1147f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski if (eventType == UsageEvents.Event.CONFIGURATION_CHANGE) { 1157f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski return 1; 1167f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 1177f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski return 0; 1187f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 1197f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 1207f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski @Override 1213516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public View getView(int position, View convertView, ViewGroup parent) { 1227f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski final UsageEvents.Event event = getItem(position); 1237f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 1243516800b611a79339a3c188332d13a26e9086b09Adam Lesinski final ViewHolder holder; 1253516800b611a79339a3c188332d13a26e9086b09Adam Lesinski if (convertView == null) { 1263516800b611a79339a3c188332d13a26e9086b09Adam Lesinski holder = new ViewHolder(); 1277f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 1287f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski if (event.getEventType() == UsageEvents.Event.CONFIGURATION_CHANGE) { 1297f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski convertView = LayoutInflater.from(UsageLogActivity.this) 1307f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski .inflate(R.layout.config_row_item, parent, false); 1317f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski holder.config = (TextView) convertView.findViewById(android.R.id.text1); 1327f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } else { 1337f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski convertView = LayoutInflater.from(UsageLogActivity.this) 1347f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski .inflate(R.layout.row_item, parent, false); 1357f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski holder.packageName = (TextView) convertView.findViewById(android.R.id.text1); 1367f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski holder.state = (TextView) convertView.findViewById(android.R.id.text2); 1377f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 1383516800b611a79339a3c188332d13a26e9086b09Adam Lesinski convertView.setTag(holder); 1393516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } else { 1403516800b611a79339a3c188332d13a26e9086b09Adam Lesinski holder = (ViewHolder) convertView.getTag(); 1413516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1423516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1437f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski if (holder.packageName != null) { 1447f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski holder.packageName.setText(event.getPackageName()); 1457f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 1467f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 1477f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski if (holder.state != null) { 1487f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski holder.state.setText(eventToString(event.getEventType())); 1497f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 1507f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 1517f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski if (holder.config != null && 1527f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski event.getEventType() == UsageEvents.Event.CONFIGURATION_CHANGE) { 1537f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski holder.config.setText(event.getConfiguration().toString()); 1547f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 1557f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski return convertView; 1567f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 1577f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 1587f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski private String eventToString(int eventType) { 1597f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski switch (eventType) { 1603516800b611a79339a3c188332d13a26e9086b09Adam Lesinski case UsageEvents.Event.MOVE_TO_FOREGROUND: 1617f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski return "Foreground"; 1623516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1633516800b611a79339a3c188332d13a26e9086b09Adam Lesinski case UsageEvents.Event.MOVE_TO_BACKGROUND: 1647f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski return "Background"; 1657f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 1667f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski case UsageEvents.Event.CONFIGURATION_CHANGE: 1677f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski return "Config change"; 1683516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1693516800b611a79339a3c188332d13a26e9086b09Adam Lesinski default: 1707f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski return "Unknown: " + eventType; 1713516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1723516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1733516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1743516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1753516800b611a79339a3c188332d13a26e9086b09Adam Lesinski static class ViewHolder { 1763516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public TextView packageName; 1773516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public TextView state; 1787f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski public TextView config; 1793516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1803516800b611a79339a3c188332d13a26e9086b09Adam Lesinski} 181