Start handling bluetooth call quality signals
pop a notification for when voice is choppy

Bug: 174759512
Test: verified with telecom testapp
Change-Id: I8b6b776993fd25524823a5cdc4c12fec20142937
Merged-In: I8b6b776993fd25524823a5cdc4c12fec20142937
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 83a5673..1613ca8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2172,4 +2172,12 @@
     <string name="carrier_provisioning">Carrier Provisioning Info</string>
     <!-- Trigger Carrier Provisioning [CHAR LIMIT=NONE] -->
     <string name="trigger_carrier_provisioning">Trigger Carrier Provisioning</string>
+
+    <!-- details of the message popped up when there is
+    bad call quality caused by bluetooth connection-->
+    <string name="call_quality_notification_bluetooth_details">
+        Suggestion: Improve Bluetooth connectivity</string>
+    <!-- name of the notification that pops up during
+    a phone call when there is bad call quality -->
+    <string name="call_quality_notification_name">Call Quality Notification</string>
 </resources>
diff --git a/src/com/android/services/telephony/CallQualityManager.java b/src/com/android/services/telephony/CallQualityManager.java
new file mode 100644
index 0000000..01b5bae
--- /dev/null
+++ b/src/com/android/services/telephony/CallQualityManager.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2020 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.services.telephony;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.telecom.BluetoothCallQualityReport;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.phone.R;
+
+/**
+ * class to handle call quality events that are received by telecom and telephony
+ */
+public class CallQualityManager {
+    private static final String TAG = CallQualityManager.class.getCanonicalName();
+    private static final String CALL_QUALITY_REPORT_CHANNEL = "call_quality_report_channel";
+
+    /** notification ids */
+    public static final int BLUETOOTH_CHOPPY_VOICE_NOTIFICATION_ID = 700;
+
+    public static final String CALL_QUALITY_CHANNEL_ID = "CallQualityNotification";
+
+    private final Context mContext;
+    private final NotificationChannel mNotificationChannel;
+    private final NotificationManager mNotificationManager;
+
+    public CallQualityManager(Context context) {
+        mContext = context;
+        mNotificationChannel = new NotificationChannel(CALL_QUALITY_CHANNEL_ID,
+                mContext.getString(R.string.call_quality_notification_name),
+                NotificationManager.IMPORTANCE_HIGH);
+        mNotificationManager = (NotificationManager)
+                mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+        mNotificationManager.createNotificationChannel(mNotificationChannel);
+    }
+
+    /**
+     * method that is called whenever a
+     * {@code BluetoothCallQualityReport.EVENT_SEND_BLUETOOTH_CALL_QUALITY_REPORT} is received
+     * @param extras Bundle that includes serialized {@code BluetoothCallQualityReport} parcelable
+     */
+    @VisibleForTesting
+    public void onBluetoothCallQualityReported(Bundle extras) {
+        if (extras == null) {
+            Log.d(TAG, "onBluetoothCallQualityReported: no extras provided");
+        }
+
+        BluetoothCallQualityReport callQualityReport = extras.getParcelable(
+                BluetoothCallQualityReport.EXTRA_BLUETOOTH_CALL_QUALITY_REPORT);
+
+        if (callQualityReport.isChoppyVoice()) {
+            onChoppyVoice();
+        }
+        // TODO: once other signals are also sent, we will add more actions here
+    }
+
+    /**
+     * method to post a notification to user suggesting ways to improve call quality in case of
+     * bluetooth choppy voice
+     */
+    @VisibleForTesting
+    public void onChoppyVoice() {
+        String title = "Call Quality Improvement";
+        //TODO: update call_quality_bluetooth_enhancement_suggestion with below before submitting:
+//        "Voice is not being transmitted properly via your bluetooth device."
+//                + "To improve, try:\n"
+//                + "1. moving your phone closer to your bluetooth device\n"
+//                + "2. using a different bluetooth device, or your phone's speaker\n";
+        popUpNotification(title,
+                mContext.getText(R.string.call_quality_notification_bluetooth_details));
+    }
+
+    private void popUpNotification(String title, CharSequence details) {
+        int iconId = android.R.drawable.stat_notify_error;
+
+        Notification notification = new Notification.Builder(mContext)
+                .setSmallIcon(iconId)
+                .setWhen(System.currentTimeMillis())
+                .setAutoCancel(true)
+                .setContentTitle(title)
+                .setContentText(details)
+                .setStyle(new Notification.BigTextStyle().bigText(details))
+                .setOngoing(true)
+                .setChannelId(CALL_QUALITY_CHANNEL_ID)
+                .setOnlyAlertOnce(true)
+                .build();
+
+        mNotificationManager.notify(TAG, BLUETOOTH_CHOPPY_VOICE_NOTIFICATION_ID, notification);
+    }
+}
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 3e7f29c..7baa182 100755
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -28,6 +28,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.PersistableBundle;
+import android.telecom.BluetoothCallQualityReport;
 import android.telecom.CallAudioState;
 import android.telecom.Conference;
 import android.telecom.Connection;
@@ -810,6 +811,8 @@
     private final Set<TelephonyConnectionListener> mTelephonyListeners = Collections.newSetFromMap(
             new ConcurrentHashMap<TelephonyConnectionListener, Boolean>(8, 0.9f, 1));
 
+    private CallQualityManager mCallQualityManager;
+
     protected TelephonyConnection(com.android.internal.telephony.Connection originalConnection,
             String callId, @android.telecom.Call.Details.CallDirection int callDirection) {
         setCallDirection(callDirection);
@@ -819,6 +822,20 @@
         }
     }
 
+    @Override
+    public void onCallEvent(String event, Bundle extras) {
+        switch (event) {
+            case BluetoothCallQualityReport.EVENT_BLUETOOTH_CALL_QUALITY_REPORT:
+                if (mCallQualityManager == null) {
+                    mCallQualityManager = new CallQualityManager(getPhone().getContext());
+                }
+                mCallQualityManager.onBluetoothCallQualityReported(extras);
+                break;
+            default:
+                break;
+        }
+
+    }
     /**
      * Creates a clone of the current {@link TelephonyConnection}.
      *