DO NOT MERGE - Fixes account_* URI handling in BP2

 Cherry pick from master

 Bug: 3329654
 Changes the handling of account_* URI parameters to allow requests
 to distinguish between no account_* filtering and filter to the
 default account.

Change-Id: Ic633d2dcb4c04d51aabffb504a57f08f83de08cb
diff --git a/src/com/android/browser/BookmarkUtils.java b/src/com/android/browser/BookmarkUtils.java
index f261cb3..b548607 100644
--- a/src/com/android/browser/BookmarkUtils.java
+++ b/src/com/android/browser/BookmarkUtils.java
@@ -206,12 +206,10 @@
         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
         String accountType = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_TYPE, null);
         String accountName = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, null);
-        if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {
-            ub.appendQueryParameter(
-                    BrowserContract.Bookmarks.PARAM_ACCOUNT_NAME,accountName);
-            ub.appendQueryParameter(
-                    BrowserContract.Bookmarks.PARAM_ACCOUNT_TYPE, accountType);
-        }
+        ub.appendQueryParameter(
+                BrowserContract.Bookmarks.PARAM_ACCOUNT_NAME,accountName);
+        ub.appendQueryParameter(
+                BrowserContract.Bookmarks.PARAM_ACCOUNT_TYPE, accountType);
         return ub;
     }
 }
diff --git a/src/com/android/browser/Bookmarks.java b/src/com/android/browser/Bookmarks.java
index 9a5b6f0..beea489 100644
--- a/src/com/android/browser/Bookmarks.java
+++ b/src/com/android/browser/Bookmarks.java
@@ -100,8 +100,8 @@
      *  will remain in the database, but only as a history item, and not as a
      *  bookmarked site.
      *  @param context Context of the calling Activity.  This is used to make
-     *          Toast confirming that the bookmark has been removed.  If the
-     *          caller provides null, the Toast will not be shown.
+     *          Toast confirming that the bookmark has been removed and to
+     *          lookup the correct content uri.  It must not be null.
      *  @param cr The ContentResolver being used to remove the bookmark.
      *  @param url URL of the website to be removed.
      */
@@ -127,7 +127,8 @@
                     cursor.getLong(0));
             cr.delete(uri, null, null);
             if (context != null) {
-                Toast.makeText(context, R.string.removed_from_bookmarks, Toast.LENGTH_LONG).show();
+                Toast.makeText(context, R.string.removed_from_bookmarks,
+                        Toast.LENGTH_LONG).show();
             }
         } catch (IllegalStateException e) {
             Log.e(LOGTAG, "removeFromBookmarks", e);
diff --git a/src/com/android/browser/BookmarksLoader.java b/src/com/android/browser/BookmarksLoader.java
index 650c3ca..e2f8941 100644
--- a/src/com/android/browser/BookmarksLoader.java
+++ b/src/com/android/browser/BookmarksLoader.java
@@ -66,10 +66,7 @@
     }
 
     static Uri addAccount(Uri uri, String accountType, String accountName) {
-        if (!TextUtils.isEmpty(accountType) && !TextUtils.isEmpty(accountName)) {
-            return uri.buildUpon().appendQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE, accountType).
-                    appendQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME, accountName).build();
-        }
-        return uri;
+        return uri.buildUpon().appendQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE, accountType).
+                appendQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME, accountName).build();
     }
 }
diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java
index d8e8177..41d3749 100644
--- a/src/com/android/browser/BrowserHistoryPage.java
+++ b/src/com/android/browser/BrowserHistoryPage.java
@@ -126,10 +126,8 @@
         String accountType = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_TYPE, null);
         String accountName = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, null);
         Uri.Builder combinedBuilder = Combined.CONTENT_URI.buildUpon();
