summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml6
-rw-r--r--src/com/android/launcher3/Launcher.java9
-rw-r--r--src/com/android/launcher3/Stats.java202
3 files changed, 216 insertions, 1 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index b9f75cf5d..f885a6c63 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -50,6 +50,11 @@
android:label="@string/permlab_write_settings"
android:description="@string/permdesc_write_settings"/>
+ <permission
+ android:name="com.android.launcher3.permission.RECEIVE_LAUNCH_BROADCASTS"
+ android:protectionLevel="signature"
+ />
+
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
@@ -60,6 +65,7 @@
<uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.android.launcher3.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.launcher3.permission.WRITE_SETTINGS" />
+ <uses-permission android:name="com.android.launcher3.permission.RECEIVE_LAUNCH_BROADCASTS" />
<application
android:name="com.android.launcher3.LauncherApplication"
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index fa9627973..c3ea1ef8a 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -345,6 +345,8 @@ public class Launcher extends Activity
int cellY;
}
+ private Stats mStats;
+
private static boolean isPropertyEnabled(String propertyName) {
return Log.isLoggable(propertyName, Log.VERBOSE);
}
@@ -378,6 +380,8 @@ public class Launcher extends Activity
mDragController = new DragController(this);
mInflater = getLayoutInflater();
+ mStats = new Stats(this);
+
mAppWidgetManager = AppWidgetManager.getInstance(this);
mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);
mAppWidgetHost.startListening();
@@ -2086,7 +2090,8 @@ public class Launcher extends Activity
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
// Open shortcut
- final Intent intent = ((ShortcutInfo) tag).intent;
+ final ShortcutInfo shortcut = (ShortcutInfo) tag;
+ final Intent intent = shortcut.intent;
// Check for special shortcuts
if (intent.getComponent() != null) {
@@ -2112,6 +2117,8 @@ public class Launcher extends Activity
boolean success = startActivitySafely(v, intent, tag);
+ mStats.recordLaunch(intent, shortcut);
+
if (success && v instanceof BubbleTextView) {
mWaitingForResume = (BubbleTextView) v;
mWaitingForResume.setStayPressed(true);
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) { }
+ }
+ }
+ }
+}