summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/Stats.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3/Stats.java')
-rw-r--r--src/com/android/launcher3/Stats.java202
1 files changed, 202 insertions, 0 deletions
diff --git a/src/com/android/launcher3/Stats.java b/src/com/android/launcher3/Stats.java
new file mode 100644
index 000000000..ca088f71a
--- /dev/null
+++ b/src/com/android/launcher3/Stats.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.util.Log;
+
+import java.io.*;
+import java.util.ArrayList;
+
+public class Stats {
+ private static final boolean DEBUG_BROADCASTS = false;
+ private static final String TAG = "Launcher3/Stats";
+
+ private static final boolean LOCAL_LAUNCH_LOG = true;
+
+ public static final String ACTION_LAUNCH = "com.android.launcher3.action.LAUNCH";
+ public static final String PERM_LAUNCH = "com.android.launcher3.permission.RECEIVE_LAUNCH_BROADCASTS";
+ public static final String EXTRA_INTENT = "intent";
+ public static final String EXTRA_CONTAINER = "container";
+ public static final String EXTRA_SCREEN = "screen";
+ public static final String EXTRA_CELLX = "cellX";
+ public static final String EXTRA_CELLY = "cellY";
+
+ private static final String LOG_FILE_NAME = "launches.log";
+ private static final int LOG_VERSION = 1;
+ private static final int LOG_TAG_VERSION = 0x1;
+ private static final int LOG_TAG_LAUNCH = 0x1000;
+
+ private static final String STATS_FILE_NAME = "stats.log";
+ private static final int STATS_VERSION = 1;
+ private static final int INITIAL_STATS_SIZE = 100;
+
+ // TODO: delayed/batched writes
+ private static final boolean FLUSH_IMMEDIATELY = true;
+
+ private final Launcher mLauncher;
+
+ DataOutputStream mLog;
+
+ ArrayList<String> mIntents;
+ ArrayList<Integer> mHistogram;
+
+ public Stats(Launcher launcher) {
+ mLauncher = launcher;
+
+ loadStats();
+
+ if (LOCAL_LAUNCH_LOG) {
+ try {
+ mLog = new DataOutputStream(mLauncher.openFileOutput(LOG_FILE_NAME, Context.MODE_APPEND));
+ mLog.writeInt(LOG_TAG_VERSION);
+ mLog.writeInt(LOG_VERSION);
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "unable to create stats log: " + e);
+ mLog = null;
+ } catch (IOException e) {
+ Log.e(TAG, "unable to write to stats log: " + e);
+ mLog = null;
+ }
+ }
+
+ if (DEBUG_BROADCASTS) {
+ launcher.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ android.util.Log.v("Stats", "got broadcast: " + intent + " for launched intent: "
+ + intent.getStringExtra(EXTRA_INTENT));
+ }
+ },
+ new IntentFilter(ACTION_LAUNCH),
+ PERM_LAUNCH,
+ null
+ );
+ }
+ }
+
+ public void incrementLaunch(String intentStr) {
+ int pos = mIntents.indexOf(intentStr);
+ if (pos < 0) {
+ mIntents.add(intentStr);
+ mHistogram.add(1);
+ } else {
+ mHistogram.set(pos, mHistogram.get(pos) + 1);
+ }
+ }
+
+ public void recordLaunch(Intent intent, ShortcutInfo shortcut) {
+ intent = new Intent(intent);
+ intent.setSourceBounds(null);
+
+ final String flat = intent.toUri(0);
+
+ mLauncher.sendBroadcast(
+ new Intent(ACTION_LAUNCH)
+ .putExtra(EXTRA_INTENT, flat)
+ .putExtra(EXTRA_CONTAINER, shortcut.container)
+ .putExtra(EXTRA_SCREEN, shortcut.screenId)
+ .putExtra(EXTRA_CELLX, shortcut.cellX)
+ .putExtra(EXTRA_CELLY, shortcut.cellY),
+ PERM_LAUNCH);
+
+ incrementLaunch(flat);
+
+ if (FLUSH_IMMEDIATELY) {
+ saveStats();
+ }
+
+ if (LOCAL_LAUNCH_LOG && mLog != null) {
+ try {
+ mLog.writeInt(LOG_TAG_LAUNCH);
+ mLog.writeLong(System.currentTimeMillis());
+ mLog.writeShort((short) shortcut.container);
+ mLog.writeShort((short) shortcut.screenId);
+ mLog.writeShort((short) shortcut.cellX);
+ mLog.writeShort((short) shortcut.cellY);
+ mLog.writeUTF(flat);
+ if (FLUSH_IMMEDIATELY) {
+ mLog.flush(); // TODO: delayed writes
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void saveStats() {
+ DataOutputStream stats = null;
+ try {
+ stats = new DataOutputStream(mLauncher.openFileOutput(STATS_FILE_NAME + ".tmp", Context.MODE_PRIVATE));
+ stats.writeInt(STATS_VERSION);
+ final int N = mHistogram.size();
+ stats.writeInt(N);
+ for (int i=0; i<N; i++) {
+ stats.writeUTF(mIntents.get(i));
+ stats.writeInt(mHistogram.get(i));
+ }
+ stats.close();
+ stats = null;
+ mLauncher.getFileStreamPath(STATS_FILE_NAME + ".tmp")
+ .renameTo(mLauncher.getFileStreamPath(STATS_FILE_NAME));
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "unable to create stats data: " + e);
+ } catch (IOException e) {
+ Log.e(TAG, "unable to write to stats data: " + e);
+ } finally {
+ if (stats != null) {
+ try {
+ stats.close();
+ } catch (IOException e) { }
+ }
+ }
+ }
+
+ private void loadStats() {
+ mIntents = new ArrayList<String>(INITIAL_STATS_SIZE);
+ mHistogram = new ArrayList<Integer>(INITIAL_STATS_SIZE);
+ DataInputStream stats = null;
+ try {
+ stats = new DataInputStream(mLauncher.openFileInput(STATS_FILE_NAME));
+ final int version = stats.readInt();
+ if (version == STATS_VERSION) {
+ final int N = stats.readInt();
+ for (int i=0; i<N; i++) {
+ final String pkg = stats.readUTF();
+ final int count = stats.readInt();
+ mIntents.add(pkg);
+ mHistogram.add(count);
+ }
+ }
+ } catch (FileNotFoundException e) {
+ // not a problem
+ } catch (IOException e) {
+ // more of a problem
+
+ } finally {
+ if (stats != null) {
+ try {
+ stats.close();
+ } catch (IOException e) { }
+ }
+ }
+ }
+}