-        if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountName)) {
-            combinedBuilder.appendQueryParameter(BrowserContract.Bookmarks.PARAM_ACCOUNT_TYPE, accountType);
-            combinedBuilder.appendQueryParameter(BrowserContract.Bookmarks.PARAM_ACCOUNT_NAME, accountName);
-        }
+        combinedBuilder.appendQueryParameter(BrowserContract.Bookmarks.PARAM_ACCOUNT_TYPE, accountType);
+        combinedBuilder.appendQueryParameter(BrowserContract.Bookmarks.PARAM_ACCOUNT_NAME, accountName);
 
         switch (id) {
             case LOADER_HISTORY: {
diff --git a/src/com/android/browser/provider/BrowserProvider2.java b/src/com/android/browser/provider/BrowserProvider2.java
index 358ee2d..919a135 100644
--- a/src/com/android/browser/provider/BrowserProvider2.java
+++ b/src/com/android/browser/provider/BrowserProvider2.java
@@ -65,7 +65,8 @@
 public class BrowserProvider2 extends SQLiteContentProvider {
 
     static final String LEGACY_AUTHORITY = "browser";
-    static final Uri LEGACY_AUTHORITY_URI = new Uri.Builder().authority(LEGACY_AUTHORITY).build();
+    static final Uri LEGACY_AUTHORITY_URI = new Uri.Builder()
+            .authority(LEGACY_AUTHORITY).scheme("content").build();
 
     static final String TABLE_BOOKMARKS = "bookmarks";
     static final String TABLE_HISTORY = "history";
@@ -593,6 +594,33 @@
         return null;
     }
 
+    boolean isNullAccount(String account) {
+        if (account == null) return true;
+        account = account.trim();
+        return account.length() == 0 || account.equals("null");
+    }
+
+    Object[] getSelectionWithAccounts(Uri uri, String selection, String[] selectionArgs) {
+        // Look for account info
+        String accountType = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE);
+        String accountName = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME);
+        boolean hasAccounts = false;
+        if (accountType != null && accountName != null) {
+            if (!isNullAccount(accountType) && !isNullAccount(accountName)) {
+                selection = DatabaseUtils.concatenateWhere(selection,
+                        Bookmarks.ACCOUNT_TYPE + "=? AND " + Bookmarks.ACCOUNT_NAME + "=? ");
+                selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+                        new String[] { accountType, accountName });
+                hasAccounts = true;
+            } else {
+                selection = DatabaseUtils.concatenateWhere(selection,
+                        Bookmarks.ACCOUNT_NAME + " IS NULL AND " +
+                        Bookmarks.ACCOUNT_TYPE + " IS NULL");
+            }
+        }
+        return new Object[] { selection, selectionArgs, hasAccounts };
+    }
+
     @Override
     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
             String sortOrder) {
@@ -632,29 +660,14 @@
                             new String[] { Long.toString(ContentUris.parseId(uri)) });
                 }
 
