• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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  */
16 package com.android.settings.connecteddevice;
17 
18 import android.content.Context;
19 import android.content.pm.PackageManager;
20 import android.hardware.input.InputManager;
21 import android.util.FeatureFlagUtils;
22 import android.view.InputDevice;
23 
24 import androidx.annotation.VisibleForTesting;
25 import androidx.preference.Preference;
26 import androidx.preference.PreferenceGroup;
27 import androidx.preference.PreferenceScreen;
28 
29 import com.android.settings.bluetooth.BluetoothDeviceUpdater;
30 import com.android.settings.bluetooth.ConnectedBluetoothDeviceUpdater;
31 import com.android.settings.connecteddevice.dock.DockUpdater;
32 import com.android.settings.connecteddevice.stylus.StylusDeviceUpdater;
33 import com.android.settings.connecteddevice.usb.ConnectedUsbDeviceUpdater;
34 import com.android.settings.core.BasePreferenceController;
35 import com.android.settings.core.PreferenceControllerMixin;
36 import com.android.settings.dashboard.DashboardFragment;
37 import com.android.settings.overlay.DockUpdaterFeatureProvider;
38 import com.android.settings.overlay.FeatureFactory;
39 import com.android.settingslib.core.lifecycle.LifecycleObserver;
40 import com.android.settingslib.core.lifecycle.events.OnStart;
41 import com.android.settingslib.core.lifecycle.events.OnStop;
42 
43 /**
44  * Controller to maintain the {@link androidx.preference.PreferenceGroup} for all
45  * connected devices. It uses {@link DevicePreferenceCallback} to add/remove {@link Preference}
46  */
47 public class ConnectedDeviceGroupController extends BasePreferenceController
48         implements PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop,
49         DevicePreferenceCallback {
50 
51     private static final String KEY = "connected_device_list";
52 
53     @VisibleForTesting
54     PreferenceGroup mPreferenceGroup;
55     private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
56     private ConnectedUsbDeviceUpdater mConnectedUsbDeviceUpdater;
57     private DockUpdater mConnectedDockUpdater;
58     private StylusDeviceUpdater mStylusDeviceUpdater;
59     private final PackageManager mPackageManager;
60     private final InputManager mInputManager;
61 
ConnectedDeviceGroupController(Context context)62     public ConnectedDeviceGroupController(Context context) {
63         super(context, KEY);
64         mPackageManager = context.getPackageManager();
65         mInputManager = context.getSystemService(InputManager.class);
66     }
67 
68     @Override
onStart()69     public void onStart() {
70         if (mBluetoothDeviceUpdater != null) {
71             mBluetoothDeviceUpdater.registerCallback();
72             mBluetoothDeviceUpdater.refreshPreference();
73         }
74 
75         if (mConnectedUsbDeviceUpdater != null) {
76             mConnectedUsbDeviceUpdater.registerCallback();
77         }
78 
79         if (mConnectedDockUpdater != null) {
80             mConnectedDockUpdater.registerCallback();
81         }
82 
83         if (mStylusDeviceUpdater != null) {
84             mStylusDeviceUpdater.registerCallback();
85         }
86     }
87 
88     @Override
onStop()89     public void onStop() {
90         if (mBluetoothDeviceUpdater != null) {
91             mBluetoothDeviceUpdater.unregisterCallback();
92         }
93 
94         if (mConnectedUsbDeviceUpdater != null) {
95             mConnectedUsbDeviceUpdater.unregisterCallback();
96         }
97 
98         if (mConnectedDockUpdater != null) {
99             mConnectedDockUpdater.unregisterCallback();
100         }
101 
102         if (mStylusDeviceUpdater != null) {
103             mStylusDeviceUpdater.unregisterCallback();
104         }
105     }
106 
107     @Override
displayPreference(PreferenceScreen screen)108     public void displayPreference(PreferenceScreen screen) {
109         super.displayPreference(screen);
110 
111         mPreferenceGroup = screen.findPreference(KEY);
112         mPreferenceGroup.setVisible(false);
113 
114         if (isAvailable()) {
115             final Context context = screen.getContext();
116             if (mBluetoothDeviceUpdater != null) {
117                 mBluetoothDeviceUpdater.setPrefContext(context);
118                 mBluetoothDeviceUpdater.forceUpdate();
119             }
120 
121             if (mConnectedUsbDeviceUpdater != null) {
122                 mConnectedUsbDeviceUpdater.initUsbPreference(context);
123             }
124 
125             if (mConnectedDockUpdater != null) {
126                 mConnectedDockUpdater.setPreferenceContext(context);
127                 mConnectedDockUpdater.forceUpdate();
128             }
129 
130             if (mStylusDeviceUpdater != null) {
131                 mStylusDeviceUpdater.setPreferenceContext(context);
132                 mStylusDeviceUpdater.forceUpdate();
133             }
134         }
135     }
136 
137     @Override
getAvailabilityStatus()138     public int getAvailabilityStatus() {
139         return (hasBluetoothFeature()
140                 || hasUsbFeature()
141                 || hasUsiStylusFeature()
142                 || mConnectedDockUpdater != null)
143                 ? AVAILABLE_UNSEARCHABLE
144                 : UNSUPPORTED_ON_DEVICE;
145     }
146 
147     @Override
getPreferenceKey()148     public String getPreferenceKey() {
149         return KEY;
150     }
151 
152     @Override
onDeviceAdded(Preference preference)153     public void onDeviceAdded(Preference preference) {
154         if (mPreferenceGroup.getPreferenceCount() == 0) {
155             mPreferenceGroup.setVisible(true);
156         }
157         mPreferenceGroup.addPreference(preference);
158     }
159 
160     @Override
onDeviceRemoved(Preference preference)161     public void onDeviceRemoved(Preference preference) {
162         mPreferenceGroup.removePreference(preference);
163         if (mPreferenceGroup.getPreferenceCount() == 0) {
164             mPreferenceGroup.setVisible(false);
165         }
166     }
167 
168     @VisibleForTesting
init(BluetoothDeviceUpdater bluetoothDeviceUpdater, ConnectedUsbDeviceUpdater connectedUsbDeviceUpdater, DockUpdater connectedDockUpdater, StylusDeviceUpdater connectedStylusDeviceUpdater)169     void init(BluetoothDeviceUpdater bluetoothDeviceUpdater,
170             ConnectedUsbDeviceUpdater connectedUsbDeviceUpdater,
171             DockUpdater connectedDockUpdater,
172             StylusDeviceUpdater connectedStylusDeviceUpdater) {
173 
174         mBluetoothDeviceUpdater = bluetoothDeviceUpdater;
175         mConnectedUsbDeviceUpdater = connectedUsbDeviceUpdater;
176         mConnectedDockUpdater = connectedDockUpdater;
177         mStylusDeviceUpdater = connectedStylusDeviceUpdater;
178     }
179 
init(DashboardFragment fragment)180     public void init(DashboardFragment fragment) {
181         final Context context = fragment.getContext();
182         DockUpdaterFeatureProvider dockUpdaterFeatureProvider =
183                 FeatureFactory.getFactory(context).getDockUpdaterFeatureProvider();
184         final DockUpdater connectedDockUpdater =
185                 dockUpdaterFeatureProvider.getConnectedDockUpdater(context, this);
186         init(hasBluetoothFeature()
187                         ? new ConnectedBluetoothDeviceUpdater(context, this,
188                         fragment.getMetricsCategory())
189                         : null,
190                 hasUsbFeature()
191                         ? new ConnectedUsbDeviceUpdater(context, fragment, this)
192                         : null,
193                 connectedDockUpdater,
194                 hasUsiStylusFeature()
195                         ? new StylusDeviceUpdater(context, fragment, this)
196                         : null);
197     }
198 
hasBluetoothFeature()199     private boolean hasBluetoothFeature() {
200         return mPackageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
201     }
202 
hasUsbFeature()203     private boolean hasUsbFeature() {
204         return mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY)
205                 || mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST);
206     }
207 
hasUsiStylusFeature()208     private boolean hasUsiStylusFeature() {
209         if (!FeatureFlagUtils.isEnabled(mContext,
210                 FeatureFlagUtils.SETTINGS_SHOW_STYLUS_PREFERENCES)) {
211             return false;
212         }
213 
214         for (int deviceId : mInputManager.getInputDeviceIds()) {
215             InputDevice device = mInputManager.getInputDevice(deviceId);
216             if (device != null
217                     && device.supportsSource(InputDevice.SOURCE_STYLUS)
218                     && !device.isExternal()) {
219                 return true;
220             }
221         }
222         return false;
223     }
224 }
225