Avoid a potential race condition on mDisplays
I've now run this on a HWC1 and HWC2 build. Both appear to be running
correctly.
Original Message:
The race could occur when transitioning in/out of VR flinger mode.
It is now avoided by ensuring that the primary |DisplayDevice| is always
created once |mStateLock| is released, and ensuring that all accesses
to the primary |DisplayDevice| are guarded by |mStateLock|.
Bug: 36194616
Bug: 37249613
Bug: 37288476
Test: Compiled, installed, and ran with both HWC1 and HWC2 variants.
HWC1 was tested on Nexus 6P. Was able to boot, install apps, run apps,
turn screen on/off, and reboot phone.
HWC2 was tested on sailfish. Was able to boot, install apps, run apps,
run VR apps using both N path, and O1 path, turn screen on/off, and
reboot phone.
Change-Id: I0e80c2553f40cce2116b718bbb0d2566679f794a
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b17a5f2..c01f701 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -184,7 +184,8 @@
// returns the default Display
sp<const DisplayDevice> getDefaultDisplayDevice() const {
- return getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]);
+ Mutex::Autolock _l(mStateLock);
+ return getDefaultDisplayDeviceLocked();
}
// utility function to delete a texture on the main thread
@@ -305,7 +306,7 @@
* HWComposer::EventHandler interface
*/
virtual void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp);
- virtual void onHotplugReceived(int disp, bool connected);
+ virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected);
virtual void onInvalidateReceived(HWComposer* composer);
/* ------------------------------------------------------------------------
@@ -430,16 +431,33 @@
// Create an IBinder for a builtin display and add it to current state
void createBuiltinDisplayLocked(DisplayDevice::DisplayType type);
- // NOTE: can only be called from the main thread or with mStateLock held
+
sp<const DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) const {
+ Mutex::Autolock _l(mStateLock);
+ return getDisplayDeviceLocked(dpy);
+ }
+
+ sp<DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) {
+ Mutex::Autolock _l(mStateLock);
+ return getDisplayDeviceLocked(dpy);
+ }
+
+ // NOTE: can only be called from the main thread or with mStateLock held
+ sp<const DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& dpy) const {
return mDisplays.valueFor(dpy);
}
// NOTE: can only be called from the main thread or with mStateLock held
- sp<DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) {
+ sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& dpy) {
return mDisplays.valueFor(dpy);
}
+ sp<const DisplayDevice> getDefaultDisplayDeviceLocked() const {
+ return getDisplayDeviceLocked(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]);
+ }
+
+ void createDefaultDisplayDevice();
+
int32_t getDisplayType(const sp<IBinder>& display) {
if (!display.get()) return NAME_NOT_FOUND;
for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) {
@@ -547,7 +565,7 @@
* VrFlinger
*/
void clearHwcLayers(const LayerVector& layers);
- void resetHwc();
+ void resetHwcLocked();
// Check to see if we should handoff to vr flinger.
void updateVrFlinger();