163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan/* 263bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan * Copyright (C) 2016 The Android Open Source Project 363bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan * 463bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan * Licensed under the Apache License, Version 2.0 (the "License"); 563bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan * you may not use this file except in compliance with the License. 663bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan * You may obtain a copy of the License at 763bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan * 863bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan * http://www.apache.org/licenses/LICENSE-2.0 963bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan * 1063bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan * Unless required by applicable law or agreed to in writing, software 1163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan * distributed under the License is distributed on an "AS IS" BASIS, 1263bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1363bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan * See the License for the specific language governing permissions and 1463bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan * limitations under the License. 1563bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan */ 1663bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 1763bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tanpackage com.android.documentsui; 1863bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 1963bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tanimport android.app.Activity; 20be1e07992d1886d415f4be947a6424e945791f77Garfield Tanimport android.content.BroadcastReceiver; 21be1e07992d1886d415f4be947a6424e945791f77Garfield Tanimport android.content.Context; 22be1e07992d1886d415f4be947a6424e945791f77Garfield Tanimport android.content.Intent; 23be1e07992d1886d415f4be947a6424e945791f77Garfield Tanimport android.content.IntentFilter; 2463bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tanimport android.net.Uri; 25be1e07992d1886d415f4be947a6424e945791f77Garfield Tanimport android.support.v4.content.LocalBroadcastManager; 2663bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 2763bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tanimport com.android.documentsui.AbstractActionHandler.CommonAddons; 2863bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tanimport com.android.documentsui.base.DocumentInfo; 2963bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tanimport com.android.documentsui.base.PairedTask; 3063bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tanimport com.android.documentsui.base.RootInfo; 3163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tanimport com.android.documentsui.base.State; 3263bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tanimport com.android.documentsui.dirlist.AnimationView; 333a2682362481d1af4ec437775610a1f11e9faa24Steve McKayimport com.android.documentsui.queries.SearchViewManager; 349bd4099ee27f8302a06fc66980079f29127318f8Jon Mannimport com.android.documentsui.roots.ProvidersAccess; 3580b52b3c7a16ccf0b57f78b09858afaf3f686559Garfield Tanimport com.android.documentsui.selection.SelectionManager; 3663bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 3763bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tanimport java.util.Collection; 3863bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 3963bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan/** 4063bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan * Monitors roots change and refresh the page when necessary. 4163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan */ 4263bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tanfinal class RootsMonitor<T extends Activity & CommonAddons> { 4363bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 44be1e07992d1886d415f4be947a6424e945791f77Garfield Tan private final LocalBroadcastManager mManager; 45be1e07992d1886d415f4be947a6424e945791f77Garfield Tan private final BroadcastReceiver mReceiver; 4663bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 4763bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan RootsMonitor( 4863bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan final T activity, 4963bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan final ActionHandler actions, 509bd4099ee27f8302a06fc66980079f29127318f8Jon Mann final ProvidersAccess providers, 5163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan final DocumentsAccess docs, 5263bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan final State state, 5380b52b3c7a16ccf0b57f78b09858afaf3f686559Garfield Tan final SearchViewManager searchMgr, 5480b52b3c7a16ccf0b57f78b09858afaf3f686559Garfield Tan final Runnable actionModeFinisher) { 55be1e07992d1886d415f4be947a6424e945791f77Garfield Tan mManager = LocalBroadcastManager.getInstance(activity); 5663bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 57be1e07992d1886d415f4be947a6424e945791f77Garfield Tan mReceiver = new BroadcastReceiver() { 5863bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan @Override 59be1e07992d1886d415f4be947a6424e945791f77Garfield Tan public void onReceive(Context context, Intent intent) { 6063bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan new HandleRootsChangedTask<T>( 6163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan activity, 6263bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan actions, 639bd4099ee27f8302a06fc66980079f29127318f8Jon Mann providers, 6463bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan docs, 6563bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan state, 6680b52b3c7a16ccf0b57f78b09858afaf3f686559Garfield Tan searchMgr, 6780b52b3c7a16ccf0b57f78b09858afaf3f686559Garfield Tan actionModeFinisher).execute(activity.getCurrentRoot()); 6863bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } 6963bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan }; 7063bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } 7163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 7263bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan void start() { 739bd4099ee27f8302a06fc66980079f29127318f8Jon Mann mManager.registerReceiver(mReceiver, new IntentFilter(ProvidersAccess.BROADCAST_ACTION)); 7463bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } 7563bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 7663bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan void stop() { 77be1e07992d1886d415f4be947a6424e945791f77Garfield Tan mManager.unregisterReceiver(mReceiver); 7863bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } 7963bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 8063bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan private static class HandleRootsChangedTask<T extends Activity & CommonAddons> 8163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan extends PairedTask<T, RootInfo, RootInfo> { 8263bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan private final ActionHandler mActions; 839bd4099ee27f8302a06fc66980079f29127318f8Jon Mann private final ProvidersAccess mProviders; 8463bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan private final DocumentsAccess mDocs; 8563bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan private final State mState; 8663bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan private final SearchViewManager mSearchMgr; 8780b52b3c7a16ccf0b57f78b09858afaf3f686559Garfield Tan private final Runnable mActionModeFinisher; 8863bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 8963bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan private RootInfo mCurrentRoot; 9063bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan private DocumentInfo mDefaultRootDocument; 9163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 9263bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan private HandleRootsChangedTask( 9363bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan T activity, 9463bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan ActionHandler actions, 959bd4099ee27f8302a06fc66980079f29127318f8Jon Mann ProvidersAccess providers, 9663bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan DocumentsAccess docs, 9763bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan State state, 9880b52b3c7a16ccf0b57f78b09858afaf3f686559Garfield Tan SearchViewManager searchMgr, 9980b52b3c7a16ccf0b57f78b09858afaf3f686559Garfield Tan Runnable actionModeFinisher) { 10063bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan super(activity); 10163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan mActions = actions; 1029bd4099ee27f8302a06fc66980079f29127318f8Jon Mann mProviders = providers; 10363bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan mDocs = docs; 10463bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan mState = state; 10563bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan mSearchMgr = searchMgr; 10680b52b3c7a16ccf0b57f78b09858afaf3f686559Garfield Tan mActionModeFinisher = actionModeFinisher; 10763bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } 10863bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 10963bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan @Override 11063bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan protected RootInfo run(RootInfo... roots) { 11163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan assert (roots.length == 1); 11263bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan mCurrentRoot = roots[0]; 1139bd4099ee27f8302a06fc66980079f29127318f8Jon Mann final Collection<RootInfo> cachedRoots = mProviders.getRootsBlocking(); 11463bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan for (final RootInfo root : cachedRoots) { 11563bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan if (root.getUri().equals(mCurrentRoot.getUri())) { 11663bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan // We don't need to change the current root as the current root was not removed. 11763bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan return null; 11863bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } 11963bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } 12063bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 12163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan // Choose the default root. 1229bd4099ee27f8302a06fc66980079f29127318f8Jon Mann final RootInfo defaultRoot = mProviders.getDefaultRootBlocking(mState); 12363bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan assert (defaultRoot != null); 12463bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan if (!defaultRoot.isRecents()) { 12563bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan mDefaultRootDocument = mDocs.getRootDocument(defaultRoot); 12663bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } 12763bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan return defaultRoot; 12863bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } 12963bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 13063bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan @Override 13163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan protected void finish(RootInfo defaultRoot) { 13263bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan if (defaultRoot == null) { 13363bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan return; 13463bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } 13563bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 13663bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan // If the activity has been launched for the specific root and it is removed, finish the 13763bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan // activity. 13863bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan final Uri uri = mOwner.getIntent().getData(); 13963bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan if (uri != null && uri.equals(mCurrentRoot.getUri())) { 14063bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan mOwner.finish(); 14163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan return; 14263bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } 14363bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 14480b52b3c7a16ccf0b57f78b09858afaf3f686559Garfield Tan // Clean action mode before changing root. 14580b52b3c7a16ccf0b57f78b09858afaf3f686559Garfield Tan mActionModeFinisher.run(); 14680b52b3c7a16ccf0b57f78b09858afaf3f686559Garfield Tan 14763bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan // Clear entire backstack and start in new root. 1482a837422d25b44f2847bc82e7c90b4e8fcde1518Garfield Tan mState.stack.changeRoot(defaultRoot); 1499e047855cfd82fbac8ef07a93be27ab55cd8b4e8Tomasz Mikolajewski mSearchMgr.update(mState.stack); 15063bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan 15163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan if (defaultRoot.isRecents()) { 15263bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan mOwner.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE); 15363bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } else { 15463bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan mActions.openContainerDocument(mDefaultRootDocument); 15563bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } 15663bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } 15763bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan } 15863bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan} 159