Merge "[LayoutInflater] Use precompiled layouts if available"
diff --git a/api/current.txt b/api/current.txt
index aaacd68..b7cef9e 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -43380,6 +43380,7 @@
     method public int compareTo(android.telephony.emergency.EmergencyNumber);
     method public int describeContents();
     method public java.lang.String getCountryIso();
+    method public int getEmergencyCallRouting();
     method public int getEmergencyNumberSourceBitmask();
     method public java.util.List<java.lang.Integer> getEmergencyNumberSources();
     method public java.util.List<java.lang.Integer> getEmergencyServiceCategories();
@@ -43390,6 +43391,9 @@
     method public boolean isInEmergencyServiceCategories(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.emergency.EmergencyNumber> CREATOR;
+    field public static final int EMERGENCY_CALL_ROUTING_EMERGENCY = 1; // 0x1
+    field public static final int EMERGENCY_CALL_ROUTING_NORMAL = 2; // 0x2
+    field public static final int EMERGENCY_CALL_ROUTING_UNKNOWN = 0; // 0x0
     field public static final int EMERGENCY_NUMBER_SOURCE_DATABASE = 16; // 0x10
     field public static final int EMERGENCY_NUMBER_SOURCE_DEFAULT = 8; // 0x8
     field public static final int EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG = 4; // 0x4
diff --git a/api/system-current.txt b/api/system-current.txt
index 1bf6cf9..9cdc682 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6040,6 +6040,7 @@
     method public android.os.Bundle getCallExtras();
     method public int getCallType();
     method public static int getCallTypeFromVideoState(int);
+    method public int getEmergencyCallRouting();
     method public int getEmergencyServiceCategories();
     method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
     method public int getRestrictCause();
@@ -6053,6 +6054,7 @@
     method public void setCallExtraBoolean(java.lang.String, boolean);
     method public void setCallExtraInt(java.lang.String, int);
     method public void setCallRestrictCause(int);
+    method public void setEmergencyCallRouting(int);
     method public void setEmergencyServiceCategories(int);
     method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
     method public void updateCallType(android.telephony.ims.ImsCallProfile);
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
index fe062d5..a94b163 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -29,6 +29,7 @@
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -198,21 +199,53 @@
         EMERGENCY_NUMBER_SOURCE_SET.add(EMERGENCY_NUMBER_SOURCE_DEFAULT);
     }
 
