Remove all non-platform code and clean up files.

Change-Id: I526498b4a545813a706f86a7a106d087d3d0cb57
diff --git a/PixelPerfect/Android.mk b/PixelPerfect/Android.mk
index 4c58f5b..c3cdea9 100644
--- a/PixelPerfect/Android.mk
+++ b/PixelPerfect/Android.mk
@@ -1,85 +1,7 @@
 ########
-# Step 1 : Build all protobufs in our tree into a separate
-# static java library. Useful for IDEs etc. since the generated
-# source folder can be excluded if required.
+# Step 1 : Build the platform app
 
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-proto-files-under, imported_protos/src)
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := lite
-LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/imported_protos/src
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := libpixelperfect-protos
-LOCAL_SDK_VERSION := current
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-
-########
-# Step 2 : Build the shared platform library
-$(LOCAL_PATH) := $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_MODULE := pixelperfect-api
-LOCAL_MODULE_TAG := optional
-LOCAL_SDK_VERSION := current
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src/com/google/android/apps/pixelperfect/api) \
-        $(call all-Iaidl-files-under, src/com/google/android/apps/pixelperfect/api) \
-        $(call all-java-files-under, src/com/google/android/apps/pixelperfect/util) \
-        $(call all-proto-files-under, imported_protos/src)
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := lite
-LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/imported_protos/src
-
-LOCAL_JAVA_LIBRARIES := guava
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-
-########
-# Step 3 : Build the main app
-
-$(LOCAL_PATH) := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-# Use Google certificate instead of platform certificate since GmsCore
-# only allows usage from apps signed with the Google certificate.
-LOCAL_CERTIFICATE := vendor/unbundled_google/libraries/certs/app
-
-platform_source_file_patterns = src/com/google/android/apps/pixelperfect/platform/%
-LOCAL_SRC_FILES := $(filter-out $(platform_source_file_patterns), $(call all-java-files-under, src))
-
-LOCAL_PACKAGE_NAME := PixelPerfect
-
-# Enable proguard.
-LOCAL_PROGUARD_ENABLED := full
-LOCAL_PROGUARD_FLAG_FILES := proguard.tests.flags
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-        android-support-v13 \
-        guava \
-        pixelperfect-api \
-        libpixelperfect-protos
-
-LOCAL_MANIFEST_FILE := AndroidManifest.xml
-
-# Include GMS Core's client library.
-# The exact version is controlled by res/values/version.xml
-include vendor/unbundled_google/packages/PrebuiltGmsCore/google-play-services-first-party.mk
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
-
-# Step 4 : Build sub-packages (e.g. platform & tests)
-
-$(LOCAL_PATH) := $(call my-dir)
+LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := optional
@@ -101,10 +23,10 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
         android-support-v13 \
         guava \
-        libpixelperfect-protos \
-        pixelperfect-api
+        pixelperfect-api-prebuilt
 
-LOCAL_MANIFEST_FILE := platform/AndroidManifest.xml
+LOCAL_MANIFEST_FILE := AndroidManifest.xml
+
 # Include GMS Core's client library.
 # The exact version is controlled by res/values/version.xml
 include vendor/unbundled_google/packages/PrebuiltGmsCore/google-play-services-first-party.mk
@@ -116,7 +38,18 @@
 include $(BUILD_PACKAGE)
 
 ########
-# Step 5 : Build sub-packages (e.g. platform & tests)
+# Step 2 : Build the prebuilt libraries
+
+$(LOCAL_PATH) := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
+        pixelperfect-api-prebuilt:libs/pixelperfect-api.jar
+
+include $(BUILD_MULTI_PREBUILT)
+
+########
+# Step 3 : Build sub-packages (e.g. tests)
 
 # Use the following include to make our test apk.
 include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/PixelPerfect/AndroidManifest.xml b/PixelPerfect/AndroidManifest.xml
index a555e1f..a4d957f 100644
--- a/PixelPerfect/AndroidManifest.xml
+++ b/PixelPerfect/AndroidManifest.xml
@@ -1,8 +1,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.google.android.apps.pixelperfect"
+    package="com.google.android.apps.pixelperfect.platform"
     android:versionCode="1"
     android:versionName="1.0" >
-    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+    <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-sdk
         android:minSdkVersion="18"
@@ -10,30 +10,18 @@
     <application
         android:allowBackup="true"
         android:icon="@drawable/ic_cat"
-        android:label="@string/app_name" >
+        android:label="@string/platform_app_name" >
         <meta-data
             android:name="com.google.android.gms.version"
             android:value="@integer/google_play_services_version" />
         <service
-            android:name=".AccessibilityEventService"
-            class=".AccessibilityEventService"
+            android:name=".PixelPerfectPlatform"
+            class=".PixelPerfectPlatform"
             android:enabled="true"
-            android:exported="false"
-            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" >
+            android:exported="true" >
             <intent-filter>
-                <action android:name="android.accessibilityservice.AccessibilityService" />
+                <action android:name="com.google.android.apps.pixelperfect.api.IPixelPerfectPlatform" />
             </intent-filter>
-            <meta-data
-                android:name="android.accessibilityservice"
-                android:resource="@xml/accessibility_service_config" />
         </service>
-        <activity
-            android:name="com.google.android.apps.pixelperfect.preferences.PreferencesActivity"
-            android:screenOrientation="portrait" >
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
     </application>
 </manifest>
diff --git a/PixelPerfect/eclipse/gcore-fp.project b/PixelPerfect/eclipse/gcore-fp.project
deleted file mode 100644
index b49b722..0000000
--- a/PixelPerfect/eclipse/gcore-fp.project
+++ /dev/null
@@ -1,38 +0,0 @@
-# -*- mode: python; -*-
-
-name = 'gcore-fp'
-
-def CreateProperlyNamedLibLink(name):
-  return Link(
-      'liblinks/%s.jar' % name,
-      src='../../../out/target/common/obj/JAVA_LIBRARIES/'
-          '%s_intermediates/javalib.jar' % name)
-
-files = [
-  Link('res', src='../../../vendor/unbundled_google/packages/PrebuiltGmsCore/res'),
-  Create('AndroidManifest.xml', contents='<manifest package="com.google.android.gms"/>\n'),
-  Mkdir('libs'),
-  CreateProperlyNamedLibLink('prebuilt-google-play-services-first-party'),
-  Create('project.properties', contents='android.library=true\ntarget=android-19\n'),
-  Mkdir('gen'),
-]
-
-classpath = [
-  Src('gen'),
-  Lib('liblinks/prebuilt-google-play-services-first-party.jar'),
-  AndroidFramework(),
-  Output('bin'),
-]
-
-project = AndroidProject(
-  name=name,
-  builders=[
-    AndroidResourceManager(),
-    AndroidPreCompiler(),
-    JavaBuilder(),
-    AndroidApkBuilder(),
-  ]
-)
-
-formatting = 'eclipse/formatting.prefs'
-templates = 'eclipse/template.prefs'
diff --git a/PixelPerfect/eclipse/pixelperfect-test.project b/PixelPerfect/eclipse/pixelperfect-platform-test.project
similarity index 94%
rename from PixelPerfect/eclipse/pixelperfect-test.project
rename to PixelPerfect/eclipse/pixelperfect-platform-test.project
index 4393f5e..a136987 100644
--- a/PixelPerfect/eclipse/pixelperfect-test.project
+++ b/PixelPerfect/eclipse/pixelperfect-platform-test.project
@@ -1,6 +1,6 @@
 # -*- mode: python; -*-
 
-name = 'pixelperfect-test'
+name = 'pixelperfect-platform-test'
 
 
 def CreateProperlyNamedLibLink(name):
@@ -32,7 +32,7 @@
   Src('gen'),
   Lib('liblinks/junit4-target.jar', sourcepath='libsrcs/junit4-target'),
   Lib('liblinks/mockito-api.jar', sourcepath='libsrcs/mockito-src'),
-  Project('pixelperfect'),
+  Project('pixelperfect-platform'),
   AndroidFramework(),
   Output('bin'),
 ]
diff --git a/PixelPerfect/eclipse/pixelperfect.project b/PixelPerfect/eclipse/pixelperfect-platform.project
similarity index 83%
rename from PixelPerfect/eclipse/pixelperfect.project
rename to PixelPerfect/eclipse/pixelperfect-platform.project
index 044d2af..d2533a9 100644
--- a/PixelPerfect/eclipse/pixelperfect.project
+++ b/PixelPerfect/eclipse/pixelperfect-platform.project
@@ -1,6 +1,6 @@
 # -*- mode: python; -*-
 
