OSDN Git Service

Zen Condition text and primary click changes
[android-x86/packages-apps-Settings.git] / src / com / android / settings / deviceinfo / UsbBackend.java
1 /*
2  * Copyright (C) 2015 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.deviceinfo;
17
18 import android.content.Context;
19 import android.content.Intent;
20 import android.content.IntentFilter;
21 import android.content.pm.PackageManager;
22 import android.hardware.usb.UsbManager;
23 import android.hardware.usb.UsbPort;
24 import android.hardware.usb.UsbPortStatus;
25 import android.os.UserHandle;
26 import android.os.UserManager;
27 import android.support.annotation.VisibleForTesting;
28
29 public class UsbBackend {
30
31     public static final int MODE_POWER_MASK  = 0x01;
32     public static final int MODE_POWER_SINK   = 0x00;
33     public static final int MODE_POWER_SOURCE = 0x01;
34
35     public static final int MODE_DATA_MASK  = 0x03 << 1;
36     public static final int MODE_DATA_NONE   = 0x00 << 1;
37     public static final int MODE_DATA_MTP    = 0x01 << 1;
38     public static final int MODE_DATA_PTP    = 0x02 << 1;
39     public static final int MODE_DATA_MIDI   = 0x03 << 1;
40
41     private final boolean mRestricted;
42     private final boolean mRestrictedBySystem;
43     private final boolean mMidi;
44
45     private UsbManager mUsbManager;
46     private UsbPort mPort;
47     private UsbPortStatus mPortStatus;
48
49     private Context mContext;
50
51     public UsbBackend(Context context) {
52         this(context, new UserRestrictionUtil(context));
53     }
54
55     @VisibleForTesting
56     public UsbBackend(Context context, UserRestrictionUtil userRestrictionUtil) {
57         mContext = context;
58         mUsbManager = context.getSystemService(UsbManager.class);
59
60         mRestricted = userRestrictionUtil.isUsbFileTransferRestricted();
61         mRestrictedBySystem = userRestrictionUtil.isUsbFileTransferRestrictedBySystem();
62         mMidi = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
63
64         UsbPort[] ports = mUsbManager.getPorts();
65         if (ports == null) {
66             return;
67         }
68         // For now look for a connected port, in the future we should identify port in the
69         // notification and pick based on that.
70         final int N = ports.length;
71         for (int i = 0; i < N; i++) {
72             UsbPortStatus status = mUsbManager.getPortStatus(ports[i]);
73             if (status.isConnected()) {
74                 mPort = ports[i];
75                 mPortStatus = status;
76                 break;
77             }
78         }
79     }
80
81     public int getCurrentMode() {
82         if (mPort != null) {
83             int power = mPortStatus.getCurrentPowerRole() == UsbPort.POWER_ROLE_SOURCE
84                     ? MODE_POWER_SOURCE : MODE_POWER_SINK;
85             return power | getUsbDataMode();
86         }
87         return MODE_POWER_SINK | getUsbDataMode();
88     }
89
90     public int getUsbDataMode() {
91         if (!isUsbDataUnlocked()) {
92             return MODE_DATA_NONE;
93         } else if (mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_MTP)) {
94             return MODE_DATA_MTP;
95         } else if (mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_PTP)) {
96             return MODE_DATA_PTP;
97         } else if (mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_MIDI)) {
98             return MODE_DATA_MIDI;
99         }
100         return MODE_DATA_NONE; // ...
101     }
102
103     private boolean isUsbDataUnlocked() {
104         Intent intent = mContext.registerReceiver(null,
105             new IntentFilter(UsbManager.ACTION_USB_STATE));
106         return intent == null ?
107             false : intent.getBooleanExtra(UsbManager.USB_DATA_UNLOCKED, false);
108     }
109
110     private void setUsbFunction(int mode) {
111         switch (mode) {
112             case MODE_DATA_MTP:
113                 mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP, true);
114                 break;
115             case MODE_DATA_PTP:
116                 mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_PTP, true);
117                 break;
118             case MODE_DATA_MIDI:
119                 mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MIDI, true);
120                 break;
121             default:
122                 mUsbManager.setCurrentFunction(null, false);
123                 break;
124         }
125     }
126
127     public void setMode(int mode) {
128         if (mPort != null) {
129             int powerRole = modeToPower(mode);
130             // If we aren't using any data modes and we support host mode, then go to host mode
131             // so maybe? the other device can provide data if it wants, otherwise go into device
132             // mode because we have no choice.
133             int dataRole = (mode & MODE_DATA_MASK) == MODE_DATA_NONE
134                     && mPortStatus.isRoleCombinationSupported(powerRole, UsbPort.DATA_ROLE_HOST)
135                     ? UsbPort.DATA_ROLE_HOST : UsbPort.DATA_ROLE_DEVICE;
136             mUsbManager.setPortRoles(mPort, powerRole, dataRole);
137         }
138         setUsbFunction(mode & MODE_DATA_MASK);
139     }
140
141     private int modeToPower(int mode) {
142         return (mode & MODE_POWER_MASK) == MODE_POWER_SOURCE
143                     ? UsbPort.POWER_ROLE_SOURCE : UsbPort.POWER_ROLE_SINK;
144     }
145
146     public boolean isModeDisallowed(int mode) {
147         if (mRestricted && (mode & MODE_DATA_MASK) != MODE_DATA_NONE
148                 && (mode & MODE_DATA_MASK) != MODE_DATA_MIDI) {
149             // No USB data modes are supported.
150             return true;
151         }
152         return false;
153     }
154
155     public boolean isModeDisallowedBySystem(int mode) {
156         if (mRestrictedBySystem && (mode & MODE_DATA_MASK) != MODE_DATA_NONE
157                 && (mode & MODE_DATA_MASK) != MODE_DATA_MIDI) {
158             // No USB data modes are supported.
159             return true;
160         }
161         return false;
162     }
163
164     public boolean isModeSupported(int mode) {
165         if (!mMidi && (mode & MODE_DATA_MASK) == MODE_DATA_MIDI) {
166             return false;
167         }
168
169         if (mPort != null) {
170             int power = modeToPower(mode);
171             if ((mode & MODE_DATA_MASK) != 0) {
172                 // We have a port and data, need to be in device mode.
173                 return mPortStatus.isRoleCombinationSupported(power,
174                         UsbPort.DATA_ROLE_DEVICE);
175             } else {
176                 // No data needed, we can do this power mode in either device or host.
177                 return mPortStatus.isRoleCombinationSupported(power, UsbPort.DATA_ROLE_DEVICE)
178                         || mPortStatus.isRoleCombinationSupported(power, UsbPort.DATA_ROLE_HOST);
179             }
180         }
181         // No port, support sink modes only.
182         return (mode & MODE_POWER_MASK) != MODE_POWER_SOURCE;
183     }
184
185     // Wrapper class to enable testing with UserManager APIs
186     public static class UserRestrictionUtil {
187         private UserManager mUserManager;
188
189         public UserRestrictionUtil(Context context) {
190             mUserManager = UserManager.get(context);
191         }
192
193         public boolean isUsbFileTransferRestricted() {
194             return mUserManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER);
195         }
196
197         public boolean isUsbFileTransferRestrictedBySystem() {
198             return mUserManager.hasBaseUserRestriction(
199                 UserManager.DISALLOW_USB_FILE_TRANSFER, UserHandle.of(UserHandle.myUserId()));
200         }
201     }
202 }