Skip to content

Commit 27bd34d

Browse files
committed
Multi-user MTP.
The current MTP kernel driver at /dev/mtp_usb is exclusive, meaning only one process can have it open. In addition, each MTP session with a desktop requires unique object IDs, which doesn't hold true across users on the device. To solve these two issues, when switching users we cycle the USB host stack to disconnect both local and remote MTP connections, giving the new user's media process a chance to claim /dev/mtp_usb, and causing the desktop to initiate a new MTP session. This change also allows BroadcastReceivers to registerReceiver() allow retrieval of a current sticky broadcast. Adds a system property to override maximum users. Removes MOUNTED broadcasts for secondary users. Allows INTERACT_ACROSS_USERS to getCurrentUser(). Bug: 6925114 Change-Id: I02b4a1b535af95fb2142655887b6d15a8068d18a
1 parent a4b0e55 commit 27bd34d

File tree

6 files changed

+55
-60
lines changed

6 files changed

+55
-60
lines changed

core/java/android/app/ContextImpl.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -129,32 +129,33 @@ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter)
129129
@Override
130130
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
131131
String broadcastPermission, Handler scheduler) {
132-
throw new ReceiverCallNotAllowedException(
133-
"IntentReceiver components are not allowed to register to receive intents");
134-
//ex.fillInStackTrace();
135-
//Log.e("IntentReceiver", ex.getMessage(), ex);
136-
//return mContext.registerReceiver(receiver, filter, broadcastPermission,
137-
// scheduler);
132+
if (receiver == null) {
133+
// Allow retrieving current sticky broadcast; this is safe since we
134+
// aren't actually registering a receiver.
135+
return super.registerReceiver(null, filter, broadcastPermission, scheduler);
136+
} else {
137+
throw new ReceiverCallNotAllowedException(
138+
"BroadcastReceiver components are not allowed to register to receive intents");
139+
}
138140
}
139141

140142
@Override
141143
public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
142144
IntentFilter filter, String broadcastPermission, Handler scheduler) {
143-
throw new ReceiverCallNotAllowedException(
144-
"IntentReceiver components are not allowed to register to receive intents");
145-
//ex.fillInStackTrace();
146-
//Log.e("IntentReceiver", ex.getMessage(), ex);
147-
//return mContext.registerReceiver(receiver, filter, broadcastPermission,
148-
// scheduler);
145+
if (receiver == null) {
146+
// Allow retrieving current sticky broadcast; this is safe since we
147+
// aren't actually registering a receiver.
148+
return super.registerReceiverAsUser(null, user, filter, broadcastPermission, scheduler);
149+
} else {
150+
throw new ReceiverCallNotAllowedException(
151+
"BroadcastReceiver components are not allowed to register to receive intents");
152+
}
149153
}
150154

151155
@Override
152156
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
153157
throw new ReceiverCallNotAllowedException(
154-
"IntentReceiver components are not allowed to bind to services");
155-
//ex.fillInStackTrace();
156-
//Log.e("IntentReceiver", ex.getMessage(), ex);
157-
//return mContext.bindService(service, interfaceName, conn, flags);
158+
"BroadcastReceiver components are not allowed to bind to services");
158159
}
159160
}
160161

core/java/android/os/UserManager.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import android.content.Context;
2020
import android.content.pm.UserInfo;
2121
import android.graphics.Bitmap;
22+
import android.content.res.Resources;
2223
import android.util.Log;
2324