+    /**
+     * Indicated the framework does not know whether an emergency call should be placed using
+     * emergency or normal call routing. This means the underlying radio or IMS implementation is
+     * free to determine for itself how to route the call.
+     */
+    public static final int EMERGENCY_CALL_ROUTING_UNKNOWN = 0;
+    /**
+     * Indicates the radio or IMS implementation must handle the call through emergency routing.
+     */
+    public static final int EMERGENCY_CALL_ROUTING_EMERGENCY = 1;
+    /**
+     * Indicates the radio or IMS implementation must handle the call through normal call routing.
+     */
+    public static final int EMERGENCY_CALL_ROUTING_NORMAL = 2;
+
+    /**
+     * The routing to tell how to handle the call for the corresponding emergency number.
+     *
+     * @hide
+     */
+    @IntDef(flag = false, prefix = { "EMERGENCY_CALL_ROUTING_" }, value = {
+            EMERGENCY_CALL_ROUTING_UNKNOWN,
+            EMERGENCY_CALL_ROUTING_EMERGENCY,
+            EMERGENCY_CALL_ROUTING_NORMAL
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface EmergencyCallRouting {}
+
+
     private final String mNumber;
     private final String mCountryIso;
     private final String mMnc;
     private final int mEmergencyServiceCategoryBitmask;
     private final int mEmergencyNumberSourceBitmask;
+    private final int mEmergencyCallRouting;
 
     /** @hide */
-    public EmergencyNumber(@NonNull String number, @NonNull String countryIso,
-                           @NonNull String mnc, int emergencyServiceCategories,
-                           int emergencyNumberSources) {
+    public EmergencyNumber(@NonNull String number, @NonNull String countryIso, @NonNull String mnc,
+                           @EmergencyServiceCategories int emergencyServiceCategories,
+                           @EmergencyNumberSources int emergencyNumberSources,
+                           @EmergencyCallRouting int emergencyCallRouting) {
         this.mNumber = number;
         this.mCountryIso = countryIso;
         this.mMnc = mnc;
         this.mEmergencyServiceCategoryBitmask = emergencyServiceCategories;
         this.mEmergencyNumberSourceBitmask = emergencyNumberSources;
+        this.mEmergencyCallRouting = emergencyCallRouting;
     }
 
     /** @hide */
@@ -222,8 +255,33 @@
         mMnc = source.readString();
         mEmergencyServiceCategoryBitmask = source.readInt();
         mEmergencyNumberSourceBitmask = source.readInt();
+        mEmergencyCallRouting = source.readInt();
     }
 
+    @Override
+    /** @hide */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mNumber);
+        dest.writeString(mCountryIso);
+        dest.writeString(mMnc);
+        dest.writeInt(mEmergencyServiceCategoryBitmask);
+        dest.writeInt(mEmergencyNumberSourceBitmask);
+        dest.writeInt(mEmergencyCallRouting);
+    }
+
+    public static final Parcelable.Creator<EmergencyNumber> CREATOR =
+            new Parcelable.Creator<EmergencyNumber>() {
+                @Override
+                public EmergencyNumber createFromParcel(Parcel in) {
+                    return new EmergencyNumber(in);
+                }
+
+                @Override
+                public EmergencyNumber[] newArray(int size) {
+                    return new EmergencyNumber[size];
+                }
+            };
+
     /**
      * Get the dialing number of the emergency number.
      *
@@ -352,14 +410,17 @@
         return (mEmergencyNumberSourceBitmask & sources) == sources;
     }
 
-    @Override
-    /** @hide */
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(mNumber);
-        dest.writeString(mCountryIso);
-        dest.writeString(mMnc);
-        dest.writeInt(mEmergencyServiceCategoryBitmask);
-        dest.writeInt(mEmergencyNumberSourceBitmask);
+    /**
+     * Returns the emergency call routing information.
+     *
+     * <p>Some regions require some emergency numbers which are not routed using typical emergency
+     * call processing, but are instead placed as regular phone calls. The emergency call routing
+     * field provides information about how an emergency call will be routed when it is placed.
+     *
+     * @return the emergency call routing requirement
+     */
+    public @EmergencyCallRouting int getEmergencyCallRouting() {
+        return mEmergencyCallRouting;
     }
 
     @Override
@@ -373,7 +434,8 @@
         return "EmergencyNumber:" + "Number-" + mNumber + "|CountryIso-" + mCountryIso
                 + "|Mnc-" + mMnc
                 + "|ServiceCategories-" + Integer.toBinaryString(mEmergencyServiceCategoryBitmask)
-                + "|Sources-" + Integer.toBinaryString(mEmergencyNumberSourceBitmask);
+                + "|Sources-" + Integer.toBinaryString(mEmergencyNumberSourceBitmask)
+                + "|Routing-" + Integer.toBinaryString(mEmergencyCallRouting);
     }
 
     @Override
@@ -381,7 +443,19 @@
         if (!EmergencyNumber.class.isInstance(o)) {
             return false;
         }
