102eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood/*
2031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann * Copyright (C) 2016 The Android Open Source Project
302eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood *
4031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann *  Licensed under the Apache License, Version 2.0 (the "License");
5031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann *  you may not use this file except in compliance with the License.
6031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann *  You may obtain a copy of the License at
702eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood *
8031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann *       http://www.apache.org/licenses/LICENSE-2.0
902eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood *
10031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann *  Unless required by applicable law or agreed to in writing, software
11031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann *  distributed under the License is distributed on an "AS IS" BASIS,
12031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann *  See the License for the specific language governing permissions and
14031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann *  limitations under the License.
1502eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood */
1602eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
1702eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodpackage com.android.server.usb;
1802eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
19031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmannimport android.annotation.NonNull;
20031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmannimport android.annotation.UserIdInt;
2102eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodimport android.content.Context;
2202eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodimport android.content.Intent;
23a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmannimport android.content.pm.UserInfo;
24c4308f01c965571dc2354107c3574df113e397eeMike Lockwoodimport android.hardware.usb.UsbAccessory;
25c4308f01c965571dc2354107c3574df113e397eeMike Lockwoodimport android.hardware.usb.UsbDevice;
26c4308f01c965571dc2354107c3574df113e397eeMike Lockwoodimport android.hardware.usb.UsbManager;
275ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle;
28a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmannimport android.os.UserManager;
29fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwoodimport android.util.Slog;
30031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmannimport android.util.SparseArray;
31031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmannimport com.android.internal.annotations.GuardedBy;
322dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brownimport com.android.internal.util.IndentingPrintWriter;
3302eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
34031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann/**
35031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann * Maintains all {@link UsbUserSettingsManager} for all users.
36031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann */
37fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyclass UsbSettingsManager {
38031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    private static final String LOG_TAG = UsbSettingsManager.class.getSimpleName();
39fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood    private static final boolean DEBUG = false;
40fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
41031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    /** Context to be used by this module */
42031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    private final @NonNull Context mContext;
43163e4b6ae8a51421c8a9cccfdc2fe872afd09971Daichi Hirono
44031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    /** Map from user id to {@link UsbUserSettingsManager} for the user */
45031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    @GuardedBy("mSettingsByUser")
46031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    private final SparseArray<UsbUserSettingsManager> mSettingsByUser = new SparseArray<>();
47fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
48a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann    /**
49a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann     * Map from the parent profile's user id to {@link UsbProfileGroupSettingsManager} for the
50a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann     * group.
51a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann     */
52a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann    @GuardedBy("mSettingsByProfileGroup")
53a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann    private final SparseArray<UsbProfileGroupSettingsManager> mSettingsByProfileGroup
54a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            = new SparseArray<>();
55a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann    private UserManager mUserManager;
56a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann
57031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    public UsbSettingsManager(@NonNull Context context) {
5802eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood        mContext = context;
59a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
6002eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
6102eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
62fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    /**
63031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * Get the {@link UsbUserSettingsManager} for a user.
64031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     *
65031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * @param userId The id of the user
66031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     *
67031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * @return The settings for the user
68fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey     */
69031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    @NonNull UsbUserSettingsManager getSettingsForUser(@UserIdInt int userId) {
70031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        synchronized (mSettingsByUser) {
71031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            UsbUserSettingsManager settings = mSettingsByUser.get(userId);
72031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            if (settings == null) {
73031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                settings = new UsbUserSettingsManager(mContext, new UserHandle(userId));
74031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                mSettingsByUser.put(userId, settings);
75fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            }
76031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            return settings;
77fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        }
78fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    }
79fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
80031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    /**
81a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann     * Get the {@link UsbProfileGroupSettingsManager} for a user.
82a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann     *
83a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann     * @param user Any user of the profile group
84a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann     *
85a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann     * @return The settings for the profile group
86a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann     */
87a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann    @NonNull UsbProfileGroupSettingsManager getSettingsForProfileGroup(@NonNull UserHandle user) {
88a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        UserHandle parentUser;
89a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann
90a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        UserInfo parentUserInfo = mUserManager.getProfileParent(user.getIdentifier());
91a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        if (parentUserInfo != null) {
92a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            parentUser = parentUserInfo.getUserHandle();
93a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        } else {
94a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            parentUser = user;
95a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        }
96a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann
97a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        synchronized (mSettingsByProfileGroup) {
98a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            UsbProfileGroupSettingsManager settings = mSettingsByProfileGroup.get(
99a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                    parentUser.getIdentifier());
100a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            if (settings == null) {
101a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                settings = new UsbProfileGroupSettingsManager(mContext, parentUser, this);
102a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                mSettingsByProfileGroup.put(parentUser.getIdentifier(), settings);
103a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            }
104a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            return settings;
105a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        }
106a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann    }
107a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann
108a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann    /**
109031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * Remove the settings for a user.
110031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     *
111880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann     * @param userToRemove The user to remove
112031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     */
113880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann    void remove(@NonNull UserHandle userToRemove) {
114031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        synchronized (mSettingsByUser) {
115880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann            mSettingsByUser.remove(userToRemove.getIdentifier());
116880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann        }
117880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann
118880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann        synchronized (mSettingsByProfileGroup) {
119880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann            if (mSettingsByProfileGroup.indexOfKey(userToRemove.getIdentifier()) >= 0) {
120880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann                // The user to remove is the parent user of the group. The parent is the last user
121880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann                // that gets removed. All state will be removed with the user
122880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann                mSettingsByProfileGroup.remove(userToRemove.getIdentifier());
123880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann            } else {
124880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann                // We cannot find the parent user of the user that is removed, hence try to remove
125880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann                // it from all profile groups.
126880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann                int numProfileGroups = mSettingsByProfileGroup.size();
127880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann                for (int i = 0; i < numProfileGroups; i++) {
128880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann                    mSettingsByProfileGroup.valueAt(i).removeAllDefaultsForUser(userToRemove);
129880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann                }
130880389e6cc8044f751dd8569f2172ca61eaf2cd3Philip P. Moltmann            }
13102eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood        }
13202eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
13302eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
134031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    /**
135031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * Dump all settings of all users.
136031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     *
137031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * @param pw The writer to dump to
138031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     */
139031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    void dump(@NonNull IndentingPrintWriter pw) {
140031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        synchronized (mSettingsByUser) {
141a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            int numUsers = mSettingsByUser.size();
142a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            for (int i = 0; i < numUsers; i++) {
143031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                final int userId = mSettingsByUser.keyAt(i);
144031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                final UsbUserSettingsManager settings = mSettingsByUser.valueAt(i);
145031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                pw.println("Settings for user " + userId + ":");
146031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                pw.increaseIndent();
147031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                try {
148031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                    settings.dump(pw);
149031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                } finally {
150031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                    pw.decreaseIndent();
15102eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood                }
15202eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood            }
15302eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood        }
154a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann
155a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        synchronized (mSettingsByProfileGroup) {
156a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            int numProfileGroups = mSettingsByProfileGroup.size();
157a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            for (int i = 0; i < numProfileGroups; i++) {
158a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                final int parentUserId = mSettingsByProfileGroup.keyAt(i);
159a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                final UsbProfileGroupSettingsManager settings = mSettingsByProfileGroup.valueAt(i);
160a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                pw.println("Settings for profile group " + parentUserId + ":");
161a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                pw.increaseIndent();
162a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                try {
163a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                    settings.dump(pw);
164a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                } finally {
165a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                    pw.decreaseIndent();
166a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann                }
167a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann            }
168a6bf206649b24cabcf1348219e1b00f38214e06aPhilip P. Moltmann        }
16902eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood    }
17002eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood
171031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    /**
172031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * Remove temporary access permission and broadcast that a device was removed.
173031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     *
174031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * @param device The device that is removed
175031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     */
176031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    void usbDeviceRemoved(@NonNull UsbDevice device) {
177031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        synchronized (mSettingsByUser) {
178031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            for (int i = 0; i < mSettingsByUser.size(); i++) {
179031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                // clear temporary permissions for the device
180031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                mSettingsByUser.valueAt(i).removeDevicePermissions(device);
18102eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood            }
18202eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood        }
183c6f23e8521dedac7a07119031913235be3ca37c3Mike Lockwood
18402eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood        Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED);
18542a386b7717300bf6d75cbd3b4f7ad00f294be0dChristopher Tate        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
18602eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood        intent.putExtra(UsbManager.EXTRA_DEVICE, device);
187163e4b6ae8a51421c8a9cccfdc2fe872afd09971Daichi Hirono
188031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        if (DEBUG) {
189031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            Slog.d(LOG_TAG, "usbDeviceRemoved, sending " + intent);
1907a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood        }
1915ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
192c6f23e8521dedac7a07119031913235be3ca37c3Mike Lockwood    }
193c6f23e8521dedac7a07119031913235be3ca37c3Mike Lockwood
194031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    /**
195031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * Remove temporary access permission and broadcast that a accessory was removed.
196031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     *
197031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     * @param accessory The accessory that is removed
198031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann     */
199031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann    void usbAccessoryRemoved(@NonNull UsbAccessory accessory) {
200031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        synchronized (mSettingsByUser) {
201031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann            for (int i = 0; i < mSettingsByUser.size(); i++) {
202031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                // clear temporary permissions for the accessory
203031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann                mSettingsByUser.valueAt(i).removeAccessoryPermissions(accessory);
2043a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood            }
2053a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood        }
2063a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood
207031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
20842a386b7717300bf6d75cbd3b4f7ad00f294be0dChristopher Tate        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
2093a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood        intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
210031cee90a350b7be93ef939630b277cfb28c171bPhilip P. Moltmann        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
211163e4b6ae8a51421c8a9cccfdc2fe872afd09971Daichi Hirono    }
21202eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood}
213