Add system wide management of core settings

bug:3505060

Since we want to have some settings that are used very frequently
by many applications (long-press timeout is one example) these should
be managed efficiently to reduce lookups from different processes
because in the case of a cache miss a disk I/O is performed. Now
the system manages such core settings and propagates them to the
application processes.

Change-Id: Ie793211baf8770f2181ac8ba9d7c2609dfaa32a7
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 8f9a76b..b409f2f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -98,7 +98,6 @@
 import java.util.regex.Pattern;
 
 import dalvik.system.CloseGuard;
-import dalvik.system.SamplingProfiler;
 
 final class SuperNotCalledException extends AndroidRuntimeException {
     public SuperNotCalledException(String msg) {
@@ -355,6 +354,7 @@
         boolean restrictedBackupMode;
         Configuration config;
         boolean handlingProfiling;
+        Bundle coreSettings;
         public String toString() {
             return "AppBindData{appInfo=" + appInfo + "}";
         }
@@ -552,7 +552,7 @@
                 ComponentName instrumentationName, String profileFile,
                 Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
                 int debugMode, boolean isRestrictedBackupMode, Configuration config,
-                Map<String, IBinder> services) {
+                Map<String, IBinder> services, Bundle coreSettings) {
 
             if (services != null) {
                 // Setup the service cache in the ServiceManager
@@ -570,6 +570,7 @@
             data.debugMode = debugMode;
             data.restrictedBackupMode = isRestrictedBackupMode;
             data.config = config;
+            data.coreSettings = coreSettings;
             queueOrSendMessage(H.BIND_APPLICATION, data);
         }
 
@@ -896,6 +897,10 @@
         private void printRow(PrintWriter pw, String format, Object...objs) {
             pw.println(String.format(format, objs));
         }
+
+        public void setCoreSettings(Bundle settings) {
+            queueOrSendMessage(H.SET_CORE_SETTINGS, settings);
+        }
     }
 
     private final class H extends Handler {
@@ -937,6 +942,7 @@
         public static final int DUMP_HEAP               = 135;
         public static final int DUMP_ACTIVITY           = 136;
         public static final int SLEEPING                = 137;
+        public static final int SET_CORE_SETTINGS       = 138;
         String codeToString(int code) {
             if (DEBUG_MESSAGES) {
                 switch (code) {
@@ -978,6 +984,7 @@
                     case DUMP_HEAP: return "DUMP_HEAP";
                     case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
                     case SLEEPING: return "SLEEPING";
+                    case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
                 }
             }
             return "(unknown)";
@@ -1113,6 +1120,9 @@
                 case SLEEPING:
                     handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
                     break;
+                case SET_CORE_SETTINGS:
+                    handleSetCoreSettings((Bundle) msg.obj);
+                    break;
             }
             if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
         }
@@ -2709,6 +2719,14 @@
         }
     }
 
+    private void handleSetCoreSettings(Bundle coreSettings) {
+        if (mBoundApplication != null) {
+            synchronized (mBoundApplication) {
+                mBoundApplication.coreSettings = coreSettings;
+            }
+        }
+    }
+
     private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
         final int N = results.size();
         for (int i=0; i<N; i++) {
@@ -3971,6 +3989,20 @@
         }
     }
 
+    public int getIntCoreSetting(String key, int defaultValue) {
+        if (mBoundApplication == null) {
+            return defaultValue;
+        }
+        synchronized (mBoundApplication) {
+            Bundle coreSettings = mBoundApplication.coreSettings;
+            if (coreSettings != null) {
+                return coreSettings.getInt(key, defaultValue);
+            } else {
+                return defaultValue;
+            }
+        }
+    }
+
     public static final void main(String[] args) {
         SamplingProfilerIntegration.start();
 
diff --git a/core/java/android/app/AppGlobals.java b/core/java/android/app/AppGlobals.java
index 9a39129..55515b8 100644
--- a/core/java/android/app/AppGlobals.java
+++ b/core/java/android/app/AppGlobals.java
@@ -38,12 +38,23 @@
     public static String getInitialPackage() {
         return ActivityThread.currentPackageName();
     }
-    
+
     /**
      * Return the raw interface to the package manager.
-     * @return
+     * @return The package manager.
      */
     public static IPackageManager getPackageManager() {
         return ActivityThread.getPackageManager();
     }
+
+    /**
+     * Gets the value of an integer core setting.
+     *
+     * @param key The setting key.
+     * @param defaultValue The setting default value.
+     * @return The core settings.
+     */
+    public static int getIntCoreSetting(String key, int defaultValue) {
+        return ActivityThread.currentActivityThread().getIntCoreSetting(key, defaultValue);
+    }
 }
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index ef92933..aa26b04 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -257,10 +257,11 @@
             boolean restrictedBackupMode = (data.readInt() != 0);
             Configuration config = Configuration.CREATOR.createFromParcel(data);
             HashMap<String, IBinder> services = data.readHashMap(null);
