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