2425
import java.util.List;
@@ -232,8 +233,9 @@ public void wipeUser(int userHandle) {
232233
* @hide
233234
* @return a value greater than or equal to 1
234235
*/
235-
public int getMaxSupportedUsers() {
236-
return mContext.getResources().getInteger(R.integer.config_multiuserMaximumUsers);
236+
public static int getMaxSupportedUsers() {
237+
return SystemProperties.getInt("fw.max_users",
238+
Resources.getSystem().getInteger(R.integer.config_multiuserMaximumUsers));
237239
}
238240

239241
/**

services/java/com/android/server/MountService.java

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -549,34 +549,6 @@ private void handleSystemReady() {
549549
}
550550
}
551551

552-
private final BroadcastReceiver mBootReceiver = new BroadcastReceiver() {
553-
@Override
554-
public void onReceive(Context context, Intent intent) {
555-
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
556-
if (userId == -1) return;
557-
final UserHandle user = new UserHandle(userId);
558-
559-
Slog.d(TAG, "BOOT_COMPLETED for " + user);
560-
561-
// Broadcast mounted volumes to newly booted user. This kicks off
562-
// media scanner when a user becomes active.
563-
synchronized (mVolumesLock) {
564-
for (StorageVolume volume : mVolumes) {
565-
final UserHandle owner = volume.getOwner();
566-
final boolean ownerMatch = owner == null
567-
|| owner.getIdentifier() == user.getIdentifier();
568-
569-
final String state = mVolumeStates.get(volume.getPath());
570-
571-
if (ownerMatch && (Environment.MEDIA_MOUNTED.equals(state)
572-
|| Environment.MEDIA_MOUNTED_READ_ONLY.equals(state))) {
573-
sendStorageIntent(Intent.ACTION_MEDIA_MOUNTED, volume, user);
574-
}
575-
}
576-
}
577-
}
578-
};
579-
580552
private final BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
581553
@Override
582554
public void onReceive(Context context, Intent intent) {
@@ -1309,10 +1281,6 @@ public MountService(Context context) {
13091281
mHandlerThread.start();
13101282
mHandler = new MountServiceHandler(mHandlerThread.getLooper());
13111283

1312-
// Watch for user boot completion
1313-
mContext.registerReceiverAsUser(mBootReceiver, UserHandle.ALL,
1314-
new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, mHandler);
1315-
13161284
// Watch for user changes
13171285
final IntentFilter userFilter = new IntentFilter();
13181286
userFilter.addAction(Intent.ACTION_USER_ADDED);

services/java/com/android/server/am/ActivityManagerService.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14224,12 +14224,14 @@ void finishUserStop(UserStartedState uss) {
1422414224

1422514225
@Override
1422614226
public UserInfo getCurrentUser() {
14227-
if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
14228-
!= PackageManager.PERMISSION_GRANTED) {
14227+
if ((checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
14228+
!= PackageManager.PERMISSION_GRANTED) && (
14229+
checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
14230+
!= PackageManager.PERMISSION_GRANTED)) {
1422914231
String msg = "Permission Denial: getCurrentUser() from pid="
1423014232
+ Binder.getCallingPid()
1423114233
+ ", uid=" + Binder.getCallingUid()
14232-
+ " requires " + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
14234+
+ " requires " + android.Manifest.permission.INTERACT_ACROSS_USERS;
1423314235
Slog.w(TAG, msg);
1423414236
throw new SecurityException(msg);
1423514237
}

services/java/com/android/server/pm/UserManagerService.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import android.os.Process;
4040
import android.os.RemoteException;
4141
import android.os.UserHandle;
42+
import android.os.UserManager;
4243
import android.util.AtomicFile;
4344
import android.util.Slog;
4445
import android.util.SparseArray;
@@ -85,8 +86,6 @@ public class UserManagerService extends IUserManager.Stub {
8586

8687
private SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();
8788

88-
private final int mUserLimit;
89-
9089
private int[] mUserIds;
9190
private boolean mGuestEnabled;
9291
private int mNextSerialNumber;
@@ -129,8 +128,6 @@ private UserManagerService(Context context, PackageManagerService pm,
129128
mPm = pm;
130129
mInstallLock = installLock;
131130
mPackagesLock = packagesLock;
132-
mUserLimit = mContext.getResources().getInteger(
133-
com.android.internal.R.integer.config_multiuserMaximumUsers);
134131
mUsersDir = new File(dataDir, USER_INFO_DIR);
135132
mUsersDir.mkdirs();
136133
// Make zeroth user directory, for services to migrate their files to that location
@@ -275,7 +272,7 @@ public void makeInitialized(int userId) {
275272
*/
276273
private boolean isUserLimitReachedLocked() {
277274
int nUsers = mUsers.size();
278-
return nUsers >= mUserLimit;
275+
return nUsers >= UserManager.getMaxSupportedUsers();
279276
}
280277

281278
/**

services/java/com/android/server/usb/UsbDeviceManager.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ public class UsbDeviceManager {
9191
private static final int MSG_SET_CURRENT_FUNCTIONS = 2;
9292
private static final int MSG_SYSTEM_READY = 3;
9393
private static final int MSG_BOOT_COMPLETED = 4;
94+
private static final int MSG_USER_SWITCHED = 5;
9495

9596
private static final int AUDIO_MODE_NONE = 0;
9697
private static final int AUDIO_MODE_SOURCE = 1;
@@ -295,14 +296,24 @@ private final class UsbHandler extends Handler {
295296
private UsbAccessory mCurrentAccessory;
296297
private int mUsbNotificationId;
297298
private boolean mAdbNotificationShown;
299+
private int mCurrentUser = UserHandle.USER_NULL;
298300

299301
private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
302+
@Override
300303
public void onReceive(Context context, Intent intent) {
301304
if (DEBUG) Slog.d(TAG, "boot completed");
302305
mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
303306
}
304307
};
305308

309+
private final BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
310+
@Override
311+
public void onReceive(Context context, Intent intent) {
312+
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
313+
mHandler.obtainMessage(MSG_USER_SWITCHED, userId, 0).sendToTarget();
314+
}
315+
};
316+
306317
public UsbHandler(Looper looper) {
307318
super(looper);
308319
try {
@@ -347,8 +358,10 @@ public UsbHandler(Looper looper) {
347358
mUEventObserver.startObserving(USB_STATE_MATCH);
348359
mUEventObserver.startObserving(ACCESSORY_START_MATCH);
349360

350-
mContext.registerReceiver(mBootCompletedReceiver,
351-
new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
361+
mContext.registerReceiver(
362+
mBootCompletedReceiver, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
363+
mContext.registerReceiver(
364+
mUserSwitchedReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED));
352365
} catch (Exception e) {
353366
Slog.e(TAG, "Error initializing UsbHandler", e);
354367
}
@@ -611,6 +624,18 @@ public void handleMessage(Message msg) {
611624
mDebuggingManager.setAdbEnabled(mAdbEnabled);
612625
}
613626
break;
627+
case MSG_USER_SWITCHED: {
628+
final boolean mtpActive =
629+
containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)
630+
|| containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP);
631+
if (mtpActive && mCurrentUser != UserHandle.USER_NULL) {
632+
Slog.v(TAG, "Current user switched; resetting USB host stack for MTP");
633+
setUsbConfig("none");
634+
setUsbConfig(mCurrentFunctions);
635+
}
636+
mCurrentUser = msg.arg1;
637+
break;
638+
}
614639
}
615640
}
616641

0 commit comments

Comments
 (0)