DO NOT MERGE ANYWHERE

Add ability to set supported audio routes on phone accounts and connection.

The set audio routes are used by Telecom to restrict where the audio may
be routed to. For example, an account can specify that calls may not be
routed over bluetooth headsets, which will prevent a new call from being
routed to this source.

Bug: 25485578
Change-Id: Ia1ca665e9ae8852a2538ab7cbeb3a73217d9b03b
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 6511705..eab13afe 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -253,6 +253,7 @@
         private final PhoneAccountHandle mAccountHandle;
         private final int mCallCapabilities;
         private final int mCallProperties;
+        private final int mSupportedAudioRoutes;
         private final DisconnectCause mDisconnectCause;
         private final long mConnectTimeMillis;
         private final GatewayInfo mGatewayInfo;
@@ -448,6 +449,15 @@
         }
 
         /**
+         * @return a bitmask of the audio routes available for the call.
+         *
+         * @hide
+         */
+        public int getSupportedAudioRoutes() {
+            return mSupportedAudioRoutes;
+        }
+
+        /**
          * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
          * by {@link android.telecom.DisconnectCause}.
          */
@@ -513,6 +523,7 @@
                         Objects.equals(mAccountHandle, d.mAccountHandle) &&
                         Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
                         Objects.equals(mCallProperties, d.mCallProperties) &&
+                        Objects.equals(mSupportedAudioRoutes, d.mSupportedAudioRoutes) &&
                         Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
                         Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
                         Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
@@ -534,6 +545,7 @@
                     Objects.hashCode(mAccountHandle) +
                     Objects.hashCode(mCallCapabilities) +
                     Objects.hashCode(mCallProperties) +
+                    Objects.hashCode(mSupportedAudioRoutes) +
                     Objects.hashCode(mDisconnectCause) +
                     Objects.hashCode(mConnectTimeMillis) +
                     Objects.hashCode(mGatewayInfo) +
@@ -552,6 +564,7 @@
                 PhoneAccountHandle accountHandle,
                 int capabilities,
                 int properties,
+                int audioRoutes,
                 DisconnectCause disconnectCause,
                 long connectTimeMillis,
                 GatewayInfo gatewayInfo,
@@ -566,6 +579,7 @@
             mAccountHandle = accountHandle;
             mCallCapabilities = capabilities;
             mCallProperties = properties;
+            mSupportedAudioRoutes = audioRoutes;
             mDisconnectCause = disconnectCause;
             mConnectTimeMillis = connectTimeMillis;
             mGatewayInfo = gatewayInfo;
@@ -1008,6 +1022,7 @@
                 parcelableCall.getAccountHandle(),
                 parcelableCall.getCapabilities(),
                 parcelableCall.getProperties(),
+                parcelableCall.getSupportedAudioRoutes(),
                 parcelableCall.getDisconnectCause(),
                 parcelableCall.getConnectTimeMillis(),
                 parcelableCall.getGatewayInfo(),
diff --git a/telecomm/java/android/telecom/CallAudioState.java b/telecomm/java/android/telecom/CallAudioState.java
index 2b16722..f601d8b 100644
--- a/telecomm/java/android/telecom/CallAudioState.java
+++ b/telecomm/java/android/telecom/CallAudioState.java
@@ -44,8 +44,12 @@
      */
     public static final int ROUTE_WIRED_OR_EARPIECE = ROUTE_EARPIECE | ROUTE_WIRED_HEADSET;
 
-    /** Bit mask of all possible audio routes. */
-    private static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
+    /**
+     * Bit mask of all possible audio routes.
+     *
+     * @hide
+     **/
+    public static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
             ROUTE_SPEAKER;
 
     private final boolean isMuted;
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 430760a..a44b79c 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -416,6 +416,7 @@
         public void onRingbackRequested(Connection c, boolean ringback) {}
         public void onDestroyed(Connection c) {}
         public void onConnectionCapabilitiesChanged(Connection c, int capabilities) {}
+        public void onSupportedAudioRoutesChanged(Connection c, int supportedAudioRoutes) {}
         public void onVideoProviderChanged(
                 Connection c, VideoProvider videoProvider) {}
         public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {}
@@ -1082,6 +1083,7 @@
     private int mCallerDisplayNamePresentation;
     private boolean mRingbackRequested = false;
     private int mConnectionCapabilities;
+    private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
     private VideoProvider mVideoProvider;
     private boolean mAudioModeIsVoip;
     private long mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED;
