RootsFragment.java revision 008e948c3eac913ae3321bd690e3913e468e7fb1
166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey/* 266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Copyright (C) 2013 The Android Open Source Project 366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * 466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * you may not use this file except in compliance with the License. 666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * You may obtain a copy of the License at 766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * 866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * 1066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Unless required by applicable law or agreed to in writing, software 1166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 1266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * See the License for the specific language governing permissions and 1466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * limitations under the License. 1566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey */ 1666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 1766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeypackage com.android.documentsui; 1866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 1935820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKayimport static com.android.documentsui.Shared.DEBUG; 2035820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKay 2166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.Fragment; 2266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.FragmentManager; 2366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.FragmentTransaction; 24a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport android.app.LoaderManager.LoaderCallbacks; 2566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.content.Context; 2654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport android.content.Intent; 27a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport android.content.Loader; 2854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport android.content.pm.PackageManager; 2954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport android.content.pm.ResolveInfo; 30c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkeyimport android.net.Uri; 3166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.os.Bundle; 32c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkeyimport android.provider.Settings; 334a1ca86f4757647b62995eede2a45d06273503bfSteve McKayimport android.support.annotation.Nullable; 344ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkeyimport android.text.TextUtils; 359fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkeyimport android.text.format.Formatter; 3635820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKayimport android.util.Log; 3766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.LayoutInflater; 3866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.View; 3966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.ViewGroup; 4066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.AdapterView; 4166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.AdapterView.OnItemClickListener; 42c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkeyimport android.widget.AdapterView.OnItemLongClickListener; 4366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.ArrayAdapter; 4466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.ImageView; 4566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.ListView; 4666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.TextView; 4766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 48ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport com.android.documentsui.model.RootInfo; 4966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 5058efce36cd1b26006e08ddd696292bf06fc34c81Steve McKayimport java.util.ArrayList; 51a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport java.util.Collection; 526efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkeyimport java.util.Collections; 53aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport java.util.Comparator; 5454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport java.util.List; 55e6585b32ea586743258a5457e2184ffc087f2d2fKenny Rootimport java.util.Objects; 5666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 5766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey/** 5866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Display list of known storage backend roots. 5966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey */ 6066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeypublic class RootsFragment extends Fragment { 6166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 6235820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKay private static final String TAG = "RootsFragment"; 6335820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKay private static final String EXTRA_INCLUDE_APPS = "includeApps"; 6435820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKay 6566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey private ListView mList; 666efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey private RootsAdapter mAdapter; 67a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey private LoaderCallbacks<Collection<RootInfo>> mCallbacks; 68a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey 6954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey 7054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey public static void show(FragmentManager fm, Intent includeApps) { 7154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey final Bundle args = new Bundle(); 7254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey args.putParcelable(EXTRA_INCLUDE_APPS, includeApps); 7354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey 7466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey final RootsFragment fragment = new RootsFragment(); 7554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey fragment.setArguments(args); 7666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 7766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey final FragmentTransaction ft = fm.beginTransaction(); 7866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey ft.replace(R.id.container_roots, fragment); 7966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey ft.commitAllowingStateLoss(); 8066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey } 8166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 8266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey public static RootsFragment get(FragmentManager fm) { 8366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey return (RootsFragment) fm.findFragmentById(R.id.container_roots); 8466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey } 8566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 8666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey @Override 8766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey public View onCreateView( 8866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 8966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 9066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey final View view = inflater.inflate(R.layout.fragment_roots, container, false); 912036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa mList = (ListView) view.findViewById(R.id.roots_list); 9266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey mList.setOnItemClickListener(mItemListener); 9328c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey mList.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 9466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey return view; 9566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey } 9666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 979fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey @Override 98a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey public void onActivityCreated(Bundle savedInstanceState) { 99a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey super.onActivityCreated(savedInstanceState); 100a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey 101a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey final Context context = getActivity(); 102a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey final RootsCache roots = DocumentsApplication.getRootsCache(context); 103e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay final State state = ((BaseActivity) context).getDisplayState(); 104a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey 105a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey mCallbacks = new LoaderCallbacks<Collection<RootInfo>>() { 106a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey @Override 107a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey public Loader<Collection<RootInfo>> onCreateLoader(int id, Bundle args) { 108a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey return new RootsLoader(context, roots, state); 109a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey } 110a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey 111a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey @Override 112a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey public void onLoadFinished( 113a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey Loader<Collection<RootInfo>> loader, Collection<RootInfo> result) { 1144a1ca86f4757647b62995eede2a45d06273503bfSteve McKay if (!isAdded()) { 1154a1ca86f4757647b62995eede2a45d06273503bfSteve McKay return; 1164a1ca86f4757647b62995eede2a45d06273503bfSteve McKay } 117a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey 1184a1ca86f4757647b62995eede2a45d06273503bfSteve McKay Intent handlerAppIntent = getArguments().getParcelable(EXTRA_INCLUDE_APPS); 119a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey 1204a1ca86f4757647b62995eede2a45d06273503bfSteve McKay mAdapter = new RootsAdapter(context, result, handlerAppIntent); 121a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey mList.setAdapter(mAdapter); 122a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey 123a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey onCurrentRootChanged(); 124a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey } 125a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey 126a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey @Override 127a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey public void onLoaderReset(Loader<Collection<RootInfo>> loader) { 128a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey mAdapter = null; 129a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey mList.setAdapter(null); 130a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey } 131a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey }; 132a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey } 133a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey 134a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey @Override 13588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey public void onResume() { 13688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey super.onResume(); 137669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey onDisplayStateChanged(); 138669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey } 1399fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey 140669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey public void onDisplayStateChanged() { 1419fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey final Context context = getActivity(); 142e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay final State state = ((BaseActivity) context).getDisplayState(); 143348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey 144e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay if (state.action == State.ACTION_GET_CONTENT) { 145c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey mList.setOnItemLongClickListener(mItemLongClickListener); 146c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey } else { 147c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey mList.setOnItemLongClickListener(null); 148c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey mList.setLongClickable(false); 149c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey } 150c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey 151a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey getLoaderManager().restartLoader(2, null, mCallbacks); 15228c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey } 15328c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey 15428c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey public void onCurrentRootChanged() { 1554a1ca86f4757647b62995eede2a45d06273503bfSteve McKay if (mAdapter == null) { 1564a1ca86f4757647b62995eede2a45d06273503bfSteve McKay return; 1574a1ca86f4757647b62995eede2a45d06273503bfSteve McKay } 15828c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey 159e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay final RootInfo root = ((BaseActivity) getActivity()).getCurrentRoot(); 16028c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey for (int i = 0; i < mAdapter.getCount(); i++) { 16128c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey final Object item = mAdapter.getItem(i); 162a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey if (item instanceof RootItem) { 163a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey final RootInfo testRoot = ((RootItem) item).root; 164e6585b32ea586743258a5457e2184ffc087f2d2fKenny Root if (Objects.equals(testRoot, root)) { 165a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey mList.setItemChecked(i, true); 1668e1c9637ec56fbfe313e964a5b60986c1bb092b9Aga Wronska mList.setSelection(i); 167a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey return; 168a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey } 16928c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey } 17028c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey } 1719fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey } 1729fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey 1732036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa /** 1742036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa * Attempts to shift focus back to the navigation drawer. 1752036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa */ 1762036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa public void requestFocus() { 1772036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa mList.requestFocus(); 1782036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa } 1792036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa 180c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey private void showAppDetails(ResolveInfo ri) { 181c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 182c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey intent.setData(Uri.fromParts("package", ri.activityInfo.packageName, null)); 183c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 184c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey startActivity(intent); 185c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey } 186c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey 18766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey private OnItemClickListener mItemListener = new OnItemClickListener() { 18866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey @Override 18966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 190ef3e2cf35fbede340d5ff830b410baea8e461a94Steve McKay Item item = mAdapter.getItem(position); 1916efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey if (item instanceof RootItem) { 192ef3e2cf35fbede340d5ff830b410baea8e461a94Steve McKay BaseActivity activity = BaseActivity.get(RootsFragment.this); 19345f75e2a81674d792077516f13088d476c0ba510Aga Wronska RootInfo newRoot = ((RootItem) item).root; 19445f75e2a81674d792077516f13088d476c0ba510Aga Wronska Metrics.logRootVisited(getActivity(), newRoot); 19545f75e2a81674d792077516f13088d476c0ba510Aga Wronska activity.onRootPicked(newRoot); 1966efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } else if (item instanceof AppItem) { 197ef3e2cf35fbede340d5ff830b410baea8e461a94Steve McKay DocumentsActivity activity = DocumentsActivity.get(RootsFragment.this); 198723799858a15fa316128716d9e131a681d1a51d2Ben Kwa ResolveInfo info = ((AppItem) item).info; 199723799858a15fa316128716d9e131a681d1a51d2Ben Kwa Metrics.logAppVisited(getActivity(), info); 200723799858a15fa316128716d9e131a681d1a51d2Ben Kwa activity.onAppPicked(info); 20135820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKay } else if (item instanceof SpacerItem) { 20235820cfe963ce120a5876b8a123d5b1df13cbac5Steve McKay if (DEBUG) Log.d(TAG, "Ignoring click on spacer item."); 20354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey } else { 20454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey throw new IllegalStateException("Unknown root: " + item); 20554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey } 20666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey } 20766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey }; 20866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 209c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey private OnItemLongClickListener mItemLongClickListener = new OnItemLongClickListener() { 210c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey @Override 211c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { 212c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey final Item item = mAdapter.getItem(position); 213c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey if (item instanceof AppItem) { 214c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey showAppDetails(((AppItem) item).info); 215c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey return true; 216c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey } else { 217c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey return false; 218c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey } 219c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey } 220c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey }; 221c24bbd4ce525d80e385de6e27b19dac239db1dfdJeff Sharkey 2226efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey private static abstract class Item { 2236efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey private final int mLayoutId; 2246efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 2256efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public Item(int layoutId) { 2266efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey mLayoutId = layoutId; 22766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey } 22866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 2296efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public View getView(View convertView, ViewGroup parent) { 23066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey if (convertView == null) { 2316efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey convertView = LayoutInflater.from(parent.getContext()) 2326efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey .inflate(mLayoutId, parent, false); 23366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey } 2346efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey bindView(convertView); 2356efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey return convertView; 2366efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 2376efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 2386efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public abstract void bindView(View convertView); 2396efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 24066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 2416efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey private static class RootItem extends Item { 2426efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public final RootInfo root; 2436efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 2446efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public RootItem(RootInfo root) { 2456efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey super(R.layout.item_root); 2466efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey this.root = root; 2476efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 2486efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 2496efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey @Override 2506efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public void bindView(View convertView) { 25166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon); 25266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey final TextView title = (TextView) convertView.findViewById(android.R.id.title); 25366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey final TextView summary = (TextView) convertView.findViewById(android.R.id.summary); 25466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 2556efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey final Context context = convertView.getContext(); 256cbce47001e15be85b084c36a64c20039a0c4a667Jeff Sharkey icon.setImageDrawable(root.loadDrawerIcon(context)); 25766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey title.setText(root.title); 25866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 2596efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey // Show available space if no summary 2606efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey String summaryText = root.summary; 2616efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey if (TextUtils.isEmpty(summaryText) && root.availableBytes >= 0) { 2629fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey summaryText = context.getString(R.string.root_available_bytes, 2639fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey Formatter.formatFileSize(context, root.availableBytes)); 2649fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey } 2659fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey 2669fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey summary.setText(summaryText); 2674ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey summary.setVisibility(TextUtils.isEmpty(summaryText) ? View.GONE : View.VISIBLE); 2686efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 2696efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 27066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 2716efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey private static class SpacerItem extends Item { 2726efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public SpacerItem() { 2736efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey super(R.layout.item_root_spacer); 27466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey } 27566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 27666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey @Override 2776efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public void bindView(View convertView) { 2786efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey // Nothing to bind 27966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey } 28066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey } 28166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 2826efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey private static class AppItem extends Item { 2836efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public final ResolveInfo info; 2846efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 2856efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public AppItem(ResolveInfo info) { 2866efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey super(R.layout.item_root); 2876efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey this.info = info; 28854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey } 28954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey 29054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey @Override 2916efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public void bindView(View convertView) { 29254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon); 29354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey final TextView title = (TextView) convertView.findViewById(android.R.id.title); 29454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey final TextView summary = (TextView) convertView.findViewById(android.R.id.summary); 29554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey 2966efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey final PackageManager pm = convertView.getContext().getPackageManager(); 29754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey icon.setImageDrawable(info.loadIcon(pm)); 29854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey title.setText(info.loadLabel(pm)); 29954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey 30054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey // TODO: match existing summary behavior from disambig dialog 30154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey summary.setVisibility(View.GONE); 30254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey } 3036efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 30454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey 3056efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey private static class RootsAdapter extends ArrayAdapter<Item> { 3064a1ca86f4757647b62995eede2a45d06273503bfSteve McKay 3074a1ca86f4757647b62995eede2a45d06273503bfSteve McKay /** 3084a1ca86f4757647b62995eede2a45d06273503bfSteve McKay * @param handlerAppIntent When not null, apps capable of handling the original 3094a1ca86f4757647b62995eede2a45d06273503bfSteve McKay * intent will be included in list of roots (in special section at bottom). 3104a1ca86f4757647b62995eede2a45d06273503bfSteve McKay */ 3114a1ca86f4757647b62995eede2a45d06273503bfSteve McKay public RootsAdapter( 3124a1ca86f4757647b62995eede2a45d06273503bfSteve McKay Context context, Collection<RootInfo> roots, @Nullable Intent handlerAppIntent) { 3136efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey super(context, 0); 31454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey 3150c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa final List<RootItem> libraries = new ArrayList<>(); 316abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono final List<RootItem> others = new ArrayList<>(); 317abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono 318abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono for (final RootInfo root : roots) { 319abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono final RootItem item = new RootItem(root); 320e95c321fd991773e895e71bc415afff46236c77bBen Kwa if (root.isLibrary()) { 3213ce95951bd173c422b8d369b4651c28e5bcc20f4Steve McKay if (DEBUG) Log.d(TAG, "Adding " + root + " as library."); 322abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono libraries.add(item); 323abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono } else { 3243ce95951bd173c422b8d369b4651c28e5bcc20f4Steve McKay if (DEBUG) Log.d(TAG, "Adding " + root + " as non-library."); 325abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono others.add(item); 3265545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey } 3276efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 3285545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey 3296efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey final RootComparator comp = new RootComparator(); 3300c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa Collections.sort(libraries, comp); 331abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono Collections.sort(others, comp); 3326efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 3330c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa addAll(libraries); 3344a1ca86f4757647b62995eede2a45d06273503bfSteve McKay // Only add the spacer if it is actually separating something. 3354a1ca86f4757647b62995eede2a45d06273503bfSteve McKay if (!libraries.isEmpty() && !others.isEmpty()) { 3364a1ca86f4757647b62995eede2a45d06273503bfSteve McKay add(new SpacerItem()); 3374a1ca86f4757647b62995eede2a45d06273503bfSteve McKay } 338abf397458dca89fd3df4234d547a94bf0487033dDaichi Hirono addAll(others); 33966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 3404a1ca86f4757647b62995eede2a45d06273503bfSteve McKay // Include apps that can handle this intent too. 3414a1ca86f4757647b62995eede2a45d06273503bfSteve McKay if (handlerAppIntent != null) { 3424a1ca86f4757647b62995eede2a45d06273503bfSteve McKay includeHandlerApps(context, handlerAppIntent); 3434a1ca86f4757647b62995eede2a45d06273503bfSteve McKay } 3444a1ca86f4757647b62995eede2a45d06273503bfSteve McKay } 3456efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 3464a1ca86f4757647b62995eede2a45d06273503bfSteve McKay /** 3474a1ca86f4757647b62995eede2a45d06273503bfSteve McKay * Adds apps capable of handling the original intent will be included 3484a1ca86f4757647b62995eede2a45d06273503bfSteve McKay * in list of roots (in special section at bottom). 3494a1ca86f4757647b62995eede2a45d06273503bfSteve McKay */ 3504a1ca86f4757647b62995eede2a45d06273503bfSteve McKay private void includeHandlerApps(Context context, Intent handlerAppIntent) { 3514a1ca86f4757647b62995eede2a45d06273503bfSteve McKay final PackageManager pm = context.getPackageManager(); 3524a1ca86f4757647b62995eede2a45d06273503bfSteve McKay final List<ResolveInfo> infos = pm.queryIntentActivities( 3534a1ca86f4757647b62995eede2a45d06273503bfSteve McKay handlerAppIntent, PackageManager.MATCH_DEFAULT_ONLY); 3544a1ca86f4757647b62995eede2a45d06273503bfSteve McKay 3554a1ca86f4757647b62995eede2a45d06273503bfSteve McKay final List<AppItem> apps = new ArrayList<>(); 3564a1ca86f4757647b62995eede2a45d06273503bfSteve McKay 3574a1ca86f4757647b62995eede2a45d06273503bfSteve McKay // Omit ourselves from the list 3584a1ca86f4757647b62995eede2a45d06273503bfSteve McKay for (ResolveInfo info : infos) { 3594a1ca86f4757647b62995eede2a45d06273503bfSteve McKay if (!context.getPackageName().equals(info.activityInfo.packageName)) { 3604a1ca86f4757647b62995eede2a45d06273503bfSteve McKay apps.add(new AppItem(info)); 3616efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 3624a1ca86f4757647b62995eede2a45d06273503bfSteve McKay } 3636efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 3644a1ca86f4757647b62995eede2a45d06273503bfSteve McKay if (apps.size() > 0) { 3654a1ca86f4757647b62995eede2a45d06273503bfSteve McKay add(new SpacerItem()); 3664a1ca86f4757647b62995eede2a45d06273503bfSteve McKay addAll(apps); 36754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey } 3686efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 36954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey 3706efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey @Override 3716efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public View getView(int position, View convertView, ViewGroup parent) { 3726efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey final Item item = getItem(position); 3736efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey return item.getView(convertView, parent); 3746efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 37566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 3766efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey @Override 3776efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public boolean areAllItemsEnabled() { 3786efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey return false; 3796efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 3806efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 3816efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey @Override 3826efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public boolean isEnabled(int position) { 3836efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey return getItemViewType(position) != 1; 3846efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 3856efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 3866efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey @Override 3876efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public int getItemViewType(int position) { 3886efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey final Item item = getItem(position); 3896efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey if (item instanceof RootItem || item instanceof AppItem) { 3906efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey return 0; 3916efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } else { 3926efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey return 1; 39354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey } 39466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey } 3956efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 3966efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey @Override 3976efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public int getViewTypeCount() { 3986efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey return 2; 3996efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 40066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey } 401aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 4020c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa public static class RootComparator implements Comparator<RootItem> { 403aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey @Override 4040c64308240a7e9d3a78d4dedba2a419da63b5afdBen Kwa public int compare(RootItem lhs, RootItem rhs) { 405008e948c3eac913ae3321bd690e3913e468e7fb1Steve McKay return lhs.root.compareTo(rhs.root); 406aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey } 407aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey } 40866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey} 409