OSDN Git Service

Add Emergency Call Routing
authorsqian <shuoq@google.com>
Wed, 19 Dec 2018 05:09:21 +0000 (21:09 -0800)
committerShuo Qian <shuoq@google.com>
Thu, 17 Jan 2019 18:05:16 +0000 (18:05 +0000)
Some countries or carriers require some emergency numbers that must
be handled with normal call routing or emergency routing.

Do not send service types from the database
as the emergency service categories

When searching for the corresponding service categories,
try to find the one that comes from the radio indication.

Test: Treehugger
Bug: 112657134
Change-Id: I95dadd07e9155c6e402a72339f307b4d7ef32fe4
Merged-In: I95dadd07e9155c6e402a72339f307b4d7ef32fe4
(cherry picked from commit a4bd738b8b4a4402a26747d6be5d9a2228a45329)

api/current.txt
api/system-current.txt
telephony/java/android/telephony/emergency/EmergencyNumber.java
telephony/java/android/telephony/ims/ImsCallProfile.java

index aaacd68..b7cef9e 100755 (executable)
@@ -43380,6 +43380,7 @@ package android.telephony.emergency {
     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 @@ package android.telephony.emergency {
     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
index 1bf6cf9..9cdc682 100644 (file)
@@ -6040,6 +6040,7 @@ package android.telephony.ims {
     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 @@ package android.telephony.ims {
     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);
index fe062d5..a94b163 100644 (file)
@@ -29,6 +29,7 @@ import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -198,21 +199,53 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
         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 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
         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 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
         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 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
         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 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
         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 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
                 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 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
      * 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 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
      *
      * @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 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
                 != 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 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
      *
      * @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];
-        }
-    };
 }
index cb6fcd7..9c8d078 100644 (file)
@@ -24,9 +24,11 @@ import android.os.Parcel;
 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 @@ public final class ImsCallProfile implements Parcelable {
             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 @@ public final class ImsCallProfile implements Parcelable {
 
     @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 @@ public final class ImsCallProfile implements Parcelable {
         out.writeBundle(filteredExtras);
         out.writeParcelable(mMediaProfile, 0);
         out.writeInt(mEmergencyServiceCategories);
+        out.writeInt(mEmergencyCallRouting);
     }
 
     private void readFromParcel(Parcel in) {
@@ -530,6 +549,7 @@ public final class ImsCallProfile implements Parcelable {
         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 @@ public final class ImsCallProfile implements Parcelable {
     }
 
     /**
+     * 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 @@ public final class ImsCallProfile implements Parcelable {
      * 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 final class ImsCallProfile implements Parcelable {
     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;
+    }
 }