wire up sampling profiler to dropbox

When system property "persist.sys.profiler_hz" > 0, SamplingProfilerService is
loaded to SystemServer. It creates a FileObserver, watching any new file in the snapshot
directory. When a snapshot is found, it is put in dropbox and deleted after that.

SamplingProfilerIntegration writes snapshots with headers. Headers are <name, value> pairs,
instantiated by caller.

Currently header format is (also in source comment):

Version: <version number of profiler>\n
Process: <process name>\n
Package: <package name, if exists>\n
Package-Version: <version number of the package, if exists>\n
Build: <fingerprint>\n
\n
<the actual snapshot content begins here...>

BUG=2732642

Change-Id: I2c1699f1728e603de13dbd38f9d8443cd3eecc06
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 468b271..112d9da 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -31,6 +31,7 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ServiceInfo;
 import android.content.res.AssetManager;
@@ -2149,8 +2150,27 @@
 
         void maybeSnapshot() {
             if (mBoundApplication != null) {
-                SamplingProfilerIntegration.writeSnapshot(
-                        mBoundApplication.processName);
+                // convert the *private* ActivityThread.PackageInfo to *public* known
+                // android.content.pm.PackageInfo
+                String packageName = mBoundApplication.info.mPackageName;
+                android.content.pm.PackageInfo packageInfo = null;
+                try {
+                    Context context = getSystemContext();
+                    if(context == null) {
+                        Log.e(TAG, "cannot get a valid context");
+                        return;
+                    }
+                    PackageManager pm = context.getPackageManager();
+                    if(pm == null) {
+                        Log.e(TAG, "cannot get a valid PackageManager");
+                        return;
+                    }
+                    packageInfo = pm.getPackageInfo(
+                            packageName, PackageManager.GET_ACTIVITIES);
+                } catch (NameNotFoundException e) {
+                    Log.e(TAG, "cannot get package info for " + packageName, e);
+                }
+                SamplingProfilerIntegration.writeSnapshot(mBoundApplication.processName, packageInfo);
             }
         }
     }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 37f18de..a66c9ed 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -16,14 +16,11 @@
 
 package android.provider;
 
-import com.google.android.collect.Maps;
 
-import org.apache.commons.codec.binary.Base64;
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.ComponentName;
-import android.content.ContentQueryMap;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
@@ -38,19 +35,14 @@
 import android.database.SQLException;
 import android.net.Uri;
 import android.os.*;
-import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.AndroidException;
 import android.util.Config;
 import android.util.Log;
 
 import java.net.URISyntaxException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Map;
 
 
 /**
@@ -2416,6 +2408,14 @@
         public static final String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
 
         /**
+         * A positive value indicates the frequency of SamplingProfiler
+         * taking snapshots in hertz. Zero value means SamplingProfiler is disabled.
+         *
+         * @hide
+         */
+        public static final String SAMPLING_PROFILER_HZ = "sampling_profiler_hz";
+
+        /**
          * Settings classname to launch when Settings is clicked from All
          * Applications.  Needed because of user testing between the old
          * and new Settings apps.