Merge branch 'kraken' of ssh://android-git:29418/platform/frameworks/base into kraken
diff --git a/core/java/android/database/sqlite/SQLiteCompiledSql.java b/core/java/android/database/sqlite/SQLiteCompiledSql.java
index 72ceb9b..047e176 100644
--- a/core/java/android/database/sqlite/SQLiteCompiledSql.java
+++ b/core/java/android/database/sqlite/SQLiteCompiledSql.java
@@ -54,6 +54,9 @@
     private boolean mInUse = false;
 
     /* package */ SQLiteCompiledSql(SQLiteDatabase db, String sql) {
+        if (!db.isOpen()) {
+            throw new IllegalStateException("database " + db.getPath() + " already closed");
+        }
         mDatabase = db;
         mSqlStmt = sql;
         mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
@@ -75,6 +78,9 @@
      *  existing compiled SQL program already around
      */
     private void compile(String sql, boolean forceCompilation) {
+        if (!mDatabase.isOpen()) {
+            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
+        }
         // Only compile if we don't have a valid statement already or the caller has
         // explicitly requested a recompile.
         if (forceCompilation) {
@@ -90,6 +96,9 @@
     }
 
     /* package */ void releaseSqlStatement() {
+        if (!mDatabase.isOpen()) {
+            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
+        }
         // Note that native_finalize() checks to make sure that nStatement is
         // non-null before destroying it.
         if (nStatement != 0) {
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 3b7416e..70f681f 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -500,10 +500,10 @@
      * {@link #yieldIfContendedSafely}.
      */
     public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
+        lockForced();
         if (!isOpen()) {
             throw new IllegalStateException("database not open");
         }
-        lockForced();
         boolean ok = false;
         try {
             // If this thread already had the lock then get out
@@ -915,11 +915,11 @@
      * @return the database version
      */
     public int getVersion() {
+        SQLiteStatement prog = null;
+        lock();
         if (!isOpen()) {
             throw new IllegalStateException("database not open");
         }
-        SQLiteStatement prog = null;
-        lock();
         try {
             prog = new SQLiteStatement(this, "PRAGMA user_version;");
             long version = prog.simpleQueryForLong();
@@ -936,9 +936,6 @@
      * @param version the new database version
      */
     public void setVersion(int version) {
-        if (!isOpen()) {
-            throw new IllegalStateException("database not open");
-        }
         execSQL("PRAGMA user_version = " + version);
     }
 
@@ -948,11 +945,11 @@
      * @return the new maximum database size
      */
     public long getMaximumSize() {
+        SQLiteStatement prog = null;
+        lock();
         if (!isOpen()) {
             throw new IllegalStateException("database not open");
         }
-        SQLiteStatement prog = null;
-        lock();
         try {
             prog = new SQLiteStatement(this,
                     "PRAGMA max_page_count;");
@@ -972,11 +969,11 @@
      * @return the new maximum database size
      */
     public long setMaximumSize(long numBytes) {
+        SQLiteStatement prog = null;
+        lock();
         if (!isOpen()) {
             throw new IllegalStateException("database not open");
         }
-        SQLiteStatement prog = null;
-        lock();
         try {
             long pageSize = getPageSize();
             long numPages = numBytes / pageSize;
@@ -1000,11 +997,11 @@
      * @return the database page size, in bytes
      */
     public long getPageSize() {
+        SQLiteStatement prog = null;
+        lock();
         if (!isOpen()) {
             throw new IllegalStateException("database not open");
         }
-        SQLiteStatement prog = null;
-        lock();
         try {
             prog = new SQLiteStatement(this,
                     "PRAGMA page_size;");
@@ -1024,9 +1021,6 @@
      * @param numBytes the database page size, in bytes
      */
     public void setPageSize(long numBytes) {
-        if (!isOpen()) {
-            throw new IllegalStateException("database not open");
-        }
         execSQL("PRAGMA page_size = " + numBytes);
     }
 
@@ -1143,10 +1137,10 @@
      * @return a pre-compiled statement object.
      */
     public SQLiteStatement compileStatement(String sql) throws SQLException {
+        lock();
         if (!isOpen()) {
             throw new IllegalStateException("database not open");
         }
-        lock();
         try {
             return new SQLiteStatement(this, sql);
         } finally {
@@ -1586,10 +1580,10 @@
      *         whereClause.
      */
     public int delete(String table, String whereClause, String[] whereArgs) {
+        lock();
         if (!isOpen()) {
             throw new IllegalStateException("database not open");
         }
-        lock();
         SQLiteStatement statement = null;
         try {
             statement = compileStatement("DELETE FROM " + table
@@ -1641,10 +1635,6 @@
      */
     public int updateWithOnConflict(String table, ContentValues values,
             String whereClause, String[] whereArgs, int conflictAlgorithm) {
-        if (!isOpen()) {
-            throw new IllegalStateException("database not open");
-        }
-
         if (values == null || values.size() == 0) {
             throw new IllegalArgumentException("Empty values");
         }
@@ -1673,6 +1663,9 @@
         }
 
         lock();
+        if (!isOpen()) {
+            throw new IllegalStateException("database not open");
+        }
         SQLiteStatement statement = null;
         try {
             statement = compileStatement(sql.toString());
@@ -1724,11 +1717,11 @@
      * @throws SQLException If the SQL string is invalid for some reason
      */
     public void execSQL(String sql) throws SQLException {
+        long timeStart = SystemClock.uptimeMillis();
+        lock();
         if (!isOpen()) {
             throw new IllegalStateException("database not open");
         }
-        long timeStart = SystemClock.uptimeMillis();
-        lock();
         logTimeStat(mLastSqlStatement, timeStart, GET_LOCK_LOG_PREFIX);
         try {
             native_execSQL(sql);
@@ -1759,14 +1752,14 @@
      * @throws SQLException If the SQL string is invalid for some reason
      */
     public void execSQL(String sql, Object[] bindArgs) throws SQLException {
-        if (!isOpen()) {
-            throw new IllegalStateException("database not open");
-        }
         if (bindArgs == null) {
             throw new IllegalArgumentException("Empty bindArgs");
         }
         long timeStart = SystemClock.uptimeMillis();
         lock();
+        if (!isOpen()) {
+            throw new IllegalStateException("database not open");
+        }
         SQLiteStatement statement = null;
         try {
             statement = compileStatement(sql);
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 66ce3b0..5f13eb1 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -173,6 +173,9 @@
      * @param index The 1-based index to the parameter to bind null to
      */
     public void bindNull(int index) {
+        if (!mDatabase.isOpen()) {
+            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
+        }
         acquireReference();
         try {
             native_bind_null(index);
@@ -189,6 +192,9 @@
      * @param value The value to bind
      */
     public void bindLong(int index, long value) {
+        if (!mDatabase.isOpen()) {
+            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
+        }
         acquireReference();
         try {
             native_bind_long(index, value);
@@ -205,6 +211,9 @@
      * @param value The value to bind
      */
     public void bindDouble(int index, double value) {
+        if (!mDatabase.isOpen()) {
+            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
+        }
         acquireReference();
         try {
             native_bind_double(index, value);
@@ -224,6 +233,9 @@
         if (value == null) {
             throw new IllegalArgumentException("the bind value at index " + index + " is null");
         }
+        if (!mDatabase.isOpen()) {
+            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
+        }
         acquireReference();
         try {
             native_bind_string(index, value);
@@ -243,6 +255,9 @@
         if (value == null) {
             throw new IllegalArgumentException("the bind value at index " + index + " is null");
         }
+        if (!mDatabase.isOpen()) {
+            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
+        }
         acquireReference();
         try {
             native_bind_blob(index, value);
@@ -255,6 +270,9 @@
      * Clears all existing bindings. Unset bindings are treated as NULL.
      */
     public void clearBindings() {
+        if (!mDatabase.isOpen()) {
+            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
+        }
         acquireReference();
         try {
             native_clear_bindings();
@@ -267,6 +285,9 @@
      * Release this program's resources, making it invalid.
      */
     public void close() {
+        if (!mDatabase.isOpen()) {
+            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
+        }
         mDatabase.lock();
         try {
             releaseReference();
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index 7f484ff..98da414 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -44,6 +44,9 @@
      *         some reason
      */
     public void execute() {
+        if (!mDatabase.isOpen()) {
+            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
+        }
         long timeStart = SystemClock.uptimeMillis();
         mDatabase.lock();
 
@@ -67,6 +70,9 @@
      *         some reason
      */
     public long executeInsert() {
+        if (!mDatabase.isOpen()) {
+            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
+        }
         long timeStart = SystemClock.uptimeMillis();
         mDatabase.lock();
 
@@ -90,6 +96,9 @@
      * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
      */
     public long simpleQueryForLong() {
+        if (!mDatabase.isOpen()) {
+            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
+        }
         long timeStart = SystemClock.uptimeMillis();
         mDatabase.lock();
 
@@ -113,6 +122,9 @@
      * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
      */
     public String simpleQueryForString() {
+        if (!mDatabase.isOpen()) {
+            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
+        }
         long timeStart = SystemClock.uptimeMillis();
         mDatabase.lock();
 
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 7bd83e7..602eedf 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -540,10 +540,10 @@
     static final int FIND_AGAIN                         = 126;
     static final int CENTER_FIT_RECT                    = 127;
     static final int REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID = 128;
+    static final int SET_SCROLLBAR_MODES                = 129;
 
     private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
-    private static final int LAST_PACKAGE_MSG_ID
-            = REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID;
+    private static final int LAST_PACKAGE_MSG_ID = SET_SCROLLBAR_MODES;
 
     static final String[] HandlerPrivateDebugString = {
         "REMEMBER_PASSWORD", //              = 1;
@@ -586,7 +586,8 @@
         "RETURN_LABEL", //                   = 125;
         "FIND_AGAIN", //                     = 126;
         "CENTER_FIT_RECT", //                = 127;
-        "REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID" // = 128;
+        "REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID", // = 128;
+        "SET_SCROLLBAR_MODES" //             = 129;
     };
 
     // If the site doesn't use the viewport meta tag to specify the viewport,
@@ -657,6 +658,14 @@
     private static final int DRAW_EXTRAS_SELECTION = 2;
     private static final int DRAW_EXTRAS_CURSOR_RING = 3;
 
+    // keep this in sync with WebCore:ScrollbarMode in WebKit
+    private static final int SCROLLBAR_AUTO = 0;
+    private static final int SCROLLBAR_ALWAYSOFF = 1;
+    // as we auto fade scrollbar, this is ignored.
+    private static final int SCROLLBAR_ALWAYSON = 2;
+    private int mHorizontalScrollBarMode = SCROLLBAR_AUTO;
+    private int mVerticalScrollBarMode = SCROLLBAR_AUTO;
+
     // Used to match key downs and key ups
     private boolean mGotKeyDown;
 
@@ -2277,6 +2286,8 @@
     protected int computeHorizontalScrollRange() {
         if (mDrawHistory) {
             return mHistoryWidth;
+        } else if (mHorizontalScrollBarMode == SCROLLBAR_ALWAYSOFF) {
+            return computeHorizontalScrollExtent();
         } else {
             // to avoid rounding error caused unnecessary scrollbar, use floor
             return (int) Math.floor(mContentWidth * mActualScale);
@@ -2287,6 +2298,8 @@
     protected int computeVerticalScrollRange() {
         if (mDrawHistory) {
             return mHistoryHeight;
+        } else if (mVerticalScrollBarMode == SCROLLBAR_ALWAYSOFF) {
+            return computeVerticalScrollExtent();
         } else {
             // to avoid rounding error caused unnecessary scrollbar, use floor
             return (int) Math.floor(mContentHeight * mActualScale);
@@ -5024,7 +5037,9 @@
         if (settings.supportZoom()
                 && settings.getBuiltInZoomControls()
                 && !getZoomButtonsController().isVisible()
-                && mMinZoomScale < mMaxZoomScale) {
+                && mMinZoomScale < mMaxZoomScale
+                && (mHorizontalScrollBarMode != SCROLLBAR_ALWAYSOFF
+                        || mVerticalScrollBarMode != SCROLLBAR_ALWAYSOFF)) {
             mZoomButtonsController.setVisible(true);
             int count = settings.getDoubleTapToastCount();
             if (mInZoomOverview && count > 0) {
@@ -6641,6 +6656,11 @@
                     centerFitRect(r.left, r.top, r.width(), r.height());
                     break;
 
+                case SET_SCROLLBAR_MODES:
+                    mHorizontalScrollBarMode = msg.arg1;
+                    mVerticalScrollBarMode = msg.arg2;
+                    break;
+
                 default:
                     super.handleMessage(msg);
                     break;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 0175aed..4118119 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2453,6 +2453,15 @@
                 new Rect(x, y, x + width, y + height)).sendToTarget();
     }
 
+    // called by JNI
+    private void setScrollbarModes(int hMode, int vMode) {
+        if (mWebView == null) {
+            return;
+        }
+        mWebView.mPrivateHandler.obtainMessage(WebView.SET_SCROLLBAR_MODES,
+                hMode, vMode).sendToTarget();
+    }
+
     private native void nativePause();
     private native void nativeResume();
     private native void nativeFreeMemory();