diff options
8 files changed, 2 insertions, 601 deletions
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java index 5635943cb76e..4aebde536dcf 100644 --- a/core/java/com/android/internal/notification/SystemNotificationChannels.java +++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java @@ -67,7 +67,6 @@ public class SystemNotificationChannels { @Deprecated public static final String SYSTEM_CHANGES_DEPRECATED = "SYSTEM_CHANGES"; public static final String SYSTEM_CHANGES = "SYSTEM_CHANGES_ALERTS"; public static final String ACCESSIBILITY_MAGNIFICATION = "ACCESSIBILITY_MAGNIFICATION"; - public static final String ACCESSIBILITY_HEARING_DEVICE = "ACCESSIBILITY_HEARING_DEVICE"; public static final String ACCESSIBILITY_SECURITY_POLICY = "ACCESSIBILITY_SECURITY_POLICY"; public static final String ABUSIVE_BACKGROUND_APPS = "ABUSIVE_BACKGROUND_APPS"; @@ -204,13 +203,6 @@ public class SystemNotificationChannels { newFeaturePrompt.setBlockable(true); channelsList.add(newFeaturePrompt); - final NotificationChannel accessibilityHearingDeviceChannel = new NotificationChannel( - ACCESSIBILITY_HEARING_DEVICE, - context.getString(R.string.notification_channel_accessibility_hearing_device), - NotificationManager.IMPORTANCE_HIGH); - accessibilityHearingDeviceChannel.setBlockable(true); - channelsList.add(accessibilityHearingDeviceChannel); - final NotificationChannel accessibilitySecurityPolicyChannel = new NotificationChannel( ACCESSIBILITY_SECURITY_POLICY, context.getString(R.string.notification_channel_accessibility_security_policy), diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index ad9e7252c6a8..6313054e47f5 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -881,10 +881,6 @@ <string name="notification_channel_accessibility_magnification">Magnification</string> <!-- Text shown when viewing channel settings for notifications related to accessibility - hearing device. [CHAR_LIMIT=NONE]--> - <string name="notification_channel_accessibility_hearing_device">Hearing device</string> - - <!-- Text shown when viewing channel settings for notifications related to accessibility security policy. [CHAR_LIMIT=NONE]--> <string name="notification_channel_accessibility_security_policy">Accessibility usage</string> @@ -4989,19 +4985,6 @@ <!-- Text used to describe system navigation features, shown within a UI allowing a user to assign system magnification features to the Accessibility button in the navigation bar. --> <string name="accessibility_magnification_chooser_text">Magnification</string> - <!-- Notification title for switching input to the phone's microphone. It will be shown when making a phone call with the hearing device. [CHAR LIMIT=none] --> - <string name="hearing_device_switch_phone_mic_notification_title">Switch to phone mic?</string> - <!-- Notification title for switching input to the hearing device's microphone. It will be shown when making a phone call with the hearing device. [CHAR LIMIT=none] --> - <string name="hearing_device_switch_hearing_mic_notification_title">Switch to hearing aid mic?</string> - <!-- Notification content for switching input to the phone's microphone. It will be shown when making a phone call with the hearing device. [CHAR LIMIT=none] --> - <string name="hearing_device_switch_phone_mic_notification_text">For better sound or if your hearing aid battery is low. This only switches your mic during the call.</string> - <!-- Notification content for switching input to the hearing device's microphone. It will be shown when making a phone call with the hearing device. [CHAR LIMIT=none] --> - <string name="hearing_device_switch_hearing_mic_notification_text">You can use your hearing aid microphone for hands-free calling. This only switches your mic during the call.</string> - <!-- Notification action button. Click it will switch the input between phone's microphone and hearing device's microphone. It will be shown when making a phone call with the hearing device. [CHAR LIMIT=none] --> - <string name="hearing_device_notification_switch_button">Switch</string> - <!-- Notification action button. Click it will open the bluetooth device details page for this hearing device. It will be shown when making a phone call with the hearing device. [CHAR LIMIT=none] --> - <string name="hearing_device_notification_settings_button">Settings</string> - <!-- Text spoken when the current user is switched if accessibility is enabled. [CHAR LIMIT=none] --> <string name="user_switched">Current user <xliff:g id="name" example="Bob">%1$s</xliff:g>.</string> <!-- Message shown when switching to a user [CHAR LIMIT=none] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 9634da6e2c83..a18f923d625b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3839,13 +3839,6 @@ <java-symbol type="string" name="reduce_bright_colors_feature_name" /> <java-symbol type="string" name="one_handed_mode_feature_name" /> - <java-symbol type="string" name="hearing_device_switch_phone_mic_notification_title" /> - <java-symbol type="string" name="hearing_device_switch_hearing_mic_notification_title" /> - <java-symbol type="string" name="hearing_device_switch_phone_mic_notification_text" /> - <java-symbol type="string" name="hearing_device_switch_hearing_mic_notification_text" /> - <java-symbol type="string" name="hearing_device_notification_switch_button" /> - <java-symbol type="string" name="hearing_device_notification_settings_button" /> - <!-- com.android.internal.widget.RecyclerView --> <java-symbol type="id" name="item_touch_helper_previous_elevation"/> <java-symbol type="dimen" name="item_touch_helper_max_drag_scroll_per_frame"/> @@ -4032,7 +4025,6 @@ <java-symbol type="string" name="notification_channel_heavy_weight_app" /> <java-symbol type="string" name="notification_channel_system_changes" /> <java-symbol type="string" name="notification_channel_accessibility_magnification" /> - <java-symbol type="string" name="notification_channel_accessibility_hearing_device" /> <java-symbol type="string" name="notification_channel_accessibility_security_policy" /> <java-symbol type="string" name="notification_channel_display" /> <java-symbol type="string" name="config_defaultAutofillService" /> diff --git a/core/tests/coretests/src/com/android/internal/notification/SystemNotificationChannelsTest.java b/core/tests/coretests/src/com/android/internal/notification/SystemNotificationChannelsTest.java index 2bd3f4df9435..0bf406c970f2 100644 --- a/core/tests/coretests/src/com/android/internal/notification/SystemNotificationChannelsTest.java +++ b/core/tests/coretests/src/com/android/internal/notification/SystemNotificationChannelsTest.java @@ -17,7 +17,6 @@ package com.android.internal.notification; import static com.android.internal.notification.SystemNotificationChannels.ABUSIVE_BACKGROUND_APPS; -import static com.android.internal.notification.SystemNotificationChannels.ACCESSIBILITY_HEARING_DEVICE; import static com.android.internal.notification.SystemNotificationChannels.ACCESSIBILITY_MAGNIFICATION; import static com.android.internal.notification.SystemNotificationChannels.ACCESSIBILITY_SECURITY_POLICY; import static com.android.internal.notification.SystemNotificationChannels.ACCOUNT; @@ -91,8 +90,8 @@ public class SystemNotificationChannelsTest { DEVELOPER_IMPORTANT, UPDATES, NETWORK_STATUS, NETWORK_ALERTS, NETWORK_AVAILABLE, VPN, DEVICE_ADMIN, ALERTS, RETAIL_MODE, USB, FOREGROUND_SERVICE, HEAVY_WEIGHT_APP, SYSTEM_CHANGES, - ACCESSIBILITY_MAGNIFICATION, ACCESSIBILITY_HEARING_DEVICE, - ACCESSIBILITY_SECURITY_POLICY, ABUSIVE_BACKGROUND_APPS); + ACCESSIBILITY_MAGNIFICATION, ACCESSIBILITY_SECURITY_POLICY, + ABUSIVE_BACKGROUND_APPS); } @Test diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto index 3a38152825c9..648990588d29 100644 --- a/proto/src/system_messages.proto +++ b/proto/src/system_messages.proto @@ -420,9 +420,5 @@ message SystemMessage { // Notify the user that accessibility floating menu is hidden. // Package: com.android.systemui NOTE_A11Y_FLOATING_MENU_HIDDEN = 1009; - - // Notify the hearing aid user that input device can be changed to builtin device or hearing device. - // Package: android - NOTE_HEARING_DEVICE_INPUT_SWITCH = 1012; } } diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 6cd1f721d215..37d045bf6422 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -413,7 +413,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub private SparseArray<SurfaceControl> mA11yOverlayLayers = new SparseArray<>(); private final FlashNotificationsController mFlashNotificationsController; - private final HearingDevicePhoneCallNotificationController mHearingDeviceNotificationController; private final UserManagerInternal mUmi; private AccessibilityUserState getCurrentUserStateLocked() { @@ -570,12 +569,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub // TODO(b/255426725): not used on tests mVisibleBgUserIds = null; mInputManager = context.getSystemService(InputManager.class); - if (com.android.settingslib.flags.Flags.hearingDevicesInputRoutingControl()) { - mHearingDeviceNotificationController = new HearingDevicePhoneCallNotificationController( - context); - } else { - mHearingDeviceNotificationController = null; - } init(); } @@ -625,12 +618,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } else { mVisibleBgUserIds = null; } - if (com.android.settingslib.flags.Flags.hearingDevicesInputRoutingControl()) { - mHearingDeviceNotificationController = new HearingDevicePhoneCallNotificationController( - context); - } else { - mHearingDeviceNotificationController = null; - } init(); } @@ -643,11 +630,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub if (enableTalkbackAndMagnifierKeyGestures()) { mInputManager.registerKeyGestureEventHandler(mKeyGestureEventHandler); } - if (com.android.settingslib.flags.Flags.hearingDevicesInputRoutingControl()) { - if (mHearingDeviceNotificationController != null) { - mHearingDeviceNotificationController.startListenForCallState(); - } - } disableAccessibilityMenuToMigrateIfNeeded(); } diff --git a/services/accessibility/java/com/android/server/accessibility/HearingDevicePhoneCallNotificationController.java b/services/accessibility/java/com/android/server/accessibility/HearingDevicePhoneCallNotificationController.java deleted file mode 100644 index d06daf5db127..000000000000 --- a/services/accessibility/java/com/android/server/accessibility/HearingDevicePhoneCallNotificationController.java +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright (C) 2024 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.accessibility; - -import android.Manifest; -import android.annotation.NonNull; -import android.annotation.SuppressLint; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothManager; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothUuid; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.media.AudioDeviceAttributes; -import android.media.AudioDeviceInfo; -import android.media.AudioManager; -import android.media.MediaRecorder; -import android.os.Bundle; -import android.telephony.TelephonyCallback; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.Log; - -import androidx.annotation.VisibleForTesting; - -import com.android.internal.R; -import com.android.internal.messages.nano.SystemMessageProto; -import com.android.internal.notification.SystemNotificationChannels; -import com.android.internal.util.ArrayUtils; - -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.stream.Collectors; - -/** - * A controller class to handle notification for hearing device during phone calls. - */ -public class HearingDevicePhoneCallNotificationController { - - private final TelephonyManager mTelephonyManager; - private final TelephonyCallback mTelephonyListener; - private final Executor mCallbackExecutor; - - public HearingDevicePhoneCallNotificationController(@NonNull Context context) { - mTelephonyListener = new CallStateListener(context); - mTelephonyManager = context.getSystemService(TelephonyManager.class); - mCallbackExecutor = Executors.newSingleThreadExecutor(); - } - - @VisibleForTesting - HearingDevicePhoneCallNotificationController(@NonNull Context context, - TelephonyCallback telephonyCallback) { - mTelephonyListener = telephonyCallback; - mTelephonyManager = context.getSystemService(TelephonyManager.class); - mCallbackExecutor = context.getMainExecutor(); - } - - /** - * Registers a telephony callback to listen for call state changed to handle notification for - * hearing device during phone calls. - */ - public void startListenForCallState() { - mTelephonyManager.registerTelephonyCallback(mCallbackExecutor, mTelephonyListener); - } - - /** - * A telephony callback listener to listen to call state changes and show/dismiss notification - */ - @VisibleForTesting - static class CallStateListener extends TelephonyCallback implements - TelephonyCallback.CallStateListener { - - private static final String TAG = - "HearingDevice_CallStateListener"; - private static final String ACTION_SWITCH_TO_BUILTIN_MIC = - "com.android.server.accessibility.hearingdevice.action.SWITCH_TO_BUILTIN_MIC"; - private static final String ACTION_SWITCH_TO_HEARING_MIC = - "com.android.server.accessibility.hearingdevice.action.SWITCH_TO_HEARING_MIC"; - private static final String ACTION_BLUETOOTH_DEVICE_DETAILS = - "com.android.settings.BLUETOOTH_DEVICE_DETAIL_SETTINGS"; - private static final String KEY_BLUETOOTH_ADDRESS = "device_address"; - private static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args"; - private static final int MICROPHONE_SOURCE_VOICE_COMMUNICATION = - MediaRecorder.AudioSource.VOICE_COMMUNICATION; - private static final AudioDeviceAttributes BUILTIN_MIC = new AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_INPUT, AudioDeviceInfo.TYPE_BUILTIN_MIC, ""); - - private final Context mContext; - private NotificationManager mNotificationManager; - private AudioManager mAudioManager; - private BroadcastReceiver mHearingDeviceActionReceiver; - private BluetoothDevice mHearingDevice; - private boolean mIsNotificationShown = false; - - CallStateListener(@NonNull Context context) { - mContext = context; - } - - @Override - @SuppressLint("AndroidFrameworkRequiresPermission") - public void onCallStateChanged(int state) { - // NotificationManagerService and AudioService are all initialized after - // AccessibilityManagerService. - // Can not get them in constructor. Need to get these services until callback is - // triggered. - mNotificationManager = mContext.getSystemService(NotificationManager.class); - mAudioManager = mContext.getSystemService(AudioManager.class); - if (mNotificationManager == null || mAudioManager == null) { - Log.w(TAG, "NotificationManager or AudioManager is not prepare yet."); - return; - } - - if (state == TelephonyManager.CALL_STATE_IDLE) { - dismissNotificationIfNeeded(); - - if (mHearingDevice != null) { - // reset to its original status - setMicrophonePreferredForCalls(mHearingDevice.isMicrophonePreferredForCalls()); - } - mHearingDevice = null; - } - if (state == TelephonyManager.CALL_STATE_OFFHOOK) { - mHearingDevice = getSupportedInputHearingDeviceInfo( - mAudioManager.getAvailableCommunicationDevices()); - if (mHearingDevice != null) { - showNotificationIfNeeded(); - } - } - } - - private void showNotificationIfNeeded() { - if (mIsNotificationShown) { - return; - } - - showNotification(mHearingDevice.isMicrophonePreferredForCalls()); - mIsNotificationShown = true; - } - - private void dismissNotificationIfNeeded() { - if (!mIsNotificationShown) { - return; - } - - dismissNotification(); - mIsNotificationShown = false; - } - - private void showNotification(boolean useRemoteMicrophone) { - mNotificationManager.notify( - SystemMessageProto.SystemMessage.NOTE_HEARING_DEVICE_INPUT_SWITCH, - createSwitchInputNotification(useRemoteMicrophone)); - registerReceiverIfNeeded(); - } - - private void dismissNotification() { - unregisterReceiverIfNeeded(); - mNotificationManager.cancel( - SystemMessageProto.SystemMessage.NOTE_HEARING_DEVICE_INPUT_SWITCH); - } - - private BluetoothDevice getSupportedInputHearingDeviceInfo(List<AudioDeviceInfo> infoList) { - final BluetoothAdapter bluetoothAdapter = mContext.getSystemService( - BluetoothManager.class).getAdapter(); - if (bluetoothAdapter == null) { - return null; - } - if (!isHapClientSupported()) { - return null; - } - - final Set<String> inputDeviceAddress = Arrays.stream( - mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).map( - AudioDeviceInfo::getAddress).collect(Collectors.toSet()); - - //TODO: b/370812132 - Need to update if TYPE_LEA_HEARING_AID is added - final AudioDeviceInfo hearingDeviceInfo = infoList.stream() - .filter(info -> info.getType() == AudioDeviceInfo.TYPE_BLE_HEADSET) - .filter(info -> inputDeviceAddress.contains(info.getAddress())) - .filter(info -> isHapClientDevice(bluetoothAdapter, info)) - .findAny() - .orElse(null); - - return (hearingDeviceInfo != null) ? bluetoothAdapter.getRemoteDevice( - hearingDeviceInfo.getAddress()) : null; - } - - @VisibleForTesting - boolean isHapClientDevice(BluetoothAdapter bluetoothAdapter, AudioDeviceInfo info) { - BluetoothDevice device = bluetoothAdapter.getRemoteDevice(info.getAddress()); - return ArrayUtils.contains(device.getUuids(), BluetoothUuid.HAS); - } - - @VisibleForTesting - boolean isHapClientSupported() { - return BluetoothAdapter.getDefaultAdapter().getSupportedProfiles().contains( - BluetoothProfile.HAP_CLIENT); - } - - private Notification createSwitchInputNotification(boolean useRemoteMicrophone) { - return new Notification.Builder(mContext, - SystemNotificationChannels.ACCESSIBILITY_HEARING_DEVICE) - .setContentTitle(getSwitchInputTitle(useRemoteMicrophone)) - .setContentText(getSwitchInputMessage(useRemoteMicrophone)) - .setSmallIcon(R.drawable.ic_settings_24dp) - .setColor(mContext.getResources().getColor( - com.android.internal.R.color.system_notification_accent_color)) - .setLocalOnly(true) - .setCategory(Notification.CATEGORY_SYSTEM) - .setContentIntent(createPendingIntent(ACTION_BLUETOOTH_DEVICE_DETAILS)) - .setActions(buildSwitchInputAction(useRemoteMicrophone), - buildOpenSettingsAction()) - .build(); - } - - private Notification.Action buildSwitchInputAction(boolean useRemoteMicrophone) { - return useRemoteMicrophone - ? new Notification.Action.Builder(null, - mContext.getString(R.string.hearing_device_notification_switch_button), - createPendingIntent(ACTION_SWITCH_TO_BUILTIN_MIC)).build() - : new Notification.Action.Builder(null, - mContext.getString(R.string.hearing_device_notification_switch_button), - createPendingIntent(ACTION_SWITCH_TO_HEARING_MIC)).build(); - } - - private Notification.Action buildOpenSettingsAction() { - return new Notification.Action.Builder(null, - mContext.getString(R.string.hearing_device_notification_settings_button), - createPendingIntent(ACTION_BLUETOOTH_DEVICE_DETAILS)).build(); - } - - private PendingIntent createPendingIntent(String action) { - final Intent intent = new Intent(action); - - switch (action) { - case ACTION_SWITCH_TO_BUILTIN_MIC, ACTION_SWITCH_TO_HEARING_MIC -> { - intent.setPackage(mContext.getPackageName()); - return PendingIntent.getBroadcast(mContext, /* requestCode = */ 0, intent, - PendingIntent.FLAG_IMMUTABLE); - } - case ACTION_BLUETOOTH_DEVICE_DETAILS -> { - Bundle bundle = new Bundle(); - bundle.putString(KEY_BLUETOOTH_ADDRESS, mHearingDevice.getAddress()); - intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, bundle); - intent.addFlags( - Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - return PendingIntent.getActivity(mContext, /* requestCode = */ 0, intent, - PendingIntent.FLAG_IMMUTABLE); - } - } - return null; - } - - private void setMicrophonePreferredForCalls(boolean useRemoteMicrophone) { - if (useRemoteMicrophone) { - switchToHearingMic(); - } else { - switchToBuiltinMic(); - } - } - - @SuppressLint("AndroidFrameworkRequiresPermission") - private void switchToBuiltinMic() { - mAudioManager.clearPreferredDevicesForCapturePreset( - MICROPHONE_SOURCE_VOICE_COMMUNICATION); - mAudioManager.setPreferredDeviceForCapturePreset(MICROPHONE_SOURCE_VOICE_COMMUNICATION, - BUILTIN_MIC); - } - - @SuppressLint("AndroidFrameworkRequiresPermission") - private void switchToHearingMic() { - // clear config to let audio manager to determine next priority device. We can assume - // user connects to hearing device here, so next priority device should be hearing - // device. - mAudioManager.clearPreferredDevicesForCapturePreset( - MICROPHONE_SOURCE_VOICE_COMMUNICATION); - } - - private void registerReceiverIfNeeded() { - if (mHearingDeviceActionReceiver != null) { - return; - } - mHearingDeviceActionReceiver = new HearingDeviceActionReceiver(); - final IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(ACTION_SWITCH_TO_BUILTIN_MIC); - intentFilter.addAction(ACTION_SWITCH_TO_HEARING_MIC); - mContext.registerReceiver(mHearingDeviceActionReceiver, intentFilter, - Manifest.permission.MANAGE_ACCESSIBILITY, null, Context.RECEIVER_NOT_EXPORTED); - } - - private void unregisterReceiverIfNeeded() { - if (mHearingDeviceActionReceiver == null) { - return; - } - mContext.unregisterReceiver(mHearingDeviceActionReceiver); - mHearingDeviceActionReceiver = null; - } - - private CharSequence getSwitchInputTitle(boolean useRemoteMicrophone) { - return useRemoteMicrophone - ? mContext.getString( - R.string.hearing_device_switch_phone_mic_notification_title) - : mContext.getString( - R.string.hearing_device_switch_hearing_mic_notification_title); - } - - private CharSequence getSwitchInputMessage(boolean useRemoteMicrophone) { - return useRemoteMicrophone - ? mContext.getString( - R.string.hearing_device_switch_phone_mic_notification_text) - : mContext.getString( - R.string.hearing_device_switch_hearing_mic_notification_text); - } - - private class HearingDeviceActionReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (TextUtils.isEmpty(action)) { - return; - } - - if (ACTION_SWITCH_TO_BUILTIN_MIC.equals(action)) { - switchToBuiltinMic(); - showNotification(/* useRemoteMicrophone= */ false); - } else if (ACTION_SWITCH_TO_HEARING_MIC.equals(action)) { - switchToHearingMic(); - showNotification(/* useRemoteMicrophone= */ true); - } - } - } - } -} diff --git a/services/tests/servicestests/src/com/android/server/accessibility/HearingDevicePhoneCallNotificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/HearingDevicePhoneCallNotificationControllerTest.java deleted file mode 100644 index efea21428937..000000000000 --- a/services/tests/servicestests/src/com/android/server/accessibility/HearingDevicePhoneCallNotificationControllerTest.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2024 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.accessibility; - -import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.Application; -import android.app.Instrumentation; -import android.app.NotificationManager; -import android.bluetooth.BluetoothAdapter; -import android.content.Context; -import android.media.AudioDeviceInfo; -import android.media.AudioDevicePort; -import android.media.AudioManager; -import android.telephony.TelephonyCallback; -import android.telephony.TelephonyManager; - -import androidx.annotation.NonNull; -import androidx.test.core.app.ApplicationProvider; -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.messages.nano.SystemMessageProto; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.Spy; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; - -import java.util.List; -import java.util.concurrent.Executor; - -/** - * Tests for the {@link HearingDevicePhoneCallNotificationController}. - */ -@RunWith(AndroidJUnit4.class) -public class HearingDevicePhoneCallNotificationControllerTest { - @Rule - public MockitoRule mockito = MockitoJUnit.rule(); - - private static final String TEST_ADDRESS = "55:66:77:88:99:AA"; - - private final Application mApplication = ApplicationProvider.getApplicationContext(); - @Spy - private final Context mContext = mApplication.getApplicationContext(); - private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation(); - - @Mock - private TelephonyManager mTelephonyManager; - @Mock - private NotificationManager mNotificationManager; - @Mock - private AudioManager mAudioManager; - private HearingDevicePhoneCallNotificationController mController; - private TestCallStateListener mTestCallStateListener; - - @Before - public void setUp() { - mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(BLUETOOTH_PRIVILEGED); - when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); - when(mContext.getSystemService(NotificationManager.class)).thenReturn(mNotificationManager); - when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager); - - mTestCallStateListener = new TestCallStateListener(mContext); - mController = new HearingDevicePhoneCallNotificationController(mContext, - mTestCallStateListener); - mController.startListenForCallState(); - } - - @Test - public void startListenForCallState_callbackNotNull() { - Mockito.reset(mTelephonyManager); - mController = new HearingDevicePhoneCallNotificationController(mContext); - ArgumentCaptor<TelephonyCallback> listenerCaptor = ArgumentCaptor.forClass( - TelephonyCallback.class); - - mController.startListenForCallState(); - - verify(mTelephonyManager).registerTelephonyCallback(any(Executor.class), - listenerCaptor.capture()); - TelephonyCallback callback = listenerCaptor.getValue(); - assertThat(callback).isNotNull(); - } - - @Test - public void onCallStateChanged_stateOffHook_hapDevice_showNotification() { - AudioDeviceInfo hapDeviceInfo = createAudioDeviceInfo(TEST_ADDRESS, - AudioManager.DEVICE_OUT_BLE_HEADSET); - when(mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).thenReturn( - new AudioDeviceInfo[]{hapDeviceInfo}); - when(mAudioManager.getAvailableCommunicationDevices()).thenReturn(List.of(hapDeviceInfo)); - - mTestCallStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK); - - verify(mNotificationManager).notify( - eq(SystemMessageProto.SystemMessage.NOTE_HEARING_DEVICE_INPUT_SWITCH), any()); - } - - @Test - public void onCallStateChanged_stateOffHook_a2dpDevice_noNotification() { - AudioDeviceInfo a2dpDeviceInfo = createAudioDeviceInfo(TEST_ADDRESS, - AudioManager.DEVICE_OUT_BLUETOOTH_A2DP); - when(mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).thenReturn( - new AudioDeviceInfo[]{a2dpDeviceInfo}); - when(mAudioManager.getAvailableCommunicationDevices()).thenReturn(List.of(a2dpDeviceInfo)); - - mTestCallStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK); - - verify(mNotificationManager, never()).notify( - eq(SystemMessageProto.SystemMessage.NOTE_HEARING_DEVICE_INPUT_SWITCH), any()); - } - - @Test - public void onCallStateChanged_stateOffHookThenIdle_hapDeviceInfo_cancelNotification() { - AudioDeviceInfo hapDeviceInfo = createAudioDeviceInfo(TEST_ADDRESS, - AudioManager.DEVICE_OUT_BLE_HEADSET); - when(mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).thenReturn( - new AudioDeviceInfo[]{hapDeviceInfo}); - when(mAudioManager.getAvailableCommunicationDevices()).thenReturn(List.of(hapDeviceInfo)); - - mTestCallStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK); - mTestCallStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_IDLE); - - verify(mNotificationManager).cancel( - eq(SystemMessageProto.SystemMessage.NOTE_HEARING_DEVICE_INPUT_SWITCH)); - } - - private AudioDeviceInfo createAudioDeviceInfo(String address, int type) { - AudioDevicePort audioDevicePort = mock(AudioDevicePort.class); - doReturn(type).when(audioDevicePort).type(); - doReturn(address).when(audioDevicePort).address(); - doReturn("testDevice").when(audioDevicePort).name(); - - return new AudioDeviceInfo(audioDevicePort); - } - - /** - * For easier testing for CallStateListener, override methods that contain final object. - */ - private static class TestCallStateListener extends - HearingDevicePhoneCallNotificationController.CallStateListener { - - TestCallStateListener(@NonNull Context context) { - super(context); - } - - @Override - boolean isHapClientSupported() { - return true; - } - - @Override - boolean isHapClientDevice(BluetoothAdapter bluetoothAdapter, AudioDeviceInfo info) { - return TEST_ADDRESS.equals(info.getAddress()); - } - } -} |