blob: 7da937159cabec34bb391b862f3624165c9ed6f1 [file] [log] [blame]
Steve McKay0ce04b72017-06-05 13:23:54 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Steve McKay052985f2017-06-07 11:30:46 -070016package com.android.documentsui;
Steve McKay0ce04b72017-06-05 13:23:54 -070017
Jeff Sharkeya4ff00f2018-07-09 14:57:51 -060018import androidx.annotation.DrawableRes;
Steve McKay0ce04b72017-06-05 13:23:54 -070019import android.content.Context;
20import android.content.Intent;
21import android.content.pm.ShortcutInfo;
22import android.content.pm.ShortcutManager;
23import android.graphics.drawable.Icon;
24
25import com.android.documentsui.R;
26import com.android.documentsui.base.Providers;
27import com.android.documentsui.base.RootInfo;
Tony Huang48974eb2019-02-14 16:24:31 +080028import com.android.documentsui.base.Shared;
Steve McKay052985f2017-06-07 11:30:46 -070029import com.android.documentsui.files.FilesActivity;
Steve McKay0ce04b72017-06-05 13:23:54 -070030import com.android.documentsui.prefs.ScopedPreferences;
31
32import java.util.ArrayList;
33import java.util.Collection;
34import java.util.HashMap;
35import java.util.List;
36import java.util.Map;
37
38/**
39 * Manages dynamic shortcuts.
40 */
41public final class ShortcutsUpdater {
42
43 private final ScopedPreferences mPrefs;
44 private final Context mContext;
45
46 public ShortcutsUpdater(Context context, ScopedPreferences prefs) {
47 mContext = context;
48 mPrefs = prefs;
49 }
50
51 public void update(Collection<RootInfo> roots) {
Tony Huang48974eb2019-02-14 16:24:31 +080052 if (!Shared.isLauncherEnabled(mContext)) {
53 return;
54 }
55
Steve McKay0ce04b72017-06-05 13:23:54 -070056 ShortcutManager mgr = mContext.getSystemService(ShortcutManager.class);
57
58 Map<String, ShortcutInfo> existing = getPinnedShortcuts(mgr);
59 List<ShortcutInfo> devices = getDeviceShortcuts(roots);
60 List<String> deviceIds = new ArrayList<>();
61 for (ShortcutInfo s : devices) {
62 deviceIds.add(s.getId());
63 }
64
65 mgr.setDynamicShortcuts(devices.subList(0, getNumDynSlots(mgr, devices.size())));
66
67 // Mark any shortcut that doesn't correspond to a current root as disabled.
68 List<String> disabled = new ArrayList<>();
69 for (String id : existing.keySet()) {
70 // If it isn't in candidates, it isn't a live target, so we disable it.
71 if (!deviceIds.contains(id)) {
72 disabled.add(id);
73 }
74 }
75
76 mgr.enableShortcuts(deviceIds);
77 mgr.disableShortcuts(disabled);
78 }
79
80 /**
81 * Return at most four awesome devices/roots to include as dynamic shortcuts.
82 */
83 private List<ShortcutInfo> getDeviceShortcuts(Collection<RootInfo> roots) {
84 List<ShortcutInfo> devices = new ArrayList<>();
85 for (RootInfo root : roots) {
86 String id = root.getUri().toString();
87 // TODO: Hook up third party providers. For now, there may be dupes when
88 // user has multiple accounts installed, and the plain title doesn't
89 // disambiguate for the user. So, we don't add them.
90 // if (!Providers.isSystemProvider(root.authority)) {
91 // // add third party providers at the beginning of the list.
92 // devices.add(createShortcut(root, R.drawable.ic_folder_shortcut));
93 // } else
94 if (root.isAdvanced() && root.authority.equals(Providers.AUTHORITY_STORAGE)) {
95 // internal storage
96 if (mPrefs.getShowDeviceRoot()) {
97 devices.add(0, createShortcut(root, R.drawable.ic_advanced_shortcut));
98 }
99 } else if (root.isAdvanced()) {
100 // probably just bugreports provider
101 devices.add(0, createShortcut(root, R.drawable.ic_folder_shortcut));
102 }
103 // TODO: Hook up USB and MTP devices. In order to do this we need
104 // to fire up a broadcast to listen for ACTION_MEDIA_MOUNTED
105 // and ACTION_MEDIA_REMOVED. But doing so now would require a good
106 // bit of refactoring, rendering out of scope for now. <sadface>.
107 // else if (root.isUsb() || root.isMtp()) {
108 // // probably just bugreports provider
109 // devices.add(0, createShortcut(root, R.drawable.ic_usb_shortcut));
110 // }
111 }
112
113 return devices;
114 }
115
116 private Map<String, ShortcutInfo> getPinnedShortcuts(ShortcutManager mgr) {
117 Map<String, ShortcutInfo> pinned = new HashMap<>();
118 for (ShortcutInfo s : mgr.getDynamicShortcuts()) {
119 pinned.put(s.getId(), s);
120 }
121 return pinned;
122 }
123
124 private int getNumDynSlots(ShortcutManager mgr, int numDevices) {
Tony Huang057e9872018-11-05 11:23:00 +0800125 int slots = mgr.getMaxShortcutCountPerActivity() - mgr.getManifestShortcuts().size();
Steve McKay0ce04b72017-06-05 13:23:54 -0700126 return numDevices >= slots ? slots : numDevices;
127 }
128
129 private ShortcutInfo createShortcut(RootInfo root, @DrawableRes int resId) {
130 Intent intent = new Intent(mContext, FilesActivity.class);
131 intent.setAction(Intent.ACTION_VIEW);
132 intent.setData(root.getUri());
133
134 return new ShortcutInfo.Builder(mContext, root.getUri().toString())
135 .setShortLabel(root.title)
136 .setIcon(Icon.createWithResource(mContext, resId))
137 .setIntent(intent)
138 .build();
139 }
140}