Merge "Allow callers to synchronously block for shutdown"
diff --git a/api/current.txt b/api/current.txt
index 10edfdc..db0946d7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -35422,6 +35422,7 @@
     field public static final deprecated java.lang.String RADIO_NFC = "nfc";
     field public static final deprecated java.lang.String RADIO_WIFI = "wifi";
     field public static final java.lang.String RINGTONE = "ringtone";
+    field public static final java.lang.String RTT_CALLING_MODE = "rtt_calling_mode";
     field public static final java.lang.String SCREEN_BRIGHTNESS = "screen_brightness";
     field public static final java.lang.String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
     field public static final int SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1; // 0x1
@@ -39250,6 +39251,7 @@
     field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80
     field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
     field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
+    field public static final int PROPERTY_RTT = 1024; // 0x400
     field public static final int PROPERTY_SELF_MANAGED = 256; // 0x100
     field public static final int PROPERTY_WIFI = 8; // 0x8
   }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f4842c6..36dcca6 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3665,18 +3665,15 @@
         public static final Validator TTY_MODE_VALIDATOR = new InclusiveIntegerRangeValidator(0, 3);
 
         /**
-         * User-selected RTT mode
+         * User-selected RTT mode. When on, outgoing and incoming calls will be answered as RTT
+         * calls when supported by the device and carrier. Boolean value.
          * 0 = OFF
-         * 1 = FULL
-         * 2 = VCO
-         * 3 = HCO
-         * Uses the same constants as TTY (e.g. {@link android.telecom.TelecomManager#TTY_MODE_OFF})
-         * @hide
+         * 1 = ON
          */
         public static final String RTT_CALLING_MODE = "rtt_calling_mode";
 
         /** @hide */
-        public static final Validator RTT_CALLING_MODE_VALIDATOR = TTY_MODE_VALIDATOR;
+        public static final Validator RTT_CALLING_MODE_VALIDATOR = sBooleanValidator;
 
         /**
          * Whether the sounds effects (key clicks, lid open ...) are enabled. The value is
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 339c767..ede172c 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3606,6 +3606,21 @@
     }
 
      /**
+     * Indicate Hearing Aid connection state change.
+     * @param device Bluetooth device connected/disconnected
+     * @param state new connection state (BluetoothProfile.STATE_xxx)
+     * {@hide}
+     */
+    public void setHearingAidDeviceConnectionState(BluetoothDevice device, int state) {
+        final IAudioService service = getService();
+        try {
+            service.setHearingAidDeviceConnectionState(device, state);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+     /**
      * Indicate A2DP source or sink connection state change.
      * @param device Bluetooth device connected/disconnected
      * @param state  new connection state (BluetoothProfile.STATE_xxx)
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 6c65223..07b6bbd 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -143,6 +143,8 @@
     void setWiredDeviceConnectionState(int type, int state, String address, String name,
             String caller);
 
+    void setHearingAidDeviceConnectionState(in BluetoothDevice device, int state);
+
     int setBluetoothA2dpDeviceConnectionState(in BluetoothDevice device, int state, int profile);
 
     void handleBluetoothA2dpDeviceConfigChange(in BluetoothDevice device);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 4293d45..503dfe9 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4104,6 +4104,11 @@
         }
     }
 
+    @Override
+    public void setHearingAidDeviceConnectionState(BluetoothDevice device, int state)
+    {
+    }
+
     public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)
     {
         return setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 2341f03..a79f2c9 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -426,8 +426,14 @@
          */
         public static final int PROPERTY_ASSISTED_DIALING_USED = 0x00000200;
 
+        /**
+         * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
+         * {@link RttCall} object that is used to send and receive text.
+         */
+        public static final int PROPERTY_RTT = 0x00000400;
+
         //******************************************************************************************
-        // Next PROPERTY value: 0x00000400
+        // Next PROPERTY value: 0x00000800
         //******************************************************************************************
 
         private final String mTelecomCallId;
@@ -1190,6 +1196,23 @@
                 return null;
             }
         }