-name = 'pixelperfect'
+name = 'pixelperfect-platform'
 
 def CreateProperlyNamedLibLink(name):
   return Link(
@@ -14,17 +14,14 @@
   Link('proguard.tests.flags'),
   Link('res'),
   Link('src'),
-  Link('imported_protos'),
   Link('scripts'),
   Link('eclipse'),
-  Link('platform'),
   LinkFramework('framework-core', 'frameworks/base/core/java'),
   LinkFramework('framework-java', 'libcore/luni/src/main/java'),
-  CreateProperlyNamedLibLink('libpixelperfect-protos'),
+  CreateProperlyNamedLibLink('pixelperfect-api-prebuilt'),
   CreateProperlyNamedLibLink('guava'),
   CreateProperlyNamedLibLink('android-support-v13'),
   CreateProperlyNamedLibLink('prebuilt-google-play-services-first-party'),
-  Link('libsrcs/libpixelperfect-protos', src='../../../out/target/common/obj/JAVA_LIBRARIES/libpixelperfect-protos_intermediates/src/proto/src/'),
   Link('libsrcs/android-support-v13', src='../../../frameworks/support/v13/java'),
   Link('libsrcs/guava', src='../../../external/guava/guava/src/'),
   Create('project.properties', contents='target=android-19\n'),
@@ -42,7 +39,7 @@
   Src('gen'),
   AndroidFrameworkSrc('framework-core'),
   AndroidFrameworkSrc('framework-java'),
-  Lib('liblinks/libpixelperfect-protos.jar', sourcepath='libsrcs/libpixelperfect-protos'),
+  Lib('liblinks/pixelperfect-api-prebuilt.jar'),
   Lib('liblinks/guava.jar', sourcepath='libsrcs/guava'),
   Lib('liblinks/android-support-v13.jar', sourcepath='libsrcs/android-support-v13'),
   Lib('liblinks/prebuilt-google-play-services-first-party.jar'),
diff --git a/PixelPerfect/imported_protos/src/net/proto2/bridge/proto/message_set.proto b/PixelPerfect/imported_protos/src/net/proto2/bridge/proto/message_set.proto
deleted file mode 100644
index 6133df4..0000000
--- a/PixelPerfect/imported_protos/src/net/proto2/bridge/proto/message_set.proto
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2007 Google Inc.  All rights reserved.
-// Author: kenton@google.com (Kenton Varda)
-//
-// This is proto2's version of MessageSet.  See net/proto/message_set.h to
-// learn what MessageSets are and how they are used.
-//
-// In proto2, we implement MessageSet in terms of extensions, except with a
-// special wire format for backwards-compatibily.  To define a message that
-// goes in a MessageSet in proto2, you must declare within that message's
-// scope an extension of MessageSet named "message_set_extension" and with
-// the field number matching the type ID.  So, for example, this proto1 code:
-//   message Foo {
-//     enum TypeId { MESSAGE_TYPE_ID = 1234; }
-//   }
-// becomes this proto2 code:
-//   message Foo {
-//     extend proto2.bridge.MessageSet {
-//       optional Foo message_set_extension = 1234;
-//     }
-//   }
-//
-// Now you can use the usual proto2 extensions accessors to access this
-// message.  For example, the proto1 code:
-//   MessageSet mset;
-//   Foo* foo = mset.get_mutable<Foo>();
-// becomes this proto2 code:
-//   proto2::bridge::MessageSet mset;
-//   Foo* foo = mset.MutableExtension(Foo::message_set_extension);
-//
-// Of course, new code that doesn't have backwards-compatibility requirements
-// should just use extensions themselves and not worry about MessageSet.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-
-package proto2.bridge;
-
-option java_outer_classname = "MessageSetProtos";
-option java_multiple_files = true;
-
-message MessageSet {
-  option message_set_wire_format = true;
-  extensions 4 to max;
-}
diff --git a/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/clientanalytics.proto b/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/clientanalytics.proto
deleted file mode 100644
index a40f702..0000000
--- a/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/clientanalytics.proto
+++ /dev/null
@@ -1,353 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-// Author: neel@google.com (Neel Parekh)
-//         jme@google.com (Big Tex Ellington)
-//
-// Protos by which Play clients communicate logging events to the Playlog
-// server.  Do not update this file without understanding the implications --
-// e.g. android clients are built against Java generated from this proto.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-
-package wireless_android_play_playlog;
-
-option java_package = "com.google.wireless.android.play.playlog.proto";
-option java_outer_classname = "ClientAnalytics";
-
-import "wireless/android/play/playlog/proto/play_games_client.proto";
-import "wireless/android/play/playlog/proto/play_store_client.proto";
-
-// Semi-arbitrary key-value pairs describing the event. Common entries
-// will be extracted into strongly typed fields in the GWS log records.
-message LogEventKeyValues {
-  optional string key = 1;
-  optional string value = 2;
-}
-
-// The set of currently active experiments for a given LogEvent.
-//
-// Next tag: 4
-message ActiveExperiments {
-  // The list of IDs of client-behavior-altering experiments that are on.
-  repeated string client_altering_experiment = 1;
-
-  // The list of IDs of other experiments that are on. The client must not
-  // change its hehavior in response to these experiments.
-  repeated string other_experiment = 2;
-
-  // The list of GWS experiments that are on. These are not targeted by Playlog.
-  repeated int32 gws_experiment = 3;
-}
-
-// Next tag: 13
-message LogEvent {
-  // Epoch time in milliseconds.
-  optional int64 event_time_ms = 1;
-
-  // Type of event, could be “CLICK” or “PAGE_VIEW” or “DOWNLOAD_STATUS”.
-  // There will be a common repository of cross-vertical events that should be
-  // used, but any individual app would be free to define their own tags.
-  //
-  // DISCOURAGED: use event_code instead.
-  optional string tag = 2;
-
-  // Type of event. Different kinds of events inside a client app should have
-  // different values of 'event_code'. Different client apps may have
-  // overlapping sets of 'event_code' values; these velues are only meant to
-  // make sense within the context of a single client app, as identified by
-  // the 'log_source' field of LogRequest.
-  //
-  // A typical way to use 'event_code' is to define the enum of possible values
-  // inside of the clientevents/ subdirectory (example: http://cl/58990806).
-  optional int32 event_code = 11;
-
-  // Identifies a group of events that belong to the same flow or session of
-  // user interaction, which is a client-specific concept.
-  //
-  // These IDs are used in the Clearcut/UMA pipeline for computing latencies
-  // between pairs of events, where it is necessary to ensure that both events
-  // belong to the same flow.
-  //
-  // For example, the Google Play team may want to give a unique ID to each
-  // purchase session, including all of the events starting from the initial
-  // search for an app to the eventual purchase and installation of the app.
-  // Another example would be the Search app wanting to tie together search
-  // query events and clicks on search results, especially if several instances
-  // of the app may be active at the same time.
-  optional int32 event_flow_id = 12;
-
-  // Whether this event was initiated by the user at the time of the event or
-  // shortly before (vs. a background event like upgrading a database after the
-  // app was automatically updated).
-  optional bool is_user_initiated = 10;
-
-  // These might contain PII and will not be stored for more than 8 days.
-  // If possible, please create a named field in the protos below instead.
-  repeated LogEventKeyValues value = 3;
-
-  // TODO: Deprecate/Remove. Use source_extension instead.
-  //
-  // Extension for Play Store app logs.
-  optional PlayStoreLogEvent store = 4;
-
-  // TODO: Deprecate/Remove. Use source_extension instead.
-  //
-  // Extension for Play Games app logs
-  optional PlayGamesLogEvent games = 5;
-
-  // First-party app usage tracking. Used only when log_source = APP_USAGE_1P.
-  optional AppUsage1pLogEvent app_usage_1p = 9;
-
-  // A source specific extension (typically a serialized proto). The type of
-  // this data is determined by the log_source of the enclosing LogRequest.
-  optional bytes source_extension = 6;
-
-  // A JsProto version of source_extension, using array serialization format.
-  optional bytes source_extension_js = 8;
-
-  // The set of currently active experiments. If missing, then the server will
-  // assume that experiment on/off status has not changed since the previous
-  // LogEvent message in the same LogRequest proto. If missing in the very first
-  // LogEveent of a LogRequest, then the server will assume that all experiments
-  // are off.
-  optional ActiveExperiments exp = 7;
-}
-
-// Atributes specific to Android clients.
-//
-// Next tag: 17
-message AndroidClientInfo {
-  // "Gservices" android ID.  Considered PII.  Never logged in archival logs.
-  optional int64 android_id = 1;
-
-  // Pseudonymous, random id (sticky) per device.  Never logged in temp logs.
-  optional string logging_id = 2;
-
-  // This comes from android.os.Build.VERSION.SDK_INT.
-  optional int32 sdk_version = 3;
-
-  // Textual description of the client platform.  e.g., "Nexus 4".
-  // This comes from android.os.Build.MODEL.
-  optional string model = 4;
-
-  // The name of the overall product. e.g., "occam".
-  // This comes from android.os.Build.Product.
-  optional string product = 5;
-
-  // The name of the hardware (from the kernel command line or /proc).
-  // This comes from android.os.Build.Hardware.  e.g., "mako".
-  optional string hardware = 8;
-
-  // The name of the industrial design.  e.g., "mako".
-  // This comes from android.os.Build.Device.
-  optional string device = 9;
-
-  // This comes from android.os.Build.ID.  e.g., something like "JRN54F".
-  optional string os_build = 6;
-
-  // The client application version. The java int version in the android package
-  // converted to string.
-  optional string application_build = 7;
-
-  // The mobile country code / mobile network code (MCC/MNC).
-  // e.g., 310004 for Verizon USA.
-  optional string mcc_mnc = 10;
-
-  // The chosen locale from the client. e.g., "en_US", "ko_KR", "en_GB".
-  optional string locale = 11;
-
-  // The chosen country from the client. e.g., "US", "KR", "JP".
-  optional string country = 12;
-
-  // The manufacturer of the hardware.
-  // This comes from android.os.Build.MANUFACTURER
-  optional string manufacturer = 13;
-
-  // The brand the software is customized for, if any.  Often a carrier name.
-  // e.g. "google"
-  // from http://developer.android.com/reference/android/os/Build.html#BRAND
-  optional string brand = 14;
-
-  // The name of the underlying board
-  // e.g. "tuna"
-  // from http://developer.android.com/reference/android/os/Build.html#BOARD
-  optional string board = 15;
-
-  // Radio version as reported by device, if available at reporting time
-  // e.g. "I9250XXLJ1"
-  // from http://developer.android.com/reference/android/os/Build.html#getRadioVersion()
-  optional string radio_version = 16;
-}
-
-// Atributes specific to desktop clients.
-//
-// Next tag: 7
-message DesktopClientInfo {
-  // Sticky ID that should be considered PII.
-  optional string client_id = 1;
-
-  // Pseudonymous, random id (sticky) per device.  Never logged in temp logs.
-  optional string logging_id = 2;
-
-  // e.g., "mac", "windows", "linux"
-  optional string os = 3;
-
-  // e.g., "10.7", "Vista", "Win7"
-  optional string os_major_version = 4;
-
-  // e.g., "10.7.3", "Win7 SP1"
-  optional string os_full_version = 5;
-
-  // The client application version.
-  optional string application_build = 6;
-}
-
-// Attributes specific to iOS clients.
-//
-// Next tag: 6
-message IosClientInfo {
-  // Sticky ID that should be considered PII.
-  optional string client_id = 1;
-
-  // Pseudonymous, random id (sticky) per device.  Never logged in temp logs.
-  optional string logging_id = 2;
-
-  optional string os_major_version = 3;
-
-  optional string os_full_version = 4;
-
-  // The client application version.
-  optional string application_build = 5;
-}
-
-// Next tag: 5
-message ClientInfo {
-  // The type of client that made this request.
-  // Next enum tag: 5
-  enum ClientType {
-    UNKNOWN = 0;
-    JS = 1;
-    DESKTOP = 2;
-    IOS = 3;
-    ANDROID = 4;
-  }
-
-  optional ClientType client_type = 1 [default = UNKNOWN];
-
-  // Only one of the following *_client_info fields will exist in any request.
-  optional AndroidClientInfo android_client_info = 2;
-  optional DesktopClientInfo desktop_client_info = 3;
-  optional IosClientInfo ios_client_info = 4;
-}
-
-// The list of IDs of experiments that are currently on for this client. All
-// other experiments are off.
-//
-// Next tag: 2
-message ExperimentIdList {
-  // IDs are sorted and do not contain duplicates.
-  repeated string id = 1;
-}
-
-// First party app usage log event extension.
-// Used only when log_source = APP_USAGE_1P.
-//
-// Next tag: 19
-message AppUsage1pLogEvent {
-  enum AppType {
-    UNKNOWN = 0;
-    GOOGLE_SEARCH = 1;
-    GOOGLE_CALENDAR = 2;
-    GOOGLE_PLUS = 3;
-    GMAIL = 4;
-    GOOGLE_PLAY_STORE = 5;
-    GOOGLE_PLAY_MUSIC = 6;
-    GOOGLE_PLAY_BOOKS = 7;
-    GOOGLE_PLAY_VIDEO = 8;
-    GOOGLE_PLAY_MAGAZINES = 9;
-    GOOGLE_PLAY_GAMES = 10;
-    GMS_CORE = 11;
-    ANDROID_IDE = 12;
-    ANDROID_TV = 13;
-    LE = 14; // Location Engine within GMSCore, potentially with PII data
-    GOOGLE_MAPS = 15;
-    GOOGLE_CAMERA = 16;
-    YOUTUBE = 17;
-    ANDROID_TIMELY = 18;
-  }
-  optional AppType app_type = 1;
-
-  // Package name of the app (on Android).
-  optional string android_package_name = 2;
-
-  // Version of the app.
-  optional string version = 3;
-}
-
-// A LogRequest represents a batched collection of loggable events, each
-// event to be persited in a GWS log entry by the Playlog server.
-//
-// Next tag: 6
-message LogRequest {
-  // Next enum tag: 28
-  enum LogSource {
-    UNKNOWN = -1;
-
-    STORE = 0;
-    MUSIC = 1;
-    BOOKS = 2;
-    VIDEO = 3;
-    MAGAZINES = 4;
-    GAMES = 5;
-    LB_A = 6;   // for collecting app usage stats (Lockbox project)
-    ANDROID_IDE = 7;  // Android IDE (go/android-diamond)
-    LB_P = 8;  // for collecting phone call events and stats (Lockbox project)
-    LB_S = 9;  // for collecting SMS events and stats (Lockbox project)
-    GMS_CORE = 10;  // Usage of GMS Core itself and its internal stats
-    APP_USAGE_1P = 11;  // First-party app usage tracking.
-    ICING = 12;  // Icing stats (AppDataSearch go/icing)
-    HERREVAD = 13;  // for collecting Nova Network quality data
-    ANDROID_TV = 14;  // Android TV, not Eureka.
-    EDU_STORE = 15;  // for collecting stats on Play for Education
-    GMS_CORE_PEOPLE = 16;  // GMS core people (aka menagerie)
-    LE = 17;  // Location Engine statistics
-    GOOGLE_ANALYTICS = 18;  // Google Analytics SDK health monitoring
-    LB_D = 19;  // for collecting device state changes (Lockbox project)
-    ANDROID_GSA = 20;  // Android GSA (Google Search App) stats
-    LB_T = 21;  // for collecting Android RunningTaskInfo (Lockbox project)
-    PERSONAL_LOGGER = 22;  // PixelPerfect activity logger
-    GMS_CORE_WALLET_MERCHANT_ERROR = 23;  // GMS core wallet merchant errors
-    LB_C = 24; // Android contacts going from Now to Moonshine.
-    ANDROID_AUTH = 25;  // for collecting GMS core android auth data
-    ANDROID_CAMERA = 26; // Android camera usage statistics
-    CW = 27;  // Clockwork interaction logs
-  }
-
-  // "Now", in milliseconds, according to the same clock that was used to set
-  // 'event_time_ms' values in the LogEvent protos below.
-  optional int64 request_time_ms = 4;
-
-  optional ClientInfo client_info = 1;
-  optional LogSource log_source = 2 [default = UNKNOWN];
-  repeated LogEvent log_event = 3;
-
-  // Can be used instead of 'log_event' in order to save battery in cases where
-  // LogEvent protos are already serialized, and deserializing is undesirable.
-  // If used, this is a collection of byte streams each produced using a
-  // CodedOutputStream.
-  repeated bytes serialized_log_events = 5;
-}
-
-// Next tag: 3
-message LogResponse {
-  // Client should wait for next_request_wait_millis before sending the next log
-  // request.
-  optional int64 next_request_wait_millis = 1 [default = -1];
-
-  // If present, this is the new set of enabled experiments for this client.
-  // Otherwise, the client should assume that there has been no change in the
-  // set of enabled experiments.
-  optional ExperimentIdList experiments = 2;
-}
-
diff --git a/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/personal_application_event.proto b/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/personal_application_event.proto
deleted file mode 100644
index a483af0..0000000
--- a/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/personal_application_event.proto
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-// Author: alasdair@google.com (Alasdair Mackintosh)
-//
-// A record of a user interaction event captured by PixelPerfect.  Combines the
-// RecordedUpdate generated by the PersonalRecorder app with additional
-// information from the Clearcut log.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-
-package wireless_android_play_playlog;
-
-import "net/proto2/bridge/proto/message_set.proto";
-import "wireless/android/play/playlog/proto/clientanalytics.proto";
-import "wireless/android/play/playlog/proto/personal_recorder.proto";
-
-option java_package = "com.google.wireless.android.play.playlog.proto";
-option java_outer_classname = "PersonalApplicationEventProto";
-
-message PersonalApplicationEvent {
-  extend proto2.bridge.MessageSet {
-    optional PersonalApplicationEvent message_set_extension = 58425595;
-  }
-
-  // Describes the client where this event came from
-  optional ClientInfo client_info = 1;
-
-  // The UTC timestamp for when this event happened.
-  optional int64 timestamp_millis = 2;
-
-  // The UTC timestamp that the client gave us for when this event happened.
-  // Unreliable, but useful for diagnosing clock skew issues.
-  optional int64 client_timestamp_millis = 3;
-
-  // The event recorded by the client.
-  optional RecordedUpdate recorded_update = 4;
-}
diff --git a/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/personal_recorder.proto b/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/personal_recorder.proto
deleted file mode 100644
index 728fe69..0000000
--- a/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/personal_recorder.proto
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-// Author: alasdair@google.com (Alasdair Mackintosh)
-//
-// Interaction data captured by the PixelPerfect PersonalRecorder app. Records
-// how a user interacts with installed applications on their Android device.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-
-option java_package = "com.google.common.logging";
-option java_outer_classname = "RecordedEvent";
-
-package wireless_android_play_playlog;
-
-// The data contained in an android.graphics.Rect object
-message RecordedRect {
-  optional int32 bottom = 1;
-  optional int32 left = 2;
-  optional int32 right = 3;
-  optional int32 top = 4;
-}
-
-message RecordedTypes {
-  // Represents the type of an Android screen widget.
-  enum WidgetType {
-    CUSTOM = 0;  // Not a predefined Android type
-    APP_WIDGET_HOST_VIEW = 1;  // android.appwidget.AppWidgetHostView
-    VIEW = 2;  // android.view.View
-    WEB_VIEW = 3;  // android.webkit.WebView
-    BUTTON = 4;  // android.widget.Button
-    CHECK_BOX = 5;  // android.widget.CheckBox
-    CHECKED_TEXT_VIEW = 6;  // android.widget.CheckedTextView
-    EDIT_TEXT = 7;  // android.widget.EditText
-    FRAME_LAYOUT = 8;  // android.widget.FrameLayout
-    HORIZONTAL_SCROLL_VIEW = 9;  // android.widget.HorizontalScrollView
-    IMAGE_BUTTON = 10;  // android.widget.ImageButton
-    IMAGE_VIEW = 11;  // android.widget.ImageView
-    LINEAR_LAYOUT = 12;  // android.widget.LinearLayout
-    LIST_VIEW = 13;  // android.widget.ListView
-    MULTI_AUTO_COMPLETE_TEXT_VIEW = 14;  // android.widget.MultiAutoCompleteTextView
-    PROGRESS_BAR = 15;  // android.widget.ProgressBar
-    RELATIVE_LAYOUT = 16;  // android.widget.RelativeLayout
-    SCROLL_VIEW = 17;  // android.widget.ScrollView
-    SPINNER = 18;  // android.widget.Spinner
-    SWITCH = 19;  // android.widget.Switch
-    TAB_HOST = 20;  // android.widget.TabHost
-    TAB_WIDGET = 21;  // android.widget.TabWidget
-    TEXT_VIEW = 22;  // android.widget.TextView
-    VIEW_SWITCHER = 23;  // android.widget.ViewSwitcher
-  }
-}
-
-// Represents an image, such as for screen shots.
-// Next available id: 6
-message Bitmap {
-  // Possible bitmap configurations.
-  // http://go/android-reference/android/graphics/Bitmap.Config.html
-  // Next available id: 3
-  message BitmapConfig {
-    enum Config {
-      UNKNOWN = 0;
-      ALPHA_8 = 1;
-      ARGB_4444 = 2;
-      ARGB_8888 = 3;
-      RGB_565 = 4;
-    }
-    // tag 1 is deprecated.
-    optional Config value = 2;
-  };
-
-  // Known formats that the bitmap can be compressed to.
-  // http://go/android-reference/android/graphics/Bitmap.CompressFormat.html
-  // Next available id: 4
-  message CompressionConfig {
-    enum CompressFormat {
-      UNKNOWN = 0;
-      JPEG = 1;
-      PNG = 2;
-      WEBP = 3;
-    }
-    // tag 1 is deprecated.
-    optional CompressFormat format = 2;
-    optional int32 quality = 3;
-  };
-
-  // The actual bitmap.
-  optional bytes bitmap = 1;
-  optional int32 height = 2;
-  optional int32 width = 3;
-  // Bitmap and compression config.
-  optional BitmapConfig bitmap_config = 4;
-  optional CompressionConfig compression_config = 5;
-}
-
-message Screenshot {
-  // Bitmap of the screenshot.
-  optional Bitmap bitmap = 1;
-  // Display rotation when screenshot was taken. We could "fix" the orientation
-  // at the client, but it may be useful to preserve this information and let
-  // any fixing, if required, be done by the analysis and processing machinery.
-  // http://go/android-reference/android/view/Surface.html#ROTATION_0
-  optional int32 rotation = 2;
-};
-
-// Represents an Android UI element, and optionally its children.  Next
-// available id = 10
-message UIElement {
-  // The type of the element. If the type is CUSTOM, the class_name will be set
-  // to the full class name of the element's widget type. Otherwise the class
-  // name will be empty. (We use this to avoid transmitting unnecessary string
-  // data.)
-  optional RecordedTypes.WidgetType class_type = 1 [default = CUSTOM];
-
-  optional string class_name = 2;
-
-  // The name of the Android UI resource. (The "android:id" property defined in
-  // the app's layout XML file.)
-  optional string resource_name = 3;
-
-  // The android:contentDescription of this view item, if specified.
-  optional string description = 4;
-
-  // The text content of this item, if any.
-  optional string content = 5;
-
-  // Whether the content of the UIElement are intentionally elided.
-  // This happens for sensitive fields, such as passwords.
-  optional bool content_elided = 8 [default = false];
-
-  // The boundary of this element, relative to its parent. See
-  // http://developer.android.com/reference/android/view/accessibility/
-  // AccessibilityNodeInfo.html#getBoundsInParent(android.graphics.Rect)
-  optional RecordedRect rect = 6;
-
-  // Screenshot for the corresponding UI element.
-  // Screenshot is genuinely optional, and should not be assumed to be
-  // present.
-  optional Screenshot screenshot = 9;
-
-  // Children of this element.
-  repeated UIElement child = 7;
-}
-
-// Represents an update to the user's application, either caused by a direct
-// user action (pressing a button, entering text) or by the application
-// performing a screen update.
-message RecordedUpdate {
-  // The type of the update. Corresponds to the types defined in
-  // android.view.accessibility.AccessibilityEvent.
-  enum Type {
-    UNSET = 0;
-    TYPE_NOTIFICATION_STATE_CHANGED = 1;
-    TYPE_VIEW_CLICKED = 2;
-    TYPE_VIEW_FOCUSED = 3;
-    TYPE_VIEW_LONG_CLICKED = 4;
-    TYPE_VIEW_SCROLLED = 5;
-    TYPE_VIEW_SELECTED = 6;
-    TYPE_VIEW_TEXT_CHANGED = 7;
-    TYPE_VIEW_TEXT_SELECTION_CHANGED = 8;
-    TYPE_WINDOW_CONTENT_CHANGED = 9;
-  }
-  optional Type type = 1;
-
-  // The name of the package that triggered this event. Taken from the
-  // getPackageName() method in android.view.accessibility.AccessibilityEvent.
-  // E.g. "com.android.launcher" or "com.google.android.youtube".
-  optional string package_name = 4;
-
-  // The UIElement that this update applies to. If the type is
-  // TYPE_WINDOW_CONTENT_CHANGED, then the element represents the root window,
-  // and its children will be recursively populated. Otherwise it represents the
-  // UI element where the event took place (e.g. the item that was clicked on)
-  // and the children will not be populated.
-  optional UIElement element = 2;
-
-  // The version of the recorder application that published this udpate.
-  optional string version = 3;
-}
diff --git a/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/play_games_client.proto b/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/play_games_client.proto
deleted file mode 100644
index 7c71b27..0000000
--- a/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/play_games_client.proto
+++ /dev/null
@@ -1,761 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-// Author: gshih@google.com (Grace Shih)
-//
-// Play Games logging protos. This is sent as a field within
-// clientanalytics.proto.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-
-package wireless_android_play_playlog;
-
-option java_package = "com.google.wireless.android.play.playlog.proto";
-option java_outer_classname = "PlayGames";
-
-// DEPRECATED(11/07/2013): sent by old clients. Use GenericNotificationAction
-// Details about a user-visible notification sent from old clients
-message PlayGamesNotificationActionDeprecated {
-
-  enum NotificationActionType {
-
-    // The notification was received on the device.
-    RECEIVED = 1;
-
-    // The notification was displayed to the user.
-    DISPLAYED = 2;
-
-    // The user saw the notification and dismissed it.
-    DISMISSED = 3;
-
-    // The user interacted with the notification and opened it.
-    OPENED = 4;
-
-    // The system chose to revoke this notification without the user seeing it.
-    // This could be because of action on another device, time limit, etc.
-    CANCELED = 5;
-
-    // This notification was consumed by another client before being displayed
-    // to the user.
-    CONSUMED = 6;
-
-    // Next index: 7;
-  }
-
-  // The type of action this log event represents.
-  optional NotificationActionType action_type = 1;
-
-  // The IDs of the notifications this action is for, if any.
-  repeated string notification_id = 2;
-
-  // How many notifications are being displayed to the user.
-  optional int32 displayed_count = 3;
-
-  // Next index: 4;
-}
-
-// Details about the user-visible android notification
-message PlayGamesAndroidNotificationAction {
-
-  enum NotificationActionType {
-
-    // The notification type was unknown
-    UNKNOWN = 0;
-
-    // The notification was received on the device.
-    RECEIVED = 1;
-
-    // The notification was displayed to the user.
-    DISPLAYED = 2;
-
-    // The user saw the notification and dismissed it.
-    DISMISSED = 3;
-
-    // The user interacted with the notification and opened it.
-    OPENED = 4;
-
-    // The system chose to revoke this notification without the user seeing it.
-    // This could be because of action on another device, time limit, etc.
-    CANCELED = 5;
-
-    // This notification was consumed by another client before being displayed
-    // to the user.
-    CONSUMED = 6;
-
-    // Next index: 7;
-  }
-
-  // The type of action this log event represents.
-  optional NotificationActionType action_type = 1;
-
-  // The IDs of the notifications this action is for, if any.
-  repeated string notification_id = 2;
-
-  // How many notifications are being displayed to the user.
-  optional int32 displayed_count = 3;
-
-  // Next index: 4;
-}
-
-// Details about the iOS notification
-message PlayGamesIosNotificationAction {
-
-  // The action the notification
-  enum NotificationActionType {
-
-    // The notification type was unknown
-    UNKNOWN = 0;
-
-    // The notification was received on the device.
-    APP_CONSUMED = 1;
-
-    // Next index: 2;
-  }
-
-  // The type of action this log event represents.
-  optional NotificationActionType action_type = 1;
-
-  // Next index: 2;
-}
-
-// Details about a user-visible notification
-message PlayGamesGenericNotificationAction {
-
-  // The type of notification action this was
-  enum NotificationPlatform {
-    UNKNOWN = 0;
-
-    // The notification was on an android device
-    ANDROID = 1;
-
-    // The notification was on an iOS device
-    IOS = 2;
-
-    // Next index: 3;
-  }
-
-  // Which type of notification this was
-  optional NotificationPlatform action_type = 1;
-
-  // Only one of the fields below will be populated
-  // The Android notification details
-  optional PlayGamesAndroidNotificationAction android_action = 2;
-
-  // The iOS notification details
-  optional PlayGamesIosNotificationAction ios_action = 3;
-
-  // Next index: 4;
-}
-
-// Details about an iOS device registration
-message PlayGamesIosDeviceRegister {
-
-  // 32 byte APNS device token assigned by apple.
-  optional bytes apns_device_token = 1;
-
-  // The iOS sdk version that sent the registration
-  optional string sdk_version = 2;
-
-  // The language of the device
-  optional string language = 3;
-
-  // Next index: 4
-}
-
-// Details about an iOS device unregistration
-message PlayGamesIosDeviceUnregister {
-
-  // 32 byte APNS device token assigned by apple.
-  optional bytes apns_device_token = 1;
-
-  // Next index: 2
-}
-
-// Details about an iOS specific type of message
-message PlayGamesIosDeviceAction {
-
-  // The type of iOS action
-  enum IosDeviceActionType {
-    UNKNOWN = 0;
-
-    // The device token was registered
-    REGISTER_DEVICE = 1;
-
-    // The device token was unregistered
-    UNREGISTER_DEVICE = 2;
-
-    // Next index: 3
-  }
-
-  // What type of token registration was this and
-  optional IosDeviceActionType action_type = 1;
-
-  // Only one of these fields will be filled depending on action_type
-  // The details of registration
-  optional PlayGamesIosDeviceRegister register_action = 2;
-
-  // The details of the unregistration
-  optional PlayGamesIosDeviceUnregister unregister_action = 3;
-
-  // Next index: 4;
-}
-
-// Details about the game tab in the destination app
-message PlayGamesDestinationAppGameTabInfo {
-
-  // The application collection being viewed
-  enum ApplicationCollection {
-    UNKNOWN_COLLECTION = 0;
-    FEATURED = 1;
-    MULTIPLAYER = 2;
-    PLAYED = 3;
-    RECOMMENDED = 4;
-    DOWNLOADED = 5;
-    ALL_GAMES = 6;
-    HIDDEN_GAMES = 7;
-    INSTALLED = 8;
-    // Next index = 9
-  }
-
-  // The collection type being displayed
-  optional ApplicationCollection collection = 1;
-
-  // True if user is viewing the top of the list, false if user has scrolled
-  // down
-  optional bool top_of_list = 2;
-
-  // Tracking id for actions taken based on search / recommendations
-  optional string discovery_tid = 3;
-
-  // Next index: 4
-}
-
-// Details about a game purchase from the destination app
-message PlayGamesDestinationAppGamePurchase {
-
-  // The price displayed to the user; null or 0 means free
-  optional int64 price_micros = 1;
-
-  // The purchase was successfully completed.  (This only matters when
-  // is_start_action = false.)
-  optional bool has_completed_purchase = 2;
-
-  // Tracking id for actions taken based on search / recommendations
-  optional string discovery_tid = 3;
-
-  // How far down in search / recommendations this game was displayed.
-  optional uint32 ranking_position = 4;
-
-  // Next index: 5
-}
-
-// Details about a game in the destination app
-message PlayGamesDestinationAppGameAction {
-
-  // Which section the user is viewing on the game detail page
-  enum GameDetailSection {
-
-    // UNKNOWN
-    UNKNOWN_SECTION = 0;
-
-    // About game
-    ABOUT = 1;
-
-    // The achievements for the game
-    ACHIEVEMENT_LIST = 2;
-
-    // The leaderboards for the game
-    LEADERBOARD_LIST = 3;
-
-    // Friends who also play this game
-    FRIEND_LIST = 4;
-
-    // Next index: 5
-  }
-
-  // The app id of the game
-  optional string application_id = 1;
-
-  // The section the user is viewing
-  optional GameDetailSection section = 2;
-
-  // User launched the game from the dest app
-  optional bool launched_game = 3;
-
-  // Leaderboard actions if the player chose a specific leaderboard
-  optional PlayGamesLeaderboardAction leaderboard = 4;
-
-  // User clicked to purchase game from the dest app
-  optional PlayGamesDestinationAppGamePurchase game_purchase = 5;
-
-  // Tracking id for actions taken based on search / recommendations
-  optional string discovery_tid = 6;
-
-  // How far down in search / recommendations this game was displayed.
-  optional uint32 ranking_position = 7;
-
-  // Next index: 8
-}
-
-// Details about the game tab in the destination app
-message PlayGamesDestinationAppPlayerTabInfo {
-
-  // The application collection being viewed
-  enum PlayerCollection {
-
-    // Unknown default actions
-    UNKNOWN_COLLECTION = 0;
-
-    // List of everyone in your circles
-    ALL = 1;
-
-    // List of people in your circles who have recently played games
-    MOST_RECENT = 2;
-
-    // List of people you may know
-    YOU_MAY_KNOW = 3;
-
-    // Next index: 4
-  }
-
-  // The collection type being displayed
-  optional PlayerCollection collection = 1;
-
-  // True if user is viewing the top of the list, false if user has scrolled
-  // down
-  optional bool top_of_list = 2;
-
-  // Tracking id for actions taken based on search / recommendations
-  optional string discovery_tid = 3;
-
-  // Next index: 4
-}
-
-// Details about a player in the destination app
-message PlayGamesDestinationAppPlayerAction {
-
-  // Which section the user is viewing on the player detail page
-  enum PlayerDetailSection {
-
-    // UNKNOWN
-    UNKNOWN_SECTION = 0;
-
-    // List of recently played games
-    RECENTLY_PLAYED = 1;
-
-    // Next index: 2
-  }
-
-  // The section the user is viewing
-  optional PlayerDetailSection section = 1;
-
-  // Tracking id for actions taken based on search / recommendations
-  optional string discovery_tid = 2;
-
-  // How far down in search / recommendations this game was displayed.
-  optional uint32 ranking_position = 3;
-
-  // Next index: 4
-}
-
-// Details about an action taken in the Settings page
-message PlayGamesDestinationAppSettingsAction {
-
-  // True if the user switched accounts
-  optional bool switched_account = 1;
-
-  // True if the user enabled notifications, false if the user disabled
-  // notifications
-  optional bool mobile_notifications_enabled = 2;
-
-  // True if the user enabled email notifications, false if the user
-  // disabled email notifications
-  optional bool email_notifications_enabled = 3;
-
-  // True if the user enabled social sharing, false if the user
-  // disabled social sharing
-  optional bool social_sharing_enabled = 4;
-
-  // The app id that the user chose to unmute notifications
-  repeated string unmuted_notifications_app_id = 5;
-
-  // Next index: 6
-}
-
-// Details about a destination app action
-message PlayGamesDestinationAppAction {
-
-  // The page in the destination app that the user clicked on
-  enum DestinationAppPageType {
-
-    // Unknown page
-    UNKNOWN_PAGE_TYPE = 0;
-
-    // The splash screen
-    SPLASH_SCREEN = 1;
-
-    // The list of games
-    GAME_TAB = 2;
-
-    // The list of players/friends
-    PLAYER_TAB = 3;
-
-    // The list of matches
-    MATCH_TAB = 4;
-
-    // The detail page for a game
-    GAME_DETAIL = 5;
-
-    // The detail page for a player
-    PLAYER_DETAIL = 6;
-
-    // The settings page
-    SETTINGS = 7;
-
-    // Launched the play store
-    PLAY_STORE = 8;
-
-    // Next index: 9
-  }
-
-  // The page the user wants to view
-  optional DestinationAppPageType page_type = 1;
-
-  // Details about the game tab if page_type == GAMES_TAB
-  optional PlayGamesDestinationAppGameTabInfo game_tab_info = 2;
-
-  // Details about an action to a specific game
-  optional PlayGamesDestinationAppGameAction game_action = 3;
-
-  // Details about actions inside the settings page
-  optional PlayGamesDestinationAppSettingsAction settings_action = 4;
-
-  // Details about the player tab if page_type == PLAYER_TAB
-  optional PlayGamesDestinationAppPlayerTabInfo player_tab_info = 5;
-
-  // Details about an action to a specific player
-  optional PlayGamesDestinationAppPlayerAction player_action = 6;
-
-  // Next index: 7
-}
-
-// Details about a leaderboard list view, top scores, or score window action
-message PlayGamesLeaderboardAction {
-
-  enum LeaderboardType {
-
-    // Unknown leaderboard type
-    UNKNOWN_LEADERBOARD_TYPE = 0;
-
-    // Public leaderboard
-    PUBLIC = 1;
-
-    // Social leaderboard
-    SOCIAL = 2;
-
-    // Next index = 3;
-  }
-
-  enum ScoreWindowType {
-
-    // Unknown score window type
-    UNKNOWN_SCORE_WINDOW = 0;
-
-    // The "daily" score window
-    DAILY = 1;
-
-    // The "weekly" score window
-    WEEKLY = 2;
-
-    // The "all time" score window
-    ALL_TIME = 3;
-
-    // Next index = 4;
-  }
-
-  // The leaderboard id this action is requesting
-  optional string leaderboard_id = 1;
-
-  // The type of the leaderboard
-  optional LeaderboardType leaderboard_type = 2;
-
-  // The score window type requested, if applicable
-  optional ScoreWindowType score_window_type = 3;
-
-  // Next index = 4;
-}
-
-// Details about a GPlus upgrade action
-message PlayGamesGPlusUpgrade {
-
-  enum GPlusUpgradeStatus {
-
-    // Unknown state
-    UNKNOWN_GPLUS_UPGRADE = 0;
-
-    // User accepted the G+ upgrade
-    ACCEPT = 1;
-
-    // User cancelled G+ upgrade
-    CANCEL = 2;
-
-    // Next index: 3
-  }
-
-  // Status of GPlus upgrade screen
-  optional GPlusUpgradeStatus state = 1;
-
-  // Next index: 2
-}
-
-// Details about the sign in account
-message PlayGamesSignInAccount {
-
-  enum AccountStatus {
-
-    // Unknown account status
-    UNKNOWN_ACCOUNT_STATUS = 0;
-
-    // User created a new account
-    NEW = 1;
-
-    // Proceeded passed the sign-in without account selector because user only
-    // has one account
-    PROCEED_NO_ACCOUNT_SELECTOR = 2;
-
-    // Proceeded passed the sign-in with account selector because user has
-    // multiple accounts
-    PROCEED_WITH_ACCOUNT_SELECTOR = 3;
-
-    // User canceled account sign-in
-    CANCEL = 4;
-
-    // Next index: 5
-  }
-
-  // The status of the account sign-in
-  optional AccountStatus status = 1;
-
-  // Next index: 2
-}
-
-// Details of an action taken inside a game
-message PlayGamesInGameAction {
-
-  enum GameActionType {
-
-    // Unknown action
-    UNKNOWN_GAME_ACTION = 0;
-
-    // User viewed the achievement list
-    ACHIEVEMENT_LIST = 1;
-
-    // User viewed the leaderboard list
-    LEADERBOARD_LIST = 2;
-
-    // User viewed a leaderboard top score
-    LEADERBOARD_TOP_SCORES = 3;
-
-    // User viewed a leaderboard score window
-    LEADERBOARD_SCORE_WINDOW = 4;
-
-    // User viewed game settings
-    SETTINGS = 5;
-
-    // User signed out of a game
-    SIGN_OUT = 6;
-
-    // User viewed the select opponents UI
-    SELECT_OPPONENTS = 7;
-
-    // User viewed the player search UI
-    PLAYER_SEARCH = 8;
-
-    // User viewed the waiting room UI
-    WAITING_ROOM = 9;
-
-    // User viewed the multiplayer inbox UI
-    MULTIPLAYER_INBOX = 10;
-
-    // User viewed the send request UI
-    SEND_REQUEST = 11;
-
-    // User viewed the request inbox UI
-    REQUEST_INBOX = 12;
-
-    // User viewed the public invitation list UI
-    PUBLIC_INVITATION_LIST = 13;
-
-    // User viewed the public request list UI
-    PUBLIC_REQUEST_LIST = 14;
-
-    // Next index: 15
-  }
-
-  // The action type
-  optional GameActionType type = 1;
-
-  // Leaderboard action, populated if one of the leaderboard game actions
-  // were taken by the user
-  optional PlayGamesLeaderboardAction leaderboard = 2;
-
-  // Next index: 3
-}
-
-// Details of a sign-in action
-message PlayGamesSignInAction {
-
-  enum SignInActionType {
-
-    // Unknown action
-    UNKNOWN_SIGN_IN_ACTION = 0;
-
-    // Games service connection attempt
-    // Sent whenever a game attempts to connect to the games service.
-    CONNECTION_START = 1;
-
-    // Sign in required
-    // Sent when a game was sent the SIGN_IN_REQUIRED result.
-    SIGN_IN_REQUIRED = 2;
-
-    // Connection success
-    // Sent when a game successfully connects to the games service.
-    CONNECTION_SUCCESS = 3;
-
-    // Next index: 4
-  }
-
-  // The account selector screen
-  optional PlayGamesSignInAccount account = 1;
-
-  // The G+ upgrade screen
-  optional PlayGamesGPlusUpgrade gplus_upgrade = 2;
-
-  // The type of action this event represents
-  optional SignInActionType type = 3;
-
-  // Next index: 4
-}
-
-// Details of a circle-modification action
-message PlayGamesModifyCirclesAction {
-
-  enum CircleActionSource {
-
-    // Unknown circle source
-    UNKNOWN = 0;
-
-    // Participant list
-    PARTICIPANT_LIST = 1;
-
-    // Recently played players
-    RECENTLY_PLAYED_PLAYERS = 2;
-
-    // Player search
-    PLAYER_SEARCH = 3;
-
-    // Player detail
-    PLAYER_DETAIL = 4;
-
-    // "You may know" list (player screen)
-    YOU_MAY_KNOW_LIST_PLAYERS = 5;
-
-    // "You may know" list (homescreen)
-    YOU_MAY_KNOW_LIST_HOMESCREEN = 6;
-
-    // Next index: 7
-  }
-
-  // The source of the modification action
-  optional CircleActionSource source = 1;
-
-  // Whether or not the player was added to circles
-  optional bool added = 2;
-
-  // Next index: 3
-}
-
-// Details about an Android sync action
-message PlayGamesAndroidSyncAction {
-
-  // The authority the sync was requested for.
-  optional string authority = 1;
-
-  // Which feed, if any, triggered this sync operation.
-  optional string feed = 2;
-
-  // The duration of the sync operation in milliseconds.
-  optional int64 duration_millis = 3;
-
-  // Whether or not this sync completed successfully.
-  optional bool success = 4;
-
-  // How many errors were encountered during this sync operations. Note that
-  // this may be 0 and still have the success flag set to false if the sync
-  // generated a non-recoverable error.
-  optional int32 num_errors = 5;
-
-  // Next index: 6
-}
-
-// Details about the request
-message PlayGamesRequestInfo {
-
-  // True if the action indicates the start of the request, false if the action
-  // indicates the end of the request.  This field is necessary only when we
-  // care about the latency of this action.  In order to accurately calculate
-  // latency, also include the start_timestamp_millis field below.
-  optional bool is_start_action = 1;
-
-  // The 3P application id making the request
-  optional string application_id = 2;
-
-  // The start timestamp that should be logged if we care about latency of this
-  // action.  Should only be logged if is_start_action = false. This should
-  // correspond to the PlaylogLogProto timestamp_millis field so that we can
-  // later Dremel the start and stop log events.
-  optional int64 start_timestamp_millis = 3;
-
-  // The instance ID of the application making the request. On Android, this
-  // will be a package name. On iOS, this will be the bundle identifier.
-  optional string instance_id = 4;
-
-  // Version of the client SDK that sent this request.
-  optional string client_version = 5;
-
-  // Next index: 6;
-}
-
-// A Play Games log event
-message PlayGamesLogEvent {
-
-  // General info about the request.  Every action should log this field.
-  optional PlayGamesRequestInfo request_info = 1;
-
-  // A user sign-in action
-  optional PlayGamesSignInAction sign_in = 2;
-
-  // An action that occurs within a game
-  optional PlayGamesInGameAction in_game = 3;
-
-  // An action that occurs within the games destination app
-  optional PlayGamesDestinationAppAction dest_app = 4;
-
-  // DEPRECATED(11/07/2013): action only sent by old clients. Instead use
-  // generic_notification.
-  optional PlayGamesNotificationActionDeprecated notification = 5;
-
-  // Notification action used by all clients
-  optional PlayGamesGenericNotificationAction generic_notification = 6;
-
-  // An iOS device registration/unregistration action
-  optional PlayGamesIosDeviceAction ios_action = 7;
-
-  // Action logged when modifying the state of the user's circles
-  optional PlayGamesModifyCirclesAction modify_circles = 8;
-
-  // Action logged when a device performs a sync
-  optional PlayGamesAndroidSyncAction sync = 9;
-
-  // Next index: 10
-}
diff --git a/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/play_store_client.proto b/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/play_store_client.proto
deleted file mode 100644
index 0942cef..0000000
--- a/PixelPerfect/imported_protos/src/wireless/android/play/playlog/proto/play_store_client.proto
+++ /dev/null
@@ -1,1171 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-// Authors: abednego@google.com (Igor Naverniouk)
-//          aurash@google.com (Aurash Mahbod)
-//          stadler@google.com (Andy Stadler)
-//          chstuder@google.com (Christoph Studer)
-//
-// Play Store logging protos.  This is sent as a field within
-// clientanalytics.proto.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-
-package wireless_android_play_playlog;
-
-option java_package = "com.google.wireless.android.play.playlog.proto";
-option java_outer_classname = "PlayStore";
-
-// Client-generated information that accompanies a PlayStoreUiElement.
-message PlayStoreUiElementInfo {
-  // For payment instrument related UI elements.
-  optional InstrumentInfo instrument_info = 1;
-
-  message InstrumentInfo {
-    // The instrument family as defined in InstrumentEnums.Family:
-    // wireless/android/finsky/proto/billing/device/common.proto
-    optional int32 instrument_family = 1;
-
-    // True if the payment instrument is marked as the default.
-    optional bool is_default = 2;
-  }
-
-  // Serialized finsky.Docid(e.g. "["MUSIC",2,2]"), for web front end only,
-  // that is associated with the node such as Page, DocList, or Document.
-  // This field is deprecated. Instead set the docid in server_logs_cookie.
-  optional string serial_docid = 2;
-
-  // Host name of server used for a WebViewChallenge.  Never the full URL.
-  optional string host = 3;
-
-  // The encoded docid for document specific UI elements that don't contain a
-  // server logs cookie. Only use this if it's impossible to use a server logs
-  // cookie.
-  //
-  // E.g. "inapp:potion:com.android.vending" or "book-012345678901".
-  //
-  // See java/com/google/wireless/android/finsky/util/DocidUtils.java for the
-  // encoding / decoding functions.
-  optional string document = 4;
-
-  // The Offer.Type for purchase related UI elements that don't contain a
-  // server logs cookie. Only use this if it's impossible to use a server logs
-  // cookie.
-  //
-  // Offer.Type defined here: wireless/android/finsky/proto/common.proto
-  optional int32 offer_type = 5;
-}
-
-// Something that can be displayed on a page and possibly clicked.
-// A DOM node, essentially, for interesting nodes.
-message PlayStoreUiElement {
-
-  // If you add a Type value, and you want elements of that type to be tracked
-  // as "clusters" in the playstats anaylitics pipeline, you *must* add
-  // [(is_cluster) = true] to the enum value definition.
-  // Next range available beyond: 1250
-  enum Type {
-    OTHER = 0;
-
-    // Top-level pages.
-    BROWSE_PAGE  = 1;
-    DETAILS_PAGE = 2;
-    SEARCH_PAGE  = 3;
-    // For someone else's people page
-    PEOPLE_PAGE= 4;
-    WISHLIST_PAGE = 5;
-    ANTENNA_PAGE = 6;
-    CREATOR_DETAILS_PAGE = 7;
-    FREE_SONG_OF_THE_DAY_PAGE = 8;
-    MY_APPS_PAGE = 9;
-    // For your own people page
-    MY_PEOPLE_PAGE = 10;
-    // Tag 11 available
-    SETTINGS_PAGE = 12;
-    AVAILABLE_PROMO_OFFER_ACTIVITY = 13;
-
-    // Links
-    CATEGORY_LINK = 100;  // Category links.
-    QUICK_LINK = 101;     // Links to other pages.
-    SEARCH_LINK = 102;
-    MY_APPS_LINK = 103;
-    MY_MUSIC_LINK = 104;
-    MY_MOVIES_AND_TV_LINK = 105;
-    MY_BOOKS_LINK = 106;
-    MY_MAGAZINES_LINK = 107;
-    MY_WISHLIST_LINK = 108;
-    REDEEM_LINK = 109;
-    ACCOUNTS_LINK = 110;
-    SETTINGS_LINK = 111;
-    HELP_LINK = 112;
-    BADGE_LINK = 113;
-    VISIT_DEV_SITE_LINK = 114;
-    SEND_DEV_EMAIL_LINK = 115;
-    DEVELOPER_PRIVACY_LINK = 116;
-    ARTIST_LINK = 117;
-    ARTIST_YOUTUBE_LINK = 118;
-    ARTIST_GOOGLEPLUS_LINK = 119;
-    PLAY_YOUTUBE_LINK = 120;
-    MY_NEWSSTAND_LINK = 121;
-    MY_MOVIES_LINK = 122;
-    MY_PEOPLE_PAGE_LINK = 123;
-
-    // Common UI elements.
-
-    PRICE_BUTTON = 200;
-    ACCEPT_AND_BUY_BUTTON = 201;
-    SHARE_BUTTON = 202;
-    // Button that takes you to the wishlist
-    WISHLIST_BUTTON = 203;
-    // Add an item to the wishlist
-    WISHLIST_ADD_ITEM_BUTTON = 204;
-    // Remove an item from the wishlist
-    WISHLIST_REMOVE_ITEM_BUTTON = 205;
-    // No longer sent from device starting from MintJulep.
-    // See tags 1200+ instead.
-    RATE_AND_REVIEW_BUTTON = 206;
-    FLAG_INAPPROPRIATE_BUTTON = 207;
-    PLUS_ONE_BUTTON = 208;
-    DETAILS_DOCUMENT = 209;
-    AUTO_UPDATE_STATE_BUTTON = 210;
-    SEASON_SELECTOR = 211;
-    // Dismiss a document (e.g. bad recommendation)
-    DISMISS_ITEM_BUTTON = 212;
-    LOADING_SPINNER = 213;
-    REFUND_BUTTON = 214;
-    UNINSTALL_BUTTON = 215;
-    DEACTIVATE_BUTTON = 216;
-    UPDATE_BUTTON = 217;
-    // This is any "open document" button, text is corpus-specific
-    // and may be "Open", "Play", "Listen", "Read", etc.
-    LAUNCH_BUTTON = 218;
-    CONTINUE_LAUNCH_BUTTON = 219;
-    ENABLE_BUTTON = 220;
-    INSTALL_BUTTON = 221;
-    TRY_BUTTON = 222;
-    FREE_BUTTON = 223;
-    DOWNLOAD_BUTTON = 224;
-    OPEN_FREE_BOOK_BUTTON = 225;
-    SUBSCRIBE_PRICE_BUTTON = 226;
-    UNSUBSCRIBE_BUTTON = 227;
-    RENT_SD_BUTTON = 228;
-    RENT_HD_BUTTON = 229;
-    RENT_FROM_BUTTON = 230;
-    BUY_SD_BUTTON = 231;
-    BUY_HD_BUTTON = 232;
-    BUY_FROM_BUTTON = 233;
-    PREORDER_BUTTON = 234;
-    PREORDER_CANCEL_BUTTON = 235;
-    // Used on the auto-update cleanup dialog when the user does not want
-    // to have their settings changed.
-    AUTO_UPDATE_CLEANUP_NOT_YET_BUTTON = 236;
-    // Used on the auto-update cleanup dialog when the user agrees to have
-    // all of their apps auto-updated.
-    AUTO_UPDATE_CLEANUP_OK_BUTTON = 237;
-    // A button that brings up an overflow menu (on a card)
-    OVERFLOW_MENU_BUTTON = 238;
-    // Buttons on details page.
-    INFO_BUTTON = 239;
-    SCREENSHOTS_BUTTON = 240;
-    TRAILER_BUTTON = 241;
-    // A specific active subscription, shown on a details page
-    ACTIVE_SUBSCRIPTION = 242;
-    // Confirm canceling a subscription
-    CANCEL_SUBSCRIPTION_YES = 243;
-    // Don't confirm canceling a subscription
-    CANCEL_SUBSCRIPTION_NO = 244;
-    // Confirm canceling a preorder
-    CANCEL_PREORDER_YES = 245;
-    // Don't confirm canceling a preorder
-    CANCEL_PREORDER_NO = 246;
-    // Clicked "continue" in GAIA recovery offer dialog
-    GAIA_RECOVERY_YES = 247;
-    // Exited GAIA recovery offer dialog
-    GAIA_RECOVERY_NO = 248;
-    // Container Filter selector (e.g. "For Tablets" / "All Apps")
-    CONTAINER_FILTER_SELECTOR = 249;
-    // OTA install dialog cancel / "No thanks" button
-    OTA_INSTALL_DIALOG_CANCEL_BUTTON = 250;
-    // OTA install dialog "Install" button
-    OTA_INSTALL_DIALOG_INSTALL_BUTTON = 251;
-    // Available promo offer
-    AVAILABLE_PROMO_OFFER_CHOSE = 252;
-    AVAILABLE_PROMO_OFFER_SKIP = 253;
-    // OK/Cancel buttons on Content Filter
-    CONTENT_FILTER_YES = 254;
-    CONTENT_FILTER_NO = 255;
-    // Details translation toggle
-    DETAILS_TRANSLATE_YES = 256;
-    DETAILS_TRANSLATE_NO = 257;
-    // PIN entry dialog
-    PIN_ENTRY_YES = 258;
-    PIN_ENTRY_NO = 259;
-    // 260-264 no longer sent from device starting with MintJulep. See tags
-    // 1200+ instead
-    RATE_REVIEW_YES = 260;
-    RATE_REVIEW_NO = 261;
-    RATE_REVIEW_CONFIRM_GPLUS_SIGNUP = 262;
-    RATE_REVIEW_CONFIRM_GPLUS_ACCEPTED = 263;
-    RATE_REVIEW_CONFIRM_GPLUS_NO = 264;
-    // Gaia authentication - succeed, fail, cancel
-    GAIA_AUTHENTICATION_YES = 265;
-    GAIA_AUTHENTICATION_NO = 266;
-    // WebView Challenge - succeed or fail. If a URL was clicked
-    // (typically containing the target pattern or the cancel pattern)
-    // then the host name part of the URL will be logged in the
-    // client cookie.
-    WEBVIEW_CHALLENGE_YES = 267;
-    WEBVIEW_CHALLENGE_NO = 268;
-    // Confirm Archive Docs dialog - OK or cancel
-    ARCHIVE_DOCS_YES = 269;
-    ARCHIVE_DOCS_NO = 270;
-    // Episode expansion toggle
-    EPISODE_EXPANSION_YES = 271;
-    EPISODE_EXPANSION_NO = 272;
-    SHARE_GPLUS = 273;
-    // Used when the user accepts the suggestion to install Play Games.
-    PLAY_GAMES_SUGGESTION_INSTALL_BUTTON = 274;
-    // Used when the user declines the suggestion to install Play Games.
-    PLAY_GAMES_SUGGESTION_NOT_NOW_BUTTON = 275;
-    UPDATE_ALL_BUTTON = 276;
-    // The user has switched the side drawer to display destinations
-    DRAWER_SWITCH_TO_DESTINATIONS = 277;
-    // The user has switched the side drawer to display accounts
-    DRAWER_SWITCH_TO_ACCOUNTS = 278;
-    // A clickable person avatar that leads that to that person's people page.
-    PERSON_AVATAR = 279;
-    // A circles button that invokes the circle picker.
-    CIRCLES_BUTTON = 280;
-    // A button that leads to a person's G+ profile in the G+ app
-    VIEW_GPLUS_PROFILE_BUTTON = 281;
-    // A slightly-hidden "self update" button
-    SELF_UPDATE_BUTTON = 282;
-
-    // Dialogs and overlays.
-    PASSWORD_PROMPT_DIALOG = 300;
-    FLAG_ITEM_DIALOG = 301;
-    // Refers to the dialog that shows more reviews of a doc
-    REVIEWS_DIALOG = 302;
-    WARM_WELCOME_DIALOG = 303;
-    CANCEL_SUBSCRIPTION_DIALOG = 304;
-    CANCEL_PREORDER_DIALOG = 305;
-    AUTO_UPDATE_CLEANUP_DIALOG = 306;
-    GAIA_RECOVERY_DIALOG = 307;
-    // This dialog is shown when a limited user is blocked from client
-    ACCESS_RESTRICTED_DIALOG = 308;
-    OTA_INSTALL_DIALOG = 309;
-    CHOOSE_ACCOUNT_DIALOG = 310;
-    PIN_ENTRY_DIALOG = 311;
-    // 312-313 no longer sent from client starting in Mintjulep. See tags 1200+
-    // instead.
-    RATE_REVIEW_DIALOG = 312;
-    RATE_REVIEW_CONFIRM_GPLUS_DIALOG = 313;
-    GAIA_AUTHENTICATION_DIALOG = 314;
-    CONTENT_FILTER_DIALOG = 315;
-    WEBVIEW_CHALLENGE = 316;
-    ARCHIVE_DOCS_DIALOG = 317;
-    // This dialog is shown to suggest that the user install Play Games.
-    PLAY_GAMES_SUGGESTION_DIALOG = 318;
-    // Dialog that shows the list of people that +1'ed a doc
-    PLUS_ONE_DIALOG = 319;
-
-    // Cluster types
-    // The generic cluster UI element that has child documents.  Cluster
-    // elements will be accompanied by a DOC_LIST server logs cookie.
-    // TODO: add enum values to classify all visual cluster types we are
-    // interested in.
-    UNCLASSIFIED_CLUSTER = 400;
-    // A tab containing categories.  Probably won't have a server cookie.
-    CATEGORIES_TAB = 401;
-    // A tab containing promo displays.
-    PROMO_TAB = 402;
-    // A tab containing regular contents.
-    CONTENTS_TAB = 403;
-    // A tab containg subscriptions (My Apps)
-    MY_APPS_SUBSCRIPTIONS_TAB = 404;
-    // A tab containing installed apps (My Apps)
-    MY_APPS_INSTALLED_TAB = 405;
-    // A tab containing library apps (My Apps)
-    MY_APPS_LIBRARY_TAB = 406;
-    // A merchandising cluster
-    MERCHANDISING_CLUSTER = 407;
-    // A generic type for the list response for a given tab. This will be
-    // the only child node under a PROMO_TAB or a CONTENTS_TAB.
-    DFE_LIST_TAB = 408;
-    // A cluster that is represented as a merchandized banner.
-    MERCH_BANNER_CLUSTER = 409;
-    // A cluster of people you may know to add to your circles
-    SUGGESTED_PEOPLE_CLUSTER = 410;
-    // A cluster for a trusted source that you can follow
-    TRUSTED_SOURCE_CLUSTER  = 411;
-    // A cluster that allows the user to rate multiple items
-    MULTI_RATE_CLUSTER = 412;
-    // A cluster that provides suggestions after rating a items
-    RATE_AND_QUICK_SUGGESTION_CLUSTER = 413;
-
-    // Card types
-    // The generic card UI element (applies to all cards shown on the screen).
-    // Card elements will be accompanied by a DOCUMENT server logs cookie.
-    // #500 is deprecated, please use a specific CARD_VIEW_ type (See below)
-    UNCLASSIFIED_CARD = 500;
-    // An app displayed in a list in MyApps
-    MY_APPS_LIST_CARD = 501;
-    // A song displayed in a list of songs
-    SONG_SNIPPET_CARD = 502;
-    // An episode displayed in a list of episodes
-    EPISODE_SNIPPET_CARD = 503;
-    // Variations on the "play card" size/shape
-    CARD_VIEW_ARTIST = 504;
-    CARD_VIEW_LARGE = 505;
-    CARD_VIEW_LISTING_SMALL = 506;
-    CARD_VIEW_MEDIUM = 507;
-    CARD_VIEW_MEDIUM_PLUS = 508;
-    CARD_VIEW_MINI = 509;
-    CARD_VIEW_SINGLE = 510;
-    CARD_VIEW_SMALL = 511;
-    CARD_VIEW_EDITORIAL_APP = 512;
-    CARD_VIEW_EDITORIAL_NON_APP = 513;
-    // Card that allows for the rating of an item
-    CARD_VIEW_RATE = 514;
-    // Card displaying a person and allows for the adding of that person
-    CARD_VIEW_PERSON = 515;
-
-    // System UI elements
-    SYSTEM_BACK_BUTTON = 600;
-    SYSTEM_TAP_OUTSIDE = 601;
-    SYSTEM_UP_BUTTON = 602;
-    // Indicates that the parent UI element (typically a dialog, screen, or
-    // activity) has been closed, caused by a user action or automatically.
-    SYSTEM_CLOSED = 603;
-
-    // Purchasing 700 - 899
-
-    // Purchase dialog
-    PURCHASE_DIALOG = 700;
-    PURCHASE_CART_SCREEN = 710;
-    PURCHASE_CART_BUY_BUTTON = 711;
-    PURCHASE_CART_CONTINUE_BUTTON = 712;
-    PURCHASE_CART_EXPANSION_TOGGLE = 713;
-    PURCHASE_CART_PAYMENT_OPTIONS_LINK = 714;
-    PURCHASE_CART_EXPANDED_DETAILS = 715;
-    PURCHASE_AUTH_SCREEN = 750;
-    PURCHASE_AUTH_CONFIRM_BUTTON = 751;
-    PURCHASE_AUTH_HELP_TOGGLE = 752;
-    PURCHASE_AUTH_OPT_OUT_CHECKBOX = 753;
-    PURCHASE_ERROR_SCREEN = 770;
-    PURCHASE_ERROR_OK_BUTTON = 771;
-    PURCHASE_SUCCESS_SCREEN = 775;
-
-    // Disambiguation
-    PURCHASE_DISAMBIGUATION_DIALOG = 780;
-    PURCHASE_DISAMBIGUATION_SCREEN = 781;
-    PURCHASE_DISAMBIGUATION_ENTRY = 782;
-
-    // Apps permissions
-    PURCHASE_APPS_PERMISSIONS_DIALOG = 790;
-    PURCHASE_APPS_PERMISSIONS_SCREEN = 791;
-    PURCHASE_APPS_PERMISSIONS_ACCEPT_BUTTON = 792;
-
-    // Billing profile / instrument switching
-    PURCHASE_PROFILE_DIALOG = 800;
-    PURCHASE_PROFILE_SCREEN = 801;
-    PURCHASE_PROFILE_EXISTING_INSTRUMENT = 802;
-    PURCHASE_PROFILE_ACTION_ADD_CREDIT_CARD = 810;
-    PURCHASE_PROFILE_ACTION_ADD_CARRIER_BILLING = 811;
-    PURCHASE_PROFILE_ACTION_REDEEM_CODE = 812;
-    PURCHASE_PROFILE_ACTION_TOP_UP = 813;
-
-    // DCB purchase flow
-    PURCHASE_DCB_PASSWORD_DIALOG = 820;
-    PURCHASE_DCB_PASSWORD_DIALOG_OK_BUTTON = 821;
-    PURCHASE_DCB_PASSWORD_DIALOG_CANCEL_BUTTON = 822;
-    PURCHASE_DCB_TOS_DIALOG = 823;
-    PURCHASE_DCB_TOS_DIALOG_ACCEPT_BUTTON = 824;
-    PURCHASE_DCB_TOS_DIALOG_DECLINE_BUTTON = 825;
-
-    // Setup DCB
-    PURCHASE_DCB2_SETUP_DIALOG = 840;
-    PURCHASE_DCB3_SETUP_DIALOG = 841;
-    //   Dialog shown while performing account association.
-    PURCHASE_DCB_ASSOCIATION_DIALOG = 842;
-    //   Screen showing the user's address and the carrier TOS footer.
-    PURCHASE_DCB_SETUP_TOS_SCREEN = 843;
-    //   Button allowing the user to edit the displayed address.
-    PURCHASE_DCB_SETUP_EDIT_ADDRESS_BUTTON = 844;
-    //   Address edit form.
-    PURCHASE_DCB_SETUP_EDIT_ADDRESS_SCREEN = 845;
-    //   Positive button on the address screen.
-    PURCHASE_DCB_SETUP_EDIT_ADDRESS_OK_BUTTON = 846;
-    //   Negative button on the address screen.
-    PURCHASE_DCB_SETUP_EDIT_ADDRESS_CANCEL_BUTTON = 847;
-    //   Positive button on the DCB setup screen.
-    PURCHASE_DCB_SETUP_ACCEPT_BUTTON = 848;
-    //   Negative button on the DCB setup screen.
-    PURCHASE_DCB_SETUP_DECLINE_BUTTON = 849;
-
-    // Add credit card
-    //   Hosts a PURCHASE_CC_SETUP_SCREEN.
-    PURCHASE_CC_SETUP_DIALOG = 860;
-    PURCHASE_CC_SETUP_SCREEN = 861;
-    PURCHASE_CC_SETUP_OK_BUTTON = 862;
-    PURCHASE_CC_SETUP_CANCEL_BUTTON = 863;
-    //   Impression logged when displaying an error message to the user.
-    PURCHASE_CC_SETUP_ERROR_DIALOG = 864;
-    //   Impression logged when displaying an error message to the user,
-    //   together with the choice of canceling the CC screen or editing the
-    //   entered info and retry.
-    PURCHASE_CC_SETUP_ERROR_DIALOG_WITH_CHOICE = 865;
-    // Impression logged when errors in the form are highlighted.
-    PURCHASE_CC_SETUP_INPUT_ERRORS = 866;
-
-    // Redeem code
-    //   Hosts the redeem code screen.
-    //   Reserved another range from 1100-1199
-    PURCHASE_REDEEM_CODE_DIALOG = 880;
-    //   The screen where the user enters the gift card / promo code.
-    PURCHASE_REDEEM_CODE_SCREEN = 881;
-    //   "Redeem" button on PURCHASE_REDEEM_CODE_SCREEN.
-    PURCHASE_REDEEM_CODE_BUTTON = 882;
-    //   Screen displaying what the user will get when they continue redemption.
-    PURCHASE_REDEEM_CONFIRMATION_SCREEN = 883;
-    //   "Add to library" button on PURCHASE_REDEEM_CONFIRMATION_SCREEN.
-    PURCHASE_REDEEM_CONFIRMATION_BUTTON = 884;
-    //   Screen showing a success message.
-    PURCHASE_REDEEM_SUCCESS_SCREEN = 885;
-    //   "Watch" / "Install", ..., button on PURCHASE_REDEEM_SUCCESS_SCREEN.
-    PURCHASE_REDEEM_SUCCESS_BUTTON = 886;
-    //   Dialog asking for the user's billing address when redeeming a monetary
-    //   promo code.
-    PURCHASE_REDEEM_ADDRESS_DIALOG = 887;
-    //   The Input text box on the redeem dialog where user enters the gift
-    //   card / promo code.
-    PURCHASE_REDEEM_CODE_INPUT = 888;
-    //   "Cancel" button on PURCHASE_REDEEM_CODE_SCREEN.
-    PURCHASE_REDEEM_CODE_CANCEL_BUTTON = 889;
-    //   Country selector menu on address dialog for new wallet account
-    //   creation.
-    PURCHASE_REDEEM_CODE_COUNTRY_MENU = 1101;
-    //   Name input box on address dialog for new wallet account creation.
-    PURCHASE_REDEEM_CODE_NAME_INPUT = 1102;
-    //   Zip code input box on address dialog for new wallet account creation.
-    PURCHASE_REDEEM_CODE_ZIP_INPUT = 1103;
-    //   1100 id is available
-
-    // Setup Wizard
-    //   Asks the user to add a credit card.
-    SETUP_AVAILABLE_PROMO_OFFER_ACTIVITY = 890;
-    //   Hosts a PURCHASE_CC_SETUP_SCREEN.
-    SETUP_WIZARD_CC_ACTIVITY = 891;
-
-    // Notifications
-    //   Notification shown when there are new updates available. Shown only for
-    //   users with auto-update disabled.
-    NOTIFICATION_NEW_UPDATES = 900;
-    //   Notification shown when an app has just been succesfully installed.
-    NOTIFICATION_SUCCESSFULLY_INSTALLED = 901;
-    //   Notification shown when an app(s) just been successfully updated.
-    NOTIFICATION_SUCCESSFULLY_UPDATED = 902;
-    //   Notifcation shown when the user has outstanding updates and has not
-    //   received any new update notifications for a given time interval
-    //   (e.g. 3 days)
-    NOTIFICATION_OUTSTANDING_UPDATES = 903;
-    //   Notification shown when the user receives new updates that require
-    //   approval. Shown only for users with auto-update enabled.
-    NOTIFICATION_NEW_UPDATES_NEED_APPROVAL = 904;
-
-    // Prompt for FOP / Burnsie
-    //   The dialog shown asking the user to review their account.
-    PROMPT_FOR_FOP_DIALOG = 1000;
-    //   The main activity taking the user through FOP setup.
-    PROMPT_FOR_FOP_ACTIVITY = 1001;
-    //   The main screen on the activity with choices to set up a FOP.
-    PROMPT_FOR_FOP_SCREEN = 1002;
-    //   Message screen shown when the user already has a FOP.
-    PROMPT_FOR_FOP_EXISTING_FOP_SCREEN = 1003;
-    //   Message screen shown when /billingProfile failed.
-    PROMPT_FOR_FOP_ERROR_SCREEN = 1004;
-    //   Success screen shown when the user added a FOP.
-    PROMPT_FOR_FOP_SUCCESS_SCREEN = 1005;
-    //   Continue button at the bottom of the screen.
-    PROMPT_FOR_FOP_CONTINUE_BUTTON = 1006;
-    //   On PROMPT_FOR_FOP_SCREEN, a toggle that expands/collapses the "More"
-    //   section.
-    PROMPT_FOR_FOP_MORE_TOGGLER = 1007;
-    //   The "None" choice on the PROMPT_FOR_FOP_SCREEN. Visual representation
-    //   varies by UI mode controlled by experiment.
-    PROMPT_FOR_FOP_NONE_ENTRY = 1008;
-    //   "More details" button at the bottom right, leading to
-    //    PROMPT_FOR_FOP_MORE_DETAILS_DIALOG
-    PROMPT_FOR_FOP_MORE_DETAILS_BUTTON = 1009;
-    //    A dialog shown when the user clicked
-    //    PROMPT_FOR_FOP_MORE_DETAILS_BUTTON.
-    PROMPT_FOR_FOP_MORE_DETAILS_DIALOG = 1010;
-
-    // Ratings and reviews
-    //   Rate/review section on details page
-    RATE_REVIEW_SECTION = 1200;
-    //   Rating bar on details page that launches the review dialog for a new
-    //   review
-    RATE_REVIEW_SECTION_RATING_BAR = 1201;
-    //   Review edit button on details page that launches the review dialog to
-    //   edit a previous review
-    RATE_REVIEW_SECTION_EDIT_BUTTON = 1202;
-    //   Review dialog launched from the details page (Redesigned in MJ)
-    RATE_REVIEW_DIALOG_V2 = 1203;
-    //   Submit button in review dialog to submit a new review
-    RATE_REVIEW_DIALOG_SUBMIT_BUTTON = 1204;
-    //   Save button in review dialog to save edits to an existing review
-    RATE_REVIEW_DIALOG_SAVE_BUTTON = 1205;
-    //   Delete button in review dialog to delete an existing review
-    RATE_REVIEW_DIALOG_DELETE_BUTTON = 1206;
-    //   Cancel action (e.g. back button or tap outside dialog) in review dialog
-    RATE_REVIEW_DIALOG_CANCEL = 1207;
-    //   Rating bar on a card (e.g. Quick Suggestions cluster)
-    RATE_REVIEW_CARD_RATING_BAR = 1208;
-  }
-
-  optional Type type = 1 [default = OTHER];
-
-  // A serialized play_store_server.proto:PlaylogStoreNodeDescriptor proto.
-  // Note: It is serialized because forcing the Android client to parse it would
-  // lose proto fields that that client version doesn't know about.
-  optional bytes server_logs_cookie = 2;
-
-  // Client can annotate UI elements with arbitrary info.
-  optional PlayStoreUiElementInfo client_logs_cookie = 3;
-
-  repeated PlayStoreUiElement child = 4;
-}
-
-message PlayStoreImpressionEvent {
-  // The DOM tree of the displayed content.
-  optional PlayStoreUiElement tree = 1;
-
-  // Descriptor path to the node on the previous screen that caused this
-  // impression. Each element on the path must have zero children.
-  // UI elements are in reversed order, i.e. from leaf to root.
-  repeated PlayStoreUiElement referrer_path = 2;
-
-  // Id identifies a full playstore impression within a user session. Any
-  // impressions sharing the same id will be deduped in the post session
-  // analysis. If the id is not set, the impression is considered unique.
-  optional int64 id = 3;
-}
-
-message PlayStoreClickEvent {
-  // The full path to the clicked UI element on the screen it was displayed on.
-  // Each element on the path must have zero children.
-  // UI elements are in reversed order, i.e. from leaf to root.
-  repeated PlayStoreUiElement element_path = 1;
-}
-
-message PlayStoreSearchEvent {
-  // Query text for the search event.
-  optional string query = 1;
-
-  // Query URL for the search event
-  optional string query_url = 2;
-
-  // Referrer URL (if known, e.g. from a deeplink)
-  optional string referrer_url = 3;
-}
-
-// Deep link event is logged when the external deep link is resolved
-// successfully by the client. The resolved link types are based on the DFE
-// response defined in wireless/android/finsky/proto/dfe/resolve_link.proto,
-// except for LAUNCH_DEEP_LINK which is generated locally when a deep link
-// intent is received.
-message PlayStoreDeepLinkEvent {
-  enum ResolvedType {
-    OTHER = 0;
-    // Deep link resolved to a document details link.
-    DETAILS = 1;
-    // Deep link resolved to a browse link.
-    BROWSE = 2;
-    // Deep link resolved to a search link.
-    SEARCH = 3;
-    // Deep link resolved to a direct purchase.
-    DIRECT_PURCHASE = 4;
-    // Deep link resolved to Home home.
-    HOME_HOME = 5;
-    // Deep link resolved to Gift card redemption.
-    REDEEM_GIFTCARD = 6;
-    // Generated immediately by the intent handler activity.
-    // Additional fields package, min_version, new_enough, and can_resolve
-    // will be set for this type.
-    LAUNCH_DEEP_LINK = 7;
-  }
-  // The external url receive in the android intent that is sent to the DFE to
-  // resolve.
-  optional string external_url = 1;
-  // The resolved link type from DFE for the external_url.
-  optional ResolvedType resolved_type = 2 [default = OTHER];
-
-  // The package name (set for LAUNCH_DEEP_LINK)
-  optional string package_name = 3;
-  // The requested minimum version (set for LAUNCH_DEEP_LINK)
-  optional int32 min_version = 4;
-  // True if the existing version meets the min version requirement
-  // (set for LAUNCH_DEEP_LINK)
-  optional bool new_enough = 5;
-  // True if the url could be resolved (set for LAUNCH_DEEP_LINK)
-  optional bool can_resolve = 6;
-
-  // A serialized play_store_server.proto:PlaylogStoreNodeDescriptor proto.
-  // See PlayStoreUiElement.server_logs_cookie for details.
-  optional bytes server_logs_cookie = 7;
-}
-
-message PlayStoreBackgroundActionEvent {
-  enum Type {
-    // Housekeeping, etc.
-    OTHER = 0;
-    SESSION_INFO = 1;
-    NLP_REPAIR_STATUS = 2;
-
-    // Download, Install, and Restore-related events
-    DOWNLOAD_QUEUED = 100;
-    DOWNLOAD_START = 101;
-    DOWNLOAD_COMPLETE = 102;
-    DOWNLOAD_CANCEL = 103;
-    DOWNLOAD_ERROR = 104;
-    INSTALL_REQUEST = 105;
-    INSTALL_START = 106;
-    INSTALL_START_ENCRYPTED = 107;
-    INSTALL_APPLY_PATCH = 108;
-    INSTALL_ACTIVATE = 109;
-    INSTALL_FINISHED = 110;
-    INSTALL_ERROR = 111;
-    INSTALL_ABANDONED = 112;
-    RESTORE_SKIP = 113;
-    UNINSTALL = 114;
-    // Auto update is attempted for a user on auto update over wifi only.
-    // Data stored in wifi_auto_update_attempt.
-    WIFI_AUTO_UPDATE_ATTEMPT = 115;
-    // Auto-Acquire is being attempted as part of a "forcefood" condition.
-    // We log two events;  One is sent to the "source" (currently owning)
-    // account and one is sent to the "dest" (acquiring) account.  Both
-    // log messages will include the package name and old (installed) and
-    // new (offered) version codes.
-    AUTO_ACQUIRE_PACKAGE_SOURCE = 116;
-    AUTO_ACQUIRE_PACKAGE_DEST = 117;
-    // App restore begins with the fetch of data (list of apps) to be restored
-    // for a given account.  Log the completion of the fetch, error code, and
-    // number of attempts.  The error codes can be any of the codes defined at
-    // https://sites.google.com/a/google.com/universal-store/documentation
-    //     /android-client/download-error-codes
-    RESTORE_FETCH_APP_LIST = 118;
-    // Report the result of a self-update check
-    // app_data will contain the old (currently installed) version, and the new
-    // version if the server provided one. exception_type will be set if there
-    // was an error during the RPC.
-    SELF_UPDATE_CHECK = 119;
-    // Report success/failure of this endpoint call.  We log it because it is
-    // in the self-update path, so failures here are 'interesting'.  If there
-    // is an error during the RPC, exception_type will be set.
-    DEVICE_CONFIGURATION_UPLOAD = 120;
-
-    // Tickles
-    TICKLE_PURCHASE_DECLINED = 200;
-    TICKLE_PACKAGE_INSTALL = 201;
-    TICKLE_PACKAGE_REMOVE = 202;
-
-    // Purchase
-    //
-    // Note that network errors and unexpected server crashes will be reflected
-    // in 'exception_type'. Expected server errors (invalid auth tokens,
-    // declined purchases, etc.) will be reflected inside server_logs_cookie.
-
-    //   Free purchase (for free docs not requiring Checkout).
-    //
-    //   These events are logged when the document is added to the user's
-    //   library. This usually happens only once per document and user (unless
-    //   ownership is revoked).
-    //   Specifically, for free apps, these events are triggered only before the
-    //   very first install by a user, and only if the installation was
-    //   initiated from the device.
-    //
-    //     Sending request to /purchase
-    PURCHASE_FREE_ACQUIRE = 300;
-    //     Received response from /purchase
-    //     Includes server_logs_cookie
-    PURCHASE_FREE_ACQUIRED = 301;
-    //   Paid purchase (for paid docs and free docs requiring Checkout)
-    //
-    //   These events are logged as the user progresses through a paid purchase.
-    //   This usually happens only once per document and user (unless ownership
-    //   is revoked).
-    //   Specifically, for paid apps, these events are logged only before the
-    //   very first install by a user, and only if the purchase is being
-    //   performed on the device.
-    //
-    //     Sending request to /preparePurchase
-    PURCHASE_PREPARE = 302;
-    //     Received response from /preparePurchase
-    //     Includes server_logs_cookie
-    PURCHASE_PREPARED = 303;
-    //     Sending request to /commitPurchase
-    //     Includes server_logs_cookie
-    PURCHASE_COMMIT = 304;
-    //     Received response from /commitPurchase
-    //     Includes server_logs_cookie
-    PURCHASE_COMMITTED = 305;
-
-    //   Instrument setup
-    //
-    //   Note that 320-323 are logged from billing profile when the user
-    //   returned from a successful instrument flow. For the "true" background
-    //   events logged when the instrument is added (also during
-    //   Setup Wizard), see events starting at 330.
-    //     The user added a credit card.
-    PURCHASE_BILLING_PROFILE_CREDIT_CARD_ADDED = 320;
-    //     The user set up a DCB instrument.
-    PURCHASE_BILLING_PROFILE_CARRIER_BILLING_ADDED = 321;
-    //     The user redeemed a gift card / promo code.
-    PURCHASE_BILLING_PROFILE_CODE_REDEEMED = 322;
-    //     Play credit purchased (top-up flow finished).
-    PURCHASE_BILLING_PROFILE_PLAY_CREDIT_PURCHASED = 323;
-
-    //     Sending request to /updateInstrument.
-    PURCHASE_CC_ADDING = 330;
-    //     Received success response from /updateInstrument.
-    PURCHASE_CC_ADD_SUCCESS = 331;
-    //    Request to /updateInstrument failed.
-    //
-    //    error_code:
-    //      0: Unknown
-    //      1: Invalid auth token
-    //      2: Volley error during escrowing
-    //      3: Volley error during saving
-    //      4: Invalid input
-    //      5: Error message
-    //
-    PURCHASE_CC_ADD_ERROR = 332;
-
-    //     Sending request to /updateInstrument.
-    PURCHASE_DCB2_ADDING = 335;
-    //     Received success response from /updateInstrument.
-    PURCHASE_DCB2_ADD_SUCCESS = 336;
-    //    Request to /updateInstrument failed.
-    //
-    //    error_code:
-    //      0: Unknown
-    //      1: Volley error
-    //      2: Invalid input
-    //      3: Error message
-    PURCHASE_DCB2_ADD_ERROR = 337;
-
-    //     Sending request to /updateInstrument.
-    PURCHASE_DCB3_ADDING = 340;
-    //     Received success response from /updateInstrument.
-    PURCHASE_DCB3_ADD_SUCCESS = 341;
-    //    Request to /updateInstrument failed.
-    //
-    //    error_code:
-    //      0: Unknown
-    //      1: Volley error
-    //      2: Invalid input
-    //      3: Error message
-    PURCHASE_DCB3_ADD_ERROR = 342;
-
-    //   Prompt for FOP / Burnsie
-    //
-    //     The user added a credit card.
-    PURCHASE_PROMPT_FOR_FOP_CREDIT_CARD_ADDED = 350;
-    //     The user set up a DCB instrument.
-    PURCHASE_PROMPT_FOR_FOP_CARRIER_BILLING_ADDED = 351;
-    //     The user redeemed a gift card / promo code.
-    PURCHASE_PROMPT_FOR_FOP_CODE_REDEEMED = 352;
-    //     Play credit purchased (top-up flow finished).
-    //     This is entirely unexpected, as we would exit the flow if the user
-    //     already has an instrument, and top-up requires an instrument.
-    PURCHASE_PROMPT_FOR_FOP_PLAY_CREDIT_PURCHASED = 353;
-    //     The user picked the "None" choice, snoozing the "Prompt for FOP"
-    //     flow.
-    PURCHASE_PROMPT_FOR_FOP_SNOOZED = 354;
-    //     We entered the "Prompt for FOP" flow and then recognized the user
-    //     already has a FOP.
-    PURCHASE_PROMPT_FOR_FOP_ALREADY_SETUP = 355;
-    //     We failed to fetch /billingProfile.
-    PURCHASE_PROMPT_FOR_FOP_BILLING_PROFILE_ERROR = 356;
-
-    //   Settings changes
-    SETTINGS_PASSWORD_RESTRICT = 400;
-    SETTINGS_CONTENT_FILTER = 401;
-    SETTINGS_AUTO_UPDATE_GLOBAL = 402;
-    SETTINGS_AUTO_UPDATE_APP = 403;
-    // Auto-update migration code is running.
-    // No "before" or "after" setting values are written here.
-    // Reason string indicates "version" for pre-jellybean update;
-    // "cleanup" for user-initated cleanup.
-    SETTINGS_AUTO_UPDATE_MIGRATED = 404;
-    // #405 is retired (was SETTINGS_AUTO_UPDATE_DIALOG_ANSWERED)
-    // The user switched accounts. No before/after values.
-    SETTINGS_SWITCH_ACCOUNT = 406;
-
-    // Misc. background events that are the direct result of user action
-    // but are decoupled from the "click: that got there
-
-    // Result of redeeming a promo offer (AVAILABLE_PROMO_OFFER_ACTIVITY)
-    // If redeemed, operation_success will be set to 'true'
-    AVAILABLE_PROMO_OFFER_REDEEMED = 500;
-    // Result of entering a content PIN (PIN_ENTRY_DIALOG)
-    // If successful, operation_success will be set to 'true'
-    PIN_ENTRY_RESULT = 501;
-    // Result of GAIA authentication attempt (GAIA_AUTHENTICATION_DIALOG)
-    // If successful, operation_success will be set to 'true'
-    GAIA_AUTHENTICATION_RESULT = 502;
-    // Successful G+ signup. Operation_success will be set to 'true'.
-    GPLUS_SIGNED_UP = 503;
-    // A WebViewChallenge URL was insecure (not https: or data:)
-    // Hostname (not complete URI) will be in "host"
-    WEBVIEW_CHALLENGE_NON_HTTPS = 504;
-    // User clicked "update all" and we log one message per package
-    // (package name in "document" field)
-    UPDATE_ALL = 505;
-    // User archived documents, and we log one message per doc
-    // (package name in "document" field)
-    REMOVE_FROM_HISTORY = 506;
-    // Widget tracking (enabled, disabled, options, deleted)
-    // See widget_event_data for details.
-    WIDGET_EVENT = 507;
-    // Result of light challenge auth attempt (PURCHASE_AUTH_SCREEN)
-    // If successful, operation_success will be set to 'true'
-    PURCHASE_AUTH_RESULT = 508;
-    // This is used to collect statistics about how often we fetch a
-    // 2nd document (for social details) during views of an app details
-    // page.  The "document" field will indicate the package, and the
-    // "operation_success" field will be 'true' for double-fetch, 'false'
-    // for a normal (single-fetch) condition.
-    DETAILS_2ND_DOCUMENT_FETCH = 509;
-    // Search suggestions have been offered. This event will include
-    // a message in search_suggestion, which includes items such as the
-    // query and the client-observed latency.
-    SEARCH_SUGGESTIONS_OFFERED = 510;
-    // A search suggestion has been clicked. This event will include
-    // a message in search_suggestion, which includes items such as the
-    // query and the client-observed latency.
-    SEARCH_SUGGESTION_CLICKED = 511;
-
-    // An acquisition flow was initiated. This event is logged whenever
-    // the user acquires a free or paid item, or goes through an app
-    // installation flow.
-    //
-    //   document: ID of the document that is being acquired / installed.
-    //   offer_type: The offer to acquire. Only set if known upfront.
-    //   offer_checkout_flow_required: Whether the offer requires a Checkout
-    //       flow. Note that this flag being true doesn't mean that the user
-    //       actually went through a purchase screen. For example, users will
-    //       go through an installation flow without purchase screen when they
-    //       install a paid app they already own, which would still have
-    //       offer_checkout_flow_required=true.
-    // TODO(chstuder): Add flags for each screen shown during the flow.
-    ACQUISITION_FLOW_STARTED = 600;
-    // An acquisition flow was finished. This is logged when an acquisition flow
-    // marked via ACQUISITION_FLOW_INITIATED has finished.
-    //
-    // The following fields will be set:
-    //   document: ID of the document that was acquired / installed.
-    //   offer_type: Offer type that was acquired.
-    //   offer_checkout_flow_required: Whether the offer required a Checkout
-    //       flow. See ACQUISITION_FLOW_STARTED for details.
-    //   operation_success: 'true' if the acquisition was completed,
-    //       'false' otherwise.
-    ACQUISITION_FLOW_FINISHED = 601;
-  }
-  optional Type type = 1 [default = OTHER];
-
-  // Additional parameters used by some events
-
-  // Flattened Docid (e.g. package name) of document in the event
-  optional string document = 2;
-
-  // An internal (engineering/debug) annotation of the event.
-  optional string reason = 3;
-
-  // Error code (HTTP status & other client-internal codes) for error events
-  // For more details, see:
-  // https://sites.google.com/a/google.com/universal-store/documentation/android-client/download-error-codes
-  optional int32 error_code = 4;
-
-  // The name of the Java exception that was thrown.
-  // Used to communicate client exceptions, network errors and server 500s.
-  optional string exception_type = 5;
-
-  // The server_logs_cookie as received from the server
-  // See PlayStoreUiElement.server_logs_cookie for details.
-  optional bytes server_logs_cookie = 6;
-
-  // Purchase related
-  // The offer type purchased (as ordinal value of finsky.OfferType.Id), see
-  // google3/wireless/android/finsky/proto/common.proto.
-  // Might be redundant with data in server_logs_cookie, but we won't always
-  // have a token.
-  optional int32 offer_type = 7;
-
-  // For a settings change, an int capturing what the setting changed from.
-  // The interpretation of this integer will depend on the type.
-  optional int32 from_setting = 8;
-
-  // For a settings change, an int capturing what the setting changed to.
-  // The interpretation of this integer will depend on the type.
-  optional int32 to_setting = 9;
-
-  // When a session is initiated, upload all out-of-band session data about
-  // the client's current state.
-  optional PlayStoreSessionData session_info = 10;
-
-  // App data for app-related background events.
-  optional AppData app_data = 11;
-
-  // For DFE request background events, the server latency as reported via
-  // ResponseWrapper.server_metadata.latency_millis.
-  optional int64 server_latency_ms = 12;
-
-  // For network request background events, the client observed latency.
-  optional int64 client_latency_ms = 13;
-
-  // For type=NLP_REPAIR_STATUS, more details
-  optional NlpRepairStatus nlp_repair_status = 14;
-
-  // For success/fail reports (e.g. password auth check) a simple true/false
-  optional bool operation_success = 15;
-
-  // Host name of server used for a WebViewChallenge.  Never the full URL.
-  optional string host = 16;
-
-  // For type WIDGET_EVENT, data describing the event.
-  optional WidgetEventData widget_event_data = 17;
-
-  // For type WIFI_AUTO_UPDATE_ATTEMPT, data describing the event.
-  optional WifiAutoUpdateAttempt wifi_auto_update_attempt = 18;
-
-  // For events that involve retries, a place to note the number of attempts
-  optional int32 attempts = 19;
-
-  // For acquisition / purchase related operations, whether
-  // Offer.checkout_flow_required was 'true' or 'false'.
-  optional bool offer_checkout_flow_required = 20;
-
-  // For search suggestion events, additional data about the
-  // query, latency, etc.
-  optional SearchSuggestionReport search_suggestion_report = 21;
-}
-
-message PlayStoreLogEvent {
-  // At most one of the following fields should be filled in.
-  // Note: tag id 2 can be reused.
-
-  // A tree of UI elements displayed on the screen.
-  optional PlayStoreImpressionEvent impression = 1;
-
-  // An explicit action taken by the user (click, tap, or swipe).
-  optional PlayStoreClickEvent click = 3;
-
-  // A background action that is interesting enough to be logged, but is not a
-  // direct result of an impression or a click.
-  optional PlayStoreBackgroundActionEvent background_action = 4;
-
-  // A search action performed by the user.
-  optional PlayStoreSearchEvent search = 5;
-
-  // A deep link event that resolved successfully.
-  optional PlayStoreDeepLinkEvent deep_link = 6;
-}
-
-message PlayStoreSessionData {
-  // True if the global auto-update setting is enabled on the client.
-  optional bool global_auto_update_enabled = 1;
-
-  // True if the auto-update over wifi only setting is enabled on the client.
-  optional bool global_auto_update_over_wifi_only = 2;
-
-  // Number of times the user has been shown the auto-update migration dialog.
-  optional int32 auto_update_cleanup_dialog_num_times_shown = 3;
-
-  // The network type at the time this event was logged (as provided by
-  // the SDK). See Android ConnectivityManager.TYPE_* for values.
-  // http://developer.android.com/reference/android/net/ConnectivityManager.html
-  optional int32 network_type = 4;
-
-  // The network subtype at the time this event was logged (as provided by
-  // the SDK). See Android TelephonyManager.NETWORK_TYPE_* for values.
-  // http://developer.android.com/reference/android/telephony/TelephonyManager.html
-  optional int32 network_sub_type = 5;
-
-  // The number of active accounts on the device.
-  optional int32 num_accounts_on_device = 6;
-
-  // The number of apps that are installed on the device.
-  optional int32 num_installed_apps = 7;
-
-  // The number of installed apps that have auto-update enabled on the device.
-  optional int32 num_auto_updating_installed_apps = 8;
-
-  // The number of installed apps that have auto-update disabled on the device.
-  optional int32 num_installed_apps_not_auto_updating = 9;
-
-  // True if gaia password auth is opted out.
-  optional bool gaia_password_auth_opted_out = 10;
-
-  // The current content filter level
-  optional int32 content_filter_level = 11;
-
-  // True if the user has "allow unknown sources" checked
-  optional bool allow_unknown_sources = 12;
-
-  // "Prompt for FOP" (Burnsie) data
-  optional PromptForFopData prompt_for_fop_data = 13;
-}
-
-// This message is added to a PlayStoreBackgroundActionEvent for search
-// suggestions (displayed or clicked).
-message SearchSuggestionReport {
-  // The query as entered by the user.
-  optional string query = 1;
-
-  // The query as rewritten by the suggestion
-  optional string suggested_query = 2;
-
-  // The client-observed latency.
-  optional int64 client_latency_ms = 3;
-}
-
-// This message will be emitted (in a background event) by code that handles
-// Nlp repairs.
-message NlpRepairStatus {
-  enum RepairStatus {
-    UNKNOWN = 0;
-    // The NLP has been found and appears to be functional.
-    PROVIDER_FOUND = 1;
-    // The NLP is not working, but all other prerequisites are
-    // satisfied, and a fix should be applied
-    PROVIDER_NEEDS_REPAIR = 2;
-    // The NLP is not working, but we are in a holdoff state
-    // so no repair will be attempted.
-    PROVIDER_REPAIR_HOLDOFF = 3;
-    // The device is running the wrong SDK version
-    WRONG_SDK_VERSION = 4;
-    // The NLP package was not found
-    PACKAGE_NOT_FOUND = 5;
-    // The NLP package has unexpected package flags
-    WRONG_FLAGS = 6;
-    // The NLP package has the wrong version #
-    WRONG_VERSION = 7;
-    // The NLP package has the wrong signature
-    WRONG_SIGNATURE = 8;
-    // The NLP package is disabled
-    PACKAGE_DISABLED = 9;
-  }
-  optional RepairStatus repair_status = 1 [default = UNKNOWN];
-
-  // The package flags of the currently-installed NLP (if found)
-  optional int32 flags = 2;
-
-  // The version code of the currently-installed NLP (if found)
-  optional int32 version_code = 3;
-
-  // The signature hash of the currently-installed NLP (if incorrect)
-  optional string signature_hash = 4;
-
-  // Set to true if test-keys version was found (not set for user builds)
-  optional bool found_test_keys = 5;
-
-  // Set to true if we are blocked from retry until next boot
-  optional bool holdoff_until_boot = 6;
-
-  // Set to true if we are blocked from retry until data wipe
-  optional bool holdoff_until_wipe = 7;
-
-  // Set to true if we have successfully installed the fixer
-  optional bool holdoff_after_install = 8;
-
-  // The package-enabled bits for the currently-installed NLP
-  optional int32 enabled = 9;
-}
-
-message AppData {
-  // The app version of the event.
-  optional int32 version = 1;
-
-  // For installations, the version currently installed on the device.
-  //
-  // Presence of this field means that this event is about an app update.
-  optional int32 old_version = 2;
-
-  // True if the currently installed version is a system app.
-  optional bool system_app = 3;
-}
-
-// Data to help track usage and changes to widgets
-message WidgetEventData {
-  // The various widget classes (map to Java classes)
-  enum WidgetClassId {
-    UNKNOWN_WIDGET = 0;
-    MARKET_WIDGET = 1;
-    RECOMMENDED_WIDGET = 2;
-    NOWPLAYING_WIDGET = 3;
-  }
-  // Java class receiving the widget event
-  optional WidgetClassId class_id = 1;
-
-  // The intent action
-  enum IntentActionId {
-    UNKNOWN_ACTION = 0;
-    ENABLED = 1;
-    DISABLED = 2;
-    UPDATE_OPTIONS = 3;
-    DELETED = 4;
-  }
-  // The intent action received
-  optional IntentActionId intent_action_id = 2;
-
-  // Number of widgets
-  optional int32 num_widgets = 3;
-
-  // The remaining fields are sent only with APPWIDGET_UPDATE_OPTIONS
-
-  // Widget type (all, apps, books, movies, music, magazines)
-  // These id's will be the same as the values in Common.Backend
-  // Or -1 if the string type could not be matched
-  optional int32 backendId = 4;
-
-  // Min & Max dimensions
-  optional int32 min_width = 5;
-  optional int32 min_height = 6;
-  optional int32 max_width = 7;
-  optional int32 max_height = 8;
-}
-
-// Data describing a wifi auto update attempt.
-message WifiAutoUpdateAttempt {
-
-  // True if auto update succeeded. False if auto update failed because wifi
-  // connecitivty was not available.
-  optional bool auto_update_success = 1;
-
-  // The number of consecutive failed attempts that have occured since the
-  // first failed attempt. Is 1 on first fail.
-  optional int32 num_failed_attempts = 2;
-
-  // Time passed since first failed attempt. Is 0 on first fail.
-  optional int64 time_since_first_fail_ms = 3;
-
-  // Time interval of wifi checks
-  optional int64 wifi_check_interval_ms = 4;
-}
-
-// Stats about "Prompt for FOP" (Burnsie)
-message PromptForFopData {
-  // Whether the user is considered to have a FOP
-  // (as determined via DFE /checkInstrument)
-  optional bool has_fop = 1;
-  // Whether the user added a FOP via Burnsie flow.
-  optional bool fop_added = 2;
-  // Number of times the "primer" dialog has been shown.
-  optional int32 num_dialog_shown = 3;
-  // Number of times the actual "Complete your account" screen was shown.
-  optional int32 num_fop_selector_shown = 4;
-  // Number of times the user snoozed the Burnsie flow.
-  optional int32 num_snooze = 5;
-}
diff --git a/PixelPerfect/libs/pixelperfect-api.jar b/PixelPerfect/libs/pixelperfect-api.jar
new file mode 100644
index 0000000..8981cf0
--- /dev/null
+++ b/PixelPerfect/libs/pixelperfect-api.jar
Binary files differ
diff --git a/PixelPerfect/platform/AndroidManifest.xml b/PixelPerfect/platform/AndroidManifest.xml
deleted file mode 100644
index 338cb93..0000000
--- a/PixelPerfect/platform/AndroidManifest.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.google.android.apps.pixelperfect.platform"
-    android:versionCode="1"
-    android:versionName="1.0" >
-    <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <uses-sdk
-        android:minSdkVersion="18"
-        android:targetSdkVersion="19" />
-    <application
-        android:allowBackup="true"
-        android:icon="@drawable/ic_cat"
-        android:label="@string/platform_app_name" >
-        <service
-            android:name=".PixelPerfectPlatform"
-            class=".PixelPerfectPlatform"
-            android:enabled="true"
-            android:exported="true" >
-            <intent-filter>
-                <action android:name="com.google.android.apps.pixelperfect.api.IPixelPerfectPlatform" />
-            </intent-filter>
-        </service>
-    </application>
-</manifest>
diff --git a/PixelPerfect/platform/tests/Android.mk b/PixelPerfect/platform/tests/Android.mk
deleted file mode 100644
index f94095d..0000000
--- a/PixelPerfect/platform/tests/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
-LOCAL_CERTIFICATE := platform
-
-# Include all test java files.
-LOCAL_SRC_FILES := \
-        $(call all-java-files-under, ../../tests/src/com/google/android/apps/pixelperfect/api) \
-        $(call all-java-files-under, ../../tests/src/com/google/android/apps/pixelperfect/platform)
-
-LOCAL_PACKAGE_NAME := PixelPerfectPlatformTests
-
-LOCAL_INSTRUMENTATION_FOR := PixelPerfectPlatform
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/PixelPerfect/platform/tests/AndroidManifest.xml b/PixelPerfect/platform/tests/AndroidManifest.xml
deleted file mode 100644
index e5c60ec..0000000
--- a/PixelPerfect/platform/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.google.android.apps.pixelperfect.platform.tests">
-
-    <!-- We add an application tag here just so that we can indicate that
-         this package needs to link against the android.test library,
-         which is needed when building test cases. -->
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <!--
-    This declares that this app uses the instrumentation test runner targeting
-    the package of com.example.android.apis.  To run the tests use the command:
-    "adb shell am instrument -w com.example.android.apis.tests/android.test.InstrumentationTestRunner"
-    -->
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
-                     android:targetPackage="com.google.android.apps.pixelperfect.platform"
-                     android:label="Tests for PixelPerfectPlatform."/>
-
-</manifest>
-
diff --git a/PixelPerfect/scripts/eclipse_setup.py b/PixelPerfect/scripts/eclipse_setup.py
index cee2364..31c992d 100755
--- a/PixelPerfect/scripts/eclipse_setup.py
+++ b/PixelPerfect/scripts/eclipse_setup.py
@@ -24,7 +24,7 @@
 
 def main(args):
   parser = optparse.OptionParser()
-  parser.set_defaults(projects=('pixelperfect','pixelperfect-test','gcore-fp'))
+  parser.set_defaults(projects=('pixelperfect-platform','pixelperfect-platform-test'))
   parser.add_option('--platform_src',
                     help='Location of the android platform source tree')
 
@@ -44,7 +44,7 @@
   else:
     output_dir = check_path("%s/../eclipse" % android_root, "eclipse folder",
         True)
-  output_dir = check_path(("%s/%s") % (output_dir, "pixelperfect"),
+  output_dir = check_path(("%s/%s") % (output_dir, "pixelperfect/platform"),
       "project subdirectory", True)
   project_root = check_path("%s/.." % scripts_dir, "project root")
   print "project_files_dir: %s" % project_files_dir
diff --git a/PixelPerfect/scripts/import_protos.py b/PixelPerfect/scripts/import_protos.py
deleted file mode 100755
index 2e14289..0000000
--- a/PixelPerfect/scripts/import_protos.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/python
-#
-# Imports protos for PixelPerfect and fixes them to work with Android's
-# proto compiler.
-#
-# Adapted from google3/wireless/voicesearch/tools/update_sidekick_proto.py
-
-import os
-import re
-import sys
-
-base_google3_path = "/home/build/google3/"
-files = [
-    "net/proto2/bridge/proto/message_set.proto",
-    "wireless/android/play/playlog/proto/clientanalytics.proto",
-    "wireless/android/play/playlog/proto/personal_application_event.proto",
-    "wireless/android/play/playlog/proto/personal_recorder.proto",
-    "wireless/android/play/playlog/proto/play_games_client.proto",
-    "wireless/android/play/playlog/proto/play_store_client.proto"
-]
-
-# Substitutions are applied in sequence, so later substitutions see effects of
-# earlier ones. This is leveraged to gracefully handle the 'default' options.
-substitutions = [
-    # Remove the field option declaration.
-    ('extend proto2.FieldOptions {[^}]*}', ''),
-    ('extend proto2.EnumValueOptions {[^}]*}', ''),
-
-    # Remove options and imports that aren't applicable or supported.
-    ('option java_api_version = 2;\n', ''),
-    ('option py_api_version = 2;\n', ''),
-    ('option cc_api_version = 2;\n', ''),
-    ('option java_generate_equals_and_hash = true;\n', ''),
-    ('option java_enable_dual_generate_mutable_api = true;\n', ''),
-    ('import "java/com/google/apps/jspb/jspb.proto";\n', ''),
-    ('import "logs/proto/logs_annotations/logs_annotations.proto";\n', ''),
-    ('import "net/proto2/proto/descriptor.proto";\n', ''),
-
-    # Remove the message-level logs_proto options.
-    ('^\s*option \(logs_proto\.\w*\) = \w*;', ''),
-
-    # Leave only default options; temporarily replace []'s with <<</>>>'s.
-    ('\[[^]]*?default = ([^]\s,]+)[^]]*\]', '<<<\\1>>>'),
-
-    # Leave bracketed expressions in comments alone.
-    ('(^\s*//[^\n]*)\[', '\\1{{{'),
-
-    # Zap anything between []'s.
-    ('\[[^]]*?\]', ''),
-
-    # Restore the []'s around default options for the fields.
-    ('<<<(.*?)>>>', '[default = \\1]'),
-
-    # Restore [ in comments.
-    ('{{{', '['),
-
-    # Add option optimize_for = LITE_RUNTIME
-    ('(syntax = "proto2";\n)', '\\1\noption optimize_for = LITE_RUNTIME;\n'),
-
-    # Zap unnecessary whitespace (including newlines). This will sometimes cause
-    # lines to become longer than 80 characters, but this is deemed an
-    # acceptable style violation since fixing this properly requires more time
-    # investment than the payoffs justify.
-    ('([0-9])\s+;', '\\1;'),
-    ('([0-9])\s+\[', '\\1 ['),
-
-    # Zap trailing whitespace.
-    (' +$', ''),
-
-    # Chomp consecutive newlines.
-    ('\n\n\n+', '\n\n')
-]
-
-def update_proto(in_file_path, out_file_path):
-  in_file = file(in_file_path)
-  proto_source = in_file.read()
-  in_file.close()
-
-  for pattern, replacement in substitutions:
-    regex = re.compile(pattern, re.MULTILINE | re.DOTALL)
-    proto_source = regex.sub(replacement, proto_source)
-
-  out_file = file(out_file_path, 'w')
-  out_file.write(proto_source)
-  out_file.close()
-
-def main(args):
-  script_path = os.path.realpath(sys.argv[0])
-  scripts_dir = os.path.dirname(script_path)
-
-  for f in files:
-    in_file_path = "%s%s" % (base_google3_path, f)
-    out_file_path = os.path.realpath(
-        "%s/../imported_protos/src/%s" % (scripts_dir, f))
-    update_proto(in_file_path, out_file_path)
-    print "processed %s" % f
-
-if __name__ == '__main__':
-  sys.exit(main(sys.argv[1:]))
diff --git a/PixelPerfect/scripts/makepp b/PixelPerfect/scripts/makepp
index 4945ef5..c296c92 100755
--- a/PixelPerfect/scripts/makepp
+++ b/PixelPerfect/scripts/makepp
@@ -34,48 +34,24 @@
   echo "  t = test" >&2
   echo "  T = uninstall tests" >&2
   echo "  u = adb uninstall (before install)" >&2
-  echo "  m = make mockito" >&2
+  echo "  m = make dependencies" >&2
   echo "  c = clean" >&2
   exit 0
 fi
 
-# Convert TARGET_PRODUCT to TARGET_DEVICE. If a product isn't listed below,
-# you can add the associated device for it from this list of devices:
-# https://sites.google.com/a/google.com/android/development/codebook
-product=$TARGET_PRODUCT
-
-if [[ $product == hammerhead ]]; then
-  device=hammerhead
-elif [[ $product == occam ]]; then
-  device=mako
-elif [[ $product == nakasi ]]; then
-  device=grouper
-elif [[ $product == nakasig ]]; then
-  device=tilapia
-elif [[ $product == razor ]]; then
-  device=flo
-elif [[ $product == razorg ]]; then
-  device=deb
-elif [[ $product == mantaray ]]; then
-  device=manta
-else
-  echo "Unknown product:"$product
-  exit 1;
-fi
-
 build=
 install=
 uninstall=
 runtests=
 uninstall_tests=
-make_mockito=
+make_dependencies=
 clean=
 
 # Explode the command line params in case they are all jammed together in
 # one parameter.
 
 [[ $* =~ c ]] && clean=1 && echo Clean
-[[ $* =~ m ]] && make_mockito=1 && echo Making mockito
+[[ $* =~ m ]] && make_dependencies=1 && echo Making dependencies
 [[ $* =~ b ]] && build=1 && echo Building
 [[ $* =~ u ]] && uninstall=1 && echo Uninstalling
 [[ $* =~ T ]] && uninstall_tests=1 && echo Uninstall Tests
@@ -88,16 +64,13 @@
   rm -rf out/target/common/obj/APPS/PixelPerfect*;
   rm -rf out/target/common/obj/JAVA_LIBRARIES/*pixelperfect*
   rm -rf out/target/product/*/data/app/PixelPerfect*"
-[[ -n "$make_mockito" ]] && make mockito-target
+[[ -n "$make_dependencies" ]] && mmm external/protobuf:libprotobuf-java-2.3.0-lite &&
+  mmma vendor/unbundled_google/packages/PrebuiltGmsCore &&
+  make mockito-target &&
+  make android-support-test
 [[ -n "$build" ]] && mmm packages/experimental/PixelPerfect
-[[ -n "$uninstall" ]] && bash -xc "
-  adb uninstall com.google.android.apps.pixelperfect;
-  adb uninstall com.google.android.apps.pixelperfect.platform;"
-[[ -n "$uninstall_tests" ]] && bash -xc "
-  adb uninstall com.google.android.apps.pixelperfect.tests;
-  adb uninstall com.google.android.apps.pixelperfect.platform.tests;"
-[[ -n "$install" ]] && bash -xc "
-  adb install -r out/target/product/$device/system/app/PixelPerfect.apk;
-  adb install -r out/target/product/$device/system/app/PixelPerfectPlatform.apk;"
+[[ -n "$uninstall" ]] && bash -xc "adb uninstall com.google.android.apps.pixelperfect.platform"
+[[ -n "$uninstall_tests" ]] && bash -xc "adb uninstall com.google.android.apps.pixelperfect.platform.tests"
+[[ -n "$install" ]] && bash -xc "adb install -r out/target/product/generic/system/app/PixelPerfectPlatform.apk"
 [[ -n "$runtests" ]] && runtest --path packages/experimental/PixelPerfect
 
diff --git a/PixelPerfect/src/com/google/android/apps/pixelperfect/AccessibilityEventProcessor.java b/PixelPerfect/src/com/google/android/apps/pixelperfect/AccessibilityEventProcessor.java
deleted file mode 100644
index 644a6fe..0000000
--- a/PixelPerfect/src/com/google/android/apps/pixelperfect/AccessibilityEventProcessor.java
+++ /dev/null
@@ -1,444 +0,0 @@
-package com.google.android.apps.pixelperfect;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.os.RemoteException;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-
-import com.google.android.gms.playlog.PlayLogger;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.logging.RecordedEvent.RecordedRect;
-import com.google.common.logging.RecordedEvent.RecordedTypes.WidgetType;
-import com.google.common.logging.RecordedEvent.RecordedUpdate;
-import com.google.common.logging.RecordedEvent.RecordedUpdate.Type;
-import com.google.common.logging.RecordedEvent.Screenshot;
-import com.google.common.logging.RecordedEvent.UIElement;
-import com.google.protobuf.CodedOutputStream;
-import com.google.wireless.android.play.playlog.proto.ClientAnalytics;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.annotation.Nullable;
-
-/**
- * Processes {@link AccessibilityEvent}s:
- * <ul>
- *   <li> Filters out events that should not be published in Clearcut.
- *   <li> Publishes the surviving events.
- * </ul>
- *
- * <p>This class is state-less and thread safe. It is used as a singleton, because it is
- * instantiated only in one place, namely AccessibilityEventService, which itself is a singleton.
- */
-public class AccessibilityEventProcessor {
-
-    private static final String TAG = "PixelPerfect.AccessibilityEventProcessor";
-
-    /** Version for the recorded updates .*/
-    // TODO(stlafon): We should be using something like "android:major.minor".
-    private static final String VERSION = "0.1";
-
-    /** Maps the name of a widget to its enum type. */
-    private static final Map<String, WidgetType> widgetTypeMap = getWidgetTypeMap();
-
-    /**
-     * Wrapper around {@link PlayLogger}. Unlike the latter, it's not final, so it can be mocked.
-     */
-    public static class ClearcutLogger {
-
-        private final PlayLogger mPlayLogger;
-
-        ClearcutLogger(Context context, int logSource, String accountName,
-                @Nullable PlayLogger.LoggerCallbacks loggerCallbacks) {
-            mPlayLogger = new PlayLogger(
-                    context,
-                    logSource,
-                    accountName,
-                    loggerCallbacks);
-        }
-
-        public void start() {
-            mPlayLogger.start();
-        }
-
-        public void logEvent(byte[] bytes) {
-            mPlayLogger.logEvent(null, bytes);
-        }
-    }
-
-    /**
-     * Maps an {@link AccessibilityEvent} type (integer value) to a {@link RecordedUpdate}'s
-     * {@link Type}.
-     */
-    private static final SparseArray<RecordedUpdate.Type> eventTypeMapping =
-            getEventTypeConversionArray();
-
-    /** The packages excluded for which no data is collected. */
-    private final ExcludedPackages mExcludedPackages;
-
-    /** Clearcut Logger for recording events. */
-    private final ClearcutLogger mLogger;
-
-    /** The type of the last AccessibilityEvent we received */
-    private int mLastEventType = -1;
-
-    /** The UIElement corresponding to the last AccessibilityEvent we received. */
-    private UIElement mLastElement = UIElement.newBuilder().build();
-
-    /** Client for communicating with PixelPerfectPlatform service, e.g., for screenshots.*/
-    private PlatformServiceClient mPlatformServiceClient;
-
-    public AccessibilityEventProcessor(Context context, String accountName,
-            ExcludedPackages excludedPackages,
-            @Nullable PlatformServiceClient platformServiceClient,
-            @Nullable PlayLogger.LoggerCallbacks loggerCallbacks) {
-        this(excludedPackages, platformServiceClient, new ClearcutLogger(
-                context,
-                ClientAnalytics.LogRequest.LogSource.PERSONAL_LOGGER.getNumber(),
-                accountName, loggerCallbacks));
-    }
-
-    @VisibleForTesting
-    AccessibilityEventProcessor(
-            ExcludedPackages excludedPackages,
-            @Nullable PlatformServiceClient platformServiceClient,
-            ClearcutLogger logger) {
-        mExcludedPackages = excludedPackages;
-        mPlatformServiceClient = platformServiceClient;
-        mLogger = logger;
-        mLogger.start();
-    }
-
-    /**
-     * Obtains a screenshot by calling the platform service.
-     * @return captured screenshot proto. {@code null} if screenshot was not captured.
-     */
-    @Nullable
-    private Screenshot obtainScreenshot() {
-        if (mPlatformServiceClient != null) {
-            try {
-               return mPlatformServiceClient.obtainScreenshot();
-            } catch (SecurityException e) {
-                // TODO(mukarram) Should we catch this or let the app crash?
-                Log.e(TAG, "SecurityException while obtaining screenshot. " + e);
-            } catch (IllegalStateException e) {
-                Log.e(TAG, "mPlatformServiceClient is not ready. " + e);
-            } catch (RemoteException e) {
-                Log.e(TAG, "RemoteException: ", e);
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Processes an {@link AccessibilityEvent}.
-     *
-     * @param event {@link AccessibilityEvent} to process
-     */
-    public void process(AccessibilityEvent event) {
-        Screenshot screenshot = obtainScreenshot();
-        if (excludeEvent(event)) {
-            return;
-        }
-
-        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
-            publishWindowChanged(event, screenshot);
-        } else {
-            publishSingleEvent(event, screenshot);
-        }
-        mLastEventType = event.getEventType();
-    }
-
-    /**
-     * Returns whether the {@link AccessibilityEvent} should be excluded.
-     *
-     * @param event the {@link AccessibilityEvent}
-     * @return true if the event should be excluded
-     */
-    private boolean excludeEvent(AccessibilityEvent event) {
-        if (mExcludedPackages.isExcluded(event.getPackageName().toString())) {
-            Log.v(TAG, "Excluding package " + event.getPackageName());
-            return true;
-        }
-        // Filter out text selections - see comment in publishWindowChanged().
-        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED) {
-            return true;
-        }
-        // Note, we could also filter based on field name, e.g. 'isPassword' etc...
-        return false;
-    }
-
-    /**
-     * Creates and returns a {@link RecordedUpdate}.
-     *
-     * @param event the {@link AccessibilityEvent}
-     * @param element {@UIElement} in which to fill the update.
-     * @return the {@link RecordedUpdate} or null if the event type is unknown.
-     */
-    private RecordedUpdate createUpdate(AccessibilityEvent event, UIElement element) {
-        // Get the {@code RecordedUpdate}'s type.
-        Type eventType = eventTypeMapping.get(event.getEventType());
-
-        if (eventType == null) {
-            Log.v(TAG, "Not logging unknown event with type = " + event.getEventType());
-            return null;
-        }
-
-        Log.v(TAG, "RecordedUpdate with " + event.getEventType() + " --> " + eventType);
-
-        RecordedUpdate.Builder updateBuilder = RecordedUpdate.newBuilder()
-                .setType(eventType)
-                .setElement(element)
-                .setVersion(VERSION);
-
-        if (event.getPackageName() != null) {
-            updateBuilder.setPackageName(event.getPackageName().toString());
-        }
-
-        return updateBuilder.build();
-    }
-
-    /**
-     * Publishes an event that's not a change of window content. This is typically an interaction
-     * with a given widget.
-     *
-     * @param event the {@link AccessibilityEvent} to publish
-     * @param screenshot the {@link Screenshot} to go with this event.
-     */
-    private void publishSingleEvent(
-            AccessibilityEvent event,
-            @Nullable Screenshot screenshot) {
-        AccessibilityNodeInfo node = event.getSource();
-        if (node == null) {
-            return;
-        }
-        RecordedUpdate update = createUpdate(event, createUIElement(node, screenshot, false));
-        if (update != null) {
-            publishUpdate(update);
-        }
-        node.recycle();
-    }
-
-    /**
-     * Publishes an {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}.
-     *
-     * @param event the {@link AccessibilityEvent} to publish
-     * @param screenshot the {@link Screenshot} to go with this event.
-     */
-    private void publishWindowChanged(
-            AccessibilityEvent event,
-            @Nullable Screenshot screenshot) {
-        AccessibilityNodeInfo node = event.getSource();
-        if (node == null) {
-            return;
-        }
-        AccessibilityNodeInfo parent = node;
-        while (parent.getParent() != null) {
-            parent = parent.getParent();
-        }
-        UIElement newElement = createUIElement(parent, screenshot, true);
-        // TODO(stlafon, mukarram) Verify that .equals() is a deep comparison.
-        if (!newElement.equals(mLastElement)) {
-            // We get window-changed events following on from a text changed event. We
-            // don't want to process every one of these, so skip printing if the last
-            // event was a text change. Note that we strip selection_change events -
-            // sometimes we get these after a text change and sometimes we don't.
-            if (mLastEventType != AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED) {
-                RecordedUpdate update = createUpdate(event, newElement);
-                if (update != null) {
-                    publishUpdate(update);
-                }
-            }
-            mLastElement = newElement;
-        }
-        node.recycle();
-    }
-
-    /**
-     * Publishes a {@link RecordedUpdate} to Clearcut.
-     *
-     * @param update the {@link RecordedUpdate} to publish
-     */
-    private void publishUpdate(RecordedUpdate update) {
-        printUIElement("", update.getElement());
-
-        // Publish to Clearcut.
-        byte[] buffer = new byte[update.getSerializedSize()];
-        CodedOutputStream outputStream = CodedOutputStream.newInstance(buffer);
-        try {
-            update.writeTo(outputStream);
-            mLogger.logEvent(buffer);
-            Log.v(TAG, "Wrote " + buffer.length + " bytes in Clearcut.");
-        } catch (IOException e) {
-            Log.e(TAG, "Failed to write update of type " + update.getType() + " : " + e);
-        }
-    }
-
-    /**
-     * Returns true if the content of the {@link AccessibilityNodeInfo} should
-     * be elided. This is desirable for sensitive UIElements, such as passwords.
-     *
-     * Note: this function is mostly heuristics; there is no guarantee that this
-     * removes all sensitive information.
-     *
-     * @param node the input {@link AccessibilityNodeInfo}
-     * @return true if content should be elided.
-     */
-    @VisibleForTesting
-    boolean shouldElideContent(AccessibilityNodeInfo node) {
-        // for now, only thing we check for is whether the node is a password node.
-        return node.isPassword();
-    }
-
-    /**
-     * Creates a {@link UIElement} message from an {@link AccessibilityNodeInfo}. Creates child
-     * nodes if {@code andChildren} is true. Note that many of the fields in
-     * {@link AccessibilityNodeInfo} can be null, so check before we set them.
-     *
-     * @param node the input {@link AccessibilityNodeInfo}
-     * @param screenshot the {@link Screenshot} to go with this element.
-     * @param createChildren whether to create child nodes
-     * @return the {@link UIElement}
-     */
-    @VisibleForTesting
-    UIElement createUIElement(
-            AccessibilityNodeInfo node,
-            @Nullable Screenshot screenshot,
-            boolean createChildren) {
-        UIElement.Builder elementBuilder = UIElement.newBuilder();
-        if (widgetTypeMap.containsKey(node.getClassName())) {
-            elementBuilder.setClassType(widgetTypeMap.get(node.getClassName()));
-        } else {
-            elementBuilder.setClassName(node.getClassName().toString());
-        }
-        // Note, getViewIdResourceName() requires API level 18.
-        if (node.getViewIdResourceName() != null) {
-            elementBuilder.setResourceName(node.getViewIdResourceName());
-        }
-        if (node.getContentDescription() != null) {
-            elementBuilder.setDescription(node.getContentDescription().toString());
-        }
-
-        final boolean elideContent = shouldElideContent(node);
-
-        if (elideContent) {
-            elementBuilder.setContentElided(true);
-        }
-
-        if (node.getText() != null && !elideContent) {
-            elementBuilder.setContent(node.getText().toString());
-        }
-
-        if (screenshot != null) {
-            elementBuilder.setScreenshot(screenshot);
-        }
-
-        Rect rect = new Rect();
-        node.getBoundsInParent(rect);
-        RecordedRect recordedRect = RecordedRect.newBuilder()
-                .setBottom(rect.bottom)
-                .setLeft(rect.left)
-                .setRight(rect.right)
-                .setTop(rect.top)
-                .build();
-        elementBuilder.setRect(recordedRect);
-        if (createChildren) {
-            int numChildren = node.getChildCount();
-            for (int i = 0; i < numChildren; i++) {
-                AccessibilityNodeInfo child = node.getChild(i);
-                if (child != null) {
-                    // Currently, we set the screenshot only on the root
-                    // UIElement object, hence passing null to the children.
-                    elementBuilder.addChild(createUIElement(child, null, true));
-                    child.recycle();
-                } else {
-                    // Create an empty element to represent the null child
-                    elementBuilder.addChild(UIElement.newBuilder().build());
-                }
-            }
-        }
-        return elementBuilder.build();
-    }
-
-    /** Prints a {@link UIElement} in the logcat. */
-    private void printUIElement(String indent, UIElement node) {
-        String className = (node.getClassType() == WidgetType.CUSTOM
-                ? node.getClassName() : "" + node.getClassType());
-        Log.v(TAG, indent + className + " (" + node.getResourceName() + ") "
-                + node.getDescription()
-                // Do not print if content is null
-                + (node.getContent() == null ? "" : " = " + node.getContent())
-                // If content was elided print that it was elided so that
-                // the reader is not confused.
-                + (node.getContentElided() ? "<Content Elided>" : "")
-                // If the node has screenshot, then print the size in bytes.
-                + (node.hasScreenshot() ? "Screenshot size (bytes): " + node.getScreenshot().getSerializedSize() : ""));
-        for (UIElement child : node.getChildList()) {
-            printUIElement(indent + "  ", child);
-        }
-    }
-
-    /**
-     * Creates and returns a {@link Map} from a widget to its enum type.
-     */
-    private static Map<String, WidgetType> getWidgetTypeMap() {
-        Map<String, WidgetType> map = new HashMap<String, WidgetType>();
-
-        map.put("android.appwidget.AppWidgetHostView", WidgetType.APP_WIDGET_HOST_VIEW);
-        map.put("android.view.View", WidgetType.VIEW);
-        map.put("android.webkit.WebView", WidgetType.WEB_VIEW);
-        map.put("android.widget.Button", WidgetType.BUTTON);
-        map.put("android.widget.CheckBox", WidgetType.CHECK_BOX);
-        map.put("android.widget.CheckedTextView", WidgetType.CHECKED_TEXT_VIEW);
-        map.put("android.widget.EditText", WidgetType.EDIT_TEXT);
-        map.put("android.widget.FrameLayout", WidgetType.FRAME_LAYOUT);
-        map.put("android.widget.HorizontalScrollView",
-                WidgetType.HORIZONTAL_SCROLL_VIEW);
-        map.put("android.widget.ImageButton", WidgetType.IMAGE_BUTTON);
-        map.put("android.widget.ImageView", WidgetType.IMAGE_VIEW);
-        map.put("android.widget.LinearLayout", WidgetType.LINEAR_LAYOUT);
-        map.put("android.widget.ListView", WidgetType.LIST_VIEW);
-        map.put("android.widget.MultiAutoCompleteTextView",
-                WidgetType.MULTI_AUTO_COMPLETE_TEXT_VIEW);
-        map.put("android.widget.ProgressBar", WidgetType.PROGRESS_BAR);
-        map.put("android.widget.RelativeLayout", WidgetType.RELATIVE_LAYOUT);
-        map.put("android.widget.ScrollView", WidgetType.SCROLL_VIEW);
-        map.put("android.widget.Spinner", WidgetType.SPINNER);
-        map.put("android.widget.Switch", WidgetType.SWITCH);
-        map.put("android.widget.TabHost", WidgetType.TAB_HOST);
-        map.put("android.widget.TabWidget", WidgetType.TAB_WIDGET);
-        map.put("android.widget.TextView", WidgetType.TEXT_VIEW);
-        map.put("android.widget.ViewSwitcher", WidgetType.VIEW_SWITCHER);
-
-        return map;
-    }
-
-    /**
-     * Creates and returns a {@link SparseArray} from {@link AccessibilityEvent}'s event types to
-     * {@link RecordedUpdate}'s {@link Type}.
-     */
-    private static SparseArray<Type> getEventTypeConversionArray() {
-        SparseArray<Type> sparseArray = new SparseArray<Type>();
-
-        sparseArray.put(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED,
-                Type.TYPE_NOTIFICATION_STATE_CHANGED);
-        sparseArray.put(AccessibilityEvent.TYPE_VIEW_CLICKED, Type.TYPE_VIEW_CLICKED);
-        sparseArray.put(AccessibilityEvent.TYPE_VIEW_FOCUSED, Type.TYPE_VIEW_FOCUSED);
-        sparseArray.put(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED, Type.TYPE_VIEW_LONG_CLICKED);
-        sparseArray.put(AccessibilityEvent.TYPE_VIEW_SCROLLED, Type.TYPE_VIEW_SCROLLED);
-        sparseArray.put(AccessibilityEvent.TYPE_VIEW_SELECTED, Type.TYPE_VIEW_SELECTED);
-        sparseArray.put(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED, Type.TYPE_VIEW_TEXT_CHANGED);
-        sparseArray.put(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED,
-                Type.TYPE_VIEW_TEXT_SELECTION_CHANGED);
-        sparseArray.put(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
-                Type.TYPE_WINDOW_CONTENT_CHANGED);
-
-        return sparseArray;
-    }
-
-}
diff --git a/PixelPerfect/src/com/google/android/apps/pixelperfect/AccessibilityEventService.java b/PixelPerfect/src/com/google/android/apps/pixelperfect/AccessibilityEventService.java
deleted file mode 100644
index 187839c..0000000
--- a/PixelPerfect/src/com/google/android/apps/pixelperfect/AccessibilityEventService.java
+++ /dev/null
@@ -1,326 +0,0 @@
-package com.google.android.apps.pixelperfect;
-
-import com.google.android.apps.pixelperfect.util.RealClock;
-import com.google.android.apps.pixelperfect.preferences.PreferencesActivity;
-import com.google.android.gms.playlog.PlayLogger;
-
-import android.accessibilityservice.AccessibilityService;
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Intent;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.Toast;
-import android.util.Log;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Sets;
-
-import java.util.Locale;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
-/**
- * Listens to {@link AccessibilityEvent}s triggered when there's a state
- * transition in the UI.
- */
-public class AccessibilityEventService extends AccessibilityService
-        implements PlayLogger.LoggerCallbacks {
-
-    private static final String TAG = "PixelPerfect.AccessibilityEventService";
-
-    /** Action for pausing the recording. */
-    @VisibleForTesting
-    static final String ACTION_PAUSE = "com.google.android.apps.pixelperfect.PAUSE";
-
-    /** Action for resuming the recording. */
-    @VisibleForTesting
-    static final String ACTION_RESUME = "com.google.android.apps.pixelperfect.RESUME";
-
-    /** The unique id for the sticky notification. */
-    private static final int NOTIFICATION_ID = 0;
-
-    /**
-     * If true, then we don't record anything (screenshots, accessibility events...). This allows
-     * users to go enter the incognito mode.
-     */
-    private static boolean sIsPaused;
-
-    /** A {@link Toast} shown when the service is paused or resumed. */
-    private static Toast sToast;
-
-    /**
-     * The event processor. If the device doesn't have a Google corp account,
-     * then this variable will be {@code null}, and no publishing in Clearcut
-     * will occur.
-     */
-    private AccessibilityEventProcessor mProcessor;
-
-    /** The excluded packages. */
-    private ExcludedPackages mExcludedPackages;
-
-    /** Used to create the sticky notification. */
-    private NotificationManager mNotificationManager;
-
-    /** Client for PixelPerfectPlatform service.*/
-    private PlatformServiceClient mPlatformServiceClient;
-
-    /**
-     * Whitelist of usernames allowed to use the app. Should be kept sorted alphabetically.
-     * This list is a snapshot of users in the pixel-perfect@google.com group.
-     * TODO(dprothro): enforce this constraint using gservices and a google group.
-     */
-    private static final Set<String> USERNAME_WHITELIST = Sets.newHashSet(
-            "aayushkumar@google.com",
-            "ababu@google.com",
-            "abednego@google.com",
-            "adzic@google.com",
-            "agoyal@google.com",
-            "alasdair@google.com",
-            "alpha@google.com",
-            "andys@google.com",
-            "aoun@google.com",
-            "aparnacd@google.com",
-            "bhorling@google.com",
-            "chsnow@google.com",
-            "davidmonsees@google.com",
-            "dbailey@google.com",
-            "divye@google.com",
-            "djmarcin@google.com",
-            "dmauro@google.com",
-            "dprothro@google.com",
-            "dramage@google.com",
-            "ertoz@google.com",
-            "etaropa@google.com",
-            "girirao@google.com",
-            "levesque@google.com",
-            "lynnc@google.com",
-            "maureen@google.com",
-            "meliss@google.com",
-            "mukarram@google.com",
-            "panda@google.com",
-            "purui@google.com",
-            "rajan@google.com",
-            "ram@google.com",
-            "riteshg@google.com",
-            "sidds@google.com",
-            "smyang@google.com",
-            "stlafon@google.com",
-            "venkataraman@google.com",
-            "wei@google.com",
-            "wenjieli@google.com",
-            "wisam@google.com",
-            "xban@google.com",
-            "yantao@google.com",
-            "yezhao@google.com");
-
-    @Override
-    public void onCreate() {
-        Log.v(TAG, "onCreate");
-
-        // The publishing of accessibility events in Clearcut is only enabled
-        // if the device has a whitelisted account.
-        String accountName = getAccountName();
-        if (accountName != null) {
-            mPlatformServiceClient = new PlatformServiceClient(this, new RealClock());
-            // No need to synchronize this as the #onCreate method will only be
-            // called when the service is enabled in the settings, so it should
-            // be safe from concurrency issues.
-            try {
-                mExcludedPackages = ExcludedPackages.getInstance(this);
-                mProcessor = new AccessibilityEventProcessor(
-                        this, accountName, mExcludedPackages, mPlatformServiceClient,
-                        this);
-            } catch (Exception e) {
-                int msgId = ((e instanceof IllegalStateException)
-                        && e.getMessage().contains("com.google.android.gms.version"))
-                                ? R.string.gmscore_version_error
-                                : R.string.initialization_error;
-                Log.e(TAG, "Failed to initialize PixelPerfect", e);
-                showToast(msgId);
-                stopSelf();
-                return;
-            }
-            mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
-            setIsPaused(false);
-            showToast(R.string.pixelperfect_running);
-        } else {
-            showToast(R.string.unauthorized);
-        }
-    }
-
-    // TODO(stlafon): Understand why this method is never called after the onStartCommand() method
-    // is invoked (e.g. when the user clicks on pause/resume in the notification). The problem is
-    // that the notification doesn't get canceled if the following sequence happens:
-    // Enable service in settings -> Click on pause in notification -> Disable service in settings
-    @Override
-    public void onDestroy() {
-        Log.v(TAG, "onDestroy");
-
-        // Cancel the sticky notification.
-        if (mNotificationManager != null) {
-            mNotificationManager.cancel(NOTIFICATION_ID);
-        }
-        // Inform the user that PixelPerfect is no longer running.
-        showToast(R.string.pixelperfect_not_running);
-    }
-
-    @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
-        Log.v(TAG, "onStartCommand");
-
-        if (intent != null) {
-            if (ACTION_PAUSE.equals(intent.getAction())) {
-                setIsPaused(true);
-            } else if (ACTION_RESUME.equals(intent.getAction())) {
-                setIsPaused(false);
-            }
-        }
-
-        // The following will not stop the service, as the latter is not started by a call to
-        // startService(). Rather, it is enabled from the system settings. Calling stopSelf() here
-        // undoes the effect of onStartCommand(), which gets called each time the user clicks on
-        // pause/resume in the notification.
-        stopSelf();
-
-        // We want this service to continue running until it is explicitly stopped,
-        // so return sticky.
-        return START_STICKY;
-    }
-
-    @Override
-    public void onServiceConnected() {
-        Log.v(TAG, "onServiceConnected " + getServiceInfo());
-    }
-
-    @Override
-    public void onInterrupt() {
-        Log.v(TAG, "onInterrupt");
-    }
-
-    @Override
-    public void onAccessibilityEvent(AccessibilityEvent event) {
-        if (mProcessor != null && !getIsPaused()) {
-            mProcessor.process(event);
-        }
-    }
-
-    /**
-     * Atomically:
-     * <ul>
-     *   <li> sets the value of {@link #sIsPaused},
-     *   <li> updates the sticky notification,
-     *   <li> shows a toast informing the user of the new state.
-     * </ul>
-     *
-     * <p>This does not stop the {@link AccessibilityService}. It just prevents us from recording
-     * any event. To stop the service, users need to go to the system settings and manually disable.
-     * Note, calling {@link #stopSelf()} in this method doesn't seem to do anything.
-     *
-     * @param isPaused whether the recording is paused or not
-     */
-    @VisibleForTesting
-    synchronized void setIsPaused(boolean isPaused){
-        sIsPaused = isPaused;
-        mNotificationManager.notify(NOTIFICATION_ID, createNotification(sIsPaused));
-
-        int msgId = sIsPaused ? R.string.user_in_incognito : R.string.user_not_incognito;
-        showToast(msgId);
-    }
-
-    @VisibleForTesting
-    synchronized boolean getIsPaused() {
-        return sIsPaused;
-    }
-
-    /**
-     * If a whitelisted account is linked to this device, returns the account name. Otherwise,
-     * returns {@code null}.
-     */
-    @Nullable private String getAccountName() {
-        AccountManager manager = AccountManager.get(this);
-        return getAccountNameImpl(manager.getAccounts());
-    }
-
-    /** Same as {@link #getAccountName()}, but acts on an array of {@link Account}s. */
-    @VisibleForTesting
-    @Nullable String getAccountNameImpl(Account[] accounts) {
-        for (Account account : accounts) {
-            if (USERNAME_WHITELIST.contains(account.name.toLowerCase(Locale.ENGLISH))) {
-                return account.name;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Creates and returns a permanent (sticky) notification that features two buttons:
-     * <ul>
-     *   <li> A button to pause/resume data recording (pausing == going incognito).
-     *   <li> A button to launch the preferences activity, where users can set a blacklist of apps.
-     * </ul>
-     *
-     * @param isPaused whether recording is currently paused or not
-     * @return the {@link Notification}
-     */
-    @VisibleForTesting
-    Notification createNotification(boolean isPaused) {
-        int smallIconId = isPaused ? R.drawable.ic_no_cat : R.drawable.ic_cat;
-
-        Intent intent = new Intent(this, PreferencesActivity.class);
-        PendingIntent prefsPendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
-
-        intent = new Intent(this, AccessibilityEventService.class)
-            .setAction(isPaused ? ACTION_RESUME : ACTION_PAUSE);
-        PendingIntent servicePendingIntent = PendingIntent.getService(this, 0, intent, 0);
-
-        CharSequence pauseOrResume = isPaused ? getText(R.string.resume) : getText(R.string.pause);
-        int pauseOrResumeIcon = isPaused ? R.drawable.ic_resume : R.drawable.ic_pause;
-        CharSequence notifDescription =
-                isPaused ? getText(R.string.is_paused) : getText(R.string.is_running);
-
-        return new Notification.Builder(this)
-            .setContentTitle(getText(R.string.notification_title))
-            .setContentText(notifDescription)
-            .setSmallIcon(smallIconId)
-            .setOngoing(true)  // cannot be dismissed
-            .addAction(pauseOrResumeIcon, pauseOrResume, servicePendingIntent)
-            .addAction(R.drawable.ic_preferences, getText(R.string.notif_preferences),
-                    prefsPendingIntent)
-            .build();
-    }
-
-    /** Shows a {@link Toast}. */
-    private void showToast(int msgId) {
-        if (sToast == null) {
-            sToast = Toast.makeText(this, msgId, Toast.LENGTH_SHORT);
-        } else {
-            sToast.setText(msgId);
-        }
-        sToast.show();
-    }
-
-    @Override
-    public void onLoggerConnected() {
-        Log.v(TAG, "PlayLogger connected");
-    }
-
-    @Override
-    public void onLoggerFailedConnectionWithResolution(PendingIntent resolutionIntent) {
-        // TODO(dprothro): call the PendingIntent to see if the user will approve
-        // usage of the PlayLogger.
-        Log.e(TAG, "Failed to initialize PixelPerfect - loggerFailedConnectionWithResolution");
-        showToast(R.string.initialization_error);
-        stopSelf();
-    }
-
-    @Override
-    public void onLoggerFailedConnection() {
-        Log.e(TAG, "Failed to initialize PixelPerfect - loggerFailedConnection");
-        showToast(R.string.initialization_error);
-        stopSelf();
-    }
-}
diff --git a/PixelPerfect/src/com/google/android/apps/pixelperfect/ExcludedPackages.java b/PixelPerfect/src/com/google/android/apps/pixelperfect/ExcludedPackages.java
deleted file mode 100644
index bb5bba3..0000000
--- a/PixelPerfect/src/com/google/android/apps/pixelperfect/ExcludedPackages.java
+++ /dev/null
@@ -1,214 +0,0 @@
-package com.google.android.apps.pixelperfect;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * Access layer for the list of packages whose events should not be published to Clearcut.
- * This class maintains 2 exclusion sets:
- * <ul>
- *   <li>A hardcoded set of packages ("hardcoded exclusion set"), containing packages whose data
- *   must absolutely be excluding from logging (e.g. the screenlock key guard). Users cannot control
- *   the content of that set.
- *   <li>A custom set of packages ("custom exclusion set"), to which the user can freely add and
- *   remove packages.
- * </ul>
- *
- * <p>The custom exclusion set is ultimately stored on the internal storage of the device. So
- * it's a per-device set. Note that it should be made a per-user set that we store in the cloud.
- *
- * <p>This class is a singleton.
- */
-@ThreadSafe
-public class ExcludedPackages {
-
-    private static final String TAG = "PixelPerfect.ExcludedPackages";
-
-    /**
-     * The internal storage file that contains the comma-separated list of excluded packages, when
-     * the app is running (not in the tests).
-     */
-    private static final String EXCLUDED_PACKAGES_FILENAME = "excluded_packages.csv";
-
-    /** Delimiter used in the storage file. */
-    private static final String DEMILITER = ",";
-
-    /** Shared instance of this service. */
-    private static ExcludedPackages sSharedInstance;
-
-    /** Hardcoded packages. For apps that must absolutely be excluded. */
-    private final Set<String> mHardcodedPackages;
-
-    /** Packages that can be added or removed by the user. */
-    private final Set<String> mCustomPackages;
-
-    /** Filename where the exclusion list is stored. */
-    private final String mStorageFilename;
-
-    /** Context to hold on to for reading the storage file. */
-    private Context mContext;
-
-    /**
-     * Gets the instance to be used in the application. Do not use in tests! Instead, call the
-     * constructor below, and pass a custom filename (different from
-     * {@link #EXCLUDED_PACKAGES_FILENAME}).
-     */
-    public synchronized static ExcludedPackages getInstance(Context context) {
-        if (sSharedInstance == null) {
-            sSharedInstance = new ExcludedPackages(getHarcodedPackages(), context,
-                    EXCLUDED_PACKAGES_FILENAME);
-        }
-        // Use the latest context. This will make it more likely that we're not using a context
-        // that's already been destroyed.
-        sSharedInstance.mContext = context;
-        return sSharedInstance;
-    }
-
-    @VisibleForTesting
-    ExcludedPackages(Set<String> harcodedPackages, Context context, String fileName) {
-        mHardcodedPackages = harcodedPackages;
-        mCustomPackages = new HashSet<String>();
-        mContext = context;
-        mStorageFilename = fileName;
-        readFromFile();
-
-        if (sSharedInstance != null) {
-            Log.e(TAG, "Shared ExcludedPackages instance already exists!");
-        }
-        sSharedInstance = this;
-    }
-
-    /**
-     * Reads the custom exclusion set from the internal storage, and use it to populate the
-     * current state.
-     */
-    public synchronized void readFromFile() {
-        try {
-            FileInputStream inputStream = mContext.openFileInput(mStorageFilename);
-            InputStreamReader isr = new InputStreamReader(inputStream);
-            BufferedReader bufferedReader = new BufferedReader(isr);
-            String line;
-            // Note: We expect at most one line in the file.
-            line = bufferedReader.readLine();
-            mCustomPackages.clear();
-            if (line != null) {
-                mCustomPackages.addAll(Arrays.asList(line.split(DEMILITER)));
-            }
-        } catch (FileNotFoundException e) {
-            // The file hasn't been created yet. Just do nothing. It will be created next time
-            // a package is added to the custom exclusion set.
-        } catch (IOException e) {
-            Log.e(TAG, "Unable to read the excluded packages: " + e);
-        }
-    }
-
-    /**
-     * Returns whether a package should be excluded from logging.
-     *
-     * @param packageName the package name
-     */
-    public synchronized boolean isExcluded(String packageName) {
-        return mHardcodedPackages.contains(packageName)
-                || mCustomPackages.contains(packageName);
-    }
-
-    /**
-     * Returns a list containing the packages from the custom exclusion set. Hardcoded packages are
-     * not returned.
-     */
-    public synchronized List<String> getCustomExcludedPackages() {
-        return ImmutableList.copyOf(mCustomPackages);
-    }
-
-    /**
-     * Adds a package to the custom exclusion set and returns true upon success. Success means that
-     * the new package was successfully added, and that the new state was committed to disk.
-     *
-     * <p>This writes to the internal storage.
-     *
-     * @param packageName the package name
-     * @return true on success
-     */
-    public synchronized boolean addCustom(String packageName) {
-        if (mCustomPackages.contains(packageName)) {
-            return false;
-        }
-        List<String> packages = Lists.newArrayList(mCustomPackages);
-        packages.add(packageName);
-        try {
-            writeToFile(packages);
-            mCustomPackages.add(packageName);
-            return true;
-        } catch (IOException e) {
-            Log.e(TAG, "Unable to create or update excluded packages file");
-            return false;
-        }
-    }
-
-    /**
-     * Removes a package from the custom exclusion set.
-     *
-     * <p>This writes to the internal storage.
-     *
-     * @param packageName the package name
-     * @return whether something was actually removed (for instance, you can't
-     *     remove a package name that's in {@link #mHardcodedPackages}) and the new state was
-     *     successfully committed to disk
-     */
-    public synchronized boolean removeCustom(String packageName) {
-        if (!mCustomPackages.contains(packageName)) {
-            return false;
-        }
-        List<String> packages = Lists.newArrayList(mCustomPackages);
-        packages.remove(packageName);
-        try {
-            writeToFile(packages);
-            return mCustomPackages.remove(packageName);
-        } catch (IOException e) {
-            Log.e(TAG, "Unable to modify the excluded packages file");
-            return false;
-        }
-    }
-
-    /** Writes {@code packages} to the file. */
-    private void writeToFile(List<String> packages) throws IOException {
-        FileOutputStream outputStream;
-        // We only need to store the custom set of packages. That set is stored as a csv string.
-        String output = TextUtils.join(DEMILITER, packages);
-        // Create or replace the file. MODE_PRIVATE == Only readable/writable by this app.
-        outputStream = mContext.openFileOutput(mStorageFilename, Context.MODE_PRIVATE);
-        outputStream.write(output.getBytes());
-        outputStream.close();
-    }
-
-    /**
-     * Creates and returns the hardcoded exclusion set.
-     */
-    private static HashSet<String> getHarcodedPackages() {
-        // NOTE(stlafon): Excluding the key guard package might be too coarse, as it makes blind
-        // to when the user turns the screen on or off.
-        HashSet<String> hardcoded = Sets.newHashSet(
-                "com.android.keyguard",  // Key guard (screen lock)
-                "com.google.android.apps.pixelperfect");  // PixelPerfect
-        return hardcoded;
-    }
-}
diff --git a/PixelPerfect/src/com/google/android/apps/pixelperfect/PlatformServiceClient.java b/PixelPerfect/src/com/google/android/apps/pixelperfect/PlatformServiceClient.java
deleted file mode 100644
index a42d55c..0000000
--- a/PixelPerfect/src/com/google/android/apps/pixelperfect/PlatformServiceClient.java
+++ /dev/null
@@ -1,218 +0,0 @@
-package com.google.android.apps.pixelperfect;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.res.Resources;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.google.android.apps.pixelperfect.util.Clock;
-import com.google.android.apps.pixelperfect.api.IPixelPerfectPlatform;
-import com.google.android.apps.pixelperfect.api.ScreenshotParcel;
-import com.google.common.base.Preconditions;
-import com.google.common.logging.RecordedEvent.Screenshot;
-
-import javax.annotation.Nullable;
-
-/**
- * Client for interacting with PixelPerfectPlatform service.
- */
-public class PlatformServiceClient {
-    /**
-     * Constructor. Creates a new client object and binds PixelPerfectPlatform
-     * service.
-     * @param context {@link Context} of the calling application.
-     * @param clock {@link Clock} used for time stamps of connection and disconnection times.
-     */
-    public PlatformServiceClient(Context context, Clock clock) {
-        // TODO(mukarram) figure out whether a singleton would suffice.
-        // TODO(mukarram) figure out whether we need to synchronize on mPlatformService
-        Preconditions.checkNotNull(
-                context, "Context must not be null.",
-                clock, "Clock must not be null");
-        mContext = context;
-        mClock = clock;
-        initializeTimestamps();
-        connectAndBindPlatformService();
-    }
-
-    /**
-     * Obtains a screenshot by making an IPC to the PixelPerfectPlatform service.
-     *
-     * Note: calling package must be google signed AND white-listed in
-     * PixelPerfectPlatform, else a security exception is parceled and thrown
-     * while reading the screenshot.
-     *
-     * @return {@link Screenshot} proto instance that is returned by the
-     * PixelPerfectPlatformService. May return null if the returned parcel is as such.
-     */
-    public @Nullable Screenshot obtainScreenshot() throws RemoteException {
-        Log.v(TAG, "Attempting getScreenshot()");
-        // TODO(mukarram) Consider adding throttling for screenshots.
-        // Also consider whether such throttling makes sense here on the platform service itself.
-          ScreenshotParcel parcel = getPlatformServiceIfAvailable().getScreenshot();
-          if (parcel == null) {
-              return null;
-          }
-          return parcel.screenshotProto;
-    }
-
-    private static final String TAG = "PixelPerfect.PlatformServiceClient";
-
-    /** Whether we have binding to the platform service. */
-    private final Context mContext;
-    /** Reference to PixelPerfectPlatform service interface. */
-    private IPixelPerfectPlatform mPlatformService = null;
-
-    // Following time stamps are used for throttling the re-connection attempts
-    // should we loose connection to the service.
-    /** Time stamp for when the object is created. */
-    private long mLastConnectionAttemptTimeMs = 0;
-    /** Time stamp for when we are last connected from the platform service. */
-    private long mLastConnectTimeMs = 0;
-    /** Time stamp for when we are last disconnected to the platform service. */
-    private long mLastDisconnectTimeMs = 0;
-    /** Clock used for time stamps.*/
-    private Clock mClock = null;
-    /** Minimum time (in milliseconds) before attempting a reconnect.*/
-    private int mMinTimeMillsecToReconnect = 0;
-
-    /**
-     * Implements ServiceConnection to PixelPerfectPlatformService. Uses the
-     * onServiceConnected() and onServiceDisconnected callbacks to update a
-     * reference to PixelPerfectPlatform service interface.
-     */
-    class PlatformServiceConnection implements ServiceConnection {
-        @Override
-        public void onServiceConnected(ComponentName className, IBinder service) {
-            mPlatformService = IPixelPerfectPlatform.Stub.asInterface(service);
-            mLastConnectTimeMs = mClock.nowMs();
-            Log.v(TAG, "onServiceConnected: " + className.toString());
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName className) {
-            mPlatformService = null;
-            mLastDisconnectTimeMs = mClock.nowMs();
-            Log.v(TAG, "onServiceDisconnected " + className.toString());
-        }
-    }
-
-    /** Connection to the PixelPerfectPlatform service. */
-    private PlatformServiceConnection mConnection = null;
-
-    /**
-     * Helper to bind to PixelPerfectPlatform service if not already bound.
-     */
-    private void bindPlatformService() {
-        Log.v(TAG, "Attempting a bind to platform service at: " + mLastConnectionAttemptTimeMs);
-        if (mPlatformService != null) {
-            Log.v(TAG, "We are already bound to platform service. Do nothing.");
-            return;
-        }
-
-        mContext.bindService(
-                // TODO(mukarram) Use explicit intent.
-                // We are getting warnings of sort:
-                // 02-05 18:07:08.907 W/ContextImpl(16804):
-                // Implicit intents with startService are not safe:
-                // Intent { act=com.google.android.apps.pixelperfect.api.IPixelPerfectPlatform }
-                // android.content.ContextWrapper.bindService:513
-                // com.google.android.apps.pixelperfect.
-                // PlatformServiceClient.bindPlatformService:51
-                // com.google.android.apps.pixelperfect.PlatformServiceClient.<init>:71
-                //
-                // We tried:
-                // Intent intent = new Intent();
-                // intent.setClass(mContext, IPixelPerfectPlatform.class);
-                // and use that instead of new Intent(IPixelPerfectPlatform.class.getName()),
-                // but that did not work out.
-                // Still investigating.
-                new Intent(IPixelPerfectPlatform.class.getName()),
-                mConnection, Context.BIND_AUTO_CREATE);
-    }
-
-    /**
-     * Gets binding to PixelPerfectPlatform service if available. If service was
-     * for some reason disconnected, then attempts to reconnect.
-     * @return binding to PixelPerfectPlatform service if connected and bound.
-     * @throws IllegalStateException if not bound.
-     */
-    private IPixelPerfectPlatform getPlatformServiceIfAvailable() {
-        if (mPlatformService != null) {
-            return mPlatformService;
-        }
-        // We do not have a stub to platform service.
-        // See if it is okay to attempt a reconnect, if so fire off a reconnect attempt.
-        if (isThrottledConnectionRetryOkay()) {
-            Log.v(TAG, "Attempting a reconnect to platform service.");
-            // Note: following call does not block for connection to
-            // complete, therefore we cannot return a reference to
-            // platform service here, so although we are initiating a
-            // connection here, we still throw an exception.
-            // Recall from above that when connection completes,
-            // onServiceConnected() would be called in PlatformServiceConnection
-            connectAndBindPlatformService();
-        } else {
-            Log.v(TAG,
-                    "Disconnected from platform service, but not ready to reconnect yet."
-                    + "mLastConnectAttemptMs :" + mLastConnectionAttemptTimeMs
-                    + " time since:" + (mClock.nowMs() - mLastConnectionAttemptTimeMs));
-        }
-        // Throw an exception anyway, because we were not ready when get..() was called.
-        throw new IllegalStateException(
-                "Client not connected to platform service."
-                + " Connected at: " + mLastConnectTimeMs
-                + " Disconnected at: " + mLastDisconnectTimeMs);
-    }
-
-    /**
-     * Create a connection to PixelPerfectPlatform service if not already
-     * connected, and then bind, if not already bound.
-     */
-    private void connectAndBindPlatformService() {
-        // TODO(mukarram) Figure out whether we need to reestablish connection,
-        // or whether we can reuse the connection.
-        if (mConnection == null) {
-            mConnection = new PlatformServiceConnection();
-        }
-        mLastConnectionAttemptTimeMs = mClock.nowMs();
-        bindPlatformService();
-    }
-
-    private void initializeTimestamps() {
-        Resources res = mContext.getResources();
-        mMinTimeMillsecToReconnect = res.getInteger(
-                R.integer.min_time_ms_between_platform_service_reconnect);
-        mLastConnectTimeMs = 0;
-        mLastDisconnectTimeMs = 0;
-    }
-
-    /**
-     * Returns true if it is okay to attempt a reconnect.  We keep track of
-     * time stamps of when connection attempts are made and when connection
-     * disconnections occur, and throttle reconnection attempts such that there
-     * is at least mMinTimeMillsecToReconnect
-     * (R.integer.min_time_ms_between_platform_service_reconnect) is elapsed
-     * since last disconnect or between reconnect attempts.
-     * @return true if it is okay to retry, false if not.
-     */
-    private boolean isThrottledConnectionRetryOkay() {
-        final long nowMs = mClock.nowMs();
-        // If there has been at least one disconnect
-        // (i.e., mLastDisconnectTime > 0), then see if enough time has elapsed
-        // since last disconnect.
-        if (mLastDisconnectTimeMs > 0 &&
-            nowMs - mLastDisconnectTimeMs < mMinTimeMillsecToReconnect) {
-            return false;
-        }
-        // See if enough time has elapsed since last connection attempt.
-        if (nowMs - mLastConnectionAttemptTimeMs < mMinTimeMillsecToReconnect) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/PixelPerfect/src/com/google/android/apps/pixelperfect/api/IPixelPerfectPlatform.aidl b/PixelPerfect/src/com/google/android/apps/pixelperfect/api/IPixelPerfectPlatform.aidl
deleted file mode 100644
index 7cf981d..0000000
--- a/PixelPerfect/src/com/google/android/apps/pixelperfect/api/IPixelPerfectPlatform.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.google.android.apps.pixelperfect.api;
-import com.google.android.apps.pixelperfect.api.ScreenshotParcel;
-
-/**
- * PixelPerfectPlatform service interface.  This service allows appropriately
- * authorized packages to obtain certain signals that are only allowed to
- * platform-signed apps.  The idea is that the service is implemented in a
- * platform-signed apk.
- */
-interface IPixelPerfectPlatform {
-    /**
-     * Takes a screenshot
-     *
-     * @return screenshot {@link ScreenshotParcel} if successful.
-     * Exceptions, such as SecurityException if client is not authorized, are parceled back.
-     */
-    ScreenshotParcel getScreenshot() = 1;
-    // TODO(mukarram) Add an interface that allows obtaining clips of a
-    // screenshot and controlling whether compression is performed or not.
-}
\ No newline at end of file
diff --git a/PixelPerfect/src/com/google/android/apps/pixelperfect/api/ScreenshotParcel.aidl b/PixelPerfect/src/com/google/android/apps/pixelperfect/api/ScreenshotParcel.aidl
deleted file mode 100644
index 2bcbfeb..0000000
--- a/PixelPerfect/src/com/google/android/apps/pixelperfect/api/ScreenshotParcel.aidl
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.google.android.apps.pixelperfect.api;
-
-/**
-  * Used for IPC to {@link PixelPerfectPlatform} service to obtain screenshots
-  * protos {@link Screenshot}.
-  */
-parcelable ScreenshotParcel;
diff --git a/PixelPerfect/src/com/google/android/apps/pixelperfect/api/ScreenshotParcel.java b/PixelPerfect/src/com/google/android/apps/pixelperfect/api/ScreenshotParcel.java
deleted file mode 100644
index 831a0b8..0000000
--- a/PixelPerfect/src/com/google/android/apps/pixelperfect/api/ScreenshotParcel.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.google.android.apps.pixelperfect.api;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.common.logging.RecordedEvent.Screenshot;
-
-import javax.annotation.Nullable;
-
-/**
- * Screenshot parcel. Simply serializes and de-serializes the Screenshot proto
- * to/from the parcel.
- */
-public class ScreenshotParcel implements Parcelable {
-    // TODO(mukarram) We we probably want to implement something similar to
-    // https://googleplex-android.googlesource.com/platform/vendor/
-    // unbundled_google/packages/GoogleSearch/+/ub-now-lunchbox/src/com/google/
-    // android/sidekick/shared/remoteapi/ProtoParcelable.java
-    public static final Parcelable.Creator<ScreenshotParcel> CREATOR =
-            new Parcelable.Creator<ScreenshotParcel>() {
-        @Override
-        public ScreenshotParcel createFromParcel(Parcel source) {
-            return new ScreenshotParcel(source);
-        }
-
-        @Override
-        public ScreenshotParcel[] newArray(int size) {
-            return new ScreenshotParcel[size];
-        }
-    };
-
-    private static final String TAG = "PixelPerfectPlatform.ScreenshotParcel";
-    private Exception mException = null;
-    public Screenshot screenshotProto = null;
-
-    public ScreenshotParcel() {
-        screenshotProto = null;
-        mException = null;
-    }
-
-    public ScreenshotParcel(Parcel in) {
-        readFromParcel(in);
-    }
-
-    public ScreenshotParcel(Screenshot screenshotProto) {
-        this.screenshotProto = screenshotProto;
-    }
-
-    /**
-     * Set the exception that is to be written to parcel.
-     * @param e the {@link Exception} to parcel.
-     */
-    public void setException(@Nullable Exception e) {
-        this.mException = e;
-    }
-
-    // TODO(mukarram) Also add capability to carry any other errors that may
-    // occur while capturing screenshots.
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        if (mException != null) {
-            out.writeException(mException);
-        } else {
-            out.writeNoException();
-        }
-
-        if (screenshotProto == null) {
-            out.writeInt(0);
-            return;
-        }
-
-        byte[] bytes = screenshotProto.toByteArray();
-        out.writeInt(bytes.length);
-        out.writeByteArray(bytes);
-    }
-
-    public void readFromParcel(Parcel in) {
-        in.readException();
-        int length = in.readInt();
-        byte[] bytes = new byte[length];
-        in.readByteArray(bytes);
-        try {
-            Screenshot.Builder builder = Screenshot.newBuilder();
-            builder.mergeFrom(bytes);
-            screenshotProto = builder.build();
-        } catch (InvalidProtocolBufferException e) {
-            Log.e(TAG, "Could not deserialize proto " + e);
-            screenshotProto = null;
-        }
-    }
-}
diff --git a/PixelPerfect/src/com/google/android/apps/pixelperfect/preferences/PackageArrayAdapter.java b/PixelPerfect/src/com/google/android/apps/pixelperfect/preferences/PackageArrayAdapter.java
deleted file mode 100644
index 0fd5edc..0000000
--- a/PixelPerfect/src/com/google/android/apps/pixelperfect/preferences/PackageArrayAdapter.java
+++ /dev/null
@@ -1,180 +0,0 @@
-package com.google.android.apps.pixelperfect.preferences;
-
-import com.google.android.apps.pixelperfect.R;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.Filter;
-import android.widget.Filterable;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-/**
- * {@link ArrayAdapter} for displaying and selecting packages. It is used in two contexts:
- * <ul>
- *   <li> The autocomplete drop-down used for selecting a package to exclude. In that case, package
- *   icon, package name and application name are shown.
- *   <li> The custom exclusion list. In that case, the same information as above is shown, plus
- *   a button to remove the package from the list of excluded ones.
- * </ul>
- */
-@SuppressLint("DefaultLocale")
-public class PackageArrayAdapter extends ArrayAdapter<PackageItem> implements Filterable {
-
-    @SuppressWarnings("unused")
-    private static final String TAG = "PixelPerfect.PackageArrayAdapter";
-
-    private final List<PackageItem> mAllItems;
-    private List<PackageItem> mItems;
-
-    /**
-     * If true, items are featured in the auto-complete drop-down. Otherwise, it's used in the list
-     * of excluded packages.
-     */
-    private final boolean mForDropDown;
-
-    /** Filter that's used for the autocomplete drop-down. */
-    private final PackageFilter mFilter;
-
-    /** Callback used for removing a package name from the list of excluded packages. */
-    private final ReIncludePackageCallback mReIncludePackageCallback;
-
-    /**
-     * Constructs a {@link PackageArrayAdapter}.
-     *
-     * @param context the {@link Context}
-     * @param resourceId the resource ID for a layout file containing a layout to use when
-     *     instantiating views
-     * @param items the {@link PackageItem}s
-     * @param forDropDown if true, this {@link ArrayAdapter} is for the package selection drop-down,
-     *     otherwise, it's for rendering the list of excluded packages
-     * @param reIncludePackageCallback this callback is called when the user wants to
-     *     remove a given package name from the list of excluded packages. It must be
-     *     non-{@code null} if and only if {@code forDropDown} is false
-     */
-    public PackageArrayAdapter(Context context, int resourceId, List<PackageItem> items,
-            boolean forDropDown, @Nullable ReIncludePackageCallback reIncludePackageCallback) {
-        super(context, resourceId, items);
-        // reIncludePackageCallback is null iff forDropDown is true
-        Preconditions.checkArgument(forDropDown != (reIncludePackageCallback != null));
-        mAllItems = items;
-        mForDropDown = forDropDown;
-        // Note, the filter is only exercised for the drop-down.
-        mFilter = forDropDown ? new PackageFilter() : null;
-        // For the drop-down, start with nothing in the list of items. For the list case, start with
-        // all the items (and that won't change since filtering never occurs).
-        mItems = forDropDown ? null : mAllItems;
-        mReIncludePackageCallback = reIncludePackageCallback;
-    }
-
-    @Override
-    public int getCount() {
-        return mItems == null ? 0 : mItems.size();
-    }
-
-    @Override
-    public PackageItem getItem(int position) {
-        return mItems.get(position);
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * <p>Shows the trash button (to remove from the list of excluded packages) if this adapter is
-     * used in the list of excluded packages.
-     */
-    @Override
-    public View getView(final int position, View convertView, ViewGroup parent) {
-        View row = convertView;
-        LayoutInflater inflater = LayoutInflater.from(getContext());
-
-        final PackageItem item = getItem(position);
-        if (row == null) {
-            row = inflater.inflate(R.layout.package_item, parent, false);
-        }
-
-        TextView applicationNameView = (TextView) row.findViewById(R.id.applicationName);
-        TextView packageNameView = (TextView) row.findViewById(R.id.packageName);
-        if (item.getApplicationName() != null) {
-            applicationNameView.setText(item.getApplicationName());
-        }
-        packageNameView.setText(item.getPackageName());
-        if (item.getIcon() != null) {
-            ImageView icon = (ImageView) row.findViewById(R.id.icon);
-            icon.setImageDrawable(item.getIcon());
-        }
-
-        // Don't show the trash button if in the drop-down.
-        ImageButton button = (ImageButton) row.findViewById(R.id.button);
-        button.setVisibility(mForDropDown ? View.GONE : View.VISIBLE);
-        if (!mForDropDown) {
-            button.setOnClickListener(new OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    mReIncludePackageCallback.onReIncludePackage(item.getPackageName());
-                }
-            });
-        }
-
-        return row;
-    }
-
-    @Override
-    public Filter getFilter() {
-        return mFilter;
-    }
-
-    /**
-     * A {@link Filter} used to autocomplete on the package name.
-     */
-    private class PackageFilter extends Filter {
-
-        /**
-         * {@inheritDoc}
-         *
-         * Filters based on the presence of {@code constraint} as a substring of the package name
-         * or the app name.
-         */
-        @Override
-        protected FilterResults performFiltering(CharSequence constraint) {
-            FilterResults filterResults = new FilterResults();
-            ArrayList<PackageItem> results = Lists.newArrayList();
-
-            if (constraint != null) {
-                if (mAllItems != null && !mAllItems.isEmpty()) {
-                    String noramlizedConstraint = PackageItem.getNormalizedString(
-                            constraint.toString());
-                    for (PackageItem item : mAllItems) {
-                        if (item.matches(noramlizedConstraint)) {
-                            results.add(item);
-                        }
-                    }
-                }
-                filterResults.values = results;
-                filterResults.count = results.size();
-            }
-            return filterResults;
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        protected void publishResults(CharSequence constraint, FilterResults results) {
-            mItems = (ArrayList<PackageItem>) results.values;
-            notifyDataSetChanged();
-        }
-    }
-
-}
diff --git a/PixelPerfect/src/com/google/android/apps/pixelperfect/preferences/PackageItem.java b/PixelPerfect/src/com/google/android/apps/pixelperfect/preferences/PackageItem.java
deleted file mode 100644
index 9b76612..0000000
--- a/PixelPerfect/src/com/google/android/apps/pixelperfect/preferences/PackageItem.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.google.android.apps.pixelperfect.preferences;
-
-import android.graphics.drawable.Drawable;
-
-/**
- * Wrapper for a package name and its associated icon.
- */
-/* package */ class PackageItem {
-
-    /** The package name. */
-    private final String mPackageName;
-
-    /** The application name. Optional. */
-    private final String mAppName;
-
-    /** The normalized application name. Optional. */
-    private final String mNormalizedAppName;
-
-    /** The icon. */
-    private final Drawable mIcon;
-
-    PackageItem(String packageName, String appName, Drawable icon) {
-        mPackageName = packageName;
-        mAppName = appName;
-        mNormalizedAppName = getNormalizedString(appName);
-        mIcon = icon;
-    }
-
-    String getPackageName() {
-        return mPackageName;
-    }
-
-    String getApplicationName() {
-        return mAppName;
-    }
-
-    Drawable getIcon() {
-        return mIcon;
-    }
-
-    /** Normalizes a string for matching. */
-    static String getNormalizedString(String input) {
-        return input == null ? null : input.trim().toLowerCase();
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * <p>This determines what gets rendered in the autocomplete.
-     */
-    @Override
-    public String toString() {
-        return mPackageName;
-    }
-
-    /**
-     * Returns true if {@code normalizedInput} is contained in {@link #mPackageName} or in
-     * {@link #mNormalizedAppName}.
-     */
-    public boolean matches(String normalizedInput) {
-        return mPackageName.contains(normalizedInput)
-                || (mNormalizedAppName != null && mNormalizedAppName.contains(normalizedInput));
-
-    }
-}
diff --git a/PixelPerfect/src/com/google/android/apps/pixelperfect/preferences/PreferencesActivity.java b/PixelPerfect/src/com/google/android/apps/pixelperfect/preferences/PreferencesActivity.java
deleted file mode 100644
index e573d4a..0000000
--- a/PixelPerfect/src/com/google/android/apps/pixelperfect/preferences/PreferencesActivity.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.google.android.apps.pixelperfect.preferences;
-
-import com.google.android.apps.pixelperfect.ExcludedPackages;
-import com.google.android.apps.pixelperfect.R;
-import com.google.common.collect.Lists;
-
-import android.app.Activity;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.View;
-import android.widget.AutoCompleteTextView;
-import android.widget.ListView;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Preferences class. Allows to pause/resume, and also blacklist certain apps.
- *
- * <p>Users can exclude packages by adding them to the set of excluded packages.
- *
- * <p>NOTE(stlafon): This class is the only one that mutates the set of excluded packages.
- */
-public class PreferencesActivity extends Activity implements ReIncludePackageCallback {
-
-    @SuppressWarnings("unused")
-    private static final String TAG = "PixelPerfect.PreferencesActivity";
-
-    private AutoCompleteTextView mPackageExcludeTextView;
-
-    /** Maps a package name to the corresponding {@link PackageItem}. */
-    private Map<String, PackageItem> mPackageMap;
-
-    /**
-     * Instance of {@link ExcludedPackages}. It is the only instance of that class, in the entire
-     * application, that mutates the file containing the list of excluded packages.
-     */
-    private ExcludedPackages mExcludedPackages;
-
-    private PackageArrayAdapter mDropDownAdapter;
-    private PackageArrayAdapter mExcludedListAdapter;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.preferences);
-
-        // Get the list of all installed packages.
-        mExcludedPackages = ExcludedPackages.getInstance(this);
-        mPackageMap = getInstalledApplications();
-
-        // Take that list, and remove the packages that have already been excluded.
-        List<PackageItem> items = Lists.newArrayListWithCapacity(mPackageMap.size());
-        items.addAll(mPackageMap.values());
-        items.removeAll(getExcludedPackages());
-
-        // Populate the autocomplete adapter with that list.
-        mDropDownAdapter = new PackageArrayAdapter(this,
-                android.R.layout.simple_dropdown_item_1line, items, true, null);
-        mPackageExcludeTextView = (AutoCompleteTextView) findViewById(R.id.packageSearch);
-        mPackageExcludeTextView.setAdapter(mDropDownAdapter);
-
-        // Set up the list of excluded packages.
-        ListView excludedList = (ListView) findViewById(R.id.excludedList);
-        mExcludedListAdapter = new PackageArrayAdapter(this,
-                android.R.layout.simple_list_item_1, getExcludedPackages(), false, this);
-        excludedList.setAdapter(mExcludedListAdapter);
-    }
-
-    /**
-     * Called when the "Exclude" button is clicked. Adds the corresponding package name to the set
-     * of excluded packages.
-     */
-    public void onExcludePackage(@SuppressWarnings("unused") View view) {
-        String value = PackageItem.getNormalizedString(
-                mPackageExcludeTextView.getText().toString());
-        if (mPackageMap.containsKey(value)) {
-            PackageItem item = mPackageMap.get(value);
-            Log.v(TAG, "Excluding " + item);
-            // If the package was successfully added to the exclusion list, reflect it in the UI.
-            if (mExcludedPackages.addCustom(item.getPackageName())) {
-                mExcludedListAdapter.add(item);
-                mDropDownAdapter.remove(item);
-                mPackageExcludeTextView.setText("");
-            }
-        }
-    }
-
-    @Override
-    public void onReIncludePackage(String packageName) {
-        // If the package was successfully removed from the exclusion list, reflect it in the UI.
-        if (mExcludedPackages.removeCustom(packageName)) {
-            PackageItem item = getPackageItem(packageName);
-            mExcludedListAdapter.remove(item);
-            mDropDownAdapter.add(item);
-        }
-    }
-
-    /**
-     * Creates and returns a map from installed package names to their corresponding
-     * {@link PackageItem}s.
-     */
-    private Map<String, PackageItem> getInstalledApplications() {
-        Map<String, PackageItem> map = new HashMap<String, PackageItem>();
-
-        PackageManager pkgManager = getApplicationContext().getPackageManager();
-
-        List<ApplicationInfo> appInfo = pkgManager.getInstalledApplications(
-                PackageManager.GET_META_DATA);
-
-        for (ApplicationInfo info : appInfo) {
-            Drawable icon = pkgManager.getApplicationIcon(info);
-            String appName = (String) pkgManager.getApplicationLabel(info);
-            map.put(info.packageName, new PackageItem(info.packageName, appName, icon));
-        }
-        return map;
-    }
-
-    /**
-     * Creates and returns the list of excluded packages.
-     */
-    private List<PackageItem> getExcludedPackages() {
-        List<PackageItem> excluded = Lists.newArrayList();
-        for (String packageName : mExcludedPackages.getCustomExcludedPackages()) {
-            excluded.add(getPackageItem(packageName));
-        }
-        return excluded;
-    }
-
-    /**
-     * Looks up a {@link PackageItem} for a given package name in the list of installed packages,
-     * or returns a new one if it can't be found on this device.
-     */
-    private PackageItem getPackageItem(String packageName) {
-        if (mPackageMap.containsKey(packageName)) {
-            return mPackageMap.get(packageName);
-        } else {
-            // No such package in the list of packages installed on this device. This could happen
-            // if the package was un-installed, since we last created the list of installed
-            // packages. Or, in the future, if we save the excluded packages in the cloud, this
-            // could happen because the package was installed on a different device.
-            // In that case, create a new {@code PackageItem}.
-            return new PackageItem(packageName, null, null);
-        }
-    }
-}
diff --git a/PixelPerfect/src/com/google/android/apps/pixelperfect/preferences/ReIncludePackageCallback.java b/PixelPerfect/src/com/google/android/apps/pixelperfect/preferences/ReIncludePackageCallback.java
deleted file mode 100644
index c976d53..0000000
--- a/PixelPerfect/src/com/google/android/apps/pixelperfect/preferences/ReIncludePackageCallback.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.google.android.apps.pixelperfect.preferences;
-
-/**
- * Callback used to remove a package name from the list of excluded packages.
- */
-public interface ReIncludePackageCallback {
-
-    /**
-     * Removes a package name from the list of excluded packages.
-     *
-     * @param packageName the package name
-     */
-    void onReIncludePackage(String packageName);
-
-}
diff --git a/PixelPerfect/src/com/google/android/apps/pixelperfect/util/Clock.java b/PixelPerfect/src/com/google/android/apps/pixelperfect/util/Clock.java
deleted file mode 100644
index b7a9f94..0000000
--- a/PixelPerfect/src/com/google/android/apps/pixelperfect/util/Clock.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.google.android.apps.pixelperfect.util;
-
-/**
- * Provides current value of time (now).
- */
-public interface Clock {
-    /**
-     * Returns the current, absolute time in milliseconds, according to this clock.
-     */
-    public long nowMs();
-}
diff --git a/PixelPerfect/src/com/google/android/apps/pixelperfect/util/RealClock.java b/PixelPerfect/src/com/google/android/apps/pixelperfect/util/RealClock.java
deleted file mode 100644
index 2e13833..0000000
--- a/PixelPerfect/src/com/google/android/apps/pixelperfect/util/RealClock.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.google.android.apps.pixelperfect.util;
-
-import android.os.SystemClock;
-
-/**
- * Implements {@link Clock} and provides nowMs according to SystemClock.
- */
-public class RealClock implements Clock {
-    @Override
-    public long nowMs() {
-        return SystemClock.elapsedRealtime();
-    }
-}
\ No newline at end of file
diff --git a/PixelPerfect/tests/Android.mk b/PixelPerfect/tests/Android.mk
index 42231b5..aba4904 100644
--- a/PixelPerfect/tests/Android.mk
+++ b/PixelPerfect/tests/Android.mk
@@ -1,28 +1,21 @@
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-# We only want this apk build for tests.
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target \
+        android-support-test
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_CERTIFICATE := platform
 
-# Use Google certificate instead of platform certificate since GmsCore
-# only allows usage from apps signed with the Google certificate.
-# Note: the cert here and in ../Android.mk should match.
-LOCAL_CERTIFICATE := vendor/unbundled_google/libraries/certs/app
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-# Include all test java files.
-api_source_file_patterns = src/com/google/android/apps/pixelperfect/api/%
-platform_source_file_patterns = src/com/google/android/apps/pixelperfect/platform/%
-LOCAL_SRC_FILES := $(filter-out $(api_source_file_patterns), \
-        $(filter-out $(platform_source_file_patterns), $(call all-java-files-under, src)))
+LOCAL_PACKAGE_NAME := PixelPerfectPlatformTests
 
-LOCAL_PACKAGE_NAME := PixelPerfectTests
+LOCAL_PROGUARD_ENABLED := disabled
 
-LOCAL_INSTRUMENTATION_FOR := PixelPerfect
+LOCAL_INSTRUMENTATION_FOR := PixelPerfectPlatform
 
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 10
 
 include $(BUILD_PACKAGE)
diff --git a/PixelPerfect/tests/AndroidManifest.xml b/PixelPerfect/tests/AndroidManifest.xml
index fc9a358..cc47425 100644
--- a/PixelPerfect/tests/AndroidManifest.xml
+++ b/PixelPerfect/tests/AndroidManifest.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.google.android.apps.pixelperfect.tests">
+    package="com.google.android.apps.pixelperfect.platform.tests">
 
     <!-- We add an application tag here just so that we can indicate that
          this package needs to link against the android.test library,
@@ -13,10 +13,10 @@
     <!--
     This declares that this app uses the instrumentation test runner targeting
     the package of com.example.android.apis.  To run the tests use the command:
-    "adb shell am instrument -w com.example.android.apis.tests/android.test.InstrumentationTestRunner"
+    "adb shell am instrument -w com.google.android.apps.pixelperfect.platform.tests/android.test.InstrumentationTestRunner"
     -->
     <instrumentation android:name="android.test.InstrumentationTestRunner"
-                     android:targetPackage="com.google.android.apps.pixelperfect"
-                     android:label="Tests for PixelPerfect."/>
+                     android:targetPackage="com.google.android.apps.pixelperfect.platform"
+                     android:label="Tests for PixelPerfectPlatform."/>
 
 </manifest>
diff --git a/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/AccessibilityEventProcessorTest.java b/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/AccessibilityEventProcessorTest.java
deleted file mode 100644
index 594ccaa..0000000
--- a/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/AccessibilityEventProcessorTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-package com.google.android.apps.pixelperfect;
-
-import static org.mockito.Matchers.isA;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.when;
-
-import android.annotation.TargetApi;
-import android.graphics.Rect;
-import android.os.Build;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.accessibility.AccessibilityNodeInfo;
-
-import com.google.android.apps.pixelperfect.AccessibilityEventProcessor.ClearcutLogger;
-import com.google.common.logging.RecordedEvent;
-import com.google.common.logging.RecordedEvent.RecordedTypes.WidgetType;
-import com.google.common.logging.RecordedEvent.UIElement;
-
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import java.util.List;
-
-/**
- * Tests for {@link AccessibilityEventProcessor}.
- */
-@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
-@SmallTest
-public class AccessibilityEventProcessorTest extends AndroidTestCase {
-
-    private static final String VIEW_ID_RESOURCE_NAME_1 = "view 1";
-    private static final String TEXT_1 = "text 1";
-    private static final String TEXT_2 = "text 2";
-    private static final String TEXT_3 = "text 3";
-    private static final String WIDGET_CLASS_NAME_1 = "android.widget.CheckedTextView";
-    private static final String WIDGET_CLASS_NAME_2 = "android.widget.LinearLayout";
-    private static final String WIDGET_CLASS_NAME_3 = "android.widget.EditText";
-    private static final String WIDGET_CLASS_NAME_4 = "android.widget.EditText";
-
-    private static final Rect RECT = new Rect(110, 120, 130, 140);
-    private static final Rect RECT_B = new Rect(210, 220, 230, 240);
-    private static final Rect RECT_C = new Rect(310, 320, 330, 340);
-
-    @Mock private AccessibilityNodeInfo mNode;
-    @Mock private AccessibilityNodeInfo mSubNodeA;
-    @Mock private AccessibilityNodeInfo mSubNodeB;
-    @Mock private AccessibilityNodeInfo mSubNodeC;
-
-    @Mock private ExcludedPackages mExcludedPackages;
-    @Mock private ClearcutLogger mLogger;
-
-    private AccessibilityEventProcessor mProcessor;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        // The following is needed to make mockito work.
-        // see https://code.google.com/p/dexmaker/issues/detail?id=2
-        System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
-        MockitoAnnotations.initMocks(this);
-        mProcessor = new AccessibilityEventProcessor(mExcludedPackages, null, mLogger);
-    }
-
-    public void testCreateUIElement() {
-        // Stubbing for the top node.
-        when(mNode.getClassName()).thenReturn(WIDGET_CLASS_NAME_1);
-        when(mNode.getViewIdResourceName()).thenReturn(VIEW_ID_RESOURCE_NAME_1);
-        when(mNode.getText()).thenReturn(TEXT_1);
-        when(mNode.getChildCount()).thenReturn(3);
-        doAnswer(new Answer<Object>() {
-            @Override
-            public Object answer(InvocationOnMock invocation) throws Throwable {
-                Rect rect = (Rect) invocation.getArguments()[0];
-                rect.set(RECT);
-                return null;
-            }
-        }).when(mNode).getBoundsInParent(isA(Rect.class));
-
-        // Stubbing for subnode A.
-        when(mSubNodeA.getClassName()).thenReturn(WIDGET_CLASS_NAME_2);
-        when(mSubNodeA.getViewIdResourceName()).thenReturn(null);
-        when(mSubNodeA.getText()).thenReturn(TEXT_2);
-        when(mSubNodeA.getChildCount()).thenReturn(0);
-        when(mNode.getChild(0)).thenReturn(mSubNodeA);
-
-        // Stubbing for subnode B.
-        when(mSubNodeB.getClassName()).thenReturn(WIDGET_CLASS_NAME_3);
-        when(mSubNodeB.getViewIdResourceName()).thenReturn(null);
-        when(mSubNodeB.getText()).thenReturn(null);
-        when(mSubNodeB.getChildCount()).thenReturn(0);
-        doAnswer(new Answer<Object>() {
-            @Override
-            public Object answer(InvocationOnMock invocation) throws Throwable {
-                Rect rect = (Rect) invocation.getArguments()[0];
-                rect.set(RECT_B);
-                return null;
-            }
-        }).when(mSubNodeB).getBoundsInParent(isA(Rect.class));
-        when(mNode.getChild(1)).thenReturn(mSubNodeB);
-
-        // Stubbing for subnode C, which in this case is a password node.
-        when(mSubNodeC.getClassName()).thenReturn(WIDGET_CLASS_NAME_4);
-        when(mSubNodeC.getViewIdResourceName()).thenReturn(null);
-        when(mSubNodeC.getText()).thenReturn(TEXT_3);
-        when(mSubNodeC.isPassword()).thenReturn(true);
-        when(mSubNodeC.getChildCount()).thenReturn(0);
-        doAnswer(new Answer<Object>() {
-            @Override
-            public Object answer(InvocationOnMock invocation) throws Throwable {
-                Rect rect = (Rect) invocation.getArguments()[0];
-                rect.set(RECT_C);
-                return null;
-            }
-        }).when(mSubNodeC).getBoundsInParent(isA(Rect.class));
-        when(mNode.getChild(2)).thenReturn(mSubNodeC);
-
-        // Run the test.
-        // TODO(mukarram) add test for Screenshots being set properly.
-        UIElement element = mProcessor.createUIElement(mNode, null, true);
-
-        checkElement(element, WidgetType.CHECKED_TEXT_VIEW, VIEW_ID_RESOURCE_NAME_1, TEXT_1, false, RECT);
-
-        List<UIElement> childList = element.getChildList();
-        assertEquals(3, childList.size());
-        checkElement(childList.get(0), WidgetType.LINEAR_LAYOUT, null, TEXT_2, false, new Rect());
-        checkElement(childList.get(1), WidgetType.EDIT_TEXT, null, null, false, RECT_B);
-        // For the third child, we expect content to be elided.
-        checkElement(childList.get(2), WidgetType.EDIT_TEXT, null, null, true, RECT_C);
-    }
-
-    public void testShouldElideContent() {
-        when(mNode.isPassword()).thenReturn(true);
-        assertTrue(mProcessor.shouldElideContent(mNode));
-
-        when(mNode.isPassword()).thenReturn(false);
-        assertFalse(mProcessor.shouldElideContent(mNode));
-    }
-
-    private void checkElement(UIElement element, WidgetType classType, String resourceName,
-            String content, boolean contentElided, Rect rect) {
-        assertEquals(classType, element.getClassType());
-        if (resourceName != null) {
-            assertEquals(resourceName, element.getResourceName());
-        } else {
-            assertFalse(element.hasResourceName());
-        }
-        if (content != null) {
-            assertEquals(content, element.getContent());
-        } else {
-            assertFalse(element.hasContent());
-        }
-        assertEquals(contentElided, element.getContentElided());
-        checkRect(rect, element.getRect());
-    }
-
-    private void checkRect(Rect rect, RecordedEvent.RecordedRect recordedRect) {
-        assertEquals(rect.left, recordedRect.getLeft());
-        assertEquals(rect.top, recordedRect.getTop());
-        assertEquals(rect.right, recordedRect.getRight());
-        assertEquals(rect.bottom, recordedRect.getBottom());
-    }
-
-}
diff --git a/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/AccessibilityEventServiceTest.java b/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/AccessibilityEventServiceTest.java
deleted file mode 100644
index efe41a6..0000000
--- a/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/AccessibilityEventServiceTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.google.android.apps.pixelperfect;
-
-import android.accounts.Account;
-import android.annotation.TargetApi;
-import android.app.Notification;
-import android.app.Notification.Action;
-import android.content.Intent;
-import android.test.ServiceTestCase;
-
-/**
- * Tests for {@link AccessibilityEventService}.
- */
-public class AccessibilityEventServiceTest extends ServiceTestCase<AccessibilityEventService> {
-
-    private static final String ACCOUNT_NAME = "stlafon@google.com";
-
-    public AccessibilityEventServiceTest() {
-        super(AccessibilityEventService.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-      super.setUp();
-      startService(new Intent(getContext(), AccessibilityEventService.class));
-    }
-
-    public void testPauseAndResume() {
-        assertFalse(getService().getIsPaused());
-
-        Intent intent = new Intent(getService(), AccessibilityEventService.class)
-            .setAction(AccessibilityEventService.ACTION_PAUSE);
-        startService(intent);
-        assertTrue(getService().getIsPaused());
-
-        intent = new Intent(getContext(), AccessibilityEventService.class);  // No action
-        startService(intent);
-        assertTrue(getService().getIsPaused());
-
-        intent = new Intent(getContext(), AccessibilityEventService.class)
-            .setAction(AccessibilityEventService.ACTION_RESUME);
-        startService(intent);
-        assertFalse(getService().getIsPaused());
-    }
-
-    @TargetApi(19)  // for Notification#actions
-    public void testCreateNotification() {
-        // This test is pretty limited because it's not possible to look at the Intent inside a
-        // PendingIntent.
-        Notification notification = getService().createNotification(false);
-        Action[] actions = notification.actions;
-        assertEquals(2, actions.length);
-    }
-
-    public void testGetCorpAccountNameImpl() {
-        Account googleCorp = new Account(ACCOUNT_NAME, "com.google");
-        Account gmail = new Account("foo@gmail.com", "com.gmail");
-
-        Account[] accountsNoCorp = { gmail };
-        assertNull(getService().getAccountNameImpl(accountsNoCorp));
-
-        Account[] accountsHasCorp = { googleCorp, gmail };
-        assertEquals(ACCOUNT_NAME, getService().getAccountNameImpl(accountsHasCorp));
-    }
-}
diff --git a/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/ExcludedPackagesTest.java b/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/ExcludedPackagesTest.java
deleted file mode 100644
index 4237ac3..0000000
--- a/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/ExcludedPackagesTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.google.android.apps.pixelperfect;
-
-import android.content.Context;
-import android.test.AndroidTestCase;
-import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Tests for {@link ExcludedPackages}.
- */
-@SmallTest
-public class ExcludedPackagesTest extends AndroidTestCase {
-
-    private static final String GMAIL = "com.google.gmail";
-    private static final String MAPS = "com.google.maps";
-    private static final String NOW = "com.google.now";
-    private static final String YOUTUBE = "com.google.youtube";
-
-    private static final Set<String> HARDCODED_PACKAGES = new HashSet<String>();
-    static {
-        HARDCODED_PACKAGES.add(GMAIL);
-        HARDCODED_PACKAGES.add(NOW);
-    }
-
-    private static final String FILENAME = "excluded_packages_tests.csv";
-
-    private ExcludedPackages mExcludedPackages;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        cleanUpStorageFile();
-        mExcludedPackages = getNewInstance();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        cleanUpStorageFile();
-    }
-
-    public void testExclusion() {
-        assertExcluded(GMAIL);
-        assertExcluded(NOW);
-        assertNotExcluded("com.google.gmail2");
-        assertNotExcluded("com.ggggggle.now");
-        assertNotExcluded(YOUTUBE);
-
-        assertTrue(mExcludedPackages.addCustom(YOUTUBE));
-        assertExcluded(YOUTUBE);
-
-        assertTrue(mExcludedPackages.removeCustom(YOUTUBE));
-        assertNotExcluded(YOUTUBE);
-
-        assertFalse(mExcludedPackages.removeCustom(GMAIL));
-    }
-
-    public void testReadFile() throws Exception {
-        FileOutputStream outputStream;
-        String output = MAPS + "," + YOUTUBE;
-        outputStream = mContext.openFileOutput(FILENAME, Context.MODE_PRIVATE);
-        outputStream.write(output.getBytes());
-        outputStream.close();
-
-        mExcludedPackages = getNewInstance();
-        MoreAsserts.assertContentsInAnyOrder(mExcludedPackages.getCustomExcludedPackages(),
-                MAPS, YOUTUBE);
-    }
-
-    private void assertExcluded(String packageName) {
-        assertTrue(mExcludedPackages.isExcluded(packageName));
-    }
-
-    private void assertNotExcluded(String packageName) {
-        assertTrue(!mExcludedPackages.isExcluded(packageName));
-    }
-
-    private void cleanUpStorageFile() throws Exception {
-        File dir = mContext.getFilesDir();
-        File file = new File(dir, FILENAME);
-        file.delete();
-    }
-
-    private ExcludedPackages getNewInstance() {
-        return new ExcludedPackages(HARDCODED_PACKAGES, getContext(), FILENAME);
-    }
-}
diff --git a/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/PlatformServiceClientTest.java b/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/PlatformServiceClientTest.java
deleted file mode 100644
index 414c46a..0000000
--- a/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/PlatformServiceClientTest.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.google.android.apps.pixelperfect;
-import android.test.AndroidTestCase;
-
-import com.google.android.apps.pixelperfect.testutil.FakeClock;
-
-/**
- * Tests for PlatformServiceClient
- * TODO(mukarram) Do something meaningful here.
- */
-public class PlatformServiceClientTest extends AndroidTestCase {
-    public PlatformServiceClientTest() {
-        // TODO(mukarram): Auto-generated constructor stub
-    }
-}
diff --git a/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/api/ScreenshotParcelTest.java b/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/api/ScreenshotParcelTest.java
deleted file mode 100644
index ba07350..0000000
--- a/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/api/ScreenshotParcelTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package com.google.android.apps.pixelperfect.api;
-
-import android.os.Bundle;
-import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.google.android.apps.pixelperfect.platform.ScreenshotGrabber;
-import com.google.common.logging.RecordedEvent;
-import com.google.common.logging.RecordedEvent.Screenshot;
-
-import junit.framework.TestCase;
-
-import java.io.ByteArrayOutputStream;
-
-/**
- * Tests for {@link ScreenshotParcel}.
- */
-@SmallTest
-public class ScreenshotParcelTest extends TestCase {
-    private Screenshot mScreenshotProto = null;
-    private Parcel mParcel = null;
-
-    private void createTestScreenshotProto() throws Exception {
-        final int height = 10;
-        final int width = 15;
-        final int rotation = 100;
-        final int quality = 50;
-        final byte[] compressed_bytes = new byte[] {
-                (byte) 0xca, (byte) 0xfe };
-
-        ByteArrayOutputStream output = new ByteArrayOutputStream(
-                compressed_bytes.length);
-        output.write(compressed_bytes, 0, compressed_bytes.length);
-        ScreenshotGrabber grabber = new ScreenshotGrabber();
-        mScreenshotProto = grabber.fillScreenshotProto(
-                output, height, width, rotation,
-                RecordedEvent.Bitmap.BitmapConfig.Config.ARGB_8888,
-                RecordedEvent.Bitmap.CompressionConfig.CompressFormat.JPEG,
-                quality);
-
-        // TODO(mukarram) figure out why ScreenshotParcel(mScreenshotProto)
-        // does not work.
-        ScreenshotParcel screenshotParcel = new ScreenshotParcel();
-        screenshotParcel.screenshotProto = mScreenshotProto;
-
-        Bundle bundle = new Bundle();
-        bundle.putParcelable("screenshotParcel", screenshotParcel);
-        mParcel = Parcel.obtain();
-        bundle.writeToParcel(mParcel, 0);
-    }
-
-    public static void assertProtosEqual(Screenshot protoA, Screenshot protoB) {
-        assertEquals(protoA.getRotation(), protoB.getRotation());
-        assertEquals(protoA.getBitmap().getBitmap(), protoB.getBitmap().getBitmap());
-        assertEquals(protoA.getBitmap().getHeight(), protoB.getBitmap().getHeight());
-        assertEquals(protoA.getBitmap().getWidth(), protoB.getBitmap().getWidth());
-        assertEquals(protoA.getRotation(), protoB.getRotation());
-
-        assertEquals(protoA.getBitmap().getBitmapConfig().getValue(),
-                protoB.getBitmap().getBitmapConfig().getValue());
-        assertEquals(protoA.getBitmap().getCompressionConfig().getFormat(),
-                protoB.getBitmap().getCompressionConfig().getFormat());
-        assertEquals(protoA.getBitmap().getCompressionConfig().getQuality(),
-                protoB.getBitmap().getCompressionConfig().getQuality());
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        createTestScreenshotProto();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-        if (mParcel != null) {
-            mParcel.recycle();
-        }
-    }
-
-    public void testParcelReadWrite() {
-        mParcel.setDataPosition(0);
-        Bundle testBundle = mParcel.readBundle();
-        testBundle.setClassLoader(ScreenshotParcelTest.class.getClassLoader());
-        ScreenshotParcel testScreenshotParcel = testBundle.getParcelable("screenshotParcel");
-        assertProtosEqual(mScreenshotProto, testScreenshotParcel.screenshotProto);
-    }
-
-}
diff --git a/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/testutil/FakeClock.java b/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/testutil/FakeClock.java
deleted file mode 100644
index 0eb761f..0000000
--- a/PixelPerfect/tests/src/com/google/android/apps/pixelperfect/testutil/FakeClock.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.google.android.apps.pixelperfect.testutil;
-
-import com.google.android.apps.pixelperfect.util.Clock;
-
-/**
- * A fake clock that implements {@link Clock} interface. Use for tests.
- */
-public class FakeClock implements Clock {
-    @Override
-    public long nowMs() {
-        return nowMs;
-    }
-    /** Set current time*/
-    public void setTime(long nowMs) {
-        this.nowMs = nowMs;
-    }
-    /** Advance current time*/
-    public void advanceTime(long diffMs) {
-        nowMs += diffMs;
-    }
-    private long nowMs = 0;
-}