-        return (o == this || toString().equals(o.toString()));
+        EmergencyNumber other = (EmergencyNumber) o;
+        return mNumber.equals(other.mNumber)
+                && mCountryIso.equals(other.mCountryIso)
+                && mMnc.equals(other.mMnc)
+                && mEmergencyServiceCategoryBitmask == other.mEmergencyServiceCategoryBitmask
+                && mEmergencyNumberSourceBitmask == other.mEmergencyNumberSourceBitmask
+                && mEmergencyCallRouting == other.mEmergencyCallRouting;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mNumber, mCountryIso, mMnc, mEmergencyServiceCategoryBitmask,
+                mEmergencyNumberSourceBitmask, mEmergencyCallRouting);
     }
 
     /**
@@ -462,12 +536,12 @@
                 continue;
             }
             for (int j = i + 1; j < emergencyNumberList.size(); j++) {
-                if (isSameEmergencyNumber(
+                if (areSameEmergencyNumbers(
                         emergencyNumberList.get(i), emergencyNumberList.get(j))) {
                     Rlog.e(LOG_TAG, "Found unexpected duplicate numbers: "
                             + emergencyNumberList.get(i) + " vs " + emergencyNumberList.get(j));
                     // Set the merged emergency number in the current position
-                    emergencyNumberList.set(i, mergeNumbers(
+                    emergencyNumberList.set(i, mergeSameEmergencyNumbers(
                             emergencyNumberList.get(i), emergencyNumberList.get(j)));
                     // Mark the emergency number has been merged
                     mergedEmergencyNumber.add(emergencyNumberList.get(j));
@@ -486,8 +560,8 @@
      * Check if two emergency numbers are the same.
      *
      * A unique EmergencyNumber has a unique combination of ‘number’, ‘mcc’, 'mnc' and
-     * 'categories' fields. Multiple Emergency Number Sources should be merged into one bitfield
-     * for the same EmergencyNumber.
+     * 'categories', and 'routing' fields. Multiple Emergency Number Sources should be
+     * merged into one bitfield for the same EmergencyNumber.
      *
      * @param first first EmergencyNumber to compare
      * @param second second EmergencyNumber to compare
@@ -495,8 +569,8 @@
      *
      * @hide
      */
-    public static boolean isSameEmergencyNumber(@NonNull EmergencyNumber first,
-                                                @NonNull EmergencyNumber second) {
+    public static boolean areSameEmergencyNumbers(@NonNull EmergencyNumber first,
+                                                  @NonNull EmergencyNumber second) {
         if (!first.getNumber().equals(second.getNumber())) {
             return false;
         }
@@ -510,11 +584,15 @@
                 != second.getEmergencyServiceCategoryBitmask()) {
             return false;
         }
+        if (first.getEmergencyCallRouting() != second.getEmergencyCallRouting()) {
+            return false;
+        }
         return true;
     }
 
     /**
-     * Get a merged EmergencyNumber for two numbers if they are the same.
+     * Get a merged EmergencyNumber from two same emergency numbers. Two emergency numbers are
+     * the same if {@link #areSameEmergencyNumbers} returns {@code true}.
      *
      * @param first first EmergencyNumber to compare
      * @param second second EmergencyNumber to compare
@@ -522,27 +600,15 @@
      *
      * @hide
      */
-    public static EmergencyNumber mergeNumbers(@NonNull EmergencyNumber first,
-                                         @NonNull EmergencyNumber second) {
-        if (isSameEmergencyNumber(first, second)) {
+    public static EmergencyNumber mergeSameEmergencyNumbers(@NonNull EmergencyNumber first,
+                                                            @NonNull EmergencyNumber second) {
+        if (areSameEmergencyNumbers(first, second)) {
             return new EmergencyNumber(first.getNumber(), first.getCountryIso(), first.getMnc(),
                     first.getEmergencyServiceCategoryBitmask(),
                     first.getEmergencyNumberSourceBitmask()
-                            | second.getEmergencyNumberSourceBitmask());
+                            | second.getEmergencyNumberSourceBitmask(),
+                    first.getEmergencyCallRouting());
         }
         return null;
     }
-
-    public static final Parcelable.Creator<EmergencyNumber> CREATOR =
-            new Parcelable.Creator<EmergencyNumber>() {
-        @Override
-        public EmergencyNumber createFromParcel(Parcel in) {
-            return new EmergencyNumber(in);
-        }
-
-        @Override
-        public EmergencyNumber[] newArray(int size) {
-            return new EmergencyNumber[size];
-        }
-    };
 }
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index cb6fcd7..9c8d078 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -24,9 +24,11 @@
 import android.os.Parcelable;
 import android.telecom.VideoProfile;
 import android.telephony.emergency.EmergencyNumber;
+import android.telephony.emergency.EmergencyNumber.EmergencyCallRouting;
 import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.PhoneConstants;
 
 import java.lang.annotation.Retention;
