12423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood/*
22423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * Copyright (C) 2010 The Android Open Source Project
32423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood *
42423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
52423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * you may not use this file except in compliance with the License.
62423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * You may obtain a copy of the License at
72423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood *
82423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
92423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood *
102423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * Unless required by applicable law or agreed to in writing, software
112423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
122423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1346d0adf8256a42416584765625852b6e48497c90Mike Lockwood * See the License for the specific language governing permissions an
142423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * limitations under the License.
152423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood */
162423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood
1702eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodpackage com.android.server.usb;
182423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood
193a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwoodimport android.app.PendingIntent;
20460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brownimport android.app.admin.DevicePolicyManager;
21fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.content.BroadcastReceiver;
222423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwoodimport android.content.Context;
23fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.content.Intent;
24fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.content.IntentFilter;
2502eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodimport android.content.pm.PackageManager;
26c4308f01c965571dc2354107c3574df113e397eeMike Lockwoodimport android.hardware.usb.IUsbManager;
27c4308f01c965571dc2354107c3574df113e397eeMike Lockwoodimport android.hardware.usb.UsbAccessory;
28c4308f01c965571dc2354107c3574df113e397eeMike Lockwoodimport android.hardware.usb.UsbDevice;
29460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brownimport android.hardware.usb.UsbManager;
3076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brownimport android.hardware.usb.UsbPort;
3176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brownimport android.hardware.usb.UsbPortStatus;
3276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brownimport android.os.Binder;
33e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodimport android.os.Bundle;
34e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodimport android.os.ParcelFileDescriptor;
35fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.os.UserHandle;
362a67840c3c35a6267663e5d3ae921ee9ac614db9Jeff Brownimport android.os.UserManager;
37460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brownimport android.util.Slog;
38fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.util.SparseArray;
39fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
408b2c3a14603d163d7564e6f60286995079687690Jeff Sharkeyimport com.android.internal.annotations.GuardedBy;
41fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter;
4276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brownimport com.android.internal.util.Preconditions;
432cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinskiimport com.android.server.SystemService;
442423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood
452423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwoodimport java.io.File;
4602eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodimport java.io.FileDescriptor;
4702eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodimport java.io.PrintWriter;
482423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood
492423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood/**
5046d0adf8256a42416584765625852b6e48497c90Mike Lockwood * UsbService manages all USB related state, including both host and device support.
5146d0adf8256a42416584765625852b6e48497c90Mike Lockwood * Host related events and calls are delegated to UsbHostManager, and device related
5246d0adf8256a42416584765625852b6e48497c90Mike Lockwood * support is delegated to UsbDeviceManager.
532423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood */
5402eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodpublic class UsbService extends IUsbManager.Stub {
552cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski
562cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski    public static class Lifecycle extends SystemService {
572cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        private UsbService mUsbService;
582cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski
592cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        public Lifecycle(Context context) {
602cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski            super(context);
612cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        }
622cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski
632cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        @Override
642cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        public void onStart() {
652cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski            mUsbService = new UsbService(getContext());
662cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski            publishBinderService(Context.USB_SERVICE, mUsbService);
672cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        }
682cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski
692cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        @Override
702cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        public void onBootPhase(int phase) {
712cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
722cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski                mUsbService.systemReady();
73460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
74460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown                mUsbService.bootCompleted();
752cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski            }
762cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        }
772cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski    }
782cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski
79fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    private static final String TAG = "UsbService";
80fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
812423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood    private final Context mContext;
82fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
8346d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private UsbDeviceManager mDeviceManager;
8446d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private UsbHostManager mHostManager;
8576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    private UsbPortManager mPortManager;
862e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood    private final UsbAlsaManager mAlsaManager;
87ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood
88fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    private final Object mLock = new Object();
89fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
90fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    /** Map from {@link UserHandle} to {@link UsbSettingsManager} */
918b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey    @GuardedBy("mLock")
92fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    private final SparseArray<UsbSettingsManager>
93fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            mSettingsByUser = new SparseArray<UsbSettingsManager>();
94fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
95fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    private UsbSettingsManager getSettingsForUser(int userId) {
96fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        synchronized (mLock) {
97fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            UsbSettingsManager settings = mSettingsByUser.get(userId);
98fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            if (settings == null) {
99fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey                settings = new UsbSettingsManager(mContext, new UserHandle(userId));
100fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey                mSettingsByUser.put(userId, settings);
101fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            }
102fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            return settings;
103fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        }
104fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    }
1051c0e543638fa940651b675645146fd71c2ebd9b9Mike Lockwood
106770126a678ccc9328a89407ffc82f4d998b25427Mike Lockwood    public UsbService(Context context) {
107770126a678ccc9328a89407ffc82f4d998b25427Mike Lockwood        mContext = context;
108fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
1092e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood        mAlsaManager = new UsbAlsaManager(context);
1102e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood
111fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final PackageManager pm = mContext.getPackageManager();
11246d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
1132e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood            mHostManager = new UsbHostManager(context, mAlsaManager);
1142423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood        }
11502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        if (new File("/sys/class/android_usb").exists()) {
1162e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood            mDeviceManager = new UsbDeviceManager(context, mAlsaManager);
117fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        }
11876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        if (mHostManager != null || mDeviceManager != null) {
11976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            mPortManager = new UsbPortManager(context);
12076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        }
121fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
122233d94c0df13a7e54f738f442457cebc62294384Xiaohui Chen        setCurrentUser(UserHandle.USER_SYSTEM);
123fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
124460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        final IntentFilter filter = new IntentFilter();
125460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
126460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        filter.addAction(Intent.ACTION_USER_SWITCHED);
127460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        filter.addAction(Intent.ACTION_USER_STOPPED);
128460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
129460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        mContext.registerReceiver(mReceiver, filter, null, null);
130fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    }
131fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
132460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
133fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        @Override
134fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        public void onReceive(Context context, Intent intent) {
135fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
136fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            final String action = intent.getAction();
137fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
138fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey                setCurrentUser(userId);
139fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
140fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey                synchronized (mLock) {
141fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey                    mSettingsByUser.remove(userId);
142fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey                }
143460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
144460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown                    .equals(action)) {
145460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown                if (mDeviceManager != null) {
146460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown                    mDeviceManager.updateUserRestrictions();
147460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown                }
148fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            }
149fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        }
150fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    };
151fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
152fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    private void setCurrentUser(int userId) {
153fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final UsbSettingsManager userSettings = getSettingsForUser(userId);
154fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        if (mHostManager != null) {
155fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            mHostManager.setCurrentSettings(userSettings);
156fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        }
157fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        if (mDeviceManager != null) {
158460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            mDeviceManager.setCurrentUser(userId, userSettings);
159a8e3a898a2bc004ca1fcd278b68f5da5c344afbbMike Lockwood        }
160da39f0e87814c5acb8b6319a1877b93197fb910eMike Lockwood    }
161da39f0e87814c5acb8b6319a1877b93197fb910eMike Lockwood
16202eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    public void systemReady() {
1632e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood        mAlsaManager.systemReady();
1642e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood
16546d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (mDeviceManager != null) {
16646d0adf8256a42416584765625852b6e48497c90Mike Lockwood            mDeviceManager.systemReady();
16746d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
16846d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (mHostManager != null) {
16946d0adf8256a42416584765625852b6e48497c90Mike Lockwood            mHostManager.systemReady();
1702423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood        }
17176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        if (mPortManager != null) {
17276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            mPortManager.systemReady();
17376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        }
1742423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood    }
1752423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood
176460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    public void bootCompleted() {
177460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        if (mDeviceManager != null) {
178460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            mDeviceManager.bootCompleted();
179460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        }
180460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    }
181460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown
182ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood    /* Returns a list of all currently attached USB devices (host mdoe) */
183fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
184e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public void getDeviceList(Bundle devices) {
18546d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (mHostManager != null) {
18646d0adf8256a42416584765625852b6e48497c90Mike Lockwood            mHostManager.getDeviceList(devices);
187e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        }
188e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
189e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
190ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood    /* Opens the specified USB device (host mode) */
191fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
192e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public ParcelFileDescriptor openDevice(String deviceName) {
19346d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (mHostManager != null) {
19446d0adf8256a42416584765625852b6e48497c90Mike Lockwood            return mHostManager.openDevice(deviceName);
19546d0adf8256a42416584765625852b6e48497c90Mike Lockwood        } else {
19646d0adf8256a42416584765625852b6e48497c90Mike Lockwood            return null;
1978b682ad08a8e55b3ce2cf58f3aff6d3464ab668bMike Lockwood        }
198e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
199e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
200ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood    /* returns the currently attached USB accessory (device mode) */
201fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
2029182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood    public UsbAccessory getCurrentAccessory() {
20346d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (mDeviceManager != null) {
20446d0adf8256a42416584765625852b6e48497c90Mike Lockwood            return mDeviceManager.getCurrentAccessory();
20546d0adf8256a42416584765625852b6e48497c90Mike Lockwood        } else {
20646d0adf8256a42416584765625852b6e48497c90Mike Lockwood            return null;
20746d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
2089182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood    }
2099182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood
210ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood    /* opens the currently attached USB accessory (device mode) */
211fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
21202eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
21346d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (mDeviceManager != null) {
21402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            return mDeviceManager.openAccessory(accessory);
21546d0adf8256a42416584765625852b6e48497c90Mike Lockwood        } else {
21646d0adf8256a42416584765625852b6e48497c90Mike Lockwood            return null;
21702eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood        }
21802eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
21902eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
220fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
221fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public void setDevicePackage(UsbDevice device, String packageName, int userId) {
2227a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
223fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        getSettingsForUser(userId).setDevicePackage(device, packageName);
22402eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
22502eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
226fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
227fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public void setAccessoryPackage(UsbAccessory accessory, String packageName, int userId) {
2287a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
229fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        getSettingsForUser(userId).setAccessoryPackage(accessory, packageName);
23002eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
23102eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
232fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
2333a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood    public boolean hasDevicePermission(UsbDevice device) {
234fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final int userId = UserHandle.getCallingUserId();
235fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        return getSettingsForUser(userId).hasPermission(device);
2363a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood    }
2373a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood
238fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
2393a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood    public boolean hasAccessoryPermission(UsbAccessory accessory) {
240fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final int userId = UserHandle.getCallingUserId();
241fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        return getSettingsForUser(userId).hasPermission(accessory);
2423a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood    }
2433a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood
244fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
245fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) {
246fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final int userId = UserHandle.getCallingUserId();
247fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        getSettingsForUser(userId).requestPermission(device, packageName, pi);
2483a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood    }
2493a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood
250fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
251fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public void requestAccessoryPermission(
252fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            UsbAccessory accessory, String packageName, PendingIntent pi) {
253fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final int userId = UserHandle.getCallingUserId();
254fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        getSettingsForUser(userId).requestPermission(accessory, packageName, pi);
2553a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood    }
2563a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood
257fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
25802eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    public void grantDevicePermission(UsbDevice device, int uid) {
2597a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
260fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final int userId = UserHandle.getUserId(uid);
261fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        getSettingsForUser(userId).grantDevicePermission(device, uid);
26202eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
26302eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
264fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
26502eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    public void grantAccessoryPermission(UsbAccessory accessory, int uid) {
2667a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
267fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final int userId = UserHandle.getUserId(uid);
268fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        getSettingsForUser(userId).grantAccessoryPermission(accessory, uid);
26902eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
27002eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
271fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
272fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public boolean hasDefaults(String packageName, int userId) {
2737a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
274fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        return getSettingsForUser(userId).hasDefaults(packageName);
27502eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
27602eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
277fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
278fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public void clearDefaults(String packageName, int userId) {
2797a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
280fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        getSettingsForUser(userId).clearDefaults(packageName);
2819182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood    }
2829182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood
283fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
284460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    public boolean isFunctionEnabled(String function) {
285460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
286460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        return mDeviceManager != null && mDeviceManager.isFunctionEnabled(function);
287460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    }
288460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown
289460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    @Override
290fcf10f7c12cb3107bdfedce6f76a8c866d154f3cNick Kralevich    public void setCurrentFunction(String function) {
29102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
2921848d31c2cbb5404be383ad44049e58e36b258baEmily Bernier
293460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        if (!isSupportedCurrentFunction(function)) {
294460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            Slog.w(TAG, "Caller of setCurrentFunction() requested unsupported USB function: "
295460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown                    + function);
296460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            function = UsbManager.USB_FUNCTION_NONE;
2971848d31c2cbb5404be383ad44049e58e36b258baEmily Bernier        }
2981848d31c2cbb5404be383ad44049e58e36b258baEmily Bernier
29902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        if (mDeviceManager != null) {
300fcf10f7c12cb3107bdfedce6f76a8c866d154f3cNick Kralevich            mDeviceManager.setCurrentFunctions(function);
30102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        } else {
30202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            throw new IllegalStateException("USB device mode not supported");
30302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        }
30402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    }
30502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
306460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    private static boolean isSupportedCurrentFunction(String function) {
307460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        if (function == null) return true;
308460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown
309460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        switch (function) {
310460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            case UsbManager.USB_FUNCTION_NONE:
311460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            case UsbManager.USB_FUNCTION_AUDIO_SOURCE:
312460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            case UsbManager.USB_FUNCTION_MIDI:
313460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            case UsbManager.USB_FUNCTION_MTP:
314460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            case UsbManager.USB_FUNCTION_PTP:
315460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            case UsbManager.USB_FUNCTION_RNDIS:
316460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown                return true;
317460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        }
318460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown
319460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        return false;
320460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    }
321460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown
322fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
323674019065bceb4150190bfb1aa63cda9de0a8560Nick Kralevich    public void setUsbDataUnlocked(boolean unlocked) {
324674019065bceb4150190bfb1aa63cda9de0a8560Nick Kralevich        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
325674019065bceb4150190bfb1aa63cda9de0a8560Nick Kralevich        mDeviceManager.setUsbDataUnlocked(unlocked);
326674019065bceb4150190bfb1aa63cda9de0a8560Nick Kralevich    }
327674019065bceb4150190bfb1aa63cda9de0a8560Nick Kralevich
328674019065bceb4150190bfb1aa63cda9de0a8560Nick Kralevich    @Override
3294e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
3304e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
3314e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
3324e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
3334e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
334fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
3354e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    public void denyUsbDebugging() {
3364e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
3374e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        mDeviceManager.denyUsbDebugging();
3384e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
3394e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
34002eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    @Override
341cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    public void clearUsbDebuggingKeys() {
342cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
343cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby        mDeviceManager.clearUsbDebuggingKeys();
344cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    }
345cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby
346cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    @Override
34776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    public UsbPort[] getPorts() {
34876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
34902eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
35076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        final long ident = Binder.clearCallingIdentity();
35176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        try {
35276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            return mPortManager != null ? mPortManager.getPorts() : null;
35376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        } finally {
35476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            Binder.restoreCallingIdentity(ident);
35502eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood        }
35676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    }
35776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown
35876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    @Override
35976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    public UsbPortStatus getPortStatus(String portId) {
36076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        Preconditions.checkNotNull(portId, "portId must not be null");
36176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
36276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown
36376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        final long ident = Binder.clearCallingIdentity();
36476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        try {
36576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            return mPortManager != null ? mPortManager.getPortStatus(portId) : null;
36676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        } finally {
36776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            Binder.restoreCallingIdentity(ident);
36846d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
36976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    }
370fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
37176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    @Override
37276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    public void setPortRoles(String portId, int powerRole, int dataRole) {
37376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        Preconditions.checkNotNull(portId, "portId must not be null");
37476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        UsbPort.checkRoles(powerRole, dataRole);
37576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
37676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown
37776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        final long ident = Binder.clearCallingIdentity();
37876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        try {
37976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            if (mPortManager != null) {
38076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                mPortManager.setPortRoles(portId, powerRole, dataRole, null);
38176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            }
38276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        } finally {
38376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            Binder.restoreCallingIdentity(ident);
38476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        }
38576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    }
38676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown
38776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    @Override
38876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
38976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
39076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown
39176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
39276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        final long ident = Binder.clearCallingIdentity();
39376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        try {
39476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            if (args == null || args.length == 0 || "-a".equals(args[0])) {
39576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("USB Manager State:");
3962dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brown                pw.increaseIndent();
39776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mDeviceManager != null) {
39876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mDeviceManager.dump(pw);
39976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
40076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mHostManager != null) {
40176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mHostManager.dump(pw);
40276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
40376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
40476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
40576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
40676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                mAlsaManager.dump(pw);
40776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown
40876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                synchronized (mLock) {
40976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    for (int i = 0; i < mSettingsByUser.size(); i++) {
41076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        final int userId = mSettingsByUser.keyAt(i);
41176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        final UsbSettingsManager settings = mSettingsByUser.valueAt(i);
41276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.println("Settings for user " + userId + ":");
41376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.increaseIndent();
41476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        settings.dump(pw);
41576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.decreaseIndent();
41676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    }
41776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
41876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else if (args.length == 4 && "set-port-roles".equals(args[0])) {
41976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final String portId = args[1];
42076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final int powerRole;
42176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                switch (args[2]) {
42276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "source":
42376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        powerRole = UsbPort.POWER_ROLE_SOURCE;
42476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
42576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "sink":
42676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        powerRole = UsbPort.POWER_ROLE_SINK;
42776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
42876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "no-power":
42976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        powerRole = 0;
43076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
43176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    default:
43276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.println("Invalid power role: " + args[2]);
43376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        return;
43476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
43576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final int dataRole;
43676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                switch (args[3]) {
43776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "host":
43876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        dataRole = UsbPort.DATA_ROLE_HOST;
43976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
44076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "device":
44176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        dataRole = UsbPort.DATA_ROLE_DEVICE;
44276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
44376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "no-data":
44476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        dataRole = 0;
44576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
44676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    default:
44776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.println("Invalid data role: " + args[3]);
44876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        return;
44976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
45076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
45176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.setPortRoles(portId, powerRole, dataRole, pw);
45276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    // Note: It might take some time for the side-effects of this operation
45376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    // to be fully applied by the kernel since the driver may need to
45476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    // renegotiate the USB port mode.  If this proves to be an issue
45576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    // during debugging, it might be worth adding a sleep here before
45676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    // dumping the new state.
45776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    pw.println();
45876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
45976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
46076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else if (args.length == 3 && "add-port".equals(args[0])) {
46176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final String portId = args[1];
46276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final int supportedModes;
46376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                switch (args[2]) {
46476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "ufp":
46576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        supportedModes = UsbPort.MODE_UFP;
46676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
46776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "dfp":
46876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        supportedModes = UsbPort.MODE_DFP;
46976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
47076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "dual":
47176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        supportedModes = UsbPort.MODE_DUAL;
47276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
47376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "none":
47476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        supportedModes = 0;
47576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
47676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    default:
47776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.println("Invalid mode: " + args[2]);
47876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        return;
47976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
48076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
48176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.addSimulatedPort(portId, supportedModes, pw);
48276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    pw.println();
48376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
48476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
48576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else if (args.length == 5 && "connect-port".equals(args[0])) {
48676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final String portId = args[1];
48776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final int mode;
48876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final boolean canChangeMode = args[2].endsWith("?");
48976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                switch (canChangeMode ? removeLastChar(args[2]) : args[2]) {
49076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "ufp":
49176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        mode = UsbPort.MODE_UFP;
49276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
49376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "dfp":
49476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        mode = UsbPort.MODE_DFP;
49576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
49676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    default:
49776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.println("Invalid mode: " + args[2]);
49876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        return;
49976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
50076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final int powerRole;
50176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final boolean canChangePowerRole = args[3].endsWith("?");
50276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                switch (canChangePowerRole ? removeLastChar(args[3]) : args[3]) {
50376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "source":
50476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        powerRole = UsbPort.POWER_ROLE_SOURCE;
50576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
50676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "sink":
50776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        powerRole = UsbPort.POWER_ROLE_SINK;
50876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
50976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    default:
51076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.println("Invalid power role: " + args[3]);
51176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        return;
51276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
51376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final int dataRole;
51476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final boolean canChangeDataRole = args[4].endsWith("?");
51576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                switch (canChangeDataRole ? removeLastChar(args[4]) : args[4]) {
51676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "host":
51776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        dataRole = UsbPort.DATA_ROLE_HOST;
51876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
51976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "device":
52076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        dataRole = UsbPort.DATA_ROLE_DEVICE;
52176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
52276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    default:
52376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.println("Invalid data role: " + args[4]);
52476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        return;
52576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
52676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
52776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.connectSimulatedPort(portId, mode, canChangeMode,
52876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                            powerRole, canChangePowerRole, dataRole, canChangeDataRole, pw);
52976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    pw.println();
53076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
53176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
53276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else if (args.length == 2 && "disconnect-port".equals(args[0])) {
53376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final String portId = args[1];
53476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
53576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.disconnectSimulatedPort(portId, pw);
53676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    pw.println();
53776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
53876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
53976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else if (args.length == 2 && "remove-port".equals(args[0])) {
54076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final String portId = args[1];
54176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
54276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.removeSimulatedPort(portId, pw);
54376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    pw.println();
54476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
54576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
54676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else if (args.length == 1 && "reset".equals(args[0])) {
54776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
54876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.resetSimulation(pw);
54976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    pw.println();
55076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
55176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
55276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else if (args.length == 1 && "ports".equals(args[0])) {
55376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
55476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
55576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
55676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else {
55776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("Dump current USB state or issue command:");
55876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  ports");
55976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  set-port-roles <id> <source|sink|no-power> <host|device|no-data>");
56076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  add-port <id> <ufp|dfp|dual|none>");
56176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  connect-port <id> <ufp|dfp><?> <source|sink><?> <host|device><?>");
56276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("    (add ? suffix if mode, power role, or data role can be changed)");
56376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  disconnect-port <id>");
56476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  remove-port <id>");
56576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  reset");
56676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println();
56776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("Example USB type C port role switch:");
56876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb set-port-roles \"default\" source device");
56976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println();
57076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("Example USB type C port simulation with full capabilities:");
57176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb add-port \"matrix\" dual");
57276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb connect-port \"matrix\" ufp? sink? device?");
57376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb ports");
57476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb disconnect-port \"matrix\"");
57576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb remove-port \"matrix\"");
57676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb reset");
57776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println();
57876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("Example USB type C port where only power role can be changed:");
57976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb add-port \"matrix\" dual");
58076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb connect-port \"matrix\" dfp source? host");
58176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb reset");
58276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println();
58376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("Example USB OTG port where id pin determines function:");
58476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb add-port \"matrix\" dual");
58576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb connect-port \"matrix\" dfp source host");
58676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb reset");
58776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println();
58876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("Example USB device-only port:");
58976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb add-port \"matrix\" ufp");
59076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb connect-port \"matrix\" ufp sink device");
59176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb reset");
592fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            }
59376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        } finally {
59476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            Binder.restoreCallingIdentity(ident);
595fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        }
59602eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
59776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown
59876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    private static final String removeLastChar(String value) {
59976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        return value.substring(0, value.length() - 1);
60076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    }
6012423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood}
602