Merge change I4ff96000 into eclair-mr2

* changes:
  new gservices flag for delaying bad gmail operations
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index d1db35e..e6e26fa 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -541,6 +541,7 @@
                                               String method,
                                               HashMap headers,
                                               byte[] postData,
+                                              long postDataIdentifier,
                                               int cacheMode,
                                               boolean synchronous) {
         PerfChecker checker = new PerfChecker();
@@ -612,8 +613,9 @@
         }
 
         // Create a LoadListener
-        LoadListener loadListener = LoadListener.getLoadListener(mContext, this, url,
-                loaderHandle, synchronous, isMainFramePage);
+        LoadListener loadListener = LoadListener.getLoadListener(mContext,
+                this, url, loaderHandle, synchronous, isMainFramePage,
+                postDataIdentifier);
 
         mCallbackProxy.onLoadResource(url);
 
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index 75028de..910d7b2 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -283,16 +283,24 @@
     // only called from WebCore thread
     public static CacheResult getCacheFile(String url,
             Map<String, String> headers) {
+        return getCacheFile(url, 0, headers);
+    }
+
+    // only called from WebCore thread
+    static CacheResult getCacheFile(String url, long postIdentifier,
+            Map<String, String> headers) {
         if (mDisabled) {
             return null;
         }
 
-        CacheResult result = mDataBase.getCache(url);
+        String databaseKey = getDatabaseKey(url, postIdentifier);
+
+        CacheResult result = mDataBase.getCache(databaseKey);
         if (result != null) {
             if (result.contentLength == 0) {
                 if (!checkCacheRedirect(result.httpStatusCode)) {
                     // this should not happen. If it does, remove it.
-                    mDataBase.removeCache(url);
+                    mDataBase.removeCache(databaseKey);
                     return null;
                 }
             } else {
@@ -304,7 +312,7 @@
                 } catch (FileNotFoundException e) {
                     // the files in the cache directory can be removed by the
                     // system. If it is gone, clean up the database
-                    mDataBase.removeCache(url);
+                    mDataBase.removeCache(databaseKey);
                     return null;
                 }
             }
@@ -352,14 +360,24 @@
     // only called from WebCore thread
     public static CacheResult createCacheFile(String url, int statusCode,
             Headers headers, String mimeType, boolean forceCache) {
+        return createCacheFile(url, statusCode, headers, mimeType, 0,
+                forceCache);
+    }
+
+    // only called from WebCore thread
+    static CacheResult createCacheFile(String url, int statusCode,
+            Headers headers, String mimeType, long postIdentifier,
+            boolean forceCache) {
         if (!forceCache && mDisabled) {
             return null;
         }
 
+        String databaseKey = getDatabaseKey(url, postIdentifier);
+
         // according to the rfc 2616, the 303 response MUST NOT be cached.
         if (statusCode == 303) {
             // remove the saved cache if there is any
-            mDataBase.removeCache(url);
+            mDataBase.removeCache(databaseKey);
             return null;
         }
 
@@ -367,7 +385,7 @@
         // header.
         if (checkCacheRedirect(statusCode) && !headers.getSetCookie().isEmpty()) {
             // remove the saved cache if there is any
-            mDataBase.removeCache(url);
+            mDataBase.removeCache(databaseKey);
             return null;
         }
 
@@ -375,9 +393,9 @@
         if (ret == null) {
             // this should only happen if the headers has "no-store" in the
             // cache-control. remove the saved cache if there is any
-            mDataBase.removeCache(url);
+            mDataBase.removeCache(databaseKey);
         } else {
-            setupFiles(url, ret);
+            setupFiles(databaseKey, ret);
             try {
                 ret.outStream = new FileOutputStream(ret.outFile);
             } catch (FileNotFoundException e) {
@@ -408,6 +426,12 @@
      */
     // only called from WebCore thread
     public static void saveCacheFile(String url, CacheResult cacheRet) {
+        saveCacheFile(url, 0, cacheRet);
+    }
+
+    // only called from WebCore thread
+    static void saveCacheFile(String url, long postIdentifier,
+            CacheResult cacheRet) {
         try {
             cacheRet.outStream.close();
         } catch (IOException e) {
@@ -434,7 +458,7 @@
             return;
         }
 
-        mDataBase.addCache(url, cacheRet);
+        mDataBase.addCache(getDatabaseKey(url, postIdentifier), cacheRet);
 
         if (DebugFlags.CACHE_MANAGER) {
             Log.v(LOGTAG, "saveCacheFile for url " + url);
@@ -513,6 +537,11 @@
         }
     }
 
+    private static String getDatabaseKey(String url, long postIdentifier) {
+        if (postIdentifier == 0) return url;
+        return postIdentifier + url;
+    }
+
     @SuppressWarnings("deprecation")
     private static void setupFiles(String url, CacheResult cacheRet) {
         if (true) {
diff --git a/core/java/android/webkit/FrameLoader.java b/core/java/android/webkit/FrameLoader.java
index c1eeb3b..c3dac6e 100644
--- a/core/java/android/webkit/FrameLoader.java
+++ b/core/java/android/webkit/FrameLoader.java
@@ -242,7 +242,7 @@
             // to load POST content in a history navigation.
             case WebSettings.LOAD_CACHE_ONLY: {
                 CacheResult result = CacheManager.getCacheFile(mListener.url(),
-                        null);
+                        mListener.postIdentifier(), null);
                 if (result != null) {
                     startCacheLoad(result);
                 } else {
@@ -270,7 +270,7 @@
                 // Get the cache file name for the current URL, passing null for
                 // the validation headers causes no validation to occur
                 CacheResult result = CacheManager.getCacheFile(mListener.url(),
-                        null);
+                        mListener.postIdentifier(), null);
                 if (result != null) {
                     startCacheLoad(result);
                     return true;
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index 5c0ce3c..938df95 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -104,6 +104,7 @@
     private SslError mSslError;
     private RequestHandle mRequestHandle;
     private RequestHandle mSslErrorRequestHandle;
+    private long     mPostIdentifier;
 
     // Request data. It is only valid when we are doing a load from the
     // cache. It is needed if the cache returns a redirect
@@ -123,13 +124,13 @@
     // Public functions
     // =========================================================================
 
-    public static LoadListener getLoadListener(
-            Context context, BrowserFrame frame, String url,
-            int nativeLoader, boolean synchronous, boolean isMainPageLoader) {
+    public static LoadListener getLoadListener(Context context,
+            BrowserFrame frame, String url, int nativeLoader,
+            boolean synchronous, boolean isMainPageLoader, long postIdentifier) {
 
         sNativeLoaderCount += 1;
-        return new LoadListener(
-            context, frame, url, nativeLoader, synchronous, isMainPageLoader);
+        return new LoadListener(context, frame, url, nativeLoader, synchronous,
+                isMainPageLoader, postIdentifier);
     }
 
     public static int getNativeLoaderCount() {
@@ -137,7 +138,8 @@
     }
 
     LoadListener(Context context, BrowserFrame frame, String url,
-            int nativeLoader, boolean synchronous, boolean isMainPageLoader) {
+            int nativeLoader, boolean synchronous, boolean isMainPageLoader,
+            long postIdentifier) {
         if (DebugFlags.LOAD_LISTENER) {
             Log.v(LOGTAG, "LoadListener constructor url=" + url);
         }
@@ -150,6 +152,7 @@
             mMessageQueue = new Vector<Message>();
         }
         mIsMainPageLoader = isMainPageLoader;
+        mPostIdentifier = postIdentifier;
     }
 
     /**
@@ -408,9 +411,14 @@
                 mStatusCode == HTTP_MOVED_PERMANENTLY ||
                 mStatusCode == HTTP_TEMPORARY_REDIRECT) && 
                 mNativeLoader != 0) {
-            if (!mFromCache && mRequestHandle != null) {
+            // for POST request, only cache the result if there is an identifier
+            // associated with it. postUrl() or form submission should set the
+            // identifier while XHR POST doesn't.
+            if (!mFromCache && mRequestHandle != null
+                    && (!mRequestHandle.getMethod().equals("POST")
+                            || mPostIdentifier != 0)) {
                 mCacheResult = CacheManager.createCacheFile(mUrl, mStatusCode,
-                        headers, mMimeType, false);
+                        headers, mMimeType, mPostIdentifier, false);
             }
             if (mCacheResult != null) {
                 mCacheResult.encoding = mEncoding;
@@ -637,7 +645,7 @@
      */
     boolean checkCache(Map<String, String> headers) {
         // Get the cache file name for the current URL
-        CacheResult result = CacheManager.getCacheFile(url(),
+        CacheResult result = CacheManager.getCacheFile(url(), mPostIdentifier,
                 headers);
 
         // Go ahead and set the cache loader to null in case the result is
@@ -862,6 +870,10 @@
         }
     }
 
+    long postIdentifier() {
+        return mPostIdentifier;
+    }
+
     void attachRequestHandle(RequestHandle requestHandle) {
         if (DebugFlags.LOAD_LISTENER) {
             Log.v(LOGTAG, "LoadListener.attachRequestHandle(): " +
@@ -908,8 +920,9 @@
      * be used. This is just for forward/back navigation to a POST
      * URL.
      */
-    static boolean willLoadFromCache(String url) {
-        boolean inCache = CacheManager.getCacheFile(url, null) != null;
+    static boolean willLoadFromCache(String url, long identifier) {
+        boolean inCache =
+                CacheManager.getCacheFile(url, identifier, null) != null;
         if (DebugFlags.LOAD_LISTENER) {
             Log.v(LOGTAG, "willLoadFromCache: " + url + " in cache: " + 
                     inCache);
@@ -1066,7 +1079,7 @@
     void tearDown() {
         if (mCacheResult != null) {
             if (getErrorID() == OK) {
-                CacheManager.saveCacheFile(mUrl, mCacheResult);
+                CacheManager.saveCacheFile(mUrl, mPostIdentifier, mCacheResult);
             }
 
             // we need to reset mCacheResult to be null
@@ -1194,7 +1207,8 @@
             // Cache the redirect response
             if (mCacheResult != null) {
                 if (getErrorID() == OK) {
-                    CacheManager.saveCacheFile(mUrl, mCacheResult);
+                    CacheManager.saveCacheFile(mUrl, mPostIdentifier,
+                            mCacheResult);
                 }
                 mCacheResult = null;
             }
diff --git a/core/java/android/webkit/PluginUtil.java b/core/java/android/webkit/PluginUtil.java
index 8fdbd67..33ccf9d 100644
--- a/core/java/android/webkit/PluginUtil.java
+++ b/core/java/android/webkit/PluginUtil.java
@@ -19,9 +19,6 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.util.Log;
 
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-
 class PluginUtil {
 
     private static final String LOGTAG = "PluginUtil";
@@ -35,12 +32,7 @@
     static PluginStub getPluginStub(Context context, String packageName, 
             String className) {
         try {
-            Context pluginContext = context.createPackageContext(packageName,
-                    Context.CONTEXT_INCLUDE_CODE |
-                    Context.CONTEXT_IGNORE_SECURITY);
-            ClassLoader pluginCL = pluginContext.getClassLoader();
-
-            Class<?> stubClass = pluginCL.loadClass(className);
+            Class<?> stubClass = getPluginClass(context, packageName, className);
             Object stubObject = stubClass.newInstance();
 
             if (stubObject instanceof PluginStub) {
@@ -56,4 +48,14 @@
         }
         return null;
     }
+    
+    /* package */
+    static Class<?> getPluginClass(Context context, String packageName,
+            String className) throws NameNotFoundException, ClassNotFoundException {
+        Context pluginContext = context.createPackageContext(packageName,
+                Context.CONTEXT_INCLUDE_CODE |
+                Context.CONTEXT_IGNORE_SECURITY);
+        ClassLoader pluginCL = pluginContext.getClassLoader();
+        return pluginCL.loadClass(className);
+    }
 }
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index bfaa3535..5460a47 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.database.Cursor;
 import android.graphics.Canvas;
 import android.graphics.DrawFilter;
@@ -2167,6 +2168,32 @@
         }
     }
 
+    // called by JNI
+    private Class<?> getPluginClass(String libName, String clsName) {
+        
+        if (mWebView == null) {
+            return null;
+        }
+        
+        String pkgName = PluginManager.getInstance(null).getPluginsAPKName(libName);
+        if (pkgName == null) {
+            Log.w(LOGTAG, "Unable to resolve " + libName + " to a plugin APK");
+            return null;
+        }
+        
+        Class<?> pluginClass = null;
+        try {
+            pluginClass = PluginUtil.getPluginClass(mWebView.getContext(), pkgName, clsName);
+        } catch (NameNotFoundException e) {
+            Log.e(LOGTAG, "Unable to find plugin classloader for the apk (" + pkgName + ")");
+        } catch (ClassNotFoundException e) {
+            Log.e(LOGTAG, "Unable to find plugin class (" + clsName +
+                    ") in the apk (" + pkgName + ")");
+        }
+
+        return pluginClass;
+    }
+    
     // called by JNI. PluginWidget function to launch an activity and overlays
     // the activity with the View provided by the plugin class.
     private void startFullScreenPluginActivity(String libName, String clsName, int npp) {
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9058221..aaa1d8b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -200,6 +200,11 @@
     <integer-array name="config_autoBrightnessKeyboardBacklightValues">
     </integer-array>
 
+    <!-- Amount of time it takes for the light sensor to warm up in milliseconds.
+         For this time after the screen turns on, the Power Manager
+         will not debounce light sensor readings -->
+    <integer name="config_lightSensorWarmupTime">0</integer>
+
     <!-- Enables swipe versus poly-finger touch disambiguation in the KeyboardView -->
     <bool name="config_swipeDisambiguation">true</bool>
 </resources>
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 2e1cf56..af93d36 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -212,8 +212,12 @@
     private volatile boolean mPokeAwakeOnSet = false;
     private volatile boolean mInitComplete = false;
     private HashMap<IBinder,PokeLock> mPokeLocks = new HashMap<IBinder,PokeLock>();
+    // mScreenOnTime and mScreenOnStartTime are used for computing total time screen
+    // has been on since boot
     private long mScreenOnTime;
     private long mScreenOnStartTime;
+    // mLastScreenOnTime is the time the screen was last turned on
+    private long mLastScreenOnTime;
     private boolean mPreventScreenOn;
     private int mScreenBrightnessOverride = -1;
     private boolean mUseSoftwareAutoBrightness;
@@ -222,6 +226,7 @@
     private int[] mLcdBacklightValues;
     private int[] mButtonBacklightValues;
     private int[] mKeyboardBacklightValues;
+    private int mLightSensorWarmupTime;
 
     // Used when logging number and duration of touch-down cycles
     private long mTotalTouchDownTime;
@@ -456,6 +461,8 @@
                     com.android.internal.R.array.config_autoBrightnessButtonBacklightValues);
             mKeyboardBacklightValues = resources.getIntArray(
                     com.android.internal.R.array.config_autoBrightnessKeyboardBacklightValues);
+            mLightSensorWarmupTime = resources.getInteger(
+                    com.android.internal.R.integer.config_lightSensorWarmupTime);
         }
 
        ContentResolver resolver = mContext.getContentResolver();
@@ -886,6 +893,7 @@
         pw.println("  mPreventScreenOn=" + mPreventScreenOn
                 + "  mScreenBrightnessOverride=" + mScreenBrightnessOverride);
         pw.println("  mTotalDelaySetting=" + mTotalDelaySetting);
+        pw.println("  mLastScreenOnTime=" + mLastScreenOnTime);
         pw.println("  mBroadcastWakeLock=" + mBroadcastWakeLock);
         pw.println("  mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock);
         pw.println("  mStayOnWhilePluggedInPartialLock=" + mStayOnWhilePluggedInPartialLock);
@@ -1299,15 +1307,18 @@
 
     private int setScreenStateLocked(boolean on) {
         int err = Power.setScreenState(on);
-        if (err == 0 && mUseSoftwareAutoBrightness) {
-            enableLightSensor(on);
-            if (!on) {
-                // make sure button and key backlights are off too
-                mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, 0);
-                mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, 0);
-                // clear current value so we will update based on the new conditions
-                // when the sensor is reenabled.
-                mLightSensorValue = -1;
+        if (err == 0) {
+            mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
+            if (mUseSoftwareAutoBrightness) {
+                enableLightSensor(on);
+                if (!on) {
+                    // make sure button and key backlights are off too
+                    mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, 0);
+                    mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, 0);
+                    // clear current value so we will update based on the new conditions
+                    // when the sensor is reenabled.
+                    mLightSensorValue = -1;
+                }
             }
         }
         return err;
@@ -2431,13 +2442,15 @@
         public void onSensorChanged(SensorEvent event) {
             synchronized (mLocks) {
                 int value = (int)event.values[0];
+                long milliseconds = event.timestamp / 1000000;
                 if (mDebugLightSensor) {
                     Log.d(TAG, "onSensorChanged: light value: " + value);
                 }
                 mHandler.removeCallbacks(mAutoBrightnessTask);
                 if (mLightSensorValue != value) {
-                    if (mLightSensorValue == -1) {
-                        // process the value immediately
+                    if (mLightSensorValue == -1 ||
+                            milliseconds < mLastScreenOnTime + mLightSensorWarmupTime) {
+                        // process the value immediately if screen has just turned on
                         lightSensorChangedLocked(value);
                     } else {
                         // delay processing to debounce the sensor
diff --git a/tests/BrowserTestPlugin/jni/main.cpp b/tests/BrowserTestPlugin/jni/main.cpp
index e3ad4a7..2f295f0 100644
--- a/tests/BrowserTestPlugin/jni/main.cpp
+++ b/tests/BrowserTestPlugin/jni/main.cpp
@@ -65,7 +65,6 @@
 ANPLogInterfaceV0           gLogI;
 ANPPaintInterfaceV0         gPaintI;
 ANPPathInterfaceV0          gPathI;
-ANPSystemInterfaceV0        gSystemI;
 ANPTypefaceInterfaceV0      gTypefaceI;
 ANPWindowInterfaceV0        gWindowI;