Merge "Fix NPE for CompanionDeviceActivity.setResultAndFinish()" into sc-v2-dev
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 856dfe5..e8725f0 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -162,8 +162,6 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
boolean mIsCreating = false;
- private volatile boolean mRtHandlingPositionUpdates = false;
- private volatile boolean mRtReleaseSurfaces = false;
private final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener =
this::updateSurface;
@@ -909,13 +907,14 @@
mBlastBufferQueue = null;
}
- if (mRtHandlingPositionUpdates) {
- mRtReleaseSurfaces = true;
- return;
+ ViewRootImpl viewRoot = getViewRootImpl();
+ Transaction transaction = new Transaction();
+ releaseSurfaces(transaction);
+ if (viewRoot != null) {
+ viewRoot.applyTransactionOnDraw(transaction);
+ } else {
+ transaction.apply();
}
-
- releaseSurfaces(mTmpTransaction);
- mTmpTransaction.apply();
}
}
@@ -1468,15 +1467,6 @@
if (mSurfaceControl == null) {
return;
}
- // TODO: This is teensy bit racey in that a brand new SurfaceView moving on
- // its 2nd frame if RenderThread is running slowly could potentially see
- // this as false, enter the branch, get pre-empted, then this comes along
- // and reports a new position, then the UI thread resumes and reports
- // its position. This could therefore be de-sync'd in that interval, but
- // the synchronization would violate the rule that RT must never block
- // on the UI thread which would open up potential deadlocks. The risk of
- // a single-frame desync is therefore preferable for now.
- mRtHandlingPositionUpdates = true;
}
if (mRTLastReportedPosition.left == left
&& mRTLastReportedPosition.top == top
@@ -1552,12 +1542,7 @@
return;
}
mRtTransaction.hide(mSurfaceControl);
- if (mRtReleaseSurfaces) {
- mRtReleaseSurfaces = false;
- releaseSurfaces(mRtTransaction);
- }
applyOrMergeTransaction(mRtTransaction, frameNumber);
- mRtHandlingPositionUpdates = false;
}
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 65d0e49..2d7388f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -10507,9 +10507,11 @@
@Override
public boolean applyTransactionOnDraw(@NonNull SurfaceControl.Transaction t) {
- registerRtFrameCallback(frame -> {
- mergeWithNextTransaction(t, frame);
- });
+ if (mRemoved) {
+ t.apply();
+ } else {
+ registerRtFrameCallback(frame -> mergeWithNextTransaction(t, frame));
+ }
return true;
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 57b7d61..2357d13 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -5746,9 +5746,11 @@
// persisted across change, and has the RemoteViews re-applied in a different situation
// (orientation or size), we throw an exception, since the layouts may be completely
// unrelated.
- if (!rvToApply.canRecycleView(v)) {
- throw new RuntimeException("Attempting to re-apply RemoteViews to a view that"
- + " that does not share the same root layout id.");
+ if (hasMultipleLayouts()) {
+ if (!rvToApply.canRecycleView(v)) {
+ throw new RuntimeException("Attempting to re-apply RemoteViews to a view that" +
+ " that does not share the same root layout id.");
+ }
}
rvToApply.performApply(v, (ViewGroup) v.getParent(), handler, colorResources);
@@ -5792,9 +5794,11 @@
// In the case that a view has this RemoteViews applied in one orientation, is persisted
// across orientation change, and has the RemoteViews re-applied in the new orientation,
// we throw an exception, since the layouts may be completely unrelated.
- if (!rvToApply.canRecycleView(v)) {
- throw new RuntimeException("Attempting to re-apply RemoteViews to a view that"
- + " that does not share the same root layout id.");
+ if (hasMultipleLayouts()) {
+ if (!rvToApply.canRecycleView(v)) {
+ throw new RuntimeException("Attempting to re-apply RemoteViews to a view that" +
+ " that does not share the same root layout id.");
+ }
}
return new AsyncApplyTask(rvToApply, (ViewGroup) v.getParent(),
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 669965b..2511520 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -115,7 +115,7 @@
}
/**
- * Appends dozing event to the logs
+ * Appends dozing event to the logs. Logs current dozing state when entering/exiting AOD.
* @param dozing true if dozing, else false
*/
public void traceDozing(boolean dozing) {
@@ -124,6 +124,14 @@
}
/**
+ * Appends dozing event to the logs when dozing has changed in AOD.
+ * @param dozing true if we're now dozing, else false
+ */
+ public void traceDozingChanged(boolean dozing) {
+ mLogger.logDozingChanged(dozing);
+ }
+
+ /**
* Appends dozing event to the logs
* @param suppressed true if dozing is suppressed
*/
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
index d79bf22..4ba6b51 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
@@ -66,6 +66,14 @@
})
}
+ fun logDozingChanged(isDozing: Boolean) {
+ buffer.log(TAG, INFO, {
+ bool1 = isDozing
+ }, {
+ "Dozing changed dozing=$bool1"
+ })
+ }
+
fun logDozingSuppressed(isDozingSuppressed: Boolean) {
buffer.log(TAG, INFO, {
bool1 = isDozingSuppressed
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
index 292b0e2..fbfb919 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
@@ -109,11 +109,9 @@
}
@MainThread
- private fun processDevice(key: String, oldKey: String?, device: MediaDevice?) {
- val enabled = device != null
- val data = MediaDeviceData(enabled, device?.iconWithoutBackground, device?.name)
+ private fun processDevice(key: String, oldKey: String?, device: MediaDeviceData?) {
listeners.forEach {
- it.onMediaDeviceChanged(key, oldKey, data)
+ it.onMediaDeviceChanged(key, oldKey, device)
}
}
@@ -135,7 +133,7 @@
get() = controller?.sessionToken
private var started = false
private var playbackType = PLAYBACK_TYPE_UNKNOWN
- private var current: MediaDevice? = null
+ private var current: MediaDeviceData? = null
set(value) {
if (!started || value != field) {
field = value
@@ -201,15 +199,13 @@
@WorkerThread
private fun updateCurrent() {
- val device = localMediaManager.getCurrentConnectedDevice()
- controller?.let {
- val route = mr2manager.getRoutingSessionForMediaController(it)
- // If we get a null route, then don't trust the device. Just set to null to disable the
- // output switcher chip.
- current = if (route != null) device else null
- } ?: run {
- current = device
- }
+ val device = localMediaManager.currentConnectedDevice
+ val route = controller?.let { mr2manager.getRoutingSessionForMediaController(it)}
+
+ // If we have a controller but get a null route, then don't trust the device
+ val enabled = device != null && (controller == null || route != null)
+ val name = route?.name?.toString() ?: device?.name
+ current = MediaDeviceData(enabled, device?.iconWithoutBackground, name)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index 21c3e5e..7de4668 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -21,7 +21,6 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
@@ -92,10 +91,14 @@
};
@Inject
- public DozeScrimController(DozeParameters dozeParameters, DozeLog dozeLog) {
+ public DozeScrimController(
+ DozeParameters dozeParameters,
+ DozeLog dozeLog,
+ StatusBarStateController statusBarStateController
+ ) {
mDozeParameters = dozeParameters;
- //Never expected to be destroyed
- Dependency.get(StatusBarStateController.class).addCallback(this);
+ // Never expected to be destroyed
+ statusBarStateController.addCallback(this);
mDozeLog = dozeLog;
}
@@ -219,6 +222,10 @@
@Override
public void onDozingChanged(boolean isDozing) {
+ if (mDozing != isDozing) {
+ mDozeLog.traceDozingChanged(isDozing);
+ }
+
setDozing(isDozing);
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
index bf5a6e4..bbeadf6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -122,7 +122,7 @@
private lateinit var session: MediaSession
private val device = MediaDeviceData(true, null, DEVICE_NAME)
- private val disabledDevice = MediaDeviceData(false, null, null)
+ private val disabledDevice = MediaDeviceData(false, null, "Disabled Device")
@JvmField @Rule val mockito = MockitoJUnit.rule()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
index ab3b208..7dadbad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
@@ -56,6 +56,7 @@
private const val SESSION_KEY = "SESSION_KEY"
private const val SESSION_TITLE = "SESSION_TITLE"
private const val DEVICE_NAME = "DEVICE_NAME"
+private const val REMOTE_DEVICE_NAME = "REMOTE_DEVICE_NAME"
private const val USER_ID = 0
private fun <T> eq(value: T): T = Mockito.eq(value) ?: value
@@ -195,8 +196,6 @@
// THEN the device should be disabled
val data = captureDeviceData(KEY)
assertThat(data.enabled).isFalse()
- assertThat(data.name).isNull()
- assertThat(data.icon).isNull()
}
@Test
@@ -263,6 +262,20 @@
}
@Test
+ fun deviceNameFromMR2RouteInfo() {
+ // GIVEN that MR2Manager returns a valid routing session
+ whenever(route.name).thenReturn(REMOTE_DEVICE_NAME)
+ // WHEN a notification is added
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+ // THEN it uses the route name (instead of device name)
+ val data = captureDeviceData(KEY)
+ assertThat(data.enabled).isTrue()
+ assertThat(data.name).isEqualTo(REMOTE_DEVICE_NAME)
+ }
+
+ @Test
fun deviceDisabledWhenMR2ReturnsNullRouteInfo() {
// GIVEN that MR2Manager returns null for routing session
whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null)
@@ -273,8 +286,6 @@
// THEN the device is disabled
val data = captureDeviceData(KEY)
assertThat(data.enabled).isFalse()
- assertThat(data.name).isNull()
- assertThat(data.icon).isNull()
}
@Test
@@ -294,8 +305,6 @@
// THEN the device is disabled
val data = captureDeviceData(KEY)
assertThat(data.enabled).isFalse()
- assertThat(data.name).isNull()
- assertThat(data.icon).isNull()
}
@Test
@@ -315,8 +324,6 @@
// THEN the device is disabled
val data = captureDeviceData(KEY)
assertThat(data.enabled).isFalse()
- assertThat(data.name).isNull()
- assertThat(data.icon).isNull()
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeScrimControllerTest.java
index 1ce336e..34c43ef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeScrimControllerTest.java
@@ -28,6 +28,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import org.junit.Before;
import org.junit.Test;
@@ -44,12 +45,15 @@
private DozeParameters mDozeParameters;
@Mock
private DozeLog mDozeLog;
+ @Mock
+ private StatusBarStateController mStatusBarStateController;
private DozeScrimController mDozeScrimController;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mDozeScrimController = new DozeScrimController(mDozeParameters, mDozeLog);
+ mDozeScrimController = new DozeScrimController(mDozeParameters, mDozeLog,
+ mStatusBarStateController);
mDozeScrimController.setDozing(true);
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 63301ac..ab220b5e 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -47,6 +47,7 @@
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.telecom.TelecomManager;
+import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SrvccState;
@@ -1999,42 +2000,8 @@
ApnSetting apnSetting = preciseState.getApnSetting();
- int apnTypes = apnSetting.getApnTypeBitmask();
- int state = preciseState.getState();
- int networkType = preciseState.getNetworkType();
-
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
- // We only call the callback when the change is for default APN type.
- if ((ApnSetting.TYPE_DEFAULT & apnTypes) != 0
- && (mDataConnectionState[phoneId] != state
- || mDataConnectionNetworkType[phoneId] != networkType)) {
- String str = "onDataConnectionStateChanged("
- + TelephonyUtils.dataStateToString(state)
- + ", " + getNetworkTypeName(networkType)
- + ") subId=" + subId + ", phoneId=" + phoneId;
- log(str);
- mLocalLog.log(str);
- for (Record r : mRecords) {
- if (r.matchTelephonyCallbackEvent(
- TelephonyCallback.EVENT_DATA_CONNECTION_STATE_CHANGED)
- && idMatch(r, subId, phoneId)) {
- try {
- if (DBG) {
- log("Notify data connection state changed on sub: " + subId);
- }
- r.callback.onDataConnectionStateChanged(state, networkType);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
- }
- }
- }
- handleRemoveListLocked();
-
- mDataConnectionState[phoneId] = state;
- mDataConnectionNetworkType[phoneId] = networkType;
- }
-
Pair<Integer, ApnSetting> key = Pair.create(preciseState.getTransportType(),
preciseState.getApnSetting());
PreciseDataConnectionState oldState = mPreciseDataConnectionStates.get(phoneId)
@@ -2066,6 +2033,73 @@
if (preciseState.getState() != TelephonyManager.DATA_DISCONNECTED) {
mPreciseDataConnectionStates.get(phoneId).put(key, preciseState);
}
+
+ // Note that below is just the workaround for reporting the correct data connection
+ // state. The actual fix should be put in the new data stack in T.
+ // TODO: Remove the code below in T.
+
+ // Collect all possible candidate data connection state for internet. Key is the
+ // data connection state, value is the precise data connection state.
+ Map<Integer, PreciseDataConnectionState> internetConnections = new ArrayMap<>();
+ if (preciseState.getState() == TelephonyManager.DATA_DISCONNECTED
+ && preciseState.getApnSetting().getApnTypes()
+ .contains(ApnSetting.TYPE_DEFAULT)) {
+ internetConnections.put(TelephonyManager.DATA_DISCONNECTED, preciseState);
+ }
+ for (Map.Entry<Pair<Integer, ApnSetting>, PreciseDataConnectionState> entry :
+ mPreciseDataConnectionStates.get(phoneId).entrySet()) {
+ if (entry.getKey().first == AccessNetworkConstants.TRANSPORT_TYPE_WWAN
+ && entry.getKey().second.getApnTypes()
+ .contains(ApnSetting.TYPE_DEFAULT)) {
+ internetConnections.put(entry.getValue().getState(), entry.getValue());
+ }
+ }
+
+ // If any internet data is in connected state, then report connected, then check
+ // suspended, connecting, disconnecting, and disconnected. The order is very
+ // important.
+ int[] statesInPriority = new int[]{TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.DATA_SUSPENDED, TelephonyManager.DATA_CONNECTING,
+ TelephonyManager.DATA_DISCONNECTING,
+ TelephonyManager.DATA_DISCONNECTED};
+ int state = TelephonyManager.DATA_DISCONNECTED;
+ int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ for (int s : statesInPriority) {
+ if (internetConnections.containsKey(s)) {
+ state = s;
+ networkType = internetConnections.get(s).getNetworkType();
+ break;
+ }
+ }
+
+ if (mDataConnectionState[phoneId] != state
+ || mDataConnectionNetworkType[phoneId] != networkType) {
+ String str = "onDataConnectionStateChanged("
+ + TelephonyUtils.dataStateToString(state)
+ + ", " + TelephonyManager.getNetworkTypeName(networkType)
+ + ") subId=" + subId + ", phoneId=" + phoneId;
+ log(str);
+ mLocalLog.log(str);
+ for (Record r : mRecords) {
+ if (r.matchTelephonyCallbackEvent(
+ TelephonyCallback.EVENT_DATA_CONNECTION_STATE_CHANGED)
+ && idMatch(r, subId, phoneId)) {
+ try {
+ if (DBG) {
+ log("Notify data connection state changed on sub: " + subId);
+ }
+ r.callback.onDataConnectionStateChanged(state, networkType);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+ }
+ }
+
+ mDataConnectionState[phoneId] = state;
+ mDataConnectionNetworkType[phoneId] = networkType;
+
+ handleRemoveListLocked();
+ }
}
}
}