• 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.usb;
17 
18 import android.content.BroadcastReceiver;
19 import android.content.Context;
20 import android.content.Intent;
21 import android.content.IntentFilter;
22 import android.hardware.usb.UsbManager;
23 import android.hardware.usb.UsbPort;
24 import android.hardware.usb.UsbPortStatus;
25 
26 import com.android.settingslib.core.lifecycle.LifecycleObserver;
27 import com.android.settingslib.core.lifecycle.events.OnResume;
28 import com.android.settingslib.core.lifecycle.events.OnPause;
29 
30 /**
31  * Receiver to receive usb update and use {@link UsbConnectionListener} to invoke callback
32  */
33 public class UsbConnectionBroadcastReceiver extends BroadcastReceiver implements LifecycleObserver,
34         OnResume, OnPause {
35     private Context mContext;
36     private UsbConnectionListener mUsbConnectionListener;
37     private boolean mListeningToUsbEvents;
38     private UsbBackend mUsbBackend;
39 
40     private boolean mConnected;
41     private long mFunctions;
42     private int mDataRole;
43     private int mPowerRole;
44 
UsbConnectionBroadcastReceiver(Context context, UsbConnectionListener usbConnectionListener, UsbBackend backend)45     public UsbConnectionBroadcastReceiver(Context context,
46             UsbConnectionListener usbConnectionListener, UsbBackend backend) {
47         mContext = context;
48         mUsbConnectionListener = usbConnectionListener;
49         mUsbBackend = backend;
50 
51         mFunctions = UsbManager.FUNCTION_NONE;
52         mDataRole = UsbPort.DATA_ROLE_NONE;
53         mPowerRole = UsbPort.POWER_ROLE_NONE;
54     }
55 
56     @Override
onReceive(Context context, Intent intent)57     public void onReceive(Context context, Intent intent) {
58         if (UsbManager.ACTION_USB_STATE.equals(intent.getAction())) {
59             mConnected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED)
60                     || intent.getExtras().getBoolean(UsbManager.USB_HOST_CONNECTED);
61             if (mConnected) {
62                 long functions = UsbManager.FUNCTION_NONE;
63                 if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_MTP)
64                         && intent.getExtras().getBoolean(UsbManager.USB_DATA_UNLOCKED, false)) {
65                     functions |= UsbManager.FUNCTION_MTP;
66                 }
67                 if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_PTP)
68                         && intent.getExtras().getBoolean(UsbManager.USB_DATA_UNLOCKED, false)) {
69                     functions |= UsbManager.FUNCTION_PTP;
70                 }
71                 if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_MIDI)) {
72                     functions |= UsbManager.FUNCTION_MIDI;
73                 }
74                 if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_RNDIS)) {
75                     functions |= UsbManager.FUNCTION_RNDIS;
76                 }
77                 mFunctions = functions;
78                 mDataRole = mUsbBackend.getDataRole();
79                 mPowerRole = mUsbBackend.getPowerRole();
80             }
81         } else if (UsbManager.ACTION_USB_PORT_CHANGED.equals(intent.getAction())) {
82             UsbPortStatus portStatus = intent.getExtras()
83                     .getParcelable(UsbManager.EXTRA_PORT_STATUS);
84             if (portStatus != null) {
85                 mDataRole = portStatus.getCurrentDataRole();
86                 mPowerRole = portStatus.getCurrentPowerRole();
87             }
88         }
89         if (mUsbConnectionListener != null) {
90             mUsbConnectionListener.onUsbConnectionChanged(mConnected, mFunctions, mPowerRole,
91                     mDataRole);
92         }
93     }
94 
register()95     public void register() {
96         if (!mListeningToUsbEvents) {
97             mConnected = false;
98             final IntentFilter intentFilter = new IntentFilter();
99             intentFilter.addAction(UsbManager.ACTION_USB_STATE);
100             intentFilter.addAction(UsbManager.ACTION_USB_PORT_CHANGED);
101             final Intent intent = mContext.registerReceiver(this, intentFilter);
102             // TODO b/77240599 use an api instead of sticky intent
103             if (intent != null) {
104                 onReceive(mContext, intent);
105             }
106             mListeningToUsbEvents = true;
107         }
108     }
109 
unregister()110     public void unregister() {
111         if (mListeningToUsbEvents) {
112             mContext.unregisterReceiver(this);
113             mListeningToUsbEvents = false;
114         }
115     }
116 
isConnected()117     public boolean isConnected() {
118         return mConnected;
119     }
120 
121     @Override
onResume()122     public void onResume() {
123         register();
124     }
125 
126     @Override
onPause()127     public void onPause() {
128         unregister();
129     }
130 
131     /**
132      * Interface definition for a callback to be invoked when usb connection is changed.
133      */
134     interface UsbConnectionListener {
onUsbConnectionChanged(boolean connected, long functions, int powerRole, int dataRole)135         void onUsbConnectionChanged(boolean connected, long functions, int powerRole, int dataRole);
136     }
137 }
138