Merge "Revert "Unbind CS if connection is not created within 15 seconds."" into main
diff --git a/Android.bp b/Android.bp
index 0d1c81d..65e4402 100644
--- a/Android.bp
+++ b/Android.bp
@@ -31,6 +31,7 @@
"androidx.annotation_annotation",
"androidx.core_core",
"telecom_flags_core_java_lib",
+ "modules-utils-handlerexecutor",
],
resource_dirs: ["res"],
proto: {
diff --git a/flags/telecom_callaudioroutestatemachine_flags.aconfig b/flags/telecom_callaudioroutestatemachine_flags.aconfig
index 62b8bdb..3dd5c9d 100644
--- a/flags/telecom_callaudioroutestatemachine_flags.aconfig
+++ b/flags/telecom_callaudioroutestatemachine_flags.aconfig
@@ -107,3 +107,14 @@
purpose: PURPOSE_BUGFIX
}
}
+
+# OWNER=pmadapurmath TARGET=25Q1
+flag {
+ name: "new_audio_path_speaker_broadcast_and_unfocused_routing"
+ namespace: "telecom"
+ description: "Replace the speaker broadcasts with the communication device changed listener and resolve baseline routing issues when a call ends."
+ bug: "353419513"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/src/com/android/server/telecom/AudioRoute.java b/src/com/android/server/telecom/AudioRoute.java
index 6dc64ba..d3ed77d 100644
--- a/src/com/android/server/telecom/AudioRoute.java
+++ b/src/com/android/server/telecom/AudioRoute.java
@@ -318,7 +318,8 @@
// sending SPEAKER_OFF, or disconnecting SCO).
void onOrigRouteAsPendingRoute(boolean active, PendingAudioRoute pendingAudioRoute,
AudioManager audioManager, BluetoothRouteManager bluetoothRouteManager) {
- Log.i(this, "onOrigRouteAsPendingRoute: active (%b), type (%d)", active, mAudioRouteType);
+ Log.i(this, "onOrigRouteAsPendingRoute: active (%b), type (%s)", active,
+ DEVICE_TYPE_STRINGS.get(mAudioRouteType));
if (active) {
int result = clearCommunicationDevice(pendingAudioRoute, bluetoothRouteManager,
audioManager);
diff --git a/src/com/android/server/telecom/CallAudioModeStateMachine.java b/src/com/android/server/telecom/CallAudioModeStateMachine.java
index fb196f2..e149bdd 100644
--- a/src/com/android/server/telecom/CallAudioModeStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioModeStateMachine.java
@@ -17,7 +17,6 @@
package com.android.server.telecom;
import android.media.AudioAttributes;
-import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.os.Looper;
import android.os.Message;
@@ -47,22 +46,6 @@
}
}
- private static final AudioAttributes RING_AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
- .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
- .setLegacyStreamType(AudioManager.STREAM_RING)
- .build();
- public static final AudioFocusRequest RING_AUDIO_FOCUS_REQUEST = new AudioFocusRequest
- .Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)
- .setAudioAttributes(RING_AUDIO_ATTRIBUTES).build();
-
- private static final AudioAttributes CALL_AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
- .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
- .setLegacyStreamType(AudioManager.STREAM_VOICE_CALL)
- .build();
- public static final AudioFocusRequest CALL_AUDIO_FOCUS_REQUEST = new AudioFocusRequest
- .Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)
- .setAudioAttributes(CALL_AUDIO_ATTRIBUTES).build();
-
public static class MessageArgs {
public boolean hasActiveOrDialingCalls;
public boolean hasRingingCalls;
@@ -232,8 +215,6 @@
public static final String STREAMING_STATE_NAME = StreamingFocusState.class.getSimpleName();
public static final String COMMS_STATE_NAME = VoipCallFocusState.class.getSimpleName();
- private AudioFocusRequest mCurrentAudioFocusRequest = null;
-
private class BaseState extends State {
@Override
public boolean processMessage(Message msg) {
@@ -348,18 +329,9 @@
+ args.toString());
return HANDLED;
case AUDIO_OPERATIONS_COMPLETE:
- if (mFeatureFlags.telecomResolveHiddenDependencies()) {
- if (mCurrentAudioFocusRequest != null) {
- Log.i(this, "AudioOperationsComplete: "
- + "AudioManager#abandonAudioFocusRequest(); now unfocused");
- mAudioManager.abandonAudioFocusRequest(mCurrentAudioFocusRequest);
- mCurrentAudioFocusRequest = null;
- } else {
- Log.i(this, "AudioOperationsComplete: already unfocused");
- }
- } else {
- mAudioManager.abandonAudioFocusForCall();
- }
+ Log.i(this, "AudioOperationsComplete: "
+ + "AudioManager#abandonAudioFocusRequest(); now unfocused");
+ mAudioManager.abandonAudioFocusForCall();
// Clear requested communication device after the call ends.
if (mFeatureFlags.clearCommunicationDeviceAfterAudioOpsComplete()) {
mCommunicationDeviceTracker.clearCommunicationDevice(
@@ -438,14 +410,7 @@
case AUDIO_OPERATIONS_COMPLETE:
Log.i(LOG_TAG, "AudioManager#abandonAudioFocusRequest: now "
+ "AUDIO_PROCESSING");
- if (mFeatureFlags.telecomResolveHiddenDependencies()) {
- if (mCurrentAudioFocusRequest != null) {
- mAudioManager.abandonAudioFocusRequest(mCurrentAudioFocusRequest);
- mCurrentAudioFocusRequest = null;
- }
- } else {
- mAudioManager.abandonAudioFocusForCall();
- }
+ mAudioManager.abandonAudioFocusForCall();
return HANDLED;
default:
// The forced focus switch commands are handled by BaseState.
@@ -468,14 +433,10 @@
}
if (mCallAudioManager.startRinging()) {
- if (mFeatureFlags.telecomResolveHiddenDependencies()) {
- mCurrentAudioFocusRequest = RING_AUDIO_FOCUS_REQUEST;
- Log.i(this, "tryStartRinging: AudioManager#requestAudioFocus(RING)");
- mAudioManager.requestAudioFocus(RING_AUDIO_FOCUS_REQUEST);
- } else {
- mAudioManager.requestAudioFocusForCall(
- AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
- }
+ Log.i(this, "tryStartRinging: AudioManager#requestAudioFocus(RING)");
+ mAudioManager.requestAudioFocusForCall(
+ AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+
// Do not set MODE_RINGTONE if we were previously in the CALL_SCREENING mode --
// this trips up the audio system.
if (mAudioManager.getMode() != AudioManager.MODE_CALL_SCREENING) {
@@ -570,14 +531,9 @@
public void enter() {
Log.i(LOG_TAG, "Audio focus entering SIM CALL state");
mLocalLog.log("Enter SIM_CALL");
- if (mFeatureFlags.telecomResolveHiddenDependencies()) {
- mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST;
- Log.i(this, "enter: AudioManager#requestAudioFocus(CALL)");
- mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST);
- } else {
- mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
- }
+ Log.i(this, "enter: AudioManager#requestAudioFocus(CALL)");
+ mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
Log.i(this, "enter: AudioManager#setMode(MODE_IN_CALL)");
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
mLocalLog.log("Mode MODE_IN_CALL");
@@ -660,14 +616,9 @@
public void enter() {
Log.i(LOG_TAG, "Audio focus entering VOIP CALL state");
mLocalLog.log("Enter VOIP_CALL");
- if (mFeatureFlags.telecomResolveHiddenDependencies()) {
- mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST;
- Log.i(this, "enter: AudioManager#requestAudioFocus(CALL)");
- mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST);
- } else {
- mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
- }
+ Log.i(this, "enter: AudioManager#requestAudioFocus(CALL)");
+ mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
Log.i(this, "enter: AudioManager#setMode(MODE_IN_COMMUNICATION)");
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mLocalLog.log("Mode MODE_IN_COMMUNICATION");
@@ -823,14 +774,9 @@
public void enter() {
Log.i(LOG_TAG, "Audio focus entering TONE/HOLDING state");
mLocalLog.log("Enter TONE/HOLDING");
- if (mFeatureFlags.telecomResolveHiddenDependencies()) {
- mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST;
- Log.i(this, "enter: AudioManager#requestAudioFocus(CALL)");
- mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST);
- } else {
- mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
- }
+ Log.i(this, "enter: AudioManager#requestAudioFocus(CALL)");
+ mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
Log.i(this, "enter: AudioManager#setMode(%d)", mMostRecentMode);
mAudioManager.setMode(mMostRecentMode);
mLocalLog.log("Mode " + mMostRecentMode);
diff --git a/src/com/android/server/telecom/CallAudioRouteController.java b/src/com/android/server/telecom/CallAudioRouteController.java
index 7422286..12d108f 100644
--- a/src/com/android/server/telecom/CallAudioRouteController.java
+++ b/src/com/android/server/telecom/CallAudioRouteController.java
@@ -17,6 +17,7 @@
package com.android.server.telecom;
import static com.android.server.telecom.AudioRoute.BT_AUDIO_ROUTE_TYPES;
+import static com.android.server.telecom.AudioRoute.DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE;
import static com.android.server.telecom.AudioRoute.TYPE_INVALID;
import static com.android.server.telecom.AudioRoute.TYPE_SPEAKER;
@@ -63,6 +64,8 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
public class CallAudioRouteController implements CallAudioRouteAdapter {
private static final AudioRoute DUMMY_ROUTE = new AudioRoute(TYPE_INVALID, null, null);
@@ -107,6 +110,8 @@
private PendingAudioRoute mPendingAudioRoute;
private AudioRoute.Factory mAudioRouteFactory;
private StatusBarNotifier mStatusBarNotifier;
+ private AudioManager.OnCommunicationDeviceChangedListener mCommunicationDeviceListener;
+ private ExecutorService mCommunicationDeviceChangedExecutor;
private FeatureFlags mFeatureFlags;
private int mFocusType;
private int mCallSupportedRouteMask = -1;
@@ -200,10 +205,12 @@
handlerThread.start();
// Register broadcast receivers
- IntentFilter speakerChangedFilter = new IntentFilter(
- AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED);
- speakerChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- context.registerReceiver(mSpeakerPhoneChangeReceiver, speakerChangedFilter);
+ if (!mFeatureFlags.newAudioPathSpeakerBroadcastAndUnfocusedRouting()) {
+ IntentFilter speakerChangedFilter = new IntentFilter(
+ AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED);
+ speakerChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ context.registerReceiver(mSpeakerPhoneChangeReceiver, speakerChangedFilter);
+ }
IntentFilter micMuteChangedFilter = new IntentFilter(
AudioManager.ACTION_MICROPHONE_MUTE_CHANGED);
@@ -214,6 +221,27 @@
muteChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
context.registerReceiver(mMuteChangeReceiver, muteChangedFilter);
+ // Register AudioManager#onCommunicationDeviceChangedListener listener to receive updates
+ // to communication device (via AudioManager#setCommunicationDevice). This is a replacement
+ // to using broadcasts in the hopes of improving performance.
+ mCommunicationDeviceChangedExecutor = Executors.newSingleThreadExecutor();
+ mCommunicationDeviceListener = new AudioManager.OnCommunicationDeviceChangedListener() {
+ @Override
+ public void onCommunicationDeviceChanged(AudioDeviceInfo device) {
+ @AudioRoute.AudioRouteType int audioType = device != null
+ ? DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.get(device.getType())
+ : TYPE_INVALID;
+ Log.i(this, "onCommunicationDeviceChanged: %d", audioType);
+ if (device != null && device.getType() == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) {
+ if (mCurrentRoute.getType() != TYPE_SPEAKER) {
+ sendMessageWithSessionInfo(SPEAKER_ON);
+ }
+ } else {
+ sendMessageWithSessionInfo(SPEAKER_OFF);
+ }
+ }
+ };
+
// Create handler
mHandler = new Handler(handlerThread.getLooper()) {
@Override
@@ -411,6 +439,11 @@
mIsActive = false;
mCallAudioState = new CallAudioState(mIsMute, ROUTE_MAP.get(mCurrentRoute.getType()),
supportMask, null, new HashSet<>());
+ if (mFeatureFlags.newAudioPathSpeakerBroadcastAndUnfocusedRouting()) {
+ mAudioManager.addOnCommunicationDeviceChangedListener(
+ mCommunicationDeviceChangedExecutor,
+ mCommunicationDeviceListener);
+ }
}
@Override
@@ -798,11 +831,11 @@
boolean currentRouteNeedsUpdate = mCurrentRoute.getType() == type;
if (mFeatureFlags.resolveActiveBtRoutingAndBtTimingIssue()) {
if (pendingRouteNeedsUpdate) {
- pendingRouteNeedsUpdate &= mPendingAudioRoute.getDestRoute().getBluetoothAddress()
+ pendingRouteNeedsUpdate = mPendingAudioRoute.getDestRoute().getBluetoothAddress()
.equals(previouslyActiveDeviceAddress);
}
if (currentRouteNeedsUpdate) {
- currentRouteNeedsUpdate &= mCurrentRoute.getBluetoothAddress()
+ currentRouteNeedsUpdate = mCurrentRoute.getBluetoothAddress()
.equals(previouslyActiveDeviceAddress);
}
}
@@ -852,8 +885,13 @@
// Reset mute state after call ends.
handleMuteChanged(false);
- // Route back to inactive route.
- routeTo(false, mCurrentRoute);
+ // Ensure we reset call audio state at the end of the call (i.e. if we're on
+ // speaker, route back to earpiece). If we're on BT, remain on BT if it's still
+ // connected.
+ AudioRoute route = mFeatureFlags.resolveActiveBtRoutingAndBtTimingIssue()
+ ? calculateBaselineRoute(true, null)
+ : mCurrentRoute;
+ routeTo(false, route);
// Clear pending messages
mPendingAudioRoute.clearPendingMessages();
clearRingingBluetoothAddress();
@@ -1173,7 +1211,7 @@
}
// Get corresponding audio route
- @AudioRoute.AudioRouteType int type = AudioRoute.DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.get(
+ @AudioRoute.AudioRouteType int type = DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.get(
deviceAttr.getType());
if (BT_AUDIO_ROUTE_TYPES.contains(type)) {
return getBluetoothRoute(type, deviceAttr.getAddress());
diff --git a/src/com/android/server/telecom/metrics/TelecomMetricsController.java b/src/com/android/server/telecom/metrics/TelecomMetricsController.java
index 1516ddd..df735c0 100644
--- a/src/com/android/server/telecom/metrics/TelecomMetricsController.java
+++ b/src/com/android/server/telecom/metrics/TelecomMetricsController.java
@@ -30,6 +30,8 @@
import androidx.annotation.VisibleForTesting;
+import com.android.modules.utils.HandlerExecutor;
+
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -122,10 +124,23 @@
@VisibleForTesting
public void registerAtom(int tag, TelecomPulledAtom atom) {
- mStats.put(tag, atom);
+ final StatsManager statsManager = mContext.getSystemService(StatsManager.class);
+ if (statsManager != null) {
+ statsManager.setPullAtomCallback(tag, null, new HandlerExecutor(atom), this);
+ mStats.put(tag, atom);
+ } else {
+ Log.w(TAG, "Unable to register the pulled atom as StatsManager is null");
+ }
}
public void destroy() {
+ final StatsManager statsManager = mContext.getSystemService(StatsManager.class);
+ if (statsManager != null) {
+ mStats.forEach((tag, stat) -> statsManager.clearPullAtomCallback(tag));
+ } else {
+ Log.w(TAG, "Unable to clear pulled atoms as StatsManager is null");
+ }
+
mStats.clear();
mHandlerThread.quitSafely();
}
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
index 4513c65..9414e16 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
@@ -16,15 +16,10 @@
package com.android.server.telecom.tests;
-import static com.android.server.telecom.CallAudioModeStateMachine.CALL_AUDIO_FOCUS_REQUEST;
-import static com.android.server.telecom.CallAudioModeStateMachine.RING_AUDIO_FOCUS_REQUEST;
-
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -49,7 +44,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
-import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
@RunWith(JUnit4.class)
@@ -329,33 +323,6 @@
verify(mCallAudioManager, times(2)).startRinging();
}
- @SmallTest
- @Test
- public void testAudioFocusRequestWithResolveHiddenDependencies() {
- CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper,
- mAudioManager, mTestThread.getLooper(), mFeatureFlags, mCommunicationDeviceTracker);
- when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(true);
- ArgumentCaptor<AudioFocusRequest> captor = ArgumentCaptor.forClass(AudioFocusRequest.class);
- sm.setCallAudioManager(mCallAudioManager);
-
- resetMocks();
- when(mCallAudioManager.startRinging()).thenReturn(true);
- when(mCallAudioManager.isRingtonePlaying()).thenReturn(false);
-
- sm.sendMessage(CallAudioModeStateMachine.ENTER_RING_FOCUS_FOR_TESTING);
- waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
- verify(mAudioManager).requestAudioFocus(captor.capture());
- assertTrue(areAudioFocusRequestsMatch(captor.getValue(), RING_AUDIO_FOCUS_REQUEST));
-
- sm.sendMessage(CallAudioModeStateMachine.ENTER_CALL_FOCUS_FOR_TESTING);
- waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
- verify(mAudioManager, atLeast(1)).requestAudioFocus(captor.capture());
- AudioFocusRequest request = captor.getValue();
- assertTrue(areAudioFocusRequestsMatch(request, CALL_AUDIO_FOCUS_REQUEST));
-
- sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING);
- }
-
private void resetMocks() {
clearInvocations(mCallAudioManager, mAudioManager);
}
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteControllerTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteControllerTest.java
index c0e9904..528585b 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteControllerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteControllerTest.java
@@ -193,6 +193,7 @@
when(mFeatureFlags.ignoreAutoRouteToWatchDevice()).thenReturn(false);
when(mFeatureFlags.useRefactoredAudioRouteSwitching()).thenReturn(true);
when(mFeatureFlags.resolveActiveBtRoutingAndBtTimingIssue()).thenReturn(false);
+ when(mFeatureFlags.newAudioPathSpeakerBroadcastAndUnfocusedRouting()).thenReturn(false);
}
@After
@@ -1031,6 +1032,32 @@
BLUETOOTH_DEVICES.remove(scoDevice);
}
+ @Test
+ @SmallTest
+ public void verifyRouteReinitializedAfterCallEnd() {
+ when(mFeatureFlags.resolveActiveBtRoutingAndBtTimingIssue()).thenReturn(true);
+ mController.initialize();
+ mController.setActive(true);
+
+ // Switch to speaker
+ mController.sendMessageWithSessionInfo(SPEAKER_ON);
+ CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_SPEAKER,
+ CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER, null,
+ new HashSet<>());
+ verify(mCallsManager, timeout(TEST_TIMEOUT)).onCallAudioStateChanged(
+ any(CallAudioState.class), eq(expectedState));
+
+ // Verify that call audio route is reinitialized to default (in this case, earpiece) when
+ // call audio focus is lost.
+ mController.sendMessageWithSessionInfo(SWITCH_FOCUS, NO_FOCUS, 0);
+ mController.sendMessageWithSessionInfo(SPEAKER_OFF);
+ expectedState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE,
+ CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER, null,
+ new HashSet<>());
+ verify(mCallsManager, timeout(TEST_TIMEOUT)).onCallAudioStateChanged(
+ any(CallAudioState.class), eq(expectedState));
+ }
+
private void verifyConnectBluetoothDevice(int audioType) {
mController.initialize();
mController.setActive(true);
diff --git a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
index 37221d8..1432834 100644
--- a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
@@ -32,6 +32,7 @@
import android.annotation.RequiresPermission;
import android.app.AppOpsManager;
import android.app.NotificationManager;
+import android.app.StatsManager;
import android.app.StatusBarManager;
import android.app.UiModeManager;
import android.app.role.RoleManager;
@@ -258,6 +259,8 @@
return mAccessibilityManager;
case Context.BLOCKED_NUMBERS_SERVICE:
return mBlockedNumbersManager;
+ case Context.STATS_MANAGER_SERVICE:
+ return mStatsManager;
default:
return null;
}
@@ -303,6 +306,8 @@
return Context.BLOCKED_NUMBERS_SERVICE;
} else if (svcClass == AppOpsManager.class) {
return Context.APP_OPS_SERVICE;
+ } else if (svcClass == StatsManager.class) {
+ return Context.STATS_MANAGER_SERVICE;
}
throw new UnsupportedOperationException(svcClass.getName());
}
@@ -644,6 +649,7 @@
private final PermissionInfo mPermissionInfo = mock(PermissionInfo.class);
private final SensorPrivacyManager mSensorPrivacyManager = mock(SensorPrivacyManager.class);
private final List<BroadcastReceiver> mBroadcastReceivers = new ArrayList<>();
+ private final StatsManager mStatsManager = mock(StatsManager.class);
private TelecomManager mTelecomManager = mock(TelecomManager.class);
private BlockedNumbersManager mBlockedNumbersManager = mock(BlockedNumbersManager.class);
diff --git a/tests/src/com/android/server/telecom/tests/TelecomMetricsControllerTest.java b/tests/src/com/android/server/telecom/tests/TelecomMetricsControllerTest.java
index e2ab8d6..4d494f3 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomMetricsControllerTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomMetricsControllerTest.java
@@ -21,8 +21,11 @@
import static com.android.server.telecom.TelecomStatsLog.TELECOM_ERROR_STATS;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.app.StatsManager;
@@ -119,18 +122,27 @@
}
@Test
- public void testRegisterAtomIsSameInstance() {
+ public void testRegisterAtom() {
+ StatsManager statsManager = mContext.getSystemService(StatsManager.class);
ApiStats stats = mock(ApiStats.class);
mTelecomMetricsController.registerAtom(TELECOM_API_STATS, stats);
+ verify(statsManager, times(1)).setPullAtomCallback(eq(TELECOM_API_STATS), anyObject(),
+ anyObject(), eq(mTelecomMetricsController));
assertThat(mTelecomMetricsController.getStats().get(TELECOM_API_STATS))
.isSameInstanceAs(stats);
}
@Test
public void testDestroy() {
+ StatsManager statsManager = mContext.getSystemService(StatsManager.class);
mTelecomMetricsController.destroy();
+
+ verify(statsManager, times(1)).clearPullAtomCallback(eq(CALL_AUDIO_ROUTE_STATS));
+ verify(statsManager, times(1)).clearPullAtomCallback(eq(CALL_STATS));
+ verify(statsManager, times(1)).clearPullAtomCallback(eq(TELECOM_API_STATS));
+ verify(statsManager, times(1)).clearPullAtomCallback(eq(TELECOM_ERROR_STATS));
assertThat(mTelecomMetricsController.getStats()).isEmpty();
}