-                // Look for account info
-                String accountType = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE);
-                String accountName = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME);
-                // Only add it if it isn't already in the selection
-                if (selection == null ||
-                        (!selection.contains(Bookmarks.ACCOUNT_NAME)
-                        && !selection.contains(Bookmarks.ACCOUNT_TYPE))) {
-                    if (!TextUtils.isEmpty(accountType) && !TextUtils.isEmpty(accountName)) {
-                        selection = DatabaseUtils.concatenateWhere(selection,
-                                Bookmarks.ACCOUNT_TYPE + "=? AND " + Bookmarks.ACCOUNT_NAME + "=? ");
-                        selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
-                                new String[] { accountType, accountName });
-                    } else {
-                        selection = DatabaseUtils.concatenateWhere(selection,
-                                Bookmarks.ACCOUNT_TYPE + " IS NULL AND " +
-                                Bookmarks.ACCOUNT_NAME + " IS NULL ");
-                    }
-                }
+                Object[] withAccount = getSelectionWithAccounts(uri, selection, selectionArgs);
+                selection = (String) withAccount[0];
+                selectionArgs = (String[]) withAccount[1];
+                boolean hasAccounts = (Boolean) withAccount[2];
 
                 // Set a default sort order if one isn't specified
                 if (TextUtils.isEmpty(sortOrder)) {
-                    if (!TextUtils.isEmpty(accountType)
-                            && !TextUtils.isEmpty(accountName)) {
+                    if (hasAccounts) {
                         sortOrder = DEFAULT_BOOKMARKS_SORT_ORDER_SYNC;
                     } else {
                         sortOrder = DEFAULT_BOOKMARKS_SORT_ORDER;
@@ -671,7 +684,7 @@
                 boolean useAccount = false;
                 String accountType = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE);
                 String accountName = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME);
-                if (!TextUtils.isEmpty(accountType) && !TextUtils.isEmpty(accountName)) {
+                if (!isNullAccount(accountType) && !isNullAccount(accountName)) {
                     useAccount = true;
                 }
 
@@ -805,6 +818,10 @@
                         && projection == null) {
                     projection = Browser.HISTORY_PROJECTION;
                 }
+                if (match == LEGACY) {
+                    uri = BookmarkUtils.addAccountInfo(getContext(),
+                            uri.buildUpon()).build();
+                }
                 String[] args = createCombinedQuery(uri, projection, qb);
                 if (selectionArgs == null) {
                     selectionArgs = args;
@@ -876,25 +893,22 @@
     private String[] createCombinedQuery(
             Uri uri, String[] projection, SQLiteQueryBuilder qb) {
         String[] args = null;
-        // Look for account info
-        String accountType = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE);
-        String accountName = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME);
         StringBuilder whereBuilder = new StringBuilder(128);
         whereBuilder.append(Bookmarks.IS_DELETED);
-        whereBuilder.append(" = 0 AND ");
-        if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {
-            whereBuilder.append(Bookmarks.ACCOUNT_NAME);
-            whereBuilder.append("=? AND ");
-            whereBuilder.append(Bookmarks.ACCOUNT_TYPE);
-            whereBuilder.append("=?");
-            // We use this where twice
-            args = new String[] { accountName, accountType,
-                    accountName, accountType};
-        } else {
-            whereBuilder.append(Bookmarks.ACCOUNT_NAME);
-            whereBuilder.append(" IS NULL AND ");
-            whereBuilder.append(Bookmarks.ACCOUNT_TYPE);
-            whereBuilder.append(" IS NULL");
+        whereBuilder.append(" = 0");
+        // Look for account info
+        Object[] withAccount = getSelectionWithAccounts(uri, null, null);
+        String selection = (String) withAccount[0];
+        String[] selectionArgs = (String[]) withAccount[1];
+        if (selection != null) {
+            whereBuilder.append(" AND " + selection);
+            if (selectionArgs != null) {
+                // We use the selection twice, hence we need to duplicate the args
+                args = new String[selectionArgs.length * 2];
+                System.arraycopy(selectionArgs, 0, args, 0, selectionArgs.length);
+                System.arraycopy(selectionArgs, 0, args, selectionArgs.length,
+                        selectionArgs.length);
+            }
         }
         String where = whereBuilder.toString();
         // Build the bookmark subquery for history union subquery
@@ -921,31 +935,18 @@
         return args;
     }
 
-    int deleteBookmarks(Uri uri, String selection, String[] selectionArgs,
+    int deleteBookmarks(String selection, String[] selectionArgs,
             boolean callerIsSyncAdapter) {
         //TODO cascade deletes down from folders
         final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-        // Look for account info
-        String accountType = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE);
-        String accountName = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME);
-        if (!TextUtils.isEmpty(accountType) && !TextUtils.isEmpty(accountName)) {
-            selection = DatabaseUtils.concatenateWhere(selection,
-                    Bookmarks.ACCOUNT_TYPE + "=? AND " + Bookmarks.ACCOUNT_NAME + "=? ");
-            selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
-                    new String[] { accountType, accountName });
-        } else {
-            selection = DatabaseUtils.concatenateWhere(selection,
-                    Bookmarks.ACCOUNT_TYPE + " IS NULL AND " +
-                    Bookmarks.ACCOUNT_NAME + " IS NULL ");
-        }
         if (callerIsSyncAdapter) {
             return db.delete(TABLE_BOOKMARKS, selection, selectionArgs);
         }
         ContentValues values = new ContentValues();
         values.put(Bookmarks.DATE_MODIFIED, System.currentTimeMillis());
         values.put(Bookmarks.IS_DELETED, 1);
