Skip to content

Commit 6669250

Browse files
author
Jeff Brown
committed
Fix deadlock.
The display manager must never call into the activity manager with its lock held. Make it clear that the adapters are constructed while holding the syncroot lock. Bug: 7377631 Change-Id: I1557313cbb31dcad9b5a46919a88a5a1c1af3e9b
1 parent 88c66cb commit 6669250

File tree

5 files changed

+32
-20
lines changed

5 files changed

+32
-20
lines changed

services/java/com/android/server/display/DisplayAdapter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ abstract class DisplayAdapter {
4242
public static final int DISPLAY_DEVICE_EVENT_CHANGED = 2;
4343
public static final int DISPLAY_DEVICE_EVENT_REMOVED = 3;
4444

45+
// Called with SyncRoot lock held.
4546
public DisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
4647
Context context, Handler handler, Listener listener, String name) {
4748
mSyncRoot = syncRoot;

services/java/com/android/server/display/HeadlessDisplayAdapter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
final class HeadlessDisplayAdapter extends DisplayAdapter {
3030
private static final String TAG = "HeadlessDisplayAdapter";
3131

32+
// Called with SyncRoot lock held.
3233
public HeadlessDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
3334
Context context, Handler handler, Listener listener) {
3435
super(syncRoot, context, handler, listener, TAG);

services/java/com/android/server/display/LocalDisplayAdapter.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,21 @@ final class LocalDisplayAdapter extends DisplayAdapter {
4444

4545
private final SparseArray<LocalDisplayDevice> mDevices =
4646
new SparseArray<LocalDisplayDevice>();
47-
private final HotplugDisplayEventReceiver mHotplugReceiver;
47+
private HotplugDisplayEventReceiver mHotplugReceiver;
4848

4949
private final PhysicalDisplayInfo mTempPhys = new PhysicalDisplayInfo();
5050

51+
// Called with SyncRoot lock held.
5152
public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
5253
Context context, Handler handler, Listener listener) {
5354
super(syncRoot, context, handler, listener, TAG);
54-
mHotplugReceiver = new HotplugDisplayEventReceiver(handler.getLooper());
5555
}
5656

5757
@Override
5858
public void registerLocked() {
59-
// TODO: listen for notifications from Surface Flinger about
60-
// built-in displays being added or removed and rescan as needed.
6159
super.registerLocked();
60+
61+
mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
6262
scanDisplaysLocked();
6363
}
6464

services/java/com/android/server/display/OverlayDisplayAdapter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
6464
new ArrayList<OverlayDisplayHandle>();
6565
private String mCurrentOverlaySetting = "";
6666

67+
// Called with SyncRoot lock held.
6768
public OverlayDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
6869
Context context, Handler handler, Listener listener, Handler uiHandler) {
6970
super(syncRoot, context, handler, listener, TAG);

services/java/com/android/server/display/WifiDisplayAdapter.java

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ final class WifiDisplayAdapter extends DisplayAdapter {
7373
private final boolean mSupportsProtectedBuffers;
7474
private final NotificationManager mNotificationManager;
7575

76-
private final PendingIntent mSettingsPendingIntent;
77-
private final PendingIntent mDisconnectPendingIntent;
76+
private PendingIntent mSettingsPendingIntent;
77+
private PendingIntent mDisconnectPendingIntent;
7878

7979
private WifiDisplayController mDisplayController;
8080
private WifiDisplayDevice mDisplayDevice;
@@ -90,6 +90,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
9090
private boolean mPendingStatusChangeBroadcast;
9191
private boolean mPendingNotificationUpdate;
9292

93+
// Called with SyncRoot lock held.
9394
public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
9495
Context context, Handler handler, Listener listener,
9596
PersistentDataStore persistentDataStore) {
@@ -100,20 +101,6 @@ public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
100101
com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers);
101102
mNotificationManager = (NotificationManager)context.getSystemService(
102103
Context.NOTIFICATION_SERVICE);
103-
104-
Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS);
105-
settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
106-
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
107-
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
108-
mSettingsPendingIntent = PendingIntent.getActivityAsUser(
109-
context, 0, settingsIntent, 0, null, UserHandle.CURRENT);
110-
111-
Intent disconnectIntent = new Intent(ACTION_DISCONNECT);
112-
mDisconnectPendingIntent = PendingIntent.getBroadcastAsUser(
113-
context, 0, disconnectIntent, 0, UserHandle.CURRENT);
114-
115-
context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
116-
new IntentFilter(ACTION_DISCONNECT), null, mHandler);
117104
}
118105

119106
@Override
@@ -153,6 +140,9 @@ public void registerLocked() {
153140
public void run() {
154141
mDisplayController = new WifiDisplayController(
155142
getContext(), getHandler(), mWifiDisplayListener);
143+
144+
getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
145+
new IntentFilter(ACTION_DISCONNECT), null, mHandler);
156146
}
157147
});
158148
}
@@ -366,12 +356,31 @@ private void handleUpdateNotification() {
366356
isConnected = (mDisplayDevice != null);
367357
}
368358

359+
// Cancel the old notification if there is one.
369360
mNotificationManager.cancelAsUser(null,
370361
R.string.wifi_display_notification_title, UserHandle.ALL);
371362

372363
if (isConnected) {
373364
Context context = getContext();
374365

366+
// Initialize pending intents for the notification outside of the lock because
367+
// creating a pending intent requires a call into the activity manager.
368+
if (mSettingsPendingIntent == null) {
369+
Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS);
370+
settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
371+
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
372+
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
373+
mSettingsPendingIntent = PendingIntent.getActivityAsUser(
374+
context, 0, settingsIntent, 0, null, UserHandle.CURRENT);
375+
}
376+
377+
if (mDisconnectPendingIntent == null) {
378+
Intent disconnectIntent = new Intent(ACTION_DISCONNECT);
379+
mDisconnectPendingIntent = PendingIntent.getBroadcastAsUser(
380+
context, 0, disconnectIntent, 0, UserHandle.CURRENT);
381+
}
382+
383+
// Post the notification.
375384
Resources r = context.getResources();
376385
Notification notification = new Notification.Builder(context)
377386
.setContentTitle(r.getString(

0 commit comments

Comments
 (0)