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