Merge "Support whitelist entries from class2greylist"
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index a787736..9ca0745 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -12204,11 +12204,11 @@
 HPLorg/json/JSONStringer;->value(Z)Lorg/json/JSONStringer;
 HPLorg/json/JSONTokener;->syntaxError(Ljava/lang/String;)Lorg/json/JSONException;
 HPLorg/json/JSONTokener;->toString()Ljava/lang/String;
-HPLorg/kxml2/io/KXmlSerializer;->getDepth()I
-HPLorg/kxml2/io/KXmlSerializer;->getNamespace()Ljava/lang/String;
-HPLorg/kxml2/io/KXmlSerializer;->getPrefix(Ljava/lang/String;ZZ)Ljava/lang/String;
-HPLorg/kxml2/io/KXmlSerializer;->setPrefix(Ljava/lang/String;Ljava/lang/String;)V
-HPLorg/kxml2/io/KXmlSerializer;->text(Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
+HPLcom/android/org/kxml2/io/KXmlSerializer;->getDepth()I
+HPLcom/android/org/kxml2/io/KXmlSerializer;->getNamespace()Ljava/lang/String;
+HPLcom/android/org/kxml2/io/KXmlSerializer;->getPrefix(Ljava/lang/String;ZZ)Ljava/lang/String;
+HPLcom/android/org/kxml2/io/KXmlSerializer;->setPrefix(Ljava/lang/String;Ljava/lang/String;)V
+HPLcom/android/org/kxml2/io/KXmlSerializer;->text(Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
 HPLorg/w3c/dom/NamedNodeMap;->getLength()I
 HPLorg/w3c/dom/NamedNodeMap;->getNamedItem(Ljava/lang/String;)Lorg/w3c/dom/Node;
 HPLorg/w3c/dom/NamedNodeMap;->getNamedItemNS(Ljava/lang/String;Ljava/lang/String;)Lorg/w3c/dom/Node;
@@ -51896,7 +51896,7 @@
 HSPLorg/apache/harmony/xml/dom/TextImpl;->getNodeType()S
 HSPLorg/apache/harmony/xml/parsers/DocumentBuilderFactoryImpl;->newDocumentBuilder()Ljavax/xml/parsers/DocumentBuilder;
 HSPLorg/apache/harmony/xml/parsers/DocumentBuilderImpl;->appendText(Lorg/apache/harmony/xml/dom/DocumentImpl;Lorg/w3c/dom/Node;ILjava/lang/String;)V
-HSPLorg/apache/harmony/xml/parsers/DocumentBuilderImpl;->parse(Lorg/kxml2/io/KXmlParser;Lorg/apache/harmony/xml/dom/DocumentImpl;Lorg/w3c/dom/Node;I)V
+HSPLorg/apache/harmony/xml/parsers/DocumentBuilderImpl;->parse(Lcom/android/org/kxml2/io/KXmlParser;Lorg/apache/harmony/xml/dom/DocumentImpl;Lorg/w3c/dom/Node;I)V
 HSPLorg/apache/harmony/xml/parsers/DocumentBuilderImpl;->parse(Lorg/xml/sax/InputSource;)Lorg/w3c/dom/Document;
 HSPLorg/apache/harmony/xml/parsers/SAXParserFactoryImpl;->getFeature(Ljava/lang/String;)Z
 HSPLorg/apache/harmony/xml/parsers/SAXParserFactoryImpl;->isValidating()Z
@@ -52176,64 +52176,64 @@
 HSPLorg/json/JSONTokener;->readLiteral()Ljava/lang/Object;
 HSPLorg/json/JSONTokener;->readObject()Lorg/json/JSONObject;
 HSPLorg/json/JSONTokener;->skipToEndOfLine()V
-HSPLorg/kxml2/io/KXmlParser$ValueContext;-><init>(Ljava/lang/String;I)V
-HSPLorg/kxml2/io/KXmlParser;-><init>()V
-HSPLorg/kxml2/io/KXmlParser;->adjustNsp()Z
-HSPLorg/kxml2/io/KXmlParser;->close()V
-HSPLorg/kxml2/io/KXmlParser;->fillBuffer(I)Z
-HSPLorg/kxml2/io/KXmlParser;->getAttributeCount()I
-HSPLorg/kxml2/io/KXmlParser;->getAttributeName(I)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getAttributeNamespace(I)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getAttributePrefix(I)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getAttributeType(I)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getAttributeValue(I)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getAttributeValue(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getColumnNumber()I
-HSPLorg/kxml2/io/KXmlParser;->getDepth()I
-HSPLorg/kxml2/io/KXmlParser;->getEventType()I
-HSPLorg/kxml2/io/KXmlParser;->getFeature(Ljava/lang/String;)Z
-HSPLorg/kxml2/io/KXmlParser;->getLineNumber()I
-HSPLorg/kxml2/io/KXmlParser;->getName()Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getNamespace()Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getNamespace(Ljava/lang/String;)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getNamespaceCount(I)I
-HSPLorg/kxml2/io/KXmlParser;->getPositionDescription()Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getPrefix()Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getText()Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getTextCharacters([I)[C
-HSPLorg/kxml2/io/KXmlParser;->next()I
-HSPLorg/kxml2/io/KXmlParser;->next(Z)I
-HSPLorg/kxml2/io/KXmlParser;->nextTag()I
-HSPLorg/kxml2/io/KXmlParser;->nextText()Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->nextToken()I
-HSPLorg/kxml2/io/KXmlParser;->parseStartTag(ZZ)V
-HSPLorg/kxml2/io/KXmlParser;->peekType(Z)I
-HSPLorg/kxml2/io/KXmlParser;->read(C)V
-HSPLorg/kxml2/io/KXmlParser;->read([C)V
-HSPLorg/kxml2/io/KXmlParser;->readComment(Z)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->readEndTag()V
-HSPLorg/kxml2/io/KXmlParser;->readEntity(Ljava/lang/StringBuilder;ZZLorg/kxml2/io/KXmlParser$ValueContext;)V
-HSPLorg/kxml2/io/KXmlParser;->readName()Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->readUntil([CZ)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->readValue(CZZLorg/kxml2/io/KXmlParser$ValueContext;)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->readXmlDeclaration()V
-HSPLorg/kxml2/io/KXmlParser;->require(ILjava/lang/String;Ljava/lang/String;)V
-HSPLorg/kxml2/io/KXmlParser;->setFeature(Ljava/lang/String;Z)V
-HSPLorg/kxml2/io/KXmlParser;->setInput(Ljava/io/InputStream;Ljava/lang/String;)V
-HSPLorg/kxml2/io/KXmlParser;->setInput(Ljava/io/Reader;)V
-HSPLorg/kxml2/io/KXmlSerializer;-><init>()V
-HSPLorg/kxml2/io/KXmlSerializer;->append(Ljava/lang/String;II)V
-HSPLorg/kxml2/io/KXmlSerializer;->attribute(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
-HSPLorg/kxml2/io/KXmlSerializer;->check(Z)V
-HSPLorg/kxml2/io/KXmlSerializer;->endDocument()V
-HSPLorg/kxml2/io/KXmlSerializer;->endTag(Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
-HSPLorg/kxml2/io/KXmlSerializer;->flush()V
-HSPLorg/kxml2/io/KXmlSerializer;->setFeature(Ljava/lang/String;Z)V
-HSPLorg/kxml2/io/KXmlSerializer;->setOutput(Ljava/io/OutputStream;Ljava/lang/String;)V
-HSPLorg/kxml2/io/KXmlSerializer;->setOutput(Ljava/io/Writer;)V
-HSPLorg/kxml2/io/KXmlSerializer;->startDocument(Ljava/lang/String;Ljava/lang/Boolean;)V
-HSPLorg/kxml2/io/KXmlSerializer;->startTag(Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
-HSPLorg/kxml2/io/KXmlSerializer;->writeEscaped(Ljava/lang/String;I)V
+HSPLcom/android/org/kxml2/io/KXmlParser$ValueContext;-><init>(Ljava/lang/String;I)V
+HSPLcom/android/org/kxml2/io/KXmlParser;-><init>()V
+HSPLcom/android/org/kxml2/io/KXmlParser;->adjustNsp()Z
+HSPLcom/android/org/kxml2/io/KXmlParser;->close()V
+HSPLcom/android/org/kxml2/io/KXmlParser;->fillBuffer(I)Z
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeCount()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeName(I)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeNamespace(I)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributePrefix(I)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeType(I)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeValue(I)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeValue(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getColumnNumber()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getDepth()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getEventType()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getFeature(Ljava/lang/String;)Z
+HSPLcom/android/org/kxml2/io/KXmlParser;->getLineNumber()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getName()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getNamespace()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getNamespace(Ljava/lang/String;)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getNamespaceCount(I)I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getPositionDescription()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getPrefix()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getText()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getTextCharacters([I)[C
+HSPLcom/android/org/kxml2/io/KXmlParser;->next()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->next(Z)I
+HSPLcom/android/org/kxml2/io/KXmlParser;->nextTag()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->nextText()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->nextToken()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->parseStartTag(ZZ)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->peekType(Z)I
+HSPLcom/android/org/kxml2/io/KXmlParser;->read(C)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->read([C)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->readComment(Z)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->readEndTag()V
+HSPLcom/android/org/kxml2/io/KXmlParser;->readEntity(Ljava/lang/StringBuilder;ZZLcom/android/org/kxml2/io/KXmlParser$ValueContext;)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->readName()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->readUntil([CZ)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->readValue(CZZLcom/android/org/kxml2/io/KXmlParser$ValueContext;)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->readXmlDeclaration()V
+HSPLcom/android/org/kxml2/io/KXmlParser;->require(ILjava/lang/String;Ljava/lang/String;)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->setFeature(Ljava/lang/String;Z)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->setInput(Ljava/io/InputStream;Ljava/lang/String;)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->setInput(Ljava/io/Reader;)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;-><init>()V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->append(Ljava/lang/String;II)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->attribute(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->check(Z)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->endDocument()V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->endTag(Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->flush()V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->setFeature(Ljava/lang/String;Z)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->setOutput(Ljava/io/OutputStream;Ljava/lang/String;)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->setOutput(Ljava/io/Writer;)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->startDocument(Ljava/lang/String;Ljava/lang/Boolean;)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->startTag(Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->writeEscaped(Ljava/lang/String;I)V
 HSPLorg/w3c/dom/Attr;->getName()Ljava/lang/String;
 HSPLorg/w3c/dom/Attr;->getOwnerElement()Lorg/w3c/dom/Element;
 HSPLorg/w3c/dom/Attr;->getSchemaTypeInfo()Lorg/w3c/dom/TypeInfo;
@@ -63397,9 +63397,9 @@
 Lorg/json/JSONStringer$Scope;
 Lorg/json/JSONStringer;
 Lorg/json/JSONTokener;
-Lorg/kxml2/io/KXmlParser$ValueContext;
-Lorg/kxml2/io/KXmlParser;
-Lorg/kxml2/io/KXmlSerializer;
+Lcom/android/org/kxml2/io/KXmlParser$ValueContext;
+Lcom/android/org/kxml2/io/KXmlParser;
+Lcom/android/org/kxml2/io/KXmlSerializer;
 Lorg/w3c/dom/CharacterData;
 Lorg/w3c/dom/DOMImplementation;
 Lorg/w3c/dom/Document;
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 9460c80..bdaaba4 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1659,350 +1659,8 @@
 Landroid/system/OsConstants;->XATTR_REPLACE:I
 Landroid/system/OsConstants;->_LINUX_CAPABILITY_VERSION_3:I
 Landroid/system/StructTimeval;->fromMillis(J)Landroid/system/StructTimeval;
-Landroid/telephony/CarrierConfigManager;->KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY:Ljava/lang/String;
-Landroid/telephony/CarrierConfigManager;->KEY_DISABLE_VOICE_BARRING_NOTIFICATION_BOOL:Ljava/lang/String;
 Landroid/telephony/CarrierMessagingServiceManager;-><init>()V
-Landroid/telephony/cdma/CdmaCellLocation;->equalsHandlesNulls(Ljava/lang/Object;Ljava/lang/Object;)Z
-Landroid/telephony/cdma/CdmaCellLocation;->mBaseStationId:I
-Landroid/telephony/cdma/CdmaCellLocation;->mBaseStationLatitude:I
-Landroid/telephony/cdma/CdmaCellLocation;->mBaseStationLongitude:I
-Landroid/telephony/cdma/CdmaCellLocation;->mNetworkId:I
-Landroid/telephony/cdma/CdmaCellLocation;->mSystemId:I
-Landroid/telephony/CellBroadcastMessage;-><init>(Landroid/telephony/SmsCbMessage;)V
-Landroid/telephony/CellBroadcastMessage;->createFromCursor(Landroid/database/Cursor;)Landroid/telephony/CellBroadcastMessage;
-Landroid/telephony/CellBroadcastMessage;->getContentValues()Landroid/content/ContentValues;
-Landroid/telephony/CellBroadcastMessage;->getDeliveryTime()J
-Landroid/telephony/CellBroadcastMessage;->getEtwsWarningInfo()Landroid/telephony/SmsCbEtwsInfo;
-Landroid/telephony/CellBroadcastMessage;->getLanguageCode()Ljava/lang/String;
-Landroid/telephony/CellBroadcastMessage;->getMessageBody()Ljava/lang/String;
-Landroid/telephony/CellBroadcastMessage;->getSerialNumber()I
-Landroid/telephony/CellBroadcastMessage;->getServiceCategory()I
-Landroid/telephony/CellBroadcastMessage;->getSpokenDateString(Landroid/content/Context;)Ljava/lang/String;
-Landroid/telephony/CellBroadcastMessage;->isCmasMessage()Z
-Landroid/telephony/CellBroadcastMessage;->isEmergencyAlertMessage()Z
-Landroid/telephony/CellBroadcastMessage;->isEtwsMessage()Z
-Landroid/telephony/CellBroadcastMessage;->isRead()Z
-Landroid/telephony/CellIdentityCdma;-><init>(IIIII)V
-Landroid/telephony/CellIdentityGsm;-><init>()V
-Landroid/telephony/CellIdentityGsm;->mArfcn:I
-Landroid/telephony/CellIdentityGsm;->mBsic:I
-Landroid/telephony/CellIdentityLte;-><init>()V
-Landroid/telephony/CellIdentityLte;-><init>(IIIII)V
-Landroid/telephony/CellIdentityLte;->mEarfcn:I
-Landroid/telephony/CellIdentityWcdma;->mUarfcn:I
-Landroid/telephony/CellInfo;->getTimeStampType()I
-Landroid/telephony/CellInfo;->timeStampTypeToString(I)Ljava/lang/String;
-Landroid/telephony/CellInfo;->TIMESTAMP_TYPE_ANTENNA:I
-Landroid/telephony/CellInfo;->TIMESTAMP_TYPE_JAVA_RIL:I
-Landroid/telephony/CellInfo;->TIMESTAMP_TYPE_MODEM:I
-Landroid/telephony/CellInfo;->TIMESTAMP_TYPE_OEM_RIL:I
-Landroid/telephony/CellInfo;->TIMESTAMP_TYPE_UNKNOWN:I
-Landroid/telephony/CellInfoCdma;-><init>()V
-Landroid/telephony/CellInfoCdma;-><init>(Landroid/telephony/CellInfoCdma;)V
-Landroid/telephony/CellInfoCdma;->setCellIdentity(Landroid/telephony/CellIdentityCdma;)V
-Landroid/telephony/CellInfoGsm;-><init>()V
-Landroid/telephony/CellInfoLte;-><init>()V
-Landroid/telephony/CellInfoLte;->setCellIdentity(Landroid/telephony/CellIdentityLte;)V
-Landroid/telephony/CellInfoLte;->setCellSignalStrength(Landroid/telephony/CellSignalStrengthLte;)V
-Landroid/telephony/CellLocation;->fillInNotifierBundle(Landroid/os/Bundle;)V
-Landroid/telephony/CellLocation;->isEmpty()Z
-Landroid/telephony/CellLocation;->newFromBundle(Landroid/os/Bundle;)Landroid/telephony/CellLocation;
-Landroid/telephony/CellSignalStrengthGsm;-><init>()V
-Landroid/telephony/CellSignalStrengthGsm;->mBitErrorRate:I
-Landroid/telephony/CellSignalStrengthGsm;->mSignalStrength:I
-Landroid/telephony/CellSignalStrengthGsm;->mTimingAdvance:I
-Landroid/telephony/CellSignalStrengthLte;-><init>()V
-Landroid/telephony/CellSignalStrengthLte;->mCqi:I
-Landroid/telephony/CellSignalStrengthLte;->mRsrp:I
-Landroid/telephony/CellSignalStrengthLte;->mRsrq:I
-Landroid/telephony/CellSignalStrengthLte;->mRssnr:I
-Landroid/telephony/CellSignalStrengthLte;->mSignalStrength:I
-Landroid/telephony/CellSignalStrengthLte;->mTimingAdvance:I
-Landroid/telephony/CellSignalStrengthWcdma;->mBitErrorRate:I
-Landroid/telephony/CellSignalStrengthWcdma;->mSignalStrength:I
-Landroid/telephony/DisconnectCause;->toString(I)Ljava/lang/String;
-Landroid/telephony/euicc/EuiccInfo;->osVersion:Ljava/lang/String;
-Landroid/telephony/gsm/GsmCellLocation;->setPsc(I)V
-Landroid/telephony/ims/ImsSsInfo;-><init>()V
-Landroid/telephony/NeighboringCellInfo;->mCid:I
-Landroid/telephony/NeighboringCellInfo;->mLac:I
-Landroid/telephony/NeighboringCellInfo;->mNetworkType:I
-Landroid/telephony/NeighboringCellInfo;->mPsc:I
-Landroid/telephony/NeighboringCellInfo;->mRssi:I
-Landroid/telephony/PhoneNumberFormattingTextWatcher;->mFormatter:Lcom/android/i18n/phonenumbers/AsYouTypeFormatter;
-Landroid/telephony/PhoneNumberUtils;->cdmaCheckAndProcessPlusCode(Ljava/lang/String;)Ljava/lang/String;
-Landroid/telephony/PhoneNumberUtils;->compare(Ljava/lang/String;Ljava/lang/String;Z)Z
-Landroid/telephony/PhoneNumberUtils;->compareLoosely(Ljava/lang/String;Ljava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->compareStrictly(Ljava/lang/String;Ljava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->compareStrictly(Ljava/lang/String;Ljava/lang/String;Z)Z
-Landroid/telephony/PhoneNumberUtils;->convertPreDial(Ljava/lang/String;)Ljava/lang/String;
-Landroid/telephony/PhoneNumberUtils;->extractNetworkPortionAlt(Ljava/lang/String;)Ljava/lang/String;
-Landroid/telephony/PhoneNumberUtils;->getUsernameFromUriNumber(Ljava/lang/String;)Ljava/lang/String;
-Landroid/telephony/PhoneNumberUtils;->isEmergencyNumber(Ljava/lang/String;Ljava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isLocalEmergencyNumber(Landroid/content/Context;ILjava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isNanp(Ljava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isPotentialLocalEmergencyNumber(Landroid/content/Context;Ljava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isUriNumber(Ljava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isVoiceMailNumber(Landroid/content/Context;ILjava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->MIN_MATCH:I
-Landroid/telephony/PhoneNumberUtils;->ttsSpanAsPhoneNumber(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
-Landroid/telephony/PhoneStateListener;-><init>(Landroid/os/Looper;)V
-Landroid/telephony/PhoneStateListener;->callback:Lcom/android/internal/telephony/IPhoneStateListener;
-Landroid/telephony/PhoneStateListener;->LISTEN_PRECISE_CALL_STATE:I
-Landroid/telephony/PhoneStateListener;->mSubId:Ljava/lang/Integer;
-Landroid/telephony/PhoneStateListener;->onDataConnectionRealTimeInfoChanged(Landroid/telephony/DataConnectionRealTimeInfo;)V
-Landroid/telephony/PhoneStateListener;->onOemHookRawEvent([B)V
-Landroid/telephony/PhoneStateListener;->onOtaspChanged(I)V
-Landroid/telephony/PhoneStateListener;->onPreciseCallStateChanged(Landroid/telephony/PreciseCallState;)V
-Landroid/telephony/PhoneStateListener;->onPreciseDataConnectionStateChanged(Landroid/telephony/PreciseDataConnectionState;)V
-Landroid/telephony/PhoneStateListener;->onVoLteServiceStateChanged(Landroid/telephony/VoLteServiceState;)V
-Landroid/telephony/PreciseCallState;-><init>(IIIII)V
-Landroid/telephony/PreciseCallState;->getDisconnectCause()I
-Landroid/telephony/PreciseCallState;->getPreciseDisconnectCause()I
-Landroid/telephony/PreciseCallState;->getRingingCallState()I
-Landroid/telephony/PreciseDataConnectionState;-><init>(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/net/LinkProperties;Ljava/lang/String;)V
-Landroid/telephony/PreciseDataConnectionState;->getDataConnectionAPN()Ljava/lang/String;
-Landroid/telephony/PreciseDataConnectionState;->getDataConnectionAPNType()Ljava/lang/String;
-Landroid/telephony/PreciseDataConnectionState;->getDataConnectionChangeReason()Ljava/lang/String;
-Landroid/telephony/PreciseDataConnectionState;->getDataConnectionFailCause()Ljava/lang/String;
-Landroid/telephony/PreciseDataConnectionState;->getDataConnectionLinkProperties()Landroid/net/LinkProperties;
-Landroid/telephony/PreciseDataConnectionState;->getDataConnectionNetworkType()I
-Landroid/telephony/PreciseDataConnectionState;->getDataConnectionState()I
-Landroid/telephony/RadioAccessFamily;->getNetworkTypeFromRaf(I)I
-Landroid/telephony/RadioAccessFamily;->getPhoneId()I
-Landroid/telephony/RadioAccessFamily;->getRadioAccessFamily()I
-Landroid/telephony/Rlog;->d(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
-Landroid/telephony/Rlog;->i(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
-Landroid/telephony/Rlog;->v(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/telephony/Rlog;->w(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/telephony/Rlog;->w(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
-Landroid/telephony/ServiceState;->bearerBitmapHasCdma(I)Z
-Landroid/telephony/ServiceState;->equalsHandlesNulls(Ljava/lang/Object;Ljava/lang/Object;)Z
-Landroid/telephony/ServiceState;->fillInNotifierBundle(Landroid/os/Bundle;)V
-Landroid/telephony/ServiceState;->getCdmaDefaultRoamingIndicator()I
-Landroid/telephony/ServiceState;->getCdmaEriIconIndex()I
-Landroid/telephony/ServiceState;->getCdmaEriIconMode()I
-Landroid/telephony/ServiceState;->getCdmaRoamingIndicator()I
-Landroid/telephony/ServiceState;->getCssIndicator()I
-Landroid/telephony/ServiceState;->getDataNetworkType()I
-Landroid/telephony/ServiceState;->getDataOperatorAlphaShort()Ljava/lang/String;
-Landroid/telephony/ServiceState;->getDataOperatorNumeric()Ljava/lang/String;
-Landroid/telephony/ServiceState;->getDataRoamingType()I
-Landroid/telephony/ServiceState;->getRadioTechnology()I
-Landroid/telephony/ServiceState;->getRilVoiceRadioTechnology()I
-Landroid/telephony/ServiceState;->getVoiceOperatorAlphaLong()Ljava/lang/String;
-Landroid/telephony/ServiceState;->getVoiceOperatorAlphaShort()Ljava/lang/String;
-Landroid/telephony/ServiceState;->getVoiceOperatorNumeric()Ljava/lang/String;
-Landroid/telephony/ServiceState;->getVoiceRoaming()Z
-Landroid/telephony/ServiceState;->getVoiceRoamingType()I
-Landroid/telephony/ServiceState;->mCdmaDefaultRoamingIndicator:I
-Landroid/telephony/ServiceState;->mCdmaEriIconIndex:I
-Landroid/telephony/ServiceState;->mCdmaEriIconMode:I
-Landroid/telephony/ServiceState;->mCdmaRoamingIndicator:I
-Landroid/telephony/ServiceState;->mCssIndicator:Z
-Landroid/telephony/ServiceState;->mIsManualNetworkSelection:Z
-Landroid/telephony/ServiceState;->mIsUsingCarrierAggregation:Z
-Landroid/telephony/ServiceState;->mNetworkId:I
-Landroid/telephony/ServiceState;->mSystemId:I
-Landroid/telephony/ServiceState;->newFromBundle(Landroid/os/Bundle;)Landroid/telephony/ServiceState;
-Landroid/telephony/ServiceState;->RIL_RADIO_TECHNOLOGY_IWLAN:I
-Landroid/telephony/ServiceState;->setCdmaDefaultRoamingIndicator(I)V
-Landroid/telephony/ServiceState;->setCdmaEriIconIndex(I)V
-Landroid/telephony/ServiceState;->setCdmaEriIconMode(I)V
-Landroid/telephony/ServiceState;->setCdmaRoamingIndicator(I)V
-Landroid/telephony/ServiceState;->setCssIndicator(I)V
-Landroid/telephony/ServiceState;->setDataRegState(I)V
-Landroid/telephony/ServiceState;->setDataRoaming(Z)V
-Landroid/telephony/ServiceState;->setDataRoamingFromRegistration(Z)V
-Landroid/telephony/ServiceState;->setDataRoamingType(I)V
-Landroid/telephony/ServiceState;->setEmergencyOnly(Z)V
-Landroid/telephony/ServiceState;->setFromNotifierBundle(Landroid/os/Bundle;)V
-Landroid/telephony/ServiceState;->setOperatorAlphaLong(Ljava/lang/String;)V
-Landroid/telephony/ServiceState;->setVoiceRegState(I)V
-Landroid/telephony/ServiceState;->setVoiceRoaming(Z)V
-Landroid/telephony/ServiceState;->setVoiceRoamingType(I)V
-Landroid/telephony/SignalStrength;-><init>()V
-Landroid/telephony/SignalStrength;-><init>(Landroid/os/Parcel;)V
-Landroid/telephony/SignalStrength;-><init>(Landroid/telephony/SignalStrength;)V
-Landroid/telephony/SignalStrength;-><init>(Z)V
-Landroid/telephony/SignalStrength;->copyFrom(Landroid/telephony/SignalStrength;)V
-Landroid/telephony/SignalStrength;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/telephony/SignalStrength;->fillInNotifierBundle(Landroid/os/Bundle;)V
-Landroid/telephony/SignalStrength;->getAsuLevel()I
-Landroid/telephony/SignalStrength;->getCdmaAsuLevel()I
-Landroid/telephony/SignalStrength;->getCdmaLevel()I
-Landroid/telephony/SignalStrength;->getDbm()I
-Landroid/telephony/SignalStrength;->getEvdoAsuLevel()I
-Landroid/telephony/SignalStrength;->getEvdoLevel()I
-Landroid/telephony/SignalStrength;->getGsmAsuLevel()I
-Landroid/telephony/SignalStrength;->getGsmDbm()I
-Landroid/telephony/SignalStrength;->getGsmLevel()I
-Landroid/telephony/SignalStrength;->getLteAsuLevel()I
-Landroid/telephony/SignalStrength;->getLteCqi()I
-Landroid/telephony/SignalStrength;->getLteDbm()I
-Landroid/telephony/SignalStrength;->getLteLevel()I
-Landroid/telephony/SignalStrength;->getLteRsrp()I
-Landroid/telephony/SignalStrength;->getLteRsrq()I
-Landroid/telephony/SignalStrength;->getLteRssnr()I
-Landroid/telephony/SignalStrength;->getLteSignalStrength()I
-Landroid/telephony/SignalStrength;->getTdScdmaAsuLevel()I
-Landroid/telephony/SignalStrength;->getTdScdmaDbm()I
-Landroid/telephony/SignalStrength;->getTdScdmaLevel()I
-Landroid/telephony/SignalStrength;->mCdmaDbm:I
-Landroid/telephony/SignalStrength;->mCdmaEcio:I
-Landroid/telephony/SignalStrength;->mEvdoDbm:I
-Landroid/telephony/SignalStrength;->mEvdoEcio:I
-Landroid/telephony/SignalStrength;->mEvdoSnr:I
-Landroid/telephony/SignalStrength;->mGsmBitErrorRate:I
-Landroid/telephony/SignalStrength;->mGsmSignalStrength:I
-Landroid/telephony/SignalStrength;->mLteCqi:I
-Landroid/telephony/SignalStrength;->mLteRsrp:I
-Landroid/telephony/SignalStrength;->mLteRsrpBoost:I
-Landroid/telephony/SignalStrength;->mLteRsrq:I
-Landroid/telephony/SignalStrength;->mLteRssnr:I
-Landroid/telephony/SignalStrength;->mLteSignalStrength:I
-Landroid/telephony/SignalStrength;->mTdScdmaRscp:I
-Landroid/telephony/SignalStrength;->mWcdmaRscp:I
-Landroid/telephony/SignalStrength;->newFromBundle(Landroid/os/Bundle;)Landroid/telephony/SignalStrength;
-Landroid/telephony/SignalStrength;->NUM_SIGNAL_STRENGTH_BINS:I
-Landroid/telephony/SignalStrength;->setFromNotifierBundle(Landroid/os/Bundle;)V
-Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_GOOD:I
-Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_GREAT:I
-Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_MODERATE:I
-Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_NONE_OR_UNKNOWN:I
-Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_POOR:I
-Landroid/telephony/SignalStrength;->validateInput()V
-Landroid/telephony/SmsManager;->copyMessageToIcc([B[BI)Z
-Landroid/telephony/SmsManager;->deleteMessageFromIcc(I)Z
-Landroid/telephony/SmsManager;->disableCellBroadcastRange(III)Z
-Landroid/telephony/SmsManager;->enableCellBroadcastRange(III)Z
-Landroid/telephony/SmsManager;->getAllMessagesFromIcc()Ljava/util/ArrayList;
-Landroid/telephony/SmsManager;->isSMSPromptEnabled()Z
-Landroid/telephony/SmsManager;->mSubId:I
-Landroid/telephony/SmsManager;->sendMultipartTextMessage(Ljava/lang/String;Ljava/lang/String;Ljava/util/ArrayList;Ljava/util/ArrayList;Ljava/util/ArrayList;IZI)V
-Landroid/telephony/SmsManager;->sendTextMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;IZI)V
-Landroid/telephony/SmsManager;->sendTextMessageWithoutPersisting(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;IZI)V
-Landroid/telephony/SmsManager;->updateMessageOnIcc(II[B)Z
-Landroid/telephony/SmsMessage;->fragmentText(Ljava/lang/String;)Ljava/util/ArrayList;
-Landroid/telephony/SmsMessage;->getSubId()I
-Landroid/telephony/SmsMessage;->mSubId:I
-Landroid/telephony/SmsMessage;->mWrappedSmsMessage:Lcom/android/internal/telephony/SmsMessageBase;
-Landroid/telephony/SmsMessage;->setSubId(I)V
-Landroid/telephony/SmsMessage;->useCdmaFormatForMoSms()Z
-Landroid/telephony/SmsMessage;->useCdmaFormatForMoSms(I)Z
-Landroid/telephony/SubscriptionInfo;->getNameSource()I
-Landroid/telephony/SubscriptionManager;-><init>(Landroid/content/Context;)V
-Landroid/telephony/SubscriptionManager;->CONTENT_URI:Landroid/net/Uri;
-Landroid/telephony/SubscriptionManager;->DEFAULT_SUBSCRIPTION_ID:I
-Landroid/telephony/SubscriptionManager;->getActiveSubscriptionIdList()[I
-Landroid/telephony/SubscriptionManager;->getAllSubscriptionInfoCount()I
-Landroid/telephony/SubscriptionManager;->getAllSubscriptionInfoList()Ljava/util/List;
-Landroid/telephony/SubscriptionManager;->getDefaultDataPhoneId()I
-Landroid/telephony/SubscriptionManager;->getDefaultDataSubscriptionInfo()Landroid/telephony/SubscriptionInfo;
-Landroid/telephony/SubscriptionManager;->getDefaultSmsPhoneId()I
-Landroid/telephony/SubscriptionManager;->getDefaultVoiceSubscriptionInfo()Landroid/telephony/SubscriptionInfo;
-Landroid/telephony/SubscriptionManager;->getPhoneId(I)I
-Landroid/telephony/SubscriptionManager;->getSlotIndex(I)I
-Landroid/telephony/SubscriptionManager;->getSubId(I)[I
-Landroid/telephony/SubscriptionManager;->NAME_SOURCE_USER_INPUT:I
-Landroid/telephony/SubscriptionManager;->setDataRoaming(II)I
-Landroid/telephony/SubscriptionManager;->setDefaultDataSubId(I)V
-Landroid/telephony/SubscriptionManager;->setDefaultSmsSubId(I)V
-Landroid/telephony/SubscriptionManager;->setDisplayNumber(Ljava/lang/String;I)I
-Landroid/telephony/TelephonyManager$MultiSimVariants;->TSTS:Landroid/telephony/TelephonyManager$MultiSimVariants;
-Landroid/telephony/TelephonyManager$MultiSimVariants;->UNKNOWN:Landroid/telephony/TelephonyManager$MultiSimVariants;
 Landroid/telephony/TelephonyManager$MultiSimVariants;->values()[Landroid/telephony/TelephonyManager$MultiSimVariants;
-Landroid/telephony/TelephonyManager;-><init>()V
-Landroid/telephony/TelephonyManager;-><init>(Landroid/content/Context;)V
-Landroid/telephony/TelephonyManager;-><init>(Landroid/content/Context;I)V
-Landroid/telephony/TelephonyManager;->ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED:Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->from(Landroid/content/Context;)Landroid/telephony/TelephonyManager;
-Landroid/telephony/TelephonyManager;->getCallState(I)I
-Landroid/telephony/TelephonyManager;->getCdmaEriIconIndex(I)I
-Landroid/telephony/TelephonyManager;->getCdmaEriIconMode(I)I
-Landroid/telephony/TelephonyManager;->getCdmaEriText(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getCompleteVoiceMailNumber()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getCompleteVoiceMailNumber(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getDataNetworkType(I)I
-Landroid/telephony/TelephonyManager;->getDefault()Landroid/telephony/TelephonyManager;
-Landroid/telephony/TelephonyManager;->getDeviceSoftwareVersion(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getGroupIdLevel1(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getIccAuthentication(IIILjava/lang/String;)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getImsConfig(II)Landroid/telephony/ims/aidl/IImsConfig;
-Landroid/telephony/TelephonyManager;->getImsRegistration(II)Landroid/telephony/ims/aidl/IImsRegistration;
-Landroid/telephony/TelephonyManager;->getIsimImpi()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getIsimImpu()[Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getIsimPcscf()[Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getITelephony()Lcom/android/internal/telephony/ITelephony;
-Landroid/telephony/TelephonyManager;->getLine1AlphaTag(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getLine1Number(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getLteOnCdmaMode()I
-Landroid/telephony/TelephonyManager;->getLteOnCdmaMode(I)I
-Landroid/telephony/TelephonyManager;->getLteOnCdmaModeStatic()I
-Landroid/telephony/TelephonyManager;->getMergedSubscriberIds()[Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getMsisdn()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getMsisdn(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getMultiSimConfiguration()Landroid/telephony/TelephonyManager$MultiSimVariants;
-Landroid/telephony/TelephonyManager;->getNai(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkClass(I)I
-Landroid/telephony/TelephonyManager;->getNetworkCountryIso(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkCountryIsoForPhone(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkOperator(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkOperatorForPhone(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkOperatorName(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkType(I)I
-Landroid/telephony/TelephonyManager;->getNetworkTypeName(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getOtaSpNumberSchemaForPhone(ILjava/lang/String;)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getPhoneId(I)I
-Landroid/telephony/TelephonyManager;->getPhoneType(I)I
-Landroid/telephony/TelephonyManager;->getPhoneTypeFromProperty(I)I
-Landroid/telephony/TelephonyManager;->getProcCmdLine()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimCount()I
-Landroid/telephony/TelephonyManager;->getSimCountryIso(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimCountryIsoForPhone(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimOperator(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimOperatorName(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimOperatorNameForPhone(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimOperatorNumeric()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimOperatorNumeric(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimOperatorNumericForPhone(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimSerialNumber(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSlotIndex()I
-Landroid/telephony/TelephonyManager;->getSubId(I)I
-Landroid/telephony/TelephonyManager;->getSubIdForPhoneAccount(Landroid/telecom/PhoneAccount;)I
-Landroid/telephony/TelephonyManager;->getSubscriberId(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSubscriberInfo()Lcom/android/internal/telephony/IPhoneSubInfo;
-Landroid/telephony/TelephonyManager;->getTelephonyProperty(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getTelephonyProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getVoiceMailAlphaTag(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getVoiceMailNumber(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getVoiceMessageCount(I)I
-Landroid/telephony/TelephonyManager;->hasIccCard(I)Z
-Landroid/telephony/TelephonyManager;->isMultiSimEnabled()Z
-Landroid/telephony/TelephonyManager;->isNetworkRoaming(I)Z
-Landroid/telephony/TelephonyManager;->isVideoTelephonyAvailable()Z
-Landroid/telephony/TelephonyManager;->isVolteAvailable()Z
-Landroid/telephony/TelephonyManager;->isWifiCallingAvailable()Z
-Landroid/telephony/TelephonyManager;->mSubscriptionManager:Landroid/telephony/SubscriptionManager;
-Landroid/telephony/TelephonyManager;->NETWORK_CLASS_2_G:I
-Landroid/telephony/TelephonyManager;->NETWORK_CLASS_3_G:I
-Landroid/telephony/TelephonyManager;->NETWORK_CLASS_4_G:I
-Landroid/telephony/TelephonyManager;->NETWORK_TYPE_LTE_CA:I
-Landroid/telephony/TelephonyManager;->nvReadItem(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->setBasebandVersionForPhone(ILjava/lang/String;)V
-Landroid/telephony/TelephonyManager;->setDataNetworkTypeForPhone(II)V
-Landroid/telephony/TelephonyManager;->setImsRegistrationState(Z)V
-Landroid/telephony/TelephonyManager;->setNetworkOperatorNameForPhone(ILjava/lang/String;)V
-Landroid/telephony/TelephonyManager;->setNetworkOperatorNumericForPhone(ILjava/lang/String;)V
-Landroid/telephony/TelephonyManager;->setNetworkRoamingForPhone(IZ)V
-Landroid/telephony/TelephonyManager;->setPhoneType(II)V
-Landroid/telephony/TelephonyManager;->setRoamingOverride(Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;)Z
-Landroid/telephony/TelephonyManager;->setSimCountryIsoForPhone(ILjava/lang/String;)V
-Landroid/telephony/TelephonyManager;->setSimOperatorNameForPhone(ILjava/lang/String;)V
-Landroid/telephony/TelephonyManager;->setSimOperatorNumericForPhone(ILjava/lang/String;)V
-Landroid/telephony/TelephonyManager;->setSimStateForPhone(ILjava/lang/String;)V
-Landroid/telephony/TelephonyManager;->setTelephonyProperty(ILjava/lang/String;Ljava/lang/String;)V
-Landroid/telephony/VoLteServiceState;-><init>(I)V
 Landroid/transition/ChangeBounds;->BOTTOM_RIGHT_ONLY_PROPERTY:Landroid/util/Property;
 Landroid/transition/ChangeBounds;->POSITION_PROPERTY:Landroid/util/Property;
 Landroid/transition/Scene;->mEnterAction:Ljava/lang/Runnable;
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index 3c38da8..266e793 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -138,42 +138,10 @@
 Landroid/system/Os;->setsockoptTimeval(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V
 Landroid/system/PacketSocketAddress;-><init>(I[B)V
 Landroid/system/PacketSocketAddress;-><init>(SI)V
-Landroid/telephony/euicc/DownloadableSubscription;->encodedActivationCode:Ljava/lang/String;
-Landroid/telephony/euicc/DownloadableSubscription;->setAccessRules([Landroid/telephony/UiccAccessRule;)V
-Landroid/telephony/euicc/DownloadableSubscription;->setCarrierName(Ljava/lang/String;)V
-Landroid/telephony/ims/compat/feature/ImsFeature;->getFeatureState()I
-Landroid/telephony/ims/compat/feature/ImsFeature;->setFeatureState(I)V
 Landroid/telephony/ims/compat/feature/MMTelFeature;-><init>()V
 Landroid/telephony/ims/compat/ImsService;-><init>()V
-Landroid/telephony/ims/compat/ImsService;->mImsServiceController:Landroid/os/IBinder;
 Landroid/telephony/ims/compat/stub/ImsCallSessionImplBase;-><init>()V
-Landroid/telephony/ims/compat/stub/ImsConfigImplBase;-><init>(Landroid/content/Context;)V
-Landroid/telephony/ims/compat/stub/ImsConfigImplBase;->getIImsConfig()Lcom/android/ims/internal/IImsConfig;
 Landroid/telephony/ims/compat/stub/ImsUtListenerImplBase;-><init>()V
-Landroid/telephony/ims/ImsCallForwardInfo;-><init>()V
-Landroid/telephony/ims/ImsCallForwardInfo;->mCondition:I
-Landroid/telephony/ims/ImsCallForwardInfo;->mNumber:Ljava/lang/String;
-Landroid/telephony/ims/ImsCallForwardInfo;->mServiceClass:I
-Landroid/telephony/ims/ImsCallForwardInfo;->mStatus:I
-Landroid/telephony/ims/ImsCallForwardInfo;->mTimeSeconds:I
-Landroid/telephony/ims/ImsCallForwardInfo;->mToA:I
-Landroid/telephony/ims/ImsCallProfile;->mCallExtras:Landroid/os/Bundle;
-Landroid/telephony/ims/ImsCallProfile;->mCallType:I
-Landroid/telephony/ims/ImsCallProfile;->mMediaProfile:Landroid/telephony/ims/ImsStreamMediaProfile;
-Landroid/telephony/ims/ImsCallProfile;->mRestrictCause:I
-Landroid/telephony/ims/ImsCallProfile;->presentationToOIR(I)I
-Landroid/telephony/ims/ImsExternalCallState;-><init>(ILandroid/net/Uri;ZIIZ)V
-Landroid/telephony/ims/ImsReasonInfo;-><init>(II)V
-Landroid/telephony/ims/ImsReasonInfo;->mCode:I
-Landroid/telephony/ims/ImsReasonInfo;->mExtraCode:I
-Landroid/telephony/ims/ImsReasonInfo;->mExtraMessage:Ljava/lang/String;
-Landroid/telephony/ims/ImsSsInfo;->mIcbNum:Ljava/lang/String;
-Landroid/telephony/ims/ImsSsInfo;->mStatus:I
-Landroid/telephony/ims/ImsStreamMediaProfile;-><init>()V
-Landroid/telephony/ims/ImsStreamMediaProfile;->mAudioDirection:I
-Landroid/telephony/ims/ImsStreamMediaProfile;->mAudioQuality:I
-Landroid/telephony/ims/ImsStreamMediaProfile;->mVideoDirection:I
-Landroid/telephony/ims/ImsVideoCallProvider;->getInterface()Lcom/android/ims/internal/IImsVideoCallProvider;
 Landroid/telephony/mbms/IMbmsStreamingSessionCallback$Stub;-><init>()V
 Landroid/telephony/mbms/IStreamingServiceCallback$Stub;-><init>()V
 Landroid/telephony/mbms/vendor/IMbmsStreamingService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/telephony/mbms/vendor/IMbmsStreamingService;
@@ -181,58 +149,6 @@
 Landroid/telephony/mbms/vendor/IMbmsStreamingService;->initialize(Landroid/telephony/mbms/IMbmsStreamingSessionCallback;I)I
 Landroid/telephony/mbms/vendor/IMbmsStreamingService;->requestUpdateStreamingServices(ILjava/util/List;)I
 Landroid/telephony/mbms/vendor/IMbmsStreamingService;->startStreaming(ILjava/lang/String;Landroid/telephony/mbms/IStreamingServiceCallback;)I
-Landroid/telephony/PhoneNumberUtils;->formatNumber(Ljava/lang/String;I)Ljava/lang/String;
-Landroid/telephony/PhoneNumberUtils;->isEmergencyNumber(ILjava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isPotentialEmergencyNumber(ILjava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isPotentialLocalEmergencyNumber(Landroid/content/Context;ILjava/lang/String;)Z
-Landroid/telephony/PhoneStateListener;-><init>(Ljava/lang/Integer;)V
-Landroid/telephony/PhoneStateListener;-><init>(Ljava/lang/Integer;Landroid/os/Looper;)V
-Landroid/telephony/PreciseCallState;->getBackgroundCallState()I
-Landroid/telephony/PreciseCallState;->getForegroundCallState()I
-Landroid/telephony/RadioAccessFamily;-><init>(II)V
-Landroid/telephony/RadioAccessFamily;->getRafFromNetworkType(I)I
-Landroid/telephony/Rlog;->d(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/telephony/Rlog;->e(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/telephony/Rlog;->e(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
-Landroid/telephony/Rlog;->i(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/telephony/ServiceState;->bitmaskHasTech(II)Z
-Landroid/telephony/ServiceState;->getDataRegState()I
-Landroid/telephony/ServiceState;->getDataRoaming()Z
-Landroid/telephony/ServiceState;->getRilDataRadioTechnology()I
-Landroid/telephony/ServiceState;->getVoiceNetworkType()I
-Landroid/telephony/ServiceState;->getVoiceRegState()I
-Landroid/telephony/ServiceState;->isCdma(I)Z
-Landroid/telephony/ServiceState;->isEmergencyOnly()Z
-Landroid/telephony/ServiceState;->isGsm(I)Z
-Landroid/telephony/ServiceState;->mergeServiceStates(Landroid/telephony/ServiceState;Landroid/telephony/ServiceState;)Landroid/telephony/ServiceState;
-Landroid/telephony/ServiceState;->rilRadioTechnologyToString(I)Ljava/lang/String;
-Landroid/telephony/SubscriptionInfo;->setDisplayName(Ljava/lang/CharSequence;)V
-Landroid/telephony/SubscriptionInfo;->setIconTint(I)V
-Landroid/telephony/SubscriptionManager;->clearDefaultsForInactiveSubIds()V
-Landroid/telephony/SubscriptionManager;->getDefaultVoicePhoneId()I
-Landroid/telephony/SubscriptionManager;->getResourcesForSubId(Landroid/content/Context;I)Landroid/content/res/Resources;
-Landroid/telephony/SubscriptionManager;->isActiveSubId(I)Z
-Landroid/telephony/SubscriptionManager;->isUsableSubIdValue(I)Z
-Landroid/telephony/SubscriptionManager;->isValidPhoneId(I)Z
-Landroid/telephony/SubscriptionManager;->isValidSlotIndex(I)Z
-Landroid/telephony/SubscriptionManager;->isValidSubscriptionId(I)Z
-Landroid/telephony/SubscriptionManager;->putPhoneIdAndSubIdExtra(Landroid/content/Intent;I)V
-Landroid/telephony/SubscriptionManager;->putPhoneIdAndSubIdExtra(Landroid/content/Intent;II)V
-Landroid/telephony/SubscriptionManager;->setDisplayName(Ljava/lang/String;IJ)I
-Landroid/telephony/SubscriptionManager;->setIconTint(II)I
-Landroid/telephony/TelephonyManager$MultiSimVariants;->DSDA:Landroid/telephony/TelephonyManager$MultiSimVariants;
-Landroid/telephony/TelephonyManager$MultiSimVariants;->DSDS:Landroid/telephony/TelephonyManager$MultiSimVariants;
-Landroid/telephony/TelephonyManager;->getIntAtIndex(Landroid/content/ContentResolver;Ljava/lang/String;I)I
-Landroid/telephony/TelephonyManager;->getIsimDomain()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkTypeName()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getPreferredNetworkType(I)I
-Landroid/telephony/TelephonyManager;->getServiceStateForSubscriber(I)Landroid/telephony/ServiceState;
-Landroid/telephony/TelephonyManager;->getVoiceMessageCount()I
-Landroid/telephony/TelephonyManager;->getVoiceNetworkType(I)I
-Landroid/telephony/TelephonyManager;->isImsRegistered()Z
-Landroid/telephony/TelephonyManager;->nvResetConfig(I)Z
-Landroid/telephony/TelephonyManager;->putIntAtIndex(Landroid/content/ContentResolver;Ljava/lang/String;II)Z
-Landroid/telephony/TelephonyManager;->setPreferredNetworkType(II)Z
 Landroid/view/IAppTransitionAnimationSpecsFuture$Stub;-><init>()V
 Landroid/view/IRecentsAnimationController;->finish(Z)V
 Landroid/view/IRecentsAnimationController;->screenshotTask(I)Landroid/app/ActivityManager$TaskSnapshot;
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 19e399a..7d9af00 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -1343,9 +1343,11 @@
                 @StyleableRes int[] attrs,
                 @AttrRes int defStyleAttr,
                 @StyleRes int defStyleRes) {
+            Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "obtainStyledAttributes");
+            TypedArray array;
             synchronized (mKey) {
                 final int len = attrs.length;
-                final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
+                array = TypedArray.obtain(wrapper.getResources(), len);
 
                 // XXX note that for now we only work with compiled XML files.
                 // To support generic XML files we will need to manually parse
@@ -1356,8 +1358,9 @@
                         array.mDataAddress, array.mIndicesAddress);
                 array.mTheme = wrapper;
                 array.mXml = parser;
-                return array;
             }
+            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+            return array;
         }
 
         @NonNull
diff --git a/core/java/android/database/OWNERS b/core/java/android/database/OWNERS
index 84e81e4..7e19942 100644
--- a/core/java/android/database/OWNERS
+++ b/core/java/android/database/OWNERS
@@ -1,2 +1,3 @@
-fkupolov@google.com
-omakoto@google.com
\ No newline at end of file
+omakoto@google.com
+jsharkey@android.com
+yamasani@google.com
diff --git a/core/java/android/net/IpConfiguration.java b/core/java/android/net/IpConfiguration.java
index 7543920..3319f33 100644
--- a/core/java/android/net/IpConfiguration.java
+++ b/core/java/android/net/IpConfiguration.java
@@ -35,7 +35,7 @@
          * with staticIpConfiguration */
         @UnsupportedAppUsage
         STATIC,
-        /* Use dynamically configured IP settigns */
+        /* Use dynamically configured IP settings */
         DHCP,
         /* no IP details are assigned, this is used to indicate
          * that any existing IP settings should be retained */
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 599ccb2..34e9476 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -22,6 +22,7 @@
 import android.util.Pair;
 
 import java.io.FileDescriptor;
+import java.io.IOException;
 import java.math.BigInteger;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
@@ -131,6 +132,17 @@
     public native static boolean queryUserAccess(int uid, int netId);
 
     /**
+     * Add an entry into the ARP cache.
+     */
+    public static void addArpEntry(Inet4Address ipv4Addr, MacAddress ethAddr, String ifname,
+            FileDescriptor fd) throws IOException {
+        addArpEntry(ethAddr.toByteArray(), ipv4Addr.getAddress(), ifname, fd);
+    }
+
+    private static native void addArpEntry(byte[] ethAddr, byte[] netAddr, String ifname,
+            FileDescriptor fd) throws IOException;
+
+    /**
      * @see #intToInet4AddressHTL(int)
      * @deprecated Use either {@link #intToInet4AddressHTH(int)}
      *             or {@link #intToInet4AddressHTL(int)}
@@ -149,7 +161,7 @@
      * @param hostAddress an int coding for an IPv4 address, where higher-order int byte is
      *                    lower-order IPv4 address byte
      */
-    public static InetAddress intToInet4AddressHTL(int hostAddress) {
+    public static Inet4Address intToInet4AddressHTL(int hostAddress) {
         return intToInet4AddressHTH(Integer.reverseBytes(hostAddress));
     }
 
@@ -157,14 +169,14 @@
      * Convert a IPv4 address from an integer to an InetAddress (0x01020304 -> 1.2.3.4)
      * @param hostAddress an int coding for an IPv4 address
      */
-    public static InetAddress intToInet4AddressHTH(int hostAddress) {
+    public static Inet4Address intToInet4AddressHTH(int hostAddress) {
         byte[] addressBytes = { (byte) (0xff & (hostAddress >> 24)),
                 (byte) (0xff & (hostAddress >> 16)),
                 (byte) (0xff & (hostAddress >> 8)),
                 (byte) (0xff & hostAddress) };
 
         try {
-            return InetAddress.getByAddress(addressBytes);
+            return (Inet4Address) InetAddress.getByAddress(addressBytes);
         } catch (UnknownHostException e) {
             throw new AssertionError();
         }
@@ -397,6 +409,28 @@
     }
 
     /**
+     * Get a prefix mask as Inet4Address for a given prefix length.
+     *
+     * <p>For example 20 -> 255.255.240.0
+     */
+    public static Inet4Address getPrefixMaskAsInet4Address(int prefixLength)
+            throws IllegalArgumentException {
+        return intToInet4AddressHTH(prefixLengthToV4NetmaskIntHTH(prefixLength));
+    }
+
+    /**
+     * Get the broadcast address for a given prefix.
+     *
+     * <p>For example 192.168.0.1/24 -> 192.168.0.255
+     */
+    public static Inet4Address getBroadcastAddress(Inet4Address addr, int prefixLength)
+            throws IllegalArgumentException {
+        final int intBroadcastAddr = inet4AddressToIntHTH(addr)
+                | ~prefixLengthToV4NetmaskIntHTH(prefixLength);
+        return intToInet4AddressHTH(intBroadcastAddr);
+    }
+
+    /**
      * Check if IP address type is consistent between two InetAddress.
      * @return true if both are the same type.  False otherwise.
      */
diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS
index e4b2930..5c79d21 100644
--- a/core/java/android/widget/OWNERS
+++ b/core/java/android/widget/OWNERS
@@ -1,11 +1 @@
-per-file TextView.java = siyamed@google.com
-per-file TextView.java = nona@google.com
-per-file TextView.java = clarabayarri@google.com
-
-per-file EditText.java = siyamed@google.com
-per-file EditText.java = nona@google.com
-per-file EditText.java = clarabayarri@google.com
-
-per-file Editor.java = siyamed@google.com
-per-file Editor.java = nona@google.com
-per-file Editor.java = clarabayarri@google.com
+per-file TextView.java, EditText.java, Editor.java = siyamed@google.com, nona@google.com, clarabayarri@google.com
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index ce79049..a365a56 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -1,12 +1,6 @@
 # Camera
-per-file *Camera*,*camera* = cychen@google.com
-per-file *Camera*,*camera* = epeev@google.com
-per-file *Camera*,*camera* = etalvala@google.com
-per-file *Camera*,*camera* = shuzhenwang@google.com
-per-file *Camera*,*camera* = yinchiayeh@google.com
-per-file *Camera*,*camera* = zhijunhe@google.com
+per-file *Camera*,*camera* = cychen@google.com, epeev@google.com, etalvala@google.com
+per-file *Camera*,*camera* = shuzhenwang@google.com, yinchiayeh@google.com, zhijunhe@google.com
 
 # Connectivity
-per-file android_net_*=ek@google.com
-per-file android_net_*=lorenzo@google.com
-per-file android_net_*=satk@google.com
+per-file android_net_* = ek@google.com, lorenzo@google.com, satk@google.com
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 823f1cc..9b138eb 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -323,6 +323,55 @@
     return (jboolean) !queryUserAccess(uid, netId);
 }
 
+static bool checkLenAndCopy(JNIEnv* env, const jbyteArray& addr, int len, void* dst)
+{
+    if (env->GetArrayLength(addr) != len) {
+        return false;
+    }
+    env->GetByteArrayRegion(addr, 0, len, reinterpret_cast<jbyte*>(dst));
+    return true;
+}
+
+static void android_net_utils_addArpEntry(JNIEnv *env, jobject thiz, jbyteArray ethAddr,
+        jbyteArray ipv4Addr, jstring ifname, jobject javaFd)
+{
+    struct arpreq req = {};
+    struct sockaddr_in& netAddrStruct = *reinterpret_cast<sockaddr_in*>(&req.arp_pa);
+    struct sockaddr& ethAddrStruct = req.arp_ha;
+
+    ethAddrStruct.sa_family = ARPHRD_ETHER;
+    if (!checkLenAndCopy(env, ethAddr, ETH_ALEN, ethAddrStruct.sa_data)) {
+        jniThrowException(env, "java/io/IOException", "Invalid ethAddr length");
+        return;
+    }
+
+    netAddrStruct.sin_family = AF_INET;
+    if (!checkLenAndCopy(env, ipv4Addr, sizeof(in_addr), &netAddrStruct.sin_addr)) {
+        jniThrowException(env, "java/io/IOException", "Invalid ipv4Addr length");
+        return;
+    }
+
+    int ifLen = env->GetStringLength(ifname);
+    // IFNAMSIZ includes the terminating NULL character
+    if (ifLen >= IFNAMSIZ) {
+        jniThrowException(env, "java/io/IOException", "ifname too long");
+        return;
+    }
+    env->GetStringUTFRegion(ifname, 0, ifLen, req.arp_dev);
+
+    req.arp_flags = ATF_COM;  // Completed entry (ha valid)
+    int fd = jniGetFDFromFileDescriptor(env, javaFd);
+    if (fd < 0) {
+        jniThrowExceptionFmt(env, "java/io/IOException", "Invalid file descriptor");
+        return;
+    }
+    // See also: man 7 arp
+    if (ioctl(fd, SIOCSARP, &req)) {
+        jniThrowExceptionFmt(env, "java/io/IOException", "ioctl error: %s", strerror(errno));
+        return;
+    }
+}
+
 
 // ----------------------------------------------------------------------------
 
@@ -337,6 +386,7 @@
     { "bindSocketToNetwork", "(II)I", (void*) android_net_utils_bindSocketToNetwork },
     { "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
     { "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess },
+    { "addArpEntry", "([B[BLjava/lang/String;Ljava/io/FileDescriptor;)V", (void*) android_net_utils_addArpEntry },
     { "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter },
     { "attachRaFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachRaFilter },
     { "attachControlPacketFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachControlPacketFilter },
diff --git a/data/etc/OWNERS b/data/etc/OWNERS
index f7a3e1a..bbec474 100644
--- a/data/etc/OWNERS
+++ b/data/etc/OWNERS
@@ -1,7 +1 @@
-per-file privapp-permissions-platform.xml = bpoiesz@google.com
-per-file privapp-permissions-platform.xml = fkupolov@google.com
-per-file privapp-permissions-platform.xml = hackbod@android.com
-per-file privapp-permissions-platform.xml = jsharkey@android.com
-per-file privapp-permissions-platform.xml = svetoslavganov@google.com
-per-file privapp-permissions-platform.xml = toddke@google.com
-per-file privapp-permissions-platform.xml = yamasani@google.com
+per-file privapp-permissions-platform.xml = hackbod@android.com, jsharkey@android.com, svetoslavganov@google.com, toddke@google.com, yamasani@google.com
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index b37f2cf..f2766d6 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -39,7 +39,7 @@
     virtual void onError(const std::string& message) = 0;
 
 protected:
-    ~ErrorHandler() {}
+    virtual ~ErrorHandler() {}
 };
 
 class TreeObserver {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 689f518..e9c2649 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -59,7 +59,7 @@
     virtual void doFrame() = 0;
 
 protected:
-    ~IFrameCallback() {}
+    virtual ~IFrameCallback() {}
 };
 
 struct VsyncSource {
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 54541f0..7cf8828 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -43,27 +43,27 @@
 
 #define FIND_CLASS(var, className) \
     var = env->FindClass(className); \
-    LOG_FATAL_IF(! (var), "Unable to find class " className);
+    LOG_FATAL_IF(! (var), "Unable to find class %s", className);
 
 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
     var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
-    LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
+    LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName);
 
 #define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
     var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
-    LOG_FATAL_IF(! (var), "Unable to find method " fieldName);
+    LOG_FATAL_IF(! (var), "Unable to find method %s", fieldName);
 
 #define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
     var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
-    LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
+    LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName);
 
 #define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
     var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
-    LOG_FATAL_IF(! (var), "Unable to find static method " fieldName);
+    LOG_FATAL_IF(! (var), "Unable to find static method %s", fieldName);
 
-#define GET_STATIC_OBJECT_FIELD(var, clazz, fieldName) \
-    var = env->GetStaticObjectField(clazz, fieldName); \
-    LOG_FATAL_IF(! (var), "Unable to find static object field " fieldName);
+#define GET_STATIC_OBJECT_FIELD(var, clazz, fieldId) \
+    var = env->GetStaticObjectField(clazz, fieldId); \
+    LOG_FATAL_IF(! (var), "Unable to find static object field %p", fieldId);
 
 
 struct RequestFields {
diff --git a/native/android/OWNERS b/native/android/OWNERS
index 067cdf8..b3f50aa 100644
--- a/native/android/OWNERS
+++ b/native/android/OWNERS
@@ -1,15 +1,4 @@
 set noparent
 
-per-file libandroid_net.map.txt=codewiz@google.com
-per-file libandroid_net.map.txt=ek@google.com
-per-file libandroid_net.map.txt=jchalard@google.com
-per-file libandroid_net.map.txt=lorenzo@google.com
-per-file libandroid_net.map.txt=reminv@google.com
-per-file libandroid_net.map.txt=satk@google.com
-
-per-file net.c=codewiz@google.com
-per-file net.c=ek@google.com
-per-file net.c=jchalard@google.com
-per-file net.c=lorenzo@google.com
-per-file net.c=reminv@google.com
-per-file net.c=satk@google.com
+per-file libandroid_net.map.txt, net.c = codewiz@google.com, ek@google.com, jchalard@google.com
+per-file libandroid_net.map.txt, net.c = lorenzo@google.com, reminv@google.com, satk@google.com
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 4fa0c07..fe9f1b5 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -1,25 +1,5 @@
 # Connectivity / Networking
-per-file ConnectivityService.java=codewiz@google.com
-per-file ConnectivityService.java=ek@google.com
-per-file ConnectivityService.java=jchalard@google.com
-per-file ConnectivityService.java=lorenzo@google.com
-per-file ConnectivityService.java=reminv@google.com
-per-file ConnectivityService.java=satk@google.com
-per-file NetworkManagementService.java=codewiz@google.com
-per-file NetworkManagementService.java=ek@google.com
-per-file NetworkManagementService.java=jchalard@google.com
-per-file NetworkManagementService.java=lorenzo@google.com
-per-file NetworkManagementService.java=reminv@google.com
-per-file NetworkManagementService.java=satk@google.com
-per-file NsdService.java=codewiz@google.com
-per-file NsdService.java=ek@google.com
-per-file NsdService.java=jchalard@google.com
-per-file NsdService.java=lorenzo@google.com
-per-file NsdService.java=reminv@google.com
-per-file NsdService.java=satk@google.com
+per-file ConnectivityService.java,NetworkManagementService.java,NsdService.java = codewiz@google.com, ek@google.com, jchalard@google.com, lorenzo@google.com, reminv@google.com, satk@google.com
 
-# Vibrator
-per-file VibratorService.java=michaelwr@google.com
-
-# Threads
-per-file DisplayThread.java=michaelwr@google.com
+# Vibrator / Threads
+per-file VibratorService.java, DisplayThread.java = michaelwr@google.com
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index ad9fa40..566ce4f 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -36,6 +36,7 @@
 import android.telephony.CellLocation;
 import android.telephony.DisconnectCause;
 import android.telephony.LocationAccessPolicy;
+import android.telephony.PhoneCapability;
 import android.telephony.PhoneStateListener;
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
@@ -47,7 +48,6 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.VoLteServiceState;
-import android.text.TextUtils;
 import android.util.LocalLog;
 
 import com.android.internal.app.IBatteryStats;
@@ -200,6 +200,8 @@
 
     private boolean mCarrierNetworkChangeState = false;
 
+    private PhoneCapability mPhoneCapability = null;
+
     private final LocalLog mLocalLog = new LocalLog(100);
 
     private PreciseDataConnectionState mPreciseDataConnectionState =
@@ -658,6 +660,13 @@
                             remove(r.binder);
                         }
                     }
+                    if ((events & PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE) != 0) {
+                        try {
+                            r.callback.onPhoneCapabilityChanged(mPhoneCapability);
+                        } catch (RemoteException ex) {
+                            remove(r.binder);
+                        }
+                    }
                 }
             }
         } else {
@@ -1453,6 +1462,33 @@
         }
     }
 
+    public void notifyPhoneCapabilityChanged(PhoneCapability capability) {
+        if (!checkNotifyPermission("notifyPhoneCapabilityChanged()")) {
+            return;
+        }
+
+        if (VDBG) {
+            log("notifyPhoneCapabilityChanged: capability=" + capability);
+        }
+
+        synchronized (mRecords) {
+            mPhoneCapability = capability;
+
+            for (Record r : mRecords) {
+                if (r.matchPhoneStateListenerEvent(
+                        PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE)) {
+                    try {
+                        r.callback.onPhoneCapabilityChanged(capability);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+    }
+
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
@@ -1488,6 +1524,7 @@
             pw.println("mForegroundCallState=" + mForegroundCallState);
             pw.println("mBackgroundCallState=" + mBackgroundCallState);
             pw.println("mVoLteServiceState=" + mVoLteServiceState);
+            pw.println("mPhoneCapability=" + mPhoneCapability);
 
             pw.decreaseIndent();
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 9eb9ab9..96bf44a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -546,6 +546,9 @@
                     case "-e":
                         listEnabled = true;
                         break;
+                    case "-a":
+                        getFlags |= PackageManager.MATCH_KNOWN_PACKAGES;
+                        break;
                     case "-f":
                         showSourceDir = true;
                         break;
@@ -2687,6 +2690,7 @@
         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");
+        pw.println("      -a: all known packages");
         pw.println("      -d: filter to only show disabled packages");
         pw.println("      -e: filter to only show enabled packages");
         pw.println("      -s: filter to only show system packages");
diff --git a/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
index 91e6bd6..11f2b61 100644
--- a/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
@@ -24,10 +24,17 @@
  */
 class DhcpDiscoverPacket extends DhcpPacket {
     /**
+     * The IP address of the client which sent this packet.
+     */
+    final Inet4Address mSrcIp;
+
+    /**
      * Generates a DISCOVER packet with the specified parameters.
      */
-    DhcpDiscoverPacket(int transId, short secs, byte[] clientMac, boolean broadcast) {
-        super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
+    DhcpDiscoverPacket(int transId, short secs, Inet4Address relayIp, byte[] clientMac,
+            boolean broadcast, Inet4Address srcIp) {
+        super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, relayIp, clientMac, broadcast);
+        mSrcIp = srcIp;
     }
 
     public String toString() {
@@ -41,8 +48,8 @@
      */
     public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
         ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
-        fillInPacket(encap, INADDR_BROADCAST, INADDR_ANY, destUdp,
-                srcUdp, result, DHCP_BOOTREQUEST, mBroadcast);
+        fillInPacket(encap, INADDR_BROADCAST, mSrcIp, destUdp, srcUdp, result, DHCP_BOOTREQUEST,
+                mBroadcast);
         result.flip();
         return result;
     }
diff --git a/services/net/java/android/net/dhcp/DhcpLease.java b/services/net/java/android/net/dhcp/DhcpLease.java
new file mode 100644
index 0000000..d2a15b3
--- /dev/null
+++ b/services/net/java/android/net/dhcp/DhcpLease.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.MacAddress;
+import android.os.SystemClock;
+import android.text.TextUtils;
+
+import com.android.internal.util.HexDump;
+
+import java.net.Inet4Address;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * An IPv4 address assignment done through DHCPv4.
+ * @hide
+ */
+public class DhcpLease {
+    public static final long EXPIRATION_NEVER = Long.MAX_VALUE;
+    public static final String HOSTNAME_NONE = null;
+
+    @Nullable
+    private final byte[] mClientId;
+    @NonNull
+    private final MacAddress mHwAddr;
+    @NonNull
+    private final Inet4Address mNetAddr;
+    /**
+     * Expiration time for the lease, to compare with {@link SystemClock#elapsedRealtime()}.
+     */
+    private final long mExpTime;
+    @Nullable
+    private final String mHostname;
+
+    public DhcpLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr,
+            @NonNull Inet4Address netAddr, long expTime, @Nullable String hostname) {
+        mClientId = (clientId == null ? null : Arrays.copyOf(clientId, clientId.length));
+        mHwAddr = hwAddr;
+        mNetAddr = netAddr;
+        mExpTime = expTime;
+        mHostname = hostname;
+    }
+
+    @Nullable
+    public byte[] getClientId() {
+        if (mClientId == null) {
+            return null;
+        }
+        return Arrays.copyOf(mClientId, mClientId.length);
+    }
+
+    @NonNull
+    public MacAddress getHwAddr() {
+        return mHwAddr;
+    }
+
+    @Nullable
+    public String getHostname() {
+        return mHostname;
+    }
+
+    @NonNull
+    public Inet4Address getNetAddr() {
+        return mNetAddr;
+    }
+
+    public long getExpTime() {
+        return mExpTime;
+    }
+
+    /**
+     * Push back the expiration time of this lease. If the provided time is sooner than the original
+     * expiration time, the lease time will not be updated.
+     *
+     * <p>The lease hostname is updated with the provided one if set.
+     * @return A {@link DhcpLease} with expiration time set to max(expTime, currentExpTime)
+     */
+    public DhcpLease renewedLease(long expTime, @Nullable String hostname) {
+        return new DhcpLease(mClientId, mHwAddr, mNetAddr, Math.max(expTime, mExpTime),
+                (hostname == null ? mHostname : hostname));
+    }
+
+    public boolean matchesClient(@Nullable byte[] clientId, @NonNull MacAddress hwAddr) {
+        if (mClientId != null) {
+            return Arrays.equals(mClientId, clientId);
+        } else {
+            return clientId == null && mHwAddr.equals(hwAddr);
+        }
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof DhcpLease)) {
+            return false;
+        }
+        final DhcpLease other = (DhcpLease)obj;
+        return Arrays.equals(mClientId, other.mClientId)
+                && mHwAddr.equals(other.mHwAddr)
+                && mNetAddr.equals(other.mNetAddr)
+                && mExpTime == other.mExpTime
+                && TextUtils.equals(mHostname, other.mHostname);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mClientId, mHwAddr, mNetAddr, mHostname, mExpTime);
+    }
+
+    static String clientIdToString(byte[] bytes) {
+        if (bytes == null) {
+            return "null";
+        }
+        return HexDump.toHexString(bytes);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("clientId: %s, hwAddr: %s, netAddr: %s, expTime: %d, hostname: %s",
+                clientIdToString(mClientId), mHwAddr.toString(), mNetAddr, mExpTime, mHostname);
+    }
+}
diff --git a/services/net/java/android/net/dhcp/DhcpLeaseRepository.java b/services/net/java/android/net/dhcp/DhcpLeaseRepository.java
new file mode 100644
index 0000000..7e57c9f
--- /dev/null
+++ b/services/net/java/android/net/dhcp/DhcpLeaseRepository.java
@@ -0,0 +1,538 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import static android.net.NetworkUtils.inet4AddressToIntHTH;
+import static android.net.NetworkUtils.intToInet4AddressHTH;
+import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTH;
+import static android.net.dhcp.DhcpLease.EXPIRATION_NEVER;
+import static android.net.util.NetworkConstants.IPV4_ADDR_BITS;
+
+import static java.lang.Math.min;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.IpPrefix;
+import android.net.MacAddress;
+import android.net.util.SharedLog;
+import android.os.SystemClock;
+import android.util.ArrayMap;
+
+import java.net.Inet4Address;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.function.Function;
+
+/**
+ * A repository managing IPv4 address assignments through DHCPv4.
+ *
+ * <p>This class is not thread-safe. All public methods should be called on a common thread or
+ * use some synchronization mechanism.
+ *
+ * <p>Methods are optimized for a small number of allocated leases, assuming that most of the time
+ * only 2~10 addresses will be allocated, which is the common case. Managing a large number of
+ * addresses is supported but will be slower: some operations have complexity in O(num_leases).
+ * @hide
+ */
+class DhcpLeaseRepository {
+    public static final byte[] CLIENTID_UNSPEC = null;
+    public static final Inet4Address INETADDR_UNSPEC = null;
+
+    @NonNull
+    private final SharedLog mLog;
+    @NonNull
+    private final Clock mClock;
+
+    @NonNull
+    private IpPrefix mPrefix;
+    @NonNull
+    private Set<Inet4Address> mReservedAddrs;
+    private int mSubnetAddr;
+    private int mSubnetMask;
+    private int mNumAddresses;
+    private long mLeaseTimeMs;
+
+    public static class Clock {
+        /**
+         * @see SystemClock#elapsedRealtime()
+         */
+        public long elapsedRealtime() {
+            return SystemClock.elapsedRealtime();
+        }
+    }
+
+    /**
+     * Next timestamp when committed or declined leases should be checked for expired ones. This
+     * will always be lower than or equal to the time for the first lease to expire: it's OK not to
+     * update this when removing entries, but it must always be updated when adding/updating.
+     */
+    private long mNextExpirationCheck = EXPIRATION_NEVER;
+
+    static class DhcpLeaseException extends Exception {
+        DhcpLeaseException(String message) {
+            super(message);
+        }
+    }
+
+    static class OutOfAddressesException extends DhcpLeaseException {
+        OutOfAddressesException(String message) {
+            super(message);
+        }
+    }
+
+    static class InvalidAddressException extends DhcpLeaseException {
+        InvalidAddressException(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * Leases by IP address
+     */
+    private final ArrayMap<Inet4Address, DhcpLease> mCommittedLeases = new ArrayMap<>();
+
+    /**
+     * Map address -> expiration timestamp in ms. Addresses are guaranteed to be valid as defined
+     * by {@link #isValidAddress(Inet4Address)}, but are not necessarily otherwise available for
+     * assignment.
+     */
+    private final LinkedHashMap<Inet4Address, Long> mDeclinedAddrs = new LinkedHashMap<>();
+
+    public DhcpLeaseRepository(@NonNull IpPrefix prefix, @NonNull Set<Inet4Address> reservedAddrs,
+            long leaseTimeMs, @NonNull SharedLog log, @NonNull Clock clock) {
+        updateParams(prefix, reservedAddrs, leaseTimeMs);
+        mLog = log;
+        mClock = clock;
+    }
+
+    public void updateParams(@NonNull IpPrefix prefix, @NonNull Set<Inet4Address> reservedAddrs,
+            long leaseTimeMs) {
+        mPrefix = prefix;
+        mReservedAddrs = Collections.unmodifiableSet(new HashSet<>(reservedAddrs));
+        mSubnetMask = prefixLengthToV4NetmaskIntHTH(prefix.getPrefixLength());
+        mSubnetAddr = inet4AddressToIntHTH((Inet4Address) prefix.getAddress()) & mSubnetMask;
+        mNumAddresses = 1 << (IPV4_ADDR_BITS - prefix.getPrefixLength());
+        mLeaseTimeMs = leaseTimeMs;
+
+        cleanMap(mCommittedLeases);
+        cleanMap(mDeclinedAddrs);
+    }
+
+    /**
+     * From a map keyed by {@link Inet4Address}, remove entries where the key is invalid (as
+     * specified by {@link #isValidAddress(Inet4Address)}), or is a reserved address.
+     */
+    private <T> void cleanMap(Map<Inet4Address, T> map) {
+        final Iterator<Entry<Inet4Address, T>> it = map.entrySet().iterator();
+        while (it.hasNext()) {
+            final Inet4Address addr = it.next().getKey();
+            if (!isValidAddress(addr) || mReservedAddrs.contains(addr)) {
+                it.remove();
+            }
+        }
+    }
+
+    /**
+     * Get a DHCP offer, to reply to a DHCPDISCOVER. Follows RFC2131 #4.3.1.
+     *
+     * @param clientId Client identifier option if specified, or {@link #CLIENTID_UNSPEC}
+     * @param relayAddr Internet address of the relay (giaddr), can be {@link Inet4Address#ANY}
+     * @param reqAddr Requested address by the client (option 50), or {@link #INETADDR_UNSPEC}
+     * @param hostname Client-provided hostname, or {@link DhcpLease#HOSTNAME_NONE}
+     * @throws OutOfAddressesException The server does not have any available address
+     * @throws InvalidAddressException The lease was requested from an unsupported subnet
+     */
+    @NonNull
+    public DhcpLease getOffer(@Nullable byte[] clientId, @NonNull MacAddress hwAddr,
+            @NonNull Inet4Address relayAddr,
+            @Nullable Inet4Address reqAddr, @Nullable String hostname)
+            throws OutOfAddressesException, InvalidAddressException {
+        final long currentTime = mClock.elapsedRealtime();
+        final long expTime = currentTime + mLeaseTimeMs;
+
+        removeExpiredLeases(currentTime);
+
+        // As per #4.3.1, addresses are assigned based on the relay address if present. This
+        // implementation only assigns addresses if the relayAddr is inside our configured subnet.
+        // This also applies when the client requested a specific address for consistency between
+        // requests, and with older behavior.
+        if (isIpAddrOutsidePrefix(mPrefix, relayAddr)) {
+            throw new InvalidAddressException("Lease requested by relay from outside of subnet");
+        }
+
+        final DhcpLease currentLease = findByClient(clientId, hwAddr);
+        final DhcpLease newLease;
+        if (currentLease != null) {
+            newLease = currentLease.renewedLease(expTime, hostname);
+            mLog.log("Offering extended lease " + newLease);
+            // Do not update lease time in the map: the offer is not committed yet.
+        } else if (reqAddr != null && isValidAddress(reqAddr) && isAvailable(reqAddr)) {
+            newLease = new DhcpLease(clientId, hwAddr, reqAddr, expTime, hostname);
+            mLog.log("Offering requested lease " + newLease);
+        } else {
+            newLease = makeNewOffer(clientId, hwAddr, expTime, hostname);
+            mLog.log("Offering new generated lease " + newLease);
+        }
+        return newLease;
+    }
+
+    private static boolean isIpAddrOutsidePrefix(IpPrefix prefix, Inet4Address addr) {
+        return addr != null && !addr.equals(Inet4Address.ANY) && !prefix.contains(addr);
+    }
+
+    @Nullable
+    private DhcpLease findByClient(@Nullable byte[] clientId, @NonNull MacAddress hwAddr) {
+        for (DhcpLease lease : mCommittedLeases.values()) {
+            if (lease.matchesClient(clientId, hwAddr)) {
+                return lease;
+            }
+        }
+
+        // Note this differs from dnsmasq behavior, which would match by hwAddr if clientId was
+        // given but no lease keyed on clientId matched. This would prevent one interface from
+        // obtaining multiple leases with different clientId.
+        return null;
+    }
+
+    /**
+     * Make a lease conformant to a client DHCPREQUEST or renew the client's existing lease,
+     * commit it to the repository and return it.
+     *
+     * <p>This method always succeeds and commits the lease if it does not throw, and has no side
+     * effects if it throws.
+     *
+     * @param clientId Client identifier option if specified, or {@link #CLIENTID_UNSPEC}
+     * @param reqAddr Requested address by the client (option 50), or {@link #INETADDR_UNSPEC}
+     * @param sidSet Whether the server identifier was set in the request
+     * @return The newly created or renewed lease
+     * @throws InvalidAddressException The client provided an address that conflicts with its
+     *                                 current configuration, or other committed/reserved leases.
+     */
+    @NonNull
+    public DhcpLease requestLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr,
+            @NonNull Inet4Address clientAddr, @Nullable Inet4Address reqAddr, boolean sidSet,
+            @Nullable String hostname) throws InvalidAddressException {
+        final long currentTime = mClock.elapsedRealtime();
+        removeExpiredLeases(currentTime);
+        final DhcpLease assignedLease = findByClient(clientId, hwAddr);
+
+        final Inet4Address leaseAddr = reqAddr != null ? reqAddr : clientAddr;
+        if (assignedLease != null) {
+            if (sidSet && reqAddr != null) {
+                // Client in SELECTING state; remove any current lease before creating a new one.
+                mCommittedLeases.remove(assignedLease.getNetAddr());
+            } else if (!assignedLease.getNetAddr().equals(leaseAddr)) {
+                // reqAddr null (RENEWING/REBINDING): client renewing its own lease for clientAddr.
+                // reqAddr set with sid not set (INIT-REBOOT): client verifying configuration.
+                // In both cases, throw if clientAddr or reqAddr does not match the known lease.
+                throw new InvalidAddressException("Incorrect address for client in " +
+                        (reqAddr != null ? "INIT-REBOOT" : "RENEWING/REBINDING"));
+            }
+        }
+
+        // In the init-reboot case, RFC2131 #4.3.2 says that the server must not reply if
+        // assignedLease == null, but dnsmasq will let the client use the requested address if
+        // available, when configured with --dhcp-authoritative. This is preferable to avoid issues
+        // if the server lost the lease DB: the client would not get a reply because the server
+        // does not know their lease.
+        // Similarly in RENEWING/REBINDING state, create a lease when possible if the
+        // client-provided lease is unknown.
+        final DhcpLease lease =
+                checkClientAndMakeLease(clientId, hwAddr, leaseAddr, hostname, currentTime);
+        mLog.logf("DHCPREQUEST assignedLease %s, reqAddr=%s, sidSet=%s: created/renewed lease %s",
+                assignedLease, reqAddr, sidSet, lease);
+        return lease;
+    }
+
+    /**
+     * Check that the client can request the specified address, make or renew the lease if yes, and
+     * commit it.
+     *
+     * <p>This method always succeeds and returns the lease if it does not throw, and has no
+     * side-effect if it throws.
+     *
+     * @return The newly created or renewed, committed lease
+     * @throws InvalidAddressException The client provided an address that conflicts with its
+     *                                 current configuration, or other committed/reserved leases.
+     */
+    private DhcpLease checkClientAndMakeLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr,
+            @NonNull Inet4Address addr, @Nullable String hostname, long currentTime)
+            throws InvalidAddressException {
+        final long expTime = currentTime + mLeaseTimeMs;
+        final DhcpLease currentLease = mCommittedLeases.getOrDefault(addr, null);
+        if (currentLease != null && !currentLease.matchesClient(clientId, hwAddr)) {
+            throw new InvalidAddressException("Address in use");
+        }
+
+        final DhcpLease lease;
+        if (currentLease == null) {
+            if (isValidAddress(addr) && !mReservedAddrs.contains(addr)) {
+                lease = new DhcpLease(clientId, hwAddr, addr, expTime, hostname);
+            } else {
+                throw new InvalidAddressException("Lease not found and address unavailable");
+            }
+        } else {
+            lease = currentLease.renewedLease(expTime, hostname);
+        }
+        commitLease(lease);
+        return lease;
+    }
+
+    private void commitLease(@NonNull DhcpLease lease) {
+        mCommittedLeases.put(lease.getNetAddr(), lease);
+        maybeUpdateEarliestExpiration(lease.getExpTime());
+    }
+
+    /**
+     * Delete a committed lease from the repository.
+     *
+     * @return true if a lease matching parameters was found.
+     */
+    public boolean releaseLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr,
+            @NonNull Inet4Address addr) {
+        final DhcpLease currentLease = mCommittedLeases.getOrDefault(addr, null);
+        if (currentLease == null) {
+            mLog.w("Could not release unknown lease for " + addr);
+            return false;
+        }
+        if (currentLease.matchesClient(clientId, hwAddr)) {
+            mCommittedLeases.remove(addr);
+            mLog.log("Released lease " + currentLease);
+            return true;
+        }
+        mLog.w(String.format("Not releasing lease %s: does not match client (cid %s, hwAddr %s)",
+                currentLease, DhcpLease.clientIdToString(clientId), hwAddr));
+        return false;
+    }
+
+    public void markLeaseDeclined(@NonNull Inet4Address addr) {
+        if (mDeclinedAddrs.containsKey(addr) || !isValidAddress(addr)) {
+            mLog.logf("Not marking %s as declined: already declined or not assignable", addr);
+            return;
+        }
+        final long expTime = mClock.elapsedRealtime() + mLeaseTimeMs;
+        mDeclinedAddrs.put(addr, expTime);
+        mLog.logf("Marked %s as declined expiring %d", addr, expTime);
+        maybeUpdateEarliestExpiration(expTime);
+    }
+
+    /**
+     * Get the list of currently valid committed leases in the repository.
+     */
+    @NonNull
+    public List<DhcpLease> getCommittedLeases() {
+        removeExpiredLeases(mClock.elapsedRealtime());
+        return new ArrayList<>(mCommittedLeases.values());
+    }
+
+    /**
+     * Get the set of addresses that have been marked as declined in the repository.
+     */
+    @NonNull
+    public Set<Inet4Address> getDeclinedAddresses() {
+        removeExpiredLeases(mClock.elapsedRealtime());
+        return new HashSet<>(mDeclinedAddrs.keySet());
+    }
+
+    /**
+     * Given the expiration time of a new committed lease or declined address, update
+     * {@link #mNextExpirationCheck} so it stays lower than or equal to the time for the first lease
+     * to expire.
+     */
+    private void maybeUpdateEarliestExpiration(long expTime) {
+        if (expTime < mNextExpirationCheck) {
+            mNextExpirationCheck = expTime;
+        }
+    }
+
+    /**
+     * Remove expired entries from a map keyed by {@link Inet4Address}.
+     *
+     * @param tag Type of lease in the map, for logging
+     * @param getExpTime Functor returning the expiration time for an object in the map.
+     *                   Must not return null.
+     * @return The lowest expiration time among entries remaining in the map
+     */
+    private <T> long removeExpired(long currentTime, @NonNull Map<Inet4Address, T> map,
+            @NonNull String tag, @NonNull Function<T, Long> getExpTime) {
+        final Iterator<Entry<Inet4Address, T>> it = map.entrySet().iterator();
+        long firstExpiration = EXPIRATION_NEVER;
+        while (it.hasNext()) {
+            final Entry<Inet4Address, T> lease = it.next();
+            final long expTime = getExpTime.apply(lease.getValue());
+            if (expTime <= currentTime) {
+                mLog.logf("Removing expired %s lease for %s (expTime=%s, currentTime=%s)",
+                        tag, lease.getKey(), expTime, currentTime);
+                it.remove();
+            } else {
+                firstExpiration = min(firstExpiration, expTime);
+            }
+        }
+        return firstExpiration;
+    }
+
+    /**
+     * Go through committed and declined leases and remove the expired ones.
+     */
+    private void removeExpiredLeases(long currentTime) {
+        if (currentTime < mNextExpirationCheck) {
+            return;
+        }
+
+        final long commExp = removeExpired(
+                currentTime, mCommittedLeases, "committed", DhcpLease::getExpTime);
+        final long declExp = removeExpired(
+                currentTime, mDeclinedAddrs, "declined", Function.identity());
+
+        mNextExpirationCheck = min(commExp, declExp);
+    }
+
+    private boolean isAvailable(@NonNull Inet4Address addr) {
+        return !mReservedAddrs.contains(addr) && !mCommittedLeases.containsKey(addr);
+    }
+
+    /**
+     * Get the 0-based index of an address in the subnet.
+     *
+     * <p>Given ordering of addresses 5.6.7.8 < 5.6.7.9 < 5.6.8.0, the index on a subnet is defined
+     * so that the first address is 0, the second 1, etc. For example on a /16, 192.168.0.0 -> 0,
+     * 192.168.0.1 -> 1, 192.168.1.0 -> 256
+     *
+     */
+    private int getAddrIndex(int addr) {
+        return addr & ~mSubnetMask;
+    }
+
+    private int getAddrByIndex(int index) {
+        return mSubnetAddr | index;
+    }
+
+    /**
+     * Get a valid address starting from the supplied one.
+     *
+     * <p>This only checks that the address is numerically valid for assignment, not whether it is
+     * already in use. The return value is always inside the configured prefix, even if the supplied
+     * address is not.
+     *
+     * <p>If the provided address is valid, it is returned as-is. Otherwise, the next valid
+     * address (with the ordering in {@link #getAddrIndex(int)}) is returned.
+     */
+    private int getValidAddress(int addr) {
+        final int lastByteMask = 0xff;
+        int addrIndex = getAddrIndex(addr); // 0-based index of the address in the subnet
+
+        // Some OSes do not handle addresses in .255 or .0 correctly: avoid those.
+        final int lastByte = getAddrByIndex(addrIndex) & lastByteMask;
+        if (lastByte == lastByteMask) {
+            // Avoid .255 address, and .0 address that follows
+            addrIndex = (addrIndex + 2) % mNumAddresses;
+        } else if (lastByte == 0) {
+            // Avoid .0 address
+            addrIndex = (addrIndex + 1) % mNumAddresses;
+        }
+
+        // Do not use first or last address of range
+        if (addrIndex == 0 || addrIndex == mNumAddresses - 1) {
+            // Always valid and not end of range since prefixLength is at most 30 in serving params
+            addrIndex = 1;
+        }
+        return getAddrByIndex(addrIndex);
+    }
+
+    /**
+     * Returns whether the address is in the configured subnet and part of the assignable range.
+     */
+    private boolean isValidAddress(Inet4Address addr) {
+        final int intAddr = inet4AddressToIntHTH(addr);
+        return getValidAddress(intAddr) == intAddr;
+    }
+
+    private int getNextAddress(int addr) {
+        final int addrIndex = getAddrIndex(addr);
+        final int nextAddress = getAddrByIndex((addrIndex + 1) % mNumAddresses);
+        return getValidAddress(nextAddress);
+    }
+
+    /**
+     * Calculate a first candidate address for a client by hashing the hardware address.
+     *
+     * <p>This will be a valid address as checked by {@link #getValidAddress(int)}, but may be
+     * in use.
+     *
+     * @return An IPv4 address encoded as 32-bit int
+     */
+    private int getFirstClientAddress(MacAddress hwAddr) {
+        // This follows dnsmasq behavior. Advantages are: clients will often get the same
+        // offers for different DISCOVER even if the lease was not yet accepted or has expired,
+        // and address generation will generally not need to loop through many allocated addresses
+        // until it finds a free one.
+        int hash = 0;
+        for (byte b : hwAddr.toByteArray()) {
+            hash += b + (b << 8) + (b << 16);
+        }
+        // This implementation will not always result in the same IPs as dnsmasq would give out in
+        // Android <= P, because it includes invalid and reserved addresses in mNumAddresses while
+        // the configured ranges for dnsmasq did not.
+        final int addrIndex = hash % mNumAddresses;
+        return getValidAddress(getAddrByIndex(addrIndex));
+    }
+
+    /**
+     * Create a lease that can be offered to respond to a client DISCOVER.
+     *
+     * <p>This method always succeeds and returns the lease if it does not throw. If no non-declined
+     * address is available, it will try to offer the oldest declined address if valid.
+     *
+     * @throws OutOfAddressesException The server has no address left to offer
+     */
+    private DhcpLease makeNewOffer(@Nullable byte[] clientId, @NonNull MacAddress hwAddr,
+            long expTime, @Nullable String hostname) throws OutOfAddressesException {
+        int intAddr = getFirstClientAddress(hwAddr);
+        // Loop until a free address is found, or there are no more addresses.
+        // There is slightly less than this many usable addresses, but some extra looping is OK
+        for (int i = 0; i < mNumAddresses; i++) {
+            final Inet4Address addr = intToInet4AddressHTH(intAddr);
+            if (isAvailable(addr) && !mDeclinedAddrs.containsKey(addr)) {
+                return new DhcpLease(clientId, hwAddr, addr, expTime, hostname);
+            }
+            intAddr = getNextAddress(intAddr);
+        }
+
+        // Try freeing DECLINEd addresses if out of addresses.
+        final Iterator<Inet4Address> it = mDeclinedAddrs.keySet().iterator();
+        while (it.hasNext()) {
+            final Inet4Address addr = it.next();
+            it.remove();
+            mLog.logf("Out of addresses in address pool: dropped declined addr %s", addr);
+            // isValidAddress() is always verified for entries in mDeclinedAddrs.
+            // However declined addresses may have been requested (typically by the machine that was
+            // already using the address) after being declined.
+            if (isAvailable(addr)) {
+                return new DhcpLease(clientId, hwAddr, addr, expTime, hostname);
+            }
+        }
+
+        throw new OutOfAddressesException("No address available for offer");
+    }
+}
diff --git a/services/net/java/android/net/dhcp/DhcpNakPacket.java b/services/net/java/android/net/dhcp/DhcpNakPacket.java
index 6458232..ef9af52 100644
--- a/services/net/java/android/net/dhcp/DhcpNakPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpNakPacket.java
@@ -26,11 +26,9 @@
     /**
      * Generates a NAK packet with the specified parameters.
      */
-    DhcpNakPacket(int transId, short secs, Inet4Address clientIp, Inet4Address yourIp,
-                  Inet4Address nextIp, Inet4Address relayIp,
-                  byte[] clientMac) {
-        super(transId, secs, INADDR_ANY, INADDR_ANY, nextIp, relayIp,
-            clientMac, false);
+    DhcpNakPacket(int transId, short secs, Inet4Address nextIp, Inet4Address relayIp,
+            byte[] clientMac, boolean broadcast) {
+        super(transId, secs, INADDR_ANY, INADDR_ANY, nextIp, relayIp, clientMac, broadcast);
     }
 
     public String toString() {
@@ -43,11 +41,11 @@
      */
     public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
         ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
-        Inet4Address destIp = mClientIp;
-        Inet4Address srcIp = mYourIp;
+        // Constructor does not set values for layers <= 3: use empty values
+        Inet4Address destIp = INADDR_ANY;
+        Inet4Address srcIp = INADDR_ANY;
 
-        fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result,
-            DHCP_BOOTREPLY, mBroadcast);
+        fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result, DHCP_BOOTREPLY, mBroadcast);
         result.flip();
         return result;
     }
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index d90a4a2..888821a 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -1,5 +1,6 @@
 package android.net.dhcp;
 
+import android.annotation.Nullable;
 import android.net.DhcpResults;
 import android.net.LinkAddress;
 import android.net.NetworkUtils;
@@ -204,6 +205,7 @@
     protected static final byte DHCP_MESSAGE_TYPE_DECLINE = 4;
     protected static final byte DHCP_MESSAGE_TYPE_ACK = 5;
     protected static final byte DHCP_MESSAGE_TYPE_NAK = 6;
+    protected static final byte DHCP_MESSAGE_TYPE_RELEASE = 7;
     protected static final byte DHCP_MESSAGE_TYPE_INFORM = 8;
 
     /**
@@ -252,6 +254,7 @@
      * DHCP Optional Type: DHCP Client Identifier
      */
     protected static final byte DHCP_CLIENT_IDENTIFIER = 61;
+    protected byte[] mClientId;
 
     /**
      * DHCP zero-length option code: pad
@@ -281,7 +284,7 @@
     protected final Inet4Address mClientIp;
     protected final Inet4Address mYourIp;
     private final Inet4Address mNextIp;
-    private final Inet4Address mRelayIp;
+    protected final Inet4Address mRelayIp;
 
     /**
      * Does the client request a broadcast response?
@@ -338,13 +341,28 @@
         return mClientMac;
     }
 
+    // TODO: refactor DhcpClient to set clientId when constructing packets and remove
+    // hasExplicitClientId logic
     /**
-     * Returns the client ID. This follows RFC 2132 and is based on the hardware address.
+     * Returns whether a client ID was set in the options for this packet.
+     */
+    public boolean hasExplicitClientId() {
+        return mClientId != null;
+    }
+
+    /**
+     * Returns the client ID. If not set explicitly, this follows RFC 2132 and creates a client ID
+     * based on the hardware address.
      */
     public byte[] getClientId() {
-        byte[] clientId = new byte[mClientMac.length + 1];
-        clientId[0] = CLIENT_ID_ETHER;
-        System.arraycopy(mClientMac, 0, clientId, 1, mClientMac.length);
+        final byte[] clientId;
+        if (hasExplicitClientId()) {
+            clientId = Arrays.copyOf(mClientId, mClientId.length);
+        } else {
+            clientId = new byte[mClientMac.length + 1];
+            clientId[0] = CLIENT_ID_ETHER;
+            System.arraycopy(mClientMac, 0, clientId, 1, mClientMac.length);
+        }
         return clientId;
     }
 
@@ -531,8 +549,10 @@
 
     /**
      * Adds an optional parameter containing an array of bytes.
+     *
+     * <p>This method is a no-op if the payload argument is null.
      */
-    protected static void addTlv(ByteBuffer buf, byte type, byte[] payload) {
+    protected static void addTlv(ByteBuffer buf, byte type, @Nullable byte[] payload) {
         if (payload != null) {
             if (payload.length > MAX_OPTION_LEN) {
                 throw new IllegalArgumentException("DHCP option too long: "
@@ -546,8 +566,10 @@
 
     /**
      * Adds an optional parameter containing an IP address.
+     *
+     * <p>This method is a no-op if the address argument is null.
      */
-    protected static void addTlv(ByteBuffer buf, byte type, Inet4Address addr) {
+    protected static void addTlv(ByteBuffer buf, byte type, @Nullable Inet4Address addr) {
         if (addr != null) {
             addTlv(buf, type, addr.getAddress());
         }
@@ -555,8 +577,10 @@
 
     /**
      * Adds an optional parameter containing a list of IP addresses.
+     *
+     * <p>This method is a no-op if the addresses argument is null or empty.
      */
-    protected static void addTlv(ByteBuffer buf, byte type, List<Inet4Address> addrs) {
+    protected static void addTlv(ByteBuffer buf, byte type, @Nullable List<Inet4Address> addrs) {
         if (addrs == null || addrs.size() == 0) return;
 
         int optionLen = 4 * addrs.size();
@@ -574,9 +598,11 @@
     }
 
     /**
-     * Adds an optional parameter containing a short integer
+     * Adds an optional parameter containing a short integer.
+     *
+     * <p>This method is a no-op if the value argument is null.
      */
-    protected static void addTlv(ByteBuffer buf, byte type, Short value) {
+    protected static void addTlv(ByteBuffer buf, byte type, @Nullable Short value) {
         if (value != null) {
             buf.put(type);
             buf.put((byte) 2);
@@ -585,9 +611,11 @@
     }
 
     /**
-     * Adds an optional parameter containing a simple integer
+     * Adds an optional parameter containing a simple integer.
+     *
+     * <p>This method is a no-op if the value argument is null.
      */
-    protected static void addTlv(ByteBuffer buf, byte type, Integer value) {
+    protected static void addTlv(ByteBuffer buf, byte type, @Nullable Integer value) {
         if (value != null) {
             buf.put(type);
             buf.put((byte) 4);
@@ -597,12 +625,16 @@
 
     /**
      * Adds an optional parameter containing an ASCII string.
+     *
+     * <p>This method is a no-op if the string argument is null.
      */
-    protected static void addTlv(ByteBuffer buf, byte type, String str) {
-        try {
-            addTlv(buf, type, str.getBytes("US-ASCII"));
-        } catch (UnsupportedEncodingException e) {
-           throw new IllegalArgumentException("String is not US-ASCII: " + str);
+    protected static void addTlv(ByteBuffer buf, byte type, @Nullable String str) {
+        if (str != null) {
+            try {
+                addTlv(buf, type, str.getBytes("US-ASCII"));
+            } catch (UnsupportedEncodingException e) {
+                throw new IllegalArgumentException("String is not US-ASCII: " + str);
+            }
         }
     }
 
@@ -740,6 +772,7 @@
         Inet4Address nextIp;
         Inet4Address relayIp;
         byte[] clientMac;
+        byte[] clientId = null;
         List<Inet4Address> dnsServers = new ArrayList<>();
         List<Inet4Address> gateways = new ArrayList<>();  // aka router
         Inet4Address serverIdentifier = null;
@@ -1038,8 +1071,8 @@
                 throw new ParseException(DhcpErrorEvent.DHCP_NO_MSG_TYPE,
                         "No DHCP message type option");
             case DHCP_MESSAGE_TYPE_DISCOVER:
-                newPacket = new DhcpDiscoverPacket(
-                    transactionId, secs, clientMac, broadcast);
+                newPacket = new DhcpDiscoverPacket(transactionId, secs, relayIp, clientMac,
+                        broadcast, ipSrc);
                 break;
             case DHCP_MESSAGE_TYPE_OFFER:
                 newPacket = new DhcpOfferPacket(
@@ -1047,7 +1080,7 @@
                 break;
             case DHCP_MESSAGE_TYPE_REQUEST:
                 newPacket = new DhcpRequestPacket(
-                    transactionId, secs, clientIp, clientMac, broadcast);
+                    transactionId, secs, clientIp, relayIp, clientMac, broadcast);
                 break;
             case DHCP_MESSAGE_TYPE_DECLINE:
                 newPacket = new DhcpDeclinePacket(
@@ -1060,8 +1093,15 @@
                 break;
             case DHCP_MESSAGE_TYPE_NAK:
                 newPacket = new DhcpNakPacket(
-                    transactionId, secs, clientIp, yourIp, nextIp, relayIp,
-                    clientMac);
+                        transactionId, secs, nextIp, relayIp, clientMac, broadcast);
+                break;
+            case DHCP_MESSAGE_TYPE_RELEASE:
+                if (serverIdentifier == null) {
+                    throw new ParseException(DhcpErrorEvent.MISC_ERROR,
+                            "DHCPRELEASE without server identifier");
+                }
+                newPacket = new DhcpReleasePacket(
+                        transactionId, serverIdentifier, clientIp, relayIp, clientMac);
                 break;
             case DHCP_MESSAGE_TYPE_INFORM:
                 newPacket = new DhcpInformPacket(
@@ -1074,6 +1114,7 @@
         }
 
         newPacket.mBroadcastAddress = bcAddr;
+        newPacket.mClientId = clientId;
         newPacket.mDnsServers = dnsServers;
         newPacket.mDomainName = domainName;
         newPacket.mGateways = gateways;
@@ -1173,8 +1214,8 @@
      */
     public static ByteBuffer buildDiscoverPacket(int encap, int transactionId,
         short secs, byte[] clientMac, boolean broadcast, byte[] expectedParams) {
-        DhcpPacket pkt = new DhcpDiscoverPacket(
-            transactionId, secs, clientMac, broadcast);
+        DhcpPacket pkt = new DhcpDiscoverPacket(transactionId, secs, INADDR_ANY /* relayIp */,
+                clientMac, broadcast, INADDR_ANY /* srcIp */);
         pkt.mRequestedParams = expectedParams;
         return pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT);
     }
@@ -1223,12 +1264,11 @@
     /**
      * Builds a DHCP-NAK packet from the required specified parameters.
      */
-    public static ByteBuffer buildNakPacket(int encap, int transactionId,
-        Inet4Address serverIpAddr, Inet4Address clientIpAddr, byte[] mac) {
-        DhcpPacket pkt = new DhcpNakPacket(transactionId, (short) 0, clientIpAddr,
-            serverIpAddr, serverIpAddr, serverIpAddr, mac);
-        pkt.mMessage = "requested address not available";
-        pkt.mRequestedIp = clientIpAddr;
+    public static ByteBuffer buildNakPacket(int encap, int transactionId, Inet4Address serverIpAddr,
+            byte[] mac, boolean broadcast, String message) {
+        DhcpPacket pkt = new DhcpNakPacket(
+                transactionId, (short) 0, serverIpAddr, serverIpAddr, mac, broadcast);
+        pkt.mMessage = message;
         return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER);
     }
 
@@ -1240,7 +1280,7 @@
         byte[] clientMac, Inet4Address requestedIpAddress,
         Inet4Address serverIdentifier, byte[] requestedParams, String hostName) {
         DhcpPacket pkt = new DhcpRequestPacket(transactionId, secs, clientIp,
-            clientMac, broadcast);
+                INADDR_ANY /* relayIp */, clientMac, broadcast);
         pkt.mRequestedIp = requestedIpAddress;
         pkt.mServerIdentifier = serverIdentifier;
         pkt.mHostName = hostName;
diff --git a/services/net/java/android/net/dhcp/DhcpPacketListener.java b/services/net/java/android/net/dhcp/DhcpPacketListener.java
new file mode 100644
index 0000000..498fd93
--- /dev/null
+++ b/services/net/java/android/net/dhcp/DhcpPacketListener.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import android.annotation.Nullable;
+import android.net.util.FdEventsReader;
+import android.net.util.PacketReader;
+import android.os.Handler;
+import android.system.Os;
+
+import java.io.FileDescriptor;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+
+/**
+ * A {@link FdEventsReader} to receive and parse {@link DhcpPacket}.
+ * @hide
+ */
+abstract class DhcpPacketListener extends FdEventsReader<DhcpPacketListener.Payload> {
+    static final class Payload {
+        final byte[] bytes = new byte[DhcpPacket.MAX_LENGTH];
+        Inet4Address srcAddr;
+    }
+
+    public DhcpPacketListener(Handler handler) {
+        super(handler, new Payload());
+    }
+
+    @Override
+    protected int recvBufSize(Payload buffer) {
+        return buffer.bytes.length;
+    }
+
+    @Override
+    protected final void handlePacket(Payload recvbuf, int length) {
+        if (recvbuf.srcAddr == null) {
+            return;
+        }
+
+        try {
+            final DhcpPacket packet = DhcpPacket.decodeFullPacket(recvbuf.bytes, length,
+                    DhcpPacket.ENCAP_BOOTP);
+            onReceive(packet, recvbuf.srcAddr);
+        } catch (DhcpPacket.ParseException e) {
+            logParseError(recvbuf.bytes, length, e);
+        }
+    }
+
+    @Override
+    protected int readPacket(FileDescriptor fd, Payload packetBuffer) throws Exception {
+        final InetSocketAddress addr = new InetSocketAddress();
+        final int read = Os.recvfrom(
+                fd, packetBuffer.bytes, 0, packetBuffer.bytes.length, 0 /* flags */, addr);
+
+        // Buffers with null srcAddr will be dropped in handlePacket()
+        packetBuffer.srcAddr = inet4AddrOrNull(addr);
+        return read;
+    }
+
+    @Nullable
+    private static Inet4Address inet4AddrOrNull(InetSocketAddress addr) {
+        return addr.getAddress() instanceof Inet4Address
+                ? (Inet4Address) addr.getAddress()
+                : null;
+    }
+
+    protected abstract void onReceive(DhcpPacket packet, Inet4Address srcAddr);
+    protected abstract void logParseError(byte[] packet, int length, DhcpPacket.ParseException e);
+}
diff --git a/services/net/java/android/net/dhcp/DhcpReleasePacket.java b/services/net/java/android/net/dhcp/DhcpReleasePacket.java
new file mode 100644
index 0000000..3958303
--- /dev/null
+++ b/services/net/java/android/net/dhcp/DhcpReleasePacket.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import java.net.Inet4Address;
+import java.nio.ByteBuffer;
+
+/**
+ * Implements DHCP-RELEASE
+ */
+class DhcpReleasePacket extends DhcpPacket {
+
+    final Inet4Address mClientAddr;
+
+    /**
+     * Generates a RELEASE packet with the specified parameters.
+     */
+    public DhcpReleasePacket(int transId, Inet4Address serverId, Inet4Address clientAddr,
+            Inet4Address relayIp, byte[] clientMac) {
+        super(transId, (short)0, clientAddr, INADDR_ANY /* yourIp */, INADDR_ANY /* nextIp */,
+                relayIp, clientMac, false /* broadcast */);
+        mServerIdentifier = serverId;
+        mClientAddr = clientAddr;
+    }
+
+
+    @Override
+    public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
+        ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
+        fillInPacket(encap, mServerIdentifier /* destIp */, mClientIp /* srcIp */, destUdp, srcUdp,
+                result, DHCP_BOOTREPLY, mBroadcast);
+        result.flip();
+        return result;
+    }
+
+    @Override
+    void finishPacket(ByteBuffer buffer) {
+        addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_RELEASE);
+        addTlv(buffer, DHCP_CLIENT_IDENTIFIER, getClientId());
+        addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier);
+        addCommonClientTlvs(buffer);
+        addTlvEnd(buffer);
+    }
+}
diff --git a/services/net/java/android/net/dhcp/DhcpRequestPacket.java b/services/net/java/android/net/dhcp/DhcpRequestPacket.java
index 4f9aa01..231d0457 100644
--- a/services/net/java/android/net/dhcp/DhcpRequestPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpRequestPacket.java
@@ -28,9 +28,9 @@
     /**
      * Generates a REQUEST packet with the specified parameters.
      */
-    DhcpRequestPacket(int transId, short secs, Inet4Address clientIp, byte[] clientMac,
-                      boolean broadcast) {
-        super(transId, secs, clientIp, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
+    DhcpRequestPacket(int transId, short secs, Inet4Address clientIp, Inet4Address relayIp,
+            byte[] clientMac, boolean broadcast) {
+        super(transId, secs, clientIp, INADDR_ANY, INADDR_ANY, relayIp, clientMac, broadcast);
     }
 
     public String toString() {
diff --git a/services/net/java/android/net/dhcp/DhcpServingParams.java b/services/net/java/android/net/dhcp/DhcpServingParams.java
new file mode 100644
index 0000000..ba9d116
--- /dev/null
+++ b/services/net/java/android/net/dhcp/DhcpServingParams.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import static android.net.NetworkUtils.getPrefixMaskAsInet4Address;
+import static android.net.dhcp.DhcpPacket.INFINITE_LEASE;
+import static android.net.util.NetworkConstants.IPV4_MAX_MTU;
+import static android.net.util.NetworkConstants.IPV4_MIN_MTU;
+
+import static java.lang.Integer.toUnsignedLong;
+
+import android.annotation.NonNull;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.NetworkUtils;
+
+import java.net.Inet4Address;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Parameters used by the DhcpServer to serve requests.
+ *
+ * <p>Instances are immutable. Use {@link DhcpServingParams.Builder} to instantiate.
+ * @hide
+ */
+public class DhcpServingParams {
+    public static final int MTU_UNSET = 0;
+    public static final int MIN_PREFIX_LENGTH = 16;
+    public static final int MAX_PREFIX_LENGTH = 30;
+
+    /** Server inet address and prefix to serve */
+    @NonNull
+    public final LinkAddress serverAddr;
+
+    /**
+     * Default routers to be advertised to DHCP clients. May be empty.
+     * This set is provided by {@link DhcpServingParams.Builder} and is immutable.
+     */
+    @NonNull
+    public final Set<Inet4Address> defaultRouters;
+
+    /**
+     * DNS servers to be advertised to DHCP clients. May be empty.
+     * This set is provided by {@link DhcpServingParams.Builder} and is immutable.
+     */
+    @NonNull
+    public final Set<Inet4Address> dnsServers;
+
+    /**
+     * Excluded addresses that the DHCP server is not allowed to assign to clients.
+     * This set is provided by {@link DhcpServingParams.Builder} and is immutable.
+     */
+    @NonNull
+    public final Set<Inet4Address> excludedAddrs;
+
+    // DHCP uses uint32. Use long for clearer code, and check range when building.
+    public final long dhcpLeaseTimeSecs;
+    public final int linkMtu;
+
+    /**
+     * Checked exception thrown when some parameters used to build {@link DhcpServingParams} are
+     * missing or invalid.
+     */
+    public static class InvalidParameterException extends Exception {
+        public InvalidParameterException(String message) {
+            super(message);
+        }
+    }
+
+    private DhcpServingParams(@NonNull LinkAddress serverAddr,
+            @NonNull Set<Inet4Address> defaultRouters,
+            @NonNull Set<Inet4Address> dnsServers, @NonNull Set<Inet4Address> excludedAddrs,
+            long dhcpLeaseTimeSecs, int linkMtu) {
+        this.serverAddr = serverAddr;
+        this.defaultRouters = defaultRouters;
+        this.dnsServers = dnsServers;
+        this.excludedAddrs = excludedAddrs;
+        this.dhcpLeaseTimeSecs = dhcpLeaseTimeSecs;
+        this.linkMtu = linkMtu;
+    }
+
+    @NonNull
+    public Inet4Address getServerInet4Addr() {
+        return (Inet4Address) serverAddr.getAddress();
+    }
+
+    /**
+     * Get the served prefix mask as an IPv4 address.
+     *
+     * <p>For example, if the served prefix is 192.168.42.0/24, this will return 255.255.255.0.
+     */
+    @NonNull
+    public Inet4Address getPrefixMaskAsAddress() {
+        return getPrefixMaskAsInet4Address(serverAddr.getPrefixLength());
+    }
+
+    /**
+     * Get the server broadcast address.
+     *
+     * <p>For example, if the server {@link LinkAddress} is 192.168.42.1/24, this will return
+     * 192.168.42.255.
+     */
+    @NonNull
+    public Inet4Address getBroadcastAddress() {
+        return NetworkUtils.getBroadcastAddress(getServerInet4Addr(), serverAddr.getPrefixLength());
+    }
+
+    /**
+     * Utility class to create new instances of {@link DhcpServingParams} while checking validity
+     * of the parameters.
+     */
+    public static class Builder {
+        private LinkAddress serverAddr;
+        private Set<Inet4Address> defaultRouters;
+        private Set<Inet4Address> dnsServers;
+        private Set<Inet4Address> excludedAddrs;
+        private long dhcpLeaseTimeSecs;
+        private int linkMtu = MTU_UNSET;
+
+        /**
+         * Set the server address and served prefix for the DHCP server.
+         *
+         * <p>This parameter is required.
+         */
+        public Builder setServerAddr(@NonNull LinkAddress serverAddr) {
+            this.serverAddr = serverAddr;
+            return this;
+        }
+
+        /**
+         * Set the default routers to be advertised to DHCP clients.
+         *
+         * <p>Each router must be inside the served prefix. This may be an empty set, but it must
+         * always be set explicitly before building the {@link DhcpServingParams}.
+         */
+        public Builder setDefaultRouters(@NonNull Set<Inet4Address> defaultRouters) {
+            this.defaultRouters = defaultRouters;
+            return this;
+        }
+
+        /**
+         * Set the DNS servers to be advertised to DHCP clients.
+         *
+         * <p>This may be an empty set, but it must always be set explicitly before building the
+         * {@link DhcpServingParams}.
+         */
+        public Builder setDnsServers(@NonNull Set<Inet4Address> dnsServers) {
+            this.dnsServers = dnsServers;
+            return this;
+        }
+
+        /**
+         * Set excluded addresses that the DHCP server is not allowed to assign to clients.
+         *
+         * <p>This parameter is optional. DNS servers and default routers are always excluded
+         * and do not need to be set here.
+         */
+        public Builder setExcludedAddrs(@NonNull Set<Inet4Address> excludedAddrs) {
+            this.excludedAddrs = excludedAddrs;
+            return this;
+        }
+
+        /**
+         * Set the lease time for leases assigned by the DHCP server.
+         *
+         * <p>This parameter is required.
+         */
+        public Builder setDhcpLeaseTimeSecs(long dhcpLeaseTimeSecs) {
+            this.dhcpLeaseTimeSecs = dhcpLeaseTimeSecs;
+            return this;
+        }
+
+        /**
+         * Set the link MTU to be advertised to DHCP clients.
+         *
+         * <p>If set to {@link #MTU_UNSET}, no MTU will be advertised to clients. This parameter
+         * is optional and defaults to {@link #MTU_UNSET}.
+         */
+        public Builder setLinkMtu(int linkMtu) {
+            this.linkMtu = linkMtu;
+            return this;
+        }
+
+        /**
+         * Create a new {@link DhcpServingParams} instance based on parameters set in the builder.
+         *
+         * <p>This method has no side-effects. If it does not throw, a valid
+         * {@link DhcpServingParams} is returned.
+         * @return The constructed parameters.
+         * @throws InvalidParameterException At least one parameter is missing or invalid.
+         */
+        @NonNull
+        public DhcpServingParams build() throws InvalidParameterException {
+            if (serverAddr == null) {
+                throw new InvalidParameterException("Missing serverAddr");
+            }
+            if (defaultRouters == null) {
+                throw new InvalidParameterException("Missing defaultRouters");
+            }
+            if (dnsServers == null) {
+                // Empty set is OK, but enforce explicitly setting it
+                throw new InvalidParameterException("Missing dnsServers");
+            }
+            if (dhcpLeaseTimeSecs <= 0 || dhcpLeaseTimeSecs > toUnsignedLong(INFINITE_LEASE)) {
+                throw new InvalidParameterException("Invalid lease time: " + dhcpLeaseTimeSecs);
+            }
+            if (linkMtu != MTU_UNSET && (linkMtu < IPV4_MIN_MTU || linkMtu > IPV4_MAX_MTU)) {
+                throw new InvalidParameterException("Invalid link MTU: " + linkMtu);
+            }
+            if (!serverAddr.isIPv4()) {
+                throw new InvalidParameterException("serverAddr must be IPv4");
+            }
+            if (serverAddr.getPrefixLength() < MIN_PREFIX_LENGTH
+                    || serverAddr.getPrefixLength() > MAX_PREFIX_LENGTH) {
+                throw new InvalidParameterException("Prefix length is not in supported range");
+            }
+
+            final IpPrefix prefix = makeIpPrefix(serverAddr);
+            for (Inet4Address addr : defaultRouters) {
+                if (!prefix.contains(addr)) {
+                    throw new InvalidParameterException(String.format(
+                            "Default router %s is not in server prefix %s", addr, serverAddr));
+                }
+            }
+
+            final Set<Inet4Address> excl = new HashSet<>();
+            if (excludedAddrs != null) {
+                excl.addAll(excludedAddrs);
+            }
+            excl.add((Inet4Address) serverAddr.getAddress());
+            excl.addAll(defaultRouters);
+            excl.addAll(dnsServers);
+
+            return new DhcpServingParams(serverAddr,
+                    Collections.unmodifiableSet(new HashSet<>(defaultRouters)),
+                    Collections.unmodifiableSet(new HashSet<>(dnsServers)),
+                    Collections.unmodifiableSet(excl),
+                    dhcpLeaseTimeSecs, linkMtu);
+        }
+    }
+
+    @NonNull
+    static IpPrefix makeIpPrefix(@NonNull LinkAddress addr) {
+        return new IpPrefix(addr.getAddress(), addr.getPrefixLength());
+    }
+}
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index 7f821ff..b77da28 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -524,7 +524,7 @@
                 return false;
             }
             // There no more than one IPv4 address
-            if (ipAddresses.stream().filter(Inet4Address.class::isInstance).count() > 1) {
+            if (ipAddresses.stream().filter(LinkAddress::isIPv4).count() > 1) {
                 return false;
             }
 
diff --git a/services/net/java/android/net/util/FdEventsReader.java b/services/net/java/android/net/util/FdEventsReader.java
new file mode 100644
index 0000000..575444f
--- /dev/null
+++ b/services/net/java/android/net/util/FdEventsReader.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.util;
+
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.MessageQueue;
+import android.system.ErrnoException;
+import android.system.OsConstants;
+
+import libcore.io.IoUtils;
+
+import java.io.FileDescriptor;
+
+
+/**
+ * This class encapsulates the mechanics of registering a file descriptor
+ * with a thread's Looper and handling read events (and errors).
+ *
+ * Subclasses MUST implement createFd() and SHOULD override handlePacket(). They MAY override
+ * onStop() and onStart().
+ *
+ * Subclasses can expect a call life-cycle like the following:
+ *
+ *     [1] when a client calls start(), createFd() is called, followed by the onStart() hook if all
+ *         goes well. Implementations may override onStart() for additional initialization.
+ *
+ *     [2] yield, waiting for read event or error notification:
+ *
+ *             [a] readPacket() && handlePacket()
+ *
+ *             [b] if (no error):
+ *                     goto 2
+ *                 else:
+ *                     goto 3
+ *
+ *     [3] when a client calls stop(), the onStop() hook is called (unless already stopped or never
+ *         started). Implementations may override onStop() for additional cleanup.
+ *
+ * The packet receive buffer is recycled on every read call, so subclasses
+ * should make any copies they would like inside their handlePacket()
+ * implementation.
+ *
+ * All public methods MUST only be called from the same thread with which
+ * the Handler constructor argument is associated.
+ *
+ * @hide
+ */
+public abstract class FdEventsReader<BufferType> {
+    private static final int FD_EVENTS = EVENT_INPUT | EVENT_ERROR;
+    private static final int UNREGISTER_THIS_FD = 0;
+
+    @NonNull
+    private final Handler mHandler;
+    @NonNull
+    private final MessageQueue mQueue;
+    @NonNull
+    private final BufferType mBuffer;
+    @Nullable
+    private FileDescriptor mFd;
+    private long mPacketsReceived;
+
+    protected static void closeFd(FileDescriptor fd) {
+        IoUtils.closeQuietly(fd);
+    }
+
+    protected FdEventsReader(@NonNull Handler h, @NonNull BufferType buffer) {
+        mHandler = h;
+        mQueue = mHandler.getLooper().getQueue();
+        mBuffer = buffer;
+    }
+
+    public final void start() {
+        if (onCorrectThread()) {
+            createAndRegisterFd();
+        } else {
+            mHandler.post(() -> {
+                logError("start() called from off-thread", null);
+                createAndRegisterFd();
+            });
+        }
+    }
+
+    public final void stop() {
+        if (onCorrectThread()) {
+            unregisterAndDestroyFd();
+        } else {
+            mHandler.post(() -> {
+                logError("stop() called from off-thread", null);
+                unregisterAndDestroyFd();
+            });
+        }
+    }
+
+    @NonNull
+    public Handler getHandler() { return mHandler; }
+
+    protected abstract int recvBufSize(@NonNull BufferType buffer);
+
+    public int recvBufSize() { return recvBufSize(mBuffer); }
+
+    /**
+     * Get the number of successful calls to {@link #readPacket(FileDescriptor, Object)}.
+     *
+     * <p>A call was successful if {@link #readPacket(FileDescriptor, Object)} returned a value > 0.
+     */
+    public final long numPacketsReceived() { return mPacketsReceived; }
+
+    /**
+     * Subclasses MUST create the listening socket here, including setting
+     * all desired socket options, interface or address/port binding, etc.
+     */
+    @Nullable
+    protected abstract FileDescriptor createFd();
+
+    /**
+     * Implementations MUST return the bytes read or throw an Exception.
+     *
+     * <p>The caller may throw a {@link ErrnoException} with {@link OsConstants#EAGAIN} or
+     * {@link OsConstants#EINTR}, in which case {@link FdEventsReader} will ignore the buffer
+     * contents and respectively wait for further input or retry the read immediately. For all other
+     * exceptions, the {@link FdEventsReader} will be stopped with no more interactions with this
+     * method.
+     */
+    protected abstract int readPacket(@NonNull FileDescriptor fd, @NonNull BufferType buffer)
+            throws Exception;
+
+    /**
+     * Called by the main loop for every packet.  Any desired copies of
+     * |recvbuf| should be made in here, as the underlying byte array is
+     * reused across all reads.
+     */
+    protected void handlePacket(@NonNull BufferType recvbuf, int length) {}
+
+    /**
+     * Called by the main loop to log errors.  In some cases |e| may be null.
+     */
+    protected void logError(@NonNull String msg, @Nullable Exception e) {}
+
+    /**
+     * Called by start(), if successful, just prior to returning.
+     */
+    protected void onStart() {}
+
+    /**
+     * Called by stop() just prior to returning.
+     */
+    protected void onStop() {}
+
+    private void createAndRegisterFd() {
+        if (mFd != null) return;
+
+        try {
+            mFd = createFd();
+            if (mFd != null) {
+                // Force the socket to be non-blocking.
+                IoUtils.setBlocking(mFd, false);
+            }
+        } catch (Exception e) {
+            logError("Failed to create socket: ", e);
+            closeFd(mFd);
+            mFd = null;
+        }
+
+        if (mFd == null) return;
+
+        mQueue.addOnFileDescriptorEventListener(
+                mFd,
+                FD_EVENTS,
+                (fd, events) -> {
+                    // Always call handleInput() so read/recvfrom are given
+                    // a proper chance to encounter a meaningful errno and
+                    // perhaps log a useful error message.
+                    if (!isRunning() || !handleInput()) {
+                        unregisterAndDestroyFd();
+                        return UNREGISTER_THIS_FD;
+                    }
+                    return FD_EVENTS;
+                });
+        onStart();
+    }
+
+    private boolean isRunning() { return (mFd != null) && mFd.valid(); }
+
+    // Keep trying to read until we get EAGAIN/EWOULDBLOCK or some fatal error.
+    private boolean handleInput() {
+        while (isRunning()) {
+            final int bytesRead;
+
+            try {
+                bytesRead = readPacket(mFd, mBuffer);
+                if (bytesRead < 1) {
+                    if (isRunning()) logError("Socket closed, exiting", null);
+                    break;
+                }
+                mPacketsReceived++;
+            } catch (ErrnoException e) {
+                if (e.errno == OsConstants.EAGAIN) {
+                    // We've read everything there is to read this time around.
+                    return true;
+                } else if (e.errno == OsConstants.EINTR) {
+                    continue;
+                } else {
+                    if (isRunning()) logError("readPacket error: ", e);
+                    break;
+                }
+            } catch (Exception e) {
+                if (isRunning()) logError("readPacket error: ", e);
+                break;
+            }
+
+            try {
+                handlePacket(mBuffer, bytesRead);
+            } catch (Exception e) {
+                logError("handlePacket error: ", e);
+                break;
+            }
+        }
+
+        return false;
+    }
+
+    private void unregisterAndDestroyFd() {
+        if (mFd == null) return;
+
+        mQueue.removeOnFileDescriptorEventListener(mFd);
+        closeFd(mFd);
+        mFd = null;
+        onStop();
+    }
+
+    private boolean onCorrectThread() {
+        return (mHandler.getLooper() == Looper.myLooper());
+    }
+}
diff --git a/services/net/java/android/net/util/NetworkConstants.java b/services/net/java/android/net/util/NetworkConstants.java
index de04fd0..3defe56 100644
--- a/services/net/java/android/net/util/NetworkConstants.java
+++ b/services/net/java/android/net/util/NetworkConstants.java
@@ -77,10 +77,12 @@
     /**
      * IPv4 constants.
      *
-     * See als:
+     * See also:
      *     - https://tools.ietf.org/html/rfc791
      */
     public static final int IPV4_HEADER_MIN_LEN = 20;
+    public static final int IPV4_MIN_MTU = 68;
+    public static final int IPV4_MAX_MTU = 65_535;
     public static final int IPV4_IHL_MASK = 0xf;
     public static final int IPV4_FLAGS_OFFSET = 6;
     public static final int IPV4_FRAGMENT_MASK = 0x1fff;
diff --git a/services/net/java/android/net/util/PacketReader.java b/services/net/java/android/net/util/PacketReader.java
index 10da2a5..4aec6b6 100644
--- a/services/net/java/android/net/util/PacketReader.java
+++ b/services/net/java/android/net/util/PacketReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,236 +16,46 @@
 
 package android.net.util;
 
-import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
-import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
+import static java.lang.Math.max;
 
-import android.annotation.Nullable;
 import android.os.Handler;
-import android.os.Looper;
-import android.os.MessageQueue;
-import android.os.MessageQueue.OnFileDescriptorEventListener;
-import android.system.ErrnoException;
 import android.system.Os;
-import android.system.OsConstants;
-
-import libcore.io.IoUtils;
 
 import java.io.FileDescriptor;
-import java.io.IOException;
-
 
 /**
- * This class encapsulates the mechanics of registering a file descriptor
- * with a thread's Looper and handling read events (and errors).
- *
- * Subclasses MUST implement createFd() and SHOULD override handlePacket().
-
- * Subclasses can expect a call life-cycle like the following:
- *
- *     [1] start() calls createFd() and (if all goes well) onStart()
- *
- *     [2] yield, waiting for read event or error notification:
- *
- *             [a] readPacket() && handlePacket()
- *
- *             [b] if (no error):
- *                     goto 2
- *                 else:
- *                     goto 3
- *
- *     [3] stop() calls onStop() if not previously stopped
- *
- * The packet receive buffer is recycled on every read call, so subclasses
- * should make any copies they would like inside their handlePacket()
- * implementation.
- *
- * All public methods MUST only be called from the same thread with which
- * the Handler constructor argument is associated.
+ * Specialization of {@link FdEventsReader} that reads packets into a byte array.
  *
  * TODO: rename this class to something more correctly descriptive (something
  * like [or less horrible than] FdReadEventsHandler?).
  *
  * @hide
  */
-public abstract class PacketReader {
-    private static final int FD_EVENTS = EVENT_INPUT | EVENT_ERROR;
-    private static final int UNREGISTER_THIS_FD = 0;
+public abstract class PacketReader extends FdEventsReader<byte[]> {
 
     public static final int DEFAULT_RECV_BUF_SIZE = 2 * 1024;
 
-    private final Handler mHandler;
-    private final MessageQueue mQueue;
-    private final byte[] mPacket;
-    private FileDescriptor mFd;
-    private long mPacketsReceived;
-
-    protected static void closeFd(FileDescriptor fd) {
-        IoUtils.closeQuietly(fd);
-    }
-
     protected PacketReader(Handler h) {
         this(h, DEFAULT_RECV_BUF_SIZE);
     }
 
-    protected PacketReader(Handler h, int recvbufsize) {
-        mHandler = h;
-        mQueue = mHandler.getLooper().getQueue();
-        mPacket = new byte[Math.max(recvbufsize, DEFAULT_RECV_BUF_SIZE)];
+    protected PacketReader(Handler h, int recvBufSize) {
+        super(h, new byte[max(recvBufSize, DEFAULT_RECV_BUF_SIZE)]);
     }
 
-    public final void start() {
-        if (onCorrectThread()) {
-            createAndRegisterFd();
-        } else {
-            mHandler.post(() -> {
-                logError("start() called from off-thread", null);
-                createAndRegisterFd();
-            });
-        }
+    @Override
+    protected final int recvBufSize(byte[] buffer) {
+        return buffer.length;
     }
 
-    public final void stop() {
-        if (onCorrectThread()) {
-            unregisterAndDestroyFd();
-        } else {
-            mHandler.post(() -> {
-                logError("stop() called from off-thread", null);
-                unregisterAndDestroyFd();
-            });
-        }
-    }
-
-    public Handler getHandler() { return mHandler; }
-
-    public final int recvBufSize() { return mPacket.length; }
-
-    public final long numPacketsReceived() { return mPacketsReceived; }
-
-    /**
-     * Subclasses MUST create the listening socket here, including setting
-     * all desired socket options, interface or address/port binding, etc.
-     */
-    protected abstract FileDescriptor createFd();
-
     /**
      * Subclasses MAY override this to change the default read() implementation
      * in favour of, say, recvfrom().
      *
      * Implementations MUST return the bytes read or throw an Exception.
      */
+    @Override
     protected int readPacket(FileDescriptor fd, byte[] packetBuffer) throws Exception {
         return Os.read(fd, packetBuffer, 0, packetBuffer.length);
     }
-
-    /**
-     * Called by the main loop for every packet.  Any desired copies of
-     * |recvbuf| should be made in here, as the underlying byte array is
-     * reused across all reads.
-     */
-    protected void handlePacket(byte[] recvbuf, int length) {}
-
-    /**
-     * Called by the main loop to log errors.  In some cases |e| may be null.
-     */
-    protected void logError(String msg, Exception e) {}
-
-    /**
-     * Called by start(), if successful, just prior to returning.
-     */
-    protected void onStart() {}
-
-    /**
-     * Called by stop() just prior to returning.
-     */
-    protected void onStop() {}
-
-    private void createAndRegisterFd() {
-        if (mFd != null) return;
-
-        try {
-            mFd = createFd();
-            if (mFd != null) {
-                // Force the socket to be non-blocking.
-                IoUtils.setBlocking(mFd, false);
-            }
-        } catch (Exception e) {
-            logError("Failed to create socket: ", e);
-            closeFd(mFd);
-            mFd = null;
-            return;
-        }
-
-        if (mFd == null) return;
-
-        mQueue.addOnFileDescriptorEventListener(
-                mFd,
-                FD_EVENTS,
-                new OnFileDescriptorEventListener() {
-                    @Override
-                    public int onFileDescriptorEvents(FileDescriptor fd, int events) {
-                        // Always call handleInput() so read/recvfrom are given
-                        // a proper chance to encounter a meaningful errno and
-                        // perhaps log a useful error message.
-                        if (!isRunning() || !handleInput()) {
-                            unregisterAndDestroyFd();
-                            return UNREGISTER_THIS_FD;
-                        }
-                        return FD_EVENTS;
-                    }
-                });
-        onStart();
-    }
-
-    private boolean isRunning() { return (mFd != null) && mFd.valid(); }
-
-    // Keep trying to read until we get EAGAIN/EWOULDBLOCK or some fatal error.
-    private boolean handleInput() {
-        while (isRunning()) {
-            final int bytesRead;
-
-            try {
-                bytesRead = readPacket(mFd, mPacket);
-                if (bytesRead < 1) {
-                    if (isRunning()) logError("Socket closed, exiting", null);
-                    break;
-                }
-                mPacketsReceived++;
-            } catch (ErrnoException e) {
-                if (e.errno == OsConstants.EAGAIN) {
-                    // We've read everything there is to read this time around.
-                    return true;
-                } else if (e.errno == OsConstants.EINTR) {
-                    continue;
-                } else {
-                    if (isRunning()) logError("readPacket error: ", e);
-                    break;
-                }
-            } catch (Exception e) {
-                if (isRunning()) logError("readPacket error: ", e);
-                break;
-            }
-
-            try {
-                handlePacket(mPacket, bytesRead);
-            } catch (Exception e) {
-                logError("handlePacket error: ", e);
-                break;
-            }
-        }
-
-        return false;
-    }
-
-    private void unregisterAndDestroyFd() {
-        if (mFd == null) return;
-
-        mQueue.removeOnFileDescriptorEventListener(mFd);
-        closeFd(mFd);
-        mFd = null;
-        onStop();
-    }
-
-    private boolean onCorrectThread() {
-        return (mHandler.getLooper() == Looper.myLooper());
-    }
 }
diff --git a/services/net/java/android/net/util/SharedLog.java b/services/net/java/android/net/util/SharedLog.java
index bbd3d13..f7bf393 100644
--- a/services/net/java/android/net/util/SharedLog.java
+++ b/services/net/java/android/net/util/SharedLog.java
@@ -16,6 +16,7 @@
 
 package android.net.util;
 
+import android.annotation.NonNull;
 import android.text.TextUtils;
 import android.util.LocalLog;
 import android.util.Log;
@@ -90,6 +91,13 @@
         Log.e(mTag, record(Category.ERROR, msg));
     }
 
+    /**
+     * Log an error due to an exception, with the exception stacktrace.
+     */
+    public void e(@NonNull String msg, @NonNull Throwable e) {
+        Log.e(mTag, record(Category.ERROR, msg + ": " + e.getMessage()), e);
+    }
+
     public void i(String msg) {
         Log.i(mTag, record(Category.NONE, msg));
     }
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index b3a3bf2..d25e59f 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -156,6 +156,18 @@
             "android.telecom.extra.PLAY_CALL_RECORDING_TONE";
 
     /**
+     * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()} which
+     * indicates whether calls for a {@link PhoneAccount} should skip call filtering.
+     * <p>
+     * If not specified, this will default to false; all calls will undergo call filtering unless
+     * specifically exempted (e.g. {@link Connection#PROPERTY_EMERGENCY_CALLBACK_MODE}.) However,
+     * this may be used to skip call filtering when it has already been performed on another device.
+     * @hide
+     */
+    public static final String EXTRA_SKIP_CALL_FILTERING =
+        "android.telecom.extra.SKIP_CALL_FILTERING";
+
+    /**
      * Flag indicating that this {@code PhoneAccount} can act as a connection manager for
      * other connections. The {@link ConnectionService} associated with this {@code PhoneAccount}
      * will be allowed to manage phone calls including using its own proprietary phone-call
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 4fc6949..fdee2f4 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -22,6 +22,7 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
@@ -1198,6 +1199,7 @@
      * disable_metered_apns}
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY =
             "carrier_default_actions_on_redirection_string_array";
 
@@ -1810,6 +1812,7 @@
      * Key identifying if voice call barring notification is required to be shown to the user.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String KEY_DISABLE_VOICE_BARRING_NOTIFICATION_BOOL =
             "disable_voice_barring_notification_bool";
 
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index c240dbb..76a0026 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -129,6 +129,12 @@
         return mAlphaShort;
     }
 
+    /**
+     * @return a CellLocation object for this CellIdentity
+     * @hide
+     */
+    public abstract CellLocation asCellLocation();
+
     @Override
     public boolean equals(Object other) {
         if (!(other instanceof CellIdentity)) {
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 2809066..9218bdc 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -17,8 +17,9 @@
 package android.telephony;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
-import android.text.TextUtils;
+import android.telephony.cdma.CdmaCellLocation;
 
 import java.util.Objects;
 
@@ -74,6 +75,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public CellIdentityCdma(int nid, int sid, int bid, int lon, int lat) {
         this(nid, sid, bid, lon, lat, null, null);
     }
@@ -176,6 +178,18 @@
                 super.hashCode());
     }
 
+    /** @hide */
+    @Override
+    public CdmaCellLocation asCellLocation() {
+        CdmaCellLocation cl = new CdmaCellLocation();
+        int bsid = mBasestationId != Integer.MAX_VALUE ? mBasestationId : -1;
+        int sid = mSystemId != Integer.MAX_VALUE ? mSystemId : -1;
+        int nid = mNetworkId != Integer.MAX_VALUE ? mNetworkId : -1;
+        // lat and long already use Integer.MAX_VALUE for invalid/unknown
+        cl.setCellLocationData(bsid, mLatitude, mLongitude, sid, nid);
+        return cl;
+    }
+
     @Override
     public boolean equals(Object other) {
         if (this == other) {
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 4031254..cb9dbf3 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -17,7 +17,9 @@
 package android.telephony;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
+import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
 
 import java.util.Objects;
@@ -34,13 +36,16 @@
     // 16-bit GSM Cell Identity described in TS 27.007, 0..65535
     private final int mCid;
     // 16-bit GSM Absolute RF Channel Number
+    @UnsupportedAppUsage
     private final int mArfcn;
     // 6-bit Base Station Identity Code
+    @UnsupportedAppUsage
     private final int mBsic;
 
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public CellIdentityGsm() {
         super(TAG, CellInfo.TYPE_GSM, null, null, null, null);
         mLac = Integer.MAX_VALUE;
@@ -194,6 +199,17 @@
         return Integer.MAX_VALUE;
     }
 
+    /** @hide */
+    @Override
+    public GsmCellLocation asCellLocation() {
+        GsmCellLocation cl = new GsmCellLocation();
+        int lac = mLac != Integer.MAX_VALUE ? mLac : -1;
+        int cid = mCid != Integer.MAX_VALUE ? mCid : -1;
+        cl.setLacAndCid(lac, cid);
+        cl.setPsc(-1);
+        return cl;
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(mLac, mCid, super.hashCode());
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 5257372..b44e891 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -17,7 +17,9 @@
 package android.telephony;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
+import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
 
 import java.util.Objects;
@@ -36,6 +38,7 @@
     // 16-bit tracking area code
     private final int mTac;
     // 18-bit Absolute RF Channel Number
+    @UnsupportedAppUsage
     private final int mEarfcn;
     // cell bandwidth, in kHz
     private final int mBandwidth;
@@ -43,6 +46,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public CellIdentityLte() {
         super(TAG, CellInfo.TYPE_LTE, null, null, null, null);
         mCi = Integer.MAX_VALUE;
@@ -62,6 +66,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac) {
         this(ci, pci, tac, Integer.MAX_VALUE, Integer.MAX_VALUE, String.valueOf(mcc),
                 String.valueOf(mnc), null, null);
@@ -196,6 +201,28 @@
         return mEarfcn;
     }
 
+    /**
+     * A hack to allow tunneling of LTE information via GsmCellLocation
+     * so that older Network Location Providers can return some information
+     * on LTE only networks, see bug 9228974.
+     *
+     * The tunnel'd LTE information is returned as follows:
+     *   LAC = TAC field
+     *   CID = CI field
+     *   PSC = 0.
+     *
+     * @hide
+     */
+    @Override
+    public GsmCellLocation asCellLocation() {
+        GsmCellLocation cl = new GsmCellLocation();
+        int tac = mTac != Integer.MAX_VALUE ? mTac : -1;
+        int cid = mCi != Integer.MAX_VALUE ? mCi : -1;
+        cl.setLacAndCid(tac, cid);
+        cl.setPsc(0);
+        return cl;
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(mCi, mPci, mTac, super.hashCode());
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 21b9601..5a9e474 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -17,6 +17,7 @@
 package android.telephony;
 
 import android.os.Parcel;
+import android.telephony.gsm.GsmCellLocation;
 
 import java.util.Objects;
 
@@ -134,6 +135,17 @@
         return mUarfcn;
     }
 
+    /** @hide */
+    @Override
+    public GsmCellLocation asCellLocation() {
+        GsmCellLocation cl = new GsmCellLocation();
+        int lac = mLac != Integer.MAX_VALUE ? mLac : -1;
+        int cid = mCid != Integer.MAX_VALUE ? mCid : -1;
+        cl.setLacAndCid(lac, cid);
+        cl.setPsc(-1); // There is no PSC for TD-SCDMA; not using this for CPI to stem shenanigans
+        return cl;
+    }
+
     @Override
     public boolean equals(Object other) {
         if (this == other) {
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index a4ac8e3..727d990 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -17,7 +17,9 @@
 package android.telephony;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
+import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
 
 import java.util.Objects;
@@ -36,6 +38,7 @@
     // 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511
     private final int mPsc;
     // 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.4
+    @UnsupportedAppUsage
     private final int mUarfcn;
 
     /**
@@ -189,6 +192,19 @@
         return mUarfcn;
     }
 
+    /** @hide */
+    @Override
+    public GsmCellLocation asCellLocation() {
+        GsmCellLocation cl = new GsmCellLocation();
+        int lac = mLac != Integer.MAX_VALUE ? mLac : -1;
+        int cid = mCid != Integer.MAX_VALUE ? mCid : -1;
+        int psc = mPsc != Integer.MAX_VALUE ? mPsc : -1;
+        cl.setLacAndCid(lac, cid);
+        cl.setPsc(psc);
+
+        return cl;
+    }
+
     @Override
     public boolean equals(Object other) {
         if (this == other) {
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index 6b320f4..4fe1b01 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -70,14 +71,19 @@
     // Type to distinguish where time stamp gets recorded.
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final int TIMESTAMP_TYPE_UNKNOWN = 0;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int TIMESTAMP_TYPE_ANTENNA = 1;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int TIMESTAMP_TYPE_MODEM = 2;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int TIMESTAMP_TYPE_OEM_RIL = 3;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int TIMESTAMP_TYPE_JAVA_RIL = 4;
 
     /** @hide */
@@ -184,6 +190,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getTimeStampType() {
         return mTimeStampType;
     }
@@ -223,6 +230,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static String timeStampTypeToString(int type) {
         switch (type) {
             case 1:
diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java
index 8b8d1bb..f67733d 100644
--- a/telephony/java/android/telephony/CellInfoCdma.java
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Rlog;
@@ -32,6 +33,7 @@
     private CellSignalStrengthCdma mCellSignalStrengthCdma;
 
     /** @hide */
+    @UnsupportedAppUsage
     public CellInfoCdma() {
         super();
         mCellIdentityCdma = new CellIdentityCdma();
@@ -39,6 +41,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public CellInfoCdma(CellInfoCdma ci) {
         super(ci);
         this.mCellIdentityCdma = ci.mCellIdentityCdma.copy();
@@ -50,6 +53,7 @@
         return mCellIdentityCdma;
     }
     /** @hide */
+    @UnsupportedAppUsage
     public void setCellIdentity(CellIdentityCdma cid) {
         mCellIdentityCdma = cid;
     }
diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java
index f7af1b2..7211de1 100644
--- a/telephony/java/android/telephony/CellInfoGsm.java
+++ b/telephony/java/android/telephony/CellInfoGsm.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Rlog;
@@ -32,6 +33,7 @@
     private CellSignalStrengthGsm mCellSignalStrengthGsm;
 
     /** @hide */
+    @UnsupportedAppUsage
     public CellInfoGsm() {
         super();
         mCellIdentityGsm = new CellIdentityGsm();
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index 97d856e..389f643 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Rlog;
@@ -32,6 +33,7 @@
     private CellSignalStrengthLte mCellSignalStrengthLte;
 
     /** @hide */
+    @UnsupportedAppUsage
     public CellInfoLte() {
         super();
         mCellIdentityLte = new CellIdentityLte();
@@ -51,6 +53,7 @@
         return mCellIdentityLte;
     }
     /** @hide */
+    @UnsupportedAppUsage
     public void setCellIdentity(CellIdentityLte cid) {
         if (DBG) log("setCellIdentity: " + cid);
         mCellIdentityLte = cid;
@@ -62,6 +65,7 @@
         return mCellSignalStrengthLte;
     }
     /** @hide */
+    @UnsupportedAppUsage
     public void setCellSignalStrength(CellSignalStrengthLte css) {
         if (DBG) log("setCellSignalStrength: " + css);
         mCellSignalStrengthLte = css;
diff --git a/telephony/java/android/telephony/CellLocation.java b/telephony/java/android/telephony/CellLocation.java
index 5bcaa6e..0133153 100644
--- a/telephony/java/android/telephony/CellLocation.java
+++ b/telephony/java/android/telephony/CellLocation.java
@@ -20,6 +20,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 
+import android.annotation.UnsupportedAppUsage;
 import android.telephony.cdma.CdmaCellLocation;
 import android.telephony.gsm.GsmCellLocation;
 import com.android.internal.telephony.ITelephony;
@@ -57,6 +58,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static CellLocation newFromBundle(Bundle bundle) {
         // TelephonyManager.getDefault().getCurrentPhoneType() handles the case when
         // ITelephony interface is not up yet.
@@ -73,11 +75,13 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract void fillInNotifierBundle(Bundle bundle);
 
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract boolean isEmpty();
 
     /**
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index cff159b..1e8d119 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Rlog;
@@ -34,11 +35,15 @@
     private static final int GSM_SIGNAL_STRENGTH_GOOD = 8;
     private static final int GSM_SIGNAL_STRENGTH_MODERATE = 5;
 
+    @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 mTimingAdvance; // range from 0-219 or Integer.MAX_VALUE if unknown
 
     /** @hide */
+    @UnsupportedAppUsage
     public CellSignalStrengthGsm() {
         setDefaultValues();
     }
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 2f059f4..ed7d4b2 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Rlog;
@@ -30,14 +31,21 @@
     private static final String LOG_TAG = "CellSignalStrengthLte";
     private static final boolean DBG = false;
 
+    @UnsupportedAppUsage
     private int mSignalStrength;
+    @UnsupportedAppUsage
     private int mRsrp;
+    @UnsupportedAppUsage
     private int mRsrq;
+    @UnsupportedAppUsage
     private int mRssnr;
+    @UnsupportedAppUsage
     private int mCqi;
+    @UnsupportedAppUsage
     private int mTimingAdvance;
 
     /** @hide */
+    @UnsupportedAppUsage
     public CellSignalStrengthLte() {
         setDefaultValues();
     }
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index 21cf0be..66e0882 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Rlog;
@@ -34,8 +35,10 @@
     private static final int WCDMA_SIGNAL_STRENGTH_GOOD = 8;
     private static final int WCDMA_SIGNAL_STRENGTH_MODERATE = 5;
 
+    @UnsupportedAppUsage
     private int mSignalStrength; // in ASU; Valid values are (0-31, 99) as defined in TS 27.007 8.5
                                  // or Integer.MAX_VALUE if unknown
+    @UnsupportedAppUsage
     private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
                                // Integer.MAX_VALUE if unknown
     private int mRscp; // bit error rate (0-96, 255) as defined in TS 27.007 8.69 or
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 4fa304a..ee5cdc2 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * Contains disconnect call causes generated by the framework and the RIL.
  * @hide
@@ -329,6 +331,7 @@
     }
 
     /** Returns descriptive string for the specified disconnect cause. */
+    @UnsupportedAppUsage
     public static String toString(int cause) {
         switch (cause) {
         case NOT_DISCONNECTED:
diff --git a/telephony/java/android/telephony/ModemInfo.java b/telephony/java/android/telephony/ModemInfo.java
new file mode 100644
index 0000000..564effe
--- /dev/null
+++ b/telephony/java/android/telephony/ModemInfo.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Information of a single logical modem indicating
+ * its id, supported rats and whether it supports voice or data, etc.
+ * @hide
+ */
+public class ModemInfo implements Parcelable {
+    public final int modemId;
+    public final int rat; /* bitset */
+    public final boolean isVoiceSupported;
+    public final boolean isDataSupported;
+
+    public ModemInfo(int modemId, int rat, boolean isVoiceSupported, boolean isDataSupported) {
+        this.modemId = modemId;
+        this.rat = rat;
+        this.isVoiceSupported = isVoiceSupported;
+        this.isDataSupported = isDataSupported;
+    }
+
+    public ModemInfo(Parcel in) {
+        modemId = in.readInt();
+        rat = in.readInt();
+        isVoiceSupported = in.readBoolean();
+        isDataSupported = in.readBoolean();
+    }
+
+    @Override
+    public String toString() {
+        return "modemId=" + modemId + " rat=" + rat + " isVoiceSupported:" + isVoiceSupported
+                + " isDataSupported:" + isDataSupported;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(modemId, rat, isVoiceSupported, isDataSupported);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || !(o instanceof ModemInfo) || hashCode() != o.hashCode()) {
+            return false;
+        }
+
+        if (this == o) {
+            return true;
+        }
+
+        ModemInfo s = (ModemInfo) o;
+
+        return (modemId == s.modemId
+                && rat == s.rat
+                && isVoiceSupported == s.isVoiceSupported
+                && isDataSupported == s.isDataSupported);
+    }
+
+    /**
+     * {@link Parcelable#describeContents}
+     */
+    public @ContentsFlags int describeContents() {
+        return 0;
+    }
+
+    /**
+     * {@link Parcelable#writeToParcel}
+     */
+    public void writeToParcel(Parcel dest, @WriteFlags int flags) {
+        dest.writeInt(modemId);
+        dest.writeInt(rat);
+        dest.writeBoolean(isVoiceSupported);
+        dest.writeBoolean(isDataSupported);
+    }
+
+    public static final Parcelable.Creator<ModemInfo> CREATOR = new Parcelable.Creator() {
+        public ModemInfo createFromParcel(Parcel in) {
+            return new ModemInfo(in);
+        }
+
+        public ModemInfo[] newArray(int size) {
+            return new ModemInfo[size];
+        }
+    };
+}
diff --git a/telephony/java/android/telephony/NeighboringCellInfo.java b/telephony/java/android/telephony/NeighboringCellInfo.java
index b7ccee5..8e99518 100644
--- a/telephony/java/android/telephony/NeighboringCellInfo.java
+++ b/telephony/java/android/telephony/NeighboringCellInfo.java
@@ -24,6 +24,7 @@
 import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
 import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -47,24 +48,29 @@
      * In GSM, mRssi is the Received RSSI;
      * In UMTS, mRssi is the Level index of CPICH Received Signal Code Power
      */
+    @UnsupportedAppUsage
     private int mRssi;
     /**
      * CID in 16 bits format in GSM. Return UNKNOWN_CID in UMTS and CMDA.
      */
+    @UnsupportedAppUsage
     private int mCid;
     /**
      * LAC in 16 bits format in GSM. Return UNKNOWN_CID in UMTS and CMDA.
      */
+    @UnsupportedAppUsage
     private int mLac;
     /**
      * Primary Scrambling Code in 9 bits format in UMTS
      * Return UNKNOWN_CID in GSM and CMDA.
      */
+    @UnsupportedAppUsage
     private int mPsc;
     /**
      * Radio network type, value is one of following
      * TelephonyManager.NETWORK_TYPE_XXXXXX.
      */
+    @UnsupportedAppUsage
     private int mNetworkType;
 
     /**
diff --git a/telephony/java/android/telephony/PhoneCapability.aidl b/telephony/java/android/telephony/PhoneCapability.aidl
new file mode 100644
index 0000000..5de8d4a
--- /dev/null
+++ b/telephony/java/android/telephony/PhoneCapability.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.telephony;
+
+parcelable PhoneCapability;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java
new file mode 100644
index 0000000..2ebfa53
--- /dev/null
+++ b/telephony/java/android/telephony/PhoneCapability.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Define capability of a modem group. That is, the capabilities
+ * are shared between those modems defined by list of modem IDs.
+ * @hide
+ */
+public class PhoneCapability implements Parcelable {
+    public final int maxActiveVoiceCalls;
+    public final int maxActiveData;
+    public final int max5G;
+    public final List<ModemInfo> logicalModemList;
+
+    public PhoneCapability(int maxActiveVoiceCalls, int maxActiveData, int max5G,
+            List<ModemInfo> logicalModemList) {
+        this.maxActiveVoiceCalls = maxActiveVoiceCalls;
+        this.maxActiveData = maxActiveData;
+        this.max5G = max5G;
+        // Make sure it's not null.
+        this.logicalModemList = logicalModemList == null ? new ArrayList<>() : logicalModemList;
+    }
+
+    @Override
+    public String toString() {
+        return "maxActiveVoiceCalls=" + maxActiveVoiceCalls + " maxActiveData=" + maxActiveData
+                + " max5G=" + max5G + "logicalModemList:"
+                + Arrays.toString(logicalModemList.toArray());
+    }
+
+    private PhoneCapability(Parcel in) {
+        maxActiveVoiceCalls = in.readInt();
+        maxActiveData = in.readInt();
+        max5G = in.readInt();
+        logicalModemList = new ArrayList<>();
+        in.readList(logicalModemList, ModemInfo.class.getClassLoader());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(maxActiveVoiceCalls, maxActiveData, max5G, logicalModemList);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || !(o instanceof PhoneCapability) || hashCode() != o.hashCode()) {
+            return false;
+        }
+
+        if (this == o) {
+            return true;
+        }
+
+        PhoneCapability s = (PhoneCapability) o;
+
+        return (maxActiveVoiceCalls == s.maxActiveVoiceCalls
+                && maxActiveData == s.maxActiveData
+                && max5G == s.max5G
+                && logicalModemList.equals(s.logicalModemList));
+    }
+
+    /**
+     * {@link Parcelable#describeContents}
+     */
+    public @Parcelable.ContentsFlags int describeContents() {
+        return 0;
+    }
+
+    /**
+     * {@link Parcelable#writeToParcel}
+     */
+    public void writeToParcel(Parcel dest, @Parcelable.WriteFlags int flags) {
+        dest.writeInt(maxActiveVoiceCalls);
+        dest.writeInt(maxActiveData);
+        dest.writeInt(max5G);
+        dest.writeList(logicalModemList);
+    }
+
+    public static final Parcelable.Creator<PhoneCapability> CREATOR = new Parcelable.Creator() {
+        public PhoneCapability createFromParcel(Parcel in) {
+            return new PhoneCapability(in);
+        }
+
+        public PhoneCapability[] newArray(int size) {
+            return new PhoneCapability[size];
+        }
+    };
+}
diff --git a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
index f7dee99..ac6bcaa 100644
--- a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
+++ b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
@@ -19,6 +19,7 @@
 import com.android.i18n.phonenumbers.AsYouTypeFormatter;
 import com.android.i18n.phonenumbers.PhoneNumberUtil;
 
+import android.annotation.UnsupportedAppUsage;
 import android.telephony.PhoneNumberUtils;
 import android.text.Editable;
 import android.text.Selection;
@@ -50,6 +51,7 @@
      */
     private boolean mStopFormatting;
 
+    @UnsupportedAppUsage
     private AsYouTypeFormatter mFormatter;
 
     /**
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index fadfc91..f6e8d34 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -23,6 +23,7 @@
 import com.android.i18n.phonenumbers.ShortNumberInfo;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
@@ -279,6 +280,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static String extractNetworkPortionAlt(String phoneNumber) {
         if (phoneNumber == null) {
             return null;
@@ -352,6 +354,7 @@
      * RFC 3601 says pause is 'p' and tonewait is 'w'.
      * @hide
      */
+    @UnsupportedAppUsage
     public static String convertPreDial(String phoneNumber) {
         if (phoneNumber == null) {
             return null;
@@ -464,6 +467,7 @@
     /**
      * @hide only for testing.
      */
+    @UnsupportedAppUsage
     public static boolean compare(String a, String b, boolean useStrictComparation) {
         return (useStrictComparation ? compareStrictly(a, b) : compareLoosely(a, b));
     }
@@ -482,6 +486,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean
     compareLoosely(String a, String b) {
         int ia, ib;
@@ -579,6 +584,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean
     compareStrictly(String a, String b) {
         return compareStrictly(a, b, true);
@@ -587,6 +593,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean
     compareStrictly(String a, String b, boolean acceptInvalidCCCPrefix) {
         if (a == null || b == null) {
@@ -1260,6 +1267,7 @@
      * @deprecated Use link #formatNumber(String phoneNumber, String defaultCountryIso) instead
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static String formatNumber(String source, int defaultFormattingType) {
         SpannableStringBuilder text = new SpannableStringBuilder(source);
         formatNumber(text, defaultFormattingType);
@@ -1720,6 +1728,7 @@
     //
     // However, in order to loose match 650-555-1212 and 555-1212, we need to set the min match
     // to 7.
+    @UnsupportedAppUsage
     static final int MIN_MATCH = 7;
 
     /**
@@ -1744,6 +1753,7 @@
      *         listed in the RIL / SIM, otherwise return false.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isEmergencyNumber(int subId, String number) {
         // Return true only if the specified number *exactly* matches
         // one of the emergency numbers listed by the RIL / SIM.
@@ -1794,6 +1804,7 @@
      *         same digits as any of those emergency numbers.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isPotentialEmergencyNumber(int subId, String number) {
         // Check against the emergency numbers listed by the RIL / SIM,
         // and *don't* require an exact match.
@@ -1858,6 +1869,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isEmergencyNumber(String number, String defaultCountryIso) {
             return isEmergencyNumber(getDefaultVoiceSubId(), number, defaultCountryIso);
     }
@@ -2081,6 +2093,7 @@
      * is currently in.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isLocalEmergencyNumber(Context context, int subId, String number) {
         return isLocalEmergencyNumberInternal(subId, number,
                                               context,
@@ -2109,6 +2122,7 @@
      * @see android.location.CountryDetector
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isPotentialLocalEmergencyNumber(Context context, String number) {
         return isPotentialLocalEmergencyNumber(context, getDefaultVoiceSubId(), number);
     }
@@ -2135,6 +2149,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isPotentialLocalEmergencyNumber(Context context, int subId,
             String number) {
         return isLocalEmergencyNumberInternal(subId, number,
@@ -2244,6 +2259,7 @@
      * to read the VM number.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isVoiceMailNumber(Context context, int subId, String number) {
         String vmNumber, mdn;
         try {
@@ -2390,6 +2406,7 @@
      *
      * @hide TODO: pending API Council approval
      */
+    @UnsupportedAppUsage
     public static String cdmaCheckAndProcessPlusCode(String dialStr) {
         if (!TextUtils.isEmpty(dialStr)) {
             if (isReallyDialable(dialStr.charAt(0)) &&
@@ -2569,6 +2586,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static CharSequence ttsSpanAsPhoneNumber(CharSequence phoneNumber) {
         return createTtsSpannable(phoneNumber);
     }
@@ -2680,6 +2698,7 @@
      * i.e. NXX-NXX-XXXX, N is any digit 2-9 and X is any digit 0-9
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isNanp (String dialStr) {
         boolean retVal = false;
         if (dialStr != null) {
@@ -2727,6 +2746,7 @@
      * @param number
      * @return true if number contains @
      */
+    @UnsupportedAppUsage
     public static boolean isUriNumber(String number) {
         // Note we allow either "@" or "%40" to indicate a URI, in case
         // the passed-in string is URI-escaped.  (Neither "@" nor "%40"
@@ -2744,6 +2764,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static String getUsernameFromUriNumber(String number) {
         // The delimiter between username and domain name can be
         // either "@" or "%40" (the URI-escaped equivalent.)
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 8420165..bd6a59d 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -17,16 +17,16 @@
 package android.telephony;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.telecom.TelecomManager;
 
 import com.android.internal.telephony.IPhoneStateListener;
 
-import java.util.List;
 import java.lang.ref.WeakReference;
+import java.util.List;
 
 /**
  * A listener class for monitoring changes in specific telephony states
@@ -171,6 +171,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int LISTEN_PRECISE_CALL_STATE                       = 0x00000800;
 
     /**
@@ -271,11 +272,20 @@
      */
     public static final int LISTEN_PHYSICAL_CHANNEL_CONFIGURATION          = 0x00100000;
 
+    /**
+     *  Listen for changes to the phone capability.
+     *
+     *  @see #onPhoneCapabilityChanged
+     *  @hide
+     */
+    public static final int LISTEN_PHONE_CAPABILITY_CHANGE                 = 0x00200000;
+
     /*
      * Subscription used to listen to the phone state changes
      * @hide
      */
     /** @hide */
+    @UnsupportedAppUsage
     protected Integer mSubId;
 
     private final Handler mHandler;
@@ -293,6 +303,7 @@
      * using a particular non-null Looper.
      * @hide
      */
+    @UnsupportedAppUsage
     public PhoneStateListener(Looper looper) {
         this(null, looper);
     }
@@ -303,6 +314,7 @@
      * own non-null Looper use PhoneStateListener(int subId, Looper looper) below.
      * @hide
      */
+    @UnsupportedAppUsage
     public PhoneStateListener(Integer subId) {
         this(subId, Looper.myLooper());
     }
@@ -312,6 +324,7 @@
      * and non-null Looper.
      * @hide
      */
+    @UnsupportedAppUsage
     public PhoneStateListener(Integer subId, Looper looper) {
         if (DBG) log("ctor: subId=" + subId + " looper=" + looper);
         mSubId = subId;
@@ -389,6 +402,10 @@
                         PhoneStateListener.this.onPhysicalChannelConfigurationChanged(
                                 (List<PhysicalChannelConfig>)msg.obj);
                         break;
+                    case LISTEN_PHONE_CAPABILITY_CHANGE:
+                        PhoneStateListener.this.onPhoneCapabilityChanged(
+                                (PhoneCapability) msg.obj);
+                        break;
                 }
             }
         };
@@ -515,6 +532,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void onOtaspChanged(int otaspMode) {
         // default implementation empty
     }
@@ -532,6 +550,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void onPreciseCallStateChanged(PreciseCallState callState) {
         // default implementation empty
     }
@@ -541,6 +560,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void onPreciseDataConnectionStateChanged(
             PreciseDataConnectionState dataConnectionState) {
         // default implementation empty
@@ -551,6 +571,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void onDataConnectionRealTimeInfoChanged(
             DataConnectionRealTimeInfo dcRtInfo) {
         // default implementation empty
@@ -562,6 +583,7 @@
      * @param stateInfo is the current LTE network information
      * @hide
      */
+    @UnsupportedAppUsage
     public void onVoLteServiceStateChanged(VoLteServiceState stateInfo) {
     }
 
@@ -608,11 +630,22 @@
      * @param rawData is the byte array of the OEM hook raw data.
      * @hide
      */
+    @UnsupportedAppUsage
     public void onOemHookRawEvent(byte[] rawData) {
         // default implementation empty
     }
 
     /**
+     * Callback invoked when phone capability changes. Requires
+     * the READ_PRIVILEGED_PHONE_STATE permission.
+     * @param capability the new phone capability
+     * @hide
+     */
+    public void onPhoneCapabilityChanged(PhoneCapability capability) {
+        // default implementation empty
+    }
+
+    /**
      * Callback invoked when telephony has received notice from a carrier
      * app that a network action that could result in connectivity loss
      * has been requested by an app using
@@ -739,8 +772,13 @@
         public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) {
             send(LISTEN_PHYSICAL_CHANNEL_CONFIGURATION, 0, 0, configs);
         }
+
+        public void onPhoneCapabilityChanged(PhoneCapability capability) {
+            send(LISTEN_PHONE_CAPABILITY_CHANGE, 0, 0, capability);
+        }
     }
 
+    @UnsupportedAppUsage
     IPhoneStateListener callback = new IPhoneStateListenerStub(this);
 
     private void log(String s) {
diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java
index f246416..ed5c26a 100644
--- a/telephony/java/android/telephony/PreciseCallState.java
+++ b/telephony/java/android/telephony/PreciseCallState.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.DisconnectCause;
@@ -71,6 +72,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public PreciseCallState(int ringingCall, int foregroundCall, int backgroundCall,
             int disconnectCause, int preciseDisconnectCause) {
         mRingingCallState = ringingCall;
@@ -113,6 +115,7 @@
      * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
      * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
      */
+    @UnsupportedAppUsage
     public int getRingingCallState() {
         return mRingingCallState;
     }
@@ -131,6 +134,7 @@
      * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
      * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
      */
+    @UnsupportedAppUsage
     public int getForegroundCallState() {
         return mForegroundCallState;
     }
@@ -149,6 +153,7 @@
      * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
      * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
      */
+    @UnsupportedAppUsage
     public int getBackgroundCallState() {
         return mBackgroundCallState;
     }
@@ -195,6 +200,7 @@
      * @see DisconnectCause#CDMA_ACCESS_BLOCKED
      * @see DisconnectCause#ERROR_UNSPECIFIED
      */
+    @UnsupportedAppUsage
     public int getDisconnectCause() {
         return mDisconnectCause;
     }
@@ -233,6 +239,7 @@
      * @see PreciseDisconnectCause#CDMA_ACCESS_BLOCKED
      * @see PreciseDisconnectCause#ERROR_UNSPECIFIED
      */
+    @UnsupportedAppUsage
     public int getPreciseDisconnectCause() {
         return mPreciseDisconnectCause;
     }
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index 31c9a9e..b258f52 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.TelephonyManager;
@@ -53,6 +54,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public PreciseDataConnectionState(int state, int networkType,
             String apnType, String apn, String reason,
             LinkProperties linkProperties, String failCause) {
@@ -95,6 +97,7 @@
      * @see TelephonyManager#DATA_CONNECTED
      * @see TelephonyManager#DATA_SUSPENDED
      */
+    @UnsupportedAppUsage
     public int getDataConnectionState() {
         return mState;
     }
@@ -119,6 +122,7 @@
      * @see TelephonyManager#NETWORK_TYPE_EHRPD
      * @see TelephonyManager#NETWORK_TYPE_HSPAP
      */
+    @UnsupportedAppUsage
     public int getDataConnectionNetworkType() {
         return mNetworkType;
     }
@@ -126,6 +130,7 @@
     /**
      * Get data connection APN type
      */
+    @UnsupportedAppUsage
     public String getDataConnectionAPNType() {
         return mAPNType;
     }
@@ -133,6 +138,7 @@
     /**
      * Get data connection APN.
      */
+    @UnsupportedAppUsage
     public String getDataConnectionAPN() {
         return mAPN;
     }
@@ -140,6 +146,7 @@
     /**
      * Get data connection change reason.
      */
+    @UnsupportedAppUsage
     public String getDataConnectionChangeReason() {
         return mReason;
     }
@@ -147,6 +154,7 @@
     /**
      * Get the properties of the network link.
      */
+    @UnsupportedAppUsage
     public LinkProperties getDataConnectionLinkProperties() {
         return mLinkProperties;
     }
@@ -154,6 +162,7 @@
     /**
      * Get data connection fail cause, in case there was a failure.
      */
+    @UnsupportedAppUsage
     public String getDataConnectionFailCause() {
         return mFailCause;
     }
diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java
index d657bae..1d79988 100644
--- a/telephony/java/android/telephony/RadioAccessFamily.java
+++ b/telephony/java/android/telephony/RadioAccessFamily.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -77,6 +78,7 @@
      *        in RadioAccessFamily. It's a bit mask value to represent
      *        the support type.
      */
+    @UnsupportedAppUsage
     public RadioAccessFamily(int phoneId, int radioAccessFamily) {
         mPhoneId = phoneId;
         mRadioAccessFamily = radioAccessFamily;
@@ -87,6 +89,7 @@
      *
      * @return phone ID
      */
+    @UnsupportedAppUsage
     public int getPhoneId() {
         return mPhoneId;
     }
@@ -96,6 +99,7 @@
      *
      * @return radio access family
      */
+    @UnsupportedAppUsage
     public int getRadioAccessFamily() {
         return mRadioAccessFamily;
     }
@@ -150,6 +154,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     public static int getRafFromNetworkType(int type) {
         int raf;
 
@@ -263,6 +268,7 @@
         return TelephonyManager.NETWORK_CLASS_UNKNOWN;
     }
 
+    @UnsupportedAppUsage
     public static int getNetworkTypeFromRaf(int raf) {
         int type;
 
diff --git a/telephony/java/android/telephony/Rlog.java b/telephony/java/android/telephony/Rlog.java
index e0b46e1..5f2fa33 100644
--- a/telephony/java/android/telephony/Rlog.java
+++ b/telephony/java/android/telephony/Rlog.java
@@ -20,6 +20,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.Base64;
 
 import java.security.MessageDigest;
@@ -38,6 +39,7 @@
     private Rlog() {
     }
 
+    @UnsupportedAppUsage
     public static int v(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.VERBOSE, tag, msg);
     }
@@ -47,28 +49,34 @@
                 msg + '\n' + Log.getStackTraceString(tr));
     }
 
+    @UnsupportedAppUsage
     public static int d(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.DEBUG, tag, msg);
     }
 
+    @UnsupportedAppUsage
     public static int d(String tag, String msg, Throwable tr) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.DEBUG, tag,
                 msg + '\n' + Log.getStackTraceString(tr));
     }
 
+    @UnsupportedAppUsage
     public static int i(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.INFO, tag, msg);
     }
 
+    @UnsupportedAppUsage
     public static int i(String tag, String msg, Throwable tr) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.INFO, tag,
                 msg + '\n' + Log.getStackTraceString(tr));
     }
 
+    @UnsupportedAppUsage
     public static int w(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.WARN, tag, msg);
     }
 
+    @UnsupportedAppUsage
     public static int w(String tag, String msg, Throwable tr) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.WARN, tag,
                 msg + '\n' + Log.getStackTraceString(tr));
@@ -78,10 +86,12 @@
         return Log.println_native(Log.LOG_ID_RADIO, Log.WARN, tag, Log.getStackTraceString(tr));
     }
 
+    @UnsupportedAppUsage
     public static int e(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.ERROR, tag, msg);
     }
 
+    @UnsupportedAppUsage
     public static int e(String tag, String msg, Throwable tr) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.ERROR, tag,
                 msg + '\n' + Log.getStackTraceString(tr));
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 9e8529e..2ee1a09 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -169,6 +170,7 @@
      * IWLAN
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int RIL_RADIO_TECHNOLOGY_IWLAN = 18;
 
     /**
@@ -233,6 +235,7 @@
     private String mDataOperatorAlphaLong;
     private String mDataOperatorAlphaShort;
     private String mDataOperatorNumeric;
+    @UnsupportedAppUsage
     private boolean mIsManualNetworkSelection;
 
     private boolean mIsEmergencyOnly;
@@ -240,16 +243,24 @@
     private int mRilVoiceRadioTechnology;
     private int mRilDataRadioTechnology;
 
+    @UnsupportedAppUsage
     private boolean mCssIndicator;
+    @UnsupportedAppUsage
     private int mNetworkId;
+    @UnsupportedAppUsage
     private int mSystemId;
+    @UnsupportedAppUsage
     private int mCdmaRoamingIndicator;
+    @UnsupportedAppUsage
     private int mCdmaDefaultRoamingIndicator;
+    @UnsupportedAppUsage
     private int mCdmaEriIconIndex;
+    @UnsupportedAppUsage
     private int mCdmaEriIconMode;
 
     private boolean mIsDataRoamingFromRegistration;
 
+    @UnsupportedAppUsage
     private boolean mIsUsingCarrierAggregation;
 
     private int mChannelNumber;
@@ -294,6 +305,7 @@
      * @return newly created ServiceState
      * @hide
      */
+    @UnsupportedAppUsage
     public static ServiceState newFromBundle(Bundle m) {
         ServiceState ret;
         ret = new ServiceState();
@@ -442,6 +454,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getVoiceRegState() {
         return mVoiceRegState;
     }
@@ -456,6 +469,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getDataRegState() {
         return mDataRegState;
     }
@@ -516,6 +530,7 @@
      * @return roaming status
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean getVoiceRoaming() {
         return mVoiceRoamingType != ROAMING_TYPE_NOT_ROAMING;
     }
@@ -525,6 +540,7 @@
      * @return roaming type
      * @hide
      */
+    @UnsupportedAppUsage
     public int getVoiceRoamingType() {
         return mVoiceRoamingType;
     }
@@ -534,6 +550,7 @@
      * @return roaming type
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean getDataRoaming() {
         return mDataRoamingType != ROAMING_TYPE_NOT_ROAMING;
     }
@@ -545,6 +562,7 @@
      * once the data registration phase has completed.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDataRoamingFromRegistration(boolean dataRoaming) {
         mIsDataRoamingFromRegistration = dataRoaming;
     }
@@ -563,6 +581,7 @@
      * @return roaming type
      * @hide
      */
+    @UnsupportedAppUsage
     public int getDataRoamingType() {
         return mDataRoamingType;
     }
@@ -570,6 +589,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isEmergencyOnly() {
         return mIsEmergencyOnly;
     }
@@ -577,6 +597,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public int getCdmaRoamingIndicator(){
         return this.mCdmaRoamingIndicator;
     }
@@ -584,6 +605,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public int getCdmaDefaultRoamingIndicator(){
         return this.mCdmaDefaultRoamingIndicator;
     }
@@ -591,6 +613,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public int getCdmaEriIconIndex() {
         return this.mCdmaEriIconIndex;
     }
@@ -598,6 +621,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public int getCdmaEriIconMode() {
         return this.mCdmaEriIconMode;
     }
@@ -619,6 +643,7 @@
      * @return long name of operator
      * @hide
      */
+    @UnsupportedAppUsage
     public String getVoiceOperatorAlphaLong() {
         return mVoiceOperatorAlphaLong;
     }
@@ -648,6 +673,7 @@
      * @return short name of operator, null if unregistered or unknown
      * @hide
      */
+    @UnsupportedAppUsage
     public String getVoiceOperatorAlphaShort() {
         return mVoiceOperatorAlphaShort;
     }
@@ -657,6 +683,7 @@
      * @return short name of operator, null if unregistered or unknown
      * @hide
      */
+    @UnsupportedAppUsage
     public String getDataOperatorAlphaShort() {
         return mDataOperatorAlphaShort;
     }
@@ -700,6 +727,7 @@
      * @return numeric format of operator, null if unregistered or unknown
      * @hide
      */
+    @UnsupportedAppUsage
     public String getVoiceOperatorNumeric() {
         return mVoiceOperatorNumeric;
     }
@@ -709,6 +737,7 @@
      * @return numeric format of operator, null if unregistered or unknown
      * @hide
      */
+    @UnsupportedAppUsage
     public String getDataOperatorNumeric() {
         return mDataOperatorNumeric;
     }
@@ -794,6 +823,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static String rilRadioTechnologyToString(int rt) {
         String rtString;
 
@@ -968,12 +998,14 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setVoiceRegState(int state) {
         mVoiceRegState = state;
         if (DBG) Rlog.d(LOG_TAG, "[ServiceState] setVoiceRegState=" + mVoiceRegState);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setDataRegState(int state) {
         mDataRegState = state;
         if (VDBG) Rlog.d(LOG_TAG, "[ServiceState] setDataRegState=" + mDataRegState);
@@ -997,21 +1029,25 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setVoiceRoaming(boolean roaming) {
         mVoiceRoamingType = (roaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setVoiceRoamingType(int type) {
         mVoiceRoamingType = type;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setDataRoaming(boolean dataRoaming) {
         mDataRoamingType = (dataRoaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setDataRoamingType(int type) {
         mDataRoamingType = type;
     }
@@ -1019,6 +1055,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setEmergencyOnly(boolean emergencyOnly) {
         mIsEmergencyOnly = emergencyOnly;
     }
@@ -1026,6 +1063,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCdmaRoamingIndicator(int roaming) {
         this.mCdmaRoamingIndicator = roaming;
     }
@@ -1033,6 +1071,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCdmaDefaultRoamingIndicator (int roaming) {
         this.mCdmaDefaultRoamingIndicator = roaming;
     }
@@ -1040,6 +1079,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCdmaEriIconIndex(int index) {
         this.mCdmaEriIconIndex = index;
     }
@@ -1047,6 +1087,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCdmaEriIconMode(int mode) {
         this.mCdmaEriIconMode = mode;
     }
@@ -1080,6 +1121,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setOperatorAlphaLong(String longName) {
         mVoiceOperatorAlphaLong = longName;
         mDataOperatorAlphaLong = longName;
@@ -1106,6 +1148,7 @@
      * @param b second obj
      * @return true if two objects equal or both are null
      */
+    @UnsupportedAppUsage
     private static boolean equalsHandlesNulls (Object a, Object b) {
         return (a == null) ? (b == null) : a.equals (b);
     }
@@ -1116,6 +1159,7 @@
      * @param m intent notifier map
      * @hide
      */
+    @UnsupportedAppUsage
     private void setFromNotifierBundle(Bundle m) {
         mVoiceRegState = m.getInt("voiceRegState");
         mDataRegState = m.getInt("dataRegState");
@@ -1149,6 +1193,7 @@
      * @param m intent notifier Bundle
      * @hide
      */
+    @UnsupportedAppUsage
     public void fillInNotifierBundle(Bundle m) {
         m.putInt("voiceRegState", mVoiceRegState);
         m.putInt("dataRegState", mDataRegState);
@@ -1221,6 +1266,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setCssIndicator(int css) {
         this.mCssIndicator = (css != 0);
     }
@@ -1233,10 +1279,12 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getRilVoiceRadioTechnology() {
         return this.mRilVoiceRadioTechnology;
     }
     /** @hide */
+    @UnsupportedAppUsage
     public int getRilDataRadioTechnology() {
         return this.mRilDataRadioTechnology;
     }
@@ -1245,6 +1293,7 @@
      * @Deprecated to be removed Q3 2013 use {@link #getRilDataRadioTechnology} or
      * {@link #getRilVoiceRadioTechnology}
      */
+    @UnsupportedAppUsage
     public int getRadioTechnology() {
         Rlog.e(LOG_TAG, "ServiceState.getRadioTechnology() DEPRECATED will be removed *******");
         return getRilDataRadioTechnology();
@@ -1374,16 +1423,19 @@
 
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getDataNetworkType() {
         return rilRadioTechnologyToNetworkType(mRilDataRadioTechnology);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getVoiceNetworkType() {
         return rilRadioTechnologyToNetworkType(mRilVoiceRadioTechnology);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getCssIndicator() {
         return this.mCssIndicator ? 1 : 0;
     }
@@ -1407,6 +1459,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static boolean isGsm(int radioTechnology) {
         return radioTechnology == RIL_RADIO_TECHNOLOGY_GPRS
                 || radioTechnology == RIL_RADIO_TECHNOLOGY_EDGE
@@ -1424,6 +1477,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static boolean isCdma(int radioTechnology) {
         return radioTechnology == RIL_RADIO_TECHNOLOGY_IS95A
                 || radioTechnology == RIL_RADIO_TECHNOLOGY_IS95B
@@ -1441,11 +1495,13 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static boolean bearerBitmapHasCdma(int radioTechnologyBitmap) {
         return (RIL_RADIO_CDMA_TECHNOLOGY_BITMASK & radioTechnologyBitmap) != 0;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static boolean bitmaskHasTech(int bearerBitmask, int radioTech) {
         if (bearerBitmask == 0) {
             return true;
@@ -1517,6 +1573,7 @@
      * voice SS. The voice SS is only used if it is IN_SERVICE (otherwise the base SS is returned).
      * @hide
      * */
+    @UnsupportedAppUsage
     public static ServiceState mergeServiceStates(ServiceState baseSs, ServiceState voiceSs) {
         if (voiceSs.mVoiceRegState != STATE_IN_SERVICE) {
             return baseSs;
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 95abb91..ed758a9 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -36,21 +37,27 @@
     private static final boolean DBG = false;
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN
             = TelephonyProtoEnums.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; // = 0
     /** @hide */
+    @UnsupportedAppUsage
     public static final int SIGNAL_STRENGTH_POOR
             = TelephonyProtoEnums.SIGNAL_STRENGTH_POOR; // = 1
     /** @hide */
+    @UnsupportedAppUsage
     public static final int SIGNAL_STRENGTH_MODERATE
             = TelephonyProtoEnums.SIGNAL_STRENGTH_MODERATE; // = 2
     /** @hide */
+    @UnsupportedAppUsage
     public static final int SIGNAL_STRENGTH_GOOD
             = TelephonyProtoEnums.SIGNAL_STRENGTH_GOOD; // = 3
     /** @hide */
+    @UnsupportedAppUsage
     public static final int SIGNAL_STRENGTH_GREAT
             = TelephonyProtoEnums.SIGNAL_STRENGTH_GREAT; // = 4
     /** @hide */
+    @UnsupportedAppUsage
     public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
     /** @hide */
     public static final String[] SIGNAL_STRENGTH_NAMES = {
@@ -75,24 +82,39 @@
     private static final String MEASUMENT_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
 
     /** 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
@@ -121,6 +143,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static SignalStrength newFromBundle(Bundle m) {
         SignalStrength ret;
         ret = new SignalStrength();
@@ -133,6 +156,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public SignalStrength() {
         this(true);
     }
@@ -145,6 +169,7 @@
      * @return newly created SignalStrength
      * @hide
      */
+    @UnsupportedAppUsage
     public SignalStrength(boolean gsmFlag) {
         mGsmSignalStrength = 99;
         mGsmBitErrorRate = -1;
@@ -247,6 +272,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public SignalStrength(SignalStrength s) {
         copyFrom(s);
     }
@@ -254,6 +280,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     protected void copyFrom(SignalStrength s) {
         mGsmSignalStrength = s.mGsmSignalStrength;
         mGsmBitErrorRate = s.mGsmBitErrorRate;
@@ -284,6 +311,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public SignalStrength(Parcel in) {
         if (DBG) log("Size of signalstrength parcel:" + in.dataSize());
 
@@ -351,6 +379,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<SignalStrength> CREATOR = new Parcelable.Creator() {
         public SignalStrength createFromParcel(Parcel in) {
             return new SignalStrength(in);
@@ -372,6 +401,7 @@
      *      Valid values for all signalstrength fields
      * @hide
      */
+    @UnsupportedAppUsage
     public void validateInput() {
         if (DBG) log("Signal before validate=" + this);
         // TS 27.007 8.5
@@ -546,26 +576,31 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getLteSignalStrength() {
         return mLteSignalStrength;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getLteRsrp() {
         return mLteRsrp;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getLteRsrq() {
         return mLteRsrq;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getLteRssnr() {
         return mLteRssnr;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getLteCqi() {
         return mLteCqi;
     }
@@ -594,6 +629,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getAsuLevel() {
         int asuLevel = 0;
         if (mIsGsm) {
@@ -629,6 +665,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getDbm() {
         int dBm = INVALID;
 
@@ -661,6 +698,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getGsmDbm() {
         int dBm;
 
@@ -680,6 +718,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getGsmLevel() {
         int level;
 
@@ -702,6 +741,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getGsmAsuLevel() {
         // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
         // asu = 0 (-113dB or less) is very weak
@@ -717,6 +757,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getCdmaLevel() {
         final int cdmaDbm = getCdmaDbm();
         final int cdmaEcio = getCdmaEcio();
@@ -746,6 +787,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getCdmaAsuLevel() {
         final int cdmaDbm = getCdmaDbm();
         final int cdmaEcio = getCdmaEcio();
@@ -777,6 +819,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getEvdoLevel() {
         int evdoDbm = getEvdoDbm();
         int evdoSnr = getEvdoSnr();
@@ -805,6 +848,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getEvdoAsuLevel() {
         int evdoDbm = getEvdoDbm();
         int evdoSnr = getEvdoSnr();
@@ -835,6 +879,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getLteDbm() {
         return mLteRsrp;
     }
@@ -844,6 +889,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getLteLevel() {
         /*
          * TS 36.214 Physical Layer Section 5.1.3
@@ -930,6 +976,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getLteAsuLevel() {
         int lteAsuLevel = 99;
         int lteDbm = getLteDbm();
@@ -973,6 +1020,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getTdScdmaDbm() {
         return this.mTdScdmaRscp;
     }
@@ -985,6 +1033,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getTdScdmaLevel() {
         final int tdScdmaDbm = getTdScdmaDbm();
         int level;
@@ -1006,6 +1055,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getTdScdmaAsuLevel() {
         final int tdScdmaDbm = getTdScdmaDbm();
         int tdScdmaAsuLevel;
@@ -1245,6 +1295,7 @@
      * @param m intent notifier map
      * @hide
      */
+    @UnsupportedAppUsage
     private void setFromNotifierBundle(Bundle m) {
         mGsmSignalStrength = m.getInt("GsmSignalStrength");
         mGsmBitErrorRate = m.getInt("GsmBitErrorRate");
@@ -1282,6 +1333,7 @@
      * @param m intent notifier Bundle
      * @hide
      */
+    @UnsupportedAppUsage
     public void fillInNotifierBundle(Bundle m) {
         m.putInt("GsmSignalStrength", mGsmSignalStrength);
         m.putInt("GsmBitErrorRate", mGsmBitErrorRate);
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 6cec977..ea408bf 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -19,6 +19,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressAutoDoc;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.app.PendingIntent;
 import android.content.ActivityNotFoundException;
@@ -88,6 +89,7 @@
             new ArrayMap<Integer, SmsManager>();
 
     /** A concrete subscription id, or the pseudo DEFAULT_SUBSCRIPTION_ID */
+    @UnsupportedAppUsage
     private int mSubId;
 
     /*
@@ -451,6 +453,7 @@
      * @throws IllegalArgumentException if destinationAddress or text are empty
      * {@hide}
      */
+    @UnsupportedAppUsage
     public void sendTextMessage(
             String destinationAddress, String scAddress, String text,
             PendingIntent sentIntent, PendingIntent deliveryIntent,
@@ -504,6 +507,7 @@
      * PendingIntent, int, boolean, int)
      * @hide
      */
+    @UnsupportedAppUsage
     public void sendTextMessageWithoutPersisting(
             String destinationAddress, String scAddress, String text,
             PendingIntent sentIntent, PendingIntent deliveryIntent, int priority,
@@ -729,6 +733,7 @@
      * @throws IllegalArgumentException if destinationAddress or data are empty
      * {@hide}
      */
+    @UnsupportedAppUsage
     public void sendMultipartTextMessage(
             String destinationAddress, String scAddress, ArrayList<String> parts,
             ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
@@ -997,6 +1002,7 @@
      * @throws IllegalArgumentException if pdu is NULL
      * {@hide}
      */
+    @UnsupportedAppUsage
     public boolean copyMessageToIcc(byte[] smsc, byte[] pdu,int status) {
         boolean success = false;
 
@@ -1027,6 +1033,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public boolean
     deleteMessageFromIcc(int messageIndex) {
         boolean success = false;
@@ -1061,6 +1068,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) {
         boolean success = false;
 
@@ -1087,6 +1095,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public ArrayList<SmsMessage> getAllMessagesFromIcc() {
         List<SmsRawData> records = null;
 
@@ -1199,6 +1208,7 @@
      * @throws IllegalArgumentException if endMessageId < startMessageId
      * {@hide}
      */
+    @UnsupportedAppUsage
     public boolean enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) {
         boolean success = false;
 
@@ -1241,6 +1251,7 @@
      * @throws IllegalArgumentException if endMessageId < startMessageId
      * {@hide}
      */
+    @UnsupportedAppUsage
     public boolean disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) {
         boolean success = false;
 
@@ -1358,6 +1369,7 @@
      * @return true if enabled, false otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isSMSPromptEnabled() {
         ISms iccISms = null;
         try {
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index 57f89e3..91e24a9 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -20,6 +20,7 @@
 
 import android.annotation.Nullable;
 import android.annotation.StringDef;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.os.Binder;
 import android.text.TextUtils;
@@ -107,18 +108,21 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public SmsMessageBase mWrappedSmsMessage;
 
     /** Indicates the subId
      *
      * @hide
      */
+    @UnsupportedAppUsage
     private int mSubId = 0;
 
     /** set Subscription information
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSubId(int subId) {
         mSubId = subId;
     }
@@ -127,6 +131,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getSubId() {
         return mSubId;
     }
@@ -368,6 +373,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static ArrayList<String> fragmentText(String text) {
         // This function is for MO SMS
         TextEncodingDetails ted = (useCdmaFormatForMoSms()) ?
@@ -822,6 +828,7 @@
      *
      * @return true if Cdma format should be used for MO SMS, false otherwise.
      */
+    @UnsupportedAppUsage
     private static boolean useCdmaFormatForMoSms() {
         // IMS is registered with SMS support, check the SMS format supported
         return useCdmaFormatForMoSms(SubscriptionManager.getDefaultSmsSubscriptionId());
@@ -836,6 +843,7 @@
      *
      * @return true if Cdma format should be used for MO SMS, false otherwise.
      */
+    @UnsupportedAppUsage
     private static boolean useCdmaFormatForMoSms(int subId) {
         SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
         if (!smsManager.isImsSmsSupported()) {
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 2bc43d4..ec26622 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -216,6 +217,7 @@
      * Sets the name displayed to the user that identifies this subscription
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDisplayName(CharSequence name) {
         this.mDisplayName = name;
     }
@@ -240,6 +242,7 @@
      * NAME_SOURCE_SIM_SOURCE or NAME_SOURCE_USER_INPUT.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getNameSource() {
         return this.mNameSource;
     }
@@ -298,6 +301,7 @@
      * Sets the color displayed to the user that identifies this subscription
      * @hide
      */
+    @UnsupportedAppUsage
     public void setIconTint(int iconTint) {
         this.mIconTint = iconTint;
     }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 151b936..119733e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -28,6 +28,7 @@
 import android.annotation.SuppressAutoDoc;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.BroadcastOptions;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -86,6 +87,7 @@
 
     /** Indicates the caller wants the default sub id. */
     /** @hide */
+    @UnsupportedAppUsage
     public static final int DEFAULT_SUBSCRIPTION_ID = Integer.MAX_VALUE;
 
     /**
@@ -108,6 +110,7 @@
     public static final int MAX_SUBSCRIPTION_ID_VALUE = DEFAULT_SUBSCRIPTION_ID - 1;
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
 
     /**
@@ -185,6 +188,7 @@
      * The name_source is from the user
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int NAME_SOURCE_USER_INPUT = 2;
 
     /**
@@ -615,6 +619,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public SubscriptionManager(Context context) {
         if (DBG) logd("SubscriptionManager created");
         mContext = context;
@@ -793,6 +798,7 @@
      * include those that were inserted before, maybe empty but not null.
      * @hide
      */
+    @UnsupportedAppUsage
     public List<SubscriptionInfo> getAllSubscriptionInfoList() {
         if (VDBG) logd("[getAllSubscriptionInfoList]+");
 
@@ -964,6 +970,7 @@
      * all subscriptions that have been seen.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getAllSubscriptionInfoCount() {
         if (VDBG) logd("[getAllSubscriptionInfoCount]+");
 
@@ -1069,6 +1076,7 @@
      * @return the number of records updated
      * @hide
      */
+    @UnsupportedAppUsage
     public int setIconTint(int tint, int subId) {
         if (VDBG) logd("[setIconTint]+ tint:" + tint + " subId:" + subId);
         return setSubscriptionPropertyHelper(subId, "setIconTint",
@@ -1096,6 +1104,7 @@
      * @return the number of records updated or < 0 if invalid subId
      * @hide
      */
+    @UnsupportedAppUsage
     public int setDisplayName(String displayName, int subId, long nameSource) {
         if (VDBG) {
             logd("[setDisplayName]+  displayName:" + displayName + " subId:" + subId
@@ -1113,6 +1122,7 @@
      * @return the number of records updated
      * @hide
      */
+    @UnsupportedAppUsage
     public int setDisplayNumber(String number, int subId) {
         if (number == null) {
             logd("[setDisplayNumber]- fail");
@@ -1130,6 +1140,7 @@
      * @return the number of records updated
      * @hide
      */
+    @UnsupportedAppUsage
     public int setDataRoaming(int roaming, int subId) {
         if (VDBG) logd("[setDataRoaming]+ roaming:" + roaming + " subId:" + subId);
         return setSubscriptionPropertyHelper(subId, "setDataRoaming",
@@ -1143,6 +1154,7 @@
      * SIM_NOT_INSERTED or < 0 if an invalid slot index
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getSlotIndex(int subId) {
         if (!isValidSubscriptionId(subId)) {
             if (DBG) {
@@ -1166,6 +1178,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static int[] getSubId(int slotIndex) {
         if (!isValidSlotIndex(slotIndex)) {
             logd("[getSubId]- fail");
@@ -1187,6 +1200,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static int getPhoneId(int subId) {
         if (!isValidSubscriptionId(subId)) {
             if (DBG) {
@@ -1284,11 +1298,13 @@
      * @return the SubscriptionInfo for the default voice subscription.
      * @hide
      */
+    @UnsupportedAppUsage
     public SubscriptionInfo getDefaultVoiceSubscriptionInfo() {
         return getActiveSubscriptionInfo(getDefaultVoiceSubscriptionId());
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static int getDefaultVoicePhoneId() {
         return getPhoneId(getDefaultVoiceSubscriptionId());
     }
@@ -1317,6 +1333,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setDefaultSmsSubId(int subId) {
         if (VDBG) logd("setDefaultSmsSubId sub id = " + subId);
         try {
@@ -1342,6 +1359,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getDefaultSmsPhoneId() {
         return getPhoneId(getDefaultSmsSubscriptionId());
     }
@@ -1370,6 +1388,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setDefaultDataSubId(int subId) {
         if (VDBG) logd("setDataSubscription sub id = " + subId);
         try {
@@ -1390,11 +1409,13 @@
      * @return the SubscriptionInfo for the default data subscription.
      * @hide
      */
+    @UnsupportedAppUsage
     public SubscriptionInfo getDefaultDataSubscriptionInfo() {
         return getActiveSubscriptionInfo(getDefaultDataSubscriptionId());
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getDefaultDataPhoneId() {
         return getPhoneId(getDefaultDataSubscriptionId());
     }
@@ -1433,6 +1454,7 @@
      * an invalid subscription id, i.e. < 0.
      * @hide
      */
+    @UnsupportedAppUsage
     public void clearDefaultsForInactiveSubIds() {
         if (VDBG) logd("clearDefaultsForInactiveSubIds");
         try {
@@ -1449,6 +1471,7 @@
      * @return true if a valid subId else false
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isValidSubscriptionId(int subId) {
         return subId > INVALID_SUBSCRIPTION_ID ;
     }
@@ -1458,21 +1481,25 @@
      * usable subId means its neither a INVALID_SUBSCRIPTION_ID nor a DEFAULT_SUB_ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isUsableSubIdValue(int subId) {
         return subId >= MIN_SUBSCRIPTION_ID_VALUE && subId <= MAX_SUBSCRIPTION_ID_VALUE;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static boolean isValidSlotIndex(int slotIndex) {
         return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getSimCount();
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static boolean isValidPhoneId(int phoneId) {
         return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount();
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) {
         int[] subIds = SubscriptionManager.getSubId(phoneId);
         if (subIds != null && subIds.length > 0) {
@@ -1483,6 +1510,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId) {
         if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
@@ -1498,6 +1526,7 @@
      *         is never null but the length maybe 0.
      * @hide
      */
+    @UnsupportedAppUsage
     public @NonNull int[] getActiveSubscriptionIdList() {
         int[] subId = null;
 
@@ -1656,6 +1685,7 @@
      * @return Resources associated with Subscription.
      * @hide
      */
+    @UnsupportedAppUsage
     public static Resources getResourcesForSubId(Context context, int subId) {
         final SubscriptionInfo subInfo =
                 SubscriptionManager.from(context).getActiveSubscriptionInfo(subId);
@@ -1679,6 +1709,7 @@
      * and the SIM providing the subscription is present in a slot and in "LOADED" state.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isActiveSubId(int subId) {
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 59f3f1a..cc841fa 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -28,6 +28,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 import android.app.ActivityThread;
 import android.app.PendingIntent;
@@ -155,6 +156,7 @@
 
     private final Context mContext;
     private final int mSubId;
+    @UnsupportedAppUsage
     private SubscriptionManager mSubscriptionManager;
     private TelephonyScanManager mTelephonyScanManager;
 
@@ -168,18 +170,24 @@
      **/
     /** @hide */
     public enum MultiSimVariants {
+        @UnsupportedAppUsage
         DSDS,
+        @UnsupportedAppUsage
         DSDA,
+        @UnsupportedAppUsage
         TSTS,
+        @UnsupportedAppUsage
         UNKNOWN
     };
 
     /** @hide */
+    @UnsupportedAppUsage
     public TelephonyManager(Context context) {
       this(context, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public TelephonyManager(Context context, int subId) {
         mSubId = subId;
         Context appContext = context.getApplicationContext();
@@ -192,6 +200,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     private TelephonyManager() {
         mContext = null;
         mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -201,6 +210,7 @@
 
     /** @hide
     /* @deprecated - use getSystemService as described above */
+    @UnsupportedAppUsage
     public static TelephonyManager getDefault() {
         return sInstance;
     }
@@ -228,6 +238,7 @@
      * Returns UNKNOWN for others
      */
     /** {@hide} */
+    @UnsupportedAppUsage
     public MultiSimVariants getMultiSimConfiguration() {
         String mSimConfig =
             SystemProperties.get(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG);
@@ -288,6 +299,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static TelephonyManager from(Context context) {
         return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
     }
@@ -319,6 +331,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public boolean isMultiSimEnabled() {
         return (multiSimConfig.equals("dsds") || multiSimConfig.equals("dsda") ||
             multiSimConfig.equals("tsts"));
@@ -672,6 +685,7 @@
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     @Deprecated
+    @UnsupportedAppUsage
     public static final String ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED =
             "android.intent.action.PRECISE_DATA_CONNECTION_STATE_CHANGED";
 
@@ -1206,6 +1220,7 @@
      */
     /** {@hide} */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getDeviceSoftwareVersion(int slotIndex) {
         ITelephony telephony = getITelephony();
         if (telephony == null) return null;
@@ -1418,6 +1433,7 @@
      *  @param slotIndex of which Nai is returned
      */
     /** {@hide}*/
+    @UnsupportedAppUsage
     public String getNai(int slotIndex) {
         int[] subId = SubscriptionManager.getSubId(slotIndex);
         if (subId == null) {
@@ -1657,6 +1673,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     private int getPhoneTypeFromProperty(int phoneId) {
         String type = getTelephonyProperty(phoneId,
                 TelephonyProperties.CURRENT_ACTIVE_PHONE, null);
@@ -1691,6 +1708,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getPhoneType(int networkMode) {
         switch(networkMode) {
         case RILConstants.NETWORK_MODE_CDMA:
@@ -1736,6 +1754,7 @@
     /**
      * The contents of the /proc/cmdline file
      */
+    @UnsupportedAppUsage
     private static String getProcCmdLine()
     {
         String cmdline = "";
@@ -1782,6 +1801,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getLteOnCdmaModeStatic() {
         int retVal;
         int curVal;
@@ -1837,6 +1857,7 @@
      * @param subId
      * @hide
      */
+    @UnsupportedAppUsage
     public String getNetworkOperatorName(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ALPHA, "");
@@ -1864,6 +1885,7 @@
      * @param subId
      * @hide
      */
+    @UnsupportedAppUsage
     public String getNetworkOperator(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getNetworkOperatorForPhone(phoneId);
@@ -1880,6 +1902,7 @@
      * @param phoneId
      * @hide
      **/
+    @UnsupportedAppUsage
     public String getNetworkOperatorForPhone(int phoneId) {
         return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, "");
      }
@@ -1942,6 +1965,7 @@
      * @param subId
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isNetworkRoaming(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return Boolean.parseBoolean(getTelephonyProperty(phoneId,
@@ -1970,6 +1994,7 @@
      * @param subId for which Network CountryIso is returned
      * @hide
      */
+    @UnsupportedAppUsage
     public String getNetworkCountryIso(int subId) {
         return getNetworkCountryIsoForPhone(getPhoneId(subId));
     }
@@ -1985,6 +2010,7 @@
      * @param phoneId for which Network CountryIso is returned
      */
     /** {@hide} */
+    @UnsupportedAppUsage
     public String getNetworkCountryIsoForPhone(int phoneId) {
         try {
             ITelephony telephony = getITelephony();
@@ -2040,6 +2066,7 @@
     /** Current network is IWLAN */
     public static final int NETWORK_TYPE_IWLAN = TelephonyProtoEnums.NETWORK_TYPE_IWLAN; // = 18.
     /** Current network is LTE_CA {@hide} */
+    @UnsupportedAppUsage
     public static final int NETWORK_TYPE_LTE_CA = TelephonyProtoEnums.NETWORK_TYPE_LTE_CA; // = 19.
 
     /** Max network type number. Update as new types are added. Don't add negative types. {@hide} */
@@ -2092,6 +2119,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+   @UnsupportedAppUsage
    public int getNetworkType(int subId) {
        try {
            ITelephony telephony = getITelephony();
@@ -2154,6 +2182,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getDataNetworkType(int subId) {
         try{
             ITelephony telephony = getITelephony();
@@ -2189,6 +2218,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getVoiceNetworkType(int subId) {
         try{
             ITelephony telephony = getITelephony();
@@ -2216,10 +2246,13 @@
     /** Unknown network class. {@hide} */
     public static final int NETWORK_CLASS_UNKNOWN = 0;
     /** Class of broadly defined "2G" networks. {@hide} */
+    @UnsupportedAppUsage
     public static final int NETWORK_CLASS_2_G = 1;
     /** Class of broadly defined "3G" networks. {@hide} */
+    @UnsupportedAppUsage
     public static final int NETWORK_CLASS_3_G = 2;
     /** Class of broadly defined "4G" networks. {@hide} */
+    @UnsupportedAppUsage
     public static final int NETWORK_CLASS_4_G = 3;
 
     /**
@@ -2228,6 +2261,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getNetworkClass(int networkType) {
         switch (networkType) {
             case NETWORK_TYPE_GPRS:
@@ -2264,6 +2298,7 @@
      *
      * @hide pending API council review
      */
+    @UnsupportedAppUsage
     public String getNetworkTypeName() {
         return getNetworkTypeName(getNetworkType());
     }
@@ -2276,6 +2311,7 @@
      *
      */
     /** {@hide} */
+    @UnsupportedAppUsage
     public static String getNetworkTypeName(int type) {
         switch (type) {
             case NETWORK_TYPE_GPRS:
@@ -2475,6 +2511,7 @@
      */
     /** {@hide} */
     // FIXME Input argument slotIndex should be of type int
+    @UnsupportedAppUsage
     public boolean hasIccCard(int slotIndex) {
 
         try {
@@ -2638,6 +2675,7 @@
      * @param subId for which SimOperator is returned
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimOperator(int subId) {
         return getSimOperatorNumeric(subId);
     }
@@ -2651,6 +2689,7 @@
      * @see #getSimState
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimOperatorNumeric() {
         int subId = mSubId;
         if (!SubscriptionManager.isUsableSubIdValue(subId)) {
@@ -2679,6 +2718,7 @@
      * @param subId for which SimOperator is returned
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimOperatorNumeric(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getSimOperatorNumericForPhone(phoneId);
@@ -2692,6 +2732,7 @@
      * @param phoneId for which SimOperator is returned
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimOperatorNumericForPhone(int phoneId) {
         return getTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "");
@@ -2718,6 +2759,7 @@
      * @param subId for which SimOperatorName is returned
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimOperatorName(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getSimOperatorNameForPhone(phoneId);
@@ -2728,6 +2770,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimOperatorNameForPhone(int phoneId) {
          return getTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, "");
@@ -2746,6 +2789,7 @@
      * @param subId for which SimCountryIso is returned
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimCountryIso(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getSimCountryIsoForPhone(phoneId);
@@ -2756,6 +2800,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimCountryIsoForPhone(int phoneId) {
         return getTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY, "");
@@ -2782,6 +2827,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getSimSerialNumber(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -2807,6 +2853,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getLteOnCdmaMode() {
         return getLteOnCdmaMode(getSubId());
     }
@@ -2822,6 +2869,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getLteOnCdmaMode(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -2929,6 +2977,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getSubscriberId(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3109,6 +3158,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getGroupIdLevel1(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3158,6 +3208,7 @@
             android.Manifest.permission.READ_SMS,
             android.Manifest.permission.READ_PHONE_NUMBERS
     })
+    @UnsupportedAppUsage
     public String getLine1Number(int subId) {
         String number = null;
         try {
@@ -3244,6 +3295,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getLine1AlphaTag(int subId) {
         String alphaTag = null;
         try {
@@ -3278,6 +3330,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public @Nullable String[] getMergedSubscriberIds() {
         try {
             ITelephony telephony = getITelephony();
@@ -3296,6 +3349,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getMsisdn() {
         return getMsisdn(getSubId());
     }
@@ -3308,6 +3362,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getMsisdn(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3341,6 +3396,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getVoiceMailNumber(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3361,6 +3417,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.CALL_PRIVILEGED)
+    @UnsupportedAppUsage
     public String getCompleteVoiceMailNumber() {
         return getCompleteVoiceMailNumber(getSubId());
     }
@@ -3372,6 +3429,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.CALL_PRIVILEGED)
+    @UnsupportedAppUsage
     public String getCompleteVoiceMailNumber(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3931,6 +3989,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getVoiceMessageCount() {
         return getVoiceMessageCount(getSubId());
     }
@@ -3941,6 +4000,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getVoiceMessageCount(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -3976,6 +4036,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getVoiceMailAlphaTag(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -4022,6 +4083,7 @@
      * @return the IMPI, or null if not present or not loaded
      * @hide
      */
+    @UnsupportedAppUsage
     public String getIsimImpi() {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -4042,6 +4104,7 @@
      * @return the IMS domain name, or null if not present or not loaded
      * @hide
      */
+    @UnsupportedAppUsage
     public String getIsimDomain() {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -4063,6 +4126,7 @@
      *      not present or not loaded
      * @hide
      */
+    @UnsupportedAppUsage
     public String[] getIsimImpu() {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -4081,6 +4145,7 @@
    /**
     * @hide
     */
+    @UnsupportedAppUsage
     private IPhoneSubInfo getSubscriberInfo() {
         // get it each time because that process crashes a lot
         return IPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));
@@ -4146,6 +4211,7 @@
      * @param subId the subscription to check call state for.
      * @hide
      */
+    @UnsupportedAppUsage
     public @CallState int getCallState(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getCallStateForSlot(phoneId);
@@ -4257,6 +4323,7 @@
    /**
     * @hide
     */
+    @UnsupportedAppUsage
     private ITelephony getITelephony() {
         return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
     }
@@ -4341,6 +4408,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getCdmaEriIconIndex(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -4375,6 +4443,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getCdmaEriIconMode(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -4405,6 +4474,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getCdmaEriText(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -4877,6 +4947,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String nvReadItem(int itemID) {
         try {
             ITelephony telephony = getITelephony();
@@ -4957,6 +5028,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean nvResetConfig(int resetType) {
         try {
             ITelephony telephony = getITelephony();
@@ -4993,6 +5065,7 @@
      * {@see SubscriptionManager#getDefaultVoiceSubscriptionId()}
      * {@see SubscriptionManager#getDefaultSmsSubscriptionId()}
      */
+    @UnsupportedAppUsage
     private int getSubId(int preferredSubId) {
         if (SubscriptionManager.isUsableSubIdValue(mSubId)) {
             return mSubId;
@@ -5021,6 +5094,7 @@
      * {@see SubscriptionManager#getDefaultVoiceSubscriptionId()}
      * {@see SubscriptionManager#getDefaultSmsSubscriptionId()}
      */
+    @UnsupportedAppUsage
     private int getPhoneId(int preferredSubId) {
         return SubscriptionManager.getPhoneId(getSubId(preferredSubId));
     }
@@ -5036,6 +5110,7 @@
      * {@hide}
      */
     @VisibleForTesting
+    @UnsupportedAppUsage
     public int getSlotIndex() {
         int slotIndex = SubscriptionManager.getSlotIndex(getSubId());
         if (slotIndex == SubscriptionManager.SIM_NOT_INSERTED) {
@@ -5049,6 +5124,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void setTelephonyProperty(int phoneId, String property, String value) {
         String propVal = "";
         String p[] = null;
@@ -5126,6 +5202,7 @@
      * @return The value at the given index of settings.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getIntAtIndex(android.content.ContentResolver cr,
             String name, int index)
             throws android.provider.Settings.SettingNotFoundException {
@@ -5158,6 +5235,7 @@
      * @return true if the value was set, false on database errors
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean putIntAtIndex(android.content.ContentResolver cr,
             String name, int index, int value) {
         String data = "";
@@ -5199,6 +5277,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static String getTelephonyProperty(int phoneId, String property, String defaultVal) {
         String propVal = null;
         String prop = SystemProperties.get(property);
@@ -5219,12 +5298,14 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static String getTelephonyProperty(String property, String defaultVal) {
         String propVal = SystemProperties.get(property);
         return propVal == null ? defaultVal : propVal;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getSimCount() {
         // FIXME Need to get it from Telephony Dev Controller when that gets implemented!
         // and then this method shouldn't be used at all!
@@ -5261,6 +5342,7 @@
      *         not present or not loaded
      * @hide
      */
+    @UnsupportedAppUsage
     public String[] getIsimPcscf() {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -5341,6 +5423,7 @@
      *   Authentication error, no memory space available in EFMUK
      * @hide
      */
+    @UnsupportedAppUsage
     public String getIccAuthentication(int subId, int appType, int authType, String data) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -5503,6 +5586,7 @@
      * Corresponds to features defined in ImsFeature.
      * @hide
      */
+    @UnsupportedAppUsage
     public @Nullable IImsRegistration getImsRegistration(int slotIndex, int feature) {
         try {
             ITelephony telephony = getITelephony();
@@ -5522,6 +5606,7 @@
      * Corresponds to features defined in ImsFeature.
      * @hide
      */
+    @UnsupportedAppUsage
     public @Nullable IImsConfig getImsConfig(int slotIndex, int feature) {
         try {
             ITelephony telephony = getITelephony();
@@ -5557,6 +5642,7 @@
      * @param Registration state
      * @hide
      */
+    @UnsupportedAppUsage
     public void setImsRegistrationState(boolean registered) {
         try {
             ITelephony telephony = getITelephony();
@@ -5577,6 +5663,7 @@
      * @return the preferred network type, defined in RILConstants.java.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getPreferredNetworkType(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -5725,6 +5812,7 @@
      * @return true on success; false on any failure.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean setPreferredNetworkType(int subId, int networkType) {
         try {
             ITelephony telephony = getITelephony();
@@ -5899,6 +5987,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean setRoamingOverride(List<String> gsmRoamingList,
             List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
             List<String> cdmaNonRoamingList) {
@@ -6753,6 +6842,7 @@
      * @see SubscriptionManager#getDefaultSubscriptionId()
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isImsRegistered() {
        try {
            return getITelephony().isImsRegistered(getSubId());
@@ -6769,6 +6859,7 @@
      * @see SubscriptionManager#getDefaultSubscriptionId()
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isVolteAvailable() {
         try {
             return getITelephony().isVolteAvailable(getSubId());
@@ -6785,6 +6876,7 @@
      * @return true if VT is available, or false if it is unavailable or unknown.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isVideoTelephonyAvailable() {
         try {
             return getITelephony().isVideoTelephonyAvailable(getSubId());
@@ -6799,6 +6891,7 @@
      * @return true if VoWiFi is available, or false if it is unavailable or unknown.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isWifiCallingAvailable() {
        try {
            return getITelephony().isWifiCallingAvailable(getSubId());
@@ -6841,6 +6934,7 @@
     *
     * @hide
     */
+    @UnsupportedAppUsage
     public void setSimOperatorNumericForPhone(int phoneId, String numeric) {
         setTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, numeric);
@@ -6861,6 +6955,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSimOperatorNameForPhone(int phoneId, String name) {
         setTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, name);
@@ -6881,6 +6976,7 @@
     *
     * @hide
     */
+    @UnsupportedAppUsage
     public void setSimCountryIsoForPhone(int phoneId, String iso) {
         setTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY, iso);
@@ -6901,6 +6997,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSimStateForPhone(int phoneId, String state) {
         setTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_SIM_STATE, state);
@@ -7006,6 +7103,7 @@
      * @param version baseband version
      * @hide
      */
+    @UnsupportedAppUsage
     public void setBasebandVersionForPhone(int phoneId, String version) {
         setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_BASEBAND_VERSION, version);
     }
@@ -7071,6 +7169,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPhoneType(int phoneId, int type) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
             TelephonyManager.setTelephonyProperty(phoneId,
@@ -7100,6 +7199,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String getOtaSpNumberSchemaForPhone(int phoneId, String defaultValue) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
             return TelephonyManager.getTelephonyProperty(phoneId,
@@ -7187,6 +7287,7 @@
      * @param name the alphabetic name of current registered operator.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setNetworkOperatorNameForPhone(int phoneId, String name) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
             setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ALPHA, name);
@@ -7209,6 +7310,7 @@
      * @param operator the numeric name (MCC+MNC) of current registered operator
      * @hide
      */
+    @UnsupportedAppUsage
     public void setNetworkOperatorNumericForPhone(int phoneId, String numeric) {
         setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, numeric);
     }
@@ -7229,6 +7331,7 @@
      * @param isRoaming is network in romaing state or not
      * @hide
      */
+    @UnsupportedAppUsage
     public void setNetworkRoamingForPhone(int phoneId, boolean isRoaming) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
             setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ISROAMING,
@@ -7256,6 +7359,7 @@
      * @param type the network type currently in use on the device for data transmission
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDataNetworkTypeForPhone(int phoneId, int type) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
             setTelephonyProperty(phoneId,
@@ -7268,6 +7372,7 @@
      * Returns the subscription ID for the given phone account.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
         int retval = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
         try {
@@ -7359,6 +7464,7 @@
      * either READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE to retrieve the information.
      * @hide
      */
+    @UnsupportedAppUsage
     public ServiceState getServiceStateForSubscriber(int subId) {
         try {
             ITelephony service = getITelephony();
@@ -8019,4 +8125,23 @@
         }
         return UNKNOWN_CARRIER_ID_LIST_VERSION;
     }
+
+
+    /**
+     * How many modems can have simultaneous data connections.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    public int getNumberOfModemsWithSimultaneousDataConnections() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getNumberOfModemsWithSimultaneousDataConnections(
+                        getSubId(), mContext.getOpPackageName());
+            }
+        } catch (RemoteException ex) {
+            // This could happen if binder process crashes.
+        }
+        return 0;
+    }
 }
diff --git a/telephony/java/android/telephony/VoLteServiceState.java b/telephony/java/android/telephony/VoLteServiceState.java
index afef601b..25bb8b4 100644
--- a/telephony/java/android/telephony/VoLteServiceState.java
+++ b/telephony/java/android/telephony/VoLteServiceState.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -77,6 +78,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public VoLteServiceState(int srvccState) {
         initialize();
 
diff --git a/telephony/java/android/telephony/cdma/CdmaCellLocation.java b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
index 7c10569..ee602c0 100644
--- a/telephony/java/android/telephony/cdma/CdmaCellLocation.java
+++ b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
@@ -16,6 +16,7 @@
 
 package android.telephony.cdma;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.telephony.CellLocation;
 
@@ -23,6 +24,7 @@
  * Represents the cell location on a CDMA phone.
  */
 public class CdmaCellLocation extends CellLocation {
+    @UnsupportedAppUsage
     private int mBaseStationId = -1;
 
     /**
@@ -36,6 +38,7 @@
      * to 1296000, both values inclusive (corresponding to a range of -90
      * to +90 degrees). Integer.MAX_VALUE is considered invalid value.
      */
+    @UnsupportedAppUsage
     private int mBaseStationLatitude = INVALID_LAT_LONG;
 
     /**
@@ -44,9 +47,12 @@
      * to 2592000, both values inclusive (corresponding to a range of -180
      * to +180 degrees). Integer.MAX_VALUE is considered invalid value.
      */
+    @UnsupportedAppUsage
     private int mBaseStationLongitude = INVALID_LAT_LONG;
 
+    @UnsupportedAppUsage
     private int mSystemId = -1;
+    @UnsupportedAppUsage
     private int mNetworkId = -1;
 
     /**
@@ -200,6 +206,7 @@
      * @param b second obj
      * @return true if two objects equal or both are null
      */
+    @UnsupportedAppUsage
     private static boolean equalsHandlesNulls(Object a, Object b) {
         return (a == null) ? (b == null) : a.equals (b);
     }
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 9388ed1..0e4a7ad 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -810,7 +810,7 @@
             version = 1;
         }
 
-        String[] a = data.split("\\s*,\\s*");
+        String[] a = data.split("\\s*,\\s*", -1);
         if (a.length < 14) {
             return null;
         }
diff --git a/telephony/java/android/telephony/euicc/DownloadableSubscription.java b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
index edf3b08..f1d5bdd 100644
--- a/telephony/java/android/telephony/euicc/DownloadableSubscription.java
+++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
@@ -17,6 +17,7 @@
 
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -59,6 +60,7 @@
      */
     @Nullable
     @Deprecated
+    @UnsupportedAppUsage
     public final String encodedActivationCode;
 
     @Nullable private String confirmationCode;
@@ -188,6 +190,7 @@
      * @deprecated - Do not use.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void setCarrierName(String carrierName) {
         this.carrierName = carrierName;
     }
@@ -234,6 +237,7 @@
      * @deprecated - Do not use.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void setAccessRules(UiccAccessRule[] accessRules) {
         this.accessRules = Arrays.asList(accessRules);
     }
diff --git a/telephony/java/android/telephony/euicc/EuiccInfo.java b/telephony/java/android/telephony/euicc/EuiccInfo.java
index a4adf05..28855b2 100644
--- a/telephony/java/android/telephony/euicc/EuiccInfo.java
+++ b/telephony/java/android/telephony/euicc/EuiccInfo.java
@@ -16,6 +16,7 @@
 package android.telephony.euicc;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -43,6 +44,7 @@
             };
 
     @Nullable
+    @UnsupportedAppUsage
     private final String osVersion;
 
     /**
diff --git a/telephony/java/android/telephony/gsm/GsmCellLocation.java b/telephony/java/android/telephony/gsm/GsmCellLocation.java
index 1717802..98ce333 100644
--- a/telephony/java/android/telephony/gsm/GsmCellLocation.java
+++ b/telephony/java/android/telephony/gsm/GsmCellLocation.java
@@ -16,6 +16,7 @@
 
 package android.telephony.gsm;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.telephony.CellLocation;
 
@@ -91,6 +92,7 @@
      * Set the primary scrambling code.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPsc(int psc) {
         mPsc = psc;
     }
diff --git a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
index 2831127..34b8884 100644
--- a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
+++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -30,30 +31,37 @@
     // Refer to ImsUtInterface#CDIV_CF_XXX
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter.
+    @UnsupportedAppUsage
     public int mCondition;
     // 0: disabled, 1: enabled
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter.
+    @UnsupportedAppUsage
     public int mStatus;
     // 0x91: International, 0x81: Unknown
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter.
+    @UnsupportedAppUsage
     public int mToA;
     // Service class
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter.
+    @UnsupportedAppUsage
     public int mServiceClass;
     // Number (it will not include the "sip" or "tel" URI scheme)
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter.
+    @UnsupportedAppUsage
     public String mNumber;
     // No reply timer for CF
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter.
+    @UnsupportedAppUsage
     public int mTimeSeconds;
 
     /** @hide */
     // TODO: Will be removed in the future, use public constructor instead.
+    @UnsupportedAppUsage
     public ImsCallForwardInfo() {
     }
 
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 350dfe3..f0d3c89 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -260,8 +261,10 @@
     /** @hide */
     public int mServiceType;
     /** @hide */
+    @UnsupportedAppUsage
     public int mCallType;
     /** @hide */
+    @UnsupportedAppUsage
     public int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
 
     /**
@@ -287,8 +290,10 @@
      * a {@link android.os.Binder}.
      */
     /** @hide */
+    @UnsupportedAppUsage
     public Bundle mCallExtras;
     /** @hide */
+    @UnsupportedAppUsage
     public ImsStreamMediaProfile mMediaProfile;
 
     /** @hide */
@@ -568,6 +573,7 @@
      * See {@link #presentationToOir(int)}.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int presentationToOIR(int presentation) {
         switch (presentation) {
             case PhoneConstants.PRESENTATION_RESTRICTED:
diff --git a/telephony/java/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java
index e158fa8..8d18ae8 100644
--- a/telephony/java/android/telephony/ims/ImsExternalCallState.java
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -58,6 +59,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public ImsExternalCallState(int callId, Uri address, boolean isPullable, int callState,
             int callType, boolean isCallheld) {
         mCallId = callId;
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index 81f2fe7..32cb8ce 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -581,12 +582,15 @@
 
     // For main reason code
     /** @hide */
+    @UnsupportedAppUsage
     public int mCode;
     // For the extra code value; it depends on the code value.
     /** @hide */
+    @UnsupportedAppUsage
     public int mExtraCode;
     // For the additional message of the reason info.
     /** @hide */
+    @UnsupportedAppUsage
     public String mExtraMessage;
 
     /** @hide */
@@ -603,6 +607,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public ImsReasonInfo(int code, int extraCode) {
         mCode = code;
         mExtraCode = extraCode;
diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java
index e924a25..3a784c1 100644
--- a/telephony/java/android/telephony/ims/ImsSsInfo.java
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -65,15 +66,18 @@
     // 0: disabled, 1: enabled
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter!
+    @UnsupportedAppUsage
     public int mStatus;
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter!
+    @UnsupportedAppUsage
     public String mIcbNum;
     /** @hide */
     public int mProvisionStatus = SERVICE_PROVISIONING_UNKNOWN;
 
     /**@hide*/
     // TODO: Remove! Do not use this constructor, instead use public version.
+    @UnsupportedAppUsage
     public ImsSsInfo() {
     }
 
diff --git a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
index 137106a..52d72b5 100644
--- a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
+++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -82,13 +83,16 @@
 
     // Audio related information
     /** @hide */
+    @UnsupportedAppUsage
     public int mAudioQuality;
     /** @hide */
+    @UnsupportedAppUsage
     public int mAudioDirection;
     // Video related information
     /** @hide */
     public int mVideoQuality;
     /** @hide */
+    @UnsupportedAppUsage
     public int mVideoDirection;
     // Rtt related information
     /** @hide */
@@ -156,6 +160,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public ImsStreamMediaProfile() {
         mAudioQuality = AUDIO_QUALITY_NONE;
         mAudioDirection = DIRECTION_SEND_RECEIVE;
diff --git a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
index b4f60b9..1772401 100644
--- a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
+++ b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
@@ -179,6 +180,7 @@
      * Returns binder object which can be used across IPC methods.
      * @hide
      */
+    @UnsupportedAppUsage
     public final IImsVideoCallProvider getInterface() {
         return mBinder;
     }
diff --git a/telephony/java/android/telephony/ims/compat/ImsService.java b/telephony/java/android/telephony/ims/compat/ImsService.java
index cf1efb3..2750e51 100644
--- a/telephony/java/android/telephony/ims/compat/ImsService.java
+++ b/telephony/java/android/telephony/ims/compat/ImsService.java
@@ -17,6 +17,7 @@
 package android.telephony.ims.compat;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
@@ -86,6 +87,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     protected final IBinder mImsServiceController = new IImsServiceController.Stub() {
 
         @Override
diff --git a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
index 0a12cae..e8fcac1 100644
--- a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
@@ -17,6 +17,7 @@
 package android.telephony.ims.compat.feature;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.os.IInterface;
@@ -104,10 +105,12 @@
         mSlotId = slotId;
     }
 
+    @UnsupportedAppUsage
     public int getFeatureState() {
         return mState;
     }
 
+    @UnsupportedAppUsage
     protected final void setFeatureState(@ImsState int state) {
         if (mState != state) {
             mState = state;
diff --git a/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
index d3d17f4..40ea208 100644
--- a/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
@@ -20,6 +20,7 @@
 import android.os.Message;
 import android.os.RemoteException;
 
+import android.annotation.UnsupportedAppUsage;
 import android.telephony.ims.ImsCallProfile;
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsCallSessionListener;
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
index e5ed825..23de2fd 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
@@ -28,6 +28,7 @@
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsVideoCallProvider;
 
+import android.annotation.UnsupportedAppUsage;
 import android.telephony.ims.ImsCallSession;
 
 /**
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
index 2c325ba8..e55c3d0 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
@@ -16,6 +16,7 @@
 
 package android.telephony.ims.compat.stub;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.os.RemoteException;
@@ -58,6 +59,7 @@
 
     ImsConfigStub mImsConfigStub;
 
+    @UnsupportedAppUsage
     public ImsConfigImplBase(Context context) {
         mImsConfigStub = new ImsConfigStub(this, context);
     }
@@ -162,6 +164,7 @@
     public void setVideoQuality(int quality, ImsConfigListener listener) throws RemoteException {
     }
 
+    @UnsupportedAppUsage
     public IImsConfig getIImsConfig() { return mImsConfigStub; }
 
     /**
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
index b2aa080..976c2be 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
@@ -19,6 +19,7 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 
+import android.annotation.UnsupportedAppUsage;
 import android.telephony.ims.ImsCallForwardInfo;
 import android.telephony.ims.ImsReasonInfo;
 import android.telephony.ims.ImsSsData;
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 0d315e5..1ebb697 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -21,6 +21,7 @@
 import android.telephony.SignalStrength;
 import android.telephony.CellInfo;
 import android.telephony.DataConnectionRealTimeInfo;
+import android.telephony.PhoneCapability;
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
 import android.telephony.PreciseDataConnectionState;
@@ -50,5 +51,6 @@
     void onOemHookRawEvent(in byte[] rawData);
     void onCarrierNetworkChange(in boolean active);
     void onUserMobileDataStateChanged(in boolean enabled);
+    void onPhoneCapabilityChanged(in PhoneCapability capability);
 }
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 5cf3dff..7c6dbca 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1537,4 +1537,10 @@
      * @hide
      */
     void refreshUiccProfile(int subId);
+
+    /**
+     * How many modems can have simultaneous data connections.
+     * @hide
+     */
+    int getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage);
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 0127db9..e0e1a7b 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -21,6 +21,7 @@
 import android.net.NetworkCapabilities;
 import android.os.Bundle;
 import android.telephony.CellInfo;
+import android.telephony.PhoneCapability;
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
@@ -74,4 +75,5 @@
     void notifySubscriptionInfoChanged();
     void notifyCarrierNetworkChange(in boolean active);
     void notifyUserMobileDataStateChangedForPhoneId(in int phoneId, in int subId, in boolean state);
+    void notifyPhoneCapabilityChanged(in PhoneCapability capability);
 }
diff --git a/tests/net/java/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java
index 2b172da..3452819 100644
--- a/tests/net/java/android/net/NetworkUtilsTest.java
+++ b/tests/net/java/android/net/NetworkUtilsTest.java
@@ -24,6 +24,8 @@
 import static android.net.NetworkUtils.netmaskToPrefixLength;
 import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTH;
 import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTL;
+import static android.net.NetworkUtils.getBroadcastAddress;
+import static android.net.NetworkUtils.getPrefixMaskAsInet4Address;
 
 import static junit.framework.Assert.assertEquals;
 
@@ -125,7 +127,6 @@
         assertInvalidNetworkMask(IPv4Address("255.255.0.255"));
     }
 
-
     @Test
     public void testPrefixLengthToV4NetmaskIntHTL() {
         assertEquals(0, prefixLengthToV4NetmaskIntHTL(0));
@@ -266,4 +267,44 @@
         assertEquals(BigInteger.valueOf(7l - 4 + 4 + 16 + 65536),
                 NetworkUtils.routedIPv6AddressCount(set));
     }
+
+    @Test
+    public void testGetPrefixMaskAsAddress() {
+        assertEquals("255.255.240.0", getPrefixMaskAsInet4Address(20).getHostAddress());
+        assertEquals("255.0.0.0", getPrefixMaskAsInet4Address(8).getHostAddress());
+        assertEquals("0.0.0.0", getPrefixMaskAsInet4Address(0).getHostAddress());
+        assertEquals("255.255.255.255", getPrefixMaskAsInet4Address(32).getHostAddress());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testGetPrefixMaskAsAddress_PrefixTooLarge() {
+        getPrefixMaskAsInet4Address(33);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testGetPrefixMaskAsAddress_NegativePrefix() {
+        getPrefixMaskAsInet4Address(-1);
+    }
+
+    @Test
+    public void testGetBroadcastAddress() {
+        assertEquals("192.168.15.255",
+                getBroadcastAddress(IPv4Address("192.168.0.123"), 20).getHostAddress());
+        assertEquals("192.255.255.255",
+                getBroadcastAddress(IPv4Address("192.168.0.123"), 8).getHostAddress());
+        assertEquals("192.168.0.123",
+                getBroadcastAddress(IPv4Address("192.168.0.123"), 32).getHostAddress());
+        assertEquals("255.255.255.255",
+                getBroadcastAddress(IPv4Address("192.168.0.123"), 0).getHostAddress());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testGetBroadcastAddress_PrefixTooLarge() {
+        getBroadcastAddress(IPv4Address("192.168.0.123"), 33);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testGetBroadcastAddress_NegativePrefix() {
+        getBroadcastAddress(IPv4Address("192.168.0.123"), -1);
+    }
 }
diff --git a/tests/net/java/android/net/dhcp/DhcpLeaseRepositoryTest.java b/tests/net/java/android/net/dhcp/DhcpLeaseRepositoryTest.java
new file mode 100644
index 0000000..edadd6e
--- /dev/null
+++ b/tests/net/java/android/net/dhcp/DhcpLeaseRepositoryTest.java
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import static android.net.dhcp.DhcpLease.HOSTNAME_NONE;
+import static android.net.dhcp.DhcpLeaseRepository.CLIENTID_UNSPEC;
+import static android.net.dhcp.DhcpLeaseRepository.INETADDR_UNSPEC;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.when;
+
+import static java.lang.String.format;
+import static java.net.InetAddress.parseNumericAddress;
+
+import android.annotation.NonNull;
+import android.net.IpPrefix;
+import android.net.MacAddress;
+import android.net.dhcp.DhcpLeaseRepository.Clock;
+import android.net.util.SharedLog;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.net.Inet4Address;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DhcpLeaseRepositoryTest {
+    private static final Inet4Address INET4_ANY = (Inet4Address) Inet4Address.ANY;
+    private static final Inet4Address TEST_DEF_ROUTER = parseAddr4("192.168.42.247");
+    private static final Inet4Address TEST_SERVER_ADDR = parseAddr4("192.168.42.241");
+    private static final Inet4Address TEST_RESERVED_ADDR = parseAddr4("192.168.42.243");
+    private static final MacAddress TEST_MAC_1 = MacAddress.fromBytes(
+            new byte[] { 5, 4, 3, 2, 1, 0 });
+    private static final MacAddress TEST_MAC_2 = MacAddress.fromBytes(
+            new byte[] { 0, 1, 2, 3, 4, 5 });
+    private static final MacAddress TEST_MAC_3 = MacAddress.fromBytes(
+            new byte[] { 0, 1, 2, 3, 4, 6 });
+    private static final Inet4Address TEST_INETADDR_1 = parseAddr4("192.168.42.248");
+    private static final Inet4Address TEST_INETADDR_2 = parseAddr4("192.168.42.249");
+    private static final String TEST_HOSTNAME_1 = "hostname1";
+    private static final String TEST_HOSTNAME_2 = "hostname2";
+    private static final IpPrefix TEST_IP_PREFIX = new IpPrefix(TEST_SERVER_ADDR, 22);
+    private static final long TEST_TIME = 100L;
+    private static final int TEST_LEASE_TIME_MS = 3_600_000;
+    private static final Set<Inet4Address> TEST_EXCL_SET =
+            Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
+                TEST_SERVER_ADDR, TEST_DEF_ROUTER, TEST_RESERVED_ADDR)));
+
+    @NonNull
+    private SharedLog mLog;
+    @NonNull @Mock
+    private Clock mClock;
+    @NonNull
+    private DhcpLeaseRepository mRepo;
+
+    private static Inet4Address parseAddr4(String inet4Addr) {
+        return (Inet4Address) parseNumericAddress(inet4Addr);
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mLog = new SharedLog("DhcpLeaseRepositoryTest");
+        when(mClock.elapsedRealtime()).thenReturn(TEST_TIME);
+        mRepo = new DhcpLeaseRepository(
+                TEST_IP_PREFIX, TEST_EXCL_SET, TEST_LEASE_TIME_MS, mLog, mClock);
+    }
+
+    /**
+     * Request a number of addresses through offer/request. Useful to test address exhaustion.
+     * @param nAddr Number of addresses to request.
+     */
+    private void requestAddresses(byte nAddr) throws Exception {
+        final HashSet<Inet4Address> addrs = new HashSet<>();
+        byte[] hwAddrBytes = new byte[] { 8, 4, 3, 2, 1, 0 };
+        for (byte i = 0; i < nAddr; i++) {
+            hwAddrBytes[5] = i;
+            MacAddress newMac = MacAddress.fromBytes(hwAddrBytes);
+            final String hostname = "host_" + i;
+            final DhcpLease lease = mRepo.getOffer(CLIENTID_UNSPEC, newMac,
+                    INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, hostname);
+
+            assertNotNull(lease);
+            assertEquals(newMac, lease.getHwAddr());
+            assertEquals(hostname, lease.getHostname());
+            assertTrue(format("Duplicate address allocated: %s in %s", lease.getNetAddr(), addrs),
+                    addrs.add(lease.getNetAddr()));
+
+            mRepo.requestLease(null, newMac, null, lease.getNetAddr(), true, hostname);
+        }
+    }
+
+    @Test
+    public void testAddressExhaustion() throws Exception {
+        // Use a /28 to quickly run out of addresses
+        mRepo.updateParams(new IpPrefix(TEST_SERVER_ADDR, 28), TEST_EXCL_SET, TEST_LEASE_TIME_MS);
+
+        // /28 should have 16 addresses, 14 w/o the first/last, 11 w/o excluded addresses
+        requestAddresses((byte)11);
+
+        try {
+            mRepo.getOffer(null, TEST_MAC_2,
+                    null /* relayAddr */, null /* reqAddr */, HOSTNAME_NONE);
+            fail("Should be out of addresses");
+        } catch (DhcpLeaseRepository.OutOfAddressesException e) {
+            // Expected
+        }
+    }
+
+    @Test
+    public void testUpdateParams_LeaseCleanup() throws Exception {
+        // Inside /28:
+        final Inet4Address reqAddrIn28 = parseAddr4("192.168.42.242");
+        final Inet4Address declinedAddrIn28 = parseAddr4("192.168.42.245");
+
+        // Inside /28, but not available there (first address of the range)
+        final Inet4Address declinedFirstAddrIn28 = parseAddr4("192.168.42.240");
+
+        final DhcpLease reqAddrIn28Lease = mRepo.requestLease(
+                CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY, reqAddrIn28, false, HOSTNAME_NONE);
+        mRepo.markLeaseDeclined(declinedAddrIn28);
+        mRepo.markLeaseDeclined(declinedFirstAddrIn28);
+
+        // Inside /22, but outside /28:
+        final Inet4Address reqAddrIn22 = parseAddr4("192.168.42.3");
+        final Inet4Address declinedAddrIn22 = parseAddr4("192.168.42.4");
+
+        final DhcpLease reqAddrIn22Lease = mRepo.requestLease(
+                CLIENTID_UNSPEC, TEST_MAC_3, INET4_ANY, reqAddrIn22, false, HOSTNAME_NONE);
+        mRepo.markLeaseDeclined(declinedAddrIn22);
+
+        // Address that will be reserved in the updateParams call below
+        final Inet4Address reservedAddr = parseAddr4("192.168.42.244");
+        final DhcpLease reservedAddrLease = mRepo.requestLease(
+                CLIENTID_UNSPEC, TEST_MAC_2, INET4_ANY, reservedAddr, false, HOSTNAME_NONE);
+
+        // Update from /22 to /28 and add another reserved address
+        Set<Inet4Address> newReserved = new HashSet<>(TEST_EXCL_SET);
+        newReserved.add(reservedAddr);
+        mRepo.updateParams(new IpPrefix(TEST_SERVER_ADDR, 28), newReserved, TEST_LEASE_TIME_MS);
+
+        assertHasLease(reqAddrIn28Lease);
+        assertDeclined(declinedAddrIn28);
+
+        assertNotDeclined(declinedFirstAddrIn28);
+
+        assertNoLease(reqAddrIn22Lease);
+        assertNotDeclined(declinedAddrIn22);
+
+        assertNoLease(reservedAddrLease);
+    }
+
+    @Test
+    public void testGetOffer_StableAddress() throws Exception {
+        for (final MacAddress macAddr : new MacAddress[] { TEST_MAC_1, TEST_MAC_2, TEST_MAC_3 }) {
+            final DhcpLease lease = mRepo.getOffer(CLIENTID_UNSPEC, macAddr,
+                    INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+
+            // Same lease is offered twice
+            final DhcpLease newLease = mRepo.getOffer(CLIENTID_UNSPEC, macAddr,
+                    INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+            assertEquals(lease, newLease);
+        }
+    }
+
+    @Test
+    public void testUpdateParams_UsesNewPrefix() throws Exception {
+        final IpPrefix newPrefix = new IpPrefix(parseAddr4("192.168.123.0"), 24);
+        mRepo.updateParams(newPrefix, TEST_EXCL_SET, TEST_LEASE_TIME_MS);
+
+        DhcpLease lease = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
+                INETADDR_UNSPEC, INETADDR_UNSPEC, HOSTNAME_NONE);
+        assertTrue(newPrefix.contains(lease.getNetAddr()));
+    }
+
+    @Test
+    public void testGetOffer_ExistingLease() throws Exception {
+        mRepo.requestLease(
+                CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY, TEST_INETADDR_1, false, TEST_HOSTNAME_1);
+
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
+                INETADDR_UNSPEC, INETADDR_UNSPEC, HOSTNAME_NONE);
+        assertEquals(TEST_INETADDR_1, offer.getNetAddr());
+        assertEquals(TEST_HOSTNAME_1, offer.getHostname());
+    }
+
+    @Test
+    public void testGetOffer_ClientIdHasExistingLease() throws Exception {
+        final byte[] clientId = new byte[] { 1, 2 };
+        mRepo.requestLease(clientId, TEST_MAC_1, INET4_ANY, TEST_INETADDR_1, false,
+                TEST_HOSTNAME_1);
+
+        // Different MAC, but same clientId
+        DhcpLease offer = mRepo.getOffer(clientId, TEST_MAC_2,
+                INETADDR_UNSPEC, INETADDR_UNSPEC, HOSTNAME_NONE);
+        assertEquals(TEST_INETADDR_1, offer.getNetAddr());
+        assertEquals(TEST_HOSTNAME_1, offer.getHostname());
+    }
+
+    @Test
+    public void testGetOffer_DifferentClientId() throws Exception {
+        final byte[] clientId1 = new byte[] { 1, 2 };
+        final byte[] clientId2 = new byte[] { 3, 4 };
+        mRepo.requestLease(clientId1, TEST_MAC_1, INET4_ANY, TEST_INETADDR_1, false,
+                TEST_HOSTNAME_1);
+
+        // Same MAC, different client ID
+        DhcpLease offer = mRepo.getOffer(clientId2, TEST_MAC_1,
+                INETADDR_UNSPEC, INETADDR_UNSPEC, HOSTNAME_NONE);
+        // Obtains a different address
+        assertNotEquals(TEST_INETADDR_1, offer.getNetAddr());
+        assertEquals(HOSTNAME_NONE, offer.getHostname());
+        assertEquals(TEST_MAC_1, offer.getHwAddr());
+    }
+
+    @Test
+    public void testGetOffer_RequestedAddress() throws Exception {
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_1, TEST_HOSTNAME_1);
+        assertEquals(TEST_INETADDR_1, offer.getNetAddr());
+        assertEquals(TEST_HOSTNAME_1, offer.getHostname());
+    }
+
+    @Test
+    public void testGetOffer_RequestedAddressInUse() throws Exception {
+        mRepo.requestLease(
+                CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY, TEST_INETADDR_1, false, HOSTNAME_NONE);
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_2, INET4_ANY,
+                TEST_INETADDR_1, HOSTNAME_NONE);
+        assertNotEquals(TEST_INETADDR_1, offer.getNetAddr());
+    }
+
+    @Test
+    public void testGetOffer_RequestedAddressReserved() throws Exception {
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_RESERVED_ADDR, HOSTNAME_NONE);
+        assertNotEquals(TEST_RESERVED_ADDR, offer.getNetAddr());
+    }
+
+    @Test
+    public void testGetOffer_RequestedAddressInvalid() throws Exception {
+        final Inet4Address invalidAddr = parseAddr4("192.168.42.0");
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                invalidAddr, HOSTNAME_NONE);
+        assertNotEquals(invalidAddr, offer.getNetAddr());
+    }
+
+    @Test
+    public void testGetOffer_RequestedAddressOutsideSubnet() throws Exception {
+        final Inet4Address invalidAddr = parseAddr4("192.168.254.2");
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                invalidAddr, HOSTNAME_NONE);
+        assertNotEquals(invalidAddr, offer.getNetAddr());
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testGetOffer_RelayInInvalidSubnet() throws Exception {
+        mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
+                parseAddr4("192.168.254.2") /* relayAddr */, INETADDR_UNSPEC, HOSTNAME_NONE);
+    }
+
+    @Test
+    public void testRequestLease_SelectingTwice() throws Exception {
+        DhcpLease lease1 = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, TEST_HOSTNAME_1);
+
+        // Second request from same client for a different address
+        DhcpLease lease2 = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_2, true /* sidSet */, TEST_HOSTNAME_2);
+
+        assertEquals(TEST_INETADDR_1, lease1.getNetAddr());
+        assertEquals(TEST_HOSTNAME_1, lease1.getHostname());
+
+        assertEquals(TEST_INETADDR_2, lease2.getNetAddr());
+        assertEquals(TEST_HOSTNAME_2, lease2.getHostname());
+
+        // First address freed when client requested a different one: another client can request it
+        DhcpLease lease3 = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_2, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+        assertEquals(TEST_INETADDR_1, lease3.getNetAddr());
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testRequestLease_SelectingInvalid() throws Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                parseAddr4("192.168.254.5"), true /* sidSet */, HOSTNAME_NONE);
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testRequestLease_SelectingInUse() throws Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_2, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testRequestLease_SelectingReserved() throws Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_RESERVED_ADDR, true /* sidSet */, HOSTNAME_NONE);
+    }
+
+    @Test
+    public void testRequestLease_InitReboot() throws Exception {
+        // Request address once
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+
+        final long newTime = TEST_TIME + 100;
+        when(mClock.elapsedRealtime()).thenReturn(newTime);
+
+        // init-reboot (sidSet == false): verify configuration
+        DhcpLease lease = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_1, false, HOSTNAME_NONE);
+        assertEquals(TEST_INETADDR_1, lease.getNetAddr());
+        assertEquals(newTime + TEST_LEASE_TIME_MS, lease.getExpTime());
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testRequestLease_InitRebootWrongAddr() throws Exception {
+        // Request address once
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+        // init-reboot with different requested address
+        mRepo.requestLease(
+                CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY, TEST_INETADDR_2, false, HOSTNAME_NONE);
+    }
+
+    @Test
+    public void testRequestLease_InitRebootUnknownAddr() throws Exception {
+        // init-reboot with unknown requested address
+        DhcpLease lease = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_2, false, HOSTNAME_NONE);
+        // RFC2131 says we should not reply to accommodate other servers, but since we are
+        // authoritative we allow creating the lease to avoid issues with lost lease DB (same as
+        // dnsmasq behavior)
+        assertEquals(TEST_INETADDR_2, lease.getNetAddr());
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testRequestLease_InitRebootWrongSubnet() throws Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                parseAddr4("192.168.254.2"), false /* sidSet */, HOSTNAME_NONE);
+    }
+
+    @Test
+    public void testRequestLease_Renewing() throws Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1,
+                INET4_ANY /* clientAddr */, TEST_INETADDR_1 /* reqAddr */, true, HOSTNAME_NONE);
+
+        final long newTime = TEST_TIME + 100;
+        when(mClock.elapsedRealtime()).thenReturn(newTime);
+
+        // Renewing: clientAddr filled in, no reqAddr
+        DhcpLease lease = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1,
+                TEST_INETADDR_1 /* clientAddr */, INETADDR_UNSPEC /* reqAddr */, false,
+                HOSTNAME_NONE);
+
+        assertEquals(TEST_INETADDR_1, lease.getNetAddr());
+        assertEquals(newTime + TEST_LEASE_TIME_MS, lease.getExpTime());
+    }
+
+    @Test
+    public void testRequestLease_RenewingUnknownAddr() throws Exception {
+        final long newTime = TEST_TIME + 100;
+        when(mClock.elapsedRealtime()).thenReturn(newTime);
+        DhcpLease lease = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1,
+                TEST_INETADDR_1 /* clientAddr */, INETADDR_UNSPEC /* reqAddr */, false,
+                HOSTNAME_NONE);
+        // Allows renewing an unknown address if available
+        assertEquals(TEST_INETADDR_1, lease.getNetAddr());
+        assertEquals(newTime + TEST_LEASE_TIME_MS, lease.getExpTime());
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testRequestLease_RenewingAddrInUse() throws Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_2,
+                INET4_ANY /* clientAddr */, TEST_INETADDR_1 /* reqAddr */, true, HOSTNAME_NONE);
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1,
+                TEST_INETADDR_1 /* clientAddr */, INETADDR_UNSPEC /* reqAddr */, false,
+                HOSTNAME_NONE);
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testRequestLease_RenewingInvalidAddr() throws Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, parseAddr4("192.168.254.2") /* clientAddr */,
+                INETADDR_UNSPEC /* reqAddr */, false, HOSTNAME_NONE);
+    }
+
+    @Test
+    public void testReleaseLease() throws Exception {
+        DhcpLease lease1 = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+
+        assertHasLease(lease1);
+        assertTrue(mRepo.releaseLease(CLIENTID_UNSPEC, TEST_MAC_1, TEST_INETADDR_1));
+        assertNoLease(lease1);
+
+        DhcpLease lease2 = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_2, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+
+        assertEquals(TEST_INETADDR_1, lease2.getNetAddr());
+    }
+
+    @Test
+    public void testReleaseLease_UnknownLease() {
+        assertFalse(mRepo.releaseLease(CLIENTID_UNSPEC, TEST_MAC_1, TEST_INETADDR_1));
+    }
+
+    @Test
+    public void testReleaseLease_StableOffer() throws Exception {
+        for (MacAddress mac : new MacAddress[] { TEST_MAC_1, TEST_MAC_2, TEST_MAC_3 }) {
+            final DhcpLease lease = mRepo.getOffer(CLIENTID_UNSPEC, mac,
+                    INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+            mRepo.requestLease(
+                    CLIENTID_UNSPEC, mac, INET4_ANY, lease.getNetAddr(), true,
+                    HOSTNAME_NONE);
+            mRepo.releaseLease(CLIENTID_UNSPEC, mac, lease.getNetAddr());
+
+            // Same lease is offered after it was released
+            final DhcpLease newLease = mRepo.getOffer(CLIENTID_UNSPEC, mac,
+                    INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+            assertEquals(lease.getNetAddr(), newLease.getNetAddr());
+        }
+    }
+
+    @Test
+    public void testMarkLeaseDeclined() throws Exception {
+        final DhcpLease lease = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
+                INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+
+        mRepo.markLeaseDeclined(lease.getNetAddr());
+
+        // Same lease is not offered again
+        final DhcpLease newLease = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
+                INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+        assertNotEquals(lease.getNetAddr(), newLease.getNetAddr());
+    }
+
+    @Test
+    public void testMarkLeaseDeclined_UsedIfOutOfAddresses() throws Exception {
+        // Use a /28 to quickly run out of addresses
+        mRepo.updateParams(new IpPrefix(TEST_SERVER_ADDR, 28), TEST_EXCL_SET, TEST_LEASE_TIME_MS);
+
+        mRepo.markLeaseDeclined(TEST_INETADDR_1);
+        mRepo.markLeaseDeclined(TEST_INETADDR_2);
+
+        // /28 should have 16 addresses, 14 w/o the first/last, 11 w/o excluded addresses
+        requestAddresses((byte)9);
+
+        // Last 2 addresses: addresses marked declined should be used
+        final DhcpLease firstLease = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
+                INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, TEST_HOSTNAME_1);
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY, firstLease.getNetAddr(), true,
+                HOSTNAME_NONE);
+
+        final DhcpLease secondLease = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_2,
+                INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, TEST_HOSTNAME_2);
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_2, INET4_ANY, secondLease.getNetAddr(), true,
+                HOSTNAME_NONE);
+
+        // Now out of addresses
+        try {
+            mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_3, INETADDR_UNSPEC /* relayAddr */,
+                    INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+            fail("Repository should be out of addresses and throw");
+        } catch (DhcpLeaseRepository.OutOfAddressesException e) { /* expected */ }
+
+        assertEquals(TEST_INETADDR_1, firstLease.getNetAddr());
+        assertEquals(TEST_HOSTNAME_1, firstLease.getHostname());
+        assertEquals(TEST_INETADDR_2, secondLease.getNetAddr());
+        assertEquals(TEST_HOSTNAME_2, secondLease.getHostname());
+    }
+
+    private void assertNoLease(DhcpLease lease) {
+        assertFalse("Leases contain " + lease, mRepo.getCommittedLeases().contains(lease));
+    }
+
+    private void assertHasLease(DhcpLease lease) {
+        assertTrue("Leases do not contain " + lease, mRepo.getCommittedLeases().contains(lease));
+    }
+
+    private void assertNotDeclined(Inet4Address addr) {
+        assertFalse("Address is declined: " + addr, mRepo.getDeclinedAddresses().contains(addr));
+    }
+
+    private void assertDeclined(Inet4Address addr) {
+        assertTrue("Address is not declined: " + addr, mRepo.getDeclinedAddresses().contains(addr));
+    }
+}
diff --git a/tests/net/java/android/net/dhcp/DhcpServingParamsTest.java b/tests/net/java/android/net/dhcp/DhcpServingParamsTest.java
new file mode 100644
index 0000000..dfa09a9
--- /dev/null
+++ b/tests/net/java/android/net/dhcp/DhcpServingParamsTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import static android.net.dhcp.DhcpServingParams.MTU_UNSET;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static java.net.InetAddress.parseNumericAddress;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.LinkAddress;
+import android.net.dhcp.DhcpServingParams.InvalidParameterException;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.Inet4Address;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DhcpServingParamsTest {
+    @NonNull
+    private DhcpServingParams.Builder mBuilder;
+
+    private static final Set<Inet4Address> TEST_DEFAULT_ROUTERS = new HashSet<>(
+            Arrays.asList(parseAddr("192.168.0.123"), parseAddr("192.168.0.124")));
+    private static final long TEST_LEASE_TIME_SECS = 3600L;
+    private static final Set<Inet4Address> TEST_DNS_SERVERS = new HashSet<>(
+            Arrays.asList(parseAddr("192.168.0.126"), parseAddr("192.168.0.127")));
+    private static final Inet4Address TEST_SERVER_ADDR = parseAddr("192.168.0.2");
+    private static final LinkAddress TEST_LINKADDR = new LinkAddress(TEST_SERVER_ADDR, 20);
+    private static final int TEST_MTU = 1500;
+    private static final Set<Inet4Address> TEST_EXCLUDED_ADDRS = new HashSet<>(
+            Arrays.asList(parseAddr("192.168.0.200"), parseAddr("192.168.0.201")));
+
+    @Before
+    public void setUp() {
+        mBuilder = new DhcpServingParams.Builder()
+                .setDefaultRouters(TEST_DEFAULT_ROUTERS)
+                .setDhcpLeaseTimeSecs(TEST_LEASE_TIME_SECS)
+                .setDnsServers(TEST_DNS_SERVERS)
+                .setServerAddr(TEST_LINKADDR)
+                .setLinkMtu(TEST_MTU)
+                .setExcludedAddrs(TEST_EXCLUDED_ADDRS);
+    }
+
+    @Test
+    public void testBuild_Immutable() throws InvalidParameterException {
+        final Set<Inet4Address> routers = new HashSet<>(TEST_DEFAULT_ROUTERS);
+        final Set<Inet4Address> dnsServers = new HashSet<>(TEST_DNS_SERVERS);
+        final Set<Inet4Address> excludedAddrs = new HashSet<>(TEST_EXCLUDED_ADDRS);
+
+        final DhcpServingParams params = mBuilder
+                .setDefaultRouters(routers)
+                .setDnsServers(dnsServers)
+                .setExcludedAddrs(excludedAddrs)
+                .build();
+
+        // Modifications to source objects should not affect builder or final parameters
+        final Inet4Address addedAddr = parseAddr("192.168.0.223");
+        routers.add(addedAddr);
+        dnsServers.add(addedAddr);
+        excludedAddrs.add(addedAddr);
+
+        assertEquals(TEST_DEFAULT_ROUTERS, params.defaultRouters);
+        assertEquals(TEST_LEASE_TIME_SECS, params.dhcpLeaseTimeSecs);
+        assertEquals(TEST_DNS_SERVERS, params.dnsServers);
+        assertEquals(TEST_LINKADDR, params.serverAddr);
+        assertEquals(TEST_MTU, params.linkMtu);
+
+        assertContains(params.excludedAddrs, TEST_EXCLUDED_ADDRS);
+        assertContains(params.excludedAddrs, TEST_DEFAULT_ROUTERS);
+        assertContains(params.excludedAddrs, TEST_DNS_SERVERS);
+        assertContains(params.excludedAddrs, TEST_SERVER_ADDR);
+
+        assertFalse("excludedAddrs should not contain " + addedAddr,
+                params.excludedAddrs.contains(addedAddr));
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_NegativeLeaseTime() throws InvalidParameterException {
+        mBuilder.setDhcpLeaseTimeSecs(-1).build();
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_LeaseTimeTooLarge() throws InvalidParameterException {
+        // Set lease time larger than max value for uint32
+        mBuilder.setDhcpLeaseTimeSecs(1L << 32).build();
+    }
+
+    @Test
+    public void testBuild_InfiniteLeaseTime() throws InvalidParameterException {
+        final long infiniteLeaseTime = 0xffffffffL;
+        final DhcpServingParams params = mBuilder
+                .setDhcpLeaseTimeSecs(infiniteLeaseTime).build();
+        assertEquals(infiniteLeaseTime, params.dhcpLeaseTimeSecs);
+        assertTrue(params.dhcpLeaseTimeSecs > 0L);
+    }
+
+    @Test
+    public void testBuild_UnsetMtu() throws InvalidParameterException {
+        final DhcpServingParams params = mBuilder.setLinkMtu(MTU_UNSET).build();
+        assertEquals(MTU_UNSET, params.linkMtu);
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_MtuTooSmall() throws InvalidParameterException {
+        mBuilder.setLinkMtu(20).build();
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_MtuTooLarge() throws InvalidParameterException {
+        mBuilder.setLinkMtu(65_536).build();
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_IPv6Addr() throws InvalidParameterException {
+        mBuilder.setServerAddr(new LinkAddress(parseNumericAddress("fe80::1111"), 120)).build();
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_PrefixTooLarge() throws InvalidParameterException {
+        mBuilder.setServerAddr(new LinkAddress(TEST_SERVER_ADDR, 15)).build();
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_PrefixTooSmall() throws InvalidParameterException {
+        mBuilder.setDefaultRouters(Collections.singleton(parseAddr("192.168.0.254")))
+                .setServerAddr(new LinkAddress(TEST_SERVER_ADDR, 31))
+                .build();
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_RouterNotInPrefix() throws InvalidParameterException {
+        mBuilder.setDefaultRouters(Collections.singleton(parseAddr("192.168.254.254"))).build();
+    }
+
+    private static <T> void assertContains(@NonNull Set<T> set, @NonNull Set<T> subset) {
+        for (final T elem : subset) {
+            assertContains(set, elem);
+        }
+    }
+
+    private static <T> void assertContains(@NonNull Set<T> set, @Nullable T elem) {
+        assertTrue("Set does not contain " + elem, set.contains(elem));
+    }
+
+    @NonNull
+    private static Inet4Address parseAddr(@NonNull String inet4Addr) {
+        return (Inet4Address) parseNumericAddress(inet4Addr);
+    }
+}
diff --git a/tools/aapt2/cmd/Dump.cpp b/tools/aapt2/cmd/Dump.cpp
index 8e7e5e5..6bb762a 100644
--- a/tools/aapt2/cmd/Dump.cpp
+++ b/tools/aapt2/cmd/Dump.cpp
@@ -23,6 +23,7 @@
 #include "Debug.h"
 #include "Diagnostics.h"
 #include "Flags.h"
+#include "LoadedApk.h"
 #include "format/Container.h"
 #include "format/binary/BinaryResourceParser.h"
 #include "format/proto/ProtoDeserialize.h"
@@ -254,6 +255,32 @@
   return true;
 }
 
+static bool DumpPackageName(IAaptContext* context, const std::string& file_path) {
+  auto loaded_apk = LoadedApk::LoadApkFromPath(file_path, context->GetDiagnostics());
+  if (!loaded_apk) {
+    return false;
+  }
+
+  constexpr size_t kStdOutBufferSize = 1024u;
+  io::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize);
+  Printer printer(&fout);
+
+  xml::Element* manifest_el = loaded_apk->GetManifest()->root.get();
+  if (!manifest_el) {
+    context->GetDiagnostics()->Error(DiagMessage() << "No AndroidManifest.");
+    return false;
+  }
+
+  xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
+  if (!attr) {
+    context->GetDiagnostics()->Error(DiagMessage() << "No package name.");
+    return false;
+  }
+  printer.Println(StringPrintf("%s", attr->value.c_str()));
+
+  return true;
+}
+
 namespace {
 
 class DumpContext : public IAaptContext {
@@ -324,9 +351,20 @@
   DumpContext context;
   context.SetVerbose(verbose);
 
+  auto parsedArgs = flags.GetArgs();
+  if (parsedArgs.size() > 1 && parsedArgs[0] == "packagename") {
+    parsedArgs.erase(parsedArgs.begin());
+    for (const std::string& arg : parsedArgs) {
+      if (!DumpPackageName(&context, arg)) {
+        return 1;
+      }
+    }
+    return 0;
+  }
+
   options.print_options.show_sources = true;
   options.print_options.show_values = !no_values;
-  for (const std::string& arg : flags.GetArgs()) {
+  for (const std::string& arg : parsedArgs) {
     if (!TryDumpFile(&context, arg, options)) {
       return 1;
     }