@@ -1306,6 +1308,15 @@
     }
 
     /**
+     * Returns the connection's supported audio routes.
+     *
+     * @hide
+     */
+    public final int getSupportedAudioRoutes() {
+        return mSupportedAudioRoutes;
+    }
+
+    /**
      * Sets the value of the {@link #getAddress()} property.
      *
      * @param address The new address.
@@ -1502,6 +1513,22 @@
     }
 
     /**
+     * Sets the supported audio routes.
+     *
+     * @param supportedAudioRoutes the supported audio routes as a bitmask.
+     *                             See {@link CallAudioState}
+     * @hide
+     */
+    public final void setSupportedAudioRoutes(int supportedAudioRoutes) {
+        if (mSupportedAudioRoutes != supportedAudioRoutes) {
+            mSupportedAudioRoutes = supportedAudioRoutes;
+            for (Listener l : mListeners) {
+                l.onSupportedAudioRoutesChanged(this, mSupportedAudioRoutes);
+            }
+        }
+    }
+
+    /**
      * Tears down the Connection object.
      */
     public final void destroy() {
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 4e330bdb..d35bac0 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -660,6 +660,7 @@
                         request.getAccountHandle(),
                         connection.getState(),
                         connection.getConnectionCapabilities(),
+                        connection.getSupportedAudioRoutes(),
                         connection.getAddress(),
                         connection.getAddressPresentation(),
                         connection.getCallerDisplayName(),
@@ -997,6 +998,7 @@
                     phoneAccountHandle,
                     connection.getState(),
                     connection.getConnectionCapabilities(),
+                    connection.getSupportedAudioRoutes(),
                     connection.getAddress(),
                     connection.getAddressPresentation(),
                     connection.getCallerDisplayName(),
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index 8cf4aeb..599c210 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -39,6 +39,7 @@
     private final List<String> mCannedSmsResponses;
     private final int mCapabilities;
     private final int mProperties;
+    private final int mSupportedAudioRoutes;
     private final long mConnectTimeMillis;
     private final Uri mHandle;
     private final int mHandlePresentation;
@@ -64,6 +65,7 @@
             List<String> cannedSmsResponses,
             int capabilities,
             int properties,
+            int supportedAudioRoutes,
             long connectTimeMillis,
             Uri handle,
             int handlePresentation,
@@ -86,6 +88,7 @@
         mCannedSmsResponses = cannedSmsResponses;
         mCapabilities = capabilities;
         mProperties = properties;
+        mSupportedAudioRoutes = supportedAudioRoutes;
         mConnectTimeMillis = connectTimeMillis;
         mHandle = handle;
         mHandlePresentation = handlePresentation;
@@ -137,6 +140,11 @@
     /** Bitmask of properties of the call. */
     public int getProperties() { return mProperties; }
 
+    /** Bitmask of supported routes of the call */
+    public int getSupportedAudioRoutes() {
+        return mSupportedAudioRoutes;
+    }
+
     /** The time that the call switched to the active state. */
     public long getConnectTimeMillis() {
         return mConnectTimeMillis;
@@ -291,6 +299,7 @@
             source.readList(conferenceableCallIds, classLoader);
             Bundle intentExtras = source.readBundle(classLoader);
             Bundle extras = source.readBundle(classLoader);
+            int supportedAudioRoutes = source.readInt();
             return new ParcelableCall(
                     id,
                     state,
@@ -298,6 +307,7 @@
                     cannedSmsResponses,
                     capabilities,
                     properties,
+                    supportedAudioRoutes,
                     connectTimeMillis,
                     handle,
                     handlePresentation,
@@ -354,6 +364,7 @@
         destination.writeList(mConferenceableCallIds);
         destination.writeBundle(mIntentExtras);
         destination.writeBundle(mExtras);
+        destination.writeInt(mSupportedAudioRoutes);
     }
 
     @Override
diff --git a/telecomm/java/android/telecom/ParcelableConnection.java b/telecomm/java/android/telecom/ParcelableConnection.java
index fe0a4d8..3ce9176 100644
--- a/telecomm/java/android/telecom/ParcelableConnection.java
+++ b/telecomm/java/android/telecom/ParcelableConnection.java
@@ -36,6 +36,7 @@
     private final PhoneAccountHandle mPhoneAccount;
     private final int mState;
     private final int mConnectionCapabilities;
+    private final int mSupportedAudioRoutes;
     private final Uri mAddress;
     private final int mAddressPresentation;
     private final String mCallerDisplayName;
@@ -55,6 +56,7 @@
             PhoneAccountHandle phoneAccount,
             int state,
             int capabilities,
+            int supportedAudioRoutes,
             Uri address,
             int addressPresentation,
             String callerDisplayName,
@@ -71,6 +73,7 @@
         mPhoneAccount = phoneAccount;
         mState = state;
         mConnectionCapabilities = capabilities;
+        mSupportedAudioRoutes = supportedAudioRoutes;
         mAddress = address;
         mAddressPresentation = addressPresentation;
         mCallerDisplayName = callerDisplayName;
@@ -99,6 +102,10 @@
         return mConnectionCapabilities;
     }
 
+    public int getSupportedAudioRoutes() {
+        return mSupportedAudioRoutes;
+    }
+
     public Uri getHandle() {
         return mAddress;
     }
@@ -189,11 +196,13 @@
             List<String> conferenceableConnectionIds = new ArrayList<>();
             source.readStringList(conferenceableConnectionIds);
             Bundle extras = source.readBundle(classLoader);
+            int supportedAudioRoutes = source.readInt();
 
             return new ParcelableConnection(
                     phoneAccount,
                     state,
                     capabilities,
+                    supportedAudioRoutes,
                     address,
                     addressPresentation,
                     callerDisplayName,
@@ -241,5 +250,6 @@
         destination.writeParcelable(mDisconnectCause, 0);
         destination.writeStringList(mConferenceableConnectionIds);
         destination.writeBundle(mExtras);
+        destination.writeInt(mSupportedAudioRoutes);
     }
 }
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index b64043c..e7f5e3c 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -17,15 +17,6 @@
 package android.telecom;
 
 import android.annotation.SystemApi;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.Resources.NotFoundException;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Parcel;