@@ -321,6 +323,20 @@
             EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED;
 
     /**
+     * The emergency call routing, only valid if {@link #getServiceType} returns
+     * {@link #SERVICE_TYPE_EMERGENCY}
+     *
+     * If valid, the value is any of the following constants:
+     * <ol>
+     * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_UNKNOWN} </li>
+     * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_NORMAL} </li>
+     * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_EMERGENCY} </li>
+     * </ol>
+     */
+    private @EmergencyCallRouting int mEmergencyCallRouting =
+            EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
+
+    /**
      * Extras associated with this {@link ImsCallProfile}.
      * <p>
      * Valid data types include:
@@ -503,10 +519,12 @@
 
     @Override
     public String toString() {
-        return "{ serviceType=" + mServiceType +
-                ", callType=" + mCallType +
-                ", restrictCause=" + mRestrictCause +
-                ", mediaProfile=" + mMediaProfile.toString() + " }";
+        return "{ serviceType=" + mServiceType
+                + ", callType=" + mCallType
+                + ", restrictCause=" + mRestrictCause
+                + ", mediaProfile=" + mMediaProfile.toString()
+                + ", emergencyServiceCategories=" + mEmergencyCallRouting
+                + ", emergencyCallRouting=" + mEmergencyCallRouting + " }";
     }
 
     @Override
@@ -522,6 +540,7 @@
         out.writeBundle(filteredExtras);
         out.writeParcelable(mMediaProfile, 0);
         out.writeInt(mEmergencyServiceCategories);
+        out.writeInt(mEmergencyCallRouting);
     }
 
     private void readFromParcel(Parcel in) {
@@ -530,6 +549,7 @@
         mCallExtras = in.readBundle();
         mMediaProfile = in.readParcelable(ImsStreamMediaProfile.class.getClassLoader());
         mEmergencyServiceCategories = in.readInt();
+        mEmergencyCallRouting = in.readInt();
     }
 
     public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() {
@@ -740,6 +760,21 @@
     }
 
     /**
+     * Set the emergency service categories and emergency call routing. The set value is valid
+     * only if {@link #getServiceType} returns {@link #SERVICE_TYPE_EMERGENCY}
+     *
+     * Reference: 3gpp 23.167, Section 6 - Functional description;
+     *            3gpp 22.101, Section 10 - Emergency Calls.
+     *
+     * @hide
+     */
+    public void setEmergencyCallInfo(EmergencyNumber num) {
+        setEmergencyServiceCategories(num.getEmergencyServiceCategoryBitmask());
+        setEmergencyCallRouting(num.getEmergencyCallRouting());
+    }
+
+
+    /**
      * Set the emergency service categories. The set value is valid only if
      * {@link #getServiceType} returns {@link #SERVICE_TYPE_EMERGENCY}
      *
@@ -758,12 +793,29 @@
      * Reference: 3gpp 23.167, Section 6 - Functional description;
      *            3gpp 22.101, Section 10 - Emergency Calls.
      */
+    @VisibleForTesting
     public void setEmergencyServiceCategories(
             @EmergencyServiceCategories int emergencyServiceCategories) {
         mEmergencyServiceCategories = emergencyServiceCategories;
     }
 
     /**
+     * Set the emergency call routing, only valid if {@link #getServiceType} returns
+     * {@link #SERVICE_TYPE_EMERGENCY}
+     *
+     * If valid, the value is any of the following constants:
+     * <ol>
+     * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_UNKNOWN} </li>
+     * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_NORMAL} </li>
+     * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_EMERGENCY} </li>
+     * </ol>
+     */
+    @VisibleForTesting
+    public void setEmergencyCallRouting(@EmergencyCallRouting int emergencyCallRouting) {
+        mEmergencyCallRouting = emergencyCallRouting;
+    }
+
+    /**
      * Get the emergency service categories, only valid if {@link #getServiceType} returns
      * {@link #SERVICE_TYPE_EMERGENCY}
      *
@@ -787,4 +839,19 @@
     public @EmergencyServiceCategories int getEmergencyServiceCategories() {
         return mEmergencyServiceCategories;
     }
+
+    /**
+     * Get the emergency call routing, only valid if {@link #getServiceType} returns
+     * {@link #SERVICE_TYPE_EMERGENCY}
+     *
+     * If valid, the value is any of the following constants:
+     * <ol>
+     * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_UNKNOWN} </li>
+     * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_NORMAL} </li>
+     * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_EMERGENCY} </li>
+     * </ol>
+     */
+    public @EmergencyCallRouting int getEmergencyCallRouting() {
+        return mEmergencyCallRouting;
+    }
 }