Merge change 27032 into eclair

* changes:
  BatteryService: Specify low battery levels in resources.
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 776c923..3aaed38 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -412,10 +412,10 @@
      * Set the Bluetooth scan mode of the local Bluetooth adapter.
      * <p>The Bluetooth scan mode determines if the local adapter is
      * connectable and/or discoverable from remote Bluetooth devices.
-     * <p>For privacy reasons, it is recommended to limit the duration of time
-     * that the local adapter remains in a discoverable scan mode. For example,
-     * 2 minutes is a generous time to allow a remote Bluetooth device to
-     * initiate and complete its discovery process.
+     * <p>For privacy reasons, discoverable mode is automatically turned off
+     * after <code>duration</code> seconds. For example, 120 seconds should be
+     * enough for a remote device to initiate and complete its discovery
+     * process.
      * <p>Valid scan mode values are:
      * {@link #SCAN_MODE_NONE},
      * {@link #SCAN_MODE_CONNECTABLE},
@@ -427,17 +427,24 @@
      * </code>instead.
      *
      * @param mode valid scan mode
+     * @param duration time in seconds to apply scan mode, only used for
+     *                 {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}
      * @return     true if the scan mode was set, false otherwise
      * @hide
      */
-    public boolean setScanMode(int mode) {
+    public boolean setScanMode(int mode, int duration) {
         try {
-            return mService.setScanMode(mode);
+            return mService.setScanMode(mode, duration);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
 
     /** @hide */
+    public boolean setScanMode(int mode) {
+        return setScanMode(mode, 120);
+    }
+
+    /** @hide */
     public int getDiscoverableTimeout() {
         try {
             return mService.getDiscoverableTimeout();
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 203a61d..1bc2f96 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -35,7 +35,7 @@
     boolean setName(in String name);
 
     int getScanMode();
-    boolean setScanMode(int mode);
+    boolean setScanMode(int mode, int duration);
 
     int getDiscoverableTimeout();
     boolean setDiscoverableTimeout(int timeout);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e3fc72d..2b6313d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1416,6 +1416,7 @@
             DIM_SCREEN,
             SCREEN_OFF_TIMEOUT,
             SCREEN_BRIGHTNESS,
+            SCREEN_BRIGHTNESS_MODE,
             VIBRATE_ON,
             NOTIFICATIONS_USE_RING_VOLUME,
             MODE_RINGER,
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index de14b5b..8b9ba84 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -78,6 +78,7 @@
     private static final int MESSAGE_REGISTER_SDP_RECORDS = 1;
     private static final int MESSAGE_FINISH_DISABLE = 2;
     private static final int MESSAGE_UUID_INTENT = 3;
+    private static final int MESSAGE_DISCOVERABLE_TIMEOUT = 4;
 
     // The timeout used to sent the UUIDs Intent
     // This timeout should be greater than the page timeout
@@ -308,6 +309,15 @@
                 if (address != null)
                     sendUuidIntent(address);
                 break;
+            case MESSAGE_DISCOVERABLE_TIMEOUT:
+                int mode = msg.arg1;
+                if (isEnabled()) {
+                    // TODO: Switch back to the previous scan mode
+                    // This is ok for now, because we only use
+                    // CONNECTABLE and CONNECTABLE_DISCOVERABLE
+                    setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, -1);
+                }
+                break;
             }
         }
     };
@@ -679,23 +689,30 @@
         return setPropertyInteger("DiscoverableTimeout", timeout);
     }
 
-    public synchronized boolean setScanMode(int mode) {
+    public synchronized boolean setScanMode(int mode, int duration) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
                                                 "Need WRITE_SECURE_SETTINGS permission");
         boolean pairable = false;
         boolean discoverable = false;
+
         switch (mode) {
         case BluetoothAdapter.SCAN_MODE_NONE:
+            mHandler.removeMessages(MESSAGE_DISCOVERABLE_TIMEOUT);
             pairable = false;
             discoverable = false;
             break;
         case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
+            mHandler.removeMessages(MESSAGE_DISCOVERABLE_TIMEOUT);
             pairable = true;
             discoverable = false;
             break;
         case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
+            mHandler.removeMessages(MESSAGE_DISCOVERABLE_TIMEOUT);
             pairable = true;
             discoverable = true;
+            Message msg = mHandler.obtainMessage(MESSAGE_DISCOVERABLE_TIMEOUT);
+            mHandler.sendMessageDelayed(msg, duration * 1000);
+            if (DBG) Log.d(TAG, "BT Discoverable for " + duration + " seconds");
             break;
         default:
             Log.w(TAG, "Requested invalid scan mode " + mode);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 3ce1815..90985e0 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -3587,9 +3587,13 @@
 
         // update mMinZoomScale if the minimum zoom scale is not fixed
         if (!mMinZoomScaleFixed) {
-            mMinZoomScale = (float) getViewWidth()
+            // when change from narrow screen to wide screen, the new viewWidth
+            // can be wider than the old content width. We limit the minimum
+            // scale to 1.0f. The proper minimum scale will be calculated when
+            // the new picture shows up.
+            mMinZoomScale = Math.min(1.0f, (float) getViewWidth()
                     / (mDrawHistory ? mHistoryPicture.getWidth()
-                            : mZoomOverviewWidth);
+                            : mZoomOverviewWidth));
         }
 
         // we always force, in case our height changed, in which case we still
diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp
index 70d74d52..2532eff 100644
--- a/core/jni/android_bluetooth_BluetoothSocket.cpp
+++ b/core/jni/android_bluetooth_BluetoothSocket.cpp
@@ -402,7 +402,6 @@
     return -1;
 }
 
-/** jb must not be null. offset and offset+length must be within array */
 static jint readNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset,
         jint length) {
 #ifdef HAVE_BLUETOOTH
@@ -410,10 +409,20 @@
 
     int ret;
     jbyte *b;
+    int sz;
     struct asocket *s = get_socketData(env, obj);
 
     if (!s)
         return -1;
+    if (jb == NULL) {
+        jniThrowIOException(env, EINVAL);
+        return -1;
+    }
+    sz = env->GetArrayLength(jb);
+    if (offset < 0 || length < 0 || offset + length > sz) {
+        jniThrowIOException(env, EINVAL);
+        return -1;
+    }
 
     b = env->GetByteArrayElements(jb, NULL);
     if (b == NULL) {
@@ -436,7 +445,6 @@
     return -1;
 }
 
-/** jb must not be null. offset and offset+length must be within array */
 static jint writeNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset,
         jint length) {
 #ifdef HAVE_BLUETOOTH
@@ -444,10 +452,20 @@
 
     int ret;
     jbyte *b;
+    int sz;
     struct asocket *s = get_socketData(env, obj);
 
     if (!s)
         return -1;
+    if (jb == NULL) {
+        jniThrowIOException(env, EINVAL);
+        return -1;
+    }
+    sz = env->GetArrayLength(jb);
+    if (offset < 0 || length < 0 || offset + length > sz) {
+        jniThrowIOException(env, EINVAL);
+        return -1;
+    }
 
     b = env->GetByteArrayElements(jb, NULL);
     if (b == NULL) {
diff --git a/core/res/res/drawable-hdpi/tab_selected_bar_left_v4.9.png b/core/res/res/drawable-hdpi/tab_selected_bar_left_v4.9.png
index 109bbcd..e7a07255 100644
--- a/core/res/res/drawable-hdpi/tab_selected_bar_left_v4.9.png
+++ b/core/res/res/drawable-hdpi/tab_selected_bar_left_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected_bar_right_v4.9.png b/core/res/res/drawable-hdpi/tab_selected_bar_right_v4.9.png
index 109bbcd..e7a07255 100644
--- a/core/res/res/drawable-hdpi/tab_selected_bar_right_v4.9.png
+++ b/core/res/res/drawable-hdpi/tab_selected_bar_right_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected_v4.9.png b/core/res/res/drawable-hdpi/tab_selected_v4.9.png
index 2981ea5..77d0f344 100644
--- a/core/res/res/drawable-hdpi/tab_selected_v4.9.png
+++ b/core/res/res/drawable-hdpi/tab_selected_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_unselected_v4.9.png b/core/res/res/drawable-hdpi/tab_unselected_v4.9.png
index 7a13b8a..43b1ee5 100644
--- a/core/res/res/drawable-hdpi/tab_unselected_v4.9.png
+++ b/core/res/res/drawable-hdpi/tab_unselected_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_bar_left_v4.9.png b/core/res/res/drawable-mdpi/tab_selected_bar_left_v4.9.png
new file mode 100644
index 0000000..d14c02b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_selected_bar_left_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_bar_right_v4.9.png b/core/res/res/drawable-mdpi/tab_selected_bar_right_v4.9.png
new file mode 100644
index 0000000..d14c02b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_selected_bar_right_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_v4.9.png b/core/res/res/drawable-mdpi/tab_selected_v4.9.png
new file mode 100644
index 0000000..52cc34e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_selected_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_unselected_v4.9.png b/core/res/res/drawable-mdpi/tab_unselected_v4.9.png
new file mode 100644
index 0000000..7d0859a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_unselected_v4.9.png
Binary files differ
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 03ffc67..8180a7c 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.content.ContentValues;
+import android.os.SystemProperties;
 import android.provider.MediaStore.Audio;
 import android.provider.MediaStore.Images;
 import android.provider.MediaStore.Video;
@@ -103,7 +104,9 @@
         addFileType("WAV", FILE_TYPE_WAV, "audio/x-wav");
         addFileType("AMR", FILE_TYPE_AMR, "audio/amr");
         addFileType("AWB", FILE_TYPE_AWB, "audio/amr-wb");
-        addFileType("WMA", FILE_TYPE_WMA, "audio/x-ms-wma");    
+        if (SystemProperties.getInt("ro.media.dec.aud.wma.enabled", 0) != 0) {
+            addFileType("WMA", FILE_TYPE_WMA, "audio/x-ms-wma");
+        }
         addFileType("OGG", FILE_TYPE_OGG, "application/ogg");
         addFileType("OGA", FILE_TYPE_OGG, "application/ogg");
         addFileType("AAC", FILE_TYPE_AAC, "audio/aac");
@@ -123,8 +126,10 @@
         addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp");
         addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2");
         addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2");
-        addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv");
-        addFileType("ASF", FILE_TYPE_ASF, "video/x-ms-asf");
+        if (SystemProperties.getInt("ro.media.dec.vid.wmv.enabled", 0) != 0) {
+            addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv");
+            addFileType("ASF", FILE_TYPE_ASF, "video/x-ms-asf");
+        }
 
         addFileType("JPG", FILE_TYPE_JPEG, "image/jpeg");
         addFileType("JPEG", FILE_TYPE_JPEG, "image/jpeg");
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 77da8f1..3b91a38 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -40,16 +40,23 @@
     private Context mContext;
     private AudioManager mAudioManager;
     private IContentService mContentService;
+    private IPowerManager mPowerManager;
     private static final String[] PROVIDERS = { "gmail-ls", "calendar", "contacts" };
 
     private boolean mSilent;
     private boolean mVibrate;
+    private boolean mHasAutoBrightness;
 
     public SettingsHelper(Context context) {
         mContext = context;
         mAudioManager = (AudioManager) context
                 .getSystemService(Context.AUDIO_SERVICE);
         mContentService = ContentResolver.getContentService();
+        mPowerManager = IPowerManager.Stub.asInterface(
+                ServiceManager.getService("power"));
+
+        mHasAutoBrightness = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_automatic_brightness_available);
     }
 
     /**
@@ -64,6 +71,18 @@
     public boolean restoreValue(String name, String value) {
         if (Settings.System.SCREEN_BRIGHTNESS.equals(name)) {
             setBrightness(Integer.parseInt(value));
+        } else if (Settings.System.SCREEN_BRIGHTNESS_MODE.equals(name)) {
+            if (mHasAutoBrightness) {
+                // When setting auto-brightness, must reset the brightness afterwards
+                try {
+                    int curBrightness = Settings.System.getInt(mContext.getContentResolver(),
+                            Settings.System.SCREEN_BRIGHTNESS);
+                    setAutoBrightness(Integer.parseInt(value) != 0);
+                    setBrightness(curBrightness);
+                } catch (Settings.SettingNotFoundException e) {
+                    // no brightness setting at all?  weird.  skip this then.
+                }
+            }
         } else if (Settings.System.SOUND_EFFECTS_ENABLED.equals(name)) {
             setSoundEffects(Integer.parseInt(value) == 1);
         } else if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
@@ -73,6 +92,16 @@
         return true;
     }
 
+    private void setAutoBrightness(boolean value) {
+        if (mPowerManager != null) {
+            try {
+                mPowerManager.setAutoBrightness(value);
+            } catch (RemoteException e) {
+                // unable to reach the power manager; skip
+            }
+        }
+    }
+
     private void setGpsLocation(String value) {
         final String GPS = LocationManager.GPS_PROVIDER;
         boolean enabled =