-        return updateInTransaction(Bookmarks.CONTENT_URI, values,
-                selection, selectionArgs, callerIsSyncAdapter);
+        return updateBookmarksInTransaction(values, selection, selectionArgs,
+                callerIsSyncAdapter);
     }
 
     @Override
@@ -962,7 +963,11 @@
                 // fall through
             }
             case BOOKMARKS: {
-                int deleted = deleteBookmarks(uri, selection, selectionArgs, callerIsSyncAdapter);
+                // Look for account info
+                Object[] withAccount = getSelectionWithAccounts(uri, selection, selectionArgs);
+                selection = (String) withAccount[0];
+                selectionArgs = (String[]) withAccount[1];
+                int deleted = deleteBookmarks(selection, selectionArgs, callerIsSyncAdapter);
                 pruneImages();
                 return deleted;
             }
@@ -1027,7 +1032,7 @@
                     boolean isBookmark = c.getInt(1) != 0;
                     String url = c.getString(2);
                     if (isBookmark) {
-                        deleted += deleteBookmarks(uri, Bookmarks._ID + "=?",
+                        deleted += deleteBookmarks(Bookmarks._ID + "=?",
                                 new String[] { Long.toString(id) },
                                 callerIsSyncAdapter);
                         db.delete(TABLE_HISTORY, History.URL + "=?",
@@ -1041,7 +1046,7 @@
                 return deleted;
             }
         }
-        throw new UnsupportedOperationException("Unknown update URI " + uri);
+        throw new UnsupportedOperationException("Unknown delete URI " + uri);
     }
 
     long queryDefaultFolderId(String accountName, String accountType) {
@@ -1287,6 +1292,9 @@
                 // fall through
             }
             case BOOKMARKS: {
+                Object[] withAccount = getSelectionWithAccounts(uri, selection, selectionArgs);
+                selection = (String) withAccount[0];
+                selectionArgs = (String[]) withAccount[1];
                 int updated = updateBookmarksInTransaction(values, selection, selectionArgs,
                         callerIsSyncAdapter);
                 pruneImages();
@@ -1347,9 +1355,9 @@
             String[] selectionArgs, boolean callerIsSyncAdapter) {
         int count = 0;
         final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-        Cursor cursor = query(Bookmarks.CONTENT_URI,
+        Cursor cursor = db.query(TABLE_BOOKMARKS,
                 new String[] { Bookmarks._ID, Bookmarks.VERSION, Bookmarks.URL },
-                selection, selectionArgs, null);
+                selection, selectionArgs, null, null, null);
         try {
             String[] args = new String[1];
             // Mark the bookmark dirty if the caller isn't a sync adapter
diff --git a/src/com/android/browser/widget/BookmarkListWidgetService.java b/src/com/android/browser/widget/BookmarkListWidgetService.java
index 39751e6..4d72d41 100644
--- a/src/com/android/browser/widget/BookmarkListWidgetService.java
+++ b/src/com/android/browser/widget/BookmarkListWidgetService.java
@@ -85,7 +85,7 @@
         mUiHandler = new Handler();
         mBookmarksObserver = new BookmarksObserver(mUiHandler);
         getContentResolver().registerContentObserver(
-                BrowserContract.AUTHORITY_URI, true, mBookmarksObserver);
+                BrowserContract.Bookmarks.CONTENT_URI, true, mBookmarksObserver);
     }
 
     @Override
@@ -337,12 +337,10 @@
                 uri = BrowserContract.Bookmarks.CONTENT_URI;
                 where = Bookmarks.IS_FOLDER + " == 0";
             }
-            if (!TextUtils.isEmpty(mAccountType) && !TextUtils.isEmpty(mAccountName)) {
-                uri = uri.buildUpon()
-                        .appendQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE, mAccountType)
-                        .appendQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME, mAccountName)
-                        .build();
-            }
+            uri = uri.buildUpon()
+                    .appendQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE, mAccountType)
+                    .appendQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME, mAccountName)
+                    .build();
             Cursor c = null;
             try {
                 c = mContext.getContentResolver().query(uri, PROJECTION,