Merge "Add NetworkStack app"
diff --git a/api/current.txt b/api/current.txt
index b3ab4ed..65c988f 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -27225,7 +27225,7 @@
     method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
     method public boolean bindProcessToNetwork(android.net.Network);
     method public android.net.Network getActiveNetwork();
-    method public android.net.NetworkInfo getActiveNetworkInfo();
+    method public deprecated android.net.NetworkInfo getActiveNetworkInfo();
     method public deprecated android.net.NetworkInfo[] getAllNetworkInfo();
     method public android.net.Network[] getAllNetworks();
     method public deprecated boolean getBackgroundDataSetting();
@@ -27236,7 +27236,7 @@
     method public int getMultipathPreference(android.net.Network);
     method public android.net.NetworkCapabilities getNetworkCapabilities(android.net.Network);
     method public deprecated android.net.NetworkInfo getNetworkInfo(int);
-    method public android.net.NetworkInfo getNetworkInfo(android.net.Network);
+    method public deprecated android.net.NetworkInfo getNetworkInfo(android.net.Network);
     method public deprecated int getNetworkPreference();
     method public byte[] getNetworkWatchlistConfigHash();
     method public static deprecated android.net.Network getProcessDefaultNetwork();
@@ -27270,14 +27270,14 @@
     field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
     field public static final java.lang.String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
     field public static final java.lang.String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
-    field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
-    field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
+    field public static final deprecated java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
+    field public static final deprecated java.lang.String EXTRA_IS_FAILOVER = "isFailover";
     field public static final java.lang.String EXTRA_NETWORK = "android.net.extra.NETWORK";
     field public static final deprecated java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
     field public static final java.lang.String EXTRA_NETWORK_REQUEST = "android.net.extra.NETWORK_REQUEST";
     field public static final java.lang.String EXTRA_NETWORK_TYPE = "networkType";
     field public static final java.lang.String EXTRA_NO_CONNECTIVITY = "noConnectivity";
-    field public static final java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
+    field public static final deprecated java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
     field public static final java.lang.String EXTRA_REASON = "reason";
     field public static final int MULTIPATH_PREFERENCE_HANDOVER = 1; // 0x1
     field public static final int MULTIPATH_PREFERENCE_PERFORMANCE = 4; // 0x4
@@ -27429,6 +27429,7 @@
     method public android.net.ProxyInfo getHttpProxy();
     method public java.lang.String getInterfaceName();
     method public java.util.List<android.net.LinkAddress> getLinkAddresses();
+    method public int getMtu();
     method public java.lang.String getPrivateDnsServerName();
     method public java.util.List<android.net.RouteInfo> getRoutes();
     method public boolean isPrivateDnsActive();
@@ -27577,10 +27578,10 @@
     field public static final int TRANSPORT_WIFI_AWARE = 5; // 0x5
   }
 
