android-support-v7-recyclerview \
org.cyanogenmod.platform.internal
-LOCAL_STATIC_JAVA_AAR_LIBRARIES := ambientsdk
-
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
$(call all-proto-files-under, protos)
LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/
LOCAL_AAPT_FLAGS := \
--auto-add-overlay \
- --extra-packages android.support.v7.recyclerview \
- --extra-packages com.cyanogen.ambient
+ --extra-packages android.support.v7.recyclerview
#LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := Trebuchet
<uses-permission android:name="com.android.launcher3.permission.RECEIVE_LAUNCH_BROADCASTS" />
<uses-permission android:name="com.android.launcher3.permission.RECEIVE_FIRST_LOAD_BROADCAST" />
<uses-permission android:name="cyanogenmod.permission.PROTECTED_APP" />
- <uses-permission android:name="com.cyngn.stats.SEND_ANALYTICS" />
<application
- android:name="com.android.launcher3.LauncherApplication"
android:allowBackup="@bool/enable_backup"
android:backupAgent="com.android.launcher3.LauncherBackupAgentHelper"
android:hardwareAccelerated="true"
>
</service>
- <service
- android:name="com.android.launcher3.stats.internal.service.AggregationIntentService"
- android:exported="false">
- <intent-filter>
- <action android:name="com.cyanogenmod.trebuchet.AGGREGATE_AND_TRACK" />
- </intent-filter>
- </service>
-
<receiver
android:name="com.android.launcher3.WallpaperChangedReceiver">
<intent-filter>
AppWidgetProviderInfo info = mAppWidgetManager.getAppWidgetInfo(launcherInfo.appWidgetId);
if (info != null) {
String packageName = info.providerInfo.packageName;
- LauncherApplication.getLauncherStats().sendWidgetRemoveEvent(packageName);
}
}
appWidgetInfo);
mWorkspace.removeExtraEmptyScreenDelayed(true, onComplete, delay, false);
String packageName = appWidgetInfo.providerInfo.packageName;
- LauncherApplication.getLauncherStats().sendWidgetAddEvent(packageName);
}
}
} else if (tag instanceof AppInfo) {
AppInfo info = (AppInfo) tag;
startAppShortcutOrInfoActivity(v);
- LauncherApplication.getLauncherStats().sendAppLaunchEvent(
- LauncherStats.ORIGIN_APPDRAWER, info.componentName.getPackageName());
- String packageName = info.getIntent().getComponent().getPackageName();
- if (LauncherStats.SETTINGS_PACKAGE_NAME.equals(packageName)) {
- LauncherApplication.getLauncherStats()
- .sendSettingsOpenedEvent(LauncherStats.ORIGIN_APPDRAWER);
- }
} else if (tag instanceof LauncherAppWidgetInfo) {
if (v instanceof PendingAppWidgetHostView) {
onClickPendingWidget((PendingAppWidgetHostView) v);
// Start activities
startAppShortcutOrInfoActivity(v);
- ComponentName componentName = intent.getComponent();
- if (componentName != null) {
- String packageName = intent.getComponent().getPackageName();
- LauncherApplication.getLauncherStats()
- .sendAppLaunchEvent(LauncherStats.ORIGIN_HOMESCREEN,
- packageName);
- if (LauncherStats.SETTINGS_PACKAGE_NAME.equals(packageName)) {
- LauncherApplication.getLauncherStats().sendSettingsOpenedEvent(
- LauncherStats.ORIGIN_HOMESCREEN);
- }
- }
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onClickAppShortcut(v);
AnimationDrawable frameAnimation = (AnimationDrawable) mAnimatedArrow.getBackground();
frameAnimation.start();
-
- LauncherApplication.getLauncherStats().sendSettingsOpenedEvent(
- LauncherStats.ORIGIN_TREB_LONGPRESS);
}
@Override
+++ /dev/null
-/*
- * Copyright (C) 2013 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.app.Application;
-
-import com.android.launcher3.stats.LauncherStats;
-import com.android.launcher3.stats.internal.service.AggregationIntentService;
-import com.cyanogen.ambient.analytics.AnalyticsServices;
-import com.cyanogen.ambient.analytics.Event;
-import com.cyanogen.ambient.common.api.AmbientApiClient;
-
-public class LauncherApplication extends Application {
-
- private static LauncherStats sLauncherStats = null;
- private AmbientApiClient mClient;
-
- /**
- * Get the reference handle for LauncherStats commands
- *
- * @return {@link LauncherStats}
- */
- public static LauncherStats getLauncherStats() {
- return sLauncherStats;
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- mClient = new AmbientApiClient.Builder(this)
- .addApi(AnalyticsServices.API)
- .build();
- mClient.connect();
- sLauncherStats = LauncherStats.getInstance(this);
- AggregationIntentService.scheduleService(this);
- }
-
- public void sendEvent(Event event) {
- if (mClient.isConnected()) {
- AnalyticsServices.AnalyticsApi.sendEvent(mClient, event);
- }
- }
-
-}
import cyanogenmod.providers.CMSettings;
import com.android.launcher3.settings.SettingsProvider;
-import com.android.launcher3.stats.internal.service.AggregationIntentService;
import java.lang.ref.WeakReference;
import java.net.URISyntaxException;
int widgetCount = LauncherModel.sBgAppWidgets.size();
SharedPreferences prefs = context.getSharedPreferences(LauncherAppState
.getSharedPreferencesKey(), Context.MODE_PRIVATE);
- prefs.edit().putInt(AggregationIntentService.PREF_KEY_WIDGET_COUNT, widgetCount).apply();
}
/**
int pageCount = LauncherModel.sBgWorkspaceScreens.size();
SharedPreferences prefs = context.getSharedPreferences(LauncherAppState
.getSharedPreferencesKey(), Context.MODE_PRIVATE);
- prefs.edit().putInt(AggregationIntentService.PREF_KEY_PAGE_COUNT, pageCount).apply();
}
/**
import android.content.Intent;
import android.content.SharedPreferences;
-import com.android.launcher3.stats.LauncherStats;
public class WallpaperChangedReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent data) {
SharedPreferences prefs = context.getSharedPreferences(LauncherAppState
.getSharedPreferencesKey(), Context.MODE_PRIVATE);
boolean fromSelf = prefs.getBoolean(Launcher.LONGPRESS_CHANGE, false);
- if (fromSelf) {
- prefs.edit().putBoolean(Launcher.LONGPRESS_CHANGE, false).apply();
- LauncherApplication.getLauncherStats().sendWallpaperChangedEvent(
- LauncherStats.ORIGIN_TREB_LONGPRESS);
- } else {
- LauncherApplication.getLauncherStats().sendWallpaperChangedEvent(
- LauncherStats.ORIGIN_CHOOSER);
- }
-
+ prefs.edit().putBoolean(Launcher.LONGPRESS_CHANGE, false).apply();
}
}
+++ /dev/null
-/*
- * Copyright (c) 2015. The CyanogenMod 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.stats.external;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.util.Log;
-
-import com.android.launcher3.LauncherApplication;
-import com.android.launcher3.stats.util.Logger;
-import com.cyanogen.ambient.analytics.Event;
-
-/**
- * StatsUtil
- * <pre>
- * Utility for interfacing with CyanogenStats
- * </pre>
- */
-public class StatsUtil {
-
- // Tag and logging
- private static final String TAG = StatsUtil.class.getSimpleName();
-
- // Constants
- private static final String KEY_TRACKING_ID = "tracking_id";
-
- /**
- * Send an event to CyangenStats
- *
- * @param context {@link Context} not null
- * @param trackingBundle {@link Bundle}
- * @throws IllegalArgumentException
- */
- public static void sendEvent(Context context, Bundle trackingBundle)
- throws IllegalArgumentException {
- if (context == null) {
- throw new IllegalArgumentException("'context' cannot be null!");
- }
- if (trackingBundle == null) {
- throw new IllegalArgumentException("'trackingBundle' cannot be null!");
- }
- Logger.logd(TAG, "Stats collection: ENABLED!");
-
- if (!trackingBundle.containsKey(KEY_TRACKING_ID)) {
- Logger.logd(TAG, "No tracking id in bundle");
- return;
- } else {
- if (trackingBundle.containsKey(TrackingBundle.KEY_EVENT_CATEGORY)
- && trackingBundle.containsKey(TrackingBundle.KEY_EVENT_ACTION)) {
-
- final Event.Builder builder = new Event.Builder(
- trackingBundle.getString(TrackingBundle.KEY_EVENT_CATEGORY),
- trackingBundle.getString(TrackingBundle.KEY_EVENT_ACTION));
-
- if (trackingBundle.containsKey(TrackingBundle.KEY_METADATA_ORIGIN)) {
- builder.addField(TrackingBundle.KEY_METADATA_ORIGIN,
- trackingBundle.getString(TrackingBundle.KEY_METADATA_ORIGIN));
- }
- if (trackingBundle.containsKey(TrackingBundle.KEY_METADATA_PACKAGE)) {
- builder.addField(TrackingBundle.KEY_METADATA_PACKAGE,
- trackingBundle.getString(TrackingBundle.KEY_METADATA_PACKAGE));
- }
- if (trackingBundle.containsKey(TrackingBundle.KEY_METADATA_VALUE)) {
- builder.addField(TrackingBundle.KEY_METADATA_VALUE,
- String.valueOf(trackingBundle.get(TrackingBundle.KEY_METADATA_VALUE)));
- }
- ((LauncherApplication)context.getApplicationContext()).sendEvent(builder.build());
-
- Logger.logd(TAG, trackingBundle.toString());
- } else {
- Logger.logd(TAG, "Not a valid tracking bundle");
- }
- }
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2015. The CyanogenMod 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.stats.internal.service;
-
-import android.app.AlarmManager;
-import android.app.IntentService;
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.preference.PreferenceManager;
-import android.util.Log;
-
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.stats.external.StatsUtil;
-import com.android.launcher3.stats.external.TrackingBundle;
-import com.android.launcher3.stats.internal.db.DatabaseHelper;
-import com.android.launcher3.stats.internal.model.CountAction;
-import com.android.launcher3.stats.internal.model.CountOriginByPackageAction;
-import com.android.launcher3.stats.internal.model.ITrackingAction;
-import com.android.launcher3.stats.internal.model.RemoteFolderAction;
-import com.android.launcher3.stats.internal.model.TrackingEvent;
-import com.android.launcher3.stats.util.Logger;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * <pre>
- * Service that starts on a timer and handles aggregating events and sending them to
- * CyanogenStats
- * </pre>
- *
- * @see {@link IntentService}
- */
-public class AggregationIntentService extends IntentService {
-
- // Constants
- private static final String TAG = AggregationIntentService.class.getSimpleName();
- private static final String TRACKING_ID = "com.cyanogenmod.trebuchet";
- public static final String ACTION_AGGREGATE_AND_TRACK =
- "com.cyanogenmod.trebuchet.AGGREGATE_AND_TRACK";
- private static final List<ITrackingAction> TRACKED_ACTIONS = new ArrayList<ITrackingAction>() {
- {
- add(new CountAction());
- add(new CountOriginByPackageAction());
- }
- };
- private static final int INVALID_COUNT = -1;
- private static final String KEY_LAST_TIME_RAN = "last_time_stats_ran";
- public static final String PREF_KEY_PAGE_COUNT = "page_count";
- public static final String PREF_KEY_WIDGET_COUNT = "widget_count";
-
- // Members
- private DatabaseHelper mDatabaseHelper = null;
- private int mInstanceId = -1;
- private SharedPreferences mPrefs = null;
-
- /**
- * Creates an IntentService. Invoked by your subclass's constructor.
- */
- public AggregationIntentService() {
- super(AggregationIntentService.class.getSimpleName());
- }
-
- @Override
- protected void onHandleIntent(Intent intent) {
- if (!isTrebuchetDefaultLauncher()) {
- // Cancel repeating schedule
- unscheduleService();
- // don't return b/c we still want to upload whatever metrics are left.
- }
- String action = intent.getAction();
- if (ACTION_AGGREGATE_AND_TRACK.equals(action)) {
- mPrefs = getSharedPreferences(LauncherAppState.getSharedPreferencesKey(),
- Context.MODE_PRIVATE);
- mPrefs.edit().putLong(KEY_LAST_TIME_RAN, System.currentTimeMillis()).apply();
- mInstanceId = (int) System.currentTimeMillis();
- mDatabaseHelper = DatabaseHelper.createInstance(this);
- performAggregation();
- deleteTrackingEventsForInstance();
- handleNonEventMetrics();
- }
- }
-
- private void performAggregation() {
-
- // Iterate available categories
- for (TrackingEvent.Category category : TrackingEvent.Category.values()) {
-
- // Fetch the events from the database based on the category
- List<TrackingEvent> eventList =
- mDatabaseHelper.getTrackingEventsByCategory(mInstanceId, category);
-
- Logger.logd(TAG, "Event list size: " + eventList.size());
- // Short circuit if no events for the category
- if (eventList.size() < 1) {
- continue;
- }
-
- // Now crunch the data into actionable events for the server.
- // Remote Folder data will process itself separately.
- if (category == TrackingEvent.Category.REMOTE_FOLDER) {
- performTrackingCall(new RemoteFolderAction(), category, eventList);
- } else {
- for (ITrackingAction action : TRACKED_ACTIONS) {
- performTrackingCall(action, category, eventList);
- }
- }
- }
- }
-
- private void deleteTrackingEventsForInstance() {
- mDatabaseHelper.deleteEventsByInstanceId(mInstanceId);
- }
-
- /**
- * These are metrics that are not event based and need a snapshot every INTERVAL
- */
- private void handleNonEventMetrics() {
- sendPageCountStats();
- sendWidgetCountStats();
-
- }
-
- private void sendPageCountStats() {
- int pageCount = mPrefs.getInt(PREF_KEY_PAGE_COUNT, INVALID_COUNT);
- if (pageCount == INVALID_COUNT) {
- return;
- }
- Bundle bundle = TrackingBundle
- .createTrackingBundle(TRACKING_ID, TrackingEvent.Category.HOMESCREEN_PAGE.name(),
- "count");
- bundle.putString(TrackingEvent.KEY_VALUE, String.valueOf(pageCount));
- StatsUtil.sendEvent(this, bundle);
- }
-
- private void sendWidgetCountStats() {
- int widgetCount = mPrefs.getInt(PREF_KEY_WIDGET_COUNT, INVALID_COUNT);
- if (widgetCount == INVALID_COUNT) {
- return;
- }
- Bundle bundle = TrackingBundle
- .createTrackingBundle(TRACKING_ID, TrackingEvent.Category.WIDGET.name(), "count");
- bundle.putString(TrackingEvent.KEY_VALUE, String.valueOf(widgetCount));
- StatsUtil.sendEvent(this, bundle);
- }
-
- private void performTrackingCall(ITrackingAction action, TrackingEvent.Category category,
- List<TrackingEvent> eventList)
- throws IllegalArgumentException {
- try {
- for (Bundle bundle : action.createTrackingBundles(TRACKING_ID, category, eventList)) {
- StatsUtil.sendEvent(this, bundle);
- }
- } catch (NullPointerException e) {
- Log.e(TAG, "NPE fetching bundle list!", e);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Illegal argument!", e);
- }
- }
-
- private void unscheduleService() {
- Intent intent = new Intent(this, AggregationIntentService.class);
- intent.setAction(ACTION_AGGREGATE_AND_TRACK);
- PendingIntent pi = PendingIntent.getService(this, 0, intent,
- PendingIntent.FLAG_UPDATE_CURRENT);
- AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
- alarmManager.cancel(pi);
- }
-
- private boolean isTrebuchetDefaultLauncher() {
- final IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
- filter.addCategory(Intent.CATEGORY_HOME);
-
- List<IntentFilter> filters = new ArrayList<IntentFilter>();
- filters.add(filter);
-
- final String myPackageName = getPackageName();
- List<ComponentName> activities = new ArrayList<ComponentName>();
- final PackageManager packageManager = getPackageManager();
-
- // You can use name of your package here as third argument
- packageManager.getPreferredActivities(filters, activities, null);
-
- for (ComponentName activity : activities) {
- if (myPackageName.equals(activity.getPackageName())) {
- Logger.logd(TAG, "Trebuchet IS default launcher!");
- return true;
- }
- }
- Logger.logd(TAG, "Trebuchet IS NOT default launcher!");
- return false;
- }
-
- private static final long ALARM_INTERVAL = 86400000; // 1 day
-
- /**
- * Schedule an alarm service, will cancel existing
- *
- * @param context {@link Context}
- * @throws IllegalArgumentException {@link IllegalArgumentException}
- */
- public static void scheduleService(Context context) throws IllegalArgumentException {
- if (context == null) {
- throw new IllegalArgumentException("'context' cannot be null!");
- }
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- long lastTimeRan = prefs.getLong(KEY_LAST_TIME_RAN, 0);
- Intent intent = new Intent(context, AggregationIntentService.class);
- intent.setAction(ACTION_AGGREGATE_AND_TRACK);
- PendingIntent pi = PendingIntent.getService(context, 0, intent,
- PendingIntent.FLAG_UPDATE_CURRENT);
- AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- alarmManager.cancel(pi);
- alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, lastTimeRan + ALARM_INTERVAL,
- ALARM_INTERVAL, pi);
- }
-
-}