am 78bb372f: am af927234: Merge changes I7b3f4c68,I9f022a08 into klp-dev

* commit '78bb372fb70b7c383ae4ab158734666de9ce8e95':
  Rename offer() to add(), remove/hide some APIs.
  Sort order is sticky for session, back leaves.
diff --git a/api/current.txt b/api/current.txt
index d836243..4cef74f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -290,14 +290,14 @@
     field public static final deprecated int animationResolution = 16843546; // 0x101031a
     field public static final int antialias = 16843034; // 0x101011a
     field public static final int anyDensity = 16843372; // 0x101026c
-    field public static final int apduServiceBanner = 16843758; // 0x10103ee
+    field public static final int apduServiceBanner = 16843757; // 0x10103ed
     field public static final int apiKey = 16843281; // 0x1010211
     field public static final int author = 16843444; // 0x10102b4
     field public static final int authorities = 16842776; // 0x1010018
     field public static final int autoAdvanceViewId = 16843535; // 0x101030f
     field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
     field public static final int autoLink = 16842928; // 0x10100b0
-    field public static final int autoMirrored = 16843755; // 0x10103eb
+    field public static final int autoMirrored = 16843754; // 0x10103ea
     field public static final int autoStart = 16843445; // 0x10102b5
     field public static final deprecated int autoText = 16843114; // 0x101016a
     field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -394,7 +394,6 @@
     field public static final int cropToPadding = 16843043; // 0x1010123
     field public static final int cursorVisible = 16843090; // 0x1010152
     field public static final int customNavigationLayout = 16843474; // 0x10102d2
-    field public static final int customRoots = 16843754; // 0x10103ea
     field public static final int customTokens = 16843579; // 0x101033b
     field public static final int cycles = 16843220; // 0x10101d4
     field public static final int dashGap = 16843175; // 0x10101a7
@@ -847,7 +846,7 @@
     field public static final int prompt = 16843131; // 0x101017b
     field public static final int propertyName = 16843489; // 0x10102e1
     field public static final int protectionLevel = 16842761; // 0x1010009
-    field public static final int provideAssistData = 16843759; // 0x10103ef
+    field public static final int provideAssistData = 16843758; // 0x10103ee
     field public static final int publicKey = 16843686; // 0x10103a6
     field public static final int queryActionMsg = 16843227; // 0x10101db
     field public static final int queryAfterZeroResults = 16843394; // 0x1010282
@@ -872,7 +871,7 @@
     field public static final int reqKeyboardType = 16843304; // 0x1010228
     field public static final int reqNavigation = 16843306; // 0x101022a
     field public static final int reqTouchScreen = 16843303; // 0x1010227
-    field public static final int requireDeviceUnlock = 16843757; // 0x10103ed
+    field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
     field public static final int required = 16843406; // 0x101028e
     field public static final int requiredAccountType = 16843734; // 0x10103d6
     field public static final int requiredForAllUsers = 16843728; // 0x10103d0
@@ -1021,7 +1020,7 @@
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
     field public static final int supportsRtl = 16843695; // 0x10103af
-    field public static final int supportsSwitchingToNextInputMethod = 16843756; // 0x10103ec
+    field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
     field public static final int supportsUploading = 16843419; // 0x101029b
     field public static final int switchMinWidth = 16843632; // 0x1010370
     field public static final int switchPadding = 16843633; // 0x1010371