-  public class NetworkInfo implements android.os.Parcelable {
+  public deprecated class NetworkInfo implements android.os.Parcelable {
     method public int describeContents();
     method public deprecated android.net.NetworkInfo.DetailedState getDetailedState();
-    method public java.lang.String getExtraInfo();
+    method public deprecated java.lang.String getExtraInfo();
     method public deprecated java.lang.String getReason();
     method public deprecated android.net.NetworkInfo.State getState();
     method public deprecated int getSubtype();
@@ -27596,7 +27597,7 @@
     field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
   }
 
-  public static final class NetworkInfo.DetailedState extends java.lang.Enum {
+  public static final deprecated class NetworkInfo.DetailedState extends java.lang.Enum {
     method public static android.net.NetworkInfo.DetailedState valueOf(java.lang.String);
     method public static final android.net.NetworkInfo.DetailedState[] values();
     enum_constant public static final android.net.NetworkInfo.DetailedState AUTHENTICATING;
@@ -27614,7 +27615,7 @@
     enum_constant public static final android.net.NetworkInfo.DetailedState VERIFYING_POOR_LINK;
   }
 
-  public static final class NetworkInfo.State extends java.lang.Enum {
+  public static final deprecated class NetworkInfo.State extends java.lang.Enum {
     method public static android.net.NetworkInfo.State valueOf(java.lang.String);
     method public static final android.net.NetworkInfo.State[] values();
     enum_constant public static final android.net.NetworkInfo.State CONNECTED;
@@ -37353,22 +37354,23 @@
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String CURRENT = "current";
     field public static final java.lang.String DEFAULT_SORT_ORDER = "name ASC";
-    field public static final java.lang.String MCC = "mcc";
+    field public static final deprecated java.lang.String MCC = "mcc";
     field public static final java.lang.String MMSC = "mmsc";
     field public static final java.lang.String MMSPORT = "mmsport";
     field public static final java.lang.String MMSPROXY = "mmsproxy";
-    field public static final java.lang.String MNC = "mnc";
-    field public static final java.lang.String MVNO_MATCH_DATA = "mvno_match_data";
-    field public static final java.lang.String MVNO_TYPE = "mvno_type";
+    field public static final deprecated java.lang.String MNC = "mnc";
+    field public static final deprecated java.lang.String MVNO_MATCH_DATA = "mvno_match_data";
+    field public static final deprecated java.lang.String MVNO_TYPE = "mvno_type";
     field public static final java.lang.String NAME = "name";
     field public static final java.lang.String NETWORK_TYPE_BITMASK = "network_type_bitmask";
-    field public static final java.lang.String NUMERIC = "numeric";
+    field public static final deprecated java.lang.String NUMERIC = "numeric";
     field public static final java.lang.String PASSWORD = "password";
     field public static final java.lang.String PORT = "port";
     field public static final java.lang.String PROTOCOL = "protocol";
     field public static final java.lang.String PROXY = "proxy";
     field public static final java.lang.String ROAMING_PROTOCOL = "roaming_protocol";
     field public static final java.lang.String SERVER = "server";
+    field public static final android.net.Uri SIM_APN_URI;
     field public static final java.lang.String SUBSCRIPTION_ID = "sub_id";
     field public static final java.lang.String TYPE = "type";
     field public static final java.lang.String USER = "user";
@@ -42902,12 +42904,14 @@
     method public static int getSlotIndex(int);
     method public int[] getSubscriptionIds(int);
     method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
+    method public java.util.List<android.telephony.SubscriptionInfo> getSubscriptionsInGroup(int);
     method public boolean isActiveSubscriptionId(int);
     method public boolean isNetworkRoaming(int);
     method public static boolean isUsableSubscriptionId(int);
     method public static boolean isValidSubscriptionId(int);
     method public void removeOnOpportunisticSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
     method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
+    method public boolean removeSubscriptionsFromGroup(int[]);
     method public java.lang.String setSubscriptionGroup(int[]);
     method public void setSubscriptionOverrideCongested(int, boolean, long);
     method public void setSubscriptionOverrideUnmetered(int, boolean, long);
diff --git a/api/system-current.txt b/api/system-current.txt
index b09ee82..5a038af 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3045,7 +3045,20 @@
     ctor public LinkAddress(java.lang.String);
   }
 
+  public final class LinkProperties implements android.os.Parcelable {
+    ctor public LinkProperties();
+    method public boolean addRoute(android.net.RouteInfo);
+    method public void clear();
+    method public void setDnsServers(java.util.Collection<java.net.InetAddress>);
+    method public void setDomains(java.lang.String);
+    method public void setHttpProxy(android.net.ProxyInfo);
+    method public void setInterfaceName(java.lang.String);
+    method public void setLinkAddresses(java.util.Collection<android.net.LinkAddress>);
+    method public void setMtu(int);
+  }
+
   public final class NetworkCapabilities implements android.os.Parcelable {
+    method public int getSignalStrength();
     field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16
   }
 
@@ -3065,6 +3078,10 @@
     method public abstract void onRequestScores(android.net.NetworkKey[]);
   }
 
+  public static class NetworkRequest.Builder {
+    method public android.net.NetworkRequest.Builder setSignalStrength(int);
+  }
+
   public class NetworkScoreManager {
     method public boolean clearScores() throws java.lang.SecurityException;
     method public void disableScoring() throws java.lang.SecurityException;
@@ -5044,6 +5061,83 @@
     field public static final java.lang.String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string";
   }
 
+  public class DisconnectCause {
+    field public static final int ALREADY_DIALING = 72; // 0x48
+    field public static final int ANSWERED_ELSEWHERE = 52; // 0x34
+    field public static final int BUSY = 4; // 0x4
+    field public static final int CALLING_DISABLED = 74; // 0x4a
+    field public static final int CALL_BARRED = 20; // 0x14
+    field public static final int CALL_PULLED = 51; // 0x33
+    field public static final int CANT_CALL_WHILE_RINGING = 73; // 0x49
+    field public static final int CDMA_ACCESS_BLOCKED = 35; // 0x23
+    field public static final int CDMA_ACCESS_FAILURE = 32; // 0x20
+    field public static final int CDMA_ALREADY_ACTIVATED = 49; // 0x31
+    field public static final int CDMA_DROP = 27; // 0x1b
+    field public static final int CDMA_INTERCEPT = 28; // 0x1c
+    field public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE = 26; // 0x1a
+    field public static final int CDMA_NOT_EMERGENCY = 34; // 0x22
+    field public static final int CDMA_PREEMPTED = 33; // 0x21
+    field public static final int CDMA_REORDER = 29; // 0x1d
+    field public static final int CDMA_RETRY_ORDER = 31; // 0x1f
+    field public static final int CDMA_SO_REJECT = 30; // 0x1e
+    field public static final int CONGESTION = 5; // 0x5
+    field public static final int CS_RESTRICTED = 22; // 0x16
+    field public static final int CS_RESTRICTED_EMERGENCY = 24; // 0x18
+    field public static final int CS_RESTRICTED_NORMAL = 23; // 0x17
+    field public static final int DATA_DISABLED = 54; // 0x36
+    field public static final int DATA_LIMIT_REACHED = 55; // 0x37
+    field public static final int DIALED_CALL_FORWARDING_WHILE_ROAMING = 57; // 0x39
+    field public static final int DIALED_MMI = 39; // 0x27
+    field public static final int DIAL_LOW_BATTERY = 62; // 0x3e
+    field public static final int DIAL_MODIFIED_TO_DIAL = 48; // 0x30
+    field public static final int DIAL_MODIFIED_TO_DIAL_VIDEO = 66; // 0x42
+    field public static final int DIAL_MODIFIED_TO_SS = 47; // 0x2f
+    field public static final int DIAL_MODIFIED_TO_USSD = 46; // 0x2e
+    field public static final int DIAL_VIDEO_MODIFIED_TO_DIAL = 69; // 0x45
+    field public static final int DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO = 70; // 0x46
+    field public static final int DIAL_VIDEO_MODIFIED_TO_SS = 67; // 0x43
+    field public static final int DIAL_VIDEO_MODIFIED_TO_USSD = 68; // 0x44
+    field public static final int EMERGENCY_PERM_FAILURE = 64; // 0x40
+    field public static final int EMERGENCY_TEMP_FAILURE = 63; // 0x3f
+    field public static final int ERROR_UNSPECIFIED = 36; // 0x24
+    field public static final int FDN_BLOCKED = 21; // 0x15
+    field public static final int ICC_ERROR = 19; // 0x13
+    field public static final int IMEI_NOT_ACCEPTED = 58; // 0x3a
+    field public static final int IMS_ACCESS_BLOCKED = 60; // 0x3c
+    field public static final int IMS_MERGED_SUCCESSFULLY = 45; // 0x2d
+    field public static final int IMS_SIP_ALTERNATE_EMERGENCY_CALL = 71; // 0x47
+    field public static final int INCOMING_MISSED = 1; // 0x1
+    field public static final int INCOMING_REJECTED = 16; // 0x10
+    field public static final int INVALID_CREDENTIALS = 10; // 0xa
+    field public static final int INVALID_NUMBER = 7; // 0x7
+    field public static final int LIMIT_EXCEEDED = 15; // 0xf
+    field public static final int LOCAL = 3; // 0x3
+    field public static final int LOST_SIGNAL = 14; // 0xe
+    field public static final int LOW_BATTERY = 61; // 0x3d
+    field public static final int MAXIMUM_NUMBER_OF_CALLS_REACHED = 53; // 0x35
+    field public static final int MMI = 6; // 0x6
+    field public static final int NORMAL = 2; // 0x2
+    field public static final int NORMAL_UNSPECIFIED = 65; // 0x41
+    field public static final int NOT_DISCONNECTED = 0; // 0x0
+    field public static final int NOT_VALID = -1; // 0xffffffff
+    field public static final int NO_PHONE_NUMBER_SUPPLIED = 38; // 0x26
+    field public static final int NUMBER_UNREACHABLE = 8; // 0x8
+    field public static final int OTASP_PROVISIONING_IN_PROCESS = 76; // 0x4c
+    field public static final int OUTGOING_CANCELED = 44; // 0x2c
+    field public static final int OUTGOING_FAILURE = 43; // 0x2b
+    field public static final int OUT_OF_NETWORK = 11; // 0xb
+    field public static final int OUT_OF_SERVICE = 18; // 0x12
+    field public static final int POWER_OFF = 17; // 0x11
+    field public static final int SERVER_ERROR = 12; // 0xc
+    field public static final int SERVER_UNREACHABLE = 9; // 0x9
+    field public static final int TIMED_OUT = 13; // 0xd
+    field public static final int TOO_MANY_ONGOING_CALLS = 75; // 0x4b
+    field public static final int UNOBTAINABLE_NUMBER = 25; // 0x19
+    field public static final int VIDEO_CALL_NOT_ALLOWED_WHILE_TTY_ENABLED = 50; // 0x32
+    field public static final int VOICEMAIL_NUMBER_MISSING = 40; // 0x28
+    field public static final int WIFI_LOST = 59; // 0x3b
+  }
+
   public class MbmsDownloadSession implements java.lang.AutoCloseable {
     field public static final java.lang.String MBMS_DOWNLOAD_SERVICE_ACTION = "android.telephony.action.EmbmsDownload";
   }
@@ -5132,14 +5226,134 @@
   }
 
   public class PhoneStateListener {
+    method public void onCallDisconnectCauseChanged(int, int);
+    method public void onPreciseCallStateChanged(android.telephony.PreciseCallState);
     method public void onRadioPowerStateChanged(int);
     method public void onSrvccStateChanged(int);
     method public void onVoiceActivationStateChanged(int);
+    field public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
+    field public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
     field public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000
     field public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000
     field public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000
   }
 
+  public final class PreciseCallState implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getBackgroundCallState();
+    method public int getForegroundCallState();
+    method public int getRingingCallState();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.PreciseCallState> CREATOR;
+    field public static final int PRECISE_CALL_STATE_ACTIVE = 1; // 0x1
+    field public static final int PRECISE_CALL_STATE_ALERTING = 4; // 0x4
+    field public static final int PRECISE_CALL_STATE_DIALING = 3; // 0x3
+    field public static final int PRECISE_CALL_STATE_DISCONNECTED = 7; // 0x7
+    field public static final int PRECISE_CALL_STATE_DISCONNECTING = 8; // 0x8
+    field public static final int PRECISE_CALL_STATE_HOLDING = 2; // 0x2
+    field public static final int PRECISE_CALL_STATE_IDLE = 0; // 0x0
+    field public static final int PRECISE_CALL_STATE_INCOMING = 5; // 0x5
+    field public static final int PRECISE_CALL_STATE_NOT_VALID = -1; // 0xffffffff
+    field public static final int PRECISE_CALL_STATE_WAITING = 6; // 0x6
+  }
+
+  public class PreciseDisconnectCause {
+    field public static final int ACCESS_CLASS_BLOCKED = 260; // 0x104
+    field public static final int ACCESS_INFORMATION_DISCARDED = 43; // 0x2b
+    field public static final int ACM_LIMIT_EXCEEDED = 68; // 0x44
+    field public static final int BEARER_CAPABILITY_NOT_AUTHORIZED = 57; // 0x39
+    field public static final int BEARER_NOT_AVAIL = 58; // 0x3a
+    field public static final int BEARER_SERVICE_NOT_IMPLEMENTED = 65; // 0x41
+    field public static final int BUSY = 17; // 0x11
+    field public static final int CALL_BARRED = 240; // 0xf0
+    field public static final int CALL_REJECTED = 21; // 0x15
+    field public static final int CDMA_ACCESS_BLOCKED = 1009; // 0x3f1
+    field public static final int CDMA_ACCESS_FAILURE = 1006; // 0x3ee
+    field public static final int CDMA_DROP = 1001; // 0x3e9
+    field public static final int CDMA_INTERCEPT = 1002; // 0x3ea
+    field public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE = 1000; // 0x3e8
+    field public static final int CDMA_NOT_EMERGENCY = 1008; // 0x3f0
+    field public static final int CDMA_PREEMPTED = 1007; // 0x3ef
+    field public static final int CDMA_REORDER = 1003; // 0x3eb
+    field public static final int CDMA_RETRY_ORDER = 1005; // 0x3ed
+    field public static final int CDMA_SO_REJECT = 1004; // 0x3ec
+    field public static final int CHANNEL_NOT_AVAIL = 44; // 0x2c
+    field public static final int CHANNEL_UNACCEPTABLE = 6; // 0x6
+    field public static final int CONDITIONAL_IE_ERROR = 100; // 0x64
+    field public static final int DESTINATION_OUT_OF_ORDER = 27; // 0x1b
+    field public static final int ERROR_UNSPECIFIED = 65535; // 0xffff
+    field public static final int FACILITY_REJECTED = 29; // 0x1d
+    field public static final int FDN_BLOCKED = 241; // 0xf1
+    field public static final int IMEI_NOT_ACCEPTED = 243; // 0xf3
+    field public static final int IMSI_UNKNOWN_IN_VLR = 242; // 0xf2
+    field public static final int INCOMING_CALLS_BARRED_WITHIN_CUG = 55; // 0x37
+    field public static final int INCOMPATIBLE_DESTINATION = 88; // 0x58
+    field public static final int INFORMATION_ELEMENT_NON_EXISTENT = 99; // 0x63
+    field public static final int INTERWORKING_UNSPECIFIED = 127; // 0x7f
+    field public static final int INVALID_MANDATORY_INFORMATION = 96; // 0x60
+    field public static final int INVALID_NUMBER_FORMAT = 28; // 0x1c
+    field public static final int INVALID_TRANSACTION_IDENTIFIER = 81; // 0x51
+    field public static final int MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101; // 0x65
+    field public static final int MESSAGE_TYPE_NON_IMPLEMENTED = 97; // 0x61
+    field public static final int MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98; // 0x62
+    field public static final int NETWORK_DETACH = 261; // 0x105
+    field public static final int NETWORK_OUT_OF_ORDER = 38; // 0x26
+    field public static final int NETWORK_REJECT = 252; // 0xfc
+    field public static final int NETWORK_RESP_TIMEOUT = 251; // 0xfb
+    field public static final int NORMAL = 16; // 0x10
+    field public static final int NORMAL_UNSPECIFIED = 31; // 0x1f
+    field public static final int NOT_VALID = -1; // 0xffffffff
+    field public static final int NO_ANSWER_FROM_USER = 19; // 0x13
+    field public static final int NO_CIRCUIT_AVAIL = 34; // 0x22
+    field public static final int NO_DISCONNECT_CAUSE_AVAILABLE = 0; // 0x0
+    field public static final int NO_ROUTE_TO_DESTINATION = 3; // 0x3
+    field public static final int NO_USER_RESPONDING = 18; // 0x12
+    field public static final int NO_VALID_SIM = 249; // 0xf9
+    field public static final int NUMBER_CHANGED = 22; // 0x16
+    field public static final int OEM_CAUSE_1 = 61441; // 0xf001
+    field public static final int OEM_CAUSE_10 = 61450; // 0xf00a
+    field public static final int OEM_CAUSE_11 = 61451; // 0xf00b
+    field public static final int OEM_CAUSE_12 = 61452; // 0xf00c
+    field public static final int OEM_CAUSE_13 = 61453; // 0xf00d
+    field public static final int OEM_CAUSE_14 = 61454; // 0xf00e
+    field public static final int OEM_CAUSE_15 = 61455; // 0xf00f
+    field public static final int OEM_CAUSE_2 = 61442; // 0xf002
+    field public static final int OEM_CAUSE_3 = 61443; // 0xf003
+    field public static final int OEM_CAUSE_4 = 61444; // 0xf004
+    field public static final int OEM_CAUSE_5 = 61445; // 0xf005
+    field public static final int OEM_CAUSE_6 = 61446; // 0xf006
+    field public static final int OEM_CAUSE_7 = 61447; // 0xf007
+    field public static final int OEM_CAUSE_8 = 61448; // 0xf008
+    field public static final int OEM_CAUSE_9 = 61449; // 0xf009
+    field public static final int ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 70; // 0x46
+    field public static final int OPERATOR_DETERMINED_BARRING = 8; // 0x8
+    field public static final int OUT_OF_SRV = 248; // 0xf8
+    field public static final int PREEMPTION = 25; // 0x19
+    field public static final int PROTOCOL_ERROR_UNSPECIFIED = 111; // 0x6f
+    field public static final int QOS_NOT_AVAIL = 49; // 0x31
+    field public static final int RADIO_ACCESS_FAILURE = 253; // 0xfd
+    field public static final int RADIO_INTERNAL_ERROR = 250; // 0xfa
+    field public static final int RADIO_LINK_FAILURE = 254; // 0xfe
+    field public static final int RADIO_LINK_LOST = 255; // 0xff
+    field public static final int RADIO_OFF = 247; // 0xf7
+    field public static final int RADIO_RELEASE_ABNORMAL = 259; // 0x103
+    field public static final int RADIO_RELEASE_NORMAL = 258; // 0x102
+    field public static final int RADIO_SETUP_FAILURE = 257; // 0x101
+    field public static final int RADIO_UPLINK_FAILURE = 256; // 0x100
+    field public static final int RECOVERY_ON_TIMER_EXPIRED = 102; // 0x66
+    field public static final int REQUESTED_FACILITY_NOT_IMPLEMENTED = 69; // 0x45
+    field public static final int REQUESTED_FACILITY_NOT_SUBSCRIBED = 50; // 0x32
+    field public static final int RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 47; // 0x2f
+    field public static final int SEMANTICALLY_INCORRECT_MESSAGE = 95; // 0x5f
+    field public static final int SERVICE_OPTION_NOT_AVAILABLE = 63; // 0x3f
+    field public static final int SERVICE_OR_OPTION_NOT_IMPLEMENTED = 79; // 0x4f
+    field public static final int STATUS_ENQUIRY = 30; // 0x1e
+    field public static final int SWITCHING_CONGESTION = 42; // 0x2a
+    field public static final int TEMPORARY_FAILURE = 41; // 0x29
+    field public static final int UNOBTAINABLE_NUMBER = 1; // 0x1
+    field public static final int USER_NOT_MEMBER_OF_CUG = 87; // 0x57
+  }
+
   public class ServiceState implements android.os.Parcelable {
     method public android.telephony.NetworkRegistrationState getNetworkRegistrationState(int, int);
     method public java.util.List<android.telephony.NetworkRegistrationState> getNetworkRegistrationStates();
@@ -5177,6 +5391,7 @@
 
   public class SubscriptionInfo implements android.os.Parcelable {
     method public java.util.List<android.telephony.UiccAccessRule> getAccessRules();
+    method public int getCardId();
   }
 
   public class SubscriptionManager {
diff --git a/cmds/incident_helper/src/TextParserBase.h b/cmds/incident_helper/src/TextParserBase.h
index 784c181..a6074e7 100644
--- a/cmds/incident_helper/src/TextParserBase.h
+++ b/cmds/incident_helper/src/TextParserBase.h
@@ -30,7 +30,7 @@
 public:
     String8 name;
 
-    TextParserBase(String8 name) : name(name) {};
+    explicit TextParserBase(String8 name) : name(name) {};
     virtual ~TextParserBase() {};
 
     virtual status_t Parse(const int in, const int out) const = 0;
diff --git a/cmds/incident_helper/src/ih_util.h b/cmds/incident_helper/src/ih_util.h
index c02a349..09dc8e6 100644
--- a/cmds/incident_helper/src/ih_util.h
+++ b/cmds/incident_helper/src/ih_util.h
@@ -109,7 +109,7 @@
 class Reader
 {
 public:
-    Reader(const int fd);
+    explicit Reader(const int fd);
     ~Reader();
 
     bool readLine(std::string* line);
@@ -162,7 +162,7 @@
 class Message
 {
 public:
-    Message(Table* table);
+    explicit Message(Table* table);
     ~Message();
 
     // Reconstructs the typical proto message by adding its message fields.
diff --git a/cmds/incidentd/src/IncidentService.h b/cmds/incidentd/src/IncidentService.h
index e176bfd..140484b 100644
--- a/cmds/incidentd/src/IncidentService.h
+++ b/cmds/incidentd/src/IncidentService.h
@@ -97,7 +97,7 @@
 // ================================================================================
 class IncidentService : public BnIncidentManager {
 public:
-    IncidentService(const sp<Looper>& handlerLooper);
+    explicit IncidentService(const sp<Looper>& handlerLooper);
     virtual ~IncidentService();
 
     virtual Status reportIncident(const IncidentReportArgs& args);
diff --git a/cmds/incidentd/src/Privacy.h b/cmds/incidentd/src/Privacy.h
index a3df490..a0159d9 100644
--- a/cmds/incidentd/src/Privacy.h
+++ b/cmds/incidentd/src/Privacy.h
@@ -83,7 +83,7 @@
     static PrivacySpec new_spec(int dest);
 
 private:
-    PrivacySpec(uint8_t dest) : dest(dest) {}
+    explicit PrivacySpec(uint8_t dest) : dest(dest) {}
 };
 
 }  // namespace incidentd
diff --git a/cmds/incidentd/src/Reporter.h b/cmds/incidentd/src/Reporter.h
index 45fd944..2a3abd7 100644
--- a/cmds/incidentd/src/Reporter.h
+++ b/cmds/incidentd/src/Reporter.h
@@ -89,7 +89,7 @@
     ReportRequestSet batch;
 
     Reporter();                       // PROD must use this constructor.
-    Reporter(const char* directory);  // For testing purpose only.
+    explicit Reporter(const char* directory);  // For testing purpose only.
     virtual ~Reporter();
 
     // Run the report as described in the batch and args parameters.
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 72a4103..bb5221c 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -410,7 +410,7 @@
     bool workerDone;
     status_t workerError;
 
-    WorkerThreadData(const WorkerThreadSection* section);
+    explicit WorkerThreadData(const WorkerThreadSection* section);
     virtual ~WorkerThreadData();
 };
 
diff --git a/cmds/statsd/src/anomaly/AlarmMonitor.h b/cmds/statsd/src/anomaly/AlarmMonitor.h
index 3badb1f..bca858e 100644
--- a/cmds/statsd/src/anomaly/AlarmMonitor.h
+++ b/cmds/statsd/src/anomaly/AlarmMonitor.h
@@ -42,7 +42,7 @@
  * Timestamps are in seconds since epoch in a uint32, so will fail in year 2106.
  */
 struct InternalAlarm : public RefBase {
-    InternalAlarm(uint32_t timestampSec) : timestampSec(timestampSec) {
+    explicit InternalAlarm(uint32_t timestampSec) : timestampSec(timestampSec) {
     }
 
     const uint32_t timestampSec;
diff --git a/cmds/statsd/src/condition/ConditionWizard.h b/cmds/statsd/src/condition/ConditionWizard.h
index a6f88af..2c88147 100644
--- a/cmds/statsd/src/condition/ConditionWizard.h
+++ b/cmds/statsd/src/condition/ConditionWizard.h
@@ -29,7 +29,7 @@
 class ConditionWizard : public virtual android::RefBase {
 public:
     ConditionWizard(){};  // for testing
-    ConditionWizard(std::vector<sp<ConditionTracker>>& conditionTrackers)
+    explicit ConditionWizard(std::vector<sp<ConditionTracker>>& conditionTrackers)
         : mAllConditions(conditionTrackers){};
 
     virtual ~ConditionWizard(){};
diff --git a/cmds/statsd/src/config/ConfigKey.h b/cmds/statsd/src/config/ConfigKey.h
index dc79519..4cc9393 100644
--- a/cmds/statsd/src/config/ConfigKey.h
+++ b/cmds/statsd/src/config/ConfigKey.h
@@ -33,7 +33,7 @@
 class ConfigKey {
 public:
     ConfigKey();
-    explicit ConfigKey(const ConfigKey& that);
+    ConfigKey(const ConfigKey& that);
     ConfigKey(int uid, const int64_t& id);
     ~ConfigKey();
 
diff --git a/cmds/statsd/src/external/ResourceHealthManagerPuller.h b/cmds/statsd/src/external/ResourceHealthManagerPuller.h
index 9b238eaf5..ba6e6c3 100644
--- a/cmds/statsd/src/external/ResourceHealthManagerPuller.h
+++ b/cmds/statsd/src/external/ResourceHealthManagerPuller.h
@@ -28,7 +28,7 @@
  */
 class ResourceHealthManagerPuller : public StatsPuller {
 public:
-    ResourceHealthManagerPuller(int tagId);
+    explicit ResourceHealthManagerPuller(int tagId);
     bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
 };
 
diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.h b/cmds/statsd/src/external/StatsCompanionServicePuller.h
index 0a49732..a16baf0 100644
--- a/cmds/statsd/src/external/StatsCompanionServicePuller.h
+++ b/cmds/statsd/src/external/StatsCompanionServicePuller.h
@@ -25,7 +25,7 @@
 
 class StatsCompanionServicePuller : public StatsPuller {
 public:
-    StatsCompanionServicePuller(int tagId);
+    explicit StatsCompanionServicePuller(int tagId);
     bool PullInternal(vector<std::shared_ptr<LogEvent> >* data) override;
 
     void SetStatsCompanionService(sp<IStatsCompanionService> statsCompanionService) override;
diff --git a/cmds/statsd/src/external/StatsPuller.h b/cmds/statsd/src/external/StatsPuller.h
index caac677..35be12b 100644
--- a/cmds/statsd/src/external/StatsPuller.h
+++ b/cmds/statsd/src/external/StatsPuller.h
@@ -33,7 +33,7 @@
 
 class StatsPuller : public virtual RefBase {
 public:
-    StatsPuller(const int tagId);
+    explicit StatsPuller(const int tagId);
 
     virtual ~StatsPuller() {}
 
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 24d624d..8a03ac4 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -158,7 +158,7 @@
      * Don't copy, it's slower. If we really need this we can add it but let's try to
      * avoid it.
      */
-    explicit LogEvent(const LogEvent&);
+    LogEvent(const LogEvent&);
 
     /**
      * Parses a log_msg into a LogEvent object.
diff --git a/cmds/statsd/src/socket/StatsSocketListener.h b/cmds/statsd/src/socket/StatsSocketListener.h
index 73e4d33..b8185d2 100644
--- a/cmds/statsd/src/socket/StatsSocketListener.h
+++ b/cmds/statsd/src/socket/StatsSocketListener.h
@@ -35,7 +35,7 @@
 
 class StatsSocketListener : public SocketListener, public virtual android::RefBase {
 public:
-    StatsSocketListener(const sp<LogListener>& listener);
+    explicit StatsSocketListener(const sp<LogListener>& listener);
 
     virtual ~StatsSocketListener();
 
@@ -51,4 +51,4 @@
 };
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 30e9bfb..648ff27 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -2992,7 +2992,6 @@
 Lcom/android/internal/telephony/dataconnection/DcTracker;->onActionIntentDataStallAlarm(Landroid/content/Intent;)V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->onActionIntentProvisioningApnAlarm(Landroid/content/Intent;)V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->onRecordsLoadedOrSubIdChanged()V
-Lcom/android/internal/telephony/dataconnection/DcTracker;->onSetUserDataEnabled(Z)V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->onTrySetupData(Lcom/android/internal/telephony/dataconnection/ApnContext;)Z
 Lcom/android/internal/telephony/dataconnection/DcTracker;->onTrySetupData(Ljava/lang/String;)Z
 Lcom/android/internal/telephony/dataconnection/DcTracker;->registerSettingsObserver()V
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 4714587..49c3dc6 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -187,13 +187,19 @@
      * is for a network to which the connectivity manager was failing over
      * following a disconnect on another network.
      * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}.
+     *
+     * @deprecated See {@link NetworkInfo}.
      */
+    @Deprecated
     public static final String EXTRA_IS_FAILOVER = "isFailover";
     /**
      * The lookup key for a {@link NetworkInfo} object. This is supplied when
      * there is another network that it may be possible to connect to. Retrieve with
      * {@link android.content.Intent#getParcelableExtra(String)}.
+     *
+     * @deprecated See {@link NetworkInfo}.
      */
+    @Deprecated
     public static final String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
     /**
      * The lookup key for a boolean that indicates whether there is a
@@ -214,7 +220,10 @@
      * may be passed up from the lower networking layers, and its
      * meaning may be specific to a particular network type. Retrieve
      * it with {@link android.content.Intent#getStringExtra(String)}.
+     *
+     * @deprecated See {@link NetworkInfo#getExtraInfo()}.
      */
+    @Deprecated
     public static final String EXTRA_EXTRA_INFO = "extraInfo";
     /**
      * The lookup key for an int that provides information about
@@ -895,7 +904,9 @@
      *
      * @return a {@link NetworkInfo} object for the current default network
      *        or {@code null} if no default network is currently active
+     * @deprecated See {@link NetworkInfo}.
      */
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     public NetworkInfo getActiveNetworkInfo() {
         try {
@@ -1079,7 +1090,9 @@
      * @return a {@link NetworkInfo} object for the requested
      *        network or {@code null} if the {@code Network}
      *        is not valid.
+     * @deprecated See {@link NetworkInfo}.
      */
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     public NetworkInfo getNetworkInfo(Network network) {
         return getNetworkInfoForUid(network, Process.myUid(), false);
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 1b9a66c..80517ce 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -161,7 +162,7 @@
     /**
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public LinkProperties() {
     }
 
@@ -195,7 +196,7 @@
      * @param iface The name of the network interface used for this link.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public void setInterfaceName(String iface) {
         mIfaceName = iface;
         ArrayList<RouteInfo> newRoutes = new ArrayList<>(mRoutes.size());
@@ -346,7 +347,7 @@
      *                  object.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public void setLinkAddresses(Collection<LinkAddress> addresses) {
         mLinkAddresses.clear();
         for (LinkAddress address: addresses) {
@@ -392,7 +393,7 @@
      * @param dnsServers The {@link Collection} of DNS servers to set in this object.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public void setDnsServers(Collection<InetAddress> dnsServers) {
         mDnses.clear();
         for (InetAddress dnsServer: dnsServers) {
@@ -529,7 +530,7 @@
      *                domains to search when resolving host names on this link.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public void setDomains(String domains) {
         mDomains = domains;
     }
@@ -552,7 +553,7 @@
      * @param mtu The MTU to use for this link.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public void setMtu(int mtu) {
         mMtu = mtu;
     }
@@ -562,9 +563,7 @@
      * this will return 0.
      *
      * @return The mtu value set for this link.
-     * @hide
      */
-    @UnsupportedAppUsage
     public int getMtu() {
         return mMtu;
     }
@@ -613,7 +612,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public boolean addRoute(RouteInfo route) {
         if (route != null) {
             String routeIface = route.getInterface();
@@ -688,7 +687,7 @@
      * @param proxy A {@link ProxyInfo} defining the HTTP Proxy to use on this link.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public void setHttpProxy(ProxyInfo proxy) {
         mHttpProxy = proxy;
     }
@@ -760,7 +759,7 @@
      * Clears this object to its initial state.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public void clear() {
         mIfaceName = null;
         mLinkAddresses.clear();
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index c41a56c..1b44c92 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -1017,7 +1017,7 @@
      * @return The bearer-specific signal strength.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public int getSignalStrength() {
         return mSignalStrength;
     }
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 1a1d2d334..89d9961 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -28,7 +28,20 @@
  * Describes the status of a network interface.
  * <p>Use {@link ConnectivityManager#getActiveNetworkInfo()} to get an instance that represents
  * the current network connection.
+ *
+ * @deprecated Callers should instead use the {@link ConnectivityManager.NetworkCallback} API to
+ *             learn about connectivity changes, or switch to use
+ *             {@link ConnectivityManager#getNetworkCapabilities} or
+ *             {@link ConnectivityManager#getLinkProperties} to get information synchronously. Keep
+ *             in mind that while callbacks are guaranteed to be called for every event in order,
+ *             synchronous calls have no such constraints, and as such it is unadvisable to use the
+ *             synchronous methods inside the callbacks as they will often not offer a view of
+ *             networking that is consistent (that is: they may return a past or a future state with
+ *             respect to the event being processed by the callback). Instead, callers are advised
+ *             to only use the arguments of the callbacks, possibly memorizing the specific bits of
+ *             information they need to keep from one callback to another.
  */
+@Deprecated
 public class NetworkInfo implements Parcelable {
 
     /**
@@ -52,7 +65,10 @@
      * <tr><td><code>FAILED</code></td><td><code>DISCONNECTED</code></td></tr>
      * <tr><td><code>BLOCKED</code></td><td><code>DISCONNECTED</code></td></tr>
      * </table>
+     *
+     * @deprecated See {@link NetworkInfo}.
      */
+    @Deprecated
     public enum State {
         CONNECTING, CONNECTED, SUSPENDED, DISCONNECTING, DISCONNECTED, UNKNOWN
     }
@@ -61,7 +77,10 @@
      * The fine-grained state of a network connection. This level of detail
      * is probably of interest to few applications. Most should use
      * {@link android.net.NetworkInfo.State State} instead.
+     *
+     * @deprecated See {@link NetworkInfo}.
      */
+    @Deprecated
     public enum DetailedState {
         /** Ready to start data connection setup. */
         IDLE,
@@ -463,8 +482,10 @@
      * Set the extraInfo field.
      * @param extraInfo an optional {@code String} providing addditional network state
      * information passed up from the lower networking layers.
+     * @deprecated See {@link NetworkInfo#getExtraInfo}.
      * @hide
      */
+    @Deprecated
     public void setExtraInfo(String extraInfo) {
         synchronized (this) {
             this.mExtraInfo = extraInfo;
@@ -488,7 +509,10 @@
      * Report the extra information about the network state, if any was
      * provided by the lower networking layers.
      * @return the extra information, or null if not available
+     * @deprecated Use other services e.g. WifiManager to get additional information passed up from
+     *             the lower networking layers.
      */
+    @Deprecated
     public String getExtraInfo() {
         synchronized (this) {
             return mExtraInfo;
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 04b6b44..3b01b03 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.net.NetworkCapabilities.NetCapability;
 import android.net.NetworkCapabilities.Transport;
@@ -344,7 +345,7 @@
          * @param signalStrength the bearer-specific signal strength.
          * @hide
          */
-        @UnsupportedAppUsage
+        @SystemApi
         public Builder setSignalStrength(int signalStrength) {
             mNetworkCapabilities.setSignalStrength(signalStrength);
             return this;
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 2e98d03..1dbe166 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -268,6 +268,13 @@
     public static final int FX_SURFACE_DIM = 0x00020000;
 
     /**
+     * Surface creation flag: Creates a container surface.
+     * This surface will have no buffers and will only be used
+     * as a container for other surfaces, or for its InputInfo.
+     */
+    public static final int FX_SURFACE_CONTAINER = 0x00080000;
+
+    /**
      * Mask used for FX values above.
      *
      */
@@ -523,14 +530,39 @@
          */
         public Builder setColorLayer(boolean isColorLayer) {
             if (isColorLayer) {
-                mFlags |= FX_SURFACE_DIM;
+                setFlags(FX_SURFACE_DIM, FX_SURFACE_MASK);
             } else {
-                mFlags &= ~FX_SURFACE_DIM;
+                setBufferLayer();
             }
             return this;
         }
 
         /**
+         * Indicates whether a 'ContainerLayer' is to be constructed.
+         *
+         * Container layers will not be rendered in any fashion and instead are used
+         * as a parent of renderable layers.
+         *
+         * @param isContainerLayer Whether to create a container layer.
+         */
+        public Builder setContainerLayer(boolean isContainerLayer) {
+            if (isContainerLayer) {
+                setFlags(FX_SURFACE_CONTAINER, FX_SURFACE_MASK);
+            } else {
+                setBufferLayer();
+            }
+            return this;
+        }
+
+        /**
+         * Indicates whether a buffer layer is to be constructed.
+         *
+         */
+        public Builder setBufferLayer() {
+            return setFlags(FX_SURFACE_NORMAL, FX_SURFACE_MASK);
+        }
+
+        /**
          * Set 'Surface creation flags' such as {@link HIDDEN}, {@link SECURE}.
          *
          * TODO: Finish conversion to individual builder methods?
@@ -540,6 +572,11 @@
             mFlags = flags;
             return this;
         }
+
+        private Builder setFlags(int flags, int mask) {
+            mFlags = (mFlags & ~mask) | flags;
+            return this;
+        }
     }
 
     /**
diff --git a/core/java/android/webkit/WebSyncManager.java b/core/java/android/webkit/WebSyncManager.java
index 3fa1b01..e44d6eb 100644
--- a/core/java/android/webkit/WebSyncManager.java
+++ b/core/java/android/webkit/WebSyncManager.java
@@ -26,6 +26,7 @@
 abstract class WebSyncManager implements Runnable {
     protected static final java.lang.String LOGTAG = "websync";
     protected android.webkit.WebViewDatabase mDataBase;
+    @UnsupportedAppUsage
     protected android.os.Handler mHandler;
 
     protected WebSyncManager(Context context, String name) {
diff --git a/core/java/com/android/internal/widget/NumericTextView.java b/core/java/com/android/internal/widget/NumericTextView.java
index 27c5834..d215670 100644
--- a/core/java/com/android/internal/widget/NumericTextView.java
+++ b/core/java/com/android/internal/widget/NumericTextView.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.graphics.Rect;
 import android.util.AttributeSet;
@@ -53,6 +54,7 @@
 
     private OnValueChangedListener mListener;
 
+    @UnsupportedAppUsage
     public NumericTextView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index b5860d8..c81a77d 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -264,7 +264,7 @@
         "libhardware",
         "libhardware_legacy",
         "libselinux",
-        "libicuuc",
+        "libandroidicu",
         "libmedia",
         "libmediametrics",
         "libaudioclient",
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 5a74a24..b085bc9 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -48,7 +48,7 @@
 
 class BitmapWrapper {
 public:
-    BitmapWrapper(Bitmap* bitmap)
+    explicit BitmapWrapper(Bitmap* bitmap)
         : mBitmap(bitmap) { }
 
     void freePixels() {
diff --git a/core/jni/android/graphics/FontUtils.h b/core/jni/android/graphics/FontUtils.h
index 9eaaa49..30fdf24 100644
--- a/core/jni/android/graphics/FontUtils.h
+++ b/core/jni/android/graphics/FontUtils.h
@@ -27,7 +27,7 @@
 namespace android {
 
 struct FontFamilyWrapper {
-  FontFamilyWrapper(std::shared_ptr<minikin::FontFamily>&& family) : family(family) {}
+  explicit FontFamilyWrapper(std::shared_ptr<minikin::FontFamily>&& family) : family(family) {}
   std::shared_ptr<minikin::FontFamily> family;
 };
 
diff --git a/core/jni/android/graphics/GIFMovie.cpp b/core/jni/android/graphics/GIFMovie.cpp
index dd99b37..f84a4bd 100644
--- a/core/jni/android/graphics/GIFMovie.cpp
+++ b/core/jni/android/graphics/GIFMovie.cpp
@@ -21,7 +21,7 @@
 
 class GIFMovie : public Movie {
 public:
-    GIFMovie(SkStream* stream);
+    explicit GIFMovie(SkStream* stream);
     virtual ~GIFMovie();
 
 protected:
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 6c9f463..9963a45 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -20,7 +20,6 @@
 #include "android_media_AudioTrack.h"
 
 #include <nativehelper/JNIHelp.h>
-#include <nativehelper/JniConstants.h>
 #include "core_jni_helpers.h"
 
 #include <utils/Log.h>
diff --git a/core/jni/android_media_DeviceCallback.cpp b/core/jni/android_media_DeviceCallback.cpp
index 108fa00..a1a0351 100644
--- a/core/jni/android_media_DeviceCallback.cpp
+++ b/core/jni/android_media_DeviceCallback.cpp
@@ -20,7 +20,6 @@
 
 #include <utils/Log.h>
 #include <nativehelper/JNIHelp.h>
-#include <nativehelper/JniConstants.h>
 #include "core_jni_helpers.h"
 #include <media/AudioSystem.h>
 
diff --git a/core/jni/android_os_SharedMemory.cpp b/core/jni/android_os_SharedMemory.cpp
index f6e5c7a..c33405d 100644
--- a/core/jni/android_os_SharedMemory.cpp
+++ b/core/jni/android_os_SharedMemory.cpp
@@ -20,8 +20,9 @@
 
 #include <cutils/ashmem.h>
 #include <utils/Log.h>
+
+#include <nativehelper/jni_macros.h>
 #include <nativehelper/JNIHelp.h>
-#include <nativehelper/JniConstants.h>
 #include <nativehelper/ScopedLocalRef.h>
 
 #include <algorithm>
@@ -31,10 +32,10 @@
 
 namespace {
 
-static void throwErrnoException(JNIEnv* env, const char* functionName, int error) {
-    static jmethodID ctor = env->GetMethodID(JniConstants::errnoExceptionClass,
-            "<init>", "(Ljava/lang/String;I)V");
+jclass errnoExceptionClass;
+jmethodID errnoExceptionCtor;  // MethodID for ErrnoException.<init>(String,I)
 
+void throwErrnoException(JNIEnv* env, const char* functionName, int error) {
     ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName));
     if (detailMessage.get() == NULL) {
         // Not really much we can do here. We're probably dead in the water,
@@ -42,12 +43,14 @@
         env->ExceptionClear();
     }
 
-    jobject exception = env->NewObject(JniConstants::errnoExceptionClass, ctor,
-            detailMessage.get(), error);
+    jobject exception = env->NewObject(errnoExceptionClass,
+                                       errnoExceptionCtor,
+                                       detailMessage.get(),
+                                       error);
     env->Throw(reinterpret_cast<jthrowable>(exception));
 }
 
-static jobject SharedMemory_create(JNIEnv* env, jobject, jstring jname, jint size) {
+jobject SharedMemory_nCreate(JNIEnv* env, jobject, jstring jname, jint size) {
 
     // Name is optional so we can't use ScopedUtfChars for this as it throws NPE on null
     const char* name = jname ? env->GetStringUTFChars(jname, nullptr) : nullptr;
@@ -69,7 +72,7 @@
     return jniCreateFileDescriptor(env, fd);
 }
 
-static jint SharedMemory_getSize(JNIEnv* env, jobject, jobject fileDescriptor) {
+jint SharedMemory_nGetSize(JNIEnv* env, jobject, jobject fileDescriptor) {
     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     if (!ashmem_valid(fd)) {
         return -1;
@@ -78,7 +81,7 @@
     return static_cast<jint>(std::min(size, static_cast<size_t>(std::numeric_limits<jint>::max())));
 }
 
-static jint SharedMemory_setProt(JNIEnv* env, jobject, jobject fileDescriptor, jint prot) {
+jint SharedMemory_nSetProt(JNIEnv* env, jobject, jobject fileDescriptor, jint prot) {
     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     int err = 0;
     if (ashmem_set_prot_region(fd, prot)) {
@@ -87,18 +90,21 @@
     return err;
 }
 
-static const JNINativeMethod methods[] = {
-    {"nCreate", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)SharedMemory_create},
-    {"nGetSize", "(Ljava/io/FileDescriptor;)I", (void*)SharedMemory_getSize},
-    {"nSetProt", "(Ljava/io/FileDescriptor;I)I", (void*)SharedMemory_setProt},
+const JNINativeMethod methods[] = {
+  NATIVE_METHOD(SharedMemory, nCreate, "(Ljava/lang/String;I)Ljava/io/FileDescriptor;"),
+  NATIVE_METHOD(SharedMemory, nGetSize, "(Ljava/io/FileDescriptor;)I"),
+  NATIVE_METHOD(SharedMemory, nSetProt, "(Ljava/io/FileDescriptor;I)I")
 };
 
 } // anonymous namespace
 
 namespace android {
 
-int register_android_os_SharedMemory(JNIEnv* env)
-{
+int register_android_os_SharedMemory(JNIEnv* env) {
+    errnoExceptionClass =
+        MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/system/ErrnoException"));
+    errnoExceptionCtor =
+        GetMethodIDOrDie(env, errnoExceptionClass, "<init>", "(Ljava/lang/String;I)V");
     return RegisterMethodsOrDie(env, "android/os/SharedMemory", methods, NELEM(methods));
 }
 
diff --git a/core/jni/android_util_jar_StrictJarFile.cpp b/core/jni/android_util_jar_StrictJarFile.cpp
index 4ab8db4..182a621 100644
--- a/core/jni/android_util_jar_StrictJarFile.cpp
+++ b/core/jni/android_util_jar_StrictJarFile.cpp
@@ -22,24 +22,26 @@
 
 #include <log/log.h>
 
+#include <nativehelper/jni_macros.h>
 #include <nativehelper/JNIHelp.h>
-#include <nativehelper/JniConstants.h>
 #include <nativehelper/ScopedLocalRef.h>
 #include <nativehelper/ScopedUtfChars.h>
-#include "jni.h"
+
+#include "core_jni_helpers.h"
 #include "ziparchive/zip_archive.h"
 
-namespace android {
+namespace {
 
+jclass zipEntryClass;
 // The method ID for ZipEntry.<init>(String,String,JJJIII[BJJ)
-static jmethodID zipEntryCtor;
+jmethodID zipEntryCtor;
 
-static void throwIoException(JNIEnv* env, const int32_t errorCode) {
+void throwIoException(JNIEnv* env, const int32_t errorCode) {
   jniThrowException(env, "java/io/IOException", ErrorCodeString(errorCode));
 }
 
-static jobject newZipEntry(JNIEnv* env, const ZipEntry& entry, jstring entryName) {
-  return env->NewObject(JniConstants::zipEntryClass,
+jobject newZipEntry(JNIEnv* env, const ZipEntry& entry, jstring entryName) {
+  return env->NewObject(zipEntryClass,
                         zipEntryCtor,
                         entryName,
                         NULL,  // comment
@@ -52,7 +54,7 @@
                         static_cast<jlong>(entry.offset));
 }
 
-static jlong StrictJarFile_nativeOpenJarFile(JNIEnv* env, jobject, jstring name, jint fd) {
+jlong StrictJarFile_nativeOpenJarFile(JNIEnv* env, jobject, jstring name, jint fd) {
   // Name argument is used for logging, and can be any string.
   ScopedUtfChars nameChars(env, name);
   if (nameChars.c_str() == NULL) {
@@ -90,7 +92,7 @@
 };
 
 
-static jlong StrictJarFile_nativeStartIteration(JNIEnv* env, jobject, jlong nativeHandle,
+jlong StrictJarFile_nativeStartIteration(JNIEnv* env, jobject, jlong nativeHandle,
                                                 jstring prefix) {
   ScopedUtfChars prefixChars(env, prefix);
   if (prefixChars.c_str() == NULL) {
@@ -116,7 +118,7 @@
   return reinterpret_cast<jlong>(handle);
 }
 
-static jobject StrictJarFile_nativeNextEntry(JNIEnv* env, jobject, jlong iterationHandle) {
+jobject StrictJarFile_nativeNextEntry(JNIEnv* env, jobject, jlong iterationHandle) {
   ZipEntry data;
   ZipString entryName;
 
@@ -135,7 +137,7 @@
   return newZipEntry(env, data, entryNameString.get());
 }
 
-static jobject StrictJarFile_nativeFindEntry(JNIEnv* env, jobject, jlong nativeHandle,
+jobject StrictJarFile_nativeFindEntry(JNIEnv* env, jobject, jlong nativeHandle,
                                              jstring entryName) {
   ScopedUtfChars entryNameChars(env, entryName);
   if (entryNameChars.c_str() == NULL) {
@@ -152,11 +154,11 @@
   return newZipEntry(env, data, entryName);
 }
 
-static void StrictJarFile_nativeClose(JNIEnv*, jobject, jlong nativeHandle) {
+void StrictJarFile_nativeClose(JNIEnv*, jobject, jlong nativeHandle) {
   CloseArchive(reinterpret_cast<ZipArchiveHandle>(nativeHandle));
 }
 
-static JNINativeMethod gMethods[] = {
+JNINativeMethod gMethods[] = {
   NATIVE_METHOD(StrictJarFile, nativeOpenJarFile, "(Ljava/lang/String;I)J"),
   NATIVE_METHOD(StrictJarFile, nativeStartIteration, "(JLjava/lang/String;)J"),
   NATIVE_METHOD(StrictJarFile, nativeNextEntry, "(J)Ljava/util/zip/ZipEntry;"),
@@ -164,14 +166,15 @@
   NATIVE_METHOD(StrictJarFile, nativeClose, "(J)V"),
 };
 
+}  // namespace
+
+namespace android {
+
 int register_android_util_jar_StrictJarFile(JNIEnv* env) {
-  jniRegisterNativeMethods(env, "android/util/jar/StrictJarFile", gMethods, NELEM(gMethods));
-
-  zipEntryCtor = env->GetMethodID(JniConstants::zipEntryClass, "<init>",
-      "(Ljava/lang/String;Ljava/lang/String;JJJII[BJ)V");
-  LOG_ALWAYS_FATAL_IF(zipEntryCtor == NULL, "Unable to find ZipEntry.<init>");
-
-  return 0;
+  zipEntryClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/util/zip/ZipEntry"));
+  zipEntryCtor = GetMethodIDOrDie(env, zipEntryClass, "<init>",
+                                  "(Ljava/lang/String;Ljava/lang/String;JJJII[BJ)V");
+  return jniRegisterNativeMethods(env, "android/util/jar/StrictJarFile", gMethods, NELEM(gMethods));
 }
 
 }; // namespace android
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index a03e929..d8d919d 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -148,7 +148,7 @@
   const bool is_sock;
 
  private:
-  FileDescriptorInfo(int fd);
+  explicit FileDescriptorInfo(int fd);
 
   FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
                      int fd_flags, int fs_flags, off_t offset);
diff --git a/core/jni/fd_utils.h b/core/jni/fd_utils.h
index a3570d7..09022a2 100644
--- a/core/jni/fd_utils.h
+++ b/core/jni/fd_utils.h
@@ -86,7 +86,7 @@
   bool ReopenOrDetach(std::string* error_msg);
 
  private:
-  FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map);
+  explicit FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map);
 
   bool RestatInternal(std::set<int>& open_fds, std::string* error_msg);
 
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 0082f4b..c8bd847 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -33,6 +33,10 @@
         <permission name="android.permission.CRYPT_KEEPER"/>
     </privapp-permissions>
 
+    <privapp-permissions package="com.android.carrierconfig">
+        <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+    </privapp-permissions>
+
     <privapp-permissions package="com.android.cellbroadcastreceiver">
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.MANAGE_USERS"/>
@@ -315,6 +319,8 @@
         <permission name="android.permission.PACKAGE_USAGE_STATS" />
         <permission name="android.permission.READ_FRAME_BUFFER"/>
         <permission name="android.permission.READ_LOWPAN_CREDENTIAL"/>
+        <!-- Needed for test only -->
+        <permission name="android.permission.READ_PRECISE_PHONE_STATE" />
         <permission name="android.permission.REAL_GET_TASKS"/>
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.REGISTER_CALL_PROVIDER"/>
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 6ac52d1..36b7e37 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -54,6 +54,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.security.InvalidKeyException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
@@ -303,13 +304,14 @@
     }
 
     /**
-     * List uids of all keys that are auth bound to the current user. 
+     * List uids of all keys that are auth bound to the current user.
      * Only system is allowed to call this method.
      */
     @UnsupportedAppUsage
     public int[] listUidsOfAuthBoundKeys() {
-        final int MAX_RESULT_SIZE = 100;
-        int[] uidsOut = new int[MAX_RESULT_SIZE];
+        // uids are returned as a list of strings because list of integers
+        // as an output parameter is not supported by aidl-cpp.
+        List<String> uidsOut = new ArrayList<>();
         try {
             int rc = mBinder.listUidsOfAuthBoundKeys(uidsOut);
             if (rc != NO_ERROR) {
@@ -323,8 +325,8 @@
             Log.w(TAG, "KeyStore exception", e);
             return null;
         }
-        // Remove any 0 entries
-        return Arrays.stream(uidsOut).filter(x -> x > 0).toArray();
+        // Turn list of strings into an array of uid integers.
+        return uidsOut.stream().mapToInt(Integer::parseInt).toArray();
    }
 
     public String[] list(String prefix) {
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index 38ad9c0..e9fba3a 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -30,7 +30,7 @@
 
 class SkiaPipeline : public renderthread::IRenderPipeline {
 public:
-    SkiaPipeline(renderthread::RenderThread& thread);
+    explicit SkiaPipeline(renderthread::RenderThread& thread);
     virtual ~SkiaPipeline();
 
     TaskManager* getTaskManager() override;
diff --git a/libs/hwui/pipeline/skia/SkiaProfileRenderer.h b/libs/hwui/pipeline/skia/SkiaProfileRenderer.h
index 5ae7d6b..3233c8d 100644
--- a/libs/hwui/pipeline/skia/SkiaProfileRenderer.h
+++ b/libs/hwui/pipeline/skia/SkiaProfileRenderer.h
@@ -23,7 +23,7 @@
 
 class SkiaProfileRenderer : public IProfileRenderer {
 public:
-    SkiaProfileRenderer(SkCanvas* canvas) : mCanvas(canvas) {}
+    explicit SkiaProfileRenderer(SkCanvas* canvas) : mCanvas(canvas) {}
 
     void drawRect(float left, float top, float right, float bottom, const SkPaint& paint) override;
     void drawRects(const float* rects, int count, const SkPaint& paint) override;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index 03b4c79..3d00386 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -25,7 +25,7 @@
 
 class SkiaVulkanPipeline : public SkiaPipeline {
 public:
-    SkiaVulkanPipeline(renderthread::RenderThread& thread);
+    explicit SkiaVulkanPipeline(renderthread::RenderThread& thread);
     virtual ~SkiaVulkanPipeline() {}
 
     renderthread::MakeCurrentResult makeCurrent() override;
diff --git a/libs/hwui/pipeline/skia/VectorDrawableAtlas.h b/libs/hwui/pipeline/skia/VectorDrawableAtlas.h
index 74e48ce..5e892aa 100644
--- a/libs/hwui/pipeline/skia/VectorDrawableAtlas.h
+++ b/libs/hwui/pipeline/skia/VectorDrawableAtlas.h
@@ -62,8 +62,8 @@
 public:
     enum class StorageMode { allowSharedSurface, disallowSharedSurface };
 
-    VectorDrawableAtlas(size_t surfaceArea,
-                        StorageMode storageMode = StorageMode::allowSharedSurface);
+    explicit VectorDrawableAtlas(size_t surfaceArea,
+                                 StorageMode storageMode = StorageMode::allowSharedSurface);
 
     /**
      * "prepareForDraw" may allocate a new surface if needed. It may schedule to repack the
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index 7d73352..78d2539 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -59,7 +59,7 @@
 private:
     friend class RenderThread;
 
-    CacheManager(const DisplayInfo& display);
+    explicit CacheManager(const DisplayInfo& display);
 
     void reset(sk_sp<GrContext> grContext);
     void destroy();
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index c319c9e..ea69704 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -127,6 +127,7 @@
             fPtr = ptr;
             return *this;
         }
+        // NOLINTNEXTLINE(google-explicit-constructor)
         operator FNPTR_TYPE() const { return fPtr; }
 
     private:
diff --git a/libs/incident/include/android/os/IncidentReportArgs.h b/libs/incident/include/android/os/IncidentReportArgs.h
index c56f689..ee1e33c 100644
--- a/libs/incident/include/android/os/IncidentReportArgs.h
+++ b/libs/incident/include/android/os/IncidentReportArgs.h
@@ -40,7 +40,7 @@
 class IncidentReportArgs : public Parcelable {
 public:
     IncidentReportArgs();
-    explicit IncidentReportArgs(const IncidentReportArgs& that);
+    IncidentReportArgs(const IncidentReportArgs& that);
     virtual ~IncidentReportArgs();
 
     virtual status_t writeToParcel(Parcel* out) const;
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index adeff5d..9306219 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -26,6 +26,7 @@
     <uses-permission android:name="android.permission.SEND_SMS" />
     <uses-permission android:name="android.permission.CALL_PHONE" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
     <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
     <uses-permission android:name="android.permission.READ_CONTACTS" />
     <uses-permission android:name="android.permission.WRITE_CONTACTS" />
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 66ae47c..7b29fe5 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -210,6 +210,10 @@
 
     private PreciseCallState mPreciseCallState = new PreciseCallState();
 
+    private int mCallDisconnectCause = DisconnectCause.NOT_VALID;
+
+    private int mCallPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
+
     private boolean mCarrierNetworkChangeState = false;
 
     private PhoneCapability mPhoneCapability = null;
@@ -708,6 +712,14 @@
                             remove(r.binder);
                         }
                     }
+                    if ((events & PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES) != 0) {
+                        try {
+                            r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause,
+                                    mCallPreciseDisconnectCause);
+                        } catch (RemoteException ex) {
+                            remove(r.binder);
+                        }
+                    }
                     if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
                         try {
                             r.callback.onPreciseDataConnectionStateChanged(
@@ -1478,9 +1490,8 @@
             }
             handleRemoveListLocked();
         }
-        broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState, backgroundCallState,
-                DisconnectCause.NOT_VALID,
-                PreciseDisconnectCause.NOT_VALID);
+        broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState,
+                backgroundCallState);
     }
 
     public void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause) {
@@ -1488,12 +1499,14 @@
             return;
         }
         synchronized (mRecords) {
-            mPreciseCallState = new PreciseCallState(mRingingCallState, mForegroundCallState,
-                    mBackgroundCallState, disconnectCause, preciseDisconnectCause);
+            mCallDisconnectCause = disconnectCause;
+            mCallPreciseDisconnectCause = preciseDisconnectCause;
             for (Record r : mRecords) {
-                if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_PRECISE_CALL_STATE)) {
+                if (r.matchPhoneStateListenerEvent(PhoneStateListener
+                        .LISTEN_CALL_DISCONNECT_CAUSES)) {
                     try {
-                        r.callback.onPreciseCallStateChanged(mPreciseCallState);
+                        r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause,
+                                mCallPreciseDisconnectCause);
                     } catch (RemoteException ex) {
                         mRemoveList.add(r.binder);
                     }
@@ -1501,8 +1514,6 @@
             }
             handleRemoveListLocked();
         }
-        broadcastPreciseCallStateChanged(mRingingCallState, mForegroundCallState,
-                mBackgroundCallState, disconnectCause, preciseDisconnectCause);
     }
 
     public void notifyPreciseDataConnectionFailed(String reason, String apnType,
@@ -1703,6 +1714,8 @@
             }
             pw.println("mPreciseDataConnectionState=" + mPreciseDataConnectionState);
             pw.println("mPreciseCallState=" + mPreciseCallState);
+            pw.println("mCallDisconnectCause=" + mCallDisconnectCause);
+            pw.println("mCallPreciseDisconnectCause=" + mCallPreciseDisconnectCause);
             pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState);
             pw.println("mRingingCallState=" + mRingingCallState);
             pw.println("mForegroundCallState=" + mForegroundCallState);
@@ -1877,13 +1890,11 @@
     }
 
     private void broadcastPreciseCallStateChanged(int ringingCallState, int foregroundCallState,
-            int backgroundCallState, int disconnectCause, int preciseDisconnectCause) {
+            int backgroundCallState) {
         Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_CALL_STATE_CHANGED);
         intent.putExtra(TelephonyManager.EXTRA_RINGING_CALL_STATE, ringingCallState);
         intent.putExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, foregroundCallState);
         intent.putExtra(TelephonyManager.EXTRA_BACKGROUND_CALL_STATE, backgroundCallState);
-        intent.putExtra(TelephonyManager.EXTRA_DISCONNECT_CAUSE, disconnectCause);
-        intent.putExtra(TelephonyManager.EXTRA_PRECISE_DISCONNECT_CAUSE, preciseDisconnectCause);
         mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
                 android.Manifest.permission.READ_PRECISE_PHONE_STATE);
     }
@@ -1964,6 +1975,11 @@
         }
 
 
+        if ((events & PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES) != 0) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
+        }
+
         return true;
     }
 
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 79c98e5..2649807 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -15,7 +15,7 @@
 jjaggi@google.com
 racarr@google.com
 chaviw@google.com
-brycelee@google.com
+vishnun@google.com
 akulian@google.com
 roosa@google.com
 
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index bf95210..9684f4c 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -944,6 +944,10 @@
     private class WaitingForNextProbeState extends State {
         @Override
         public void enter() {
+            scheduleNextProbe();
+        }
+
+        private void scheduleNextProbe() {
             final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
             sendMessageDelayed(msg, mReevaluateDelayMs);
             mReevaluateDelayMs *= 2;
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index c370959..3ea9810 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -43,8 +43,6 @@
 import com.android.net.IProxyPortListener;
 import com.android.net.IProxyService;
 
-import libcore.io.Streams;
-
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.net.URL;
@@ -71,6 +69,11 @@
     private static final int DELAY_LONG = 4;
     private static final long MAX_PAC_SIZE = 20 * 1000 * 1000;
 
+    // Return values for #setCurrentProxyScriptUrl
+    enum ToSendOrNotToSendBroadcast {
+        DONT_SEND_BROADCAST, DO_SEND_BROADCAST
+    }
+
     private String mCurrentPac;
     @GuardedBy("mProxyLock")
     private volatile Uri mPacUrl = Uri.EMPTY;
@@ -171,13 +174,13 @@
      * PacManager will trigger a new broadcast when it is ready.
      *
      * @param proxy Proxy information that is about to be broadcast.
-     * @return Returns true when the broadcast should not be sent
+     * @return Returns whether the broadcast should be sent : either DO_ or DONT_SEND_BROADCAST
      */
-    synchronized boolean setCurrentProxyScriptUrl(ProxyInfo proxy) {
+    synchronized ToSendOrNotToSendBroadcast setCurrentProxyScriptUrl(ProxyInfo proxy) {
         if (!Uri.EMPTY.equals(proxy.getPacFileUrl())) {
             if (proxy.getPacFileUrl().equals(mPacUrl) && (proxy.getPort() > 0)) {
                 // Allow to send broadcast, nothing to do.
-                return false;
+                return ToSendOrNotToSendBroadcast.DO_SEND_BROADCAST;
             }
             mPacUrl = proxy.getPacFileUrl();
             mCurrentDelay = DELAY_1;
@@ -185,7 +188,7 @@
             mHasDownloaded = false;
             getAlarmManager().cancel(mPacRefreshIntent);
             bind();
-            return true;
+            return ToSendOrNotToSendBroadcast.DONT_SEND_BROADCAST;
         } else {
             getAlarmManager().cancel(mPacRefreshIntent);
             synchronized (mProxyLock) {
@@ -201,7 +204,7 @@
                     }
                 }
             }
-            return false;
+            return ToSendOrNotToSendBroadcast.DO_SEND_BROADCAST;
         }
     }
 
@@ -296,7 +299,7 @@
         Intent intent = new Intent();
         intent.setClassName(PAC_PACKAGE, PAC_SERVICE);
         if ((mProxyConnection != null) && (mConnection != null)) {
-            // Already bound no need to bind again, just download the new file.
+            // Already bound: no need to bind again, just download the new file.
             mNetThreadHandler.post(mPacDownloader);
             return;
         }
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java
index 15468ff..fdddccd 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java
@@ -208,7 +208,10 @@
     public void sendProxyBroadcast() {
         final ProxyInfo defaultProxy = getDefaultProxy();
         final ProxyInfo proxyInfo = null != defaultProxy ? defaultProxy : new ProxyInfo("", 0, "");
-        if (mPacManager.setCurrentProxyScriptUrl(proxyInfo)) return;
+        if (mPacManager.setCurrentProxyScriptUrl(proxyInfo)
+                == PacManager.ToSendOrNotToSendBroadcast.DONT_SEND_BROADCAST) {
+            return;
+        }
         if (DBG) Slog.d(TAG, "sending Proxy Broadcast for " + proxyInfo);
         Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index cc640f0..5e1ed03 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -404,12 +404,17 @@
                 + " dexoptFlags=" + printDexoptFlags(dexoptFlags)
                 + " target-filter=" + compilerFilter);
 
-        // TODO(calin): b/64530081 b/66984396. Use SKIP_SHARED_LIBRARY_CHECK for the context
-        // (instead of dexUseInfo.getClassLoaderContext()) in order to compile secondary dex files
-        // in isolation (and avoid to extract/verify the main apk if it's in the class path).
-        // Note this trades correctness for performance since the resulting slow down is
-        // unacceptable in some cases until b/64530081 is fixed.
-        String classLoaderContext = SKIP_SHARED_LIBRARY_CHECK;
+        String classLoaderContext;
+        if (dexUseInfo.isUnknownClassLoaderContext() || dexUseInfo.isVariableClassLoaderContext()) {
+            // If we have an unknown (not yet set), or a variable class loader chain, compile
+            // without a context and mark the oat file with SKIP_SHARED_LIBRARY_CHECK. Note that
+            // this might lead to a incorrect compilation.
+            // TODO(calin): We should just extract in this case.
+            classLoaderContext = SKIP_SHARED_LIBRARY_CHECK;
+        } else {
+            classLoaderContext = dexUseInfo.getClassLoaderContext();
+        }
+
         int reason = options.getCompilationReason();
         try {
             for (String isa : dexUseInfo.getLoaderIsas()) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 7856bcf..e5b9030 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -627,9 +627,13 @@
                     pw.print("=");
                 }
                 pw.print(info.packageName);
-                if (showVersionCode && !isApex) {
+                if (showVersionCode) {
                     pw.print(" versionCode:");
-                    pw.print(info.applicationInfo.versionCode);
+                    if (info.applicationInfo != null) {
+                        pw.print(info.applicationInfo.versionCode);
+                    } else {
+                        pw.print(info.versionCode);
+                    }
                 }
                 if (listInstaller && !isApex) {
                     pw.print("  installer=");
@@ -2701,7 +2705,7 @@
         pw.println("    Prints all system libraries.");
         pw.println("");
         pw.println("  list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] ");
-        pw.println("      [--apex-only] [--uid UID] [--user USER_ID] [FILTER]");
+        pw.println("      [--show-versioncode] [--apex-only] [--uid UID] [--user USER_ID] [FILTER]");
         pw.println("    Prints all packages; optionally only those whose name contains");
         pw.println("    the text in FILTER.  Options are:");
         pw.println("      -f: see their associated file");
@@ -2714,6 +2718,7 @@
         pw.println("      -l: ignored (used for compatibility with older releases)");
         pw.println("      -U: also show the package UID");
         pw.println("      -u: also include uninstalled packages");
+        pw.println("      --show-versioncode: also show the version code");
         pw.println("      --apex-only: only show APEX packages");
         pw.println("      --uid UID: filter to only show packages with the given UID");
         pw.println("      --user USER_ID: only list packages belonging to the given user");
diff --git a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
index 519a20d..a194f57 100644
--- a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
+++ b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
@@ -863,15 +863,13 @@
 
         public String getClassLoaderContext() { return mClassLoaderContext; }
 
-        @VisibleForTesting
-        /* package */ boolean isUnknownClassLoaderContext() {
+        public boolean isUnknownClassLoaderContext() {
             // The class loader context may be unknown if we loaded the data from a previous version
             // which didn't save the context.
             return UNKNOWN_CLASS_LOADER_CONTEXT.equals(mClassLoaderContext);
         }
 
-        @VisibleForTesting
-        /* package */ boolean isVariableClassLoaderContext() {
+        public boolean isVariableClassLoaderContext() {
             return VARIABLE_CLASS_LOADER_CONTEXT.equals(mClassLoaderContext);
         }
     }
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index ad92f81..bef974a 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -69,6 +69,7 @@
                 .setFormat(PixelFormat.TRANSLUCENT)
                 .setMetadata(appToken.windowType,
                         window != null ? window.mOwnerUid : Binder.getCallingUid())
+                .setBufferLayer()
                 .build();
 
         if (SHOW_TRANSACTIONS) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2941e93..6700a12 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -773,7 +773,8 @@
 
         final SurfaceControl.Builder b = mService.makeSurfaceBuilder(mSession)
                 .setSize(mSurfaceSize, mSurfaceSize)
-                .setOpaque(true);
+                .setOpaque(true)
+                .setContainerLayer(true);
         mWindowingLayer = b.setName("Display Root").build();
         mOverlayLayer = b.setName("Display Overlays").build();
 
@@ -3890,7 +3891,7 @@
         SurfaceSession s = child != null ? child.getSession() : getSession();
         final SurfaceControl.Builder b = mService.makeSurfaceBuilder(s);
         b.setSize(mSurfaceSize, mSurfaceSize);
-
+        b.setContainerLayer(true);
         if (child == null) {
             return b;
         }
diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS
index fff42c5..8dda485 100644
--- a/services/core/java/com/android/server/wm/OWNERS
+++ b/services/core/java/com/android/server/wm/OWNERS
@@ -2,6 +2,6 @@
 jjaggi@google.com
 racarr@google.com
 chaviw@google.com
-brycelee@google.com
+vishnun@google.com
 akulian@google.com
 roosa@google.com
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 66c8cca..4548cec 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -104,6 +104,7 @@
 
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
         final SurfaceControl.Builder b = win.makeSurface()
+                .setBufferLayer()
                 .setParent(win.getSurfaceControl())
                 .setName(name)
                 .setSize(w, h)
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index 06059c8..757d863 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -73,7 +73,7 @@
   bool operator<(const TypeDescriptor& rhs) const { return descriptor_ < rhs.descriptor_; }
 
  private:
-  TypeDescriptor(std::string descriptor) : descriptor_{descriptor} {}
+  explicit TypeDescriptor(std::string descriptor) : descriptor_{descriptor} {}
 
   const std::string descriptor_;
 };
@@ -83,7 +83,7 @@
 class Prototype {
  public:
   template <typename... TypeDescriptors>
-  Prototype(TypeDescriptor return_type, TypeDescriptors... param_types)
+  explicit Prototype(TypeDescriptor return_type, TypeDescriptors... param_types)
       : return_type_{return_type}, param_types_{param_types...} {}
 
   // Encode this prototype into the dex file.
diff --git a/startop/view_compiler/main.cc b/startop/view_compiler/main.cc
index 9351dc3..55bfdc7 100644
--- a/startop/view_compiler/main.cc
+++ b/startop/view_compiler/main.cc
@@ -42,7 +42,7 @@
 
 class ViewCompilerXmlVisitor : public XMLVisitor {
  public:
-  ViewCompilerXmlVisitor(JavaLangViewBuilder* builder) : builder_(builder) {}
+  explicit ViewCompilerXmlVisitor(JavaLangViewBuilder* builder) : builder_(builder) {}
 
   bool VisitEnter(const XMLDocument& /*doc*/) override {
     builder_->Start();
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 0245768dd..3e4482e 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -2668,10 +2668,26 @@
 
         /**
          * The {@code content://} style URL for this table.
+         * For MSIM, this will return APNs for the default subscription
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId for MSIM,
+         * use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.
          */
         public static final Uri CONTENT_URI = Uri.parse("content://telephony/carriers");
 
         /**
+         * The {@code content://} style URL for this table. Used for APN query based on current
+         * subscription. Instead of specifying carrier matching information in the selection,
+         * this API will return all matching APNs from current subscription carrier and queries
+         * will be applied on top of that. If there is no match for MVNO (Mobile Virtual Network
+         * Operator) APNs, return APNs from its MNO (based on mccmnc) instead. For MSIM, this will
+         * return APNs for the default subscription
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId for MSIM,
+         * use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.
+         */
+        public static final Uri SIM_APN_URI = Uri.parse(
+                "content://telephony/carriers/sim_apn_list");
+
+        /**
          * The {@code content://} style URL to be called from DevicePolicyManagerService,
          * can manage DPC-owned APNs.
          * @hide
@@ -2681,7 +2697,9 @@
         /**
          * The {@code content://} style URL to be called from Telephony to query APNs.
          * When DPC-owned APNs are enforced, only DPC-owned APNs are returned, otherwise only
-         * non-DPC-owned APNs are returned.
+         * non-DPC-owned APNs are returned. For MSIM, this will return APNs for the default
+         * subscription {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId
+         * for MSIM, use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.
          * @hide
          */
         public static final Uri FILTERED_URI = Uri.parse("content://telephony/carriers/filtered");
@@ -2695,13 +2713,6 @@
                 "content://telephony/carriers/enforce_managed");
 
         /**
-         * The {@code content://} style URL to be called from Telephony to query current APNs.
-         * @hide
-         */
-        public static final Uri SIM_APN_LIST = Uri.parse(
-                "content://telephony/carriers/sim_apn_list");
-
-        /**
          * The column name for ENFORCE_MANAGED_URI, indicates whether DPC-owned APNs are enforced.
          * @hide
          */
@@ -2775,18 +2786,30 @@
         /**
          * Mobile Country Code (MCC).
          * <P>Type: TEXT</P>
+         * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+         * matching APNs based on current subscription carrier, thus no need to specify MCC and
+         * other carrier matching information. In the future, Android will not support MCC for
+         * APN query.
          */
         public static final String MCC = "mcc";
 
         /**
          * Mobile Network Code (MNC).
          * <P>Type: TEXT</P>
+         * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+         * matching APNs based on current subscription carrier, thus no need to specify MNC and
+         * other carrier matching information. In the future, Android will not support MNC for
+         * APN query.
          */
         public static final String MNC = "mnc";
 
         /**
          * Numeric operator ID (as String). Usually {@code MCC + MNC}.
          * <P>Type: TEXT</P>
+         * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+         * matching APNs based on current subscription carrier, thus no need to specify Numeric
+         * and other carrier matching information. In the future, Android will not support Numeric
+         * for APN query.
          */
         public static final String NUMERIC = "numeric";
 
@@ -2867,6 +2890,10 @@
          * MVNO type:
          * {@code SPN (Service Provider Name), IMSI, GID (Group Identifier Level 1)}.
          * <P>Type: TEXT</P>
+         * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+         * matching APNs based on current subscription carrier, thus no need to specify MVNO_TYPE
+         * and other carrier matching information. In the future, Android will not support MVNO_TYPE
+         * for APN query.
          */
         public static final String MVNO_TYPE = "mvno_type";
 
@@ -2879,6 +2906,10 @@
          *     <li>GID: 4E, 33, ...</li>
          * </ul>
          * <P>Type: TEXT</P>
+         * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+         * matching APNs based on current subscription carrier, thus no need to specify
+         * MVNO_MATCH_DATA and other carrier matching information. In the future, Android will not
+         * support MVNO_MATCH_DATA for APN query.
          */
         public static final String MVNO_MATCH_DATA = "mvno_match_data";
 
@@ -3087,7 +3118,6 @@
         })
         @Retention(RetentionPolicy.SOURCE)
         public @interface EditStatus {}
-
     }
 
     /**
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 4b7d107..4561ea3 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2000,6 +2000,8 @@
      * Determine whether to use only RSRP for the number of LTE signal bars.
      * @hide
      */
+    // FIXME: this key and related keys must not be exposed without a consistent philosophy for
+    // all RATs.
     public static final String KEY_USE_ONLY_RSRP_FOR_LTE_SIGNAL_BAR_BOOL =
             "use_only_rsrp_for_lte_signal_bar_bool";
 
@@ -2243,6 +2245,8 @@
      * Currently this only supports the value "rscp"
      * @hide
      */
+    // FIXME: this key and related keys must not be exposed without a consistent philosophy for
+    // all RATs.
     public static final String KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING =
             "wcdma_default_signal_strength_measurement_string";
 
diff --git a/telephony/java/android/telephony/CellSignalStrength.java b/telephony/java/android/telephony/CellSignalStrength.java
index afa4922..a18275f 100644
--- a/telephony/java/android/telephony/CellSignalStrength.java
+++ b/telephony/java/android/telephony/CellSignalStrength.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import android.os.PersistableBundle;
+
 /**
  * Abstract base class for cell phone signal strength related information.
  */
@@ -80,9 +82,74 @@
      */
     public abstract CellSignalStrength copy();
 
+    /**
+     * Checks and returns whether there are any non-default values in this CellSignalStrength.
+     *
+     * Checks all the values in the subclass of CellSignalStrength and returns true if any of them
+     * have been set to a value other than their default.
+     *
+     * @hide
+     */
+    public abstract boolean isValid();
+
     @Override
     public abstract int hashCode();
 
     @Override
     public abstract boolean equals (Object o);
+
+    /**
+     * Calculate and set the carrier-influenced values such as the signal "Level".
+     *
+     * @hide
+     */
+    public abstract void updateLevel(PersistableBundle cc, ServiceState ss);
+
+    // Range for RSSI in ASU (0-31, 99) as defined in TS 27.007 8.69
+    /** @hide */
+    protected static final int getRssiDbmFromAsu(int asu) {
+        if (asu > 31 || asu < 0) return CellInfo.UNAVAILABLE;
+        return -113 + (2 * asu);
+    }
+
+    // Range for RSSI in ASU (0-31, 99) as defined in TS 27.007 8.69
+    /** @hide */
+    protected static final int getAsuFromRssiDbm(int dbm) {
+        if (dbm == CellInfo.UNAVAILABLE) return 99;
+        return (dbm / 2) + 113;
+    }
+
+    // Range for RSCP in ASU (0-96, 255) as defined in TS 27.007 8.69
+    /** @hide */
+    protected static final int getRscpDbmFromAsu(int asu) {
+        if (asu > 96 || asu < 0) return CellInfo.UNAVAILABLE;
+        return asu - 120;
+    }
+
+    // Range for RSCP in ASU (0-96, 255) as defined in TS 27.007 8.69
+    /** @hide */
+    protected static final int getAsuFromRscpDbm(int dbm) {
+        if (dbm == CellInfo.UNAVAILABLE) return 255;
+        return dbm + 120;
+    }
+
+    // Range for SNR in ASU (0-49, 255) as defined in TS 27.007 8.69
+    /** @hide */
+    protected static final int getEcNoDbFromAsu(int asu) {
+        if (asu > 49 || asu < 0) return CellInfo.UNAVAILABLE;
+        return -24 + (asu / 2);
+    }
+
+    /** @hide */
+    protected static final int inRangeOrUnavailable(int value, int rangeMin, int rangeMax) {
+        if (value < rangeMin || value > rangeMax) return CellInfo.UNAVAILABLE;
+        return value;
+    }
+
+    /** @hide */
+    protected static final int inRangeOrUnavailable(
+            int value, int rangeMin, int rangeMax, int special) {
+        if ((value < rangeMin || value > rangeMax) && value != special) return CellInfo.UNAVAILABLE;
+        return value;
+    }
 }
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
index 5123052..47faf1e 100644
--- a/telephony/java/android/telephony/CellSignalStrengthCdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -18,6 +18,7 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 import android.telephony.Rlog;
 
 import java.util.Objects;
@@ -35,6 +36,7 @@
     private int mEvdoDbm;   // This value is the EVDO RSSI value
     private int mEvdoEcio;  // This value is the EVDO Ec/Io
     private int mEvdoSnr;   // Valid values are 0-8.  8 is the highest signal to noise ratio
+    private int mLevel;
 
     /** @hide */
     public CellSignalStrengthCdma() {
@@ -55,23 +57,29 @@
      * rather than left as -1, which is a departure from SignalStrength, which is stuck with the
      * values it currently reports.
      *
-     * @param cdmaDbm negative of the CDMA signal strength value or -1 if invalid.
-     * @param cdmaEcio negative of the CDMA pilot/noise ratio or -1 if invalid.
-     * @param evdoDbm negative of the EvDO signal strength value or -1 if invalid.
-     * @param evdoEcio negative of the EvDO pilot/noise ratio or -1 if invalid.
-     * @param evdoSnr an SNR value 0..8 or -1 if invalid.
+     * @param cdmaDbm CDMA signal strength value or CellInfo.UNAVAILABLE if invalid.
+     * @param cdmaEcio CDMA pilot/noise ratio or CellInfo.UNAVAILABLE  if invalid.
+     * @param evdoDbm negative of the EvDO signal strength value or CellInfo.UNAVAILABLE if invalid.
+     * @param evdoEcio negative of the EvDO pilot/noise ratio or CellInfo.UNAVAILABLE if invalid.
+     * @param evdoSnr an SNR value 0..8 or CellInfo.UNVAILABLE if invalid.
      * @hide
      */
     public CellSignalStrengthCdma(int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio,
             int evdoSnr) {
-        // The values here were lifted from SignalStrength.validateInput()
-        // FIXME: Combine all checking and setting logic between this and SignalStrength.
-        mCdmaDbm = ((cdmaDbm > 0) && (cdmaDbm < 120))  ? -cdmaDbm : CellInfo.UNAVAILABLE;
-        mCdmaEcio = ((cdmaEcio > 0) && (cdmaEcio < 160)) ? -cdmaEcio : CellInfo.UNAVAILABLE;
+        mCdmaDbm = inRangeOrUnavailable(cdmaDbm, -120, 0);
+        mCdmaEcio = inRangeOrUnavailable(cdmaEcio, -160, 0);
+        mEvdoDbm = inRangeOrUnavailable(evdoDbm, -120, 0);
+        mEvdoEcio = inRangeOrUnavailable(evdoEcio, -160, 0);
+        mEvdoSnr = inRangeOrUnavailable(evdoSnr, 0, 8);
 
-        mEvdoDbm = ((evdoDbm > 0) && (evdoDbm < 120)) ? -evdoDbm : CellInfo.UNAVAILABLE;
-        mEvdoEcio = ((evdoEcio > 0) && (evdoEcio < 160)) ? -evdoEcio : CellInfo.UNAVAILABLE;
-        mEvdoSnr = ((evdoSnr > 0) && (evdoSnr <= 8)) ? evdoSnr : CellInfo.UNAVAILABLE;
+        updateLevel(null, null);
+    }
+
+    /** @hide */
+    public CellSignalStrengthCdma(android.hardware.radio.V1_0.CdmaSignalStrength cdma,
+            android.hardware.radio.V1_0.EvdoSignalStrength evdo) {
+        // Convert from HAL values as part of construction.
+        this(-cdma.dbm, -cdma.ecio, -evdo.dbm, -evdo.ecio, evdo.signalNoiseRatio);
     }
 
     /** @hide */
@@ -86,6 +94,7 @@
         mEvdoDbm = s.mEvdoDbm;
         mEvdoEcio = s.mEvdoEcio;
         mEvdoSnr = s.mEvdoSnr;
+        mLevel = s.mLevel;
     }
 
     /** @hide */
@@ -102,6 +111,7 @@
         mEvdoDbm = CellInfo.UNAVAILABLE;
         mEvdoEcio = CellInfo.UNAVAILABLE;
         mEvdoSnr = CellInfo.UNAVAILABLE;
+        mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
     }
 
     /**
@@ -112,26 +122,54 @@
      */
     @Override
     public int getLevel() {
-        int level;
+        return mLevel;
+    }
 
+    /** @hide */
+    @Override
+    public void updateLevel(PersistableBundle cc, ServiceState ss) {
         int cdmaLevel = getCdmaLevel();
         int evdoLevel = getEvdoLevel();
         if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
             /* We don't know evdo, use cdma */
-            level = getCdmaLevel();
+            mLevel = getCdmaLevel();
         } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
             /* We don't know cdma, use evdo */
-            level = getEvdoLevel();
+            mLevel = getEvdoLevel();
         } else {
             /* We know both, use the lowest level */
-            level = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
+            mLevel = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
         }
-        if (DBG) log("getLevel=" + level);
-        return level;
     }
 
     /**
-     * Get the signal level as an asu value between 0..97, 99 is unknown
+     * Get the 1xRTT Level in (Android) ASU.
+     *
+     * There is no standard definition of ASU for CDMA; however, Android defines it as the
+     * the lesser of the following two results (for 1xRTT):
+     * <table>
+     *     <thead><tr><th>RSSI Range (dBm)</th><th>ASU Value</th></tr><thead>
+     *     <tbody>
+     *         <tr><td>-75..</td><td>16</td></tr>
+     *         <tr><td>-82..-76</td><td>8</td></tr>
+     *         <tr><td>-90..-83</td><td>4</td></tr>
+     *         <tr><td>-95..-91</td><td>2</td></tr>
+     *         <tr><td>-100..-96</td><td>1</td></tr>
+     *         <tr><td>..-101</td><td>99</td></tr>
+     *     </tbody>
+     * </table>
+     * <table>
+     *     <thead><tr><th>Ec/Io Range (dB)</th><th>ASU Value</th></tr><thead>
+     *     <tbody>
+     *         <tr><td>-90..</td><td>16</td></tr>
+     *         <tr><td>-100..-91</td><td>8</td></tr>
+     *         <tr><td>-115..-101</td><td>4</td></tr>
+     *         <tr><td>-130..-116</td><td>2</td></tr>
+     *         <tr><td>--150..-131</td><td>1</td></tr>
+     *         <tr><td>..-151</td><td>99</td></tr>
+     *     </tbody>
+     * </table>
+     * @return 1xRTT Level in Android ASU {1,2,4,8,16,99}
      */
     @Override
     public int getAsuLevel() {
@@ -220,6 +258,63 @@
     }
 
     /**
+     * Get the EVDO Level in (Android) ASU.
+     *
+     * There is no standard definition of ASU for CDMA; however, Android defines it as the
+     * the lesser of the following two results (for EVDO):
+     * <table>
+     *     <thead><tr><th>RSSI Range (dBm)</th><th>ASU Value</th></tr><thead>
+     *     <tbody>
+     *         <tr><td>-65..</td><td>16</td></tr>
+     *         <tr><td>-75..-66</td><td>8</td></tr>
+     *         <tr><td>-85..-76</td><td>4</td></tr>
+     *         <tr><td>-95..-86</td><td>2</td></tr>
+     *         <tr><td>-105..-96</td><td>1</td></tr>
+     *         <tr><td>..-106</td><td>99</td></tr>
+     *     </tbody>
+     * </table>
+     * <table>
+     *     <thead><tr><th>SNR Range (unitless)</th><th>ASU Value</th></tr><thead>
+     *     <tbody>
+     *         <tr><td>7..</td><td>16</td></tr>
+     *         <tr><td>6</td><td>8</td></tr>
+     *         <tr><td>5</td><td>4</td></tr>
+     *         <tr><td>3..4</td><td>2</td></tr>
+     *         <tr><td>1..2</td><td>1</td></tr>
+     *         <tr><td>0</td><td>99</td></tr>
+     *     </tbody>
+     * </table>
+     *
+     * @return EVDO Level in Android ASU {1,2,4,8,16,99}
+     *
+     * @hide
+     */
+    public int getEvdoAsuLevel() {
+        int evdoDbm = getEvdoDbm();
+        int evdoSnr = getEvdoSnr();
+        int levelEvdoDbm;
+        int levelEvdoSnr;
+
+        if (evdoDbm >= -65) levelEvdoDbm = 16;
+        else if (evdoDbm >= -75) levelEvdoDbm = 8;
+        else if (evdoDbm >= -85) levelEvdoDbm = 4;
+        else if (evdoDbm >= -95) levelEvdoDbm = 2;
+        else if (evdoDbm >= -105) levelEvdoDbm = 1;
+        else levelEvdoDbm = 99;
+
+        if (evdoSnr >= 7) levelEvdoSnr = 16;
+        else if (evdoSnr >= 6) levelEvdoSnr = 8;
+        else if (evdoSnr >= 5) levelEvdoSnr = 4;
+        else if (evdoSnr >= 3) levelEvdoSnr = 2;
+        else if (evdoSnr >= 1) levelEvdoSnr = 1;
+        else levelEvdoSnr = 99;
+
+        int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
+        if (DBG) log("getEvdoAsuLevel=" + level);
+        return level;
+    }
+
+    /**
      * Get the signal strength as dBm
      */
     @Override
@@ -237,6 +332,7 @@
     public int getCdmaDbm() {
         return mCdmaDbm;
     }
+
     /** @hide */
     public void setCdmaDbm(int cdmaDbm) {
         mCdmaDbm = cdmaDbm;
@@ -248,6 +344,7 @@
     public int getCdmaEcio() {
         return mCdmaEcio;
     }
+
     /** @hide */
     public void setCdmaEcio(int cdmaEcio) {
         mCdmaEcio = cdmaEcio;
@@ -259,6 +356,7 @@
     public int getEvdoDbm() {
         return mEvdoDbm;
     }
+
     /** @hide */
     public void setEvdoDbm(int evdoDbm) {
         mEvdoDbm = evdoDbm;
@@ -270,6 +368,7 @@
     public int getEvdoEcio() {
         return mEvdoEcio;
     }
+
     /** @hide */
     public void setEvdoEcio(int evdoEcio) {
         mEvdoEcio = evdoEcio;
@@ -281,6 +380,7 @@
     public int getEvdoSnr() {
         return mEvdoSnr;
     }
+
     /** @hide */
     public void setEvdoSnr(int evdoSnr) {
         mEvdoSnr = evdoSnr;
@@ -288,28 +388,29 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(mCdmaDbm, mCdmaEcio, mEvdoDbm, mEvdoEcio, mEvdoSnr);
+        return Objects.hash(mCdmaDbm, mCdmaEcio, mEvdoDbm, mEvdoEcio, mEvdoSnr, mLevel);
+    }
+
+    private static final CellSignalStrengthCdma sInvalid = new CellSignalStrengthCdma();
+
+    /** @hide */
+    @Override
+    public boolean isValid() {
+        return !this.equals(sInvalid);
     }
 
     @Override
     public boolean equals (Object o) {
         CellSignalStrengthCdma s;
-
-        try {
-            s = (CellSignalStrengthCdma) o;
-        } catch (ClassCastException ex) {
-            return false;
-        }
-
-        if (o == null) {
-            return false;
-        }
+        if (!(o instanceof CellSignalStrengthCdma)) return false;
+        s = (CellSignalStrengthCdma) o;
 
         return mCdmaDbm == s.mCdmaDbm
                 && mCdmaEcio == s.mCdmaEcio
                 && mEvdoDbm == s.mEvdoDbm
                 && mEvdoEcio == s.mEvdoEcio
-                && mEvdoSnr == s.mEvdoSnr;
+                && mEvdoSnr == s.mEvdoSnr
+                && mLevel == s.mLevel;
     }
 
     /**
@@ -322,7 +423,8 @@
                 + " cdmaEcio=" + mCdmaEcio
                 + " evdoDbm=" + mEvdoDbm
                 + " evdoEcio=" + mEvdoEcio
-                + " evdoSnr=" + mEvdoSnr;
+                + " evdoSnr=" + mEvdoSnr
+                + " level=" + mLevel;
     }
 
     /** Implement the Parcelable interface */
@@ -334,6 +436,7 @@
         dest.writeInt(mEvdoDbm);
         dest.writeInt(mEvdoEcio);
         dest.writeInt(mEvdoSnr);
+        dest.writeInt(mLevel);
     }
 
     /**
@@ -349,6 +452,7 @@
         mEvdoDbm = in.readInt();
         mEvdoEcio = in.readInt();
         mEvdoSnr = in.readInt();
+        mLevel = in.readInt();
         if (DBG) log("CellSignalStrengthCdma(Parcel): " + toString());
     }
 
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index e906f46..7b29f69 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -19,6 +19,7 @@
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 import android.telephony.Rlog;
 
 import java.util.Objects;
@@ -31,16 +32,18 @@
     private static final String LOG_TAG = "CellSignalStrengthGsm";
     private static final boolean DBG = false;
 
-    private static final int GSM_SIGNAL_STRENGTH_GREAT = 12;
-    private static final int GSM_SIGNAL_STRENGTH_GOOD = 8;
-    private static final int GSM_SIGNAL_STRENGTH_MODERATE = 5;
+    private static final int GSM_RSSI_MAX = -51;
+    private static final int GSM_RSSI_GREAT = -89;
+    private static final int GSM_RSSI_GOOD = -97;
+    private static final int GSM_RSSI_MODERATE = -103;
+    private static final int GSM_RSSI_POOR = -107;
 
+    private int mRssi; // in dBm [-113, -51] or UNAVAILABLE
     @UnsupportedAppUsage
-    private int mSignalStrength; // in ASU; Valid values are (0-31, 99) as defined in TS 27.007 8.5
-    @UnsupportedAppUsage
-    private int mBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
-    @UnsupportedAppUsage
+    private int mBitErrorRate; // bit error rate (0-7, 99) TS 27.007 8.5 or UNAVAILABLE
+    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
     private int mTimingAdvance; // range from 0-219 or CellInfo.UNAVAILABLE if unknown
+    private int mLevel;
 
     /** @hide */
     @UnsupportedAppUsage
@@ -49,15 +52,17 @@
     }
 
     /** @hide */
-    public CellSignalStrengthGsm(int ss, int ber) {
-        this(ss, ber, CellInfo.UNAVAILABLE);
+    public CellSignalStrengthGsm(int rssi, int ber, int ta) {
+        mRssi = inRangeOrUnavailable(rssi, -113, -51);
+        mBitErrorRate = inRangeOrUnavailable(ber, 0, 7, 99);
+        mTimingAdvance = inRangeOrUnavailable(ta, 0, 219);
+        updateLevel(null, null);
     }
 
     /** @hide */
-    public CellSignalStrengthGsm(int ss, int ber, int ta) {
-        mSignalStrength = ss;
-        mBitErrorRate = ber;
-        mTimingAdvance = ta;
+    public CellSignalStrengthGsm(android.hardware.radio.V1_0.GsmSignalStrength gsm) {
+        // Convert from HAL values as part of construction.
+        this(getRssiDbmFromAsu(gsm.signalStrength), gsm.bitErrorRate, gsm.timingAdvance);
     }
 
     /** @hide */
@@ -67,9 +72,10 @@
 
     /** @hide */
     protected void copyFrom(CellSignalStrengthGsm s) {
-        mSignalStrength = s.mSignalStrength;
+        mRssi = s.mRssi;
         mBitErrorRate = s.mBitErrorRate;
         mTimingAdvance = s.mTimingAdvance;
+        mLevel = s.mLevel;
     }
 
     /** @hide */
@@ -81,9 +87,10 @@
     /** @hide */
     @Override
     public void setDefaultValues() {
-        mSignalStrength = CellInfo.UNAVAILABLE;
+        mRssi = CellInfo.UNAVAILABLE;
         mBitErrorRate = CellInfo.UNAVAILABLE;
         mTimingAdvance = CellInfo.UNAVAILABLE;
+        mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
     }
 
     /**
@@ -94,20 +101,18 @@
      */
     @Override
     public int getLevel() {
-        int level;
+        return mLevel;
+    }
 
-        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
-        // asu = 0 (-113dB or less) is very weak
-        // signal, its better to show 0 bars to the user in such cases.
-        // asu = 99 is a special case, where the signal strength is unknown.
-        int asu = mSignalStrength;
-        if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-        else if (asu >= GSM_SIGNAL_STRENGTH_GREAT) level = SIGNAL_STRENGTH_GREAT;
-        else if (asu >= GSM_SIGNAL_STRENGTH_GOOD)  level = SIGNAL_STRENGTH_GOOD;
-        else if (asu >= GSM_SIGNAL_STRENGTH_MODERATE)  level = SIGNAL_STRENGTH_MODERATE;
-        else level = SIGNAL_STRENGTH_POOR;
-        if (DBG) log("getLevel=" + level);
-        return level;
+    /** @hide */
+    @Override
+    public void updateLevel(PersistableBundle cc, ServiceState ss) {
+        if (mRssi > GSM_RSSI_MAX) mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        else if (mRssi >= GSM_RSSI_GREAT) mLevel = SIGNAL_STRENGTH_GREAT;
+        else if (mRssi >= GSM_RSSI_GOOD)  mLevel = SIGNAL_STRENGTH_GOOD;
+        else if (mRssi >= GSM_RSSI_MODERATE)  mLevel = SIGNAL_STRENGTH_MODERATE;
+        else if (mRssi >= GSM_RSSI_POOR) mLevel = SIGNAL_STRENGTH_POOR;
+        else mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
     }
 
     /**
@@ -126,55 +131,52 @@
      */
     @Override
     public int getDbm() {
-        int dBm;
-
-        int level = mSignalStrength;
-        int asu = (level == 99 ? CellInfo.UNAVAILABLE : level);
-        if (asu != CellInfo.UNAVAILABLE) {
-            dBm = -113 + (2 * asu);
-        } else {
-            dBm = CellInfo.UNAVAILABLE;
-        }
-        if (DBG) log("getDbm=" + dBm);
-        return dBm;
+        return mRssi;
     }
 
     /**
-     * Get the signal level as an asu value between 0..31, 99 is unknown
+     * Get the RSSI in ASU.
+     *
      * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+     *
+     * @return RSSI in ASU 0..31, 99, or UNAVAILABLE
      */
     @Override
     public int getAsuLevel() {
-        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
-        // asu = 0 (-113dB or less) is very weak
-        // signal, its better to show 0 bars to the user in such cases.
-        // asu = 99 is a special case, where the signal strength is unknown.
-        int level = mSignalStrength;
-        if (DBG) log("getAsuLevel=" + level);
-        return level;
+        return getAsuFromRssiDbm(mRssi);
+    }
+
+    /**
+     * Return the Bit Error Rate
+     * @returns the bit error rate (0-7, 99) as defined in TS 27.007 8.5 or UNAVAILABLE.
+     * @hide
+     */
+    public int getBitErrorRate() {
+        return mBitErrorRate;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mSignalStrength, mBitErrorRate, mTimingAdvance);
+        return Objects.hash(mRssi, mBitErrorRate, mTimingAdvance);
+    }
+
+    private static final CellSignalStrengthGsm sInvalid = new CellSignalStrengthGsm();
+
+    /** @hide */
+    @Override
+    public boolean isValid() {
+        return !this.equals(sInvalid);
     }
 
     @Override
-    public boolean equals (Object o) {
-        CellSignalStrengthGsm s;
+    public boolean equals(Object o) {
+        if (!(o instanceof CellSignalStrengthGsm)) return false;
+        CellSignalStrengthGsm s = (CellSignalStrengthGsm) o;
 
-        try {
-            s = (CellSignalStrengthGsm) o;
-        } catch (ClassCastException ex) {
-            return false;
-        }
-
-        if (o == null) {
-            return false;
-        }
-
-        return mSignalStrength == s.mSignalStrength && mBitErrorRate == s.mBitErrorRate &&
-                        s.mTimingAdvance == mTimingAdvance;
+        return mRssi == s.mRssi
+                && mBitErrorRate == s.mBitErrorRate
+                && mTimingAdvance == s.mTimingAdvance
+                && mLevel == s.mLevel;
     }
 
     /**
@@ -183,18 +185,20 @@
     @Override
     public String toString() {
         return "CellSignalStrengthGsm:"
-                + " ss=" + mSignalStrength
+                + " rssi=" + mRssi
                 + " ber=" + mBitErrorRate
-                + " mTa=" + mTimingAdvance;
+                + " mTa=" + mTimingAdvance
+                + " mLevel=" + mLevel;
     }
 
     /** Implement the Parcelable interface */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        dest.writeInt(mSignalStrength);
+        dest.writeInt(mRssi);
         dest.writeInt(mBitErrorRate);
         dest.writeInt(mTimingAdvance);
+        dest.writeInt(mLevel);
     }
 
     /**
@@ -202,9 +206,10 @@
      * where the token is already been processed.
      */
     private CellSignalStrengthGsm(Parcel in) {
-        mSignalStrength = in.readInt();
+        mRssi = in.readInt();
         mBitErrorRate = in.readInt();
         mTimingAdvance = in.readInt();
+        mLevel = in.readInt();
         if (DBG) log("CellSignalStrengthGsm(Parcel): " + toString());
     }
 
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index d075394..893dbe3 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -19,7 +19,9 @@
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 
+import java.util.Arrays;
 import java.util.Objects;
 
 /**
@@ -28,7 +30,7 @@
 public final class CellSignalStrengthLte extends CellSignalStrength implements Parcelable {
 
     private static final String LOG_TAG = "CellSignalStrengthLte";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     /**
      * Indicates the unknown or undetectable RSSI value in ASU.
@@ -49,18 +51,23 @@
      */
     private static final int SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MIN_VALUE = 0;
 
-    @UnsupportedAppUsage
-    private int mSignalStrength;
-    @UnsupportedAppUsage
+    private static final int MAX_LTE_RSRP = -44;
+    private static final int MIN_LTE_RSRP = -140;
+
+    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
+    private int mSignalStrength; // To be removed
+    private int mRssi;
+    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
     private int mRsrp;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
     private int mRsrq;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
     private int mRssnr;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
     private int mCqi;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
     private int mTimingAdvance;
+    private int mLevel;
 
     /** @hide */
     @UnsupportedAppUsage
@@ -68,15 +75,38 @@
         setDefaultValues();
     }
 
+    /**
+     * Construct a cell signal strength
+     *
+     * @param rssi in dBm [-113,-51], UNKNOWN
+     * @param rsrp in dBm [-140,-43], UNKNOWN
+     * @param rsrq in dB [-20,-3], UNKNOWN
+     * @param rssnr in 10*dB [-200, +300], UNKNOWN
+     * @param cqi [0, 15], UNKNOWN
+     * @param timingAdvance [0, 1282], UNKNOWN
+     *
+     */
     /** @hide */
-    public CellSignalStrengthLte(int signalStrength, int rsrp, int rsrq, int rssnr, int cqi,
+    public CellSignalStrengthLte(int rssi, int rsrp, int rsrq, int rssnr, int cqi,
             int timingAdvance) {
-        mSignalStrength = signalStrength;
-        mRsrp = rsrp;
-        mRsrq = rsrq;
-        mRssnr = rssnr;
-        mCqi = cqi;
-        mTimingAdvance = timingAdvance;
+
+        mRssi = inRangeOrUnavailable(rssi, -113, -51);
+        mSignalStrength = mRssi;
+        mRsrp = inRangeOrUnavailable(rsrp, -140, -43);
+        mRsrq = inRangeOrUnavailable(rsrq, -20, -3);
+        mRssnr = inRangeOrUnavailable(rssnr, -200, 300);
+        mCqi = inRangeOrUnavailable(cqi, 0, 15);
+        mTimingAdvance = inRangeOrUnavailable(timingAdvance, 0, 1282);
+        updateLevel(null, null);
+    }
+
+    /** @hide */
+    public CellSignalStrengthLte(android.hardware.radio.V1_0.LteSignalStrength lte) {
+        // Convert from HAL values as part of construction.
+        this(convertRssiAsuToDBm(lte.signalStrength),
+                lte.rsrp != CellInfo.UNAVAILABLE ? -lte.rsrp : lte.rsrp,
+                lte.rsrq != CellInfo.UNAVAILABLE ? -lte.rsrq : lte.rsrq,
+                lte.rssnr, lte.cqi, lte.timingAdvance);
     }
 
     /** @hide */
@@ -87,11 +117,13 @@
     /** @hide */
     protected void copyFrom(CellSignalStrengthLte s) {
         mSignalStrength = s.mSignalStrength;
+        mRssi = s.mRssi;
         mRsrp = s.mRsrp;
         mRsrq = s.mRsrq;
         mRssnr = s.mRssnr;
         mCqi = s.mCqi;
         mTimingAdvance = s.mTimingAdvance;
+        mLevel = s.mLevel;
     }
 
     /** @hide */
@@ -104,11 +136,13 @@
     @Override
     public void setDefaultValues() {
         mSignalStrength = CellInfo.UNAVAILABLE;
+        mRssi = CellInfo.UNAVAILABLE;
         mRsrp = CellInfo.UNAVAILABLE;
         mRsrq = CellInfo.UNAVAILABLE;
         mRssnr = CellInfo.UNAVAILABLE;
         mCqi = CellInfo.UNAVAILABLE;
         mTimingAdvance = CellInfo.UNAVAILABLE;
+        mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
     }
 
     /**
@@ -119,34 +153,106 @@
      */
     @Override
     public int getLevel() {
-        int levelRsrp = 0;
-        int levelRssnr = 0;
+        return mLevel;
+    }
 
-        if (mRsrp == CellInfo.UNAVAILABLE) levelRsrp = 0;
-        else if (mRsrp >= -95) levelRsrp = SIGNAL_STRENGTH_GREAT;
-        else if (mRsrp >= -105) levelRsrp = SIGNAL_STRENGTH_GOOD;
-        else if (mRsrp >= -115) levelRsrp = SIGNAL_STRENGTH_MODERATE;
-        else levelRsrp = SIGNAL_STRENGTH_POOR;
+    // Lifted from Default carrier configs and max range of RSRP
+    private static final int[] sThresholds = new int[]{-115, -105, -95, -85};
+    private static final int sRsrpBoost = 0;
 
-        // See RIL_LTE_SignalStrength in ril.h
-        if (mRssnr == CellInfo.UNAVAILABLE) levelRssnr = 0;
-        else if (mRssnr >= 45) levelRssnr = SIGNAL_STRENGTH_GREAT;
-        else if (mRssnr >= 10) levelRssnr = SIGNAL_STRENGTH_GOOD;
-        else if (mRssnr >= -30) levelRssnr = SIGNAL_STRENGTH_MODERATE;
-        else levelRssnr = SIGNAL_STRENGTH_POOR;
-
-        int level;
-        if (mRsrp == CellInfo.UNAVAILABLE) {
-            level = levelRssnr;
-        } else if (mRssnr == CellInfo.UNAVAILABLE) {
-            level = levelRsrp;
+    /** @hide */
+    @Override
+    public void updateLevel(PersistableBundle cc, ServiceState ss) {
+        int[] thresholds;
+        boolean rsrpOnly;
+        if (cc == null) {
+            thresholds = sThresholds;
+            rsrpOnly = false;
         } else {
-            level = (levelRssnr < levelRsrp) ? levelRssnr : levelRsrp;
+            rsrpOnly = cc.getBoolean(
+                    CarrierConfigManager.KEY_USE_ONLY_RSRP_FOR_LTE_SIGNAL_BAR_BOOL, false);
+            thresholds = cc.getIntArray(
+                    CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY);
+            if (thresholds == null) thresholds = sThresholds;
+            if (DBG) log("updateLevel() carrierconfig - rsrpOnly="
+                    + rsrpOnly + ", thresholds=" + Arrays.toString(thresholds));
         }
 
-        if (DBG) log("Lte rsrp level: " + levelRsrp
-                + " snr level: " + levelRssnr + " level: " + level);
-        return level;
+
+        int rsrpBoost = 0;
+        if (ss != null) {
+            rsrpBoost = ss.getLteEarfcnRsrpBoost();
+        }
+
+        int rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        int rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        int snrIconLevel = -1;
+
+        int rsrp = mRsrp + rsrpBoost;
+
+        if (rsrp < MIN_LTE_RSRP || rsrp > MAX_LTE_RSRP) {
+            rsrpIconLevel = -1;
+        } else {
+            rsrpIconLevel = thresholds.length;
+            while (rsrpIconLevel > 0 && rsrp < thresholds[rsrpIconLevel - 1]) rsrpIconLevel--;
+        }
+
+        if (rsrpOnly) {
+            if (DBG) log("updateLevel() - rsrp = " + rsrpIconLevel);
+            if (rsrpIconLevel != -1) {
+                mLevel = rsrpIconLevel;
+                return;
+            }
+        }
+
+        /*
+         * Values are -200 dB to +300 (SNR*10dB) RS_SNR >= 13.0 dB =>4 bars 4.5
+         * dB <= RS_SNR < 13.0 dB => 3 bars 1.0 dB <= RS_SNR < 4.5 dB => 2 bars
+         * -3.0 dB <= RS_SNR < 1.0 dB 1 bar RS_SNR < -3.0 dB/No Service Antenna
+         * Icon Only
+         */
+        if (mRssnr > 300) snrIconLevel = -1;
+        else if (mRssnr >= 130) snrIconLevel = SIGNAL_STRENGTH_GREAT;
+        else if (mRssnr >= 45) snrIconLevel = SIGNAL_STRENGTH_GOOD;
+        else if (mRssnr >= 10) snrIconLevel = SIGNAL_STRENGTH_MODERATE;
+        else if (mRssnr >= -30) snrIconLevel = SIGNAL_STRENGTH_POOR;
+        else if (mRssnr >= -200)
+            snrIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+
+        if (DBG) log("updateLevel() - rsrp:" + mRsrp + " snr:" + mRssnr + " rsrpIconLevel:"
+                + rsrpIconLevel + " snrIconLevel:" + snrIconLevel
+                + " lteRsrpBoost:" + sRsrpBoost);
+
+        /* Choose a measurement type to use for notification */
+        if (snrIconLevel != -1 && rsrpIconLevel != -1) {
+            /*
+             * The number of bars displayed shall be the smaller of the bars
+             * associated with LTE RSRP and the bars associated with the LTE
+             * RS_SNR
+             */
+            mLevel = (rsrpIconLevel < snrIconLevel ? rsrpIconLevel : snrIconLevel);
+            return;
+        }
+
+        if (snrIconLevel != -1) {
+            mLevel = snrIconLevel;
+            return;
+        }
+
+        if (rsrpIconLevel != -1) {
+            mLevel = rsrpIconLevel;
+            return;
+        }
+
+        if (mRssi > -51) rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        else if (mRssi >= -89) rssiIconLevel = SIGNAL_STRENGTH_GREAT;
+        else if (mRssi >= -97) rssiIconLevel = SIGNAL_STRENGTH_GOOD;
+        else if (mRssi >= -103) rssiIconLevel = SIGNAL_STRENGTH_MODERATE;
+        else if (mRssi >= -113) rssiIconLevel = SIGNAL_STRENGTH_POOR;
+        else rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        if (DBG) log("getLteLevel - rssi:" + mRssi + " rssiIconLevel:"
+                + rssiIconLevel);
+        mLevel = rssiIconLevel;
     }
 
     /**
@@ -169,7 +275,7 @@
      * @return the RSSI if available or {@link CellInfo#UNAVAILABLE} if unavailable.
      */
     public int getRssi() {
-        return convertRssiAsuToDBm(mSignalStrength);
+        return mRssi;
     }
 
     /**
@@ -212,13 +318,16 @@
     }
 
     /**
-     * Get the LTE signal level as an asu value between 0..97, 99 is unknown
+     * Get the RSRP in ASU.
+     *
      * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+     *
+     * @return RSCP in ASU 0..97, 255, or UNAVAILABLE
      */
     @Override
     public int getAsuLevel() {
         int lteAsuLevel = 99;
-        int lteDbm = getDbm();
+        int lteDbm = mRsrp;
         if (lteDbm == CellInfo.UNAVAILABLE) lteAsuLevel = 99;
         else if (lteDbm <= -140) lteAsuLevel = 0;
         else if (lteDbm >= -43) lteAsuLevel = 97;
@@ -241,29 +350,31 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(mSignalStrength, mRsrp, mRsrq, mRssnr, mCqi, mTimingAdvance);
+        return Objects.hash(mRssi, mRsrp, mRsrq, mRssnr, mCqi, mTimingAdvance, mLevel);
+    }
+
+    private static final CellSignalStrengthLte sInvalid = new CellSignalStrengthLte();
+
+    /** @hide */
+    @Override
+    public boolean isValid() {
+        return !this.equals(sInvalid);
     }
 
     @Override
     public boolean equals (Object o) {
         CellSignalStrengthLte s;
 
-        try {
-            s = (CellSignalStrengthLte) o;
-        } catch (ClassCastException ex) {
-            return false;
-        }
+        if (!(o instanceof CellSignalStrengthLte)) return false;
+        s = (CellSignalStrengthLte) o;
 
-        if (o == null) {
-            return false;
-        }
-
-        return mSignalStrength == s.mSignalStrength
+        return mRssi == s.mRssi
                 && mRsrp == s.mRsrp
                 && mRsrq == s.mRsrq
                 && mRssnr == s.mRssnr
                 && mCqi == s.mCqi
-                && mTimingAdvance == s.mTimingAdvance;
+                && mTimingAdvance == s.mTimingAdvance
+                && mLevel == s.mLevel;
     }
 
     /**
@@ -272,27 +383,29 @@
     @Override
     public String toString() {
         return "CellSignalStrengthLte:"
-                + " ss=" + mSignalStrength
+                + " rssi=" + mRssi
                 + " rsrp=" + mRsrp
                 + " rsrq=" + mRsrq
                 + " rssnr=" + mRssnr
                 + " cqi=" + mCqi
-                + " ta=" + mTimingAdvance;
+                + " ta=" + mTimingAdvance
+                + " level=" + mLevel;
     }
 
     /** Implement the Parcelable interface */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        dest.writeInt(mSignalStrength);
+        dest.writeInt(mRssi);
         // Need to multiply rsrp and rsrq by -1
         // to ensure consistency when reading values written here
         // unless the values are invalid
-        dest.writeInt(mRsrp * (mRsrp != CellInfo.UNAVAILABLE ? -1 : 1));
-        dest.writeInt(mRsrq * (mRsrq != CellInfo.UNAVAILABLE ? -1 : 1));
+        dest.writeInt(mRsrp);
+        dest.writeInt(mRsrq);
         dest.writeInt(mRssnr);
         dest.writeInt(mCqi);
         dest.writeInt(mTimingAdvance);
+        dest.writeInt(mLevel);
     }
 
     /**
@@ -300,16 +413,14 @@
      * where the token is already been processed.
      */
     private CellSignalStrengthLte(Parcel in) {
-        mSignalStrength = in.readInt();
-        // rsrp and rsrq are written into the parcel as positive values.
-        // Need to convert into negative values unless the values are invalid
+        mRssi = in.readInt();
+        mSignalStrength = mRssi;
         mRsrp = in.readInt();
-        if (mRsrp != CellInfo.UNAVAILABLE) mRsrp *= -1;
         mRsrq = in.readInt();
-        if (mRsrq != CellInfo.UNAVAILABLE) mRsrq *= -1;
         mRssnr = in.readInt();
         mCqi = in.readInt();
         mTimingAdvance = in.readInt();
+        mLevel = in.readInt();
         if (DBG) log("CellSignalStrengthLte(Parcel): " + toString());
     }
 
@@ -342,13 +453,12 @@
     }
 
     private static int convertRssiAsuToDBm(int rssiAsu) {
-        if (rssiAsu != SIGNAL_STRENGTH_LTE_RSSI_ASU_UNKNOWN
-                && (rssiAsu < SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MIN_VALUE
-                || rssiAsu > SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MAX_VALUE)) {
-            Rlog.e(LOG_TAG, "convertRssiAsuToDBm: invalid RSSI in ASU=" + rssiAsu);
+        if (rssiAsu == SIGNAL_STRENGTH_LTE_RSSI_ASU_UNKNOWN) {
             return CellInfo.UNAVAILABLE;
         }
-        if (rssiAsu == SIGNAL_STRENGTH_LTE_RSSI_ASU_UNKNOWN) {
+        if ((rssiAsu < SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MIN_VALUE
+                || rssiAsu > SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MAX_VALUE)) {
+            Rlog.e(LOG_TAG, "convertRssiAsuToDBm: invalid RSSI in ASU=" + rssiAsu);
             return CellInfo.UNAVAILABLE;
         }
         return -113 + (2 * rssiAsu);
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index 8079242..061cd4b 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -18,6 +18,7 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 
 import java.util.Objects;
 
@@ -48,6 +49,12 @@
     private int mSsRsrp;
     private int mSsRsrq;
     private int mSsSinr;
+    private int mLevel;
+
+    /** @hide */
+    public CellSignalStrengthNr() {
+        setDefaultValues();
+    }
 
     /**
      * @param csiRsrp CSI reference signal received power.
@@ -60,12 +67,13 @@
      */
     public CellSignalStrengthNr(
             int csiRsrp, int csiRsrq, int csiSinr, int ssRsrp, int ssRsrq, int ssSinr) {
-        mCsiRsrp = csiRsrp;
-        mCsiRsrq = csiRsrq;
-        mCsiSinr = csiSinr;
-        mSsRsrp = ssRsrp;
-        mSsRsrq = ssRsrq;
-        mSsSinr = ssSinr;
+        mCsiRsrp = inRangeOrUnavailable(csiRsrp, -140, -44);
+        mCsiRsrq = inRangeOrUnavailable(csiRsrq, -20, -3);
+        mCsiSinr = inRangeOrUnavailable(csiSinr, -23, 23);
+        mSsRsrp = inRangeOrUnavailable(ssRsrp, -140, -44);
+        mSsRsrq = inRangeOrUnavailable(ssRsrq, -20, -3);
+        mSsSinr = inRangeOrUnavailable(ssSinr, -23, 40);
+        updateLevel(null, null);
     }
 
     /**
@@ -142,6 +150,7 @@
         dest.writeInt(mSsRsrp);
         dest.writeInt(mSsRsrq);
         dest.writeInt(mSsSinr);
+        dest.writeInt(mLevel);
     }
 
     private CellSignalStrengthNr(Parcel in) {
@@ -151,6 +160,7 @@
         mSsRsrp = in.readInt();
         mSsRsrq = in.readInt();
         mSsSinr = in.readInt();
+        mLevel = in.readInt();
     }
 
     /** @hide */
@@ -162,27 +172,36 @@
         mSsRsrp = CellInfo.UNAVAILABLE;
         mSsRsrq = CellInfo.UNAVAILABLE;
         mSsSinr = CellInfo.UNAVAILABLE;
+        mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
     }
 
     @Override
     public int getLevel() {
+        return mLevel;
+    }
+
+    /** @hide */
+    @Override
+    public void updateLevel(PersistableBundle cc, ServiceState ss) {
         if (mCsiRsrp == CellInfo.UNAVAILABLE) {
-            return SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+            mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
         } else if (mCsiRsrp >= SIGNAL_GREAT_THRESHOLD) {
-            return SIGNAL_STRENGTH_GREAT;
+            mLevel = SIGNAL_STRENGTH_GREAT;
         } else if (mCsiRsrp >= SIGNAL_GOOD_THRESHOLD) {
-            return SIGNAL_STRENGTH_GOOD;
+            mLevel = SIGNAL_STRENGTH_GOOD;
         } else if (mCsiRsrp >= SIGNAL_MODERATE_THRESHOLD) {
-            return SIGNAL_STRENGTH_MODERATE;
+            mLevel = SIGNAL_STRENGTH_MODERATE;
         } else {
-            return SIGNAL_STRENGTH_POOR;
+            mLevel = SIGNAL_STRENGTH_POOR;
         }
     }
 
     /**
-     * Calculates the NR signal as an asu value between 0..97, 99 is unknown.
-     * Asu is calculated based on 3GPP RSRP, refer to 3GPP TS 27.007 section 8.69.
-     * @return an integer represent the asu level of the signal strength.
+     * Get the RSRP in ASU.
+     *
+     * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+     *
+     * @return RSCP in ASU 0..97, 255, or UNAVAILABLE
      */
     @Override
     public int getAsuLevel() {
@@ -206,15 +225,33 @@
     }
 
     /** @hide */
+    public CellSignalStrengthNr(CellSignalStrengthNr s) {
+        mCsiRsrp = s.mCsiRsrp;
+        mCsiRsrq = s.mCsiRsrq;
+        mCsiSinr = s.mCsiSinr;
+        mSsRsrp = s.mSsRsrp;
+        mSsRsrq = s.mSsRsrq;
+        mSsSinr = s.mSsSinr;
+        mLevel = s.mLevel;
+    }
+
+    /** @hide */
     @Override
-    public CellSignalStrength copy() {
-        return new CellSignalStrengthNr(
-                mCsiRsrp, mCsiRsrq, mCsiSinr, mSsRsrp, mSsRsrq, mSsSinr);
+    public CellSignalStrengthNr copy() {
+        return new CellSignalStrengthNr(this);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mCsiRsrp, mCsiRsrq, mCsiSinr, mSsRsrp, mSsRsrq, mSsSinr);
+        return Objects.hash(mCsiRsrp, mCsiRsrq, mCsiSinr, mSsRsrp, mSsRsrq, mSsSinr, mLevel);
+    }
+
+    private static final CellSignalStrengthNr sInvalid = new CellSignalStrengthNr();
+
+    /** @hide */
+    @Override
+    public boolean isValid() {
+        return !this.equals(sInvalid);
     }
 
     @Override
@@ -222,7 +259,8 @@
         if (obj instanceof CellSignalStrengthNr) {
             CellSignalStrengthNr o = (CellSignalStrengthNr) obj;
             return mCsiRsrp == o.mCsiRsrp && mCsiRsrq == o.mCsiRsrq && mCsiSinr == o.mCsiSinr
-                    && mSsRsrp == o.mSsRsrp && mSsRsrq == o.mSsRsrq && mSsSinr == o.mSsSinr;
+                    && mSsRsrp == o.mSsRsrp && mSsRsrq == o.mSsRsrq && mSsSinr == o.mSsSinr
+                    && mLevel == o.mLevel;
         }
         return false;
     }
@@ -237,6 +275,7 @@
                 .append(" ssRsrp = " + mSsRsrp)
                 .append(" ssRsrq = " + mSsRsrq)
                 .append(" ssSinr = " + mSsSinr)
+                .append(" level = " + mLevel)
                 .append(" }")
                 .toString();
     }
diff --git a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
index 4d040cc..6f52b85 100644
--- a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
@@ -18,6 +18,7 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 
 import java.util.Objects;
 
@@ -31,27 +32,53 @@
     private static final String LOG_TAG = "CellSignalStrengthTdscdma";
     private static final boolean DBG = false;
 
-    private static final int TDSCDMA_SIGNAL_STRENGTH_GREAT = 12;
-    private static final int TDSCDMA_SIGNAL_STRENGTH_GOOD = 8;
-    private static final int TDSCDMA_SIGNAL_STRENGTH_MODERATE = 5;
+    private static final int TDSCDMA_RSSI_MAX = -51;
+    private static final int TDSCDMA_RSSI_GREAT = -77;
+    private static final int TDSCDMA_RSSI_GOOD = -87;
+    private static final int TDSCDMA_RSSI_MODERATE = -97;
+    private static final int TDSCDMA_RSSI_POOR = -107;
 
-    private int mSignalStrength; // in ASU; Valid values are (0-31, 99) as defined in TS 27.007 8.5
-                                 // or CellInfo.UNAVAILABLE if unknown
+    private static final int TDSCDMA_RSCP_MIN = -120;
+    private static final int TDSCDMA_RSCP_MAX = -24;
+
+    private int mRssi; // in dBm [-113, -51], CellInfo.UNAVAILABLE
+
     private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
                                // CellInfo.UNAVAILABLE if unknown
-    private int mRscp; // Pilot power (0-96, 255) as defined in TS 27.007 8.69 or
+    private int mRscp; // Pilot Power in dBm [-120, -24] or CellInfo.UNAVAILABLE
                        // CellInfo.UNAVAILABLE if unknown
 
+    private int mLevel;
+
     /** @hide */
     public CellSignalStrengthTdscdma() {
         setDefaultValues();
     }
 
+    /**
+     * @param rssi in dBm [-113, -51] or UNAVAILABLE
+     * @param ber [0-7], 99 or UNAVAILABLE
+     * @param rscp in dBm [-120, -24] or UNAVAILABLE
+     * @hide */
+    public CellSignalStrengthTdscdma(int rssi, int ber, int rscp) {
+        mRssi = inRangeOrUnavailable(rssi, -113, -51);
+        mBitErrorRate = inRangeOrUnavailable(ber, 0, 7, 99);
+        mRscp = inRangeOrUnavailable(rscp, -120, -24);
+        updateLevel(null, null);
+    }
+
     /** @hide */
-    public CellSignalStrengthTdscdma(int ss, int ber, int rscp) {
-        mSignalStrength = ss;
-        mBitErrorRate = ber;
-        mRscp = rscp;
+    public CellSignalStrengthTdscdma(android.hardware.radio.V1_0.TdScdmaSignalStrength tdscdma) {
+        // Convert from HAL values as part of construction.
+        this(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
+                tdscdma.rscp != CellInfo.UNAVAILABLE ? -tdscdma.rscp : tdscdma.rscp);
+    }
+
+    /** @hide */
+    public CellSignalStrengthTdscdma(android.hardware.radio.V1_2.TdscdmaSignalStrength tdscdma) {
+        // Convert from HAL values as part of construction.
+        this(getRssiDbmFromAsu(tdscdma.signalStrength),
+                tdscdma.bitErrorRate, getRscpDbmFromAsu(tdscdma.rscp));
     }
 
     /** @hide */
@@ -61,9 +88,10 @@
 
     /** @hide */
     protected void copyFrom(CellSignalStrengthTdscdma s) {
-        mSignalStrength = s.mSignalStrength;
+        mRssi = s.mRssi;
         mBitErrorRate = s.mBitErrorRate;
         mRscp = s.mRscp;
+        mLevel = s.mLevel;
     }
 
     /** @hide */
@@ -75,9 +103,10 @@
     /** @hide */
     @Override
     public void setDefaultValues() {
-        mSignalStrength = CellInfo.UNAVAILABLE;
+        mRssi = CellInfo.UNAVAILABLE;
         mBitErrorRate = CellInfo.UNAVAILABLE;
         mRscp = CellInfo.UNAVAILABLE;
+        mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
     }
 
     /**
@@ -88,26 +117,18 @@
      */
     @Override
     public int getLevel() {
-        int level;
+        return mLevel;
+    }
 
-        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
-        // asu = 0 (-113dB or less) is very weak
-        // signal, its better to show 0 bars to the user in such cases.
-        // asu = 99 is a special case, where the signal strength is unknown.
-        int asu = mSignalStrength;
-        if (asu <= 2 || asu == 99) {
-            level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-        } else if (asu >= TDSCDMA_SIGNAL_STRENGTH_GREAT) {
-            level = SIGNAL_STRENGTH_GREAT;
-        } else if (asu >= TDSCDMA_SIGNAL_STRENGTH_GOOD) {
-            level = SIGNAL_STRENGTH_GOOD;
-        } else if (asu >= TDSCDMA_SIGNAL_STRENGTH_MODERATE) {
-            level = SIGNAL_STRENGTH_MODERATE;
-        } else {
-            level = SIGNAL_STRENGTH_POOR;
-        }
-        if (DBG) log("getLevel=" + level);
-        return level;
+    /** @hide */
+    @Override
+    public void updateLevel(PersistableBundle cc, ServiceState ss) {
+        if (mRssi > TDSCDMA_RSSI_MAX) mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        else if (mRssi >= TDSCDMA_RSSI_GREAT) mLevel = SIGNAL_STRENGTH_GREAT;
+        else if (mRssi >= TDSCDMA_RSSI_GOOD)  mLevel = SIGNAL_STRENGTH_GOOD;
+        else if (mRssi >= TDSCDMA_RSSI_MODERATE)  mLevel = SIGNAL_STRENGTH_MODERATE;
+        else if (mRssi >= TDSCDMA_RSSI_POOR) mLevel = SIGNAL_STRENGTH_POOR;
+        else mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
     }
 
     /**
@@ -115,56 +136,55 @@
      */
     @Override
     public int getDbm() {
-        int dBm;
-
-        int level = mSignalStrength;
-        int asu = (level == 99 ? CellInfo.UNAVAILABLE : level);
-        if (asu != CellInfo.UNAVAILABLE) {
-            dBm = -113 + (2 * asu);
-        } else {
-            dBm = CellInfo.UNAVAILABLE;
-        }
-        if (DBG) log("getDbm=" + dBm);
-        return dBm;
+        return mRscp;
     }
 
     /**
-     * Get the signal level as an asu value between 0..31, 99 is unknown
+     * Get the RSCP as dBm
+     * @hide
+     */
+    public int getRscp() {
+        return mRscp;
+    }
+
+    /**
+     * Get the RSCP in ASU.
+     *
      * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+     *
+     * @return RSCP in ASU 0..96, 255, or UNAVAILABLE
      */
     @Override
     public int getAsuLevel() {
-        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
-        // asu = 0 (-113dB or less) is very weak
-        // signal, its better to show 0 bars to the user in such cases.
-        // asu = 99 is a special case, where the signal strength is unknown.
-        int level = mSignalStrength;
-        if (DBG) log("getAsuLevel=" + level);
-        return level;
+        if (mRscp != CellInfo.UNAVAILABLE) return getAsuFromRscpDbm(mRscp);
+        // For historical reasons, if RSCP is unavailable, this API will very incorrectly return
+        // RSSI. This hackery will be removed when most devices are using Radio HAL 1.2+
+        if (mRssi != CellInfo.UNAVAILABLE) return getAsuFromRssiDbm(mRssi);
+        return getAsuFromRscpDbm(CellInfo.UNAVAILABLE);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mSignalStrength, mBitErrorRate);
+        return Objects.hash(mRssi, mBitErrorRate, mRscp, mLevel);
+    }
+
+    private static final CellSignalStrengthTdscdma sInvalid = new CellSignalStrengthTdscdma();
+
+    /** @hide */
+    @Override
+    public boolean isValid() {
+        return !this.equals(sInvalid);
     }
 
     @Override
     public boolean equals(Object o) {
-        CellSignalStrengthTdscdma s;
+        if (!(o instanceof CellSignalStrengthTdscdma)) return false;
+        CellSignalStrengthTdscdma s = (CellSignalStrengthTdscdma) o;
 
-        try {
-            s = (CellSignalStrengthTdscdma) o;
-        } catch (ClassCastException ex) {
-            return false;
-        }
-
-        if (o == null) {
-            return false;
-        }
-
-        return mSignalStrength == s.mSignalStrength
+        return mRssi == s.mRssi
                 && mBitErrorRate == s.mBitErrorRate
-                && mRscp == s.mRscp;
+                && mRscp == s.mRscp
+                && mLevel == s.mLevel;
     }
 
     /**
@@ -173,18 +193,20 @@
     @Override
     public String toString() {
         return "CellSignalStrengthTdscdma:"
-                + " ss=" + mSignalStrength
+                + " rssi=" + mRssi
                 + " ber=" + mBitErrorRate
-                + " rscp=" + mRscp;
+                + " rscp=" + mRscp
+                + " level=" + mLevel;
     }
 
     /** Implement the Parcelable interface */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        dest.writeInt(mSignalStrength);
+        dest.writeInt(mRssi);
         dest.writeInt(mBitErrorRate);
         dest.writeInt(mRscp);
+        dest.writeInt(mLevel);
     }
 
     /**
@@ -192,9 +214,10 @@
      * where the token is already been processed.
      */
     private CellSignalStrengthTdscdma(Parcel in) {
-        mSignalStrength = in.readInt();
+        mRssi = in.readInt();
         mBitErrorRate = in.readInt();
         mRscp = in.readInt();
+        mLevel = in.readInt();
         if (DBG) log("CellSignalStrengthTdscdma(Parcel): " + toString());
     }
 
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index 0048cbd..88f6fbc 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -16,11 +16,14 @@
 
 package android.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.StringDef;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 import android.telephony.Rlog;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
 
 /**
@@ -31,20 +34,32 @@
     private static final String LOG_TAG = "CellSignalStrengthWcdma";
     private static final boolean DBG = false;
 
-    private static final int WCDMA_SIGNAL_STRENGTH_GREAT = 12;
-    private static final int WCDMA_SIGNAL_STRENGTH_GOOD = 8;
-    private static final int WCDMA_SIGNAL_STRENGTH_MODERATE = 5;
+    private static final int WCDMA_RSSI_MAX = -51;
+    private static final int WCDMA_RSSI_GREAT = -77;
+    private static final int WCDMA_RSSI_GOOD = -87;
+    private static final int WCDMA_RSSI_MODERATE = -97;
+    private static final int WCDMA_RSSI_POOR = -107;
+    private static final int WCDMA_RSSI_MIN = -113;
 
-    @UnsupportedAppUsage
-    private int mSignalStrength; // in ASU; Valid values are (0-31, 99) as defined in TS 27.007 8.5
-                                 // or CellInfo.UNAVAILABLE if unknown
-    @UnsupportedAppUsage
+    private static final int WCDMA_RSCP_MIN = -120;
+    private static final int WCDMA_RSCP_MAX = -24;
+
+    // TODO: Because these are used as values in CarrierConfig, they should be exposed somehow.
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @StringDef({LEVEL_CALCULATION_METHOD_RSSI, LEVEL_CALCULATION_METHOD_RSCP})
+    public @interface LevelCalculationMethod {}
+    /** @hide */
+    public static final String LEVEL_CALCULATION_METHOD_RSSI = "rssi";
+    /** @hide */
+    public static final String LEVEL_CALCULATION_METHOD_RSCP = "rscp";
+
+    private int mRssi; // in dBm [-113, 51] or CellInfo.UNAVAILABLE if unknown
     private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
                                // CellInfo.UNAVAILABLE if unknown
-    private int mRscp; // bit error rate (0-96, 255) as defined in TS 27.007 8.69 or
-                       // CellInfo.UNAVAILABLE if unknown
-    private int mEcNo; // signal to noise radio (0-49, 255) as defined in TS 27.007 8.69 or
-                       // CellInfo.UNAVAILABLE if unknown
+    private int mRscp; // in dBm [-120, -24]
+    private int mEcNo; // range -24, 1, CellInfo.UNAVAILABLE if unknown
+    private int mLevel;
 
     /** @hide */
     public CellSignalStrengthWcdma() {
@@ -52,11 +67,28 @@
     }
 
     /** @hide */
-    public CellSignalStrengthWcdma(int ss, int ber, int rscp, int ecno) {
-        mSignalStrength = ss;
-        mBitErrorRate = ber;
-        mRscp = rscp;
-        mEcNo = ecno;
+    public CellSignalStrengthWcdma(int rssi, int ber, int rscp, int ecno) {
+        mRssi = inRangeOrUnavailable(rssi, WCDMA_RSSI_MIN, WCDMA_RSSI_MAX);
+        mBitErrorRate = inRangeOrUnavailable(ber, 0, 7, 99);
+        mRscp = inRangeOrUnavailable(rscp, -120, -24);
+        mEcNo = inRangeOrUnavailable(ecno, -24, 1);
+        updateLevel(null, null);
+    }
+
+    /** @hide */
+    public CellSignalStrengthWcdma(android.hardware.radio.V1_0.WcdmaSignalStrength wcdma) {
+        // Convert from HAL values as part of construction.
+        this(getRssiDbmFromAsu(wcdma.signalStrength),
+                wcdma.bitErrorRate, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE);
+    }
+
+    /** @hide */
+    public CellSignalStrengthWcdma(android.hardware.radio.V1_2.WcdmaSignalStrength wcdma) {
+        // Convert from HAL values as part of construction.
+        this(getRssiDbmFromAsu(wcdma.base.signalStrength),
+                    wcdma.base.bitErrorRate,
+                    getRscpDbmFromAsu(wcdma.rscp),
+                    getEcNoDbFromAsu(wcdma.ecno));
     }
 
     /** @hide */
@@ -66,10 +98,11 @@
 
     /** @hide */
     protected void copyFrom(CellSignalStrengthWcdma s) {
-        mSignalStrength = s.mSignalStrength;
+        mRssi = s.mRssi;
         mBitErrorRate = s.mBitErrorRate;
         mRscp = s.mRscp;
         mEcNo = s.mEcNo;
+        mLevel = s.mLevel;
     }
 
     /** @hide */
@@ -81,12 +114,17 @@
     /** @hide */
     @Override
     public void setDefaultValues() {
-        mSignalStrength = CellInfo.UNAVAILABLE;
+        mRssi = CellInfo.UNAVAILABLE;
         mBitErrorRate = CellInfo.UNAVAILABLE;
         mRscp = CellInfo.UNAVAILABLE;
         mEcNo = CellInfo.UNAVAILABLE;
+        mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
     }
 
+    private static final String sLevelCalculationMethod = LEVEL_CALCULATION_METHOD_RSSI;
+    private static final int[] sThresholds = new int[]{
+            WCDMA_RSSI_POOR, WCDMA_RSSI_GOOD, WCDMA_RSSI_GOOD, WCDMA_RSSI_GREAT};
+
     /**
      * Retrieve an abstract level value for the overall signal strength.
      *
@@ -95,20 +133,49 @@
      */
     @Override
     public int getLevel() {
-        int level;
+        return mLevel;
+    }
 
-        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
-        // asu = 0 (-113dB or less) is very weak
-        // signal, its better to show 0 bars to the user in such cases.
-        // asu = 99 is a special case, where the signal strength is unknown.
-        int asu = mSignalStrength;
-        if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-        else if (asu >= WCDMA_SIGNAL_STRENGTH_GREAT) level = SIGNAL_STRENGTH_GREAT;
-        else if (asu >= WCDMA_SIGNAL_STRENGTH_GOOD)  level = SIGNAL_STRENGTH_GOOD;
-        else if (asu >= WCDMA_SIGNAL_STRENGTH_MODERATE)  level = SIGNAL_STRENGTH_MODERATE;
-        else level = SIGNAL_STRENGTH_POOR;
-        if (DBG) log("getLevel=" + level);
-        return level;
+    /** @hide */
+    @Override
+    public void updateLevel(PersistableBundle cc, ServiceState ss) {
+        String calcMethod;
+        int[] thresholds;
+
+        if (cc == null) {
+            calcMethod = sLevelCalculationMethod;
+            thresholds = sThresholds;
+        } else {
+            // TODO: abstract this entire thing into a series of functions
+            calcMethod = cc.getString(
+                    CarrierConfigManager.KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING,
+                    sLevelCalculationMethod);
+            thresholds = cc.getIntArray(
+                    CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY);
+            if (thresholds == null) thresholds = sThresholds;
+        }
+
+        int level = thresholds.length;
+        switch (calcMethod) {
+            case LEVEL_CALCULATION_METHOD_RSCP:
+                if (mRscp < WCDMA_RSCP_MIN || mRscp > WCDMA_RSCP_MAX) {
+                    mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+                    return;
+                }
+                while (level > 0 && mRscp < thresholds[level - 1]) level--;
+                mLevel = level;
+                return;
+            case LEVEL_CALCULATION_METHOD_RSSI:
+                if (mRssi < WCDMA_RSSI_MIN || mRssi > WCDMA_RSSI_MAX) {
+                    mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+                    return;
+                }
+                while (level > 0 && mRssi < thresholds[level - 1]) level--;
+                mLevel = level;
+                return;
+            default:
+                mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        }
     }
 
     /**
@@ -116,57 +183,66 @@
      */
     @Override
     public int getDbm() {
-        int dBm;
-
-        int level = mSignalStrength;
-        int asu = (level == 99 ? CellInfo.UNAVAILABLE : level);
-        if (asu != CellInfo.UNAVAILABLE) {
-            dBm = -113 + (2 * asu);
-        } else {
-            dBm = CellInfo.UNAVAILABLE;
-        }
-        if (DBG) log("getDbm=" + dBm);
-        return dBm;
+        if (mRscp != CellInfo.UNAVAILABLE) return mRscp;
+        return mRssi;
     }
 
     /**
-     * Get the signal level as an asu value between 0..31, 99 is unknown
-     * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+     * Get the RSCP in ASU.
+     *
+     * Asu is calculated based on 3GPP RSCP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+     *
+     * @return RSCP in ASU 0..96, 255, or UNAVAILABLE
      */
     @Override
     public int getAsuLevel() {
-        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
-        // asu = 0 (-113dB or less) is very weak
-        // signal, its better to show 0 bars to the user in such cases.
-        // asu = 99 is a special case, where the signal strength is unknown.
-        int level = mSignalStrength;
-        if (DBG) log("getAsuLevel=" + level);
-        return level;
+        if (mRscp != CellInfo.UNAVAILABLE) return getAsuFromRscpDbm(mRscp);
+        // For historical reasons, if RSCP is unavailable, this API will very incorrectly return
+        // RSSI. This hackery will be removed when most devices are using Radio HAL 1.2+
+        if (mRssi != CellInfo.UNAVAILABLE) return getAsuFromRssiDbm(mRssi);
+        return getAsuFromRscpDbm(CellInfo.UNAVAILABLE);
+    }
+
+    /**
+     * Get the signal strength as dBm
+     *
+     * @hide
+     */
+    public int getRssi() {
+        return mRssi;
+    }
+
+    /**
+     * Get the RSCP as dBm
+     * @hide
+     */
+    public int getRscp() {
+        return mRscp;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mSignalStrength, mBitErrorRate);
+        return Objects.hash(mRssi, mBitErrorRate, mRscp, mEcNo, mLevel);
+    }
+
+    private static final CellSignalStrengthWcdma sInvalid = new CellSignalStrengthWcdma();
+
+    /** @hide */
+    @Override
+    public boolean isValid() {
+        return !this.equals(sInvalid);
     }
 
     @Override
-    public boolean equals (Object o) {
-        CellSignalStrengthWcdma s;
+    public boolean equals(Object o) {
+        if (!(o instanceof CellSignalStrengthWcdma)) return false;
+        CellSignalStrengthWcdma s = (CellSignalStrengthWcdma) o;
 
-        try {
-            s = (CellSignalStrengthWcdma) o;
-        } catch (ClassCastException ex) {
-            return false;
-        }
-
-        if (o == null) {
-            return false;
-        }
-
-        return mSignalStrength == s.mSignalStrength
+        return mRssi == s.mRssi
                 && mBitErrorRate == s.mBitErrorRate
                 && mRscp == s.mRscp
-                && mEcNo == s.mEcNo;
+                && mEcNo == s.mEcNo
+                && mLevel == s.mLevel;
     }
 
     /**
@@ -175,20 +251,22 @@
     @Override
     public String toString() {
         return "CellSignalStrengthWcdma:"
-                + " ss=" + mSignalStrength
+                + " ss=" + mRssi
                 + " ber=" + mBitErrorRate
                 + " rscp=" + mRscp
-                + " ecno=" + mEcNo;
+                + " ecno=" + mEcNo
+                + " level=" + mLevel;
     }
 
     /** Implement the Parcelable interface */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        dest.writeInt(mSignalStrength);
+        dest.writeInt(mRssi);
         dest.writeInt(mBitErrorRate);
         dest.writeInt(mRscp);
         dest.writeInt(mEcNo);
+        dest.writeInt(mLevel);
     }
 
     /**
@@ -196,10 +274,11 @@
      * where the token is already been processed.
      */
     private CellSignalStrengthWcdma(Parcel in) {
-        mSignalStrength = in.readInt();
+        mRssi = in.readInt();
         mBitErrorRate = in.readInt();
         mRscp = in.readInt();
         mEcNo = in.readInt();
+        mLevel = in.readInt();
         if (DBG) log("CellSignalStrengthWcdma(Parcel): " + toString());
     }
 
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index c6f7d0e..c53b37d 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -15,151 +15,383 @@
  */
 package android.telephony;
 
+import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.content.Context;
 import android.os.PersistableBundle;
 
+import com.android.internal.util.ArrayUtils;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
 /**
- * Returned as the reason for a connection failure as defined
- * by RIL_DataCallFailCause in ril.h and some local errors.
+ * Returned as the reason for a data connection failure as defined by modem and some local errors.
  * @hide
  */
-public enum DataFailCause {
-    NONE(0),
+public final class DataFailCause {
+    /** There is no failure */
+    public static final int NONE = 0;
 
     // This series of errors as specified by the standards
     // specified in ril.h
-    OPERATOR_BARRED(0x08),                  /* no retry */
-    NAS_SIGNALLING(0x0E),
-    LLC_SNDCP(0x19),
-    INSUFFICIENT_RESOURCES(0x1A),
-    MISSING_UNKNOWN_APN(0x1B),              /* no retry */
-    UNKNOWN_PDP_ADDRESS_TYPE(0x1C),         /* no retry */
-    USER_AUTHENTICATION(0x1D),              /* no retry */
-    ACTIVATION_REJECT_GGSN(0x1E),           /* no retry */
-    ACTIVATION_REJECT_UNSPECIFIED(0x1F),
-    SERVICE_OPTION_NOT_SUPPORTED(0x20),     /* no retry */
-    SERVICE_OPTION_NOT_SUBSCRIBED(0x21),    /* no retry */
-    SERVICE_OPTION_OUT_OF_ORDER(0x22),
-    NSAPI_IN_USE(0x23),                     /* no retry */
-    REGULAR_DEACTIVATION(0x24),             /* possibly restart radio, based on config */
-    QOS_NOT_ACCEPTED(0x25),
-    NETWORK_FAILURE(0x26),
-    UMTS_REACTIVATION_REQ(0x27),
-    FEATURE_NOT_SUPP(0x28),
-    TFT_SEMANTIC_ERROR(0x29),
-    TFT_SYTAX_ERROR(0x2A),
-    UNKNOWN_PDP_CONTEXT(0x2B),
-    FILTER_SEMANTIC_ERROR(0x2C),
-    FILTER_SYTAX_ERROR(0x2D),
-    PDP_WITHOUT_ACTIVE_TFT(0x2E),
-    ONLY_IPV4_ALLOWED(0x32),                /* no retry */
-    ONLY_IPV6_ALLOWED(0x33),                /* no retry */
-    ONLY_SINGLE_BEARER_ALLOWED(0x34),
-    ESM_INFO_NOT_RECEIVED(0x35),
-    PDN_CONN_DOES_NOT_EXIST(0x36),
-    MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED(0x37),
-    MAX_ACTIVE_PDP_CONTEXT_REACHED(0x41),
-    UNSUPPORTED_APN_IN_CURRENT_PLMN(0x42),
-    INVALID_TRANSACTION_ID(0x51),
-    MESSAGE_INCORRECT_SEMANTIC(0x5F),
-    INVALID_MANDATORY_INFO(0x60),
-    MESSAGE_TYPE_UNSUPPORTED(0x61),
-    MSG_TYPE_NONCOMPATIBLE_STATE(0x62),
-    UNKNOWN_INFO_ELEMENT(0x63),
-    CONDITIONAL_IE_ERROR(0x64),
-    MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE(0x65),
-    PROTOCOL_ERRORS(0x6F),                  /* no retry */
-    APN_TYPE_CONFLICT(0x70),
-    INVALID_PCSCF_ADDR(0x71),
-    INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN(0x72),
-    EMM_ACCESS_BARRED(0x73),
-    EMERGENCY_IFACE_ONLY(0x74),
-    IFACE_MISMATCH(0x75),
-    COMPANION_IFACE_IN_USE(0x76),
-    IP_ADDRESS_MISMATCH(0x77),
-    IFACE_AND_POL_FAMILY_MISMATCH(0x78),
-    EMM_ACCESS_BARRED_INFINITE_RETRY(0x79),
-    AUTH_FAILURE_ON_EMERGENCY_CALL(0x7A),
+    /** Operator determined barring. */
+    public static final int OPERATOR_BARRED = 0x08;
+    /** NAS signalling. */
+    public static final int NAS_SIGNALLING = 0x0E;
+    /** Logical Link Control (LLC) Sub Network Dependent Convergence Protocol (SNDCP). */
+    public static final int LLC_SNDCP = 0x19;
+    /** Insufficient resources. */
+    public static final int INSUFFICIENT_RESOURCES = 0x1A;
+    /** Missing or unknown APN. */
+    public static final int MISSING_UNKNOWN_APN = 0x1B;              /* no retry */
+    /** Unknown Packet Data Protocol (PDP) address type. */
+    public static final int UNKNOWN_PDP_ADDRESS_TYPE = 0x1C;         /* no retry */
+    /** User authentication. */
+    public static final int USER_AUTHENTICATION = 0x1D;              /* no retry */
+    /** Activation rejected by Gateway GPRS Support Node (GGSN), Serving Gateway or PDN Gateway. */
+    public static final int ACTIVATION_REJECT_GGSN = 0x1E;           /* no retry */
+    /** Activation rejected, unspecified. */
+    public static final int ACTIVATION_REJECT_UNSPECIFIED = 0x1F;
+    /** Service option not supported. */
+    public static final int SERVICE_OPTION_NOT_SUPPORTED = 0x20;     /* no retry */
+    /** Requested service option not subscribed. */
+    public static final int SERVICE_OPTION_NOT_SUBSCRIBED = 0x21;    /* no retry */
+    /** Service option temporarily out of order. */
+    public static final int SERVICE_OPTION_OUT_OF_ORDER = 0x22;
+    /** The Network Service Access Point Identifier (NSAPI) is in use. */
+    public static final int NSAPI_IN_USE = 0x23;                     /* no retry */
+    /* possibly restart radio, based on config */
+    /** Regular deactivation. */
+    public static final int REGULAR_DEACTIVATION = 0x24;
+    /** Quality of service (QoS) is not accepted. */
+    public static final int QOS_NOT_ACCEPTED = 0x25;
+    /** Network Failure. */
+    public static final int NETWORK_FAILURE = 0x26;
+    /** Universal Mobile Telecommunications System (UMTS) reactivation request. */
+    public static final int UMTS_REACTIVATION_REQ = 0x27;
+    /** Feature not supported. */
+    public static final int FEATURE_NOT_SUPP = 0x28;
+    /** Semantic error in the Traffic flow templates (TFT) operation. */
+    public static final int TFT_SEMANTIC_ERROR = 0x29;
+    /** Syntactical error in the Traffic flow templates (TFT) operation. */
+    public static final int TFT_SYTAX_ERROR = 0x2A;
+    /** Unknown Packet Data Protocol (PDP) context. */
+    public static final int UNKNOWN_PDP_CONTEXT = 0x2B;
+    /** Semantic errors in packet filter. */
+    public static final int FILTER_SEMANTIC_ERROR = 0x2C;
+    /** Syntactical errors in packet filter(s). */
+    public static final int FILTER_SYTAX_ERROR = 0x2D;
+    /** Packet Data Protocol (PDP) without active traffic flow template (TFT). */
+    public static final int PDP_WITHOUT_ACTIVE_TFT = 0x2E;
+    /** Packet Data Protocol (PDP) type IPv4 only allowed. */
+    public static final int ONLY_IPV4_ALLOWED = 0x32;                /* no retry */
+    /** Packet Data Protocol (PDP) type IPv6 only allowed. */
+    public static final int ONLY_IPV6_ALLOWED = 0x33;                /* no retry */
+    /** Single address bearers only allowed. */
+    public static final int ONLY_SINGLE_BEARER_ALLOWED = 0x34;
+    /** EPS Session Management (ESM) information is not received. */
+    public static final int ESM_INFO_NOT_RECEIVED = 0x35;
+    /** PDN connection does not exist. */
+    public static final int PDN_CONN_DOES_NOT_EXIST = 0x36;
+    /** Multiple connections to a same PDN is not allowed. */
+    public static final int MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED = 0x37;
+    /** Packet Data Protocol (PDP) */
+    public static final int MAX_ACTIVE_PDP_CONTEXT_REACHED = 0x41;
+    /** Unsupported APN in current public land mobile network (PLMN). */
+    public static final int UNSUPPORTED_APN_IN_CURRENT_PLMN = 0x42;
+    /** Invalid transaction id. */
+    public static final int INVALID_TRANSACTION_ID = 0x51;
+    /** Incorrect message semantic. */
+    public static final int MESSAGE_INCORRECT_SEMANTIC = 0x5F;
+    /** Invalid mandatory information. */
+    public static final int INVALID_MANDATORY_INFO = 0x60;
+    /** Unsupported message type. */
+    public static final int MESSAGE_TYPE_UNSUPPORTED = 0x61;
+    /** Message type uncompatible. */
+    public static final int MSG_TYPE_NONCOMPATIBLE_STATE = 0x62;
+    /** Unknown info element. */
+    public static final int UNKNOWN_INFO_ELEMENT = 0x63;
+    /** Conditional Information Element (IE) error. */
+    public static final int CONDITIONAL_IE_ERROR = 0x64;
+    /** Message and protocol state uncompatible. */
+    public static final int MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE = 0x65;
+    /** Protocol errors. */
+    public static final int PROTOCOL_ERRORS = 0x6F;                  /* no retry */
+    /** APN type conflict. */
+    public static final int APN_TYPE_CONFLICT = 0x70;
+    /** Invalid Proxy-Call Session Control Function (P-CSCF) address. */
+    public static final int INVALID_PCSCF_ADDR = 0x71;
+    /** Internal data call preempt by high priority APN. */
+    public static final int INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN = 0x72;
+    /** EPS (Evolved Packet System) Mobility Management (EMM) access barred. */
+    public static final int EMM_ACCESS_BARRED = 0x73;
+    /** Emergency interface only. */
+    public static final int EMERGENCY_IFACE_ONLY = 0x74;
+    /** Interface mismatch. */
+    public static final int IFACE_MISMATCH = 0x75;
+    /** Companion interface in use. */
+    public static final int COMPANION_IFACE_IN_USE = 0x76;
+    /** IP address mismatch. */
+    public static final int IP_ADDRESS_MISMATCH = 0x77;
+    public static final int IFACE_AND_POL_FAMILY_MISMATCH = 0x78;
+    /** EPS (Evolved Packet System) Mobility Management (EMM) access barred infinity retry. **/
+    public static final int EMM_ACCESS_BARRED_INFINITE_RETRY = 0x79;
+    /** Authentication failure on emergency call. */
+    public static final int AUTH_FAILURE_ON_EMERGENCY_CALL = 0x7A;
 
     // OEM sepecific error codes. To be used by OEMs when they don't
     // want to reveal error code which would be replaced by ERROR_UNSPECIFIED
-    OEM_DCFAILCAUSE_1(0x1001),
-    OEM_DCFAILCAUSE_2(0x1002),
-    OEM_DCFAILCAUSE_3(0x1003),
-    OEM_DCFAILCAUSE_4(0x1004),
-    OEM_DCFAILCAUSE_5(0x1005),
-    OEM_DCFAILCAUSE_6(0x1006),
-    OEM_DCFAILCAUSE_7(0x1007),
-    OEM_DCFAILCAUSE_8(0x1008),
-    OEM_DCFAILCAUSE_9(0x1009),
-    OEM_DCFAILCAUSE_10(0x100A),
-    OEM_DCFAILCAUSE_11(0x100B),
-    OEM_DCFAILCAUSE_12(0x100C),
-    OEM_DCFAILCAUSE_13(0x100D),
-    OEM_DCFAILCAUSE_14(0x100E),
-    OEM_DCFAILCAUSE_15(0x100F),
+    public static final int OEM_DCFAILCAUSE_1 = 0x1001;
+    public static final int OEM_DCFAILCAUSE_2 = 0x1002;
+    public static final int OEM_DCFAILCAUSE_3 = 0x1003;
+    public static final int OEM_DCFAILCAUSE_4 = 0x1004;
+    public static final int OEM_DCFAILCAUSE_5 = 0x1005;
+    public static final int OEM_DCFAILCAUSE_6 = 0x1006;
+    public static final int OEM_DCFAILCAUSE_7 = 0x1007;
+    public static final int OEM_DCFAILCAUSE_8 = 0x1008;
+    public static final int OEM_DCFAILCAUSE_9 = 0x1009;
+    public static final int OEM_DCFAILCAUSE_10 = 0x100A;
+    public static final int OEM_DCFAILCAUSE_11 = 0x100B;
+    public static final int OEM_DCFAILCAUSE_12 = 0x100C;
+    public static final int OEM_DCFAILCAUSE_13 = 0x100D;
+    public static final int OEM_DCFAILCAUSE_14 = 0x100E;
+    public static final int OEM_DCFAILCAUSE_15 = 0x100F;
 
     // Local errors generated by Vendor RIL
     // specified in ril.h
-    REGISTRATION_FAIL(-1),
-    GPRS_REGISTRATION_FAIL(-2),
-    SIGNAL_LOST(-3),                        /* no retry */
-    PREF_RADIO_TECH_CHANGED(-4),
-    RADIO_POWER_OFF(-5),                    /* no retry */
-    TETHERED_CALL_ACTIVE(-6),               /* no retry */
-    ERROR_UNSPECIFIED(0xFFFF),
+    public static final int REGISTRATION_FAIL = -1;
+    public static final int GPRS_REGISTRATION_FAIL = -2;
+    public static final int SIGNAL_LOST = -3;                        /* no retry */
+    public static final int PREF_RADIO_TECH_CHANGED = -4;
+    public static final int RADIO_POWER_OFF = -5;                    /* no retry */
+    public static final int TETHERED_CALL_ACTIVE = -6;               /* no retry */
+    public static final int ERROR_UNSPECIFIED = 0xFFFF;
 
     // Errors generated by the Framework
     // specified here
-    UNKNOWN(0x10000),
-    RADIO_NOT_AVAILABLE(0x10001),                   /* no retry */
-    UNACCEPTABLE_NETWORK_PARAMETER(0x10002),        /* no retry */
-    CONNECTION_TO_DATACONNECTIONAC_BROKEN(0x10003),
-    LOST_CONNECTION(0x10004),
-    RESET_BY_FRAMEWORK(0x10005);
+    public static final int UNKNOWN = 0x10000;
+    public static final int RADIO_NOT_AVAILABLE = 0x10001;                   /* no retry */
+    public static final int UNACCEPTABLE_NETWORK_PARAMETER = 0x10002;        /* no retry */
+    public static final int CONNECTION_TO_DATACONNECTIONAC_BROKEN = 0x10003;
+    public static final int LOST_CONNECTION = 0x10004;
+    /** Data was reset by framework. */
+    public static final int RESET_BY_FRAMEWORK = 0x10005;
 
-    private final int mErrorCode;
-    private static final HashMap<Integer, DataFailCause> sErrorCodeToFailCauseMap;
+    /** @hide */
+    @IntDef(value = {
+            NONE,
+            OPERATOR_BARRED,
+            NAS_SIGNALLING,
+            LLC_SNDCP,
+            INSUFFICIENT_RESOURCES,
+            MISSING_UNKNOWN_APN,
+            UNKNOWN_PDP_ADDRESS_TYPE,
+            USER_AUTHENTICATION,
+            ACTIVATION_REJECT_GGSN,
+            ACTIVATION_REJECT_UNSPECIFIED,
+            SERVICE_OPTION_NOT_SUPPORTED,
+            SERVICE_OPTION_NOT_SUBSCRIBED,
+            SERVICE_OPTION_OUT_OF_ORDER,
+            NSAPI_IN_USE,
+            REGULAR_DEACTIVATION,
+            QOS_NOT_ACCEPTED,
+            NETWORK_FAILURE,
+            UMTS_REACTIVATION_REQ,
+            FEATURE_NOT_SUPP,
+            TFT_SEMANTIC_ERROR,
+            TFT_SYTAX_ERROR,
+            UNKNOWN_PDP_CONTEXT,
+            FILTER_SEMANTIC_ERROR,
+            FILTER_SYTAX_ERROR,
+            PDP_WITHOUT_ACTIVE_TFT,
+            ONLY_IPV4_ALLOWED,
+            ONLY_IPV6_ALLOWED,
+            ONLY_SINGLE_BEARER_ALLOWED,
+            ESM_INFO_NOT_RECEIVED,
+            PDN_CONN_DOES_NOT_EXIST,
+            MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED,
+            MAX_ACTIVE_PDP_CONTEXT_REACHED,
+            UNSUPPORTED_APN_IN_CURRENT_PLMN,
+            INVALID_TRANSACTION_ID,
+            MESSAGE_INCORRECT_SEMANTIC,
+            INVALID_MANDATORY_INFO,
+            MESSAGE_TYPE_UNSUPPORTED,
+            MSG_TYPE_NONCOMPATIBLE_STATE,
+            UNKNOWN_INFO_ELEMENT,
+            CONDITIONAL_IE_ERROR,
+            MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE,
+            PROTOCOL_ERRORS,                 /* no retry */
+            APN_TYPE_CONFLICT,
+            INVALID_PCSCF_ADDR,
+            INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN,
+            EMM_ACCESS_BARRED,
+            EMERGENCY_IFACE_ONLY,
+            IFACE_MISMATCH,
+            COMPANION_IFACE_IN_USE,
+            IP_ADDRESS_MISMATCH,
+            IFACE_AND_POL_FAMILY_MISMATCH,
+            EMM_ACCESS_BARRED_INFINITE_RETRY,
+            AUTH_FAILURE_ON_EMERGENCY_CALL,
+            OEM_DCFAILCAUSE_1,
+            OEM_DCFAILCAUSE_2,
+            OEM_DCFAILCAUSE_3,
+            OEM_DCFAILCAUSE_4,
+            OEM_DCFAILCAUSE_5,
+            OEM_DCFAILCAUSE_6,
+            OEM_DCFAILCAUSE_7,
+            OEM_DCFAILCAUSE_8,
+            OEM_DCFAILCAUSE_9,
+            OEM_DCFAILCAUSE_10,
+            OEM_DCFAILCAUSE_11,
+            OEM_DCFAILCAUSE_12,
+            OEM_DCFAILCAUSE_13,
+            OEM_DCFAILCAUSE_14,
+            OEM_DCFAILCAUSE_15,
+            REGISTRATION_FAIL,
+            GPRS_REGISTRATION_FAIL,
+            SIGNAL_LOST,
+            PREF_RADIO_TECH_CHANGED,
+            RADIO_POWER_OFF,
+            TETHERED_CALL_ACTIVE,
+            ERROR_UNSPECIFIED,
+            UNKNOWN,
+            RADIO_NOT_AVAILABLE,
+            UNACCEPTABLE_NETWORK_PARAMETER,
+            CONNECTION_TO_DATACONNECTIONAC_BROKEN,
+            LOST_CONNECTION,
+            RESET_BY_FRAMEWORK
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FailCause{}
+
+    private static final Map<Integer, String> sFailCauseMap;
     static {
-        sErrorCodeToFailCauseMap = new HashMap<Integer, DataFailCause>();
-        for (DataFailCause fc : values()) {
-            sErrorCodeToFailCauseMap.put(fc.getErrorCode(), fc);
-        }
+        sFailCauseMap = new HashMap<>();
+        sFailCauseMap.put(NONE, "NONE");
+        sFailCauseMap.put(OPERATOR_BARRED, "OPERATOR_BARRED");
+        sFailCauseMap.put(NAS_SIGNALLING, "NAS_SIGNALLING");
+        sFailCauseMap.put(LLC_SNDCP, "LLC_SNDCP");
+        sFailCauseMap.put(INSUFFICIENT_RESOURCES, "INSUFFICIENT_RESOURCES");
+        sFailCauseMap.put(MISSING_UNKNOWN_APN, "MISSING_UNKNOWN_APN");
+        sFailCauseMap.put(UNKNOWN_PDP_ADDRESS_TYPE, "UNKNOWN_PDP_ADDRESS_TYPE");
+        sFailCauseMap.put(USER_AUTHENTICATION, "USER_AUTHENTICATION");
+        sFailCauseMap.put(ACTIVATION_REJECT_GGSN, "ACTIVATION_REJECT_GGSN");
+        sFailCauseMap.put(ACTIVATION_REJECT_UNSPECIFIED,
+                "ACTIVATION_REJECT_UNSPECIFIED");
+        sFailCauseMap.put(SERVICE_OPTION_NOT_SUPPORTED,
+                "SERVICE_OPTION_NOT_SUPPORTED");
+        sFailCauseMap.put(SERVICE_OPTION_NOT_SUBSCRIBED,
+                "SERVICE_OPTION_NOT_SUBSCRIBED");
+        sFailCauseMap.put(SERVICE_OPTION_OUT_OF_ORDER, "SERVICE_OPTION_OUT_OF_ORDER");
+        sFailCauseMap.put(NSAPI_IN_USE, "NSAPI_IN_USE");
+        sFailCauseMap.put(REGULAR_DEACTIVATION, "REGULAR_DEACTIVATION");
+        sFailCauseMap.put(QOS_NOT_ACCEPTED, "QOS_NOT_ACCEPTED");
+        sFailCauseMap.put(NETWORK_FAILURE, "NETWORK_FAILURE");
+        sFailCauseMap.put(UMTS_REACTIVATION_REQ, "UMTS_REACTIVATION_REQ");
+        sFailCauseMap.put(FEATURE_NOT_SUPP, "FEATURE_NOT_SUPP");
+        sFailCauseMap.put(TFT_SEMANTIC_ERROR, "TFT_SEMANTIC_ERROR");
+        sFailCauseMap.put(TFT_SYTAX_ERROR, "TFT_SYTAX_ERROR");
+        sFailCauseMap.put(UNKNOWN_PDP_CONTEXT, "UNKNOWN_PDP_CONTEXT");
+        sFailCauseMap.put(FILTER_SEMANTIC_ERROR, "FILTER_SEMANTIC_ERROR");
+        sFailCauseMap.put(FILTER_SYTAX_ERROR, "FILTER_SYTAX_ERROR");
+        sFailCauseMap.put(PDP_WITHOUT_ACTIVE_TFT, "PDP_WITHOUT_ACTIVE_TFT");
+        sFailCauseMap.put(ONLY_IPV4_ALLOWED, "ONLY_IPV4_ALLOWED");
+        sFailCauseMap.put(ONLY_IPV6_ALLOWED, "ONLY_IPV6_ALLOWED");
+        sFailCauseMap.put(ONLY_SINGLE_BEARER_ALLOWED, "ONLY_SINGLE_BEARER_ALLOWED");
+        sFailCauseMap.put(ESM_INFO_NOT_RECEIVED, "ESM_INFO_NOT_RECEIVED");
+        sFailCauseMap.put(PDN_CONN_DOES_NOT_EXIST, "PDN_CONN_DOES_NOT_EXIST");
+        sFailCauseMap.put(MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED,
+                "MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED");
+        sFailCauseMap.put(MAX_ACTIVE_PDP_CONTEXT_REACHED,
+                "MAX_ACTIVE_PDP_CONTEXT_REACHED");
+        sFailCauseMap.put(UNSUPPORTED_APN_IN_CURRENT_PLMN,
+                "UNSUPPORTED_APN_IN_CURRENT_PLMN");
+        sFailCauseMap.put(INVALID_TRANSACTION_ID, "INVALID_TRANSACTION_ID");
+        sFailCauseMap.put(MESSAGE_INCORRECT_SEMANTIC, "MESSAGE_INCORRECT_SEMANTIC");
+        sFailCauseMap.put(INVALID_MANDATORY_INFO, "INVALID_MANDATORY_INFO");
+        sFailCauseMap.put(MESSAGE_TYPE_UNSUPPORTED, "MESSAGE_TYPE_UNSUPPORTED");
+        sFailCauseMap.put(MSG_TYPE_NONCOMPATIBLE_STATE, "MSG_TYPE_NONCOMPATIBLE_STATE");
+        sFailCauseMap.put(UNKNOWN_INFO_ELEMENT, "UNKNOWN_INFO_ELEMENT");
+        sFailCauseMap.put(CONDITIONAL_IE_ERROR, "CONDITIONAL_IE_ERROR");
+        sFailCauseMap.put(MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE,
+                "MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE");
+        sFailCauseMap.put(PROTOCOL_ERRORS, "PROTOCOL_ERRORS");
+        sFailCauseMap.put(APN_TYPE_CONFLICT, "APN_TYPE_CONFLICT");
+        sFailCauseMap.put(INVALID_PCSCF_ADDR, "INVALID_PCSCF_ADDR");
+        sFailCauseMap.put(INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN,
+                "INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN");
+        sFailCauseMap.put(EMM_ACCESS_BARRED, "EMM_ACCESS_BARRED");
+        sFailCauseMap.put(EMERGENCY_IFACE_ONLY, "EMERGENCY_IFACE_ONLY");
+        sFailCauseMap.put(IFACE_MISMATCH, "IFACE_MISMATCH");
+        sFailCauseMap.put(COMPANION_IFACE_IN_USE, "COMPANION_IFACE_IN_USE");
+        sFailCauseMap.put(IP_ADDRESS_MISMATCH, "IP_ADDRESS_MISMATCH");
+        sFailCauseMap.put(IFACE_AND_POL_FAMILY_MISMATCH,
+                "IFACE_AND_POL_FAMILY_MISMATCH");
+        sFailCauseMap.put(EMM_ACCESS_BARRED_INFINITE_RETRY,
+                "EMM_ACCESS_BARRED_INFINITE_RETRY");
+        sFailCauseMap.put(AUTH_FAILURE_ON_EMERGENCY_CALL,
+                "AUTH_FAILURE_ON_EMERGENCY_CALL");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_1, "OEM_DCFAILCAUSE_1");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_2, "OEM_DCFAILCAUSE_2");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_3, "OEM_DCFAILCAUSE_3");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_4, "OEM_DCFAILCAUSE_4");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_5, "OEM_DCFAILCAUSE_5");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_6, "OEM_DCFAILCAUSE_6");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_7, "OEM_DCFAILCAUSE_7");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_8, "OEM_DCFAILCAUSE_8");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_9, "OEM_DCFAILCAUSE_9");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_10, "OEM_DCFAILCAUSE_10");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_11, "OEM_DCFAILCAUSE_11");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_12, "OEM_DCFAILCAUSE_12");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_13, "OEM_DCFAILCAUSE_13");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_14, "OEM_DCFAILCAUSE_14");
+        sFailCauseMap.put(OEM_DCFAILCAUSE_15, "OEM_DCFAILCAUSE_15");
+        sFailCauseMap.put(REGISTRATION_FAIL, "REGISTRATION_FAIL");
+        sFailCauseMap.put(GPRS_REGISTRATION_FAIL, "GPRS_REGISTRATION_FAIL");
+        sFailCauseMap.put(SIGNAL_LOST, "SIGNAL_LOST");
+        sFailCauseMap.put(PREF_RADIO_TECH_CHANGED, "PREF_RADIO_TECH_CHANGED");
+        sFailCauseMap.put(RADIO_POWER_OFF, "RADIO_POWER_OFF");
+        sFailCauseMap.put(TETHERED_CALL_ACTIVE, "TETHERED_CALL_ACTIVE");
+        sFailCauseMap.put(ERROR_UNSPECIFIED, "ERROR_UNSPECIFIED");
+        sFailCauseMap.put(UNKNOWN, "UNKNOWN");
+        sFailCauseMap.put(RADIO_NOT_AVAILABLE, "RADIO_NOT_AVAILABLE");
+        sFailCauseMap.put(UNACCEPTABLE_NETWORK_PARAMETER,
+                "UNACCEPTABLE_NETWORK_PARAMETER");
+        sFailCauseMap.put(CONNECTION_TO_DATACONNECTIONAC_BROKEN,
+                "CONNECTION_TO_DATACONNECTIONAC_BROKEN");
+        sFailCauseMap.put(LOST_CONNECTION, "LOST_CONNECTION");
+        sFailCauseMap.put(RESET_BY_FRAMEWORK, "RESET_BY_FRAMEWORK");
     }
 
     /**
      * Map of subId -> set of data call setup permanent failure for the carrier.
      */
-    private static final HashMap<Integer, HashSet<DataFailCause>> sPermanentFailureCache =
+    private static final HashMap<Integer, Set<Integer>> sPermanentFailureCache =
             new HashMap<>();
 
-    DataFailCause(int errorCode) {
-        mErrorCode = errorCode;
-    }
-
-    public int getErrorCode() {
-        return mErrorCode;
-    }
-
     /**
      * Returns whether or not the fail cause is a failure that requires a modem restart
      *
      * @param context device context
+     * @param cause data disconnect cause
      * @param subId subscription index
      * @return true if the fail cause code needs platform to trigger a modem restart.
      */
-    public boolean isRadioRestartFailure(Context context, int subId) {
+    public static boolean isRadioRestartFailure(@NonNull Context context, @FailCause int cause,
+                                                int subId) {
         CarrierConfigManager configManager = (CarrierConfigManager)
                 context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
         if (configManager != null) {
             PersistableBundle b = configManager.getConfigForSubId(subId);
 
             if (b != null) {
-                if (this == REGULAR_DEACTIVATION
+                if (cause == REGULAR_DEACTIVATION
                         && b.getBoolean(CarrierConfigManager
                         .KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL)) {
                     // This is for backward compatibility support. We need to continue support this
@@ -170,7 +402,7 @@
                 int[] causeCodes = b.getIntArray(CarrierConfigManager
                         .KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY);
                 if (causeCodes != null) {
-                    return Arrays.stream(causeCodes).anyMatch(i -> i == getErrorCode());
+                    return Arrays.stream(causeCodes).anyMatch(i -> i == cause);
                 }
             }
         }
@@ -178,11 +410,11 @@
         return false;
     }
 
-    public boolean isPermanentFailure(Context context, int subId) {
-
+    public static boolean isPermanentFailure(@NonNull Context context, @FailCause int failCause,
+                                             int subId) {
         synchronized (sPermanentFailureCache) {
 
-            HashSet<DataFailCause> permanentFailureSet = sPermanentFailureCache.get(subId);
+            Set<Integer> permanentFailureSet = sPermanentFailureCache.get(subId);
 
             // In case of cache miss, we need to look up the settings from carrier config.
             if (permanentFailureSet == null) {
@@ -194,11 +426,12 @@
                     if (b != null) {
                         String[] permanentFailureStrings = b.getStringArray(CarrierConfigManager.
                                 KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS);
-
                         if (permanentFailureStrings != null) {
                             permanentFailureSet = new HashSet<>();
-                            for (String failure : permanentFailureStrings) {
-                                permanentFailureSet.add(DataFailCause.valueOf(failure));
+                            for (Map.Entry<Integer, String> e : sFailCauseMap.entrySet()) {
+                                if (ArrayUtils.contains(permanentFailureStrings, e.getValue())) {
+                                    permanentFailureSet.add(e.getKey());
+                                }
                             }
                         }
                     }
@@ -207,7 +440,7 @@
                 // If we are not able to find the configuration from carrier config, use the default
                 // ones.
                 if (permanentFailureSet == null) {
-                    permanentFailureSet = new HashSet<DataFailCause>() {
+                    permanentFailureSet = new HashSet<Integer>() {
                         {
                             add(OPERATOR_BARRED);
                             add(MISSING_UNKNOWN_APN);
@@ -232,28 +465,39 @@
                 sPermanentFailureCache.put(subId, permanentFailureSet);
             }
 
-            return permanentFailureSet.contains(this);
+            return permanentFailureSet.contains(failCause);
         }
     }
 
-    public boolean isEventLoggable() {
-        return (this == OPERATOR_BARRED) || (this == INSUFFICIENT_RESOURCES) ||
-                (this == UNKNOWN_PDP_ADDRESS_TYPE) || (this == USER_AUTHENTICATION) ||
-                (this == ACTIVATION_REJECT_GGSN) || (this == ACTIVATION_REJECT_UNSPECIFIED) ||
-                (this == SERVICE_OPTION_NOT_SUBSCRIBED) ||
-                (this == SERVICE_OPTION_NOT_SUPPORTED) ||
-                (this == SERVICE_OPTION_OUT_OF_ORDER) || (this == NSAPI_IN_USE) ||
-                (this == ONLY_IPV4_ALLOWED) || (this == ONLY_IPV6_ALLOWED) ||
-                (this == PROTOCOL_ERRORS) || (this == SIGNAL_LOST) ||
-                (this == RADIO_POWER_OFF) || (this == TETHERED_CALL_ACTIVE) ||
-                (this == UNACCEPTABLE_NETWORK_PARAMETER);
+    public static boolean isEventLoggable(@FailCause int dataFailCause) {
+        return (dataFailCause == OPERATOR_BARRED) || (dataFailCause == INSUFFICIENT_RESOURCES)
+                || (dataFailCause == UNKNOWN_PDP_ADDRESS_TYPE)
+                || (dataFailCause == USER_AUTHENTICATION)
+                || (dataFailCause == ACTIVATION_REJECT_GGSN)
+                || (dataFailCause == ACTIVATION_REJECT_UNSPECIFIED)
+                || (dataFailCause == SERVICE_OPTION_NOT_SUBSCRIBED)
+                || (dataFailCause == SERVICE_OPTION_NOT_SUPPORTED)
+                || (dataFailCause == SERVICE_OPTION_OUT_OF_ORDER)
+                || (dataFailCause == NSAPI_IN_USE)
+                || (dataFailCause == ONLY_IPV4_ALLOWED)
+                || (dataFailCause == ONLY_IPV6_ALLOWED)
+                || (dataFailCause == PROTOCOL_ERRORS)
+                || (dataFailCause == SIGNAL_LOST)
+                || (dataFailCause == RADIO_POWER_OFF)
+                || (dataFailCause == TETHERED_CALL_ACTIVE)
+                || (dataFailCause == UNACCEPTABLE_NETWORK_PARAMETER);
     }
 
-    public static DataFailCause fromInt(int errorCode) {
-        DataFailCause fc = sErrorCodeToFailCauseMap.get(errorCode);
-        if (fc == null) {
-            fc = UNKNOWN;
+    public static String toString(@FailCause int dataFailCause) {
+        int cause = getFailCause(dataFailCause);
+        return (cause == UNKNOWN) ? "UNKNOWN(" + dataFailCause + ")" : sFailCauseMap.get(cause);
+    }
+
+    public static int getFailCause(@FailCause int failCause) {
+        if (sFailCauseMap.containsKey(failCause)) {
+            return failCause;
+        } else {
+            return UNKNOWN;
         }
-        return fc;
     }
 }
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index c6887ab..f53cb82 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -16,12 +16,16 @@
 
 package android.telephony;
 
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 
 /**
- * Contains disconnect call causes generated by the framework and the RIL.
+ * Describes the cause of a disconnected call. Those disconnect causes can be converted into a more
+ * generic {@link android.telecom.DisconnectCause} object.
+ *
  * @hide
  */
+@SystemApi
 public class DisconnectCause {
 
     /** The disconnect cause is not valid (Not received a disconnect cause) */
@@ -101,8 +105,8 @@
     /** Unknown error or not specified */
     public static final int ERROR_UNSPECIFIED              = 36;
     /**
-     * Only emergency numbers are allowed, but we tried to dial
-     * a non-emergency number.
+     * Only emergency numbers are allowed, but we tried to dial a non-emergency number.
+     * @hide
      */
     // TODO: This should be the same as NOT_EMERGENCY
     public static final int EMERGENCY_ONLY                 = 37;
@@ -115,8 +119,7 @@
      */
     public static final int DIALED_MMI                     = 39;
     /**
-     * We tried to call a voicemail: URI but the device has no
-     * voicemail number configured.
+     * We tried to call a voicemail: URI but the device has no voicemail number configured.
      */
     public static final int VOICEMAIL_NUMBER_MISSING       = 40;
     /**
@@ -129,6 +132,8 @@
      * needs to be triggered by a *disconnect* event, rather than when
      * the InCallScreen first comes to the foreground.  For now we use
      * the needToShowCallLostDialog field for this (see below.)
+     *
+     * @hide
      */
     public static final int CDMA_CALL_LOST                 = 41;
     /**
@@ -169,62 +174,52 @@
 
     /**
      * Stk Call Control modified DIAL request to USSD request.
-     * {@hide}
      */
     public static final int DIAL_MODIFIED_TO_USSD          = 46;
     /**
      * Stk Call Control modified DIAL request to SS request.
-     * {@hide}
      */
     public static final int DIAL_MODIFIED_TO_SS            = 47;
     /**
      * Stk Call Control modified DIAL request to DIAL with modified data.
-     * {@hide}
      */
     public static final int DIAL_MODIFIED_TO_DIAL          = 48;
 
     /**
      * The call was terminated because CDMA phone service and roaming have already been activated.
-     * {@hide}
      */
     public static final int CDMA_ALREADY_ACTIVATED         = 49;
 
     /**
      * The call was terminated because it is not possible to place a video call while TTY is
      * enabled.
-     * {@hide}
      */
     public static final int VIDEO_CALL_NOT_ALLOWED_WHILE_TTY_ENABLED = 50;
 
     /**
      * The call was terminated because it was pulled to another device.
-     * {@hide}
      */
     public static final int CALL_PULLED = 51;
 
     /**
      * The call was terminated because it was answered on another device.
-     * {@hide}
      */
     public static final int ANSWERED_ELSEWHERE = 52;
 
     /**
      * The call was terminated because the maximum allowable number of calls has been reached.
-     * {@hide}
      */
     public static final int MAXIMUM_NUMBER_OF_CALLS_REACHED = 53;
 
     /**
      * The call was terminated because cellular data has been disabled.
      * Used when in a video call and the user disables cellular data via the settings.
-     * {@hide}
      */
     public static final int DATA_DISABLED = 54;
 
     /**
      * The call was terminated because the data policy has disabled cellular data.
      * Used when in a video call and the user has exceeded the device data limit.
-     * {@hide}
      */
     public static final int DATA_LIMIT_REACHED = 55;
 
@@ -237,7 +232,6 @@
     /**
      * The network does not accept the emergency call request because IMEI was used as
      * identification and this cability is not supported by the network.
-     * {@hide}
      */
     public static final int IMEI_NOT_ACCEPTED = 58;
 
@@ -249,7 +243,6 @@
 
     /**
      * The call has failed because of access class barring.
-     * {@hide}
      */
     public static final int IMS_ACCESS_BLOCKED = 60;
 
@@ -265,51 +258,43 @@
 
     /**
      * Emergency call failed with a temporary fail cause and can be redialed on this slot.
-     * {@hide}
      */
     public static final int EMERGENCY_TEMP_FAILURE = 63;
 
     /**
      * Emergency call failed with a permanent fail cause and should not be redialed on this
-     * slot. 
-     * {@hide}
+     * slot.
      */
     public static final int EMERGENCY_PERM_FAILURE = 64;
 
     /**
      * This cause is used to report a normal event only when no other cause in the normal class
      * applies.
-     * {@hide}
      */
     public static final int NORMAL_UNSPECIFIED = 65;
 
     /**
      * Stk Call Control modified DIAL request to video DIAL request.
-     * {@hide}
      */
     public static final int DIAL_MODIFIED_TO_DIAL_VIDEO = 66;
 
     /**
      * Stk Call Control modified Video DIAL request to SS request.
-     * {@hide}
      */
     public static final int DIAL_VIDEO_MODIFIED_TO_SS = 67;
 
     /**
      * Stk Call Control modified Video DIAL request to USSD request.
-     * {@hide}
      */
     public static final int DIAL_VIDEO_MODIFIED_TO_USSD = 68;
 
     /**
      * Stk Call Control modified Video DIAL request to DIAL request.
-     * {@hide}
      */
     public static final int DIAL_VIDEO_MODIFIED_TO_DIAL = 69;
 
     /**
      * Stk Call Control modified Video DIAL request to Video DIAL request.
-     * {@hide}
      */
     public static final int DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO = 70;
 
@@ -359,7 +344,10 @@
         // Do nothing.
     }
 
-    /** Returns descriptive string for the specified disconnect cause. */
+    /**
+     * Returns descriptive string for the specified disconnect cause.
+     * @hide
+     */
     @UnsupportedAppUsage
     public static String toString(int cause) {
         switch (cause) {
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index e8a28ca..2b1628c 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -171,14 +171,14 @@
     public static final int LISTEN_CELL_INFO = 0x00000400;
 
     /**
-     * Listen for precise changes and fails to the device calls (cellular).
+     * Listen for {@link PreciseCallState.State} of ringing, background and foreground calls.
      * {@more}
      * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
      * READ_PRECISE_PHONE_STATE}
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public static final int LISTEN_PRECISE_CALL_STATE                       = 0x00000800;
 
     /**
@@ -316,6 +316,18 @@
      */
     public static final int LISTEN_EMERGENCY_NUMBER_LIST                   = 0x01000000;
 
+    /**
+     * Listen for call disconnect causes which contains {@link DisconnectCause} and
+     * {@link PreciseDisconnectCause}.
+     * {@more}
+     * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+     * READ_PRECISE_PHONE_STATE}
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int LISTEN_CALL_DISCONNECT_CAUSES                  = 0x02000000;
+
     /*
      * Subscription used to listen to the phone state changes
      * @hide
@@ -526,11 +538,23 @@
 
     /**
      * Callback invoked when precise device call state changes.
+     * @param callState {@link PreciseCallState}
+     * @hide
+     */
+    @SystemApi
+    public void onPreciseCallStateChanged(PreciseCallState callState) {
+        // default implementation empty
+    }
+
+    /**
+     * Callback invoked when call disconnect cause changes.
+     * @param disconnectCause {@link DisconnectCause}.
+     * @param preciseDisconnectCause {@link PreciseDisconnectCause}.
      *
      * @hide
      */
-    @UnsupportedAppUsage
-    public void onPreciseCallStateChanged(PreciseCallState callState) {
+    @SystemApi
+    public void onCallDisconnectCauseChanged(int disconnectCause, int preciseDisconnectCause) {
         // default implementation empty
     }
 
@@ -780,6 +804,15 @@
                     () -> mExecutor.execute(() -> psl.onPreciseCallStateChanged(callState)));
         }
 
+        public void onCallDisconnectCauseChanged(int disconnectCause, int preciseDisconnectCause) {
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCallDisconnectCauseChanged(
+                            disconnectCause, preciseDisconnectCause)));
+        }
+
         public void onPreciseDataConnectionStateChanged(
                 PreciseDataConnectionState dataConnectionState) {
             PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java
index ed5c26a..59f3e1f 100644
--- a/telephony/java/android/telephony/PreciseCallState.java
+++ b/telephony/java/android/telephony/PreciseCallState.java
@@ -16,29 +16,51 @@
 
 package android.telephony;
 
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.DisconnectCause;
 import android.telephony.PreciseDisconnectCause;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
 /**
- * Contains precise call state and call fail causes generated by the
- * framework and the RIL.
+ * Contains precise call states.
  *
  * The following call information is included in returned PreciseCallState:
  *
  * <ul>
- *   <li>Ringing call state.
- *   <li>Foreground call state.
- *   <li>Background call state.
- *   <li>Disconnect cause; generated by the framework.
- *   <li>Precise disconnect cause; generated by the RIL.
+ *   <li>Precise ringing call state.
+ *   <li>Precise foreground call state.
+ *   <li>Precise background call state.
  * </ul>
  *
+ * @see android.telephony.TelephonyManager.CallState which contains generic call states.
+ *
  * @hide
  */
-public class PreciseCallState implements Parcelable {
+@SystemApi
+public final class PreciseCallState implements Parcelable {
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"PRECISE_CALL_STATE_"},
+            value = {
+                    PRECISE_CALL_STATE_NOT_VALID,
+                    PRECISE_CALL_STATE_IDLE,
+                    PRECISE_CALL_STATE_ACTIVE,
+                    PRECISE_CALL_STATE_HOLDING,
+                    PRECISE_CALL_STATE_DIALING,
+                    PRECISE_CALL_STATE_ALERTING,
+                    PRECISE_CALL_STATE_INCOMING,
+                    PRECISE_CALL_STATE_WAITING,
+                    PRECISE_CALL_STATE_DISCONNECTED,
+                    PRECISE_CALL_STATE_DISCONNECTING})
+    public @interface State {}
 
     /** Call state is not valid (Not received a call state). */
     public static final int PRECISE_CALL_STATE_NOT_VALID =      -1;
@@ -61,9 +83,9 @@
     /** Call state: Disconnecting. */
     public static final int PRECISE_CALL_STATE_DISCONNECTING =  8;
 
-    private int mRingingCallState = PRECISE_CALL_STATE_NOT_VALID;
-    private int mForegroundCallState = PRECISE_CALL_STATE_NOT_VALID;
-    private int mBackgroundCallState = PRECISE_CALL_STATE_NOT_VALID;
+    private @State int mRingingCallState = PRECISE_CALL_STATE_NOT_VALID;
+    private @State int mForegroundCallState = PRECISE_CALL_STATE_NOT_VALID;
+    private @State int mBackgroundCallState = PRECISE_CALL_STATE_NOT_VALID;
     private int mDisconnectCause = DisconnectCause.NOT_VALID;
     private int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
 
@@ -73,8 +95,9 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public PreciseCallState(int ringingCall, int foregroundCall, int backgroundCall,
-            int disconnectCause, int preciseDisconnectCause) {
+    public PreciseCallState(@State int ringingCall, @State int foregroundCall,
+                            @State int backgroundCall, int disconnectCause,
+                            int preciseDisconnectCause) {
         mRingingCallState = ringingCall;
         mForegroundCallState = foregroundCall;
         mBackgroundCallState = backgroundCall;
@@ -92,6 +115,8 @@
 
     /**
      * Construct a PreciseCallState object from the given parcel.
+     *
+     * @hide
      */
     private PreciseCallState(Parcel in) {
         mRingingCallState = in.readInt();
@@ -102,59 +127,23 @@
     }
 
     /**
-     * Get precise ringing call state
-     *
-     * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
-     * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
-     * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
-     * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
-     * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
-     * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
-     * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
-     * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
-     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
-     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
+     * Returns the precise ringing call state.
      */
-    @UnsupportedAppUsage
-    public int getRingingCallState() {
+    public @State int getRingingCallState() {
         return mRingingCallState;
     }
 
     /**
-     * Get precise foreground call state
-     *
-     * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
-     * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
-     * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
-     * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
-     * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
-     * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
-     * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
-     * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
-     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
-     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
+     * Returns the precise foreground call state.
      */
-    @UnsupportedAppUsage
-    public int getForegroundCallState() {
+    public @State int getForegroundCallState() {
         return mForegroundCallState;
     }
 
     /**
-     * Get precise background call state
-     *
-     * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
-     * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
-     * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
-     * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
-     * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
-     * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
-     * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
-     * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
-     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
-     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
+     * Returns the precise background call state.
      */
-    @UnsupportedAppUsage
-    public int getBackgroundCallState() {
+    public @State int getBackgroundCallState() {
         return mBackgroundCallState;
     }
 
@@ -199,6 +188,11 @@
      * @see DisconnectCause#CDMA_NOT_EMERGENCY
      * @see DisconnectCause#CDMA_ACCESS_BLOCKED
      * @see DisconnectCause#ERROR_UNSPECIFIED
+     *
+     * TODO: remove disconnect cause from preciseCallState as there is no link between random
+     * connection disconnect cause with foreground, background or ringing call.
+     *
+     * @hide
      */
     @UnsupportedAppUsage
     public int getDisconnectCause() {
@@ -238,6 +232,11 @@
      * @see PreciseDisconnectCause#CDMA_NOT_EMERGENCY
      * @see PreciseDisconnectCause#CDMA_ACCESS_BLOCKED
      * @see PreciseDisconnectCause#ERROR_UNSPECIFIED
+     *
+     * TODO: remove precise disconnect cause from preciseCallState as there is no link between
+     * random connection disconnect cause with foreground, background or ringing call.
+     *
+     * @hide
      */
     @UnsupportedAppUsage
     public int getPreciseDisconnectCause() {
@@ -272,14 +271,8 @@
 
     @Override
     public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + mRingingCallState;
-        result = prime * result + mForegroundCallState;
-        result = prime * result + mBackgroundCallState;
-        result = prime * result + mDisconnectCause;
-        result = prime * result + mPreciseDisconnectCause;
-        return result;
+        return Objects.hash(mRingingCallState, mForegroundCallState, mForegroundCallState,
+                mDisconnectCause, mPreciseDisconnectCause);
     }
 
     @Override
diff --git a/telephony/java/android/telephony/PreciseDisconnectCause.java b/telephony/java/android/telephony/PreciseDisconnectCause.java
index 2acaf34..af88748 100644
--- a/telephony/java/android/telephony/PreciseDisconnectCause.java
+++ b/telephony/java/android/telephony/PreciseDisconnectCause.java
@@ -16,279 +16,329 @@
 
 package android.telephony;
 
+import android.annotation.SystemApi;
+
 /**
- * Contains precise disconnect call causes generated by the
- * framework and the RIL.
- *
+ * Contains precise disconnect call causes generated by the framework and the RIL.
  * @hide
  */
+@SystemApi
 public class PreciseDisconnectCause {
 
-    /** The disconnect cause is not valid (Not received a disconnect cause)*/
+    /** The disconnect cause is not valid (Not received a disconnect cause).*/
     public static final int NOT_VALID                                        = -1;
-    /** No disconnect cause provided. Generally a local disconnect or an incoming missed call */
+    /** No disconnect cause provided. Generally a local disconnect or an incoming missed call. */
     public static final int NO_DISCONNECT_CAUSE_AVAILABLE                    = 0;
     /**
      * The destination cannot be reached because the number, although valid,
-     * is not currently assigned
+     * is not currently assigned.
      */
     public static final int UNOBTAINABLE_NUMBER                              = 1;
-    /** The user cannot be reached because the network through which the call has been
-     *  routed does not serve the destination desired
+    /**
+     * The user cannot be reached because the network through which the call has been routed does
+     * not serve the destination desired.
      */
     public static final int NO_ROUTE_TO_DESTINATION                          = 3;
-    /** The channel most recently identified is not acceptable to the sending entity for
-     *  use in this call
+    /**
+     * The channel most recently identified is not acceptable to the sending entity for use in this
+     * call.
      */
     public static final int CHANNEL_UNACCEPTABLE                             = 6;
-    /** The MS has tried to access a service that the MS's network operator or service
-     *  provider is not prepared to allow
+    /**
+     * The mobile station (MS) has tried to access a service that the MS's network operator or
+     * service provider is not prepared to allow.
      */
     public static final int OPERATOR_DETERMINED_BARRING                      = 8;
-    /** One of the users involved in the call has requested that the call is cleared */
+    /** One of the users involved in the call has requested that the call is cleared. */
     public static final int NORMAL                                           = 16;
-    /** The called user is unable to accept another call */
+    /** The called user is unable to accept another call. */
     public static final int BUSY                                             = 17;
-    /** The user does not respond to a call establishment message with either an alerting
-     *  or connect indication within the prescribed period of time allocated
+    /**
+     * The user does not respond to a call establishment message with either an alerting or connect
+     * indication within the prescribed period of time allocated.
      */
     public static final int NO_USER_RESPONDING                               = 18;
-    /** The user has provided an alerting indication but has not provided a connect
-     *  indication within a prescribed period of time
+    /**
+     * The user has provided an alerting indication but has not provided a connect indication
+     * within a prescribed period of time.
      */
     public static final int NO_ANSWER_FROM_USER                              = 19;
-    /** The equipment sending this cause does not wish to accept this call */
+    /** The equipment sending this cause does not wish to accept this call. */
     public static final int CALL_REJECTED                                    = 21;
-    /** The called number is no longer assigned */
+    /** The called number is no longer assigned. */
     public static final int NUMBER_CHANGED                                   = 22;
-    /** This cause is returned to the network when a mobile station clears an active
-     *  call which is being pre-empted by another call with higher precedence
+    /**
+     * This cause is returned to the network when a mobile station clears an active call which is
+     * being pre-empted by another call with higher precedence.
      */
     public static final int PREEMPTION                                       = 25;
-    /** The destination indicated by the mobile station cannot be reached because
-     *  the interface to the destination is not functioning correctly
+    /**
+     * The destination indicated by the mobile station cannot be reached because the interface to
+     * the destination is not functioning correctly.
      */
     public static final int DESTINATION_OUT_OF_ORDER                         = 27;
-    /** The called party number is not a valid format or is not complete */
+    /** The called party number is not a valid format or is not complete. */
     public static final int INVALID_NUMBER_FORMAT                            = 28;
-    /** The facility requested by user can not be provided by the network */
+    /** The facility requested by user can not be provided by the network. */
     public static final int FACILITY_REJECTED                                = 29;
-    /** Provided in response to a STATUS ENQUIRY message */
+    /** Provided in response to a STATUS ENQUIRY message. */
     public static final int STATUS_ENQUIRY                                   = 30;
-    /** Reports a normal disconnect only when no other normal cause applies */
+    /** Reports a normal disconnect only when no other normal cause applies. */
     public static final int NORMAL_UNSPECIFIED                               = 31;
-    /** There is no channel presently available to handle the call */
+    /** There is no channel presently available to handle the call. */
     public static final int NO_CIRCUIT_AVAIL                                 = 34;
-    /** The network is not functioning correctly and that the condition is likely
-     *  to last a relatively long period of time
+    /**
+     * The network is not functioning correctly and that the condition is likely to last a
+     * relatively long period of time.
      */
     public static final int NETWORK_OUT_OF_ORDER                             = 38;
     /**
-     * The network is not functioning correctly and the condition is not likely to last
-     * a long period of time
+     * The network is not functioning correctly and the condition is not likely to last a long
+     * period of time.
      */
     public static final int TEMPORARY_FAILURE                                = 41;
-    /** The switching equipment is experiencing a period of high traffic */
+    /** The switching equipment is experiencing a period of high traffic. */
     public static final int SWITCHING_CONGESTION                             = 42;
-    /** The network could not deliver access information to the remote user as requested */
+    /** The network could not deliver access information to the remote user as requested. */
     public static final int ACCESS_INFORMATION_DISCARDED                     = 43;
-    /** The channel cannot be provided */
+    /** The channel cannot be provided. */
     public static final int CHANNEL_NOT_AVAIL                                = 44;
-    /** This cause is used to report a resource unavailable event only when no other
-     *  cause in the resource unavailable class applies
+    /**
+     * This cause is used to report a resource unavailable event only when no other cause in the
+     * resource unavailable class applies.
      */
     public static final int RESOURCES_UNAVAILABLE_OR_UNSPECIFIED             = 47;
-    /** The requested quality of service (ITU-T X.213) cannot be provided */
+    /** The requested quality of service (ITU-T X.213) cannot be provided. */
     public static final int QOS_NOT_AVAIL                                    = 49;
-    /** The facility could not be provided by the network because the user has no
-     *  complete subscription
+    /**
+     * The facility could not be provided by the network because the user has no complete
+     * subscription.
      */
     public static final int REQUESTED_FACILITY_NOT_SUBSCRIBED                = 50;
-    /** Incoming calls are not allowed within this CUG */
+    /** Incoming calls are not allowed within this calling user group (CUG). */
     public static final int INCOMING_CALLS_BARRED_WITHIN_CUG                 = 55;
-    /** The mobile station is not authorized to use bearer capability requested */
+    /** The mobile station is not authorized to use bearer capability requested. */
     public static final int BEARER_CAPABILITY_NOT_AUTHORIZED                 = 57;
-    /** The requested bearer capability is not available at this time */
+    /** The requested bearer capability is not available at this time. */
     public static final int BEARER_NOT_AVAIL                                 = 58;
-    /** The service option is not availble at this time */
+    /** The service option is not availble at this time. */
     public static final int SERVICE_OPTION_NOT_AVAILABLE                     = 63;
-    /** The equipment sending this cause does not support the bearer capability requested */
+    /** The equipment sending this cause does not support the bearer capability requested. */
     public static final int BEARER_SERVICE_NOT_IMPLEMENTED                   = 65;
-    /** The call clearing is due to ACM being greater than or equal to ACMmax */
+    /** The call clearing is due to ACM being greater than or equal to ACMmax. */
     public static final int ACM_LIMIT_EXCEEDED                               = 68;
-    /** The equipment sending this cause does not support the requested facility */
+    /** The equipment sending this cause does not support the requested facility. */
     public static final int REQUESTED_FACILITY_NOT_IMPLEMENTED               = 69;
-    /** The equipment sending this cause only supports the restricted version of
-     *  the requested bearer capability
+    /**
+     * The equipment sending this cause only supports the restricted version of the requested bearer
+     * capability.
      */
     public static final int ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE        = 70;
-    /** The service requested is not implemented at network */
+    /** The service requested is not implemented at network. */
     public static final int SERVICE_OR_OPTION_NOT_IMPLEMENTED                = 79;
-    /** The equipment sending this cause has received a message with a transaction identifier
-     *  which is not currently in use on the MS-network interface
+    /**
+     * The equipment sending this cause has received a message with a transaction identifier
+     * which is not currently in use on the mobile station network interface.
      */
     public static final int INVALID_TRANSACTION_IDENTIFIER                   = 81;
-    /** The called user for the incoming CUG call is not a member of the specified CUG */
+    /**
+     * The called user for the incoming CUG call is not a member of the specified calling user
+     * group (CUG).
+     */
     public static final int USER_NOT_MEMBER_OF_CUG                           = 87;
-    /** The equipment sending this cause has received a request which can't be accomodated */
+    /** The equipment sending this cause has received a request which can't be accomodated. */
     public static final int INCOMPATIBLE_DESTINATION                         = 88;
-    /** This cause is used to report receipt of a message with semantically incorrect contents */
+    /** This cause is used to report receipt of a message with semantically incorrect contents. */
     public static final int SEMANTICALLY_INCORRECT_MESSAGE                   = 95;
-    /** The equipment sending this cause has received a message with a non-semantical
-     *  mandatory IE error
+    /**
+     * The equipment sending this cause has received a message with a non-semantical mandatory
+     * information element (IE) error.
      */
     public static final int INVALID_MANDATORY_INFORMATION                    = 96;
-    /** This is sent in response to a message which is not defined, or defined but not
-     *  implemented by the equipment sending this cause
+    /**
+     * This is sent in response to a message which is not defined, or defined but not implemented
+     * by the equipment sending this cause.
      */
     public static final int MESSAGE_TYPE_NON_IMPLEMENTED                     = 97;
-    /** The equipment sending this cause has received a message not compatible with the
-     *  protocol state
+    /**
+     * The equipment sending this cause has received a message not compatible with the protocol
+     * state.
      */
     public static final int MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE  = 98;
-    /** The equipment sending this cause has received a message which includes information
-     *  elements not recognized because its identifier is not defined or it is defined but not
-     *  implemented by the equipment sending the cause
+    /**
+     * The equipment sending this cause has received a message which includes information
+     * elements not recognized because its identifier is not defined or it is defined but not
+     * implemented by the equipment sending the cause.
      */
     public static final int INFORMATION_ELEMENT_NON_EXISTENT                 = 99;
-    /** The equipment sending this cause has received a message with conditional IE errors */
+    /** The equipment sending this cause has received a message with conditional IE errors. */
     public static final int CONDITIONAL_IE_ERROR                             = 100;
-    /** The message has been received which is incompatible with the protocol state */
+    /** The message has been received which is incompatible with the protocol state. */
     public static final int MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE       = 101;
-    /** The  procedure has been initiated by the expiry of a timer in association with
-     *  3GPP TS 24.008 error handling procedures
+    /**
+     * The procedure has been initiated by the expiry of a timer in association with
+     * 3GPP TS 24.008 error handling procedures.
      */
     public static final int RECOVERY_ON_TIMER_EXPIRED                        = 102;
-    /** This protocol error event is reported only when no other cause in the protocol
-     *  error class applies
+    /**
+     * This protocol error event is reported only when no other cause in the protocol error class
+     * applies.
      */
     public static final int PROTOCOL_ERROR_UNSPECIFIED                       = 111;
-    /** interworking with a network which does not provide causes for actions it takes
-     *  thus, the precise cause for a message which is being sent cannot be ascertained
+    /**
+     * Interworking with a network which does not provide causes for actions it takes thus, the
+     * precise cause for a message which is being sent cannot be ascertained.
      */
     public static final int INTERWORKING_UNSPECIFIED                         = 127;
-    /** The call is restricted */
+    /** The call is restricted. */
     public static final int CALL_BARRED                                      = 240;
-    /** The call is blocked by the Fixed Dialing Number list */
+    /** The call is blocked by the Fixed Dialing Number list. */
     public static final int FDN_BLOCKED                                      = 241;
-    /** The given IMSI is not known at the VLR */
-    /** TS 24.008 cause 4 */
+    /** The given IMSI is not known at the Visitor Location Register (VLR) TS 24.008 cause . */
     public static final int IMSI_UNKNOWN_IN_VLR                              = 242;
     /**
      * The network does not accept emergency call establishment using an IMEI or not accept attach
-     * procedure for emergency services using an IMEI
+     * procedure for emergency services using an IMEI.
      */
     public static final int IMEI_NOT_ACCEPTED                                = 243;
-    /** The call cannot be established because RADIO is OFF */
+    /** The call cannot be established because RADIO is OFF. */
     public static final int RADIO_OFF                                        = 247;
-    /** The call cannot be established because of no cell coverage */
+    /** The call cannot be established because of no cell coverage. */
     public static final int OUT_OF_SRV                                       = 248;
-    /** The call cannot be established because of no valid SIM */
+    /** The call cannot be established because of no valid SIM. */
     public static final int NO_VALID_SIM                                     = 249;
-    /** The call is dropped or failed internally by modem */
+    /** The call is dropped or failed internally by modem. */
     public static final int RADIO_INTERNAL_ERROR                             = 250;
-    /** Call failed because of UE timer expired while waiting for a response from network */
+    /** Call failed because of UE timer expired while waiting for a response from network. */
     public static final int NETWORK_RESP_TIMEOUT                             = 251;
-    /** Call failed because of a network reject */
+    /** Call failed because of a network reject. */
     public static final int NETWORK_REJECT                                   = 252;
-    /** Call failed because of radio access failure. ex. RACH failure */
+    /** Call failed because of radio access failure. ex. RACH failure. */
     public static final int RADIO_ACCESS_FAILURE                             = 253;
-    /** Call failed/dropped because of a RLF */
+    /** Call failed/dropped because of a Radio Link Failure (RLF). */
     public static final int RADIO_LINK_FAILURE                               = 254;
-    /** Call failed/dropped because of radio link lost */
+    /** Call failed/dropped because of radio link lost. */
     public static final int RADIO_LINK_LOST                                  = 255;
-    /** Call failed because of a radio uplink issue */
+    /** Call failed because of a radio uplink issue. */
     public static final int RADIO_UPLINK_FAILURE                             = 256;
-    /** Call failed because of a RRC connection setup failure */
+    /** Call failed because of a RRC (Radio Resource Control) connection setup failure. */
     public static final int RADIO_SETUP_FAILURE                              = 257;
-    /** Call failed/dropped because of RRC connection release from NW */
+    /** Call failed/dropped because of RRC (Radio Resource Control) connection release from NW. */
     public static final int RADIO_RELEASE_NORMAL                             = 258;
-    /** Call failed/dropped because of RRC abnormally released by modem/network */
+    /**
+     * Call failed/dropped because of RRC (Radio Resource Control) abnormally released by
+     * modem/network.
+     */
     public static final int RADIO_RELEASE_ABNORMAL                           = 259;
-    /** Call setup failed because of access class barring */
+    /** Call setup failed because of access class barring. */
     public static final int ACCESS_CLASS_BLOCKED                             = 260;
-    /** Call failed/dropped because of a network detach */
+    /** Call failed/dropped because of a network detach. */
     public static final int NETWORK_DETACH                                   = 261;
 
-    /** MS is locked until next power cycle */
+    /** Mobile station (MS) is locked until next power cycle. */
     public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE                    = 1000;
-    /** Drop call*/
+    /** Drop call. */
     public static final int CDMA_DROP                                        = 1001;
-    /** INTERCEPT order received, MS state idle entered */
+    /** INTERCEPT order received, Mobile station (MS) state idle entered. */
     public static final int CDMA_INTERCEPT                                   = 1002;
-    /** MS has been redirected, call is cancelled */
+    /** Mobile station (MS) has been redirected, call is cancelled. */
     public static final int CDMA_REORDER                                     = 1003;
-    /** Service option rejection */
+    /** Service option rejection. */
     public static final int CDMA_SO_REJECT                                   = 1004;
-    /** Requested service is rejected, retry delay is set */
+    /** Requested service is rejected, retry delay is set. */
     public static final int CDMA_RETRY_ORDER                                 = 1005;
-    /** Unable to obtain access to the CDMA system */
+    /** Unable to obtain access to the CDMA system. */
     public static final int CDMA_ACCESS_FAILURE                              = 1006;
-    /** Not a preempted call */
+    /** Not a preempted call. */
     public static final int CDMA_PREEMPTED                                   = 1007;
-    /** Not an emergency call */
+    /** Not an emergency call. */
     public static final int CDMA_NOT_EMERGENCY                               = 1008;
-    /** Access Blocked by CDMA network */
+    /** Access Blocked by CDMA network. */
     public static final int CDMA_ACCESS_BLOCKED                              = 1009;
 
     /** Mapped from ImsReasonInfo */
+    // TODO: remove ImsReasonInfo from preciseDisconnectCause
     /* The passed argument is an invalid */
+    /** @hide */
     public static final int LOCAL_ILLEGAL_ARGUMENT                           = 1200;
     // The operation is invoked in invalid call state
+    /** @hide */
     public static final int LOCAL_ILLEGAL_STATE                              = 1201;
     // IMS service internal error
+    /** @hide */
     public static final int LOCAL_INTERNAL_ERROR                             = 1202;
     // IMS service goes down (service connection is lost)
+    /** @hide */
     public static final int LOCAL_IMS_SERVICE_DOWN                           = 1203;
     // No pending incoming call exists
+    /** @hide */
     public static final int LOCAL_NO_PENDING_CALL                            = 1204;
     // Service unavailable; by power off
+    /** @hide */
     public static final int LOCAL_POWER_OFF                                  = 1205;
     // Service unavailable; by low battery
+    /** @hide */
     public static final int LOCAL_LOW_BATTERY                                = 1206;
     // Service unavailable; by out of service (data service state)
+    /** @hide */
     public static final int LOCAL_NETWORK_NO_SERVICE                         = 1207;
     /* Service unavailable; by no LTE coverage
      * (VoLTE is not supported even though IMS is registered)
      */
+    /** @hide */
     public static final int LOCAL_NETWORK_NO_LTE_COVERAGE                    = 1208;
     /** Service unavailable; by located in roaming area */
+    /** @hide */
     public static final int LOCAL_NETWORK_ROAMING                            = 1209;
     /** Service unavailable; by IP changed */
+    /** @hide */
     public static final int LOCAL_NETWORK_IP_CHANGED                         = 1210;
     /** Service unavailable; other */
+    /** @hide */
     public static final int LOCAL_SERVICE_UNAVAILABLE                        = 1211;
     /* Service unavailable; IMS connection is lost (IMS is not registered) */
+    /** @hide */
     public static final int LOCAL_NOT_REGISTERED                             = 1212;
     /** Max call exceeded */
+    /** @hide */
     public static final int LOCAL_MAX_CALL_EXCEEDED                          = 1213;
     /** Call decline */
+    /** @hide */
     public static final int LOCAL_CALL_DECLINE                               = 1214;
     /** SRVCC is in progress */
+    /** @hide */
     public static final int LOCAL_CALL_VCC_ON_PROGRESSING                    = 1215;
     /** Resource reservation is failed (QoS precondition) */
+    /** @hide */
     public static final int LOCAL_CALL_RESOURCE_RESERVATION_FAILED           = 1216;
     /** Retry CS call; VoLTE service can't be provided by the network or remote end
      *  Resolve the extra code(EXTRA_CODE_CALL_RETRY_*) if the below code is set
+     *  @hide
      */
     public static final int LOCAL_CALL_CS_RETRY_REQUIRED                     = 1217;
     /** Retry VoLTE call; VoLTE service can't be provided by the network temporarily */
+    /** @hide */
     public static final int LOCAL_CALL_VOLTE_RETRY_REQUIRED                  = 1218;
     /** IMS call is already terminated (in TERMINATED state) */
+    /** @hide */
     public static final int LOCAL_CALL_TERMINATED                            = 1219;
     /** Handover not feasible */
+    /** @hide */
     public static final int LOCAL_HO_NOT_FEASIBLE                            = 1220;
 
     /** 1xx waiting timer is expired after sending INVITE request (MO only) */
+    /** @hide */
     public static final int TIMEOUT_1XX_WAITING                              = 1221;
     /** User no answer during call setup operation (MO/MT)
      *  MO : 200 OK to INVITE request is not received,
      *  MT : No action from user after alerting the call
+     *  @hide
      */
     public static final int TIMEOUT_NO_ANSWER                                = 1222;
     /** User no answer during call update operation (MO/MT)
      *  MO : 200 OK to re-INVITE request is not received,
      *  MT : No action from user after alerting the call
+     *  @hide
      */
     public static final int TIMEOUT_NO_ANSWER_CALL_UPDATE                    = 1223;
 
@@ -296,102 +346,142 @@
      * STATUSCODE (SIP response code) (IMS -> Telephony)
      */
     /** SIP request is redirected */
+    /** @hide */
     public static final int SIP_REDIRECTED                                   = 1300;
     /** 4xx responses */
     /** 400 : Bad Request */
+    /** @hide */
     public static final int SIP_BAD_REQUEST                                  = 1310;
     /** 403 : Forbidden */
+    /** @hide */
     public static final int SIP_FORBIDDEN                                    = 1311;
     /** 404 : Not Found */
+    /** @hide */
     public static final int SIP_NOT_FOUND                                    = 1312;
     /** 415 : Unsupported Media Type
      *  416 : Unsupported URI Scheme
      *  420 : Bad Extension
      */
+    /** @hide */
     public static final int SIP_NOT_SUPPORTED                                = 1313;
     /** 408 : Request Timeout */
+    /** @hide */
     public static final int SIP_REQUEST_TIMEOUT                              = 1314;
     /** 480 : Temporarily Unavailable */
+    /** @hide */
     public static final int SIP_TEMPRARILY_UNAVAILABLE                       = 1315;
     /** 484 : Address Incomplete */
+    /** @hide */
     public static final int SIP_BAD_ADDRESS                                  = 1316;
     /** 486 : Busy Here
      *  600 : Busy Everywhere
      */
+    /** @hide */
     public static final int SIP_BUSY                                         = 1317;
     /** 487 : Request Terminated */
+    /** @hide */
     public static final int SIP_REQUEST_CANCELLED                            = 1318;
     /** 406 : Not Acceptable
      *  488 : Not Acceptable Here
      *  606 : Not Acceptable
      */
+    /** @hide */
     public static final int SIP_NOT_ACCEPTABLE                               = 1319;
     /** 410 : Gone
      *  604 : Does Not Exist Anywhere
      */
+    /** @hide */
     public static final int SIP_NOT_REACHABLE                                = 1320;
     /** Others */
+    /** @hide */
     public static final int SIP_CLIENT_ERROR                                 = 1321;
     /** 481 : Transaction Does Not Exist */
+    /** @hide */
     public static final int SIP_TRANSACTION_DOES_NOT_EXIST                   = 1322;
     /** 5xx responses
      *  501 : Server Internal Error
      */
+    /** @hide */
     public static final int SIP_SERVER_INTERNAL_ERROR                        = 1330;
     /** 503 : Service Unavailable */
+    /** @hide */
     public static final int SIP_SERVICE_UNAVAILABLE                          = 1331;
     /** 504 : Server Time-out */
+    /** @hide */
     public static final int SIP_SERVER_TIMEOUT                               = 1332;
     /** Others */
+    /** @hide */
     public static final int SIP_SERVER_ERROR                                 = 1333;
     /** 6xx responses
      *  603 : Decline
      */
+    /** @hide */
     public static final int SIP_USER_REJECTED                                = 1340;
     /** Others */
+    /** @hide */
     public static final int SIP_GLOBAL_ERROR                                 = 1341;
     /** Emergency failure */
+    /** @hide */
     public static final int EMERGENCY_TEMP_FAILURE                           = 1342;
+    /** @hide */
     public static final int EMERGENCY_PERM_FAILURE                           = 1343;
     /** Media resource initialization failed */
+    /** @hide */
     public static final int MEDIA_INIT_FAILED                                = 1400;
     /** RTP timeout (no audio / video traffic in the session) */
+    /** @hide */
     public static final int MEDIA_NO_DATA                                    = 1401;
     /** Media is not supported; so dropped the call */
+    /** @hide */
     public static final int MEDIA_NOT_ACCEPTABLE                             = 1402;
     /** Unknown media related errors */
+    /** @hide */
     public static final int MEDIA_UNSPECIFIED                                = 1403;
     /** User triggers the call end */
+    /** @hide */
     public static final int USER_TERMINATED                                  = 1500;
     /** No action while an incoming call is ringing */
+    /** @hide */
     public static final int USER_NOANSWER                                    = 1501;
     /** User ignores an incoming call */
+    /** @hide */
     public static final int USER_IGNORE                                      = 1502;
     /** User declines an incoming call */
+    /** @hide */
     public static final int USER_DECLINE                                     = 1503;
     /** Device declines/ends a call due to low battery */
+    /** @hide */
     public static final int LOW_BATTERY                                      = 1504;
     /** Device declines call due to blacklisted call ID */
+    /** @hide */
     public static final int BLACKLISTED_CALL_ID                              = 1505;
     /** The call is terminated by the network or remote user */
+    /** @hide */
     public static final int USER_TERMINATED_BY_REMOTE                        = 1510;
 
     /**
      * UT
      */
+    /** @hide */
     public static final int UT_NOT_SUPPORTED                                 = 1800;
+    /** @hide */
     public static final int UT_SERVICE_UNAVAILABLE                           = 1801;
+    /** @hide */
     public static final int UT_OPERATION_NOT_ALLOWED                         = 1802;
+    /** @hide */
     public static final int UT_NETWORK_ERROR                                 = 1803;
+    /** @hide */
     public static final int UT_CB_PASSWORD_MISMATCH                          = 1804;
 
     /**
      * ECBM
+     * @hide
      */
     public static final int ECBM_NOT_SUPPORTED                               = 1900;
 
     /**
      * Fail code used to indicate that Multi-endpoint is not supported by the Ims framework.
+     * @hide
      */
     public static final int MULTIENDPOINT_NOT_SUPPORTED                      = 1901;
 
@@ -405,56 +495,68 @@
      * active wifi call and at the edge of coverage and there is no qualified LTE network available
      * to handover the call to. We get a handover NOT_TRIGERRED message from the modem. This error
      * code is received as part of the handover message.
+     * @hide
      */
     public static final int CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE               = 2000;
 
     /**
      * MT call has ended due to a release from the network
      * because the call was answered elsewhere
+     * @hide
      */
     public static final int ANSWERED_ELSEWHERE                               = 2100;
 
     /**
      * For MultiEndpoint - Call Pull request has failed
+     * @hide
      */
     public static final int CALL_PULL_OUT_OF_SYNC                            = 2101;
 
     /**
      * For MultiEndpoint - Call has been pulled from primary to secondary
+     * @hide
      */
     public static final int CALL_PULLED                                      = 2102;
 
     /**
      * Supplementary services (HOLD/RESUME) failure error codes.
      * Values for Supplemetary services failure - Failed, Cancelled and Re-Invite collision.
+     * @hide
      */
     public static final int SUPP_SVC_FAILED                                  = 2300;
+    /** @hide */
     public static final int SUPP_SVC_CANCELLED                               = 2301;
+    /** @hide */
     public static final int SUPP_SVC_REINVITE_COLLISION                      = 2302;
 
     /**
      * DPD Procedure received no response or send failed
+     * @hide
      */
     public static final int IWLAN_DPD_FAILURE                                = 2400;
 
     /**
      * Establishment of the ePDG Tunnel Failed
+     * @hide
      */
     public static final int EPDG_TUNNEL_ESTABLISH_FAILURE                    = 2500;
 
     /**
      * Re-keying of the ePDG Tunnel Failed; may not always result in teardown
+     * @hide
      */
     public static final int EPDG_TUNNEL_REKEY_FAILURE                        = 2501;
 
     /**
      * Connection to the packet gateway is lost
+     * @hide
      */
     public static final int EPDG_TUNNEL_LOST_CONNECTION                      = 2502;
 
     /**
      * The maximum number of calls allowed has been reached.  Used in a multi-endpoint scenario
      * where the number of calls across all connected devices has reached the maximum.
+     * @hide
      */
     public static final int MAXIMUM_NUMBER_OF_CALLS_REACHED                  = 2503;
 
@@ -462,21 +564,25 @@
      * Similar to {@link #CODE_LOCAL_CALL_DECLINE}, except indicates that a remote device has
      * declined the call.  Used in a multi-endpoint scenario where a remote device declined an
      * incoming call.
+     * @hide
      */
     public static final int REMOTE_CALL_DECLINE                              = 2504;
 
     /**
      * Indicates the call was disconnected due to the user reaching their data limit.
+     * @hide
      */
     public static final int DATA_LIMIT_REACHED                               = 2505;
 
     /**
      * Indicates the call was disconnected due to the user disabling cellular data.
+     * @hide
      */
     public static final int DATA_DISABLED                                    = 2506;
 
     /**
      * Indicates a call was disconnected due to loss of wifi signal.
+     * @hide
      */
     public static final int WIFI_LOST                                        = 2507;
 
@@ -499,7 +605,7 @@
     public static final int OEM_CAUSE_14                                     = 0xf00e;
     public static final int OEM_CAUSE_15                                     = 0xf00f;
 
-    /** Disconnected due to unspecified reasons */
+    /** Disconnected due to unspecified reasons. */
     public static final int ERROR_UNSPECIFIED                                = 0xffff;
 
     /** Private constructor to avoid class instantiation. */
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 240b8a9..ef185c5 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -16,16 +16,14 @@
 
 package android.telephony;
 
+import android.annotation.NonNull;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.telephony.CarrierConfigManager;
-import android.util.Log;
+import android.os.PersistableBundle;
 
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Objects;
 
 /**
@@ -59,6 +57,8 @@
     /** @hide */
     @UnsupportedAppUsage
     public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
+
+    /** SIGNAL_STRENGTH_NAMES is currently used by BatteryStats, but to-be-removed soon. */
     /** @hide */
     public static final String[] SIGNAL_STRENGTH_NAMES = {
         "none", "poor", "moderate", "good", "great"
@@ -72,66 +72,22 @@
     public static final int INVALID = Integer.MAX_VALUE;
 
     private static final int LTE_RSRP_THRESHOLDS_NUM = 4;
-    private static final int MAX_LTE_RSRP = -44;
-    private static final int MIN_LTE_RSRP = -140;
 
     private static final int WCDMA_RSCP_THRESHOLDS_NUM = 4;
-    private static final int MAX_WCDMA_RSCP = -24;
-    private static final int MIN_WCDMA_RSCP = -120;
 
     /* The type of signal measurement */
-    private static final String MEASUMENT_TYPE_RSCP = "rscp";
+    private static final String MEASUREMENT_TYPE_RSCP = "rscp";
 
-    /** Parameters reported by the Radio */
-    @UnsupportedAppUsage
-    private int mGsmSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
-    @UnsupportedAppUsage
-    private int mGsmBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
-    @UnsupportedAppUsage
-    private int mCdmaDbm;   // This value is the RSSI value
-    @UnsupportedAppUsage
-    private int mCdmaEcio;  // This value is the Ec/Io
-    @UnsupportedAppUsage
-    private int mEvdoDbm;   // This value is the EVDO RSSI value
-    @UnsupportedAppUsage
-    private int mEvdoEcio;  // This value is the EVDO Ec/Io
-    @UnsupportedAppUsage
-    private int mEvdoSnr;   // Valid values are 0-8.  8 is the highest signal to noise ratio
-    @UnsupportedAppUsage
-    private int mLteSignalStrength;
-    @UnsupportedAppUsage
-    private int mLteRsrp;
-    @UnsupportedAppUsage
-    private int mLteRsrq;
-    @UnsupportedAppUsage
-    private int mLteRssnr;
-    @UnsupportedAppUsage
-    private int mLteCqi;
-    @UnsupportedAppUsage
-    private int mTdScdmaRscp; // Valid values are -24...-120dBm or INVALID if unknown
-    private int mWcdmaSignalStrength;
-    private int mWcdmaRscpAsu;  // the WCDMA RSCP in ASU as reported from the HAL
-    @UnsupportedAppUsage
-    private int mWcdmaRscp;     // the WCDMA RSCP in dBm
+    CellSignalStrengthCdma mCdma;
+    CellSignalStrengthGsm mGsm;
+    CellSignalStrengthWcdma mWcdma;
+    CellSignalStrengthTdscdma mTdscdma;
+    CellSignalStrengthLte mLte;
 
     /** Parameters from the framework */
     @UnsupportedAppUsage
     private int mLteRsrpBoost; // offset to be reduced from the rsrp threshold while calculating
                                 // signal strength level
-    private boolean mIsGsm; // This value is set by the ServiceStateTracker
-                            // onSignalStrengthResult.
-    private boolean mUseOnlyRsrpForLteLevel; // Use only RSRP for the number of LTE signal bar.
-
-    // The threshold of LTE RSRP for determining the display level of LTE signal bar. Note that the
-    // min and max are fixed at MIN_LTE_RSRP (-140) and MAX_LTE_RSRP (-44).
-    private int mLteRsrpThresholds[] = new int[LTE_RSRP_THRESHOLDS_NUM];
-
-    // The type of default measurement for determining the display level of WCDMA signal bar.
-    private String mWcdmaDefaultSignalMeasurement;
-
-    // The threshold of WCDMA RSCP for determining the display level of WCDMA signal bar. Note that
-    // the min and max are fixed at MIN_WCDMA_RSCP (-120) and MAX_WCDMA_RSCP (-24).
-    private int mWcdmaRscpThresholds[] = new int[WCDMA_RSCP_THRESHOLDS_NUM];
 
     /**
      * Create a new SignalStrength from a intent notifier Bundle
@@ -153,47 +109,17 @@
     }
 
     /**
-     * Empty constructor
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public SignalStrength() {
-        this(true);
-    }
-
-    /**
      * This constructor is used to create SignalStrength with default
-     * values and set the gsmFlag with the value passed in the input
+     * values.
      *
-     * @param gsmFlag true if Gsm Phone,false if Cdma phone
      * @return newly created SignalStrength
      * @hide
      */
     @UnsupportedAppUsage
-    public SignalStrength(boolean gsmFlag) {
-        mGsmSignalStrength = 99;
-        mGsmBitErrorRate = -1;
-        mCdmaDbm = INVALID;
-        mCdmaEcio = -1;
-        mEvdoDbm = INVALID;
-        mEvdoEcio = -1;
-        mEvdoSnr = -1;
-        mLteSignalStrength = 99;
-        mLteRsrp = INVALID;
-        mLteRsrq = INVALID;
-        mLteRssnr = INVALID;
-        mLteCqi = INVALID;
-        mTdScdmaRscp = INVALID;
-        mWcdmaSignalStrength = 99;
-        mWcdmaRscp = INVALID;
-        mWcdmaRscpAsu = 255;
-        mLteRsrpBoost = 0;
-        mIsGsm = gsmFlag;
-        mUseOnlyRsrpForLteLevel = false;
-        mWcdmaDefaultSignalMeasurement = "";
-        setLteRsrpThresholds(getDefaultLteRsrpThresholds());
-        setWcdmaRscpThresholds(getDefaultWcdmaRscpThresholds());
+    public SignalStrength() {
+        this(new CellSignalStrengthCdma(), new CellSignalStrengthGsm(),
+                new CellSignalStrengthWcdma(), new CellSignalStrengthTdscdma(),
+                new CellSignalStrengthLte());
     }
 
     /**
@@ -202,68 +128,64 @@
      * @hide
      */
     public SignalStrength(
-            int gsmSignalStrength, int gsmBitErrorRate,
-            int cdmaDbm, int cdmaEcio,
-            int evdoDbm, int evdoEcio, int evdoSnr,
-            int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
-            int tdScdmaRscp, int wcdmaSignalStrength, int wcdmaRscpAsu,
-            // values Added by config
-            int lteRsrpBoost, boolean gsmFlag, boolean lteLevelBaseOnRsrp,
-            String wcdmaDefaultMeasurement) {
-        mGsmSignalStrength = gsmSignalStrength;
-        mGsmBitErrorRate = gsmBitErrorRate;
-        mCdmaDbm = cdmaDbm;
-        mCdmaEcio = cdmaEcio;
-        mEvdoDbm = evdoDbm;
-        mEvdoEcio = evdoEcio;
-        mEvdoSnr = evdoSnr;
-        mLteSignalStrength = lteSignalStrength;
-        mLteRsrp = lteRsrp;
-        mLteRsrq = lteRsrq;
-        mLteRssnr = lteRssnr;
-        mLteCqi = lteCqi;
-        mTdScdmaRscp = INVALID;
-        mWcdmaSignalStrength = wcdmaSignalStrength;
-        mWcdmaRscpAsu = wcdmaRscpAsu;
-        mWcdmaRscp = wcdmaRscpAsu - 120;
-        mLteRsrpBoost = lteRsrpBoost;
-        mIsGsm = gsmFlag;
-        mUseOnlyRsrpForLteLevel = lteLevelBaseOnRsrp;
-        mWcdmaDefaultSignalMeasurement = wcdmaDefaultMeasurement;
-        setLteRsrpThresholds(getDefaultLteRsrpThresholds());
-        setWcdmaRscpThresholds(getDefaultWcdmaRscpThresholds());
-        if (DBG) log("initialize: " + toString());
+            @NonNull CellSignalStrengthCdma cdma,
+            @NonNull CellSignalStrengthGsm gsm,
+            @NonNull CellSignalStrengthWcdma wcdma,
+            @NonNull CellSignalStrengthTdscdma tdscdma,
+            @NonNull CellSignalStrengthLte lte) {
+        mCdma = cdma;
+        mGsm = gsm;
+        mWcdma = wcdma;
+        mTdscdma = tdscdma;
+        mLte = lte;
+        mLteRsrpBoost = 0;
     }
 
     /**
-     * Constructor for only values provided by Radio HAL V1.0
+     * Constructor for Radio HAL V1.0
      *
      * @hide
      */
-    public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
-            int cdmaDbm, int cdmaEcio,
-            int evdoDbm, int evdoEcio, int evdoSnr,
-            int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
-            int tdScdmaRscp) {
-        this(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
-                evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
-                lteRsrq, lteRssnr, lteCqi, tdScdmaRscp, 99, INVALID, 0, true, false, "");
+    public SignalStrength(android.hardware.radio.V1_0.SignalStrength signalStrength) {
+        this(new CellSignalStrengthCdma(signalStrength.cdma, signalStrength.evdo),
+                new CellSignalStrengthGsm(signalStrength.gw),
+                new CellSignalStrengthWcdma(),
+                new CellSignalStrengthTdscdma(signalStrength.tdScdma),
+                new CellSignalStrengthLte(signalStrength.lte));
     }
 
     /**
-     * Constructor for only values provided by Radio HAL V1.2
+     * Constructor for Radio HAL V1.2
      *
      * @hide
      */
-    public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
-            int cdmaDbm, int cdmaEcio,
-            int evdoDbm, int evdoEcio, int evdoSnr,
-            int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
-            int tdScdmaRscp, int wcdmaSignalStrength, int wcdmaRscp) {
-        this(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
-                evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
-                lteRsrq, lteRssnr, lteCqi, tdScdmaRscp, wcdmaSignalStrength, wcdmaRscp, 0, true,
-                false, "");
+    public SignalStrength(android.hardware.radio.V1_2.SignalStrength signalStrength) {
+        this(new CellSignalStrengthCdma(signalStrength.cdma, signalStrength.evdo),
+                new CellSignalStrengthGsm(signalStrength.gsm),
+                new CellSignalStrengthWcdma(signalStrength.wcdma),
+                new CellSignalStrengthTdscdma(signalStrength.tdScdma),
+                new CellSignalStrengthLte(signalStrength.lte));
+    }
+
+    private CellSignalStrength getPrimary() {
+        // This behavior is intended to replicate the legacy behavior of getLevel() by prioritizing
+        // newer faster RATs for default/for display purposes.
+        if (mLte.isValid()) return mLte;
+        if (mCdma.isValid()) return mCdma;
+        if (mTdscdma.isValid()) return mTdscdma;
+        if (mWcdma.isValid()) return mWcdma;
+        if (mGsm.isValid()) return mGsm;
+        return mLte;
+    }
+
+    /** @hide */
+    public void updateLevel(PersistableBundle cc, ServiceState ss) {
+        mLteRsrpBoost = ss.getLteEarfcnRsrpBoost();
+        mCdma.updateLevel(cc, ss);
+        mGsm.updateLevel(cc, ss);
+        mWcdma.updateLevel(cc, ss);
+        mTdscdma.updateLevel(cc, ss);
+        mLte.updateLevel(cc, ss);
     }
 
     /**
@@ -283,28 +205,12 @@
      */
     @UnsupportedAppUsage
     protected void copyFrom(SignalStrength s) {
-        mGsmSignalStrength = s.mGsmSignalStrength;
-        mGsmBitErrorRate = s.mGsmBitErrorRate;
-        mCdmaDbm = s.mCdmaDbm;
-        mCdmaEcio = s.mCdmaEcio;
-        mEvdoDbm = s.mEvdoDbm;
-        mEvdoEcio = s.mEvdoEcio;
-        mEvdoSnr = s.mEvdoSnr;
-        mLteSignalStrength = s.mLteSignalStrength;
-        mLteRsrp = s.mLteRsrp;
-        mLteRsrq = s.mLteRsrq;
-        mLteRssnr = s.mLteRssnr;
-        mLteCqi = s.mLteCqi;
-        mTdScdmaRscp = s.mTdScdmaRscp;
-        mWcdmaSignalStrength = s.mWcdmaSignalStrength;
-        mWcdmaRscpAsu = s.mWcdmaRscpAsu;
-        mWcdmaRscp = s.mWcdmaRscp;
+        mCdma = new CellSignalStrengthCdma(s.mCdma);
+        mGsm = new CellSignalStrengthGsm(s.mGsm);
+        mWcdma = new CellSignalStrengthWcdma(s.mWcdma);
+        mTdscdma = new CellSignalStrengthTdscdma(s.mTdscdma);
+        mLte = new CellSignalStrengthLte(s.mLte);
         mLteRsrpBoost = s.mLteRsrpBoost;
-        mIsGsm = s.mIsGsm;
-        mUseOnlyRsrpForLteLevel = s.mUseOnlyRsrpForLteLevel;
-        mWcdmaDefaultSignalMeasurement = s.mWcdmaDefaultSignalMeasurement;
-        setLteRsrpThresholds(s.mLteRsrpThresholds);
-        setWcdmaRscpThresholds(s.mWcdmaRscpThresholds);
     }
 
     /**
@@ -316,56 +222,25 @@
     public SignalStrength(Parcel in) {
         if (DBG) log("Size of signalstrength parcel:" + in.dataSize());
 
-        mGsmSignalStrength = in.readInt();
-        mGsmBitErrorRate = in.readInt();
-        mCdmaDbm = in.readInt();
-        mCdmaEcio = in.readInt();
-        mEvdoDbm = in.readInt();
-        mEvdoEcio = in.readInt();
-        mEvdoSnr = in.readInt();
-        mLteSignalStrength = in.readInt();
-        mLteRsrp = in.readInt();
-        mLteRsrq = in.readInt();
-        mLteRssnr = in.readInt();
-        mLteCqi = in.readInt();
-        mTdScdmaRscp = in.readInt();
-        mWcdmaSignalStrength = in.readInt();
-        mWcdmaRscpAsu = in.readInt();
-        mWcdmaRscp = in.readInt();
+        mCdma = in.readParcelable(CellSignalStrengthCdma.class.getClassLoader());
+        mGsm = in.readParcelable(CellSignalStrengthGsm.class.getClassLoader());
+        mWcdma = in.readParcelable(CellSignalStrengthWcdma.class.getClassLoader());
+        mTdscdma = in.readParcelable(CellSignalStrengthTdscdma.class.getClassLoader());
+        mLte = in.readParcelable(CellSignalStrengthLte.class.getClassLoader());
         mLteRsrpBoost = in.readInt();
-        mIsGsm = in.readBoolean();
-        mUseOnlyRsrpForLteLevel = in.readBoolean();
-        mWcdmaDefaultSignalMeasurement = in.readString();
-        in.readIntArray(mLteRsrpThresholds);
-        in.readIntArray(mWcdmaRscpThresholds);
     }
 
     /**
      * {@link Parcelable#writeToParcel}
      */
     public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(mGsmSignalStrength);
-        out.writeInt(mGsmBitErrorRate);
-        out.writeInt(mCdmaDbm);
-        out.writeInt(mCdmaEcio);
-        out.writeInt(mEvdoDbm);
-        out.writeInt(mEvdoEcio);
-        out.writeInt(mEvdoSnr);
-        out.writeInt(mLteSignalStrength);
-        out.writeInt(mLteRsrp);
-        out.writeInt(mLteRsrq);
-        out.writeInt(mLteRssnr);
-        out.writeInt(mLteCqi);
-        out.writeInt(mTdScdmaRscp);
-        out.writeInt(mWcdmaSignalStrength);
-        out.writeInt(mWcdmaRscpAsu);
-        out.writeInt(mWcdmaRscp);
+        out.writeParcelable(mCdma, flags);
+        out.writeParcelable(mGsm, flags);
+        out.writeParcelable(mWcdma, flags);
+        out.writeParcelable(mTdscdma, flags);
+        out.writeParcelable(mLte, flags);
+
         out.writeInt(mLteRsrpBoost);
-        out.writeBoolean(mIsGsm);
-        out.writeBoolean(mUseOnlyRsrpForLteLevel);
-        out.writeString(mWcdmaDefaultSignalMeasurement);
-        out.writeIntArray(mLteRsrpThresholds);
-        out.writeIntArray(mWcdmaRscpThresholds);
     }
 
     /**
@@ -392,153 +267,21 @@
     };
 
     /**
-     * Validate the individual signal strength fields as per the range
-     * specified in ril.h
-     * Set to invalid any field that is not in the valid range
-     * Cdma, evdo, lte rsrp & rsrq values are sign converted
-     * when received from ril interface
+     * Get the GSM RSSI in ASU.
      *
-     * @return
-     *      Valid values for all signalstrength fields
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public void validateInput() {
-        if (DBG) log("Signal before validate=" + this);
-        // TS 27.007 8.5
-        mGsmSignalStrength = mGsmSignalStrength >= 0 ? mGsmSignalStrength : 99;
-        mWcdmaSignalStrength = (mWcdmaSignalStrength >= 0) ? mWcdmaSignalStrength : 99;
-        mLteSignalStrength = (mLteSignalStrength >= 0) ? mLteSignalStrength : 99;
-        // BER no change;
-
-        // WCDMA RSCP valid values are -120 through -24 as defined in TS 27.007 8.69
-        // but are reported in ASU which is 0 through 96, so we do the conversion here
-        mWcdmaRscpAsu =
-                ((mWcdmaRscpAsu - 120 >= MIN_WCDMA_RSCP) && (mWcdmaRscpAsu - 120 <= MAX_WCDMA_RSCP))
-                ? mWcdmaRscpAsu : 255;
-        mWcdmaRscp = ((mWcdmaRscp >= MIN_WCDMA_RSCP) && (mWcdmaRscp <= MAX_WCDMA_RSCP))
-                ? mWcdmaRscp : INVALID;
-
-        mCdmaDbm = mCdmaDbm > 0 ? -mCdmaDbm : -120;
-        mCdmaEcio = (mCdmaEcio >= 0) ? -mCdmaEcio : -160;
-
-        mEvdoDbm = (mEvdoDbm > 0) ? -mEvdoDbm : -120;
-        mEvdoEcio = (mEvdoEcio >= 0) ? -mEvdoEcio : -160;
-        mEvdoSnr = ((mEvdoSnr >= 0) && (mEvdoSnr <= 8)) ? mEvdoSnr : -1;
-
-        // TS 36.214 Physical Layer Section 5.1.3, TS 36.331 RRC
-        mLteRsrp = ((-mLteRsrp >= MIN_LTE_RSRP) && (-mLteRsrp <= MAX_LTE_RSRP)) ? -mLteRsrp
-                                : SignalStrength.INVALID;
-        mLteRsrq = ((mLteRsrq >= 3) && (mLteRsrq <= 20)) ? -mLteRsrq : SignalStrength.INVALID;
-        mLteRssnr = ((mLteRssnr >= -200) && (mLteRssnr <= 300)) ? mLteRssnr
-                : SignalStrength.INVALID;
-
-        mTdScdmaRscp = ((mTdScdmaRscp >= 0) && (mTdScdmaRscp <= 96))
-                ? (mTdScdmaRscp - 120) : SignalStrength.INVALID;
-        // Cqi no change
-        if (DBG) log("Signal after validate=" + this);
-    }
-
-    /**
-     * Fix {@link #mIsGsm} based on the signal strength data.
+     * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
      *
-     * @hide
-     */
-    public void fixType() {
-        mIsGsm = getCdmaRelatedSignalStrength() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-    }
-
-    /**
-     * @param true - Gsm, Lte phones
-     *        false - Cdma phones
-     *
-     * Used by voice phone to set the mIsGsm
-     *        flag
-     * @hide
-     */
-    public void setGsm(boolean gsmFlag) {
-        mIsGsm = gsmFlag;
-    }
-
-    /**
-     * @param useOnlyRsrpForLteLevel true if it uses only RSRP for the number of LTE signal bar,
-     * otherwise false.
-     *
-     * Used by phone to use only RSRP or not for the number of LTE signal bar.
-     * @hide
-     */
-    public void setUseOnlyRsrpForLteLevel(boolean useOnlyRsrpForLteLevel) {
-        mUseOnlyRsrpForLteLevel = useOnlyRsrpForLteLevel;
-    }
-
-    /**
-     * @param defaultMeasurement sets the type of WCDMA default signal measurement
-     *
-     * Used by phone to determine default measurement type for calculation WCDMA signal level.
-     * @hide
-     */
-    public void setWcdmaDefaultSignalMeasurement(String defaultMeasurement) {
-        mWcdmaDefaultSignalMeasurement = defaultMeasurement;
-    }
-
-    /**
-     * @param lteRsrpBoost - signal strength offset
-     *
-     * Used by phone to set the lte signal strength offset which will be
-     * reduced from rsrp threshold while calculating signal strength level
-     *
-     * @hide
-     */
-    public void setLteRsrpBoost(int lteRsrpBoost) {
-        mLteRsrpBoost = lteRsrpBoost;
-    }
-
-    /**
-     * Sets the threshold array for determining the display level of LTE signal bar.
-     *
-     * @param lteRsrpThresholds int array for determining the display level.
-     *
-     * @hide
-     */
-    public void setLteRsrpThresholds(int[] lteRsrpThresholds) {
-        if ((lteRsrpThresholds == null)
-                || (lteRsrpThresholds.length != LTE_RSRP_THRESHOLDS_NUM)) {
-            Log.wtf(LOG_TAG, "setLteRsrpThresholds - lteRsrpThresholds is invalid.");
-            return;
-        }
-        System.arraycopy(lteRsrpThresholds, 0, mLteRsrpThresholds, 0, LTE_RSRP_THRESHOLDS_NUM);
-    }
-
-    /**
-     * Get the GSM Signal Strength, valid values are (0-31, 99) as defined in TS
-     * 27.007 8.5
+     * @return RSSI in ASU 0..31, 99, or UNAVAILABLE
      */
     public int getGsmSignalStrength() {
-        return this.mGsmSignalStrength;
+        return mGsm.getAsuLevel();
     }
 
     /**
      * Get the GSM bit error rate (0-7, 99) as defined in TS 27.007 8.5
      */
     public int getGsmBitErrorRate() {
-        return this.mGsmBitErrorRate;
-    }
-
-    /**
-     * Sets the threshold array for determining the display level of WCDMA signal bar.
-     *
-     * @param wcdmaRscpThresholds int array for determining the display level.
-     *
-     * @hide
-     */
-    public void setWcdmaRscpThresholds(int[] wcdmaRscpThresholds) {
-        if ((wcdmaRscpThresholds == null)
-                || (wcdmaRscpThresholds.length != WCDMA_RSCP_THRESHOLDS_NUM)) {
-            Log.wtf(LOG_TAG, "setWcdmaRscpThresholds - wcdmaRscpThresholds is invalid.");
-            return;
-        }
-        System.arraycopy(wcdmaRscpThresholds, 0, mWcdmaRscpThresholds, 0,
-                WCDMA_RSCP_THRESHOLDS_NUM);
+        return mGsm.getBitErrorRate();
     }
 
     /**
@@ -547,14 +290,14 @@
      * @return the CDMA RSSI value or {@link #INVALID} if invalid
      */
     public int getCdmaDbm() {
-        return this.mCdmaDbm;
+        return mCdma.getCdmaDbm();
     }
 
     /**
      * Get the CDMA Ec/Io value in dB*10
      */
     public int getCdmaEcio() {
-        return this.mCdmaEcio;
+        return mCdma.getCdmaEcio();
     }
 
     /**
@@ -563,51 +306,51 @@
      * @return the EVDO RSSI value or {@link #INVALID} if invalid
      */
     public int getEvdoDbm() {
-        return this.mEvdoDbm;
+        return mCdma.getEvdoDbm();
     }
 
     /**
      * Get the EVDO Ec/Io value in dB*10
      */
     public int getEvdoEcio() {
-        return this.mEvdoEcio;
+        return mCdma.getEvdoEcio();
     }
 
     /**
      * Get the signal to noise ratio. Valid values are 0-8. 8 is the highest.
      */
     public int getEvdoSnr() {
-        return this.mEvdoSnr;
+        return mCdma.getEvdoSnr();
     }
 
     /** @hide */
     @UnsupportedAppUsage
     public int getLteSignalStrength() {
-        return mLteSignalStrength;
+        return mLte.getRssi();
     }
 
     /** @hide */
     @UnsupportedAppUsage
     public int getLteRsrp() {
-        return mLteRsrp;
+        return mLte.getRsrp();
     }
 
     /** @hide */
     @UnsupportedAppUsage
     public int getLteRsrq() {
-        return mLteRsrq;
+        return mLte.getRsrq();
     }
 
     /** @hide */
     @UnsupportedAppUsage
     public int getLteRssnr() {
-        return mLteRssnr;
+        return mLte.getRssnr();
     }
 
     /** @hide */
     @UnsupportedAppUsage
     public int getLteCqi() {
-        return mLteCqi;
+        return mLte.getCqi();
     }
 
     /** @hide */
@@ -624,9 +367,12 @@
      *     while 4 represents a very strong signal strength.
      */
     public int getLevel() {
-        int level = mIsGsm ? getGsmRelatedSignalStrength() : getCdmaRelatedSignalStrength();
-        if (DBG) log("getLevel=" + level);
-        return level;
+        int level = getPrimary().getLevel();
+        if (level < SIGNAL_STRENGTH_NONE_OR_UNKNOWN || level > SIGNAL_STRENGTH_GREAT) {
+            log("Invalid Level " + level + ", this=" + this);
+            return SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        }
+        return getPrimary().getLevel();
     }
 
     /**
@@ -636,33 +382,7 @@
      */
     @UnsupportedAppUsage
     public int getAsuLevel() {
-        int asuLevel = 0;
-        if (mIsGsm) {
-            if (mLteRsrp != SignalStrength.INVALID) {
-                asuLevel = getLteAsuLevel();
-            } else if (mTdScdmaRscp != SignalStrength.INVALID) {
-                asuLevel = getTdScdmaAsuLevel();
-            } else if (mWcdmaRscp != SignalStrength.INVALID) {
-                asuLevel = getWcdmaAsuLevel();
-            } else {
-                asuLevel = getGsmAsuLevel();
-            }
-        } else {
-            int cdmaAsuLevel = getCdmaAsuLevel();
-            int evdoAsuLevel = getEvdoAsuLevel();
-            if (evdoAsuLevel == 0) {
-                /* We don't know evdo use, cdma */
-                asuLevel = cdmaAsuLevel;
-            } else if (cdmaAsuLevel == 0) {
-                /* We don't know cdma use, evdo */
-                asuLevel = evdoAsuLevel;
-            } else {
-                /* We know both, use the lowest level */
-                asuLevel = cdmaAsuLevel < evdoAsuLevel ? cdmaAsuLevel : evdoAsuLevel;
-            }
-        }
-        if (DBG) log("getAsuLevel=" + asuLevel);
-        return asuLevel;
+        return getPrimary().getAsuLevel();
     }
 
     /**
@@ -672,30 +392,7 @@
      */
     @UnsupportedAppUsage
     public int getDbm() {
-        int dBm = INVALID;
-
-        if(isGsm()) {
-            dBm = getLteDbm();
-            if (dBm == INVALID) {
-                if (getTdScdmaLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
-                    if (getWcdmaDbm() == INVALID) {
-                        dBm = getGsmDbm();
-                    } else {
-                        dBm = getWcdmaDbm();
-                    }
-                } else {
-                    dBm = getTdScdmaDbm();
-                }
-            }
-        } else {
-            int cdmaDbm = getCdmaDbm();
-            int evdoDbm = getEvdoDbm();
-
-            return (evdoDbm == -120) ? cdmaDbm : ((cdmaDbm == -120) ? evdoDbm
-                    : (cdmaDbm < evdoDbm ? cdmaDbm : evdoDbm));
-        }
-        if (DBG) log("getDbm=" + dBm);
-        return dBm;
+        return getPrimary().getDbm();
     }
 
     /**
@@ -705,17 +402,7 @@
      */
     @UnsupportedAppUsage
     public int getGsmDbm() {
-        int dBm;
-
-        int gsmSignalStrength = getGsmSignalStrength();
-        int asu = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
-        if (asu != -1) {
-            dBm = -113 + (2 * asu);
-        } else {
-            dBm = -1;
-        }
-        if (DBG) log("getGsmDbm=" + dBm);
-        return dBm;
+        return mGsm.getDbm();
     }
 
     /**
@@ -725,20 +412,7 @@
      */
     @UnsupportedAppUsage
     public int getGsmLevel() {
-        int level;
-
-        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
-        // asu = 0 (-113dB or less) is very weak
-        // signal, its better to show 0 bars to the user in such cases.
-        // asu = 99 is a special case, where the signal strength is unknown.
-        int asu = getGsmSignalStrength();
-        if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-        else if (asu >= 12) level = SIGNAL_STRENGTH_GREAT;
-        else if (asu >= 8)  level = SIGNAL_STRENGTH_GOOD;
-        else if (asu >= 5)  level = SIGNAL_STRENGTH_MODERATE;
-        else level = SIGNAL_STRENGTH_POOR;
-        if (DBG) log("getGsmLevel=" + level);
-        return level;
+        return mGsm.getLevel();
     }
 
     /**
@@ -748,13 +422,7 @@
      */
     @UnsupportedAppUsage
     public int getGsmAsuLevel() {
-        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
-        // asu = 0 (-113dB or less) is very weak
-        // signal, its better to show 0 bars to the user in such cases.
-        // asu = 99 is a special case, where the signal strength is unknown.
-        int level = getGsmSignalStrength();
-        if (DBG) log("getGsmAsuLevel=" + level);
-        return level;
+        return mGsm.getAsuLevel();
     }
 
     /**
@@ -764,27 +432,7 @@
      */
     @UnsupportedAppUsage
     public int getCdmaLevel() {
-        final int cdmaDbm = getCdmaDbm();
-        final int cdmaEcio = getCdmaEcio();
-        int levelDbm;
-        int levelEcio;
-
-        if (cdmaDbm >= -75) levelDbm = SIGNAL_STRENGTH_GREAT;
-        else if (cdmaDbm >= -85) levelDbm = SIGNAL_STRENGTH_GOOD;
-        else if (cdmaDbm >= -95) levelDbm = SIGNAL_STRENGTH_MODERATE;
-        else if (cdmaDbm >= -100) levelDbm = SIGNAL_STRENGTH_POOR;
-        else levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-
-        // Ec/Io are in dB*10
-        if (cdmaEcio >= -90) levelEcio = SIGNAL_STRENGTH_GREAT;
-        else if (cdmaEcio >= -110) levelEcio = SIGNAL_STRENGTH_GOOD;
-        else if (cdmaEcio >= -130) levelEcio = SIGNAL_STRENGTH_MODERATE;
-        else if (cdmaEcio >= -150) levelEcio = SIGNAL_STRENGTH_POOR;
-        else levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-
-        int level = (levelDbm < levelEcio) ? levelDbm : levelEcio;
-        if (DBG) log("getCdmaLevel=" + level);
-        return level;
+        return mCdma.getLevel();
     }
 
     /**
@@ -794,29 +442,7 @@
      */
     @UnsupportedAppUsage
     public int getCdmaAsuLevel() {
-        final int cdmaDbm = getCdmaDbm();
-        final int cdmaEcio = getCdmaEcio();
-        int cdmaAsuLevel;
-        int ecioAsuLevel;
-
-        if (cdmaDbm >= -75) cdmaAsuLevel = 16;
-        else if (cdmaDbm >= -82) cdmaAsuLevel = 8;
-        else if (cdmaDbm >= -90) cdmaAsuLevel = 4;
-        else if (cdmaDbm >= -95) cdmaAsuLevel = 2;
-        else if (cdmaDbm >= -100) cdmaAsuLevel = 1;
-        else cdmaAsuLevel = 99;
-
-        // Ec/Io are in dB*10
-        if (cdmaEcio >= -90) ecioAsuLevel = 16;
-        else if (cdmaEcio >= -100) ecioAsuLevel = 8;
-        else if (cdmaEcio >= -115) ecioAsuLevel = 4;
-        else if (cdmaEcio >= -130) ecioAsuLevel = 2;
-        else if (cdmaEcio >= -150) ecioAsuLevel = 1;
-        else ecioAsuLevel = 99;
-
-        int level = (cdmaAsuLevel < ecioAsuLevel) ? cdmaAsuLevel : ecioAsuLevel;
-        if (DBG) log("getCdmaAsuLevel=" + level);
-        return level;
+        return mCdma.getAsuLevel();
     }
 
     /**
@@ -826,26 +452,7 @@
      */
     @UnsupportedAppUsage
     public int getEvdoLevel() {
-        int evdoDbm = getEvdoDbm();
-        int evdoSnr = getEvdoSnr();
-        int levelEvdoDbm;
-        int levelEvdoSnr;
-
-        if (evdoDbm >= -65) levelEvdoDbm = SIGNAL_STRENGTH_GREAT;
-        else if (evdoDbm >= -75) levelEvdoDbm = SIGNAL_STRENGTH_GOOD;
-        else if (evdoDbm >= -90) levelEvdoDbm = SIGNAL_STRENGTH_MODERATE;
-        else if (evdoDbm >= -105) levelEvdoDbm = SIGNAL_STRENGTH_POOR;
-        else levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-
-        if (evdoSnr >= 7) levelEvdoSnr = SIGNAL_STRENGTH_GREAT;
-        else if (evdoSnr >= 5) levelEvdoSnr = SIGNAL_STRENGTH_GOOD;
-        else if (evdoSnr >= 3) levelEvdoSnr = SIGNAL_STRENGTH_MODERATE;
-        else if (evdoSnr >= 1) levelEvdoSnr = SIGNAL_STRENGTH_POOR;
-        else levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-
-        int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
-        if (DBG) log("getEvdoLevel=" + level);
-        return level;
+        return mCdma.getEvdoLevel();
     }
 
     /**
@@ -855,28 +462,7 @@
      */
     @UnsupportedAppUsage
     public int getEvdoAsuLevel() {
-        int evdoDbm = getEvdoDbm();
-        int evdoSnr = getEvdoSnr();
-        int levelEvdoDbm;
-        int levelEvdoSnr;
-
-        if (evdoDbm >= -65) levelEvdoDbm = 16;
-        else if (evdoDbm >= -75) levelEvdoDbm = 8;
-        else if (evdoDbm >= -85) levelEvdoDbm = 4;
-        else if (evdoDbm >= -95) levelEvdoDbm = 2;
-        else if (evdoDbm >= -105) levelEvdoDbm = 1;
-        else levelEvdoDbm = 99;
-
-        if (evdoSnr >= 7) levelEvdoSnr = 16;
-        else if (evdoSnr >= 6) levelEvdoSnr = 8;
-        else if (evdoSnr >= 5) levelEvdoSnr = 4;
-        else if (evdoSnr >= 3) levelEvdoSnr = 2;
-        else if (evdoSnr >= 1) levelEvdoSnr = 1;
-        else levelEvdoSnr = 99;
-
-        int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
-        if (DBG) log("getEvdoAsuLevel=" + level);
-        return level;
+        return mCdma.getEvdoAsuLevel();
     }
 
     /**
@@ -886,7 +472,7 @@
      */
     @UnsupportedAppUsage
     public int getLteDbm() {
-        return mLteRsrp;
+        return mLte.getRsrp();
     }
 
     /**
@@ -896,83 +482,7 @@
      */
     @UnsupportedAppUsage
     public int getLteLevel() {
-        /*
-         * TS 36.214 Physical Layer Section 5.1.3
-         * TS 36.331 RRC
-         *
-         * RSSI = received signal + noise
-         * RSRP = reference signal dBm
-         * RSRQ = quality of signal dB = Number of Resource blocks*RSRP/RSSI
-         * SNR = gain = signal/noise ratio = -10log P1/P2 dB
-         */
-        int rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, rsrpIconLevel = -1, snrIconLevel = -1;
-
-        if (mLteRsrp > MAX_LTE_RSRP || mLteRsrp < MIN_LTE_RSRP) {
-            if (mLteRsrp != INVALID) {
-                Log.wtf(LOG_TAG, "getLteLevel - invalid lte rsrp: mLteRsrp=" + mLteRsrp);
-            }
-        } else if (mLteRsrp >= (mLteRsrpThresholds[3] - mLteRsrpBoost)) {
-            rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
-        } else if (mLteRsrp >= (mLteRsrpThresholds[2] - mLteRsrpBoost)) {
-            rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
-        } else if (mLteRsrp >= (mLteRsrpThresholds[1] - mLteRsrpBoost)) {
-            rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
-        } else if (mLteRsrp >= (mLteRsrpThresholds[0] - mLteRsrpBoost)) {
-            rsrpIconLevel = SIGNAL_STRENGTH_POOR;
-        } else {
-            rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-        }
-
-        if (useOnlyRsrpForLteLevel()) {
-            log("getLTELevel - rsrp = " + rsrpIconLevel);
-            if (rsrpIconLevel != -1) {
-                return rsrpIconLevel;
-            }
-        }
-
-        /*
-         * Values are -200 dB to +300 (SNR*10dB) RS_SNR >= 13.0 dB =>4 bars 4.5
-         * dB <= RS_SNR < 13.0 dB => 3 bars 1.0 dB <= RS_SNR < 4.5 dB => 2 bars
-         * -3.0 dB <= RS_SNR < 1.0 dB 1 bar RS_SNR < -3.0 dB/No Service Antenna
-         * Icon Only
-         */
-        if (mLteRssnr > 300) snrIconLevel = -1;
-        else if (mLteRssnr >= 130) snrIconLevel = SIGNAL_STRENGTH_GREAT;
-        else if (mLteRssnr >= 45) snrIconLevel = SIGNAL_STRENGTH_GOOD;
-        else if (mLteRssnr >= 10) snrIconLevel = SIGNAL_STRENGTH_MODERATE;
-        else if (mLteRssnr >= -30) snrIconLevel = SIGNAL_STRENGTH_POOR;
-        else if (mLteRssnr >= -200)
-            snrIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-
-        if (DBG) log("getLTELevel - rsrp:" + mLteRsrp + " snr:" + mLteRssnr + " rsrpIconLevel:"
-                + rsrpIconLevel + " snrIconLevel:" + snrIconLevel
-                + " lteRsrpBoost:" + mLteRsrpBoost);
-
-        /* Choose a measurement type to use for notification */
-        if (snrIconLevel != -1 && rsrpIconLevel != -1) {
-            /*
-             * The number of bars displayed shall be the smaller of the bars
-             * associated with LTE RSRP and the bars associated with the LTE
-             * RS_SNR
-             */
-            return (rsrpIconLevel < snrIconLevel ? rsrpIconLevel : snrIconLevel);
-        }
-
-        if (snrIconLevel != -1) return snrIconLevel;
-
-        if (rsrpIconLevel != -1) return rsrpIconLevel;
-
-        /* Valid values are (0-31, 99) as defined in TS 27.007 8.5 */
-        if (mLteSignalStrength > 31) rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-        else if (mLteSignalStrength >= 12) rssiIconLevel = SIGNAL_STRENGTH_GREAT;
-        else if (mLteSignalStrength >= 8) rssiIconLevel = SIGNAL_STRENGTH_GOOD;
-        else if (mLteSignalStrength >= 5) rssiIconLevel = SIGNAL_STRENGTH_MODERATE;
-        else if (mLteSignalStrength >= 0) rssiIconLevel = SIGNAL_STRENGTH_POOR;
-
-        if (DBG) log("getLteLevel - rssi:" + mLteSignalStrength + " rssiIconLevel:"
-                + rssiIconLevel);
-        return rssiIconLevel;
-
+        return mLte.getLevel();
     }
 
     /**
@@ -983,41 +493,14 @@
      */
     @UnsupportedAppUsage
     public int getLteAsuLevel() {
-        int lteAsuLevel = 99;
-        int lteDbm = getLteDbm();
-        /*
-         * 3GPP 27.007 (Ver 10.3.0) Sec 8.69
-         * 0   -140 dBm or less
-         * 1   -139 dBm
-         * 2...96  -138... -44 dBm
-         * 97  -43 dBm or greater
-         * 255 not known or not detectable
-         */
-        /*
-         * validateInput will always give a valid range between -140 t0 -44 as
-         * per ril.h. so RSRP >= -43 & <-140 will fall under asu level 255
-         * and not 97 or 0
-         */
-        if (lteDbm == SignalStrength.INVALID) lteAsuLevel = 255;
-        else lteAsuLevel = lteDbm + 140;
-        if (DBG) log("Lte Asu level: "+lteAsuLevel);
-        return lteAsuLevel;
+        return mLte.getAsuLevel();
     }
 
     /**
      * @return true if this is for GSM
      */
     public boolean isGsm() {
-        return this.mIsGsm;
-    }
-
-    /**
-     * @return true if it uses only RSRP for the number of LTE signal bar, otherwise false.
-     *
-     * @hide
-     */
-    public boolean useOnlyRsrpForLteLevel() {
-        return this.mUseOnlyRsrpForLteLevel;
+        return !(getPrimary() instanceof CellSignalStrengthCdma);
     }
 
     /**
@@ -1027,7 +510,7 @@
      */
     @UnsupportedAppUsage
     public int getTdScdmaDbm() {
-        return this.mTdScdmaRscp;
+        return mTdscdma.getRscp();
     }
 
     /**
@@ -1040,19 +523,7 @@
      */
     @UnsupportedAppUsage
     public int getTdScdmaLevel() {
-        final int tdScdmaDbm = getTdScdmaDbm();
-        int level;
-
-        if ((tdScdmaDbm > -25) || (tdScdmaDbm == SignalStrength.INVALID))
-                level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-        else if (tdScdmaDbm >= -49) level = SIGNAL_STRENGTH_GREAT;
-        else if (tdScdmaDbm >= -73) level = SIGNAL_STRENGTH_GOOD;
-        else if (tdScdmaDbm >= -97) level = SIGNAL_STRENGTH_MODERATE;
-        else if (tdScdmaDbm >= -110) level = SIGNAL_STRENGTH_POOR;
-        else level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-
-        if (DBG) log("getTdScdmaLevel = " + level);
-        return level;
+        return mTdscdma.getLevel();
      }
 
     /**
@@ -1062,13 +533,7 @@
      */
     @UnsupportedAppUsage
     public int getTdScdmaAsuLevel() {
-        final int tdScdmaDbm = getTdScdmaDbm();
-        int tdScdmaAsuLevel;
-
-        if (tdScdmaDbm == INVALID) tdScdmaAsuLevel = 255;
-        else tdScdmaAsuLevel = tdScdmaDbm + 120;
-        if (DBG) log("TD-SCDMA Asu level: " + tdScdmaAsuLevel);
-        return tdScdmaAsuLevel;
+        return mTdscdma.getAsuLevel();
     }
 
     /**
@@ -1077,7 +542,7 @@
      * @hide
      */
     public int getWcdmaRscp() {
-        return mWcdmaRscp;
+        return mWcdma.getRscp();
     }
 
     /**
@@ -1094,14 +559,7 @@
          * 96     -24 dBm or greater
          * 255    not known or not detectable
          */
-        final int wcdmaDbm = getWcdmaDbm();
-        int wcdmaAsuLevel = 255;
-        // validateInput will always give a valid range between -120 to -24 as per ril.h. so RSCP
-        // outside range is already set to INVALID
-        if (wcdmaDbm == SignalStrength.INVALID) wcdmaAsuLevel =  255;
-        else wcdmaAsuLevel = wcdmaDbm + 120;
-        if (DBG) log("Wcdma Asu level: " + wcdmaAsuLevel);
-        return wcdmaAsuLevel;
+        return mWcdma.getAsuLevel();
     }
 
     /**
@@ -1110,7 +568,7 @@
      * @hide
      */
     public int getWcdmaDbm() {
-        return mWcdmaRscp;
+        return mWcdma.getDbm();
     }
 
     /**
@@ -1119,55 +577,7 @@
      * @hide
      */
     public int getWcdmaLevel() {
-        int level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-
-        if (mWcdmaDefaultSignalMeasurement == null) {
-            Log.wtf(LOG_TAG, "getWcdmaLevel - WCDMA default signal measurement is invalid.");
-            return level;
-        }
-
-        switch (mWcdmaDefaultSignalMeasurement) {
-            case MEASUMENT_TYPE_RSCP:
-                // RSCP valid values are (-120 through -24) as defined in TS 27.007 8.69
-                if (mWcdmaRscp < MIN_WCDMA_RSCP || mWcdmaRscp > MAX_WCDMA_RSCP) {
-                    if (mWcdmaRscp != INVALID) {
-                        Log.wtf(LOG_TAG, "getWcdmaLevel - invalid WCDMA RSCP: mWcdmaRscp="
-                                + mWcdmaRscp);
-                    }
-                } else if (mWcdmaRscp >= mWcdmaRscpThresholds[3]) {
-                    level = SIGNAL_STRENGTH_GREAT;
-                } else if (mWcdmaRscp >= mWcdmaRscpThresholds[2]) {
-                    level = SIGNAL_STRENGTH_GOOD;
-                } else if (mWcdmaRscp >= mWcdmaRscpThresholds[1]) {
-                    level = SIGNAL_STRENGTH_MODERATE;
-                } else if (mWcdmaRscp >= mWcdmaRscpThresholds[0]) {
-                    level = SIGNAL_STRENGTH_POOR;
-                }
-                if (DBG) log("getWcdmaLevel=" + level + " WcdmaRscp=" + mWcdmaRscp);
-                break;
-
-            default:
-                // RSSI valid values are (0..31) as defined in TS 27.007 8.5
-                if (mWcdmaSignalStrength < 0 || mWcdmaSignalStrength > 31) {
-                    if (mWcdmaSignalStrength != 99) {
-                        Log.wtf(LOG_TAG, "getWcdmaLevel - invalid WCDMA RSSI: mWcdmaSignalStrength="
-                                + mWcdmaSignalStrength);
-                    }
-                } else if (mWcdmaSignalStrength >= 18) {
-                    level = SIGNAL_STRENGTH_GREAT;
-                } else if (mWcdmaSignalStrength >= 13) {
-                    level = SIGNAL_STRENGTH_GOOD;
-                } else if (mWcdmaSignalStrength >= 8) {
-                    level = SIGNAL_STRENGTH_MODERATE;
-                } else if (mWcdmaSignalStrength >= 3) {
-                    level = SIGNAL_STRENGTH_POOR;
-                }
-                if (DBG) log("getWcdmaLevel=" + level + " WcdmaSignalStrength=" +
-                        mWcdmaSignalStrength);
-                break;
-
-        }
-        return level;
+        return mWcdma.getLevel();
     }
 
    /**
@@ -1175,18 +585,7 @@
      */
     @Override
     public int hashCode() {
-        int primeNum = 31;
-        return ((mGsmSignalStrength * primeNum)
-                + (mGsmBitErrorRate * primeNum)
-                + (mCdmaDbm * primeNum) + (mCdmaEcio * primeNum)
-                + (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum)
-                + (mLteSignalStrength * primeNum) + (mLteRsrp * primeNum)
-                + (mLteRsrq * primeNum) + (mLteRssnr * primeNum) + (mLteCqi * primeNum)
-                + (mLteRsrpBoost * primeNum) + (mTdScdmaRscp * primeNum)
-                + (mWcdmaSignalStrength * primeNum) + (mWcdmaRscpAsu * primeNum)
-                + (mWcdmaRscp * primeNum) + (mIsGsm ? 1 : 0) + (mUseOnlyRsrpForLteLevel ? 1 : 0)
-                + (Objects.hashCode(mWcdmaDefaultSignalMeasurement))
-                + (Arrays.hashCode(mLteRsrpThresholds)) + (Arrays.hashCode(mWcdmaRscpThresholds)));
+        return Objects.hash(mCdma, mGsm, mWcdma, mTdscdma, mLte, mLteRsrpBoost);
     }
 
     /**
@@ -1194,40 +593,16 @@
      */
     @Override
     public boolean equals (Object o) {
-        SignalStrength s;
+        if (!(o instanceof SignalStrength)) return false;
 
-        try {
-            s = (SignalStrength) o;
-        } catch (ClassCastException ex) {
-            return false;
-        }
+        SignalStrength s = (SignalStrength) o;
 
-        if (o == null) {
-            return false;
-        }
-
-        return (mGsmSignalStrength == s.mGsmSignalStrength
-                && mGsmBitErrorRate == s.mGsmBitErrorRate
-                && mCdmaDbm == s.mCdmaDbm
-                && mCdmaEcio == s.mCdmaEcio
-                && mEvdoDbm == s.mEvdoDbm
-                && mEvdoEcio == s.mEvdoEcio
-                && mEvdoSnr == s.mEvdoSnr
-                && mLteSignalStrength == s.mLteSignalStrength
-                && mLteRsrp == s.mLteRsrp
-                && mLteRsrq == s.mLteRsrq
-                && mLteRssnr == s.mLteRssnr
-                && mLteCqi == s.mLteCqi
-                && mLteRsrpBoost == s.mLteRsrpBoost
-                && mTdScdmaRscp == s.mTdScdmaRscp
-                && mWcdmaSignalStrength == s.mWcdmaSignalStrength
-                && mWcdmaRscpAsu == s.mWcdmaRscpAsu
-                && mWcdmaRscp == s.mWcdmaRscp
-                && mIsGsm == s.mIsGsm
-                && mUseOnlyRsrpForLteLevel == s.mUseOnlyRsrpForLteLevel
-                && Objects.equals(mWcdmaDefaultSignalMeasurement, s.mWcdmaDefaultSignalMeasurement)
-                && Arrays.equals(mLteRsrpThresholds, s.mLteRsrpThresholds)
-                && Arrays.equals(mWcdmaRscpThresholds, s.mWcdmaRscpThresholds));
+        return mCdma.equals(s.mCdma)
+            && mGsm.equals(s.mGsm)
+            && mWcdma.equals(s.mWcdma)
+            && mTdscdma.equals(s.mTdscdma)
+            && mLte.equals(s.mLte)
+            && mLteRsrpBoost == s.mLteRsrpBoost;
     }
 
     /**
@@ -1235,63 +610,16 @@
      */
     @Override
     public String toString() {
-        return ("SignalStrength:"
-                + " " + mGsmSignalStrength
-                + " " + mGsmBitErrorRate
-                + " " + mCdmaDbm
-                + " " + mCdmaEcio
-                + " " + mEvdoDbm
-                + " " + mEvdoEcio
-                + " " + mEvdoSnr
-                + " " + mLteSignalStrength
-                + " " + mLteRsrp
-                + " " + mLteRsrq
-                + " " + mLteRssnr
-                + " " + mLteCqi
-                + " " + mLteRsrpBoost
-                + " " + mTdScdmaRscp
-                + " " + mWcdmaSignalStrength
-                + " " + mWcdmaRscpAsu
-                + " " + mWcdmaRscp
-                + " " + (mIsGsm ? "gsm|lte" : "cdma")
-                + " " + (mUseOnlyRsrpForLteLevel ? "use_only_rsrp_for_lte_level" :
-                         "use_rsrp_and_rssnr_for_lte_level")
-                + " " + mWcdmaDefaultSignalMeasurement
-                + " " + (Arrays.toString(mLteRsrpThresholds))
-                + " " + (Arrays.toString(mWcdmaRscpThresholds)));
-    }
-
-    /** Returns the signal strength related to GSM. */
-    private int getGsmRelatedSignalStrength() {
-        int level = getLteLevel();
-        if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
-            level = getTdScdmaLevel();
-            if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
-                level = getWcdmaLevel();
-                if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
-                    level = getGsmLevel();
-                }
-            }
-        }
-        return level;
-    }
-
-    /** Returns the signal strength related to CDMA. */
-    private int getCdmaRelatedSignalStrength() {
-        int level;
-        int cdmaLevel = getCdmaLevel();
-        int evdoLevel = getEvdoLevel();
-        if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
-            /* We don't know evdo, use cdma */
-            level = cdmaLevel;
-        } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
-            /* We don't know cdma, use evdo */
-            level = evdoLevel;
-        } else {
-            /* We know both, use the lowest level */
-            level = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
-        }
-        return level;
+        return new StringBuilder().append("SignalStrength:{")
+            .append("mCdma=").append(mCdma)
+            .append(",mGsm=").append(mGsm)
+            .append(",mWcdma=").append(mWcdma)
+            .append(",mTdscdma=").append(mTdscdma)
+            .append(",mLte=").append(mLte)
+            .append(",mLteRsrpBoost=").append(mLteRsrpBoost)
+            .append(",primary=").append(getPrimary().getClass().getSimpleName())
+            .append("}")
+            .toString();
     }
 
     /**
@@ -1302,34 +630,13 @@
      */
     @UnsupportedAppUsage
     private void setFromNotifierBundle(Bundle m) {
-        mGsmSignalStrength = m.getInt("GsmSignalStrength");
-        mGsmBitErrorRate = m.getInt("GsmBitErrorRate");
-        mCdmaDbm = m.getInt("CdmaDbm");
-        mCdmaEcio = m.getInt("CdmaEcio");
-        mEvdoDbm = m.getInt("EvdoDbm");
-        mEvdoEcio = m.getInt("EvdoEcio");
-        mEvdoSnr = m.getInt("EvdoSnr");
-        mLteSignalStrength = m.getInt("LteSignalStrength");
-        mLteRsrp = m.getInt("LteRsrp");
-        mLteRsrq = m.getInt("LteRsrq");
-        mLteRssnr = m.getInt("LteRssnr");
-        mLteCqi = m.getInt("LteCqi");
+        mCdma = m.getParcelable("Cdma");
+        mGsm = m.getParcelable("Gsm");
+        mWcdma = m.getParcelable("Wcdma");
+        mTdscdma = m.getParcelable("Tdscdma");
+        mLte = m.getParcelable("Lte");
+
         mLteRsrpBoost = m.getInt("LteRsrpBoost");
-        mTdScdmaRscp = m.getInt("TdScdma");
-        mWcdmaSignalStrength = m.getInt("WcdmaSignalStrength");
-        mWcdmaRscpAsu = m.getInt("WcdmaRscpAsu");
-        mWcdmaRscp = m.getInt("WcdmaRscp");
-        mIsGsm = m.getBoolean("IsGsm");
-        mUseOnlyRsrpForLteLevel = m.getBoolean("UseOnlyRsrpForLteLevel");
-        mWcdmaDefaultSignalMeasurement = m.getString("WcdmaDefaultSignalMeasurement");
-        ArrayList<Integer> lteRsrpThresholds = m.getIntegerArrayList("lteRsrpThresholds");
-        for (int i = 0; i < lteRsrpThresholds.size(); i++) {
-            mLteRsrpThresholds[i] = lteRsrpThresholds.get(i);
-        }
-        ArrayList<Integer> wcdmaRscpThresholds = m.getIntegerArrayList("wcdmaRscpThresholds");
-        for (int i = 0; i < wcdmaRscpThresholds.size(); i++) {
-            mWcdmaRscpThresholds[i] = wcdmaRscpThresholds.get(i);
-        }
     }
 
     /**
@@ -1340,56 +647,13 @@
      */
     @UnsupportedAppUsage
     public void fillInNotifierBundle(Bundle m) {
-        m.putInt("GsmSignalStrength", mGsmSignalStrength);
-        m.putInt("GsmBitErrorRate", mGsmBitErrorRate);
-        m.putInt("CdmaDbm", mCdmaDbm);
-        m.putInt("CdmaEcio", mCdmaEcio);
-        m.putInt("EvdoDbm", mEvdoDbm);
-        m.putInt("EvdoEcio", mEvdoEcio);
-        m.putInt("EvdoSnr", mEvdoSnr);
-        m.putInt("LteSignalStrength", mLteSignalStrength);
-        m.putInt("LteRsrp", mLteRsrp);
-        m.putInt("LteRsrq", mLteRsrq);
-        m.putInt("LteRssnr", mLteRssnr);
-        m.putInt("LteCqi", mLteCqi);
+        m.putParcelable("Cdma", mCdma);
+        m.putParcelable("Gsm", mGsm);
+        m.putParcelable("Wcdma", mWcdma);
+        m.putParcelable("Tdscdma", mTdscdma);
+        m.putParcelable("Lte", mLte);
+
         m.putInt("LteRsrpBoost", mLteRsrpBoost);
-        m.putInt("TdScdma", mTdScdmaRscp);
-        m.putInt("WcdmaSignalStrength", mWcdmaSignalStrength);
-        m.putInt("WcdmaRscpAsu", mWcdmaRscpAsu);
-        m.putInt("WcdmaRscp", mWcdmaRscp);
-        m.putBoolean("IsGsm", mIsGsm);
-        m.putBoolean("UseOnlyRsrpForLteLevel", mUseOnlyRsrpForLteLevel);
-        m.putString("WcdmaDefaultSignalMeasurement", mWcdmaDefaultSignalMeasurement);
-        ArrayList<Integer> lteRsrpThresholds = new ArrayList<Integer>();
-        for (int value : mLteRsrpThresholds) {
-            lteRsrpThresholds.add(value);
-        }
-        m.putIntegerArrayList("lteRsrpThresholds", lteRsrpThresholds);
-        ArrayList<Integer> wcdmaRscpThresholds = new ArrayList<Integer>();
-        for (int value : mWcdmaRscpThresholds) {
-            wcdmaRscpThresholds.add(value);
-        }
-        m.putIntegerArrayList("wcdmaRscpThresholds", wcdmaRscpThresholds);
-    }
-
-    /**
-     * Gets the default threshold array for determining the display level of LTE signal bar.
-     *
-     * @return int array for determining the display level.
-     */
-    private int[] getDefaultLteRsrpThresholds() {
-        return CarrierConfigManager.getDefaultConfig().getIntArray(
-                CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY);
-    }
-
-    /**
-     * Gets the default threshold array for determining the display level of WCDMA signal bar.
-     *
-     * @return int array for determining the display level.
-     */
-    private int[] getDefaultWcdmaRscpThresholds() {
-        return CarrierConfigManager.getDefaultConfig().getIntArray(
-                CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY);
     }
 
     /**
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index a7e8e8a..0a58fa0 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -138,10 +138,15 @@
     private UiccAccessRule[] mAccessRules;
 
     /**
-     * The ID of the SIM card. It is the ICCID of the active profile for a UICC card and the EID
-     * for an eUICC card.
+     * The string ID of the SIM card. It is the ICCID of the active profile for a UICC card and the
+     * EID for an eUICC card.
      */
-    private String mCardId;
+    private String mCardString;
+
+    /**
+     * The card ID of the SIM card. This maps uniquely to the card string.
+     */
+    private int mCardId;
 
     /**
      * Whether the subscription is opportunistic.
@@ -174,9 +179,9 @@
     public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
             CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
             Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
-            @Nullable UiccAccessRule[] accessRules, String cardId) {
+            @Nullable UiccAccessRule[] accessRules, String cardString) {
         this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
-                roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardId,
+                roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardString,
                 false, null, true, TelephonyManager.UNKNOWN_CARRIER_ID);
     }
 
@@ -186,20 +191,22 @@
     public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
             CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
             Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
-            @Nullable UiccAccessRule[] accessRules, String cardId, boolean isOpportunistic,
+            @Nullable UiccAccessRule[] accessRules, String cardString, boolean isOpportunistic,
             @Nullable String groupUUID, boolean isMetered, int carrierId) {
         this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
-                roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardId,
+                roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardString, -1,
                 isOpportunistic, groupUUID, isMetered, false, carrierId);
     }
+
     /**
      * @hide
      */
     public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
             CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
             Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
-            @Nullable UiccAccessRule[] accessRules, String cardId, boolean isOpportunistic,
-            @Nullable String groupUUID, boolean isMetered, boolean isGroupDisabled, int carrierid) {
+            @Nullable UiccAccessRule[] accessRules, String cardString, int cardId,
+            boolean isOpportunistic, @Nullable String groupUUID, boolean isMetered,
+            boolean isGroupDisabled, int carrierid) {
         this.mId = id;
         this.mIccId = iccId;
         this.mSimSlotIndex = simSlotIndex;
@@ -215,6 +222,7 @@
         this.mCountryIso = countryIso;
         this.mIsEmbedded = isEmbedded;
         this.mAccessRules = accessRules;
+        this.mCardString = cardString;
         this.mCardId = cardId;
         this.mIsOpportunistic = isOpportunistic;
         this.mGroupUUID = groupUUID;
@@ -523,10 +531,20 @@
     }
 
     /**
-     * @return the ID of the SIM card which contains the subscription.
+     * @return the card string of the SIM card which contains the subscription. The card string is
+     * the ICCID for UICCs or the EID for eUICCs.
      * @hide
      */
-    public String getCardId() {
+    public String getCardString() {
+        return this.mCardString;
+    }
+
+    /**
+     * @return the cardId of the SIM card which contains the subscription.
+     * @hide
+     */
+    @SystemApi
+    public int getCardId() {
         return this.mCardId;
     }
 
@@ -564,7 +582,8 @@
             Bitmap iconBitmap = Bitmap.CREATOR.createFromParcel(source);
             boolean isEmbedded = source.readBoolean();
             UiccAccessRule[] accessRules = source.createTypedArray(UiccAccessRule.CREATOR);
-            String cardId = source.readString();
+            String cardString = source.readString();
+            int cardId = source.readInt();
             boolean isOpportunistic = source.readBoolean();
             String groupUUID = source.readString();
             boolean isMetered = source.readBoolean();
@@ -573,8 +592,8 @@
 
             return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
                     nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso,
-                    isEmbedded, accessRules, cardId, isOpportunistic, groupUUID, isMetered,
-                    isGroupDisabled, carrierid);
+                    isEmbedded, accessRules, cardString, cardId, isOpportunistic, groupUUID,
+                    isMetered, isGroupDisabled, carrierid);
         }
 
         @Override
@@ -600,7 +619,8 @@
         mIconBitmap.writeToParcel(dest, flags);
         dest.writeBoolean(mIsEmbedded);
         dest.writeTypedArray(mAccessRules, flags);
-        dest.writeString(mCardId);
+        dest.writeString(mCardString);
+        dest.writeInt(mCardId);
         dest.writeBoolean(mIsOpportunistic);
         dest.writeString(mGroupUUID);
         dest.writeBoolean(mIsMetered);
@@ -631,7 +651,7 @@
     @Override
     public String toString() {
         String iccIdToPrint = givePrintableIccid(mIccId);
-        String cardIdToPrint = givePrintableIccid(mCardId);
+        String cardStringToPrint = givePrintableIccid(mCardString);
         return "{id=" + mId + ", iccId=" + iccIdToPrint + " simSlotIndex=" + mSimSlotIndex
                 + " carrierId=" + mCarrierId + " displayName=" + mDisplayName
                 + " carrierName=" + mCarrierName + " nameSource=" + mNameSource
@@ -639,17 +659,17 @@
                 + " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc
                 + " mnc " + mMnc + "mCountryIso=" + mCountryIso + " isEmbedded " + mIsEmbedded
                 + " accessRules " + Arrays.toString(mAccessRules)
-                + " cardId=" + cardIdToPrint + " isOpportunistic " + mIsOpportunistic
-                + " mGroupUUID=" + mGroupUUID + " isMetered=" + mIsMetered
-                + " mIsGroupDisabled=" + mIsGroupDisabled + "}";
+                + " cardString=" + cardStringToPrint + " cardId=" + mCardId
+                + " isOpportunistic " + mIsOpportunistic + " mGroupUUID=" + mGroupUUID
+                + " isMetered=" + mIsMetered + " mIsGroupDisabled=" + mIsGroupDisabled + "}";
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded,
                 mIsOpportunistic, mGroupUUID, mIsMetered, mIccId, mNumber, mMcc, mMnc,
-                mCountryIso, mCardId, mDisplayName, mCarrierName, mAccessRules, mIsGroupDisabled,
-                mCarrierId);
+                mCountryIso, mCardString, mCardId, mDisplayName, mCarrierName, mAccessRules,
+                mIsGroupDisabled, mCarrierId);
     }
 
     @Override
@@ -680,6 +700,7 @@
                 && Objects.equals(mMcc, toCompare.mMcc)
                 && Objects.equals(mMnc, toCompare.mMnc)
                 && Objects.equals(mCountryIso, toCompare.mCountryIso)
+                && Objects.equals(mCardString, toCompare.mCardString)
                 && Objects.equals(mCardId, toCompare.mCardId)
                 && TextUtils.equals(mDisplayName, toCompare.mDisplayName)
                 && TextUtils.equals(mCarrierName, toCompare.mCarrierName)
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index f782fae..b3c4b82 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -19,6 +19,7 @@
 import static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
 import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
 
+import android.Manifest;
 import android.annotation.CallbackExecutor;
 import android.annotation.DurationMillisLong;
 import android.annotation.NonNull;
@@ -52,6 +53,7 @@
 import android.os.ServiceManager;
 import android.telephony.euicc.EuiccManager;
 import android.telephony.ims.ImsMmTelManager;
+import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.Log;
 
@@ -67,6 +69,7 @@
 import java.util.Locale;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /**
  * SubscriptionManager is the application interface to SubscriptionController
@@ -2391,16 +2394,21 @@
      * together, some of them may be invisible to the users, etc.
      *
      * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE}
-     * permission or can manage all subscriptions in the list, according to their
-     * acess rules.
+     * permission or had carrier privilege permission on the subscriptions:
+     * {@link TelephonyManager#hasCarrierPrivileges()} or
+     * {@link #canManageSubscription(SubscriptionInfo)}
+     *
+     * @throws SecurityException if the caller doesn't meet the requirements
+     *             outlined above.
      *
      * @param subIdList list of subId that will be in the same group
      * @return groupUUID a UUID assigned to the subscription group. It returns
      * null if fails.
      *
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
-    public String setSubscriptionGroup(int[] subIdList) {
+    public @Nullable String setSubscriptionGroup(@NonNull int[] subIdList) {
         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
         if (VDBG) {
             logd("[setSubscriptionGroup]+ subIdList:" + Arrays.toString(subIdList));
@@ -2420,6 +2428,80 @@
     }
 
     /**
+     * Remove a list of subscriptions from their subscription group.
+     * See {@link #setSubscriptionGroup(int[])} for more details.
+     *
+     * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE}
+     * permission or had carrier privilege permission on the subscriptions:
+     * {@link TelephonyManager#hasCarrierPrivileges()} or
+     * {@link #canManageSubscription(SubscriptionInfo)}
+     *
+     * @throws SecurityException if the caller doesn't meet the requirements
+     *             outlined above.
+     *
+     * @param subIdList list of subId that need removing from their groups.
+     * @return whether the operation succeeds.
+     *
+     */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    public boolean removeSubscriptionsFromGroup(@NonNull int[] subIdList) {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        if (VDBG) {
+            logd("[removeSubscriptionsFromGroup]+ subIdList:" + Arrays.toString(subIdList));
+        }
+
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                return iSub.removeSubscriptionsFromGroup(subIdList, pkgForDebug);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return false;
+    }
+
+    /**
+     * Get subscriptionInfo list of subscriptions that are in the same group of given subId.
+     * See {@link #setSubscriptionGroup(int[])} for more details.
+     *
+     * Caller will either have {@link android.Manifest.permission#READ_PHONE_STATE}
+     * permission or had carrier privilege permission on the subscription.
+     * {@link TelephonyManager#hasCarrierPrivileges()}
+     *
+     * @throws SecurityException if the caller doesn't meet the requirements
+     *             outlined above.
+     *
+     * @param subId of which list of subInfo from the same group will be returned.
+     * @return list of subscriptionInfo that belong to the same group, including the given
+     * subscription itself. It will return null if the subscription doesn't exist or it
+     * doesn't belong to any group.
+     *
+     */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
+    public @Nullable List<SubscriptionInfo> getSubscriptionsInGroup(int subId) {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        if (VDBG) {
+            logd("[getSubscriptionsInGroup]+ subId:" + subId);
+        }
+
+        List<SubscriptionInfo> result = null;
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                result = iSub.getSubscriptionsInGroup(subId, pkgForDebug);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return result;
+    }
+
+    /**
      * Set metered by simInfo index
      *
      * @param isMetered whether it’s a metered subscription.
@@ -2434,6 +2516,42 @@
                 (iSub)-> iSub.setMetered(isMetered, subId));
     }
 
+    /**
+     * Whether system UI should hide a subscription. If it's a bundled opportunistic
+     * subscription, it shouldn't show up in anywhere in Settings app, dialer app,
+     * or status bar.
+     *
+     * @param info the subscriptionInfo to check against.
+     * @return true if this subscription should be hidden.
+     *
+     * @hide
+     */
+    public static boolean shouldHideSubscription(SubscriptionInfo info) {
+        return (info != null && !TextUtils.isEmpty(info.getGroupUuid()) && info.isOpportunistic());
+    }
+
+    /**
+     * Return a list of subscriptions that are available and visible to the user.
+     * Used by Settings app to show a list of subscriptions for user to pick.
+     *
+     * <p>
+     * Permissions android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE is required
+     * for getSelectableSubscriptionInfoList to be invoked.
+     * @return list of user selectable subscriptions.
+     *
+     * @hide
+     */
+    public @Nullable List<SubscriptionInfo> getSelectableSubscriptionInfoList() {
+        List<SubscriptionInfo> availableList = getAvailableSubscriptionInfoList();
+        if (availableList == null) {
+            return null;
+        } else {
+            return getAvailableSubscriptionInfoList().stream()
+                    .filter(subInfo -> !shouldHideSubscription(subInfo))
+                    .collect(Collectors.toList());
+        }
+    }
+
     private interface CallISubMethodHelper {
         int callMethod(ISub iSub) throws RemoteException;
     }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index bb48d53539..588073a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -625,8 +625,6 @@
      * The {@link #EXTRA_RINGING_CALL_STATE} extra indicates the ringing call state.
      * The {@link #EXTRA_FOREGROUND_CALL_STATE} extra indicates the foreground call state.
      * The {@link #EXTRA_BACKGROUND_CALL_STATE} extra indicates the background call state.
-     * The {@link #EXTRA_DISCONNECT_CAUSE} extra indicates the disconnect cause.
-     * The {@link #EXTRA_PRECISE_DISCONNECT_CAUSE} extra indicates the precise disconnect cause.
      *
      * <p class="note">
      * Requires the READ_PRECISE_PHONE_STATE permission.
@@ -634,12 +632,10 @@
      * @see #EXTRA_RINGING_CALL_STATE
      * @see #EXTRA_FOREGROUND_CALL_STATE
      * @see #EXTRA_BACKGROUND_CALL_STATE
-     * @see #EXTRA_DISCONNECT_CAUSE
-     * @see #EXTRA_PRECISE_DISCONNECT_CAUSE
      *
      * <p class="note">
      * Requires the READ_PRECISE_PHONE_STATE permission.
-     *
+     * @deprecated use {@link PhoneStateListener#LISTEN_PRECISE_CALL_STATE} instead
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -647,8 +643,28 @@
             "android.intent.action.PRECISE_CALL_STATE";
 
     /**
-     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast
-     * for an integer containing the state of the current ringing call.
+     * Broadcast intent action indicating that call disconnect cause has changed.
+     *
+     * <p>
+     * The {@link #EXTRA_DISCONNECT_CAUSE} extra indicates the disconnect cause.
+     * The {@link #EXTRA_PRECISE_DISCONNECT_CAUSE} extra indicates the precise disconnect cause.
+     *
+     * <p class="note">
+     * Requires the READ_PRECISE_PHONE_STATE permission.
+     *
+     * @see #EXTRA_DISCONNECT_CAUSE
+     * @see #EXTRA_PRECISE_DISCONNECT_CAUSE
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_CALL_DISCONNECT_CAUSE_CHANGED =
+            "android.intent.action.CALL_DISCONNECT_CAUSE";
+
+    /**
+     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
+     * {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
+     * containing the state of the current ringing call.
      *
      * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
      * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
@@ -670,8 +686,9 @@
     public static final String EXTRA_RINGING_CALL_STATE = "ringing_state";
 
     /**
-     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast
-     * for an integer containing the state of the current foreground call.
+     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
+     * {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
+     * containing the state of the current foreground call.
      *
      * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
      * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
@@ -693,8 +710,9 @@
     public static final String EXTRA_FOREGROUND_CALL_STATE = "foreground_state";
 
     /**
-     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast
-     * for an integer containing the state of the current background call.
+     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
+     * {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
+     * containing the state of the current background call.
      *
      * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
      * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
@@ -716,8 +734,9 @@
     public static final String EXTRA_BACKGROUND_CALL_STATE = "background_state";
 
     /**
-     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast
-     * for an integer containing the disconnect cause.
+     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
+     * {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
+     * containing the disconnect cause.
      *
      * @see DisconnectCause
      *
@@ -730,8 +749,9 @@
     public static final String EXTRA_DISCONNECT_CAUSE = "disconnect_cause";
 
     /**
-     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast
-     * for an integer containing the disconnect cause provided by the RIL.
+     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
+     * {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
+     * containing the disconnect cause provided by the RIL.
      *
      * @see PreciseDisconnectCause
      *
@@ -6645,7 +6665,7 @@
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                return telephony.getCarrierPrivilegeStatus(mSubId) ==
+                return telephony.getCarrierPrivilegeStatus(subId) ==
                     CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
             }
         } catch (RemoteException ex) {
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index b0c875e..0fdca5d 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -79,10 +79,7 @@
     public static final int EVENT_PS_RESTRICT_DISABLED = BASE + 23;
     public static final int EVENT_CLEAN_UP_CONNECTION = BASE + 24;
     public static final int EVENT_RESTART_RADIO = BASE + 26;
-    public static final int EVENT_SET_INTERNAL_DATA_ENABLE = BASE + 27;
     public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = BASE + 29;
-    public static final int CMD_SET_USER_DATA_ENABLE = BASE + 30;
-    public static final int CMD_SET_POLICY_DATA_ENABLE = BASE + 32;
     public static final int EVENT_ICC_CHANGED = BASE + 33;
     public static final int EVENT_DISCONNECT_DC_RETRYING = BASE + 34;
     public static final int EVENT_DATA_SETUP_COMPLETE_ERROR = BASE + 35;
@@ -93,14 +90,12 @@
     public static final int CMD_NET_STAT_POLL = BASE + 40;
     public static final int EVENT_DATA_RAT_CHANGED = BASE + 41;
     public static final int CMD_CLEAR_PROVISIONING_SPINNER = BASE + 42;
-    public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 43;
     public static final int EVENT_REDIRECTION_DETECTED = BASE + 44;
     public static final int EVENT_PCO_DATA_RECEIVED = BASE + 45;
-    public static final int EVENT_SET_CARRIER_DATA_ENABLED = BASE + 46;
+    public static final int EVENT_DATA_ENABLED_CHANGED = BASE + 46;
     public static final int EVENT_DATA_RECONNECT = BASE + 47;
     public static final int EVENT_ROAMING_SETTING_CHANGE = BASE + 48;
     public static final int EVENT_DATA_SERVICE_BINDING_CHANGED = BASE + 49;
-    public static final int EVENT_DEVICE_PROVISIONING_DATA_SETTING_CHANGE = BASE + 50;
 
     /***** Constants *****/
 
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 442fc34..40c7a9a 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -53,5 +53,6 @@
     void onPhoneCapabilityChanged(in PhoneCapability capability);
     void onRadioPowerStateChanged(in int state);
     void onPreferredDataSubIdChanged(in int subId);
+    void onCallDisconnectCauseChanged(in int disconnectCause, in int preciseDisconnectCause);
 }
 
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index f9db4b0..65d1a920 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -210,6 +210,10 @@
      */
     List<SubscriptionInfo> getOpportunisticSubscriptions(String callingPackage);
 
+    boolean removeSubscriptionsFromGroup(in int[] subIdList, String callingPackage);
+
+    List<SubscriptionInfo> getSubscriptionsInGroup(int subId, String callingPackage);
+
     int getSlotIndex(int subId);
 
     int[] getSubId(int slotIndex);
diff --git a/tools/incident_report/printer.h b/tools/incident_report/printer.h
index ed93fa1..63e276b 100644
--- a/tools/incident_report/printer.h
+++ b/tools/incident_report/printer.h
@@ -22,7 +22,7 @@
 class Out
 {
 public:
-    Out(int fd);
+    explicit Out(int fd);
     ~Out();
 
     void printf(const char* format, ...);
diff --git a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java
index 1d4c435..d368136 100644
--- a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java
+++ b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java
@@ -28,6 +28,7 @@
 
 import java.io.IOException;
 import java.io.PrintStream;
+import java.net.URLEncoder;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
@@ -38,7 +39,9 @@
 import javax.annotation.processing.SupportedAnnotationTypes;
 import javax.lang.model.SourceVersion;
 import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
 import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 
 /**
@@ -108,10 +111,25 @@
                 "startline",
                 "startcol",
                 "endline",
-                "endcol"
+                "endcol",
+                "properties"
         );
     }
 
+    private String encodeAnnotationProperties(AnnotationMirror annotation) {
+        StringBuilder sb = new StringBuilder();
+        for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e
+                : annotation.getElementValues().entrySet()) {
+            if (sb.length() > 0) {
+                sb.append("&");
+            }
+            sb.append(e.getKey().getSimpleName())
+                    .append("=")
+                    .append(URLEncoder.encode(e.getValue().toString()));
+        }
+        return sb.toString();
+    }
+
     /**
      * Maps an annotated element to the source position of the @UnsupportedAppUsage annotation
      * attached to it. It returns CSV in the format:
@@ -137,7 +155,8 @@
                 lines.getLineNumber(pair.fst.pos().getStartPosition()),
                 lines.getColumnNumber(pair.fst.pos().getStartPosition()),
                 lines.getLineNumber(pair.fst.pos().getEndPosition(pair.snd.endPositions)),
-                lines.getColumnNumber(pair.fst.pos().getEndPosition(pair.snd.endPositions)));
+                lines.getColumnNumber(pair.fst.pos().getEndPosition(pair.snd.endPositions)),
+                encodeAnnotationProperties(unsupportedAppUsage));
     }
 
     /**
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index 703a67b..5725f0c 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -96,6 +96,7 @@
 
 cc_library_shared {
     name: "libstatslog",
+    host_supported: true,
     generated_sources: ["statslog.cpp"],
     generated_headers: ["statslog.h"],
     cflags: [
@@ -105,8 +106,19 @@
     export_generated_headers: ["statslog.h"],
     shared_libs: [
         "liblog",
-        "libutils",
         "libcutils",
     ],
     static_libs: ["libstatssocket"],
+    target: {
+        android: {
+            shared_libs: [
+                "libutils",
+            ],
+        },
+        host: {
+            static_libs: [
+                "libutils",
+            ],
+        },
+    },
 }
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 485fc46..2478b91 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -108,7 +108,9 @@
     fprintf(out, "#include <mutex>\n");
     fprintf(out, "#include <chrono>\n");
     fprintf(out, "#include <thread>\n");
+    fprintf(out, "#ifdef __ANDROID__\n");
     fprintf(out, "#include <cutils/properties.h>\n");
+    fprintf(out, "#endif\n");
     fprintf(out, "#include <stats_event_list.h>\n");
     fprintf(out, "#include <log/log.h>\n");
     fprintf(out, "#include <statslog.h>\n");
@@ -119,7 +121,11 @@
     fprintf(out, "namespace util {\n");
     fprintf(out, "// the single event tag id for all stats logs\n");
     fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
+    fprintf(out, "#ifdef __ANDROID__\n");
     fprintf(out, "const static bool kStatsdEnabled = property_get_bool(\"ro.statsd.enable\", true);\n");
+    fprintf(out, "#else\n");
+    fprintf(out, "const static bool kStatsdEnabled = false;\n");
+    fprintf(out, "#endif\n");
 
     std::set<string> kTruncatingAtomNames = {"mobile_radio_power_state_changed",
                                              "audio_state_changed",