RootsFragment.java revision 2036dad877336bf4d81202c334b1f2c81462bd9f
166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey/*
266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Copyright (C) 2013 The Android Open Source Project
366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey *
466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * you may not use this file except in compliance with the License.
666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * You may obtain a copy of the License at
766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey *
866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey *
1066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Unless required by applicable law or agreed to in writing, software
1166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
1266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * See the License for the specific language governing permissions and
1466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * limitations under the License.
1566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey */
1666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
1766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeypackage com.android.documentsui;
1866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
1935820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKayimport static com.android.documentsui.Shared.DEBUG;
2035820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKay
2166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.Fragment;
2266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.FragmentManager;
2366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.FragmentTransaction;
24a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport android.app.LoaderManager.LoaderCallbacks;
2566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.content.Context;
2654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport android.content.Intent;
27a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport android.content.Loader;
2854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport android.content.pm.PackageManager;
2954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport android.content.pm.ResolveInfo;
30c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkeyimport android.net.Uri;
3166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.os.Bundle;
32c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkeyimport android.provider.Settings;
334ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkeyimport android.text.TextUtils;
349fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkeyimport android.text.format.Formatter;
3535820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKayimport android.util.Log;
3666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.LayoutInflater;
3766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.View;
3866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.ViewGroup;
3966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.AdapterView;
4066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.AdapterView.OnItemClickListener;
41c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkeyimport android.widget.AdapterView.OnItemLongClickListener;
4266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.ArrayAdapter;
4366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.ImageView;
4466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.ListView;
4566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.TextView;
4666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
47ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport com.android.documentsui.model.DocumentInfo;
48ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport com.android.documentsui.model.RootInfo;
4966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
5058efce36cd1b26006e08ddd696292bf06fc34c81Steve McKayimport java.util.ArrayList;
51a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport java.util.Collection;
526efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkeyimport java.util.Collections;
53aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport java.util.Comparator;
5454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport java.util.List;
55e6585b32ea586743258a5457e2184ffc087f2d2fKenny Rootimport java.util.Objects;
5666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
5766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey/**
5866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Display list of known storage backend roots.
5966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey */
6066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeypublic class RootsFragment extends Fragment {
6166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
6235820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKay    private static final String TAG = "RootsFragment";
6335820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKay    private static final String EXTRA_INCLUDE_APPS = "includeApps";
6435820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKay
6566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    private ListView mList;
666efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private RootsAdapter mAdapter;
67a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    private LoaderCallbacks<Collection<RootInfo>> mCallbacks;
68a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
6954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
7054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey    public static void show(FragmentManager fm, Intent includeApps) {
7154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        final Bundle args = new Bundle();
7254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        args.putParcelable(EXTRA_INCLUDE_APPS, includeApps);
7354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
7466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final RootsFragment fragment = new RootsFragment();
7554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        fragment.setArguments(args);
7666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
7766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final FragmentTransaction ft = fm.beginTransaction();
7866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        ft.replace(R.id.container_roots, fragment);
7966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        ft.commitAllowingStateLoss();
8066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
8166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
8266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    public static RootsFragment get(FragmentManager fm) {
8366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        return (RootsFragment) fm.findFragmentById(R.id.container_roots);
8466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
8566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
8666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    @Override
8766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    public View onCreateView(
8866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
8966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final Context context = inflater.getContext();
9066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
9166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final View view = inflater.inflate(R.layout.fragment_roots, container, false);
922036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa        mList = (ListView) view.findViewById(R.id.roots_list);
9366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        mList.setOnItemClickListener(mItemListener);
9428c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        mList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
9566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        return view;
9666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
9766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
989fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    @Override
99a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    public void onActivityCreated(Bundle savedInstanceState) {
100a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        super.onActivityCreated(savedInstanceState);
101a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
102a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        final Context context = getActivity();
103a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        final RootsCache roots = DocumentsApplication.getRootsCache(context);
104e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay        final State state = ((BaseActivity) context).getDisplayState();
105a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
106a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        mCallbacks = new LoaderCallbacks<Collection<RootInfo>>() {
107a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            @Override
108a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            public Loader<Collection<RootInfo>> onCreateLoader(int id, Bundle args) {
109a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                return new RootsLoader(context, roots, state);
110a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            }
111a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
112a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            @Override
113a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            public void onLoadFinished(
114a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                    Loader<Collection<RootInfo>> loader, Collection<RootInfo> result) {
115a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                if (!isAdded()) return;
116a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
117a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                final Intent includeApps = getArguments().getParcelable(EXTRA_INCLUDE_APPS);
118a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
1196efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                mAdapter = new RootsAdapter(context, result, includeApps);
120a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                mList.setAdapter(mAdapter);
121a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
122a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                onCurrentRootChanged();
123a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            }
124a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
125a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            @Override
126a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            public void onLoaderReset(Loader<Collection<RootInfo>> loader) {
127a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                mAdapter = null;
128a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                mList.setAdapter(null);
129a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            }
130a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        };
131a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    }
132a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
133a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    @Override
13488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    public void onResume() {
13588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        super.onResume();
136669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        onDisplayStateChanged();
137669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey    }
1389fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
139669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey    public void onDisplayStateChanged() {
1409fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        final Context context = getActivity();
141e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay        final State state = ((BaseActivity) context).getDisplayState();
142348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey
143e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay        if (state.action == State.ACTION_GET_CONTENT) {
144c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey            mList.setOnItemLongClickListener(mItemLongClickListener);
145c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        } else {
146c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey            mList.setOnItemLongClickListener(null);
147c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey            mList.setLongClickable(false);
148c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        }
149c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey
150a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        getLoaderManager().restartLoader(2, null, mCallbacks);
15128c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey    }
15228c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey
15328c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey    public void onCurrentRootChanged() {
15428c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        if (mAdapter == null) return;
15528c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey
156e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay        final RootInfo root = ((BaseActivity) getActivity()).getCurrentRoot();
15728c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        for (int i = 0; i < mAdapter.getCount(); i++) {
15828c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            final Object item = mAdapter.getItem(i);
159a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey            if (item instanceof RootItem) {
160a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey                final RootInfo testRoot = ((RootItem) item).root;
161e6585b32ea586743258a5457e2184ffc087f2d2fKenny Root                if (Objects.equals(testRoot, root)) {
162a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey                    mList.setItemChecked(i, true);
1638e1c9637ec56fbfe313e964a5b60986c1bb092b9Aga Wronska                    mList.setSelection(i);
164a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey                    return;
165a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey                }
16628c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            }
16728c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        }
1689fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    }
1699fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
1702036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa    /**
1712036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa     * Attempts to shift focus back to the navigation drawer.
1722036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa     */
1732036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa    public void requestFocus() {
1742036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa        mList.requestFocus();
1752036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa    }
1762036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa
177c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey    private void showAppDetails(ResolveInfo ri) {
178c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
179c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        intent.setData(Uri.fromParts("package", ri.activityInfo.packageName, null));
180c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
181c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        startActivity(intent);
182c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey    }
183c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey
18466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    private OnItemClickListener mItemListener = new OnItemClickListener() {
18566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        @Override
18666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
187ef3e2cf35fbede340d5ff830b410baea8e461a94Steve McKay            Item item = mAdapter.getItem(position);
1886efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            if (item instanceof RootItem) {
189ef3e2cf35fbede340d5ff830b410baea8e461a94Steve McKay                BaseActivity activity = BaseActivity.get(RootsFragment.this);
19045f75e2a81674d792077516f13088d476c0ba510Aga Wronska                RootInfo newRoot = ((RootItem) item).root;
19145f75e2a81674d792077516f13088d476c0ba510Aga Wronska                Metrics.logRootVisited(getActivity(), newRoot);
19245f75e2a81674d792077516f13088d476c0ba510Aga Wronska                activity.onRootPicked(newRoot);
1936efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            } else if (item instanceof AppItem) {
194ef3e2cf35fbede340d5ff830b410baea8e461a94Steve McKay                DocumentsActivity activity = DocumentsActivity.get(RootsFragment.this);
195723799858a15fa316128716d9e131a681d1a51d2Ben Kwa                ResolveInfo info = ((AppItem) item).info;
196723799858a15fa316128716d9e131a681d1a51d2Ben Kwa                Metrics.logAppVisited(getActivity(), info);
197723799858a15fa316128716d9e131a681d1a51d2Ben Kwa                activity.onAppPicked(info);
19835820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKay            } else if (item instanceof SpacerItem) {
19935820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKay                if (DEBUG) Log.d(TAG, "Ignoring click on spacer item.");
20054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            } else {
20154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                throw new IllegalStateException("Unknown root: " + item);
20254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            }
20366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
20466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    };
20566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
206c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey    private OnItemLongClickListener mItemLongClickListener = new OnItemLongClickListener() {
207c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        @Override
208c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
209c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey            final Item item = mAdapter.getItem(position);
210c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey            if (item instanceof AppItem) {
211c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey                showAppDetails(((AppItem) item).info);
212c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey                return true;
213c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey            } else {
214c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey                return false;
215c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey            }
216c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        }
217c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey    };
218c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey
2196efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private static abstract class Item {
2206efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        private final int mLayoutId;
2216efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
2226efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public Item(int layoutId) {
2236efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            mLayoutId = layoutId;
22466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
22566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
2266efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public View getView(View convertView, ViewGroup parent) {
22766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            if (convertView == null) {
2286efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                convertView = LayoutInflater.from(parent.getContext())
2296efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                        .inflate(mLayoutId, parent, false);
23066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            }
2316efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            bindView(convertView);
2326efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            return convertView;
2336efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
2346efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
2356efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public abstract void bindView(View convertView);
2366efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
23766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
2386efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private static class RootItem extends Item {
2396efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public final RootInfo root;
2406efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
2416efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public RootItem(RootInfo root) {
2426efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            super(R.layout.item_root);
2436efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            this.root = root;
2446efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
2456efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
2466efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
2476efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public void bindView(View convertView) {
24866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
24966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
25066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            final TextView summary = (TextView) convertView.findViewById(android.R.id.summary);
25166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
2526efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            final Context context = convertView.getContext();
253cbce47001e15be85b084c36a64c20039a0c4a667Jeff Sharkey            icon.setImageDrawable(root.loadDrawerIcon(context));
25466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            title.setText(root.title);
25566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
2566efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            // Show available space if no summary
2576efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            String summaryText = root.summary;
2586efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            if (TextUtils.isEmpty(summaryText) && root.availableBytes >= 0) {
2599fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                summaryText = context.getString(R.string.root_available_bytes,
2609fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                        Formatter.formatFileSize(context, root.availableBytes));
2619fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            }
2629fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
2639fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            summary.setText(summaryText);
2644ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            summary.setVisibility(TextUtils.isEmpty(summaryText) ? View.GONE : View.VISIBLE);
2656efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
2666efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
26766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
2686efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private static class SpacerItem extends Item {
2696efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public SpacerItem() {
2706efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            super(R.layout.item_root_spacer);
27166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
27266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
27366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        @Override
2746efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public void bindView(View convertView) {
2756efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            // Nothing to bind
27666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
27766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
27866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
2796efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private static class AppItem extends Item {
2806efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public final ResolveInfo info;
2816efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
2826efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public AppItem(ResolveInfo info) {
2836efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            super(R.layout.item_root);
2846efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            this.info = info;
28554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        }
28654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
28754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        @Override
2886efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public void bindView(View convertView) {
28954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
29054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
29154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final TextView summary = (TextView) convertView.findViewById(android.R.id.summary);
29254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
2936efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            final PackageManager pm = convertView.getContext().getPackageManager();
29454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            icon.setImageDrawable(info.loadIcon(pm));
29554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            title.setText(info.loadLabel(pm));
29654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
29754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            // TODO: match existing summary behavior from disambig dialog
29854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            summary.setVisibility(View.GONE);
29954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        }
3006efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
30154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
3026efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private static class RootsAdapter extends ArrayAdapter<Item> {
3036efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public RootsAdapter(Context context, Collection<RootInfo> roots, Intent includeApps) {
3046efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            super(context, 0);
30554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
3060c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            final List<RootItem> libraries = new ArrayList<>();
307abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono            final List<RootItem> others = new ArrayList<>();
308abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono
309abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono            for (final RootInfo root : roots) {
310abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono                final RootItem item = new RootItem(root);
311e95c321fd991773e895e71bc415afff46236c77bBen Kwa                if (root.isLibrary()) {
3123ce95951bd173c422b8d369b4651c28e5bcc20f4Steve McKay                    if (DEBUG) Log.d(TAG, "Adding " + root + " as library.");
313abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono                    libraries.add(item);
314abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono                } else {
3153ce95951bd173c422b8d369b4651c28e5bcc20f4Steve McKay                    if (DEBUG) Log.d(TAG, "Adding " + root + " as non-library.");
316abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono                    others.add(item);
3175545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey                }
3186efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            }
3195545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey
3206efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            final RootComparator comp = new RootComparator();
3210c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            Collections.sort(libraries, comp);
322abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono            Collections.sort(others, comp);
3236efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
3240c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            addAll(libraries);
3250c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            add(new SpacerItem());
326abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono            addAll(others);
32766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
32854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            if (includeApps != null) {
32954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                final PackageManager pm = context.getPackageManager();
33054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                final List<ResolveInfo> infos = pm.queryIntentActivities(
33154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                        includeApps, PackageManager.MATCH_DEFAULT_ONLY);
33254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
33358efce36cd1b26006e08ddd696292bf06fc34c81Steve McKay                final List<AppItem> apps = new ArrayList<>();
3346efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
33554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                // Omit ourselves from the list
33654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                for (ResolveInfo info : infos) {
33754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                    if (!context.getPackageName().equals(info.activityInfo.packageName)) {
3386efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                        apps.add(new AppItem(info));
3396efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                    }
3406efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                }
3416efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
3426efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                if (apps.size() > 0) {
3436efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                    add(new SpacerItem());
3440c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa                    addAll(apps);
34554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                }
34654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            }
3476efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
34854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
3496efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
3506efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public View getView(int position, View convertView, ViewGroup parent) {
3516efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            final Item item = getItem(position);
3526efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            return item.getView(convertView, parent);
3536efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
35466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
3556efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
3566efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public boolean areAllItemsEnabled() {
3576efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            return false;
3586efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
3596efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
3606efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
3616efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public boolean isEnabled(int position) {
3626efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            return getItemViewType(position) != 1;
3636efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
3646efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
3656efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
3666efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public int getItemViewType(int position) {
3676efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            final Item item = getItem(position);
3686efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            if (item instanceof RootItem || item instanceof AppItem) {
3696efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                return 0;
3706efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            } else {
3716efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                return 1;
37254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            }
37366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
3746efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
3756efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
3766efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public int getViewTypeCount() {
3776efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            return 2;
3786efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
37966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
380aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
3810c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa    public static class RootComparator implements Comparator<RootItem> {
382aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        @Override
3830c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa        public int compare(RootItem lhs, RootItem rhs) {
3840c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            // Sort by root type, then title, then summary.
3850c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            int score = lhs.root.derivedType - rhs.root.derivedType;
386aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            if (score != 0) {
387aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey                return score;
388aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            }
3890c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            score = DocumentInfo.compareToIgnoreCaseNullable(lhs.root.title, rhs.root.title);
3900c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            if (score != 0) {
3910c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa                return score;
3920c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            }
3930c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa
3940c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            return DocumentInfo.compareToIgnoreCaseNullable(lhs.root.summary, rhs.root.summary);
395aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        }
396aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
39766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey}
398