summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Shi <kaishi@google.com>2022-04-19 16:48:01 -0700
committerKai Shi <kaishi@google.com>2022-04-20 08:35:30 -0700
commitf00004edfd816101f7c20be91e27b92b0ff1c3c6 (patch)
treeb29112df9f3ce8facef677dee97459f5f0a8762d
parenta68572f0f423a830e2557b0ff1b6cc817f90b16e (diff)
downloadUwb-f00004edfd816101f7c20be91e27b92b0ff1c3c6.tar.gz
Trigger bugreport for device error
Add an option to trigger bugreport for device initialization error or device status error. Test: atest com.android.server.uwb Bug: 229789022 Change-Id: I83a0184452081607297c53464b147d651282df02
-rw-r--r--service/java/com/android/server/uwb/DeviceConfigFacade.java21
-rw-r--r--service/java/com/android/server/uwb/SystemBuildProperties.java36
-rw-r--r--service/java/com/android/server/uwb/UwbDiagnostics.java62
-rw-r--r--service/java/com/android/server/uwb/UwbInjector.java8
-rw-r--r--service/java/com/android/server/uwb/UwbServiceCore.java8
-rw-r--r--service/tests/src/com/android/server/uwb/DeviceConfigFacadeTest.java12
-rw-r--r--service/tests/src/com/android/server/uwb/UwbDiagnosticsTest.java83
-rw-r--r--service/tests/src/com/android/server/uwb/UwbServiceCoreTest.java4
8 files changed, 232 insertions, 2 deletions
diff --git a/service/java/com/android/server/uwb/DeviceConfigFacade.java b/service/java/com/android/server/uwb/DeviceConfigFacade.java
index 29554ee1..cd841960 100644
--- a/service/java/com/android/server/uwb/DeviceConfigFacade.java
+++ b/service/java/com/android/server/uwb/DeviceConfigFacade.java
@@ -24,11 +24,14 @@ import android.provider.DeviceConfig;
*/
public class DeviceConfigFacade {
public static final int DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS = 5_000;
+ public static final int DEFAULT_BUG_REPORT_MIN_INTERVAL_MS = 24 * 3_600_000;
private final UwbInjector mUwbInjector;
// Cached values of fields updated via updateDeviceConfigFlags()
private int mRangingResultLogIntervalMs;
+ private boolean mDeviceErrorBugreportEnabled;
+ private int mBugReportMinIntervalMs;
public DeviceConfigFacade(Handler handler, UwbInjector uwbInjector) {
mUwbInjector = uwbInjector;
@@ -45,6 +48,10 @@ public class DeviceConfigFacade {
private void updateDeviceConfigFlags() {
mRangingResultLogIntervalMs = DeviceConfig.getInt(DeviceConfig.NAMESPACE_UWB,
"ranging_result_log_interval_ms", DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS);
+ mDeviceErrorBugreportEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_UWB,
+ "device_error_bugreport_enabled", false);
+ mBugReportMinIntervalMs = DeviceConfig.getInt(DeviceConfig.NAMESPACE_UWB,
+ "bug_report_min_interval_ms", DEFAULT_BUG_REPORT_MIN_INTERVAL_MS);
}
/**
@@ -53,4 +60,18 @@ public class DeviceConfigFacade {
public int getRangingResultLogIntervalMs() {
return mRangingResultLogIntervalMs;
}
+
+ /**
+ * Gets the feature flag for reporting device error
+ */
+ public boolean isDeviceErrorBugreportEnabled() {
+ return mDeviceErrorBugreportEnabled;
+ }
+
+ /**
+ * Gets minimum wait time between two bug report captures
+ */
+ public int getBugReportMinIntervalMs() {
+ return mBugReportMinIntervalMs;
+ }
}
diff --git a/service/java/com/android/server/uwb/SystemBuildProperties.java b/service/java/com/android/server/uwb/SystemBuildProperties.java
new file mode 100644
index 00000000..4090978d
--- /dev/null
+++ b/service/java/com/android/server/uwb/SystemBuildProperties.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.uwb;
+
+import android.os.Build;
+
+class SystemBuildProperties {
+ /** @return if it is an eng build. */
+ public boolean isEngBuild() {
+ return Build.TYPE.equals("eng");
+ }
+
+ /** @return if it is an userdebug build. */
+ public boolean isUserdebugBuild() {
+ return Build.TYPE.equals("userdebug");
+ }
+
+ /** @return if it is a normal user build. */
+ public boolean isUserBuild() {
+ return Build.TYPE.equals("user");
+ }
+}
diff --git a/service/java/com/android/server/uwb/UwbDiagnostics.java b/service/java/com/android/server/uwb/UwbDiagnostics.java
new file mode 100644
index 00000000..173f9ebc
--- /dev/null
+++ b/service/java/com/android/server/uwb/UwbDiagnostics.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.uwb;
+
+import android.content.Context;
+import android.os.BugreportManager;
+import android.os.BugreportParams;
+import android.util.Log;
+
+/**
+ * A class to trigger bugreport and other logs for UWB related failures
+ */
+public class UwbDiagnostics {
+ private static final String TAG = "UwbDiagnostics";
+ private final Context mContext;
+ private final SystemBuildProperties mSystemBuildProperties;
+ private final UwbInjector mUwbInjector;
+ private long mLastBugReportTimeMs;
+ public UwbDiagnostics(
+ Context context, UwbInjector uwbInjector, SystemBuildProperties systemBuildProperties) {
+ mContext = context;
+ mSystemBuildProperties = systemBuildProperties;
+ mUwbInjector = uwbInjector;
+ }
+
+ /**
+ * Take a bug report if it is not in user build and there is no recent bug report
+ */
+ public void takeBugReport(String bugTitle) {
+ if (mSystemBuildProperties.isUserBuild()) {
+ return;
+ }
+ long currentTimeMs = mUwbInjector.getElapsedSinceBootMillis();
+ if ((currentTimeMs - mLastBugReportTimeMs)
+ < mUwbInjector.getDeviceConfigFacade().getBugReportMinIntervalMs()
+ && mLastBugReportTimeMs > 0) {
+ return;
+ }
+ mLastBugReportTimeMs = currentTimeMs;
+ BugreportManager bugreportManager = mContext.getSystemService(BugreportManager.class);
+ BugreportParams params = new BugreportParams(BugreportParams.BUGREPORT_MODE_FULL);
+ try {
+ bugreportManager.requestBugreport(params, bugTitle, bugTitle);
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Error taking bugreport: " + e);
+ }
+ }
+}
diff --git a/service/java/com/android/server/uwb/UwbInjector.java b/service/java/com/android/server/uwb/UwbInjector.java
index ace37f80..70d32b9b 100644
--- a/service/java/com/android/server/uwb/UwbInjector.java
+++ b/service/java/com/android/server/uwb/UwbInjector.java
@@ -74,6 +74,8 @@ public class UwbInjector {
private final UwbMetrics mUwbMetrics;
private final DeviceConfigFacade mDeviceConfigFacade;
private final UwbMultichipData mUwbMultichipData;
+ private final SystemBuildProperties mSystemBuildProperties;
+ private final UwbDiagnostics mUwbDiagnostics;
public UwbInjector(@NonNull UwbContext context) {
// Create UWB service thread.
@@ -103,6 +105,8 @@ public class UwbInjector {
mContext.getSystemService(AlarmManager.class), mLooper);
mUwbService = new UwbServiceCore(mContext, mNativeUwbManager, mUwbMetrics,
mUwbCountryCode, uwbSessionManager, uwbConfigurationManager, this, mLooper);
+ mSystemBuildProperties = new SystemBuildProperties();
+ mUwbDiagnostics = new UwbDiagnostics(mContext, this, mSystemBuildProperties);
}
public UwbSettingsStore getUwbSettingsStore() {
@@ -133,6 +137,10 @@ public class UwbInjector {
return mUwbService;
}
+ public UwbDiagnostics getUwbDiagnostics() {
+ return mUwbDiagnostics;
+ }
+
/**
* Create a UwbShellCommand instance.
*/
diff --git a/service/java/com/android/server/uwb/UwbServiceCore.java b/service/java/com/android/server/uwb/UwbServiceCore.java
index d97ccf80..54abc54b 100644
--- a/service/java/com/android/server/uwb/UwbServiceCore.java
+++ b/service/java/com/android/server/uwb/UwbServiceCore.java
@@ -179,6 +179,7 @@ public class UwbServiceCore implements INativeUwbManager.DeviceNotification,
if ((byte) deviceState == UwbUciConstants.DEVICE_STATE_ERROR) {
Log.e(TAG, "Error device status received. Disabling...");
mUwbMetrics.incrementDeviceStatusErrorCount();
+ takBugReportAfterDeviceError("UWB is disabled due to device status error");
setEnabled(false);
return;
}
@@ -521,6 +522,7 @@ public class UwbServiceCore implements INativeUwbManager.DeviceNotification,
if (!mNativeUwbManager.doInitialize()) {
Log.e(TAG, "Error enabling UWB");
mUwbMetrics.incrementDeviceInitFailureCount();
+ takBugReportAfterDeviceError("Error enabling UWB");
updateState(AdapterStateCallback.STATE_DISABLED,
StateChangeReason.SYSTEM_POLICY);
} else {
@@ -633,6 +635,12 @@ public class UwbServiceCore implements INativeUwbManager.DeviceNotification,
}
}
+ private void takBugReportAfterDeviceError(String bugTitle) {
+ if (mUwbInjector.getDeviceConfigFacade().isDeviceErrorBugreportEnabled()) {
+ mUwbInjector.getUwbDiagnostics().takeBugReport(bugTitle);
+ }
+ }
+
/**
* Dump the UWB service status
*/
diff --git a/service/tests/src/com/android/server/uwb/DeviceConfigFacadeTest.java b/service/tests/src/com/android/server/uwb/DeviceConfigFacadeTest.java
index a75da48f..59025a51 100644
--- a/service/tests/src/com/android/server/uwb/DeviceConfigFacadeTest.java
+++ b/service/tests/src/com/android/server/uwb/DeviceConfigFacadeTest.java
@@ -45,8 +45,7 @@ import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
public class DeviceConfigFacadeTest {
- @Mock
- UwbInjector mUwbInjector;
+ @Mock UwbInjector mUwbInjector;
final ArgumentCaptor<DeviceConfig.OnPropertiesChangedListener>
mOnPropertiesChangedListenerCaptor =
@@ -114,6 +113,9 @@ public class DeviceConfigFacadeTest {
public void testDefaultValue() throws Exception {
assertEquals(DeviceConfigFacade.DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS,
mDeviceConfigFacade.getRangingResultLogIntervalMs());
+ assertEquals(false, mDeviceConfigFacade.isDeviceErrorBugreportEnabled());
+ assertEquals(DeviceConfigFacade.DEFAULT_BUG_REPORT_MIN_INTERVAL_MS,
+ mDeviceConfigFacade.getBugReportMinIntervalMs());
}
/**
@@ -124,10 +126,16 @@ public class DeviceConfigFacadeTest {
// Simulate updating the fields
when(DeviceConfig.getInt(anyString(), eq("ranging_result_log_interval_ms"),
anyInt())).thenReturn(4000);
+ when(DeviceConfig.getBoolean(anyString(), eq("device_error_bugreport_enabled"),
+ anyBoolean())).thenReturn(true);
+ when(DeviceConfig.getInt(anyString(), eq("bug_report_min_interval_ms"),
+ anyInt())).thenReturn(10 * 3600_000);
mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null);
// Verifying fields are updated to the new values
assertEquals(4000, mDeviceConfigFacade.getRangingResultLogIntervalMs());
+ assertEquals(true, mDeviceConfigFacade.isDeviceErrorBugreportEnabled());
+ assertEquals(10 * 3600_000, mDeviceConfigFacade.getBugReportMinIntervalMs());
}
}
diff --git a/service/tests/src/com/android/server/uwb/UwbDiagnosticsTest.java b/service/tests/src/com/android/server/uwb/UwbDiagnosticsTest.java
new file mode 100644
index 00000000..51f785f7
--- /dev/null
+++ b/service/tests/src/com/android/server/uwb/UwbDiagnosticsTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.uwb;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.BugreportManager;
+import android.platform.test.annotations.Presubmit;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests for {@link com.android.server.uwb.UwbDiagnostics}.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class UwbDiagnosticsTest {
+ @Mock SystemBuildProperties mBuildProperties;
+ @Mock Context mContext;
+ @Mock UwbInjector mUwbInjector;
+ @Mock DeviceConfigFacade mDeviceConfigFacade;
+ @Mock BugreportManager mBugreportManager;
+ UwbDiagnostics mUwbDiagnostics;
+
+ private static final int BUG_REPORT_MIN_INTERVAL_MS = 3600_000;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mUwbInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
+ when(mDeviceConfigFacade.getBugReportMinIntervalMs())
+ .thenReturn(BUG_REPORT_MIN_INTERVAL_MS);
+ when(mBuildProperties.isUserBuild()).thenReturn(false);
+ when(mContext.getSystemService(BugreportManager.class)).thenReturn(mBugreportManager);
+ mUwbDiagnostics = new UwbDiagnostics(mContext, mUwbInjector, mBuildProperties);
+ }
+
+ @Test
+ public void takeBugReportDoesNothingOnUserBuild() throws Exception {
+ when(mBuildProperties.isUserBuild()).thenReturn(true);
+ mUwbDiagnostics.takeBugReport("");
+ verify(mBugreportManager, never()).requestBugreport(any(), any(), any());
+ }
+
+ @Test
+ public void takeBugReportTwiceWithInsufficientTimeGapSkipSecondRequest() throws Exception {
+ // 1st attempt should succeed
+ when(mUwbInjector.getElapsedSinceBootMillis()).thenReturn(10L);
+ mUwbDiagnostics.takeBugReport("");
+ verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any());
+ // 2nd attempt should fail
+ when(mUwbInjector.getWallClockMillis()).thenReturn(BUG_REPORT_MIN_INTERVAL_MS - 20L);
+ mUwbDiagnostics.takeBugReport("");
+ verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any());
+ }
+}
diff --git a/service/tests/src/com/android/server/uwb/UwbServiceCoreTest.java b/service/tests/src/com/android/server/uwb/UwbServiceCoreTest.java
index 0b5ff02a..5c22ae83 100644
--- a/service/tests/src/com/android/server/uwb/UwbServiceCoreTest.java
+++ b/service/tests/src/com/android/server/uwb/UwbServiceCoreTest.java
@@ -152,6 +152,7 @@ public class UwbServiceCoreTest {
@Mock private UwbSessionManager mUwbSessionManager;
@Mock private UwbConfigurationManager mUwbConfigurationManager;
@Mock private UwbInjector mUwbInjector;
+ @Mock DeviceConfigFacade mDeviceConfigFacade;
private TestLooper mTestLooper;
private MockitoSession mMockitoSession;
@@ -167,6 +168,9 @@ public class UwbServiceCoreTest {
when(mContext.getSystemService(PowerManager.class)).thenReturn(powerManager);
when(mUwbInjector.isSystemApp(TEST_UID, TEST_PACKAGE_NAME)).thenReturn(true);
when(mUwbInjector.isForegroundAppOrService(TEST_UID, TEST_PACKAGE_NAME)).thenReturn(true);
+ when(mUwbInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
+ when(mDeviceConfigFacade.getBugReportMinIntervalMs())
+ .thenReturn(DeviceConfigFacade.DEFAULT_BUG_REPORT_MIN_INTERVAL_MS);
mUwbServiceCore = new UwbServiceCore(mContext, mNativeUwbManager, mUwbMetrics,
mUwbCountryCode, mUwbSessionManager, mUwbConfigurationManager,
mUwbInjector, mTestLooper.getLooper());