+
+        /**
+         * Closes the underlying file descriptors
+         * @hide
+         */
+        public void close() {
+            try {
+                mReceiveStream.close();
+            } catch (IOException e) {
+                // ignore
+            }
+            try {
+                mTransmitStream.close();
+            } catch (IOException e) {
+                // ignore
+            }
+        }
     }
 
     /**
@@ -1665,7 +1688,7 @@
      * @return true if there is a connection, false otherwise.
      */
     public boolean isRttActive() {
-        return mRttCall != null;
+        return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
     }
 
     /**
@@ -1868,7 +1891,8 @@
 
         boolean isRttChanged = false;
         boolean rttModeChanged = false;
-        if (parcelableCall.getParcelableRttCall() != null && parcelableCall.getIsRttCallChanged()) {
+        if (parcelableCall.getIsRttCallChanged()
+                && mDetails.hasProperty(Details.PROPERTY_RTT)) {
             ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
             InputStreamReader receiveStream = new InputStreamReader(
                     new ParcelFileDescriptor.AutoCloseInputStream(
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 50c0803..9a53d8c 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -40,6 +40,8 @@
 import android.util.ArraySet;
 import android.view.Surface;
 
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
@@ -860,18 +862,19 @@
             mFdFromInCall = fromInCall;
             mFdToInCall = toInCall;
             mPipeFromInCall = new InputStreamReader(
-                    new ParcelFileDescriptor.AutoCloseInputStream(fromInCall));
+                    new FileInputStream(fromInCall.getFileDescriptor()));
             mPipeToInCall = new OutputStreamWriter(
-                    new ParcelFileDescriptor.AutoCloseOutputStream(toInCall));
+                    new FileOutputStream(toInCall.getFileDescriptor()));
         }
 
         /**
          * Writes the string {@param input} into the text stream to the UI for this RTT call. Since
          * RTT transmits text in real-time, this method should be called as often as text snippets
          * are received from the remote user, even if it is only one character.
-         *
+         * <p>
          * This method is not thread-safe -- calling it from multiple threads simultaneously may
          * lead to interleaved text.
+         *
          * @param input The message to send to the in-call app.
          */
         public void write(String input) throws IOException {
@@ -884,9 +887,10 @@
          * Reads a string from the in-call app, blocking if there is no data available. Returns
          * {@code null} if the RTT conversation has been terminated and there is no further data
          * to read.
-         *
+         * <p>
          * This method is not thread-safe -- calling it from multiple threads simultaneously may
          * lead to interleaved text.
+         *
          * @return A string containing text entered by the user, or {@code null} if the
          * conversation has been terminated or if there was an error while reading.
          */
@@ -901,6 +905,7 @@
         /**
          * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
          * be read.
+         *
          * @return A string containing text entered by the user, or {@code null} if the user has
          * not entered any new text yet.
          */
@@ -2620,7 +2625,6 @@
      * {@link #onStartRtt(RttTextStream)} has succeeded.
      */
     public final void sendRttInitiationSuccess() {
-        setRttProperty();
         mListeners.forEach((l) -> l.onRttInitiationSuccess(Connection.this));
     }
 
@@ -2632,7 +2636,6 @@
      *               exception of {@link RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
      */
     public final void sendRttInitiationFailure(int reason) {
-        unsetRttProperty();
         mListeners.forEach((l) -> l.onRttInitiationFailure(Connection.this, reason));
     }
 
@@ -2641,7 +2644,6 @@
      * side of the coll.
      */
     public final void sendRttSessionRemotelyTerminated() {
-        unsetRttProperty();
         mListeners.forEach((l) -> l.onRttSessionRemotelyTerminated(Connection.this));
     }
 
@@ -2941,22 +2943,6 @@
      */
     public void handleRttUpgradeResponse(@Nullable RttTextStream rttTextStream) {}
 
-    /**
-     * Internal method to set {@link #PROPERTY_IS_RTT}.
-     * @hide
-     */
-    void setRttProperty() {
-        setConnectionProperties(getConnectionProperties() | PROPERTY_IS_RTT);
-    }
-
-    /**
-     * Internal method to un-set {@link #PROPERTY_IS_RTT}.
-     * @hide
-     */
-    void unsetRttProperty() {
-        setConnectionProperties(getConnectionProperties() & (~PROPERTY_IS_RTT));
-    }
-
     static String toLogSafePhoneNumber(String number) {
         // For unknown number, log empty string.
         if (number == null) {
diff --git a/telecomm/java/android/telecom/ConnectionRequest.java b/telecomm/java/android/telecom/ConnectionRequest.java
index 658b473..b6e6b0e 100644
--- a/telecomm/java/android/telecom/ConnectionRequest.java
+++ b/telecomm/java/android/telecom/ConnectionRequest.java
@@ -143,6 +143,8 @@
     private final boolean mShouldShowIncomingCallUi;
     private final ParcelFileDescriptor mRttPipeToInCall;
     private final ParcelFileDescriptor mRttPipeFromInCall;
+    // Cached return value of getRttTextStream -- we don't want to wrap it more than once.
+    private Connection.RttTextStream mRttTextStream;
 
     /**
      * @param accountHandle The accountHandle which should be used to place the call.
@@ -312,7 +314,10 @@
      */
     public Connection.RttTextStream getRttTextStream() {
         if (isRequestingRtt()) {
-            return new Connection.RttTextStream(mRttPipeToInCall, mRttPipeFromInCall);
+            if (mRttTextStream == null) {
+                mRttTextStream = new Connection.RttTextStream(mRttPipeToInCall, mRttPipeFromInCall);
+            }
+            return mRttTextStream;
         } else {
             return null;
         }
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 46d6b42..593e12b 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -143,6 +143,7 @@
     private static final String SESSION_HANDOVER_COMPLETE = "CS.hC";
     private static final String SESSION_EXTRAS_CHANGED = "CS.oEC";
     private static final String SESSION_START_RTT = "CS.+RTT";
+    private static final String SESSION_UPDATE_RTT_PIPES = "CS.uRTT";
     private static final String SESSION_STOP_RTT = "CS.-RTT";
     private static final String SESSION_RTT_UPGRADE_RESPONSE = "CS.rTRUR";
     private static final String SESSION_HANDOVER_FAILED = "CS.haF";
@@ -1864,7 +1865,6 @@
         Log.d(this, "stopRtt(%s)", callId);
         if (mConnectionById.containsKey(callId)) {
             findConnectionForAction(callId, "stopRtt").onStopRtt();
-            findConnectionForAction(callId, "stopRtt").unsetRttProperty();
         } else if (mConferenceById.containsKey(callId)) {
             Log.w(this, "stopRtt called on a conference.");
         }