+            Bundle coreSettings = data.readBundle();
             bindApplication(packageName, info,
                             providers, testName, profileName,
                             testArgs, testWatcher, testMode, restrictedBackupMode,
-                            config, services);
+                            config, services, coreSettings);
             return true;
         }
         
@@ -454,6 +455,13 @@
             }
             return true;
         }
+
+        case SET_CORE_SETTINGS: {
+            data.enforceInterface(IApplicationThread.descriptor);
+            Bundle settings = data.readBundle();
+            setCoreSettings(settings);
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -712,7 +720,7 @@
             List<ProviderInfo> providers, ComponentName testName,
             String profileName, Bundle testArgs, IInstrumentationWatcher testWatcher, int debugMode,
             boolean restrictedBackupMode, Configuration config,
-            Map<String, IBinder> services) throws RemoteException {
+            Map<String, IBinder> services, Bundle coreSettings) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeString(packageName);
@@ -731,6 +739,7 @@
         data.writeInt(restrictedBackupMode ? 1 : 0);
         config.writeToParcel(data, 0);
         data.writeMap(services);
+        data.writeBundle(coreSettings);
         mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null,
                 IBinder.FLAG_ONEWAY);
         data.recycle();
@@ -938,4 +947,11 @@
         mRemote.transact(DUMP_ACTIVITY_TRANSACTION, data, null, 0);
         data.recycle();
     }
+
+    public void setCoreSettings(Bundle coreSettings) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        data.writeBundle(coreSettings);
+        mRemote.transact(SET_CORE_SETTINGS, data, null, IBinder.FLAG_ONEWAY);
+    }
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 16c3c5c..55177a9 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -82,7 +82,8 @@
     void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers,
             ComponentName testName, String profileName, Bundle testArguments, 
             IInstrumentationWatcher testWatcher, int debugMode, boolean restrictedBackupMode,
-            Configuration config, Map<String, IBinder> services) throws RemoteException;
+            Configuration config, Map<String, IBinder> services,
+            Bundle coreSettings) throws RemoteException;
     void scheduleExit() throws RemoteException;
     void scheduleSuicide() throws RemoteException;
     void requestThumbnail(IBinder token) throws RemoteException;
@@ -110,6 +111,7 @@
     void scheduleCrash(String msg) throws RemoteException;
     void dumpActivity(FileDescriptor fd, IBinder servicetoken, String prefix, String[] args)
             throws RemoteException;
+    void setCoreSettings(Bundle coreSettings) throws RemoteException;
 
     String descriptor = "android.app.IApplicationThread";
 
@@ -151,4 +153,5 @@
     int DUMP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+36;
     int CLEAR_DNS_CACHE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+37;
     int SET_HTTP_PROXY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+38;
+    int SET_CORE_SETTINGS = IBinder.FIRST_CALL_TRANSACTION+39;
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1718189..6deb5a0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2698,6 +2698,12 @@
             "accessibility_web_content_key_bindings";
 
         /**
+         * The timout for considering a press to be a long press in milliseconds.
+         * @hide
+         */
+        public static final String LONG_PRESS_TIMEOUT = "long_press_timeout";
+
+        /**
          * Setting to always use the default text-to-speech settings regardless
          * of the application settings.
          * 1 = override application settings,
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index cc4e89c..d95c5b0 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -16,8 +16,11 @@
 
 package android.view;
 
+import android.app.AppGlobals;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.os.Bundle;
+import android.provider.Settings;
 import android.util.DisplayMetrics;
 import android.util.SparseArray;
 
@@ -74,7 +77,7 @@
      * Defines the duration in milliseconds before a press turns into
      * a long press
      */
-    private static final int LONG_PRESS_TIMEOUT = 500;
+    private static final int DEFAULTLONG_PRESS_TIMEOUT = 500;
     
     /**
      * Defines the duration in milliseconds a user needs to hold down the
@@ -320,15 +323,16 @@
     public static int getPressedStateDuration() {
         return PRESSED_STATE_DURATION;
     }
-    
+
     /**
      * @return the duration in milliseconds before a press turns into
      * a long press
      */
     public static int getLongPressTimeout() {
-        return LONG_PRESS_TIMEOUT;
+        return AppGlobals.getIntCoreSetting(Settings.Secure.LONG_PRESS_TIMEOUT,
+                DEFAULTLONG_PRESS_TIMEOUT);
     }
-    
+
     /**
      * @return the duration in milliseconds we will wait to see if a touch event
      * is a tap or a scroll. If the user does not move within this interval, it is