summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoshan Pius <rpius@google.com>2022-03-31 03:41:07 +0000
committerRoshan Pius <rpius@google.com>2022-03-31 03:46:23 +0000
commiteb9e1386ebf1bc7da65dff0a3c0804ac6be3736f (patch)
treefab077fe56dbb6e8ae132cea7856eca981113fac
parentd31858155666ce4154900ca2544fc5b272519a4b (diff)
downloadUwb-eb9e1386ebf1bc7da65dff0a3c0804ac6be3736f.tar.gz
uwb(service): Start timer to track continous errors
Previous approach of using the ranging result callbacks does not work if the device is the responder and the initiator disappears. The firmware will stop sending ranging result callbacks in that case. Also, declare error for ranging result only if all the ranging measurements (for one to many sessions) are in error. Bug: 222379826 Test: Manual tests Test: atest ServiceUwbTests Change-Id: I869882582cbdb39d70107a54a6ad794decd5f0c9
-rw-r--r--service/java/com/android/server/uwb/UwbInjector.java4
-rw-r--r--service/java/com/android/server/uwb/UwbSessionManager.java71
-rw-r--r--service/tests/src/com/android/server/uwb/UwbSessionManagerTest.java74
3 files changed, 100 insertions, 49 deletions
diff --git a/service/java/com/android/server/uwb/UwbInjector.java b/service/java/com/android/server/uwb/UwbInjector.java
index dae0aa1f..f119acba 100644
--- a/service/java/com/android/server/uwb/UwbInjector.java
+++ b/service/java/com/android/server/uwb/UwbInjector.java
@@ -20,6 +20,7 @@ import static android.Manifest.permission.UWB_RANGING;
import static android.permission.PermissionManager.PERMISSION_GRANTED;
import android.annotation.NonNull;
+import android.app.AlarmManager;
import android.content.ApexEnvironment;
import android.content.AttributionSource;
import android.content.pm.ApplicationInfo;
@@ -90,7 +91,8 @@ public class UwbInjector {
new UwbSessionNotificationManager(this);
UwbSessionManager uwbSessionManager =
new UwbSessionManager(uwbConfigurationManager, mNativeUwbManager, mUwbMetrics,
- uwbSessionNotificationManager, this, mLooper);
+ uwbSessionNotificationManager, this,
+ mContext.getSystemService(AlarmManager.class), mLooper);
mUwbService = new UwbServiceCore(mContext, mNativeUwbManager, mUwbMetrics,
mUwbCountryCode, uwbSessionManager, uwbConfigurationManager, mLooper);
}
diff --git a/service/java/com/android/server/uwb/UwbSessionManager.java b/service/java/com/android/server/uwb/UwbSessionManager.java
index 305684c8..5c978450 100644
--- a/service/java/com/android/server/uwb/UwbSessionManager.java
+++ b/service/java/com/android/server/uwb/UwbSessionManager.java
@@ -20,6 +20,7 @@ import static com.google.uwb.support.fira.FiraParams.MULTICAST_LIST_UPDATE_ACTIO
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AlarmManager;
import android.content.AttributionSource;
import android.os.Handler;
import android.os.IBinder;
@@ -84,31 +85,32 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
private final UwbConfigurationManager mConfigurationManager;
private final UwbSessionNotificationManager mSessionNotificationManager;
private final UwbInjector mUwbInjector;
+ private final AlarmManager mAlarmManager;
private final int mMaxSessionNumber;
private final EventTask mEventTask;
public UwbSessionManager(UwbConfigurationManager uwbConfigurationManager,
NativeUwbManager nativeUwbManager, UwbMetrics uwbMetrics,
UwbSessionNotificationManager uwbSessionNotificationManager,
- UwbInjector uwbInjector,
- Looper serviceLooper) {
+ UwbInjector uwbInjector, AlarmManager alarmManager, Looper serviceLooper) {
mNativeUwbManager = nativeUwbManager;
mNativeUwbManager.setSessionListener(this);
mUwbMetrics = uwbMetrics;
mConfigurationManager = uwbConfigurationManager;
mSessionNotificationManager = uwbSessionNotificationManager;
mUwbInjector = uwbInjector;
+ mAlarmManager = alarmManager;
mMaxSessionNumber = mNativeUwbManager.getMaxSessionNumber();
mEventTask = new EventTask(serviceLooper);
}
- private static boolean hasAnyRangingResultError(@NonNull UwbRangingData rangingData) {
+ private static boolean hasAllRangingResultError(@NonNull UwbRangingData rangingData) {
for (UwbTwoWayMeasurement measure : rangingData.getRangingTwoWayMeasures()) {
- if (measure.getRangingStatus() != UwbUciConstants.STATUS_CODE_OK) {
- return true;
+ if (measure.getRangingStatus() == UwbUciConstants.STATUS_CODE_OK) {
+ return false;
}
}
- return false;
+ return true;
}
@Override
@@ -118,14 +120,10 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
if (uwbSession != null) {
mUwbMetrics.logRangingResult(uwbSession.getProfileType(), rangingData);
mSessionNotificationManager.onRangingResult(uwbSession, rangingData);
- if (hasAnyRangingResultError(rangingData)) {
- boolean shouldStopSession =
- uwbSession.noteRangingResultError(mUwbInjector.getElapsedSinceBootMillis());
- if (shouldStopSession) {
- stopRanging(uwbSession.getSessionHandle());
- }
+ if (hasAllRangingResultError(rangingData)) {
+ uwbSession.startRangingResultErrorStreakTimerIfNotSet();
} else {
- uwbSession.resetRangingResultErrorStreakTimestamp();
+ uwbSession.stopRangingResultErrorStreakTimerIfSet();
}
} else {
Log.i(TAG, "Session is not initialized or Ranging Data is Null");
@@ -667,7 +665,7 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
mUwbMetrics.longRangingStopEvent(uwbSession);
}
// Reset any stored error streak timestamp when session is stopped.
- uwbSession.resetRangingResultErrorStreakTimestamp();
+ uwbSession.stopRangingResultErrorStreakTimerIfSet();
}
private void reconfigure(SessionHandle sessionHandle, @Nullable Params param) {
@@ -837,7 +835,9 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
public class UwbSession implements IBinder.DeathRecipient {
// Amount of time we allow continuous failures before stopping the session.
@VisibleForTesting
- public static final long ALLOWED_RANGING_RESULT_ERROR_STREAK_MS = 30_000L;
+ public static final long RANGING_RESULT_ERROR_STREAK_TIMER_TIMEOUT_MS = 30_000L;
+ private static final String RANGING_RESULT_ERROR_STREAK_TIMER_TAG =
+ "UwbSessionRangingResultError";
private final AttributionSource mAttributionSource;
private final SessionHandle mSessionHandle;
@@ -851,7 +851,7 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
private int mSessionState;
private UwbMulticastListUpdateStatus mMulticastListUpdateStatus;
private final int mProfileType;
- private long mRangingResultErrorStreakStartTimestampMs;
+ private AlarmManager.OnAlarmListener mRangingResultErrorStreakTimerListener;
UwbSession(AttributionSource attributionSource, SessionHandle sessionHandle, int sessionId,
String protocolName, Params params, IUwbRangingCallbacks iUwbRangingCallbacks) {
@@ -952,29 +952,32 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
return mWaitObj;
}
- private boolean isLongerThanAllowedErrorStreak(long currentTimestampMs) {
- return (mRangingResultErrorStreakStartTimestampMs
- + ALLOWED_RANGING_RESULT_ERROR_STREAK_MS)
- < currentTimestampMs;
- }
-
/**
- * Note ranging result error.
- * @param currentTimestampMs Current timestamp to use for detecting error streaks.
- * @return Returns true if the error streak is longer than
- * {@link #ALLOWED_RANGING_RESULT_ERROR_STREAK_MS}.
+ * Starts a timer to detect if the error streak is longer than
+ * {@link #RANGING_RESULT_ERROR_STREAK_TIMER_TIMEOUT_MS}.
*/
- public boolean noteRangingResultError(long currentTimestampMs) {
- // Note the timestamp for the first failure to detect continuous failures.
- if (mRangingResultErrorStreakStartTimestampMs == 0L) {
- mRangingResultErrorStreakStartTimestampMs = currentTimestampMs;
+ public void startRangingResultErrorStreakTimerIfNotSet() {
+ // Start a timer on first failure to detect continuous failures.
+ if (mRangingResultErrorStreakTimerListener == null) {
+ mRangingResultErrorStreakTimerListener = () -> {
+ Log.w(TAG, "Continuous errors or no ranging results detected for 30 seconds."
+ + " Stopping session");
+ stopRanging(mSessionHandle);
+ };
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ mUwbInjector.getElapsedSinceBootMillis()
+ + RANGING_RESULT_ERROR_STREAK_TIMER_TIMEOUT_MS,
+ RANGING_RESULT_ERROR_STREAK_TIMER_TAG,
+ mRangingResultErrorStreakTimerListener, mEventTask);
}
- return isLongerThanAllowedErrorStreak(currentTimestampMs);
}
- public void resetRangingResultErrorStreakTimestamp() {
- // Reset error streak on any success.
- mRangingResultErrorStreakStartTimestampMs = 0L;
+ public void stopRangingResultErrorStreakTimerIfSet() {
+ // Cancel error streak timer on any success.
+ if (mRangingResultErrorStreakTimerListener != null) {
+ mAlarmManager.cancel(mRangingResultErrorStreakTimerListener);
+ mRangingResultErrorStreakTimerListener = null;
+ }
}
@Override
diff --git a/service/tests/src/com/android/server/uwb/UwbSessionManagerTest.java b/service/tests/src/com/android/server/uwb/UwbSessionManagerTest.java
index c76446b1..c46f3160 100644
--- a/service/tests/src/com/android/server/uwb/UwbSessionManagerTest.java
+++ b/service/tests/src/com/android/server/uwb/UwbSessionManagerTest.java
@@ -16,13 +16,12 @@
package com.android.server.uwb;
-import static com.android.server.uwb.UwbSessionManager.UwbSession.ALLOWED_RANGING_RESULT_ERROR_STREAK_MS;
-
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyByte;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeast;
@@ -36,6 +35,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.AlarmManager;
import android.content.AttributionSource;
import android.os.IBinder;
import android.os.RemoteException;
@@ -66,6 +66,7 @@ import com.google.uwb.support.fira.FiraRangingReconfigureParams;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@@ -97,15 +98,14 @@ public class UwbSessionManagerTest {
private UwbSessionNotificationManager mUwbSessionNotificationManager;
@Mock
private UwbInjector mUwbInjector;
+ @Mock
+ private ExecutorService mExecutorService;
+ @Mock
+ private AlarmManager mAlarmManager;
private TestLooper mTestLooper = new TestLooper();
-
private UwbSessionManager mUwbSessionManager;
-
private MockitoSession mMockitoSession;
- @Mock
- private ExecutorService mExecutorService;
-
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
@@ -118,6 +118,7 @@ public class UwbSessionManagerTest {
mUwbMetrics,
mUwbSessionNotificationManager,
mUwbInjector,
+ mAlarmManager,
mTestLooper.getLooper()));
// static mocking for executor service.
@@ -947,11 +948,23 @@ public class UwbSessionManagerTest {
eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
// Now send a range data notification with an error.
- when(mUwbInjector.getElapsedSinceBootMillis()).thenReturn(1L);
UwbRangingData uwbRangingData =
UwbTestUtils.generateRangingData(UwbUciConstants.STATUS_CODE_RANGING_RX_TIMEOUT);
mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
+ ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
+ ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
+ verify(mAlarmManager).set(
+ anyInt(), anyLong(), anyString(), alarmListenerCaptor.capture(), any());
+ assertThat(alarmListenerCaptor.getValue()).isNotNull();
+
+ // Send one more error and ensure that the timer is not cancelled.
+ uwbRangingData =
+ UwbTestUtils.generateRangingData(UwbUciConstants.STATUS_CODE_RANGING_RX_TIMEOUT);
+ mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
+ verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
+
+ verify(mAlarmManager, never()).cancel(any(AlarmManager.OnAlarmListener.class));
// set up for stop ranging
doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE, UwbUciConstants.UWB_SESSION_STATE_IDLE)
@@ -959,12 +972,8 @@ public class UwbSessionManagerTest {
when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID)))
.thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
- when(mUwbInjector.getElapsedSinceBootMillis())
- .thenReturn(ALLOWED_RANGING_RESULT_ERROR_STREAK_MS + 5L);
- uwbRangingData =
- UwbTestUtils.generateRangingData(UwbUciConstants.STATUS_CODE_RANGING_RX_TIMEOUT);
- mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
- verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
+ // Now fire the timer callback.
+ alarmListenerCaptor.getValue().onAlarm();
// Expect session stop.
mTestLooper.dispatchNext();
@@ -974,6 +983,43 @@ public class UwbSessionManagerTest {
}
@Test
+ public void execStartRanging_onRangeDataNotificationErrorFollowedBySuccess() throws Exception {
+ UwbSession uwbSession = prepareExistingUwbSession();
+ // set up for start ranging
+ doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
+ .when(uwbSession).getSessionState();
+ when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID)))
+ .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
+
+ mUwbSessionManager.startRanging(
+ uwbSession.getSessionHandle(), uwbSession.getParams());
+ mTestLooper.dispatchAll();
+
+ verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
+ verify(mUwbMetrics).longRangingStartEvent(
+ eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
+
+ // Now send a range data notification with an error.
+ UwbRangingData uwbRangingData =
+ UwbTestUtils.generateRangingData(UwbUciConstants.STATUS_CODE_RANGING_RX_TIMEOUT);
+ mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
+ verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
+ ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
+ ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
+ verify(mAlarmManager).set(
+ anyInt(), anyLong(), anyString(), alarmListenerCaptor.capture(), any());
+ assertThat(alarmListenerCaptor.getValue()).isNotNull();
+
+ // Send success and ensure that the timer is cancelled.
+ uwbRangingData =
+ UwbTestUtils.generateRangingData(UwbUciConstants.STATUS_CODE_OK);
+ mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
+ verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
+
+ verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
+ }
+
+ @Test
public void execStartCccRanging_success() throws Exception {
UwbSession uwbSession = prepareExistingCccUwbSession();
// set up for start ranging