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
19880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmannimport android.annotation.NonNull;
20031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmannimport android.annotation.UserIdInt;
213a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwoodimport android.app.PendingIntent;
22460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brownimport android.app.admin.DevicePolicyManager;
23fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.content.BroadcastReceiver;
24badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport android.content.ComponentName;
252423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwoodimport android.content.Context;
26fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.content.Intent;
27fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.content.IntentFilter;
2802eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodimport android.content.pm.PackageManager;
29c4308f01c965571dc2354107c3574df113e397eeMike Lockwoodimport android.hardware.usb.IUsbManager;
30c4308f01c965571dc2354107c3574df113e397eeMike Lockwoodimport android.hardware.usb.UsbAccessory;
31c4308f01c965571dc2354107c3574df113e397eeMike Lockwoodimport android.hardware.usb.UsbDevice;
32460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brownimport android.hardware.usb.UsbManager;
3376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brownimport android.hardware.usb.UsbPort;
3476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brownimport android.hardware.usb.UsbPortStatus;
3576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brownimport android.os.Binder;
36e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodimport android.os.Bundle;
37e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodimport android.os.ParcelFileDescriptor;
38fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.os.UserHandle;
392a67840c3c35a6267663e5d3ae921ee9ac614db9Jeff Brownimport android.os.UserManager;
40460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brownimport android.util.Slog;
41fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
428b2c3a14603d163d7564e6f60286995079687690Jeff Sharkeyimport com.android.internal.annotations.GuardedBy;
43fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport com.android.internal.util.DumpUtils;
44fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter;
4576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brownimport com.android.internal.util.Preconditions;
462cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinskiimport com.android.server.SystemService;
472423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood
482423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwoodimport java.io.File;
4902eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodimport java.io.FileDescriptor;
5002eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodimport java.io.PrintWriter;
512423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood
522423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood/**
5346d0adf8256a42416584765625852b6e48497c90Mike Lockwood * UsbService manages all USB related state, including both host and device support.
5446d0adf8256a42416584765625852b6e48497c90Mike Lockwood * Host related events and calls are delegated to UsbHostManager, and device related
5546d0adf8256a42416584765625852b6e48497c90Mike Lockwood * support is delegated to UsbDeviceManager.
562423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood */
5702eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodpublic class UsbService extends IUsbManager.Stub {
582cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski
592cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski    public static class Lifecycle extends SystemService {
602cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        private UsbService mUsbService;
612cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski
622cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        public Lifecycle(Context context) {
632cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski            super(context);
642cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        }
652cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski
662cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        @Override
672cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        public void onStart() {
682cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski            mUsbService = new UsbService(getContext());
692cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski            publishBinderService(Context.USB_SERVICE, mUsbService);
702cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        }
712cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski
722cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        @Override
732cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        public void onBootPhase(int phase) {
742cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
752cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski                mUsbService.systemReady();
76460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
77460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown                mUsbService.bootCompleted();
782cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski            }
792cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski        }
80031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann
81031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        @Override
82031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        public void onSwitchUser(int newUserId) {
83031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            mUsbService.onSwitchUser(newUserId);
84031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        }
85031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann
86031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        @Override
87031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        public void onStopUser(int userHandle) {
88880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann            mUsbService.onStopUser(UserHandle.of(userHandle));
89031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        }
902cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski    }
912cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski
92fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    private static final String TAG = "UsbService";
93fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
942423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood    private final Context mContext;
95031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    private final UserManager mUserManager;
96fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
9746d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private UsbDeviceManager mDeviceManager;
9846d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private UsbHostManager mHostManager;
9976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    private UsbPortManager mPortManager;
1002e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood    private final UsbAlsaManager mAlsaManager;
101ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood
102031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    private final UsbSettingsManager mSettingsManager;
103fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
104031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    /**
105031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * The user id of the current user. There might be several profiles (with separate user ids)
106031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * per user.
107031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     */
1088b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey    @GuardedBy("mLock")
109031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    private @UserIdInt int mCurrentUserId;
110fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
111031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    private final Object mLock = new Object();
112031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann
113031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    private UsbUserSettingsManager getSettingsForUser(@UserIdInt int userIdInt) {
114031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        return mSettingsManager.getSettingsForUser(userIdInt);
115fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    }
1161c0e543638fa940651b675645146fd71c2ebd9b9Mike Lockwood
117770126a678ccc9328a89407ffc82f4d998b25427Mike Lockwood    public UsbService(Context context) {
118770126a678ccc9328a89407ffc82f4d998b25427Mike Lockwood        mContext = context;
119fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
120a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        mUserManager = context.getSystemService(UserManager.class);
121031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        mSettingsManager = new UsbSettingsManager(context);
1222e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood        mAlsaManager = new UsbAlsaManager(context);
1232e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood
124fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final PackageManager pm = mContext.getPackageManager();
12546d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
126031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            mHostManager = new UsbHostManager(context, mAlsaManager, mSettingsManager);
1272423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood        }
12802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        if (new File("/sys/class/android_usb").exists()) {
129031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            mDeviceManager = new UsbDeviceManager(context, mAlsaManager, mSettingsManager);
130fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        }
13176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        if (mHostManager != null || mDeviceManager != null) {
13276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            mPortManager = new UsbPortManager(context);
13376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        }
134fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
135031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        onSwitchUser(UserHandle.USER_SYSTEM);
136fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
137460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        final IntentFilter filter = new IntentFilter();
138460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
139460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
140460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        mContext.registerReceiver(mReceiver, filter, null, null);
141fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    }
142fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
143460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
144fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        @Override
145fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        public void onReceive(Context context, Intent intent) {
146fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            final String action = intent.getAction();
147031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
148460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown                    .equals(action)) {
149460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown                if (mDeviceManager != null) {
150460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown                    mDeviceManager.updateUserRestrictions();
151460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown                }
152fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            }
153fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        }
154fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    };
155fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
156031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    /**
157031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * Set new {@link #mCurrentUserId} and propagate it to other modules.
158031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     *
159031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * @param newUserId The user id of the new current user.
160031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     */
161031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    private void onSwitchUser(@UserIdInt int newUserId) {
162031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        synchronized (mLock) {
163031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            mCurrentUserId = newUserId;
164031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann
165a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            // The following two modules need to know about the current profile group. If they need
166a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            // to distinguish by profile of the user, the id has to be passed in the call to the
167031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            // module.
168a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            UsbProfileGroupSettingsManager settings =
169a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                    mSettingsManager.getSettingsForProfileGroup(UserHandle.of(newUserId));
170031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            if (mHostManager != null) {
171a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                mHostManager.setCurrentUserSettings(settings);
172031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            }
173031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            if (mDeviceManager != null) {
174a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                mDeviceManager.setCurrentUser(newUserId, settings);
175031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            }
176a8e3a898a2bc004ca1fcd278b68f5da5c344afbbMike Lockwood        }
177da39f0e87814c5acb8b6319a1877b93197fb910eMike Lockwood    }
178da39f0e87814c5acb8b6319a1877b93197fb910eMike Lockwood
179031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    /**
180031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * Execute operations when a user is stopped.
181031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     *
182880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann     * @param stoppedUser The user that is stopped
183031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     */
184880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann    private void onStopUser(@NonNull UserHandle stoppedUser) {
185880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann        mSettingsManager.remove(stoppedUser);
186031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    }
187031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann
18802eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    public void systemReady() {
1892e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood        mAlsaManager.systemReady();
1902e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood
19146d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (mDeviceManager != null) {
19246d0adf8256a42416584765625852b6e48497c90Mike Lockwood            mDeviceManager.systemReady();
19346d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
19446d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (mHostManager != null) {
19546d0adf8256a42416584765625852b6e48497c90Mike Lockwood            mHostManager.systemReady();
1962423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood        }
19776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        if (mPortManager != null) {
19876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            mPortManager.systemReady();
19976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        }
2002423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood    }
2012423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood
202460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    public void bootCompleted() {
203460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        if (mDeviceManager != null) {
204460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            mDeviceManager.bootCompleted();
205460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        }
206460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    }
207460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown
208ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood    /* Returns a list of all currently attached USB devices (host mdoe) */
209fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
210e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public void getDeviceList(Bundle devices) {
21146d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (mHostManager != null) {
21246d0adf8256a42416584765625852b6e48497c90Mike Lockwood            mHostManager.getDeviceList(devices);
213e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        }
214e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
215e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
216031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    /**
217031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * Check if the calling user is in the same profile group as the {@link #mCurrentUserId
218031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * current user}.
219031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     *
220031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * @return Iff the caller is in the current user's profile group
221031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     */
222031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    private boolean isCallerInCurrentUserProfileGroupLocked() {
223031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        int userIdInt = UserHandle.getCallingUserId();
224031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann
225031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        long ident = clearCallingIdentity();
226031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        try {
227031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            return mUserManager.isSameProfileGroup(userIdInt, mCurrentUserId);
228031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        } finally {
229031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            restoreCallingIdentity(ident);
230031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        }
231031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    }
232031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann
233ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood    /* Opens the specified USB device (host mode) */
234fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
235e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public ParcelFileDescriptor openDevice(String deviceName) {
236031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        ParcelFileDescriptor fd = null;
237031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann
23846d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (mHostManager != null) {
239031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            synchronized (mLock) {
240031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                if (deviceName != null) {
241031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                    int userIdInt = UserHandle.getCallingUserId();
242031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                    boolean isCurrentUser = isCallerInCurrentUserProfileGroupLocked();
243031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann
244031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                    if (isCurrentUser) {
245031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                        fd = mHostManager.openDevice(deviceName, getSettingsForUser(userIdInt));
246031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                    } else {
247031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                        Slog.w(TAG, "Cannot open " + deviceName + " for user " + userIdInt +
248031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                               " as user is not active.");
249031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                    }
250031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                }
251031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            }
2528b682ad08a8e55b3ce2cf58f3aff6d3464ab668bMike Lockwood        }
253031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann
254031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        return fd;
255e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
256e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
257ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood    /* returns the currently attached USB accessory (device mode) */
258fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
2599182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood    public UsbAccessory getCurrentAccessory() {
26046d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (mDeviceManager != null) {
26146d0adf8256a42416584765625852b6e48497c90Mike Lockwood            return mDeviceManager.getCurrentAccessory();
26246d0adf8256a42416584765625852b6e48497c90Mike Lockwood        } else {
26346d0adf8256a42416584765625852b6e48497c90Mike Lockwood            return null;
26446d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
2659182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood    }
2669182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood
267ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood    /* opens the currently attached USB accessory (device mode) */
268fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
26902eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
27046d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (mDeviceManager != null) {
271031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            int userIdInt = UserHandle.getCallingUserId();
272031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann
273031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            synchronized (mLock) {
274031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                boolean isCurrentUser = isCallerInCurrentUserProfileGroupLocked();
275031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann
276031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                if (isCurrentUser) {
277031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                    return mDeviceManager.openAccessory(accessory, getSettingsForUser(userIdInt));
278031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                } else {
279031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                    Slog.w(TAG, "Cannot open " + accessory + " for user " + userIdInt +
280031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                            " as user is not active.");
281031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                }
282031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            }
28302eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood        }
284031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann
285031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        return null;
28602eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
28702eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
288fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
289fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public void setDevicePackage(UsbDevice device, String packageName, int userId) {
290a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        device = Preconditions.checkNotNull(device);
291a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann
2927a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
293a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann
294a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        UserHandle user = UserHandle.of(userId);
295a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        mSettingsManager.getSettingsForProfileGroup(user).setDevicePackage(device, packageName,
296a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                user);
29702eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
29802eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
299fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
300fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public void setAccessoryPackage(UsbAccessory accessory, String packageName, int userId) {
301a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        accessory = Preconditions.checkNotNull(accessory);
302a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann
3037a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
304a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann
305a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        UserHandle user = UserHandle.of(userId);
306a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        mSettingsManager.getSettingsForProfileGroup(user).setAccessoryPackage(accessory,
307a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                packageName, user);
30802eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
30902eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
310fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
3113a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood    public boolean hasDevicePermission(UsbDevice device) {
312fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final int userId = UserHandle.getCallingUserId();
313fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        return getSettingsForUser(userId).hasPermission(device);
3143a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood    }
3153a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood
316fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
3173a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood    public boolean hasAccessoryPermission(UsbAccessory accessory) {
318fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final int userId = UserHandle.getCallingUserId();
319fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        return getSettingsForUser(userId).hasPermission(accessory);
3203a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood    }
3213a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood
322fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
323fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) {
324fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final int userId = UserHandle.getCallingUserId();
325fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        getSettingsForUser(userId).requestPermission(device, packageName, pi);
3263a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood    }
3273a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood
328fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
329fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public void requestAccessoryPermission(
330fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            UsbAccessory accessory, String packageName, PendingIntent pi) {
331fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final int userId = UserHandle.getCallingUserId();
332fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        getSettingsForUser(userId).requestPermission(accessory, packageName, pi);
3333a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood    }
3343a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood
335fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
33602eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    public void grantDevicePermission(UsbDevice device, int uid) {
3377a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
338fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final int userId = UserHandle.getUserId(uid);
339fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        getSettingsForUser(userId).grantDevicePermission(device, uid);
34002eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
34102eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
342fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
34302eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    public void grantAccessoryPermission(UsbAccessory accessory, int uid) {
3447a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
345fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        final int userId = UserHandle.getUserId(uid);
346fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        getSettingsForUser(userId).grantAccessoryPermission(accessory, uid);
34702eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
34802eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
349fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
350fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public boolean hasDefaults(String packageName, int userId) {
351a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        packageName = Preconditions.checkStringNotEmpty(packageName);
352a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann
3537a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
354a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann
355a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        UserHandle user = UserHandle.of(userId);
356a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        return mSettingsManager.getSettingsForProfileGroup(user).hasDefaults(packageName, user);
35702eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
35802eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
359fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
360fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public void clearDefaults(String packageName, int userId) {
361a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        packageName = Preconditions.checkStringNotEmpty(packageName);
362a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann
3637a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
364a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann
365a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        UserHandle user = UserHandle.of(userId);
366a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        mSettingsManager.getSettingsForProfileGroup(user).clearDefaults(packageName, user);
3679182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood    }
3689182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood
369fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
370460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    public boolean isFunctionEnabled(String function) {
371460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
372460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        return mDeviceManager != null && mDeviceManager.isFunctionEnabled(function);
373460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    }
374460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown
375460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    @Override
3767a396be6d5ba8914933a54b5bfac25e118db0e9fJerry Zhang    public void setCurrentFunction(String function, boolean usbDataUnlocked) {
37702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
3781848d31c2cbb5404be383ad44049e58e36b258baEmily Bernier
379460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        if (!isSupportedCurrentFunction(function)) {
380460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            Slog.w(TAG, "Caller of setCurrentFunction() requested unsupported USB function: "
381460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown                    + function);
382460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            function = UsbManager.USB_FUNCTION_NONE;
3831848d31c2cbb5404be383ad44049e58e36b258baEmily Bernier        }
3841848d31c2cbb5404be383ad44049e58e36b258baEmily Bernier
38502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        if (mDeviceManager != null) {
3867a396be6d5ba8914933a54b5bfac25e118db0e9fJerry Zhang            mDeviceManager.setCurrentFunctions(function, usbDataUnlocked);
38702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        } else {
38802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            throw new IllegalStateException("USB device mode not supported");
38902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        }
39002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    }
39102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
392460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    private static boolean isSupportedCurrentFunction(String function) {
393460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        if (function == null) return true;
394460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown
395460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        switch (function) {
396460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            case UsbManager.USB_FUNCTION_NONE:
397460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            case UsbManager.USB_FUNCTION_AUDIO_SOURCE:
398460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            case UsbManager.USB_FUNCTION_MIDI:
399460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            case UsbManager.USB_FUNCTION_MTP:
400460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            case UsbManager.USB_FUNCTION_PTP:
401460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown            case UsbManager.USB_FUNCTION_RNDIS:
402460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown                return true;
403460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        }
404460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown
405460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown        return false;
406460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown    }
407460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown
408fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
4094e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
4104e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
4114e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
4124e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
4134e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
414fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    @Override
4154e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    public void denyUsbDebugging() {
4164e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
4174e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        mDeviceManager.denyUsbDebugging();
4184e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
4194e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
42002eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    @Override
421cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    public void clearUsbDebuggingKeys() {
422cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
423cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby        mDeviceManager.clearUsbDebuggingKeys();
424cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    }
425cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby
426cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    @Override
42776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    public UsbPort[] getPorts() {
42876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
42902eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
43076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        final long ident = Binder.clearCallingIdentity();
43176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        try {
43276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            return mPortManager != null ? mPortManager.getPorts() : null;
43376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        } finally {
43476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            Binder.restoreCallingIdentity(ident);
43502eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood        }
43676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    }
43776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown
43876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    @Override
43976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    public UsbPortStatus getPortStatus(String portId) {
44076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        Preconditions.checkNotNull(portId, "portId must not be null");
44176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
44276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown
44376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        final long ident = Binder.clearCallingIdentity();
44476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        try {
44576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            return mPortManager != null ? mPortManager.getPortStatus(portId) : null;
44676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        } finally {
44776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            Binder.restoreCallingIdentity(ident);
44846d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
44976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    }
450fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
45176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    @Override
45276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    public void setPortRoles(String portId, int powerRole, int dataRole) {
45376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        Preconditions.checkNotNull(portId, "portId must not be null");
45476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        UsbPort.checkRoles(powerRole, dataRole);
45576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
45676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown
45776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        final long ident = Binder.clearCallingIdentity();
45876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        try {
45976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            if (mPortManager != null) {
46076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                mPortManager.setPortRoles(portId, powerRole, dataRole, null);
46176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            }
46276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        } finally {
46376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            Binder.restoreCallingIdentity(ident);
46476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        }
46576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    }
46676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown
46776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    @Override
468badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park    public void setUsbDeviceConnectionHandler(ComponentName usbDeviceConnectionHandler) {
469badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
470031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        synchronized (mLock) {
471031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            if (mCurrentUserId == UserHandle.getCallingUserId()) {
472031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                if (mHostManager != null) {
473031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                    mHostManager.setUsbDeviceConnectionHandler(usbDeviceConnectionHandler);
474031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                }
475031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            } else {
476031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                throw new IllegalArgumentException("Only the current user can register a usb " +
477031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                        "connection handler");
478031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            }
479badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park        }
480badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park    }
481badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park
482badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park    @Override
48376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
484fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey        if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
48576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown
48676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
48776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        final long ident = Binder.clearCallingIdentity();
48876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        try {
48976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            if (args == null || args.length == 0 || "-a".equals(args[0])) {
49076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("USB Manager State:");
4912dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brown                pw.increaseIndent();
49276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mDeviceManager != null) {
49376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mDeviceManager.dump(pw);
49476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
49576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mHostManager != null) {
49676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mHostManager.dump(pw);
49776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
49876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
49976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
50076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
50176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                mAlsaManager.dump(pw);
50276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown
503031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                mSettingsManager.dump(pw);
50476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else if (args.length == 4 && "set-port-roles".equals(args[0])) {
50576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final String portId = args[1];
50676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final int powerRole;
50776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                switch (args[2]) {
50876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "source":
50976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        powerRole = UsbPort.POWER_ROLE_SOURCE;
51076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
51176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "sink":
51276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        powerRole = UsbPort.POWER_ROLE_SINK;
51376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
51476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "no-power":
51576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        powerRole = 0;
51676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
51776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    default:
51876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.println("Invalid power role: " + args[2]);
51976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        return;
52076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
52176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final int dataRole;
52276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                switch (args[3]) {
52376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "host":
52476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        dataRole = UsbPort.DATA_ROLE_HOST;
52576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
52676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "device":
52776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        dataRole = UsbPort.DATA_ROLE_DEVICE;
52876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
52976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "no-data":
53076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        dataRole = 0;
53176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
53276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    default:
53376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.println("Invalid data role: " + args[3]);
53476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        return;
53576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
53676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
53776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.setPortRoles(portId, powerRole, dataRole, pw);
53876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    // Note: It might take some time for the side-effects of this operation
53976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    // to be fully applied by the kernel since the driver may need to
54076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    // renegotiate the USB port mode.  If this proves to be an issue
54176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    // during debugging, it might be worth adding a sleep here before
54276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    // dumping the new state.
54376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    pw.println();
54476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
54576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
54676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else if (args.length == 3 && "add-port".equals(args[0])) {
54776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final String portId = args[1];
54876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final int supportedModes;
54976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                switch (args[2]) {
55076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "ufp":
55176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        supportedModes = UsbPort.MODE_UFP;
55276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
55376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "dfp":
55476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        supportedModes = UsbPort.MODE_DFP;
55576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
55676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "dual":
55776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        supportedModes = UsbPort.MODE_DUAL;
55876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
55976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "none":
56076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        supportedModes = 0;
56176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
56276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    default:
56376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.println("Invalid mode: " + args[2]);
56476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        return;
56576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
56676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
56776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.addSimulatedPort(portId, supportedModes, pw);
56876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    pw.println();
56976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
57076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
57176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else if (args.length == 5 && "connect-port".equals(args[0])) {
57276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final String portId = args[1];
57376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final int mode;
57476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final boolean canChangeMode = args[2].endsWith("?");
57576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                switch (canChangeMode ? removeLastChar(args[2]) : args[2]) {
57676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "ufp":
57776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        mode = UsbPort.MODE_UFP;
57876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
57976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "dfp":
58076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        mode = UsbPort.MODE_DFP;
58176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
58276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    default:
58376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.println("Invalid mode: " + args[2]);
58476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        return;
58576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
58676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final int powerRole;
58776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final boolean canChangePowerRole = args[3].endsWith("?");
58876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                switch (canChangePowerRole ? removeLastChar(args[3]) : args[3]) {
58976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "source":
59076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        powerRole = UsbPort.POWER_ROLE_SOURCE;
59176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
59276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "sink":
59376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        powerRole = UsbPort.POWER_ROLE_SINK;
59476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
59576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    default:
59676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.println("Invalid power role: " + args[3]);
59776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        return;
59876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
59976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final int dataRole;
60076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final boolean canChangeDataRole = args[4].endsWith("?");
60176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                switch (canChangeDataRole ? removeLastChar(args[4]) : args[4]) {
60276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "host":
60376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        dataRole = UsbPort.DATA_ROLE_HOST;
60476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
60576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    case "device":
60676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        dataRole = UsbPort.DATA_ROLE_DEVICE;
60776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        break;
60876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    default:
60976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        pw.println("Invalid data role: " + args[4]);
61076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                        return;
61176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
61276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
61376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.connectSimulatedPort(portId, mode, canChangeMode,
61476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                            powerRole, canChangePowerRole, dataRole, canChangeDataRole, pw);
61576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    pw.println();
61676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
61776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
61876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else if (args.length == 2 && "disconnect-port".equals(args[0])) {
61976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final String portId = args[1];
62076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
62176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.disconnectSimulatedPort(portId, pw);
62276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    pw.println();
62376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
62476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
62576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else if (args.length == 2 && "remove-port".equals(args[0])) {
62676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                final String portId = args[1];
62776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
62876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.removeSimulatedPort(portId, pw);
62976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    pw.println();
63076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
63176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
63276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else if (args.length == 1 && "reset".equals(args[0])) {
63376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
63476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.resetSimulation(pw);
63576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    pw.println();
63676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
63776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
63876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else if (args.length == 1 && "ports".equals(args[0])) {
63976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                if (mPortManager != null) {
64076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                    mPortManager.dump(pw);
64176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                }
64276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            } else {
64376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("Dump current USB state or issue command:");
64476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  ports");
64576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  set-port-roles <id> <source|sink|no-power> <host|device|no-data>");
64676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  add-port <id> <ufp|dfp|dual|none>");
64776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  connect-port <id> <ufp|dfp><?> <source|sink><?> <host|device><?>");
64876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("    (add ? suffix if mode, power role, or data role can be changed)");
64976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  disconnect-port <id>");
65076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  remove-port <id>");
65176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  reset");
65276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println();
65376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("Example USB type C port role switch:");
65476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb set-port-roles \"default\" source device");
65576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println();
65676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("Example USB type C port simulation with full capabilities:");
65776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb add-port \"matrix\" dual");
65876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb connect-port \"matrix\" ufp? sink? device?");
65976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb ports");
66076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb disconnect-port \"matrix\"");
66176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb remove-port \"matrix\"");
66276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb reset");
66376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println();
66476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("Example USB type C port where only power role can be changed:");
66576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb add-port \"matrix\" dual");
66676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb connect-port \"matrix\" dfp source? host");
66776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb reset");
66876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println();
66976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("Example USB OTG port where id pin determines function:");
67076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb add-port \"matrix\" dual");
67176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb connect-port \"matrix\" dfp source host");
67276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb reset");
67376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println();
67476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("Example USB device-only port:");
67576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb add-port \"matrix\" ufp");
67676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb connect-port \"matrix\" ufp sink device");
67776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown                pw.println("  dumpsys usb reset");
678fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            }
67976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        } finally {
68076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown            Binder.restoreCallingIdentity(ident);
681fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        }
68202eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
68376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown
68476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    private static final String removeLastChar(String value) {
68576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown        return value.substring(0, value.length() - 1);
68676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown    }
6872423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood}
688