RootsFragment.java revision abf397458dca89fd3df4234d547a94bf0487033d
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
1966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.Fragment;
2066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.FragmentManager;
2166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.FragmentTransaction;
22a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport android.app.LoaderManager.LoaderCallbacks;
2366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.content.Context;
2454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport android.content.Intent;
25a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport android.content.Loader;
2654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport android.content.pm.PackageManager;
2754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport android.content.pm.ResolveInfo;
28c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkeyimport android.net.Uri;
2966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.os.Bundle;
30c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkeyimport android.provider.Settings;
314ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkeyimport android.text.TextUtils;
329fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkeyimport android.text.format.Formatter;
3366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.LayoutInflater;
3466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.View;
3566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.ViewGroup;
3666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.AdapterView;
3766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.AdapterView.OnItemClickListener;
38c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkeyimport android.widget.AdapterView.OnItemLongClickListener;
3966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.ArrayAdapter;
4066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.ImageView;
4166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.ListView;
4266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.TextView;
4366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
44ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport com.android.documentsui.model.DocumentInfo;
45ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport com.android.documentsui.model.RootInfo;
4666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
4758efce36cd1b26006e08ddd696292bf06fc34c81Steve McKayimport java.util.ArrayList;
48a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport java.util.Collection;
496efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkeyimport java.util.Collections;
50aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport java.util.Comparator;
5154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport java.util.List;
52e6585b32ea586743258a5457e2184ffc087f2d2fKenny Rootimport java.util.Objects;
5366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
5466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey/**
5566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Display list of known storage backend roots.
5666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey */
5766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeypublic class RootsFragment extends Fragment {
5866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
5966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    private ListView mList;
606efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private RootsAdapter mAdapter;
6166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
62a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    private LoaderCallbacks<Collection<RootInfo>> mCallbacks;
63a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
6454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey    private static final String EXTRA_INCLUDE_APPS = "includeApps";
6554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
6654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey    public static void show(FragmentManager fm, Intent includeApps) {
6754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        final Bundle args = new Bundle();
6854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        args.putParcelable(EXTRA_INCLUDE_APPS, includeApps);
6954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
7066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final RootsFragment fragment = new RootsFragment();
7154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        fragment.setArguments(args);
7266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
7366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final FragmentTransaction ft = fm.beginTransaction();
7466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        ft.replace(R.id.container_roots, fragment);
7566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        ft.commitAllowingStateLoss();
7666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
7766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
7866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    public static RootsFragment get(FragmentManager fm) {
7966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        return (RootsFragment) fm.findFragmentById(R.id.container_roots);
8066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
8166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
8266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    @Override
8366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    public View onCreateView(
8466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
8566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final Context context = inflater.getContext();
8666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
8766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final View view = inflater.inflate(R.layout.fragment_roots, container, false);
8866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        mList = (ListView) view.findViewById(android.R.id.list);
8966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        mList.setOnItemClickListener(mItemListener);
9028c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        mList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
9166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
9266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        return view;
9366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
9466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
959fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    @Override
96a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    public void onActivityCreated(Bundle savedInstanceState) {
97a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        super.onActivityCreated(savedInstanceState);
98a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
99a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        final Context context = getActivity();
100a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        final RootsCache roots = DocumentsApplication.getRootsCache(context);
101e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay        final State state = ((BaseActivity) context).getDisplayState();
102a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
103a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        mCallbacks = new LoaderCallbacks<Collection<RootInfo>>() {
104a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            @Override
105a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            public Loader<Collection<RootInfo>> onCreateLoader(int id, Bundle args) {
106a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                return new RootsLoader(context, roots, state);
107a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            }
108a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
109a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            @Override
110a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            public void onLoadFinished(
111a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                    Loader<Collection<RootInfo>> loader, Collection<RootInfo> result) {
112a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                if (!isAdded()) return;
113a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
114a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                final Intent includeApps = getArguments().getParcelable(EXTRA_INCLUDE_APPS);
115a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
1166efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                mAdapter = new RootsAdapter(context, result, includeApps);
117a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                mList.setAdapter(mAdapter);
118a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
119a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                onCurrentRootChanged();
120a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            }
121a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
122a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            @Override
123a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            public void onLoaderReset(Loader<Collection<RootInfo>> loader) {
124a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                mAdapter = null;
125a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                mList.setAdapter(null);
126a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            }
127a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        };
128a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    }
129a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
130a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    @Override
13188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    public void onResume() {
13288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        super.onResume();
133669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        onDisplayStateChanged();
134669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey    }
1359fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
136669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey    public void onDisplayStateChanged() {
1379fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        final Context context = getActivity();
138e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay        final State state = ((BaseActivity) context).getDisplayState();
139348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey
140e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay        if (state.action == State.ACTION_GET_CONTENT) {
141c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey            mList.setOnItemLongClickListener(mItemLongClickListener);
142c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        } else {
143c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey            mList.setOnItemLongClickListener(null);
144c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey            mList.setLongClickable(false);
145c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        }
146c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey
147a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        getLoaderManager().restartLoader(2, null, mCallbacks);
14828c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey    }
14928c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey
15028c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey    public void onCurrentRootChanged() {
15128c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        if (mAdapter == null) return;
15228c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey
153e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay        final RootInfo root = ((BaseActivity) getActivity()).getCurrentRoot();
15428c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        for (int i = 0; i < mAdapter.getCount(); i++) {
15528c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            final Object item = mAdapter.getItem(i);
156a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey            if (item instanceof RootItem) {
157a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey                final RootInfo testRoot = ((RootItem) item).root;
158e6585b32ea586743258a5457e2184ffc087f2d2fKenny Root                if (Objects.equals(testRoot, root)) {
159a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey                    mList.setItemChecked(i, true);
160a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey                    return;
161a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey                }
16228c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            }
16328c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        }
1649fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    }
1659fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
166c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey    private void showAppDetails(ResolveInfo ri) {
167c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
168c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        intent.setData(Uri.fromParts("package", ri.activityInfo.packageName, null));
169c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
170c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        startActivity(intent);
171c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey    }
172c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey
17366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    private OnItemClickListener mItemListener = new OnItemClickListener() {
17466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        @Override
17566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
176ef3e2cf35fbede340d5ff830b410baea8e461a94Steve McKay            Item item = mAdapter.getItem(position);
1776efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            if (item instanceof RootItem) {
178ef3e2cf35fbede340d5ff830b410baea8e461a94Steve McKay                BaseActivity activity = BaseActivity.get(RootsFragment.this);
179ef3e2cf35fbede340d5ff830b410baea8e461a94Steve McKay                activity.onRootPicked(((RootItem) item).root);
1806efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            } else if (item instanceof AppItem) {
181ef3e2cf35fbede340d5ff830b410baea8e461a94Steve McKay                DocumentsActivity activity = DocumentsActivity.get(RootsFragment.this);
1826efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                activity.onAppPicked(((AppItem) item).info);
18354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            } else {
18454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                throw new IllegalStateException("Unknown root: " + item);
18554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            }
18666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
18766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    };
18866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
189c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey    private OnItemLongClickListener mItemLongClickListener = new OnItemLongClickListener() {
190c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        @Override
191c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
192c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey            final Item item = mAdapter.getItem(position);
193c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey            if (item instanceof AppItem) {
194c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey                showAppDetails(((AppItem) item).info);
195c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey                return true;
196c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey            } else {
197c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey                return false;
198c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey            }
199c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey        }
200c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey    };
201c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey
2026efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private static abstract class Item {
2036efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        private final int mLayoutId;
2046efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
2056efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public Item(int layoutId) {
2066efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            mLayoutId = layoutId;
20766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
20866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
2096efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public View getView(View convertView, ViewGroup parent) {
21066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            if (convertView == null) {
2116efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                convertView = LayoutInflater.from(parent.getContext())
2126efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                        .inflate(mLayoutId, parent, false);
21366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            }
2146efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            bindView(convertView);
2156efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            return convertView;
2166efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
2176efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
2186efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public abstract void bindView(View convertView);
2196efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
22066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
2216efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private static class RootItem extends Item {
2226efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public final RootInfo root;
2236efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
2246efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public RootItem(RootInfo root) {
2256efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            super(R.layout.item_root);
2266efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            this.root = root;
2276efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
2286efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
2296efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
2306efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public void bindView(View convertView) {
23166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
23266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
23366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            final TextView summary = (TextView) convertView.findViewById(android.R.id.summary);
23466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
2356efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            final Context context = convertView.getContext();
236cbce47001e15be85b084c36a64c20039a0c4a667Jeff Sharkey            icon.setImageDrawable(root.loadDrawerIcon(context));
23766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            title.setText(root.title);
23866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
2396efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            // Show available space if no summary
2406efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            String summaryText = root.summary;
2416efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            if (TextUtils.isEmpty(summaryText) && root.availableBytes >= 0) {
2429fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                summaryText = context.getString(R.string.root_available_bytes,
2439fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                        Formatter.formatFileSize(context, root.availableBytes));
2449fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            }
2459fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
2469fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            summary.setText(summaryText);
2474ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            summary.setVisibility(TextUtils.isEmpty(summaryText) ? View.GONE : View.VISIBLE);
2486efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
2496efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
25066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
2516efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private static class SpacerItem extends Item {
2526efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public SpacerItem() {
2536efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            super(R.layout.item_root_spacer);
25466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
25566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
25666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        @Override
2576efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public void bindView(View convertView) {
2586efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            // Nothing to bind
25966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
26066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
26166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
2626efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private static class AppItem extends Item {
2636efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public final ResolveInfo info;
2646efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
2656efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public AppItem(ResolveInfo info) {
2666efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            super(R.layout.item_root);
2676efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            this.info = info;
26854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        }
26954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
27054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        @Override
2716efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public void bindView(View convertView) {
27254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
27354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
27454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final TextView summary = (TextView) convertView.findViewById(android.R.id.summary);
27554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
2766efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            final PackageManager pm = convertView.getContext().getPackageManager();
27754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            icon.setImageDrawable(info.loadIcon(pm));
27854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            title.setText(info.loadLabel(pm));
27954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
28054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            // TODO: match existing summary behavior from disambig dialog
28154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            summary.setVisibility(View.GONE);
28254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        }
2836efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
28454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
2856efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private static class RootsAdapter extends ArrayAdapter<Item> {
2866efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public RootsAdapter(Context context, Collection<RootInfo> roots, Intent includeApps) {
2876efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            super(context, 0);
28854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
2890c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            final List<RootItem> libraries = new ArrayList<>();
290abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono            final List<RootItem> others = new ArrayList<>();
291abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono
292abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono            for (final RootInfo root : roots) {
293abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono                final RootItem item = new RootItem(root);
294abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono                if (root.isLibrary()) {
295abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono                    libraries.add(item);
296abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono                } else {
297abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono                    others.add(item);
2985545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey                }
2996efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            }
3005545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey
3016efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            final RootComparator comp = new RootComparator();
3020c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            Collections.sort(libraries, comp);
303abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono            Collections.sort(others, comp);
3046efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
3050c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            addAll(libraries);
3060c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            add(new SpacerItem());
307abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono            addAll(others);
30866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
30954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            if (includeApps != null) {
31054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                final PackageManager pm = context.getPackageManager();
31154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                final List<ResolveInfo> infos = pm.queryIntentActivities(
31254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                        includeApps, PackageManager.MATCH_DEFAULT_ONLY);
31354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
31458efce36cd1b26006e08ddd696292bf06fc34c81Steve McKay                final List<AppItem> apps = new ArrayList<>();
3156efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
31654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                // Omit ourselves from the list
31754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                for (ResolveInfo info : infos) {
31854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                    if (!context.getPackageName().equals(info.activityInfo.packageName)) {
3196efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                        apps.add(new AppItem(info));
3206efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                    }
3216efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                }
3226efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
3236efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                if (apps.size() > 0) {
3246efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                    add(new SpacerItem());
3250c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa                    addAll(apps);
32654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                }
32754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            }
3286efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
32954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
3306efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
3316efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public View getView(int position, View convertView, ViewGroup parent) {
3326efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            final Item item = getItem(position);
3336efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            return item.getView(convertView, parent);
3346efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
33566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
3366efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
3376efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public boolean areAllItemsEnabled() {
3386efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            return false;
3396efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
3406efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
3416efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
3426efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public boolean isEnabled(int position) {
3436efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            return getItemViewType(position) != 1;
3446efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
3456efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
3466efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
3476efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public int getItemViewType(int position) {
3486efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            final Item item = getItem(position);
3496efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            if (item instanceof RootItem || item instanceof AppItem) {
3506efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                return 0;
3516efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            } else {
3526efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                return 1;
35354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            }
35466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
3556efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
3566efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
3576efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public int getViewTypeCount() {
3586efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            return 2;
3596efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
36066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
361aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
3620c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa    public static class RootComparator implements Comparator<RootItem> {
363aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        @Override
3640c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa        public int compare(RootItem lhs, RootItem rhs) {
3650c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            // Sort by root type, then title, then summary.
3660c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            int score = lhs.root.derivedType - rhs.root.derivedType;
367aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            if (score != 0) {
368aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey                return score;
369aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            }
3700c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            score = DocumentInfo.compareToIgnoreCaseNullable(lhs.root.title, rhs.root.title);
3710c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            if (score != 0) {
3720c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa                return score;
3730c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            }
3740c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa
3750c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa            return DocumentInfo.compareToIgnoreCaseNullable(lhs.root.summary, rhs.root.summary);
376aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        }
377aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
37866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey}
379