RootsFragment.java revision a9ce049db87259e302e2368d2a4a1c11a94fd831
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;
2866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.os.Bundle;
29ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport android.provider.DocumentsContract.Root;
304ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkeyimport android.text.TextUtils;
319fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkeyimport android.text.format.Formatter;
3266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.LayoutInflater;
3366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.View;
3466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.ViewGroup;
3566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.AdapterView;
3666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.AdapterView.OnItemClickListener;
3766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.ArrayAdapter;
3866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.ImageView;
3966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.ListView;
40f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkeyimport android.widget.Space;
4166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.TextView;
4266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
43348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkeyimport com.android.documentsui.DocumentsActivity.State;
4466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport com.android.documentsui.SectionedListAdapter.SectionAdapter;
45ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport com.android.documentsui.model.DocumentInfo;
46ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport com.android.documentsui.model.RootInfo;
4728c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkeyimport com.android.internal.util.Objects;
4866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
49a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport java.util.Collection;
50aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport java.util.Comparator;
5154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport java.util.List;
5266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
5366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey/**
5466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Display list of known storage backend roots.
5566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey */
5666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeypublic class RootsFragment extends Fragment {
5766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
5866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    private ListView mList;
5966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    private SectionedRootsAdapter mAdapter;
6066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
61a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    private LoaderCallbacks<Collection<RootInfo>> mCallbacks;
62a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
6354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey    private static final String EXTRA_INCLUDE_APPS = "includeApps";
6454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
6554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey    public static void show(FragmentManager fm, Intent includeApps) {
6654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        final Bundle args = new Bundle();
6754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        args.putParcelable(EXTRA_INCLUDE_APPS, includeApps);
6854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
6966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final RootsFragment fragment = new RootsFragment();
7054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        fragment.setArguments(args);
7166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
7266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final FragmentTransaction ft = fm.beginTransaction();
7366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        ft.replace(R.id.container_roots, fragment);
7466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        ft.commitAllowingStateLoss();
7566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
7666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
7766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    public static RootsFragment get(FragmentManager fm) {
7866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        return (RootsFragment) fm.findFragmentById(R.id.container_roots);
7966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
8066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
8166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    @Override
8266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    public View onCreateView(
8366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
8466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final Context context = inflater.getContext();
8566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
8666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final View view = inflater.inflate(R.layout.fragment_roots, container, false);
8766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        mList = (ListView) view.findViewById(android.R.id.list);
8866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        mList.setOnItemClickListener(mItemListener);
8928c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        mList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
9066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
9166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        return view;
9266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
9366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
949fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    @Override
95a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    public void onActivityCreated(Bundle savedInstanceState) {
96a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        super.onActivityCreated(savedInstanceState);
97a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
98a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        final Context context = getActivity();
99a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        final RootsCache roots = DocumentsApplication.getRootsCache(context);
100a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        final State state = ((DocumentsActivity) context).getDisplayState();
101a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
102a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        mCallbacks = new LoaderCallbacks<Collection<RootInfo>>() {
103a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            @Override
104a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            public Loader<Collection<RootInfo>> onCreateLoader(int id, Bundle args) {
105a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                return new RootsLoader(context, roots, state);
106a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            }
107a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
108a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            @Override
109a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            public void onLoadFinished(
110a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                    Loader<Collection<RootInfo>> loader, Collection<RootInfo> result) {
111a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                if (!isAdded()) return;
112a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
113a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                final Intent includeApps = getArguments().getParcelable(EXTRA_INCLUDE_APPS);
114a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
115a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                mAdapter = new SectionedRootsAdapter(context, result, includeApps);
116a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                mList.setAdapter(mAdapter);
117a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
118a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                onCurrentRootChanged();
119a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            }
120a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
121a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            @Override
122a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            public void onLoaderReset(Loader<Collection<RootInfo>> loader) {
123a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                mAdapter = null;
124a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                mList.setAdapter(null);
125a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            }
126a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        };
127a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    }
128a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
129a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    @Override
13088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    public void onResume() {
13188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        super.onResume();
1329fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
1339fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        final Context context = getActivity();
134348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey        final State state = ((DocumentsActivity) context).getDisplayState();
135348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey        state.showAdvanced = SettingsActivity.getDisplayAdvancedDevices(context);
136348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey
137a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        getLoaderManager().restartLoader(2, null, mCallbacks);
13828c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey    }
13928c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey
14028c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey    public void onCurrentRootChanged() {
14128c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        if (mAdapter == null) return;
14228c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey
14328c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        final RootInfo root = ((DocumentsActivity) getActivity()).getCurrentRoot();
14428c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        for (int i = 0; i < mAdapter.getCount(); i++) {
14528c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            final Object item = mAdapter.getItem(i);
14628c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            if (Objects.equal(item, root)) {
14728c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey                mList.setItemChecked(i, true);
14828c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey                return;
14928c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            }
15028c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        }
1519fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    }
1529fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
15366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    private OnItemClickListener mItemListener = new OnItemClickListener() {
15466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        @Override
15566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
15654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final DocumentsActivity activity = DocumentsActivity.get(RootsFragment.this);
15754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final Object item = mAdapter.getItem(position);
158ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            if (item instanceof RootInfo) {
159ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                activity.onRootPicked((RootInfo) item, true);
16054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            } else if (item instanceof ResolveInfo) {
16154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                activity.onAppPicked((ResolveInfo) item);
16254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            } else {
16354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                throw new IllegalStateException("Unknown root: " + item);
16454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            }
16566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
16666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    };
16766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
168ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    private static class RootsAdapter extends ArrayAdapter<RootInfo> implements SectionAdapter {
169f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey        public RootsAdapter(Context context) {
17066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            super(context, 0);
17166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
17266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
17366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        @Override
17466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        public View getView(int position, View convertView, ViewGroup parent) {
1759fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            final Context context = parent.getContext();
17666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            if (convertView == null) {
1779fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                convertView = LayoutInflater.from(context)
17866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey                        .inflate(R.layout.item_root, parent, false);
17966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            }
18066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
18166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
18266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
18366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            final TextView summary = (TextView) convertView.findViewById(android.R.id.summary);
18466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
185ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            final RootInfo root = getItem(position);
186aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            icon.setImageDrawable(root.loadIcon(context));
18766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            title.setText(root.title);
18866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
1899fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            // Device summary is always available space
1909fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            final String summaryText;
191ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            if (root.rootType == Root.ROOT_TYPE_DEVICE && root.availableBytes >= 0) {
1929fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                summaryText = context.getString(R.string.root_available_bytes,
1939fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                        Formatter.formatFileSize(context, root.availableBytes));
1949fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            } else {
1959fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                summaryText = root.summary;
1969fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            }
1979fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
1989fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            summary.setText(summaryText);
1994ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            summary.setVisibility(TextUtils.isEmpty(summaryText) ? View.GONE : View.VISIBLE);
20066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
20166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            return convertView;
20266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
20366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
20466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        @Override
20566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        public View getHeaderView(View convertView, ViewGroup parent) {
20666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            if (convertView == null) {
207f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey                convertView = new Space(parent.getContext());
20866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            }
20966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            return convertView;
21066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
21166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
21266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
21354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey    private static class AppsAdapter extends ArrayAdapter<ResolveInfo> implements SectionAdapter {
21454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        public AppsAdapter(Context context) {
21554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            super(context, 0);
21654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        }
21754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
21854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        @Override
21954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        public View getView(int position, View convertView, ViewGroup parent) {
22054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final Context context = parent.getContext();
22154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final PackageManager pm = context.getPackageManager();
22254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            if (convertView == null) {
22354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                convertView = LayoutInflater.from(context)
22454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                        .inflate(R.layout.item_root, parent, false);
22554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            }
22654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
22754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
22854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
22954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final TextView summary = (TextView) convertView.findViewById(android.R.id.summary);
23054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
23154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final ResolveInfo info = getItem(position);
23254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            icon.setImageDrawable(info.loadIcon(pm));
23354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            title.setText(info.loadLabel(pm));
23454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
23554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            // TODO: match existing summary behavior from disambig dialog
23654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            summary.setVisibility(View.GONE);
23754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
23854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            return convertView;
23954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        }
24054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
24154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        @Override
24254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        public View getHeaderView(View convertView, ViewGroup parent) {
24354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            if (convertView == null) {
24454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                convertView = LayoutInflater.from(parent.getContext())
24554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                        .inflate(R.layout.item_root_header, parent, false);
24654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            }
24754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
24854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
24954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            title.setText(R.string.root_type_apps);
25054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
25154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            return convertView;
25254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        }
25354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey    }
25454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
25554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey    private static class SectionedRootsAdapter extends SectionedListAdapter {
25666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        private final RootsAdapter mServices;
25766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        private final RootsAdapter mShortcuts;
25866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        private final RootsAdapter mDevices;
25954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        private final AppsAdapter mApps;
26066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
261a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        public SectionedRootsAdapter(
262a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                Context context, Collection<RootInfo> roots, Intent includeApps) {
263f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey            mServices = new RootsAdapter(context);
264f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey            mShortcuts = new RootsAdapter(context);
265f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey            mDevices = new RootsAdapter(context);
26654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            mApps = new AppsAdapter(context);
26766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
268ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            for (RootInfo root : roots) {
26966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey                switch (root.rootType) {
270ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                    case Root.ROOT_TYPE_SERVICE:
27166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey                        mServices.add(root);
27266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey                        break;
273ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                    case Root.ROOT_TYPE_SHORTCUT:
27466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey                        mShortcuts.add(root);
27566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey                        break;
276ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                    case Root.ROOT_TYPE_DEVICE:
277348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey                        mDevices.add(root);
27866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey                        break;
27966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey                }
28066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            }
28166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
28254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            if (includeApps != null) {
28354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                final PackageManager pm = context.getPackageManager();
28454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                final List<ResolveInfo> infos = pm.queryIntentActivities(
28554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                        includeApps, PackageManager.MATCH_DEFAULT_ONLY);
28654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
28754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                // Omit ourselves from the list
28854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                for (ResolveInfo info : infos) {
28954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                    if (!context.getPackageName().equals(info.activityInfo.packageName)) {
29054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                        mApps.add(info);
29154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                    }
29254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                }
29354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            }
29454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
29566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            final RootComparator comp = new RootComparator();
29666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            mServices.sort(comp);
29766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            mShortcuts.sort(comp);
29866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            mDevices.sort(comp);
29966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
30066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            if (mShortcuts.getCount() > 0) {
30166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey                addSection(mShortcuts);
30266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            }
303348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey            if (mDevices.getCount() > 0) {
304348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey                addSection(mDevices);
30566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            }
306f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey            if (mServices.getCount() > 0) {
307f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey                addSection(mServices);
308f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey            }
30954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            if (mApps.getCount() > 0) {
31054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                addSection(mApps);
31154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            }
31266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
31366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
314aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
315ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public static class RootComparator implements Comparator<RootInfo> {
316aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        @Override
317ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        public int compare(RootInfo lhs, RootInfo rhs) {
318348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey            if (lhs.authority == null) {
319348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey                return -1;
320348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey            } else if (rhs.authority == null) {
321348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey                return 1;
322348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey            }
323348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey
324ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            final int score = DocumentInfo.compareToIgnoreCaseNullable(lhs.title, rhs.title);
325aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            if (score != 0) {
326aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey                return score;
327aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            } else {
328ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                return DocumentInfo.compareToIgnoreCaseNullable(lhs.summary, rhs.summary);
329aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            }
330aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        }
331aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
33266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey}
333