@@ -8164,7 +8163,7 @@
 
   public class MatrixCursor.RowBuilder {
     method public android.database.MatrixCursor.RowBuilder add(java.lang.Object);
-    method public android.database.MatrixCursor.RowBuilder offer(java.lang.String, java.lang.Object);
+    method public android.database.MatrixCursor.RowBuilder add(java.lang.String, java.lang.Object);
   }
 
   public class MergeCursor extends android.database.AbstractCursor {
@@ -20825,7 +20824,6 @@
     method public static android.net.Uri buildRootUri(java.lang.String, java.lang.String);
     method public static android.net.Uri buildRootsUri(java.lang.String);
     method public static android.net.Uri buildSearchDocumentsUri(java.lang.String, java.lang.String, java.lang.String);
-    method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
     method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
     method public static java.lang.String getDocumentId(android.net.Uri);
     method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
diff --git a/core/java/android/database/MatrixCursor.java b/core/java/android/database/MatrixCursor.java
index 2a0d9b9..5e107f2 100644
--- a/core/java/android/database/MatrixCursor.java
+++ b/core/java/android/database/MatrixCursor.java
@@ -186,7 +186,7 @@
      * column value at a time. This follows the same ordering as the column
      * names specified at cursor construction time.
      * <li>Column and value pairs can be offered for possible inclusion using
-     * {@link #offer(String, Object)}. If the cursor includes the given column,
+     * {@link #add(String, Object)}. If the cursor includes the given column,
      * the value will be set for that column, otherwise the value is ignored.
      * This approach is useful when matching data to a custom projection.
      * </ul>
@@ -227,7 +227,7 @@
          *
          * @return this builder to support chaining
          */
-        public RowBuilder offer(String columnName, Object value) {
+        public RowBuilder add(String columnName, Object value) {
             for (int i = 0; i < columnNames.length; i++) {
                 if (columnName.equals(columnNames[i])) {
                     data[(row * columnCount) + i] = value;
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index eaa4f78..91b3b48 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -694,6 +694,7 @@
      * @param mimeType MIME type of new document
      * @param displayName name of new document
      * @return newly created document, or {@code null} if failed
+     * @hide
      */
     public static Uri createDocument(ContentResolver resolver, Uri parentDocumentUri,
             String mimeType, String displayName) {
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a47e518..7ddf2e9 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -6128,8 +6128,4 @@
         <attr name="textView" format="reference" />
     </declare-styleable>
 
-    <declare-styleable name="DocumentsProviderInfo">
-        <attr name="customRoots" format="boolean" />
-    </declare-styleable>
-
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6c3856e..1b4a083 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2073,7 +2073,6 @@
   <public type="attr" name="vendor" />
   <public type="attr" name="category" />
   <public type="attr" name="isAsciiCapable" />
-  <public type="attr" name="customRoots" />
   <public type="attr" name="autoMirrored" />
   <public type="attr" name="supportsSwitchingToNextInputMethod" />
   <public type="attr" name="requireDeviceUnlock" />
diff --git a/core/tests/coretests/src/android/database/MatrixCursorTest.java b/core/tests/coretests/src/android/database/MatrixCursorTest.java
index fc48c17..aa805dc 100644
--- a/core/tests/coretests/src/android/database/MatrixCursorTest.java
+++ b/core/tests/coretests/src/android/database/MatrixCursorTest.java
@@ -132,18 +132,18 @@
         MatrixCursor cursor = newMatrixCursor();
 
         cursor.newRow()
-                .offer("float", 4.2f)
-                .offer("string", "foobar")
-                .offer("blob", new byte[] {(byte) 0xaa, (byte) 0x55})
-                .offer("lolwat", "kittens");
+                .add("float", 4.2f)
+                .add("string", "foobar")
+                .add("blob", new byte[] {(byte) 0xaa, (byte) 0x55})
+                .add("lolwat", "kittens");
 
         cursor.newRow();
 
         cursor.newRow()
-                .offer("string", "zero")
-                .offer("string", "one")
-                .offer("string", "two")
-                .offer("lolwat", "kittens");
+                .add("string", "zero")
+                .add("string", "one")
+                .add("string", "two")
+                .add("lolwat", "kittens");
 
         assertTrue(cursor.moveToFirst());
         assertEquals("foobar", cursor.getString(0));
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index f9ac3f3..45f028d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -31,6 +31,7 @@
 import android.app.FragmentTransaction;
 import android.app.LoaderManager.LoaderCallbacks;
 import android.content.ContentResolver;
+import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.Loader;
@@ -65,6 +66,7 @@
 import android.widget.Toast;
 
 import com.android.documentsui.DocumentsActivity.State;
+import com.android.documentsui.RecentsProvider.StateColumns;
 import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.model.RootInfo;
 import com.android.internal.util.Predicate;
@@ -190,11 +192,13 @@
                     case TYPE_NORMAL:
                         contentsUri = DocumentsContract.buildChildDocumentsUri(
                                 doc.authority, doc.documentId);
-                        return new DirectoryLoader(context, root, doc, contentsUri);
+                        return new DirectoryLoader(
+                                context, root, doc, contentsUri, state.userSortOrder);
                     case TYPE_SEARCH:
                         contentsUri = DocumentsContract.buildSearchDocumentsUri(
                                 doc.authority, doc.documentId, query);
-                        return new DirectoryLoader(context, root, doc, contentsUri);
+                        return new DirectoryLoader(
+                                context, root, doc, contentsUri, state.userSortOrder);
                     case TYPE_RECENT_OPEN:
                         final RootsCache roots = DocumentsApplication.getRootsCache(context);
                         final List<RootInfo> matchingRoots = roots.getMatchingRoots(state);
@@ -212,14 +216,14 @@
 
                 // Push latest state up to UI
                 // TODO: if mode change was racing with us, don't overwrite it
-                state.mode = result.mode;
-                state.sortOrder = result.sortOrder;
+                state.derivedMode = result.mode;
+                state.derivedSortOrder = result.sortOrder;
                 ((DocumentsActivity) context).onStateChanged();
 
                 updateDisplayState();
 
-                if (mLastSortOrder != result.sortOrder) {
-                    mLastSortOrder = result.sortOrder;
+                if (mLastSortOrder != state.derivedSortOrder) {
+                    mLastSortOrder = state.derivedSortOrder;
                     mListView.smoothScrollToPosition(0);
                     mGridView.smoothScrollToPosition(0);
                 }
@@ -244,12 +248,36 @@
     }
 
     public void onUserSortOrderChanged() {
-        // User change always triggers reload
+        // Sort order change always triggers reload; we'll trigger state change
+        // on the flip side.
         getLoaderManager().restartLoader(mLoaderId, null, mCallbacks);
     }
 
     public void onUserModeChanged() {
-        // Mode change is just display; no need to reload
+        final ContentResolver resolver = getActivity().getContentResolver();
+        final State state = getDisplayState(this);
+
+        final RootInfo root = getArguments().getParcelable(EXTRA_ROOT);
+        final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC);
+
+        final Uri stateUri = RecentsProvider.buildState(
+                root.authority, root.rootId, doc.documentId);
+        final ContentValues values = new ContentValues();
+        values.put(StateColumns.MODE, state.userMode);
+
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                resolver.insert(stateUri, values);
+                return null;
+            }
+        }.execute();
+
+        // Mode change is just visual change; no need to kick loader, and
+        // deliver change event immediately.
+        state.derivedMode = state.userMode;
+        ((DocumentsActivity) getActivity()).onStateChanged();
+
         updateDisplayState();
     }
 
@@ -258,11 +286,11 @@
 
         mFilter = new MimePredicate(state.acceptMimes);
 
-        if (mLastMode == state.mode) return;
-        mLastMode = state.mode;
+        if (mLastMode == state.derivedMode) return;
+        mLastMode = state.derivedMode;
 
-        mListView.setVisibility(state.mode == MODE_LIST ? View.VISIBLE : View.GONE);
-        mGridView.setVisibility(state.mode == MODE_GRID ? View.VISIBLE : View.GONE);
+        mListView.setVisibility(state.derivedMode == MODE_LIST ? View.VISIBLE : View.GONE);
+        mGridView.setVisibility(state.derivedMode == MODE_GRID ? View.VISIBLE : View.GONE);
 
         final int choiceMode;
         if (state.allowMultiple) {
@@ -272,7 +300,7 @@
         }
 
         final int thumbSize;
-        if (state.mode == MODE_GRID) {
+        if (state.derivedMode == MODE_GRID) {
             thumbSize = getResources().getDimensionPixelSize(R.dimen.grid_width);
             mListView.setAdapter(null);
             mListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
@@ -281,7 +309,7 @@
             mGridView.setNumColumns(GridView.AUTO_FIT);
             mGridView.setChoiceMode(choiceMode);
             mCurrentView = mGridView;
-        } else if (state.mode == MODE_LIST) {
+        } else if (state.derivedMode == MODE_LIST) {
             thumbSize = getResources().getDimensionPixelSize(R.dimen.icon_size);
             mGridView.setAdapter(null);
             mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE);
@@ -289,7 +317,7 @@
             mListView.setChoiceMode(choiceMode);
             mCurrentView = mListView;
         } else {
-            throw new IllegalStateException("Unknown state " + state.mode);
+            throw new IllegalStateException("Unknown state " + state.derivedMode);
         }
 
         mThumbSize = new Point(thumbSize, thumbSize);
@@ -505,9 +533,9 @@
 
             if (convertView == null) {
                 final LayoutInflater inflater = LayoutInflater.from(context);
-                if (state.mode == MODE_LIST) {
+                if (state.derivedMode == MODE_LIST) {
                     convertView = inflater.inflate(R.layout.item_message_list, parent, false);
-                } else if (state.mode == MODE_GRID) {
+                } else if (state.derivedMode == MODE_GRID) {
                     convertView = inflater.inflate(R.layout.item_message_grid, parent, false);
                 } else {
                     throw new IllegalStateException();
@@ -582,9 +610,9 @@
 
             if (convertView == null) {
                 final LayoutInflater inflater = LayoutInflater.from(context);
-                if (state.mode == MODE_LIST) {
+                if (state.derivedMode == MODE_LIST) {
                     convertView = inflater.inflate(R.layout.item_doc_list, parent, false);
-                } else if (state.mode == MODE_GRID) {
+                } else if (state.derivedMode == MODE_GRID) {
                     convertView = inflater.inflate(R.layout.item_doc_grid, parent, false);
                 } else {
                     throw new IllegalStateException();
@@ -618,7 +646,7 @@
             }
 
             final boolean supportsThumbnail = (docFlags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
-            final boolean allowThumbnail = (state.mode == MODE_GRID)
+            final boolean allowThumbnail = (state.derivedMode == MODE_GRID)
                     || MimePredicate.mimeMatches(LIST_THUMBNAIL_MIMES, docMimeType);
 
             if (supportsThumbnail && allowThumbnail) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index 72dfa30..1471836 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -65,15 +65,18 @@
     private final RootInfo mRoot;
     private final DocumentInfo mDoc;
     private final Uri mUri;
+    private final int mUserSortOrder;
 
     private CancellationSignal mSignal;
     private DirectoryResult mResult;
 
-    public DirectoryLoader(Context context, RootInfo root, DocumentInfo doc, Uri uri) {
+    public DirectoryLoader(
+            Context context, RootInfo root, DocumentInfo doc, Uri uri, int userSortOrder) {
         super(context);
         mRoot = root;
         mDoc = doc;
         mUri = uri;
+        mUserSortOrder = userSortOrder;
     }
 
     @Override
@@ -91,7 +94,6 @@
         final DirectoryResult result = new DirectoryResult();
 
         int userMode = State.MODE_UNKNOWN;
-        int userSortOrder = State.SORT_ORDER_UNKNOWN;
 
         // Pick up any custom modes requested by user
         Cursor cursor = null;
@@ -101,7 +103,6 @@
             cursor = resolver.query(stateUri, null, null, null, null);
             if (cursor.moveToFirst()) {
                 userMode = getCursorInt(cursor, StateColumns.MODE);
-                userSortOrder = getCursorInt(cursor, StateColumns.SORT_ORDER);
             }
         } finally {
             IoUtils.closeQuietly(cursor);
@@ -117,8 +118,8 @@
             }
         }
 
-        if (userSortOrder != State.SORT_ORDER_UNKNOWN) {
-            result.sortOrder = userSortOrder;
+        if (mUserSortOrder != State.SORT_ORDER_UNKNOWN) {
+            result.sortOrder = mUserSortOrder;
         } else {
             if ((mDoc.flags & Document.FLAG_DIR_PREFERS_LAST_MODIFIED) != 0) {
                 result.sortOrder = State.SORT_ORDER_LAST_MODIFIED;
@@ -127,7 +128,7 @@
             }
         }
 
-        Log.d(TAG, "userMode=" + userMode + ", userSortOrder=" + userSortOrder + " --> mode="
+        Log.d(TAG, "userMode=" + userMode + ", userSortOrder=" + mUserSortOrder + " --> mode="
                 + result.mode + ", sortOrder=" + result.sortOrder);
 
         try {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index fe39800..79d2443 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -171,10 +171,6 @@
         mState.showAdvanced = SettingsActivity.getDisplayAdvancedDevices(this);
 
         if (mState.action == ACTION_MANAGE) {
-            mState.sortOrder = SORT_ORDER_LAST_MODIFIED;
-        }
-
-        if (mState.action == ACTION_MANAGE) {
             final Uri uri = intent.getData();
             final String rootId = DocumentsContract.getRootId(uri);
             final RootInfo root = mRoots.getRoot(uri.getAuthority(), rootId);
@@ -348,8 +344,8 @@
 
         if (cwd != null) {
             sort.setVisible(true);
-            grid.setVisible(mState.mode != MODE_GRID);
-            list.setVisible(mState.mode != MODE_LIST);
+            grid.setVisible(mState.derivedMode != MODE_GRID);
+            list.setVisible(mState.derivedMode != MODE_LIST);
         } else {
             sort.setVisible(false);
             grid.setVisible(false);
@@ -433,42 +429,25 @@
      * Set state sort order based on explicit user action.
      */
     private void setUserSortOrder(int sortOrder) {
-        final RootInfo root = getCurrentRoot();
-        final DocumentInfo cwd = getCurrentDirectory();
-
-        // TODO: persist async, then trigger rebind
-        final Uri stateUri = RecentsProvider.buildState(
-                root.authority, root.rootId, cwd.documentId);
-        final ContentValues values = new ContentValues();
-        values.put(StateColumns.SORT_ORDER, sortOrder);
-        getContentResolver().insert(stateUri, values);
-
+        mState.userSortOrder = sortOrder;
         DirectoryFragment.get(getFragmentManager()).onUserSortOrderChanged();
-        onStateChanged();
     }
 
     /**
      * Set state mode based on explicit user action.
      */
     private void setUserMode(int mode) {
-        final RootInfo root = getCurrentRoot();
-        final DocumentInfo cwd = getCurrentDirectory();
-
-        // TODO: persist async, then trigger rebind
-        final Uri stateUri = RecentsProvider.buildState(
-                root.authority, root.rootId, cwd.documentId);
-        final ContentValues values = new ContentValues();
-        values.put(StateColumns.MODE, mode);
-        getContentResolver().insert(stateUri, values);
-
-        mState.mode = mode;
-
+        mState.userMode = mode;
         DirectoryFragment.get(getFragmentManager()).onUserModeChanged();
-        onStateChanged();
     }
 
     @Override
     public void onBackPressed() {
+        if (!mState.stackTouched) {
+            super.onBackPressed();
+            return;
+        }
+
         final int size = mState.stack.size();
         if (size > 1) {
             mState.stack.pop();
@@ -564,6 +543,7 @@
             }
 
             while (mState.stack.size() > itemPosition + 1) {
+                mState.stackTouched = true;
                 mState.stack.pop();
             }
             onCurrentDirectoryChanged();
@@ -629,6 +609,7 @@
 
     public void onStackPicked(DocumentStack stack) {
         mState.stack = stack;
+        mState.stackTouched = true;
         onCurrentDirectoryChanged();
     }
 
@@ -636,6 +617,7 @@
         // Clear entire backstack and start in new root
         mState.stack.root = root;
         mState.stack.clear();
+        mState.stackTouched = true;
 
         if (!mRoots.isRecentsRoot(root)) {
             try {
@@ -664,13 +646,8 @@
     public void onDocumentPicked(DocumentInfo doc) {
         final FragmentManager fm = getFragmentManager();
         if (doc.isDirectory()) {
-            // TODO: query display mode user preference for this dir
-            if (doc.isGridPreferred()) {
-                mState.mode = MODE_GRID;
-            } else {
-                mState.mode = MODE_LIST;
-            }
             mState.stack.push(doc);
+            mState.stackTouched = true;
             onCurrentDirectoryChanged();
         } else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
             // Explicit file picked, return
@@ -774,13 +751,23 @@
 
     public static class State implements android.os.Parcelable {
         public int action;
-        public int mode = MODE_LIST;
         public String[] acceptMimes;
-        public int sortOrder = SORT_ORDER_DISPLAY_NAME;
+
+        /** Explicit user choice */
+        public int userMode = MODE_UNKNOWN;
+        /** Derived after loader */
+        public int derivedMode = MODE_LIST;
+
+        /** Explicit user choice */
+        public int userSortOrder = SORT_ORDER_UNKNOWN;
+        /** Derived after loader */
+        public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME;
+
         public boolean allowMultiple = false;
         public boolean showSize = false;
         public boolean localOnly = false;
         public boolean showAdvanced = false;
+        public boolean stackTouched = false;
 
         /** Current user navigation stack; empty implies recents. */
         public DocumentStack stack = new DocumentStack();
@@ -809,13 +796,14 @@
         @Override
         public void writeToParcel(Parcel out, int flags) {
             out.writeInt(action);
-            out.writeInt(mode);
+            out.writeInt(userMode);
             out.writeStringArray(acceptMimes);
-            out.writeInt(sortOrder);
+            out.writeInt(userSortOrder);
             out.writeInt(allowMultiple ? 1 : 0);
             out.writeInt(showSize ? 1 : 0);
             out.writeInt(localOnly ? 1 : 0);
             out.writeInt(showAdvanced ? 1 : 0);
+            out.writeInt(stackTouched ? 1 : 0);
             DurableUtils.writeToParcel(out, stack);
             out.writeString(currentSearch);
         }
@@ -825,13 +813,14 @@
             public State createFromParcel(Parcel in) {
                 final State state = new State();
                 state.action = in.readInt();
-                state.mode = in.readInt();
+                state.userMode = in.readInt();
                 state.acceptMimes = in.readStringArray();
-                state.sortOrder = in.readInt();
+                state.userSortOrder = in.readInt();
                 state.allowMultiple = in.readInt() != 0;
                 state.showSize = in.readInt() != 0;
                 state.localOnly = in.readInt() != 0;
                 state.showAdvanced = in.readInt() != 0;
+                state.stackTouched = in.readInt() != 0;
                 DurableUtils.readFromParcel(in, state.stack);
                 state.currentSearch = in.readString();
                 return state;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index 8530a9f..adf4701 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -90,7 +90,6 @@
             if (info.metaData != null && info.metaData.containsKey(
                     DocumentsContract.META_DATA_DOCUMENT_PROVIDER)) {
 
-                // TODO: remove deprecated customRoots flag
                 // TODO: populate roots on background thread, and cache results
                 final Uri rootsUri = DocumentsContract.buildRootsUri(info.authority);
                 final ContentProviderClient client = resolver
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 226d635..2326ec2 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -181,12 +181,12 @@
         }
 
         final RowBuilder row = result.newRow();
-        row.offer(Document.COLUMN_DOCUMENT_ID, docId);
-        row.offer(Document.COLUMN_DISPLAY_NAME, displayName);
-        row.offer(Document.COLUMN_SIZE, file.length());
-        row.offer(Document.COLUMN_MIME_TYPE, mimeType);
-        row.offer(Document.COLUMN_LAST_MODIFIED, file.lastModified());
-        row.offer(Document.COLUMN_FLAGS, flags);
+        row.add(Document.COLUMN_DOCUMENT_ID, docId);
+        row.add(Document.COLUMN_DISPLAY_NAME, displayName);
+        row.add(Document.COLUMN_SIZE, file.length());
+        row.add(Document.COLUMN_MIME_TYPE, mimeType);
+        row.add(Document.COLUMN_LAST_MODIFIED, file.lastModified());
+        row.add(Document.COLUMN_FLAGS, flags);
     }
 
     @Override
@@ -197,13 +197,13 @@
             final File path = mIdToPath.get(rootId);
 
             final RowBuilder row = result.newRow();
-            row.offer(Root.COLUMN_ROOT_ID, root.rootId);
-            row.offer(Root.COLUMN_ROOT_TYPE, root.rootType);
-            row.offer(Root.COLUMN_FLAGS, root.flags);
-            row.offer(Root.COLUMN_ICON, root.icon);
-            row.offer(Root.COLUMN_TITLE, root.title);
-            row.offer(Root.COLUMN_DOCUMENT_ID, root.docId);
-            row.offer(Root.COLUMN_AVAILABLE_BYTES, path.getFreeSpace());
+            row.add(Root.COLUMN_ROOT_ID, root.rootId);
+            row.add(Root.COLUMN_ROOT_TYPE, root.rootType);
+            row.add(Root.COLUMN_FLAGS, root.flags);
+            row.add(Root.COLUMN_ICON, root.icon);
+            row.add(Root.COLUMN_TITLE, root.title);
+            row.add(Root.COLUMN_DOCUMENT_ID, root.docId);
+            row.add(Root.COLUMN_AVAILABLE_BYTES, path.getFreeSpace());
         }
         return result;
     }
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java
index 93db592..014c664 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java
@@ -69,13 +69,13 @@
 
         final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
         final RowBuilder row = result.newRow();
-        row.offer(Root.COLUMN_ROOT_ID, MY_ROOT_ID);
-        row.offer(Root.COLUMN_ROOT_TYPE, Root.ROOT_TYPE_SERVICE);
-        row.offer(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_RECENTS);
-        row.offer(Root.COLUMN_TITLE, "_Test title which is really long");
-        row.offer(Root.COLUMN_SUMMARY, "_Summary which is also super long text");
-        row.offer(Root.COLUMN_DOCUMENT_ID, MY_DOC_ID);
-        row.offer(Root.COLUMN_AVAILABLE_BYTES, 1024);
+        row.add(Root.COLUMN_ROOT_ID, MY_ROOT_ID);
+        row.add(Root.COLUMN_ROOT_TYPE, Root.ROOT_TYPE_SERVICE);
+        row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_RECENTS);
+        row.add(Root.COLUMN_TITLE, "_Test title which is really long");
+        row.add(Root.COLUMN_SUMMARY, "_Summary which is also super long text");
+        row.add(Root.COLUMN_DOCUMENT_ID, MY_DOC_ID);
+        row.add(Root.COLUMN_AVAILABLE_BYTES, 1024);
         return result;
     }
 
@@ -234,16 +234,16 @@
 
     private static void includeFile(MatrixCursor result, String docId) {
         final RowBuilder row = result.newRow();
-        row.offer(Document.COLUMN_DOCUMENT_ID, docId);
-        row.offer(Document.COLUMN_DISPLAY_NAME, docId);
-        row.offer(Document.COLUMN_LAST_MODIFIED, System.currentTimeMillis());
+        row.add(Document.COLUMN_DOCUMENT_ID, docId);
+        row.add(Document.COLUMN_DISPLAY_NAME, docId);
+        row.add(Document.COLUMN_LAST_MODIFIED, System.currentTimeMillis());
 
         if (MY_DOC_ID.equals(docId)) {
-            row.offer(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
+            row.add(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
         } else if (MY_DOC_NULL.equals(docId)) {
             // No MIME type
         } else {
-            row.offer(Document.COLUMN_MIME_TYPE, "application/octet-stream");
+            row.add(Document.COLUMN_MIME_TYPE, "application/octet-stream");
         }
     }
 }