diff options
Diffstat (limited to 'src/com/android/launcher3/stats/internal/model')
4 files changed, 413 insertions, 0 deletions
diff --git a/src/com/android/launcher3/stats/internal/model/CountAction.java b/src/com/android/launcher3/stats/internal/model/CountAction.java new file mode 100644 index 000000000..d509d4d26 --- /dev/null +++ b/src/com/android/launcher3/stats/internal/model/CountAction.java @@ -0,0 +1,73 @@ +/* + * 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.model; + +import android.os.Bundle; +import android.text.TextUtils; +import com.android.launcher3.stats.external.TrackingBundle; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * <pre> + * Handles the specific for sending a tracking event + * </pre> + * + * @see {@link ITrackingAction} + */ +public class CountAction implements ITrackingAction { + + public static final String TRACKING_ACTION = "count"; + + @Override + public String toString() { + return TRACKING_ACTION; + } + + @Override + public List<Bundle> createTrackingBundles(String trackingId, TrackingEvent.Category category, + List<TrackingEvent> eventList) { + + Map<String, List<TrackingEvent>> eventPackageMap = + new HashMap<String, List<TrackingEvent>>(); + + for (TrackingEvent event : eventList) { + String pkg = event.getMetaData(TrackingEvent.KEY_PACKAGE); + pkg = (TextUtils.isEmpty(pkg)) ? trackingId : pkg; + if (!eventPackageMap.containsKey(pkg)) { + eventPackageMap.put(pkg, new ArrayList<TrackingEvent>()); + } + eventPackageMap.get(pkg).add(event); + } + + List<Bundle> bundleList = new ArrayList<Bundle>(); + for (Map.Entry<String, List<TrackingEvent>> entry : eventPackageMap.entrySet()) { + Bundle bundle = TrackingBundle.createTrackingBundle(trackingId, category.name(), + TRACKING_ACTION); + bundle.putInt(TrackingBundle.KEY_METADATA_VALUE, entry.getValue().size()); + String pkg = entry.getKey(); + if (!pkg.equals(trackingId)) { + bundle.putString(TrackingBundle.KEY_METADATA_PACKAGE, pkg); + } + bundleList.add(bundle); + } + return bundleList; + } +} diff --git a/src/com/android/launcher3/stats/internal/model/CountOriginByPackageAction.java b/src/com/android/launcher3/stats/internal/model/CountOriginByPackageAction.java new file mode 100644 index 000000000..fc04ca088 --- /dev/null +++ b/src/com/android/launcher3/stats/internal/model/CountOriginByPackageAction.java @@ -0,0 +1,91 @@ +/* + * 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.model; + +import android.os.Bundle; +import android.text.TextUtils; +import com.android.launcher3.stats.external.TrackingBundle; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * <pre> + * This is an action to send a count of events with common origins + * </pre> + */ +public class CountOriginByPackageAction implements ITrackingAction { + + public static final String TRACKING_ACTION = "count_by_origin"; + + @Override + public String toString() { + return TRACKING_ACTION; + } + + @Override + public List<Bundle> createTrackingBundles(String trackingId, TrackingEvent.Category category, + List<TrackingEvent> eventList) { + // Make an origin mapper + Map<String, Map<String, List<TrackingEvent>>> originEventMap = + new HashMap<String, Map<String, List<TrackingEvent>>>(); + + // Parse the event list and categorize by origin + for (TrackingEvent event : eventList) { + // We are parsing for things with origin, if no origin is set, discard it! + if (TextUtils.isEmpty(event.getMetaData(TrackingEvent.KEY_ORIGIN))) { + continue; + } + String originKey = event.getMetaData(TrackingEvent.KEY_ORIGIN); + if (!originEventMap.containsKey(originKey)) { + HashMap<String, List<TrackingEvent>> newMap = + new HashMap<String, List<TrackingEvent>>(); + originEventMap.put(originKey, newMap); + } + String packageName = event.getMetaData(TrackingEvent.KEY_PACKAGE); + // Set a default so our iteration picks it up and just discard package metadata + packageName = (TextUtils.isEmpty(packageName)) ? trackingId : packageName; + if (!originEventMap.get(originKey).containsKey(packageName)) { + originEventMap.get(originKey).put(packageName, new ArrayList<TrackingEvent>()); + } + originEventMap.get(originKey).get(packageName).add(event); + } + + // Start building result tracking bundles + List<Bundle> bundleList = new ArrayList<Bundle>(); + for (Map.Entry<String, Map<String, List<TrackingEvent>>> entry : + originEventMap.entrySet()) { + String origin = entry.getKey(); + for (Map.Entry<String, List<TrackingEvent>> entry2 : entry.getValue().entrySet()) { + String pkg = entry2.getKey(); + List<TrackingEvent> events = entry2.getValue(); + Bundle bundle = TrackingBundle.createTrackingBundle(trackingId, category.name(), + TRACKING_ACTION); + bundle.putString(TrackingBundle.KEY_METADATA_ORIGIN, origin); + bundle.putInt(TrackingBundle.KEY_METADATA_VALUE, events.size()); + if (!trackingId.equals(pkg)) { + bundle.putString(TrackingBundle.KEY_METADATA_PACKAGE, pkg); + } + bundleList.add(bundle); + } + } + return bundleList; + } + +} diff --git a/src/com/android/launcher3/stats/internal/model/ITrackingAction.java b/src/com/android/launcher3/stats/internal/model/ITrackingAction.java new file mode 100644 index 000000000..b577ed2d0 --- /dev/null +++ b/src/com/android/launcher3/stats/internal/model/ITrackingAction.java @@ -0,0 +1,45 @@ +/* + * 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.model; + +import android.os.Bundle; + +import java.util.List; + +/** + * <pre> + * This is an action we want to perfrom from a report. + * + * e.g. + * 1. I want to get the COUNT of widgets added + * 2. I want to get the origin of app launches + * </pre> + */ +public interface ITrackingAction { + + /** + * Creates a new bundle used to tracking events + * + * @param trackingId {@link String} + * @param category {@link com.android.launcher3.stats.internal.model.TrackingEvent.Category} + * @param eventList {@link List} + * @return {@link List} + */ + List<Bundle> createTrackingBundles(String trackingId, TrackingEvent.Category category, + List<TrackingEvent> eventList); + +} diff --git a/src/com/android/launcher3/stats/internal/model/TrackingEvent.java b/src/com/android/launcher3/stats/internal/model/TrackingEvent.java new file mode 100644 index 000000000..91a9017be --- /dev/null +++ b/src/com/android/launcher3/stats/internal/model/TrackingEvent.java @@ -0,0 +1,204 @@ +/* + * 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.model; + +import android.content.ContentValues; +import android.database.Cursor; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.Log; +import com.android.launcher3.stats.external.TrackingBundle; +import com.android.launcher3.stats.internal.db.TrackingEventContract; +import com.android.launcher3.stats.util.Logger; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * <pre> + * Model of an event to track + * </pre> + */ +public class TrackingEvent { + + // Constants + private static final String TAG = TrackingEvent.class.getSimpleName(); + + // Members + private Category mCategory; + private final Map<String, String> mMetaData = new HashMap<String, String>(); + + public enum Category { + APP_LAUNCH, + WIDGET_ADD, + WIDGET_REMOVE, + SETTINGS_OPEN, + WALLPAPER_CHANGE, + HOMESCREEN_PAGE, + WIDGET, + } + + public static final String KEY_ORIGIN = TrackingBundle.KEY_METADATA_ORIGIN; + public static final String KEY_VALUE = TrackingBundle.KEY_METADATA_VALUE; + public static final String KEY_PACKAGE = TrackingBundle.KEY_METADATA_PACKAGE; + + /** + * Constructor + * + * @param category {@link TrackingEvent.Category} + * @throws IllegalArgumentException {@link IllegalArgumentException} + */ + public TrackingEvent(Category category) throws IllegalArgumentException { + if (category == null) { + throw new IllegalArgumentException("'category' cannot be null or empty!"); + } + mCategory = category; + } + + /** + * Constructor + * + * @param cursor {@link Cursor} + * @throws IllegalArgumentException {@link IllegalArgumentException} + */ + public TrackingEvent(Cursor cursor) throws IllegalArgumentException { + if (cursor == null) { + throw new IllegalArgumentException("'cursor' cannot be null!"); + } + mCategory = Category.valueOf(cursor.getString(cursor.getColumnIndex( + TrackingEventContract.EVENT_COLUMN_CATEGORY))); + String metadata = cursor.getString(cursor.getColumnIndex( + TrackingEventContract.EVENT_COLUMN_METADATA)); + if (!TextUtils.isEmpty(metadata)) { + String[] parts = metadata.split(","); + for (String part : parts) { + try { + String key = part.split("=")[0]; + String val = part.split("=")[1]; + mMetaData.put(key, val); + } catch (IndexOutOfBoundsException e) { + Log.w(TAG, e.getMessage(), e); + } + } + } + } + + /** + * Get the category + * + * @return {@link TrackingEvent.Category} + */ + public Category getCategory() { + return mCategory; + } + + /** + * Get the set of meta data keys + * + * @return {@link Set} + */ + public Set<String> getMetaDataKeySet() { + return mMetaData.keySet(); + } + + /** + * Set some meta data + * + * @param key {@link String} + * @param value {@link String} + * @throws IllegalArgumentException {@link IllegalArgumentException} + */ + public void setMetaData(String key, String value) throws IllegalArgumentException { + if (TextUtils.isEmpty(key)) { + throw new IllegalArgumentException("'key' cannot be null or empty!"); + } + if (TextUtils.isEmpty(value)) { + throw new IllegalArgumentException("'value' cannot be null or empty!"); + } + mMetaData.put(key, value); + } + + /** + * Get some meta data value + * + * @param key {@link String} + * @return {@link String} + * @throws IllegalArgumentException {@link IllegalArgumentException} + */ + public String getMetaData(String key) throws IllegalArgumentException { + if (TextUtils.isEmpty(key)) { + throw new IllegalArgumentException("'key' cannot be null or empty!"); + } + if (mMetaData.containsKey(key)) { + return mMetaData.get(key); + } + return null; + } + + /** + * Remove some meta data + * + * @param key {@link String} + * @return {@link String} or null + * @throws IllegalArgumentException {@link IllegalArgumentException} + */ + public String removeMetaData(String key) throws IllegalArgumentException { + if (TextUtils.isEmpty(key)) { + throw new IllegalArgumentException("'key' cannot be null or empty!"); + } + if (mMetaData.containsKey(key)) { + return mMetaData.remove(key); + } + return null; + } + + /** + * Converts this object into content values for use with sqlite + * + * @return {@link ContentValues} + */ + public ContentValues toContentValues() { + ContentValues contentValues = new ContentValues(); + contentValues.put(TrackingEventContract.EVENT_COLUMN_CATEGORY, mCategory.name()); + StringBuilder sb = new StringBuilder(); + for (String key : mMetaData.keySet()) { + sb.append(key).append("=").append(mMetaData.get(key)).append(","); + } + if (sb.length() > 0) { + String metadata = sb.toString(); + metadata = metadata.substring(0, metadata.length() - 1); + Logger.logd(TAG, "MetaData: " + metadata); + contentValues.put(TrackingEventContract.EVENT_COLUMN_METADATA, metadata); + } + return contentValues; + } + + /** + * Convert this object into a tracking bundle + * + * @param trackingId {@link String} + * @param action {@link ITrackingAction} + * @return {@link Bundle} + */ + public Bundle toTrackingBundle(String trackingId, ITrackingAction action) { + Bundle bundle = TrackingBundle.createTrackingBundle(trackingId, mCategory.name(), + action.toString()); + return bundle; + } + +} |