@@ -36,7 +27,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.MissingResourceException;
 
 /**
  * Represents a distinct method to place or receive a phone call. Apps which can place calls and
@@ -167,6 +157,7 @@
     private final CharSequence mLabel;
     private final CharSequence mShortDescription;
     private final List<String> mSupportedUriSchemes;
+    private final int mSupportedAudioRoutes;
     private final Icon mIcon;
     private boolean mIsEnabled;
 
@@ -174,10 +165,12 @@
      * Helper class for creating a {@link PhoneAccount}.
      */
     public static class Builder {
+
         private PhoneAccountHandle mAccountHandle;
         private Uri mAddress;
         private Uri mSubscriptionAddress;
         private int mCapabilities;
+        private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
         private int mHighlightColor = NO_HIGHLIGHT_COLOR;
         private CharSequence mLabel;
         private CharSequence mShortDescription;
@@ -210,6 +203,7 @@
             mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
             mIcon = phoneAccount.getIcon();
             mIsEnabled = phoneAccount.isEnabled();
+            mSupportedAudioRoutes = phoneAccount.getSupportedAudioRoutes();
         }
 
         /**
@@ -320,6 +314,18 @@
         }
 
         /**
+         * Sets the audio routes supported by this {@link PhoneAccount}.
+         *
+         * @param routes bit mask of available routes.
+         * @return The builder.
+         * @hide
+         */
+        public Builder setSupportedAudioRoutes(int routes) {
+            mSupportedAudioRoutes = routes;
+            return this;
+        }
+
+        /**
          * Creates an instance of a {@link PhoneAccount} based on the current builder settings.
          *
          * @return The {@link PhoneAccount}.
@@ -340,6 +346,7 @@
                     mLabel,
                     mShortDescription,
                     mSupportedUriSchemes,
+                    mSupportedAudioRoutes,
                     mIsEnabled);
         }
     }
@@ -354,6 +361,7 @@
             CharSequence label,
             CharSequence shortDescription,
             List<String> supportedUriSchemes,
+            int supportedAudioRoutes,
             boolean isEnabled) {
         mAccountHandle = account;
         mAddress = address;
@@ -364,6 +372,7 @@
         mLabel = label;
         mShortDescription = shortDescription;
         mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
+        mSupportedAudioRoutes = supportedAudioRoutes;
         mIsEnabled = isEnabled;
     }
 
@@ -463,6 +472,15 @@
     }
 
     /**
+     * The audio routes supported by this {@code PhoneAccount}.
+     *
+     * @hide
+     */
+    public int getSupportedAudioRoutes() {
+        return mSupportedAudioRoutes;
+    }
+
+    /**
      * The icon to represent this {@code PhoneAccount}.
      *
      * @return The icon.
@@ -561,6 +579,7 @@
             mIcon.writeToParcel(out, flags);
         }
         out.writeByte((byte) (mIsEnabled ? 1 : 0));
+        out.writeInt(mSupportedAudioRoutes);
     }
 
     public static final Creator<PhoneAccount> CREATOR
@@ -603,6 +622,7 @@
             mIcon = null;
         }
         mIsEnabled = in.readByte() == 1;
+        mSupportedAudioRoutes = in.readInt();
     }
 
     @Override
@@ -613,6 +633,8 @@
                 .append(mAccountHandle)
                 .append(" Capabilities: ")
                 .append(mCapabilities)
+                .append(" Audio Routes: ")
+                .append(mSupportedAudioRoutes)
                 .append(" Schemes: ");
         for (String scheme : mSupportedUriSchemes) {
             sb.append(scheme)