Merge "Fix/suppress hwui/tests google-explicit-constructor warnings"
diff --git a/api/current.txt b/api/current.txt
index 5fa75a8..1d60e8f 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -11315,8 +11315,11 @@
field public static final java.lang.String FEATURE_MICROPHONE = "android.hardware.microphone";
field public static final java.lang.String FEATURE_MIDI = "android.software.midi";
field public static final java.lang.String FEATURE_NFC = "android.hardware.nfc";
+ field public static final java.lang.String FEATURE_NFC_BEAM = "android.sofware.nfc.beam";
field public static final java.lang.String FEATURE_NFC_HOST_CARD_EMULATION = "android.hardware.nfc.hce";
field public static final java.lang.String FEATURE_NFC_HOST_CARD_EMULATION_NFCF = "android.hardware.nfc.hcef";
+ field public static final java.lang.String FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE = "android.hardware.nfc.ese";
+ field public static final java.lang.String FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC = "android.hardware.nfc.uicc";
field public static final java.lang.String FEATURE_OPENGLES_EXTENSION_PACK = "android.hardware.opengles.aep";
field public static final java.lang.String FEATURE_PC = "android.hardware.type.pc";
field public static final java.lang.String FEATURE_PICTURE_IN_PICTURE = "android.software.picture_in_picture";
@@ -29165,15 +29168,16 @@
method public deprecated void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage);
method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle);
method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context);
+ method public java.util.List<java.lang.String> getSupportedOffHostSecureElements();
method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler);
- method public boolean invokeBeam(android.app.Activity);
+ method public deprecated boolean invokeBeam(android.app.Activity);
method public boolean isEnabled();
- method public boolean isNdefPushEnabled();
- method public void setBeamPushUris(android.net.Uri[], android.app.Activity);
- method public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity);
- method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
- method public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...);
- method public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
+ method public deprecated boolean isNdefPushEnabled();
+ method public deprecated void setBeamPushUris(android.net.Uri[], android.app.Activity);
+ method public deprecated void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity);
+ method public deprecated void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
+ method public deprecated void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...);
+ method public deprecated void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
field public static final java.lang.String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
field public static final java.lang.String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
field public static final java.lang.String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
@@ -29200,15 +29204,15 @@
field public static final int STATE_TURNING_ON = 2; // 0x2
}
- public static abstract interface NfcAdapter.CreateBeamUrisCallback {
+ public static abstract deprecated interface NfcAdapter.CreateBeamUrisCallback {
method public abstract android.net.Uri[] createBeamUris(android.nfc.NfcEvent);
}
- public static abstract interface NfcAdapter.CreateNdefMessageCallback {
+ public static abstract deprecated interface NfcAdapter.CreateNdefMessageCallback {
method public abstract android.nfc.NdefMessage createNdefMessage(android.nfc.NfcEvent);
}
- public static abstract interface NfcAdapter.OnNdefPushCompleteCallback {
+ public static abstract deprecated interface NfcAdapter.OnNdefPushCompleteCallback {
method public abstract void onNdefPushComplete(android.nfc.NfcEvent);
}
@@ -29256,8 +29260,10 @@
method public boolean isDefaultServiceForCategory(android.content.ComponentName, java.lang.String);
method public boolean registerAidsForService(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>);
method public boolean removeAidsForService(android.content.ComponentName, java.lang.String);
+ method public boolean setOffHostForService(android.content.ComponentName, java.lang.String);
method public boolean setPreferredService(android.app.Activity, android.content.ComponentName);
method public boolean supportsAidPrefixRegistration();
+ method public boolean unsetOffHostForService(android.content.ComponentName);
method public boolean unsetPreferredService(android.app.Activity);
field public static final java.lang.String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
field public static final java.lang.String CATEGORY_OTHER = "other";
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index caac8ae..0c561e6 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -2878,7 +2878,6 @@
Lcom/android/internal/telephony/dataconnection/DataConnection;->mPhone:Lcom/android/internal/telephony/Phone;
Lcom/android/internal/telephony/dataconnection/DataConnection;->mRilRat:I
Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyAllOfConnected(Ljava/lang/String;)V
-Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyAllOfDisconnectDcRetrying(Ljava/lang/String;)V
Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyDisconnectCompleted(Lcom/android/internal/telephony/dataconnection/DataConnection$DisconnectParams;Z)V
Lcom/android/internal/telephony/dataconnection/DataConnection;->onConnect(Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;)V
Lcom/android/internal/telephony/dataconnection/DataConnection;->tearDownData(Ljava/lang/Object;)V
@@ -2916,8 +2915,6 @@
Lcom/android/internal/telephony/dataconnection/DcTracker;->mResolver:Landroid/content/ContentResolver;
Lcom/android/internal/telephony/dataconnection/DcTracker;->mState:Lcom/android/internal/telephony/DctConstants$State;
Lcom/android/internal/telephony/dataconnection/DcTracker;->mSubscriptionManager:Landroid/telephony/SubscriptionManager;
-Lcom/android/internal/telephony/dataconnection/DcTracker;->notifyDataConnection(Ljava/lang/String;)V
-Lcom/android/internal/telephony/dataconnection/DcTracker;->notifyOffApnsOfAvailability(Ljava/lang/String;)V
Lcom/android/internal/telephony/dataconnection/DcTracker;->onActionIntentDataStallAlarm(Landroid/content/Intent;)V
Lcom/android/internal/telephony/dataconnection/DcTracker;->onActionIntentProvisioningApnAlarm(Landroid/content/Intent;)V
Lcom/android/internal/telephony/dataconnection/DcTracker;->onRecordsLoadedOrSubIdChanged()V
@@ -2946,7 +2943,6 @@
Lcom/android/internal/telephony/DctConstants$State;->FAILED:Lcom/android/internal/telephony/DctConstants$State;
Lcom/android/internal/telephony/DctConstants$State;->IDLE:Lcom/android/internal/telephony/DctConstants$State;
Lcom/android/internal/telephony/DctConstants$State;->RETRYING:Lcom/android/internal/telephony/DctConstants$State;
-Lcom/android/internal/telephony/DctConstants$State;->SCANNING:Lcom/android/internal/telephony/DctConstants$State;
Lcom/android/internal/telephony/DctConstants$State;->values()[Lcom/android/internal/telephony/DctConstants$State;
Lcom/android/internal/telephony/DefaultPhoneNotifier;->mRegistry:Lcom/android/internal/telephony/ITelephonyRegistry;
Lcom/android/internal/telephony/DriverCall$State;->ACTIVE:Lcom/android/internal/telephony/DriverCall$State;
@@ -3370,7 +3366,7 @@
Lcom/android/internal/telephony/ITelephonyRegistry;->listen(Ljava/lang/String;Lcom/android/internal/telephony/IPhoneStateListener;IZ)V
Lcom/android/internal/telephony/ITelephonyRegistry;->notifyCallState(ILjava/lang/String;)V
Lcom/android/internal/telephony/ITelephonyRegistry;->notifyCellInfo(Ljava/util/List;)V
-Lcom/android/internal/telephony/ITelephonyRegistry;->notifyDataConnectionFailed(Ljava/lang/String;Ljava/lang/String;)V
+Lcom/android/internal/telephony/ITelephonyRegistry;->notifyDataConnectionFailed(Ljava/lang/String;)V
Lcom/android/internal/telephony/IWapPushManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IWapPushManager;
Lcom/android/internal/telephony/IWapPushManager;->addPackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZ)Z
Lcom/android/internal/telephony/IWapPushManager;->deletePackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 1394c35..83e8785 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1914,6 +1914,30 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports uicc-
+ * based NFC card emulation.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC =
+ "android.hardware.nfc.uicc";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports eSE-
+ * based NFC card emulation.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE = "android.hardware.nfc.ese";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The Beam API is enabled on the device.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_NFC_BEAM = "android.sofware.nfc.beam";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports any
* one of the {@link #FEATURE_NFC}, {@link #FEATURE_NFC_HOST_CARD_EMULATION},
* or {@link #FEATURE_NFC_HOST_CARD_EMULATION_NFCF} features.
diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/core/java/android/nfc/INfcCardEmulation.aidl
index d1b132c..dd2c0d4 100644
--- a/core/java/android/nfc/INfcCardEmulation.aidl
+++ b/core/java/android/nfc/INfcCardEmulation.aidl
@@ -31,6 +31,8 @@
boolean setDefaultServiceForCategory(int userHandle, in ComponentName service, String category);
boolean setDefaultForNextTap(int userHandle, in ComponentName service);
boolean registerAidGroupForService(int userHandle, in ComponentName service, in AidGroup aidGroup);
+ boolean setOffHostForService(int userHandle, in ComponentName service, in String offHostSecureElement);
+ boolean unsetOffHostForService(int userHandle, in ComponentName service);
AidGroup getAidGroupForService(int userHandle, in ComponentName service, String category);
boolean removeAidGroupForService(int userHandle, in ComponentName service, String category);
List<ApduServiceInfo> getServices(int userHandle, in String category);
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 21fed48..e55e036 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -16,6 +16,7 @@
package android.nfc;
+import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -42,7 +43,9 @@
import android.util.Log;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
/**
* Represents the local NFC adapter.
@@ -322,6 +325,7 @@
// Guarded by NfcAdapter.class
static boolean sIsInitialized = false;
static boolean sHasNfcFeature;
+ static boolean sHasBeamFeature;
// Final after first constructor, except for
// attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
@@ -369,7 +373,9 @@
* A callback to be invoked when the system successfully delivers your {@link NdefMessage}
* to another device.
* @see #setOnNdefPushCompleteCallback
+ * @deprecated this feature is deprecated.
*/
+ @java.lang.Deprecated
public interface OnNdefPushCompleteCallback {
/**
* Called on successful NDEF push.
@@ -392,7 +398,9 @@
* content currently visible to the user. Alternatively, you can call {@link
* #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the
* same data.
+ * @deprecated this feature is deprecated.
*/
+ @java.lang.Deprecated
public interface CreateNdefMessageCallback {
/**
* Called to provide a {@link NdefMessage} to push.
@@ -418,7 +426,10 @@
}
- // TODO javadoc
+ /**
+ * @deprecated this feature is deprecated.
+ */
+ @java.lang.Deprecated
public interface CreateBeamUrisCallback {
public Uri[] createBeamUris(NfcEvent event);
}
@@ -446,6 +457,25 @@
public boolean onUnlockAttempted(Tag tag);
}
+ /**
+ * Helper to check if this device has FEATURE_NFC_BEAM, but without using
+ * a context.
+ * Equivalent to
+ * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_BEAM)
+ */
+ private static boolean hasBeamFeature() {
+ IPackageManager pm = ActivityThread.getPackageManager();
+ if (pm == null) {
+ Log.e(TAG, "Cannot get package manager, assuming no Android Beam feature");
+ return false;
+ }
+ try {
+ return pm.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM, 0);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Package manager query failed, assuming no Android Beam feature", e);
+ return false;
+ }
+ }
/**
* Helper to check if this device has FEATURE_NFC, but without using
@@ -488,6 +518,35 @@
}
/**
+ * Return list of Secure Elements which support off host card emulation.
+ *
+ * @return List<String> containing secure elements on the device which supports
+ * off host card emulation. eSE for Embedded secure element,
+ * SIM for UICC and so on.
+ */
+ public @NonNull List<String> getSupportedOffHostSecureElements() {
+ List<String> offHostSE = new ArrayList<String>();
+ IPackageManager pm = ActivityThread.getPackageManager();
+ if (pm == null) {
+ Log.e(TAG, "Cannot get package manager, assuming no off-host CE feature");
+ return offHostSE;
+ }
+ try {
+ if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC, 0)) {
+ offHostSE.add("SIM");
+ }
+ if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE, 0)) {
+ offHostSE.add("eSE");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Package manager query failed, assuming no off-host CE feature", e);
+ offHostSE.clear();
+ return offHostSE;
+ }
+ return offHostSE;
+ }
+
+ /**
* Returns the NfcAdapter for application context,
* or throws if NFC is not available.
* @hide
@@ -496,6 +555,7 @@
public static synchronized NfcAdapter getNfcAdapter(Context context) {
if (!sIsInitialized) {
sHasNfcFeature = hasNfcFeature();
+ sHasBeamFeature = hasBeamFeature();
boolean hasHceFeature = hasNfcHceFeature();
/* is this device meant to have NFC */
if (!sHasNfcFeature && !hasHceFeature) {
@@ -921,12 +981,17 @@
* @param uris an array of Uri(s) to push over Android Beam
* @param activity activity for which the Uri(s) will be pushed
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @deprecated this feature is deprecated.
*/
+ @java.lang.Deprecated
public void setBeamPushUris(Uri[] uris, Activity activity) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return;
+ }
}
if (activity == null) {
throw new NullPointerException("activity cannot be null");
@@ -1003,12 +1068,17 @@
* @param callback callback, or null to disable
* @param activity activity for which the Uri(s) will be pushed
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @deprecated this feature is deprecated.
*/
+ @java.lang.Deprecated
public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return;
+ }
}
if (activity == null) {
throw new NullPointerException("activity cannot be null");
@@ -1087,13 +1157,18 @@
* to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @deprecated this feature is deprecated.
*/
+ @java.lang.Deprecated
public void setNdefPushMessage(NdefMessage message, Activity activity,
Activity ... activities) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return;
+ }
}
int targetSdkVersion = getSdkVersion();
try {
@@ -1200,13 +1275,18 @@
* to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @deprecated this feature is deprecated.
*/
+ @java.lang.Deprecated
public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
Activity ... activities) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return;
+ }
}
int targetSdkVersion = getSdkVersion();
try {
@@ -1281,13 +1361,18 @@
* to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @deprecated this feature is deprecated.
*/
+ @java.lang.Deprecated
public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback,
Activity activity, Activity ... activities) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return;
+ }
}
int targetSdkVersion = getSdkVersion();
try {
@@ -1492,12 +1577,17 @@
* @param activity the current foreground Activity that has registered data to share
* @return whether the Beam animation was successfully invoked
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @deprecated this feature is deprecated.
*/
+ @java.lang.Deprecated
public boolean invokeBeam(Activity activity) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return false;
+ }
}
if (activity == null) {
throw new NullPointerException("activity may not be null.");
@@ -1561,6 +1651,9 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return;
+ }
}
if (activity == null || message == null) {
throw new NullPointerException();
@@ -1595,6 +1688,9 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return;
+ }
}
if (activity == null) {
throw new NullPointerException();
@@ -1668,12 +1764,18 @@
* @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS
* @return true if NDEF Push feature is enabled
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @deprecated this feature is deprecated.
*/
+ @java.lang.Deprecated
+
public boolean isNdefPushEnabled() {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return false;
+ }
}
try {
return sService.isNdefPushEnabled();
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index e8d801c..911ec84 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -18,11 +18,10 @@
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
-import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.content.res.TypedArray;
@@ -30,7 +29,6 @@
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.ResultReceiver;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
@@ -69,6 +67,18 @@
final boolean mOnHost;
/**
+ * Offhost reader name.
+ * eg: SIM, eSE etc
+ */
+ String mOffHostName;
+
+ /**
+ * Offhost reader name from manifest file.
+ * Used for unsetOffHostSecureElement()
+ */
+ final String mStaticOffHostName;
+
+ /**
* Mapping from category to static AID group
*/
@UnsupportedAppUsage
@@ -104,15 +114,17 @@
* @hide
*/
@UnsupportedAppUsage
- public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
+ public ApduServiceInfo(ResolveInfo info, String description,
ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
boolean requiresUnlock, int bannerResource, int uid,
- String settingsActivityName) {
+ String settingsActivityName, String offHost, String staticOffHost) {
this.mService = info;
this.mDescription = description;
this.mStaticAidGroups = new HashMap<String, AidGroup>();
this.mDynamicAidGroups = new HashMap<String, AidGroup>();
- this.mOnHost = onHost;
+ this.mOffHostName = offHost;
+ this.mStaticOffHostName = staticOffHost;
+ this.mOnHost = (offHost == null);
this.mRequiresDeviceUnlock = requiresUnlock;
for (AidGroup aidGroup : staticAidGroups) {
this.mStaticAidGroups.put(aidGroup.category, aidGroup);
@@ -174,6 +186,8 @@
com.android.internal.R.styleable.HostApduService_apduServiceBanner, -1);
mSettingsActivityName = sa.getString(
com.android.internal.R.styleable.HostApduService_settingsActivity);
+ mOffHostName = null;
+ mStaticOffHostName = mOffHostName;
sa.recycle();
} else {
TypedArray sa = res.obtainAttributes(attrs,
@@ -186,6 +200,16 @@
com.android.internal.R.styleable.OffHostApduService_apduServiceBanner, -1);
mSettingsActivityName = sa.getString(
com.android.internal.R.styleable.HostApduService_settingsActivity);
+ mOffHostName = sa.getString(
+ com.android.internal.R.styleable.OffHostApduService_secureElementName);
+ if (mOffHostName != null) {
+ if (mOffHostName.equals("eSE")) {
+ mOffHostName = "eSE1";
+ } else if (mOffHostName.equals("SIM")) {
+ mOffHostName = "SIM1";
+ }
+ }
+ mStaticOffHostName = mOffHostName;
sa.recycle();
}
@@ -289,6 +313,10 @@
mService.serviceInfo.name);
}
+ public String getOffHostSecureElement() {
+ return mOffHostName;
+ }
+
/**
* Returns a consolidated list of AIDs from the AID groups
* registered by this service. Note that if a service has both
@@ -404,6 +432,20 @@
mDynamicAidGroups.put(aidGroup.getCategory(), aidGroup);
}
+ @UnsupportedAppUsage
+ public void setOffHostSecureElement(String offHost) {
+ mOffHostName = offHost;
+ }
+
+ /**
+ * Resets the off host Secure Element to statically defined
+ * by the service in the manifest file.
+ */
+ @UnsupportedAppUsage
+ public void unsetOffHostSecureElement() {
+ mOffHostName = mStaticOffHostName;
+ }
+
public CharSequence loadLabel(PackageManager pm) {
return mService.loadLabel(pm);
}
@@ -481,6 +523,8 @@
mService.writeToParcel(dest, flags);
dest.writeString(mDescription);
dest.writeInt(mOnHost ? 1 : 0);
+ dest.writeString(mOffHostName);
+ dest.writeString(mStaticOffHostName);
dest.writeInt(mStaticAidGroups.size());
if (mStaticAidGroups.size() > 0) {
dest.writeTypedList(new ArrayList<AidGroup>(mStaticAidGroups.values()));
@@ -503,6 +547,8 @@
ResolveInfo info = ResolveInfo.CREATOR.createFromParcel(source);
String description = source.readString();
boolean onHost = source.readInt() != 0;
+ String offHostName = source.readString();
+ String staticOffHostName = source.readString();
ArrayList<AidGroup> staticAidGroups = new ArrayList<AidGroup>();
int numStaticGroups = source.readInt();
if (numStaticGroups > 0) {
@@ -517,9 +563,9 @@
int bannerResource = source.readInt();
int uid = source.readInt();
String settingsActivityName = source.readString();
- return new ApduServiceInfo(info, onHost, description, staticAidGroups,
+ return new ApduServiceInfo(info, description, staticAidGroups,
dynamicAidGroups, requiresUnlock, bannerResource, uid,
- settingsActivityName);
+ settingsActivityName, offHostName, staticOffHostName);
}
@Override
@@ -531,6 +577,14 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(" " + getComponent() +
" (Description: " + getDescription() + ")");
+ if (mOnHost) {
+ pw.println(" On Host Service");
+ } else {
+ pw.println(" Off-host Service");
+ pw.println(" " + "Current off-host SE" + mOffHostName
+ + " static off-host: " + mOffHostName);
+ }
+ pw.println(" Static off-host Secure Element:");
pw.println(" Static AID groups:");
for (AidGroup group : mStaticAidGroups.values()) {
pw.println(" Category: " + group.category);
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 15d02f2..01932ab 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -27,7 +27,6 @@
import android.nfc.INfcCardEmulation;
import android.nfc.NfcAdapter;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;
@@ -345,6 +344,108 @@
}
/**
+ * Unsets the off-host Secure Element for the given service.
+ *
+ * <p>Note that this will only remove Secure Element that was dynamically
+ * set using the {@link #setOffHostForService(ComponentName, String)}
+ * and resets it to a value that was statically assigned using manifest.
+ *
+ * <p>Note that you can only unset off-host SE for a service that
+ * is running under the same UID as the caller of this API. Typically
+ * this means you need to call this from the same
+ * package as the service itself, though UIDs can also
+ * be shared between packages using shared UIDs.
+ *
+ * @param service The component name of the service
+ * @return whether the registration was successful.
+ */
+ public boolean unsetOffHostForService(ComponentName service) {
+ NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
+ if (adapter == null) {
+ return false;
+ }
+
+ try {
+ return sService.unsetOffHostForService(mContext.getUserId(), service);
+ } catch (RemoteException e) {
+ // Try one more time
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
+ try {
+ return sService.unsetOffHostForService(mContext.getUserId(), service);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to reach CardEmulationService.");
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Sets the off-host Secure Element for the given service.
+ *
+ * <p>If off-host SE was initially set (either statically
+ * through the manifest, or dynamically by using this API),
+ * it will be replaced with this one. All AIDs registered by
+ * this service will be re-routed to this Secure Element if
+ * successful.
+ *
+ * <p>Note that you can only set off-host SE for a service that
+ * is running under the same UID as the caller of this API. Typically
+ * this means you need to call this from the same
+ * package as the service itself, though UIDs can also
+ * be shared between packages using shared UIDs.
+ *
+ * <p>Registeration will be successful only if the Secure Element
+ * exists on the device.
+ *
+ * @param service The component name of the service
+ * @param offHostSecureElement Secure Element to register the AID to
+ * @return whether the registration was successful.
+ */
+ public boolean setOffHostForService(ComponentName service, String offHostSecureElement) {
+ boolean validSecureElement = false;
+
+ NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
+ if (adapter == null || offHostSecureElement == null) {
+ return false;
+ }
+
+ List<String> validSE = adapter.getSupportedOffHostSecureElements();
+ if ((offHostSecureElement.startsWith("eSE") && !validSE.contains("eSE"))
+ || (offHostSecureElement.startsWith("SIM") && !validSE.contains("SIM"))) {
+ return false;
+ }
+
+ if (offHostSecureElement.equals("eSE")) {
+ offHostSecureElement = "eSE1";
+ } else if (offHostSecureElement.equals("SIM")) {
+ offHostSecureElement = "SIM1";
+ }
+
+ try {
+ return sService.setOffHostForService(mContext.getUserId(), service,
+ offHostSecureElement);
+ } catch (RemoteException e) {
+ // Try one more time
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
+ try {
+ return sService.setOffHostForService(mContext.getUserId(), service,
+ offHostSecureElement);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to reach CardEmulationService.");
+ return false;
+ }
+ }
+ }
+
+ /**
* Retrieves the currently registered AIDs for the specified
* category for a service.
*
diff --git a/core/java/android/view/AccessibilityIterators.java b/core/java/android/view/AccessibilityIterators.java
index 9f7560c..54cfc00 100644
--- a/core/java/android/view/AccessibilityIterators.java
+++ b/core/java/android/view/AccessibilityIterators.java
@@ -147,6 +147,9 @@
@Override
public void onConfigurationChanged(Configuration globalConfig) {
final Locale locale = globalConfig.getLocales().get(0);
+ if (locale == null) {
+ return;
+ }
if (!mLocale.equals(locale)) {
mLocale = locale;
onLocaleChanged(locale);
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 80a3cf0..7232890 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -17,6 +17,7 @@
package android.view;
import android.annotation.LayoutRes;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.annotation.UnsupportedAppUsage;
@@ -774,24 +775,8 @@
ta.recycle();
}
- if (name.equals(TAG_1995)) {
- // Let's party like it's 1995!
- return new BlinkLayout(context, attrs);
- }
-
try {
- View view;
- if (mFactory2 != null) {
- view = mFactory2.onCreateView(parent, name, context, attrs);
- } else if (mFactory != null) {
- view = mFactory.onCreateView(name, context, attrs);
- } else {
- view = null;
- }
-
- if (view == null && mPrivateFactory != null) {
- view = mPrivateFactory.onCreateView(parent, name, context, attrs);
- }
+ View view = tryCreateView(parent, name, context, attrs);
if (view == null) {
final Object lastContext = mConstructorArgs[0];
@@ -826,6 +811,48 @@
}
/**
+ * Tries to create a view from a tag name using the supplied attribute set.
+ *
+ * This method gives the factory provided by {@link LayoutInflater#setFactory} and
+ * {@link LayoutInflater#setFactory2} a chance to create a view. However, it does not apply all
+ * of the general view creation logic, and thus may return {@code null} for some tags. This
+ * method is used by {@link LayoutInflater#inflate} in creating {@code View} objects.
+ *
+ * @hide for use by precompiled layouts.
+ *
+ * @param parent the parent view, used to inflate layout params
+ * @param name the name of the XML tag used to define the view
+ * @param context the inflation context for the view, typically the
+ * {@code parent} or base layout inflater context
+ * @param attrs the attribute set for the XML tag used to define the view
+ */
+ @UnsupportedAppUsage(trackingBug = 122360734)
+ @Nullable
+ public final View tryCreateView(@Nullable View parent, @NonNull String name,
+ @NonNull Context context,
+ @NonNull AttributeSet attrs) {
+ if (name.equals(TAG_1995)) {
+ // Let's party like it's 1995!
+ return new BlinkLayout(context, attrs);
+ }
+
+ View view;
+ if (mFactory2 != null) {
+ view = mFactory2.onCreateView(parent, name, context, attrs);
+ } else if (mFactory != null) {
+ view = mFactory.onCreateView(name, context, attrs);
+ } else {
+ view = null;
+ }
+
+ if (view == null && mPrivateFactory != null) {
+ view = mPrivateFactory.onCreateView(parent, name, context, attrs);
+ }
+
+ return view;
+ }
+
+ /**
* Recursive method used to inflate internal (non-root) children. This
* method calls through to {@link #rInflate} using the parent context as
* the inflation context.
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 21c10ce..b4d74af 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3690,6 +3690,8 @@
<!-- Component name of an activity that allows the user to modify
the settings for this service. -->
<attr name="settingsActivity"/>
+ <!-- Secure Element which the AIDs should be routed to -->
+ <attr name="secureElementName"/>
</declare-styleable>
<!-- Specify one or more <code>aid-group</code> elements inside a
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 190e99f..6d10632 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1313,16 +1313,17 @@
}
}
- public void notifyDataConnection(int state, boolean isDataAllowed,
- String reason, String apn, String apnType, LinkProperties linkProperties,
- NetworkCapabilities networkCapabilities, int networkType, boolean roaming) {
+ public void notifyDataConnection(int state, boolean isDataAllowed, String apn, String apnType,
+ LinkProperties linkProperties,
+ NetworkCapabilities networkCapabilities, int networkType,
+ boolean roaming) {
notifyDataConnectionForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, state,
- isDataAllowed,reason, apn, apnType, linkProperties,
- networkCapabilities, networkType, roaming);
+ isDataAllowed, apn, apnType, linkProperties,
+ networkCapabilities, networkType, roaming);
}
- public void notifyDataConnectionForSubscriber(int subId, int state,
- boolean isDataAllowed, String reason, String apn, String apnType,
+ public void notifyDataConnectionForSubscriber(int subId, int state, boolean isDataAllowed,
+ String apn, String apnType,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int networkType, boolean roaming) {
if (!checkNotifyPermission("notifyDataConnection()" )) {
@@ -1331,7 +1332,6 @@
if (VDBG) {
log("notifyDataConnectionForSubscriber: subId=" + subId
+ " state=" + state + " isDataAllowed=" + isDataAllowed
- + " reason='" + reason
+ "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType
+ " mRecords.size()=" + mRecords.size());
}
@@ -1366,7 +1366,7 @@
mDataConnectionNetworkType[phoneId] = networkType;
}
mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType,
- apnType, apn, reason, linkProperties, "");
+ apnType, apn, linkProperties, "");
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)) {
@@ -1381,30 +1381,29 @@
}
handleRemoveListLocked();
}
- broadcastDataConnectionStateChanged(state, isDataAllowed, reason, apn,
- apnType, linkProperties, networkCapabilities, roaming, subId);
- broadcastPreciseDataConnectionStateChanged(state, networkType, apnType, apn, reason,
+ broadcastDataConnectionStateChanged(state, isDataAllowed, apn, apnType, linkProperties,
+ networkCapabilities, roaming, subId);
+ broadcastPreciseDataConnectionStateChanged(state, networkType, apnType, apn,
linkProperties, "");
}
- public void notifyDataConnectionFailed(String reason, String apnType) {
+ public void notifyDataConnectionFailed(String apnType) {
notifyDataConnectionFailedForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- reason, apnType);
+ apnType);
}
- public void notifyDataConnectionFailedForSubscriber(int subId,
- String reason, String apnType) {
+ public void notifyDataConnectionFailedForSubscriber(int subId, String apnType) {
if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
return;
}
if (VDBG) {
log("notifyDataConnectionFailedForSubscriber: subId=" + subId
- + " reason=" + reason + " apnType=" + apnType);
+ + " apnType=" + apnType);
}
synchronized (mRecords) {
mPreciseDataConnectionState = new PreciseDataConnectionState(
TelephonyManager.DATA_UNKNOWN,TelephonyManager.NETWORK_TYPE_UNKNOWN,
- apnType, "", reason, null, "");
+ apnType, "", null, "");
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)) {
@@ -1417,9 +1416,9 @@
}
handleRemoveListLocked();
}
- broadcastDataConnectionFailed(reason, apnType, subId);
+ broadcastDataConnectionFailed(apnType, subId);
broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
- TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, "", reason, null, "");
+ TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, "", null, "");
}
public void notifyCellLocation(Bundle cellLocation) {
@@ -1529,15 +1528,14 @@
}
}
- public void notifyPreciseDataConnectionFailed(String reason, String apnType,
- String apn, String failCause) {
+ public void notifyPreciseDataConnectionFailed(String apnType, String apn, String failCause) {
if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) {
return;
}
synchronized (mRecords) {
mPreciseDataConnectionState = new PreciseDataConnectionState(
TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- apnType, apn, reason, null, failCause);
+ apnType, apn, null, failCause);
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)) {
@@ -1551,7 +1549,7 @@
handleRemoveListLocked();
}
broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
- TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, apn, reason, null, failCause);
+ TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, apn, null, failCause);
}
@Override
@@ -1882,10 +1880,10 @@
android.Manifest.permission.READ_CALL_LOG});
}
- private void broadcastDataConnectionStateChanged(int state,
- boolean isDataAllowed,
- String reason, String apn, String apnType, LinkProperties linkProperties,
- NetworkCapabilities networkCapabilities, boolean roaming, int subId) {
+ private void broadcastDataConnectionStateChanged(int state, boolean isDataAllowed, String apn,
+ String apnType, LinkProperties linkProperties,
+ NetworkCapabilities networkCapabilities,
+ boolean roaming, int subId) {
// Note: not reporting to the battery stats service here, because the
// status bar takes care of that after taking into account all of the
// required info.
@@ -1895,9 +1893,6 @@
if (!isDataAllowed) {
intent.putExtra(PhoneConstants.NETWORK_UNAVAILABLE_KEY, true);
}
- if (reason != null) {
- intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason);
- }
if (linkProperties != null) {
intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties);
String iface = linkProperties.getInterfaceName();
@@ -1916,17 +1911,15 @@
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
- private void broadcastDataConnectionFailed(String reason, String apnType,
- int subId) {
+ private void broadcastDataConnectionFailed(String apnType, int subId) {
Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
- intent.putExtra(PhoneConstants.FAILURE_REASON_KEY, reason);
intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
private void broadcastPreciseCallStateChanged(int ringingCallState, int foregroundCallState,
- int backgroundCallState) {
+ int backgroundCallState) {
Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_CALL_STATE_CHANGED);
intent.putExtra(TelephonyManager.EXTRA_RINGING_CALL_STATE, ringingCallState);
intent.putExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, foregroundCallState);
@@ -1936,16 +1929,16 @@
}
private void broadcastPreciseDataConnectionStateChanged(int state, int networkType,
- String apnType, String apn, String reason, LinkProperties linkProperties,
- String failCause) {
+ String apnType, String apn,
+ LinkProperties linkProperties,
+ String failCause) {
Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED);
intent.putExtra(PhoneConstants.STATE_KEY, state);
intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType);
- if (reason != null) intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason);
if (apnType != null) intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
if (apn != null) intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
if (linkProperties != null) {
- intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY,linkProperties);
+ intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties);
}
if (failCause != null) intent.putExtra(PhoneConstants.DATA_FAILURE_CAUSE_KEY, failCause);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 9fa42ab..e539ffd 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -270,14 +270,12 @@
* enforcement.
*
* <p>
- * This class uses 2-3 locks to synchronize state:
+ * This class uses 2 locks to synchronize state:
* <ul>
* <li>{@code mUidRulesFirstLock}: used to guard state related to individual UIDs (such as firewall
* rules).
* <li>{@code mNetworkPoliciesSecondLock}: used to guard state related to network interfaces (such
* as network policies).
- * <li>{@code allLocks}: not a "real" lock, but an indication (through @GuardedBy) that all locks
- * must be held.
* </ul>
*
* <p>
@@ -419,7 +417,8 @@
final Object mUidRulesFirstLock = new Object();
final Object mNetworkPoliciesSecondLock = new Object();
- @GuardedBy("allLocks") volatile boolean mSystemReady;
+ @GuardedBy({"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"})
+ volatile boolean mSystemReady;
@GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictBackground;
@GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictPower;
@@ -545,7 +544,7 @@
private final ServiceThread mUidEventThread;
- @GuardedBy("allLocks")
+ @GuardedBy({"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"})
private final AtomicFile mPolicyFile;
private final AppOpsManager mAppOps;
diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp
index 91cec554..82056e9 100644
--- a/startop/view_compiler/Android.bp
+++ b/startop/view_compiler/Android.bp
@@ -34,6 +34,7 @@
defaults: ["viewcompiler_defaults"],
srcs: [
"dex_builder.cc",
+ "dex_layout_compiler.cc",
"java_lang_builder.cc",
"tinyxml_layout_parser.cc",
"util.cc",
diff --git a/startop/view_compiler/dex_builder_test/Android.bp b/startop/view_compiler/dex_builder_test/Android.bp
index 4449ea0..d4f38ed 100644
--- a/startop/view_compiler/dex_builder_test/Android.bp
+++ b/startop/view_compiler/dex_builder_test/Android.bp
@@ -14,16 +14,30 @@
// limitations under the License.
//
+genrule {
+ name: "generate_compiled_layout",
+ tools: [":viewcompiler"],
+ cmd: "$(location :viewcompiler) $(in) --dex --out $(out) --package android.startop.test",
+ srcs: ["res/layout/layout1.xml"],
+ out: [
+ "layout1.dex",
+ ],
+}
+
android_test {
name: "dex-builder-test",
- srcs: ["src/android/startop/test/DexBuilderTest.java"],
+ srcs: [
+ "src/android/startop/test/DexBuilderTest.java",
+ "src/android/startop/test/LayoutCompilerTest.java",
+ ],
sdk_version: "current",
- data: [":generate_dex_testcases"],
+ data: [":generate_dex_testcases", ":generate_compiled_layout"],
static_libs: [
"android-support-test",
"guava",
],
manifest: "AndroidManifest.xml",
+ resource_dirs: ["res"],
test_config: "AndroidTest.xml",
test_suites: ["general-tests"],
}
diff --git a/startop/view_compiler/dex_builder_test/AndroidTest.xml b/startop/view_compiler/dex_builder_test/AndroidTest.xml
index 6f90cf3..68d8fdc 100644
--- a/startop/view_compiler/dex_builder_test/AndroidTest.xml
+++ b/startop/view_compiler/dex_builder_test/AndroidTest.xml
@@ -25,6 +25,7 @@
<option name="cleanup" value="true" />
<option name="push" value="trivial.dex->/data/local/tmp/dex-builder-test/trivial.dex" />
<option name="push" value="simple.dex->/data/local/tmp/dex-builder-test/simple.dex" />
+ <option name="push" value="layout1.dex->/data/local/tmp/dex-builder-test/layout1.dex" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/startop/view_compiler/dex_builder_test/res/layout/layout1.xml b/startop/view_compiler/dex_builder_test/res/layout/layout1.xml
new file mode 100644
index 0000000..0f9375c
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/res/layout/layout1.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:orientation="vertical"
+ android:gravity="center">
+
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+
+ </LinearLayout>
diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java
new file mode 100644
index 0000000..ce3ce83
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.startop.test;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.view.View;
+import com.google.common.io.ByteStreams;
+import dalvik.system.InMemoryDexClassLoader;
+import dalvik.system.PathClassLoader;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import org.junit.Assert;
+import org.junit.Test;
+
+// Adding tests here requires changes in several other places. See README.md in
+// the view_compiler directory for more information.
+public class LayoutCompilerTest {
+ static ClassLoader loadDexFile(String filename) throws Exception {
+ return new PathClassLoader("/data/local/tmp/dex-builder-test/" + filename,
+ ClassLoader.getSystemClassLoader());
+ }
+
+ @Test
+ public void loadAndInflaterLayout1() throws Exception {
+ ClassLoader dex_file = loadDexFile("layout1.dex");
+ Class compiled_view = dex_file.loadClass("android.startop.test.CompiledView");
+ Method layout1 = compiled_view.getMethod("layout1", Context.class, int.class);
+ Context context = InstrumentationRegistry.getTargetContext();
+ layout1.invoke(null, context, R.layout.layout1);
+ }
+}
diff --git a/startop/view_compiler/dex_layout_compiler.cc b/startop/view_compiler/dex_layout_compiler.cc
new file mode 100644
index 0000000..c68793d
--- /dev/null
+++ b/startop/view_compiler/dex_layout_compiler.cc
@@ -0,0 +1,226 @@
+/*
+ * 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.
+ */
+
+#include "dex_layout_compiler.h"
+#include "layout_validation.h"
+
+#include "android-base/stringprintf.h"
+
+namespace startop {
+
+using android::base::StringPrintf;
+
+void LayoutValidationVisitor::VisitStartTag(const std::u16string& name) {
+ if (0 == name.compare(u"merge")) {
+ message_ = "Merge tags are not supported";
+ can_compile_ = false;
+ }
+ if (0 == name.compare(u"include")) {
+ message_ = "Include tags are not supported";
+ can_compile_ = false;
+ }
+ if (0 == name.compare(u"view")) {
+ message_ = "View tags are not supported";
+ can_compile_ = false;
+ }
+ if (0 == name.compare(u"fragment")) {
+ message_ = "Fragment tags are not supported";
+ can_compile_ = false;
+ }
+}
+
+DexViewBuilder::DexViewBuilder(dex::MethodBuilder* method)
+ : method_{method},
+ context_{dex::Value::Parameter(0)},
+ resid_{dex::Value::Parameter(1)},
+ inflater_{method->MakeRegister()},
+ xml_{method->MakeRegister()},
+ attrs_{method->MakeRegister()},
+ classname_tmp_{method->MakeRegister()},
+ xml_next_{method->dex_file()->GetOrDeclareMethod(
+ dex::TypeDescriptor::FromClassname("android.content.res.XmlResourceParser"), "next",
+ dex::Prototype{dex::TypeDescriptor::Int()})},
+ try_create_view_{method->dex_file()->GetOrDeclareMethod(
+ dex::TypeDescriptor::FromClassname("android.view.LayoutInflater"), "tryCreateView",
+ dex::Prototype{dex::TypeDescriptor::FromClassname("android.view.View"),
+ dex::TypeDescriptor::FromClassname("android.view.View"),
+ dex::TypeDescriptor::FromClassname("java.lang.String"),
+ dex::TypeDescriptor::FromClassname("android.content.Context"),
+ dex::TypeDescriptor::FromClassname("android.util.AttributeSet")})},
+ generate_layout_params_{method->dex_file()->GetOrDeclareMethod(
+ dex::TypeDescriptor::FromClassname("android.view.ViewGroup"), "generateLayoutParams",
+ dex::Prototype{dex::TypeDescriptor::FromClassname("android.view.ViewGroup$LayoutParams"),
+ dex::TypeDescriptor::FromClassname("android.util.AttributeSet")})},
+ add_view_{method->dex_file()->GetOrDeclareMethod(
+ dex::TypeDescriptor::FromClassname("android.view.ViewGroup"), "addView",
+ dex::Prototype{
+ dex::TypeDescriptor::Void(),
+ dex::TypeDescriptor::FromClassname("android.view.View"),
+ dex::TypeDescriptor::FromClassname("android.view.ViewGroup$LayoutParams")})},
+ // The register stack starts with one register, which will be null for the root view.
+ register_stack_{{method->MakeRegister()}} {}
+
+void DexViewBuilder::Start() {
+ dex::DexBuilder* const dex = method_->dex_file();
+
+ // LayoutInflater inflater = LayoutInflater.from(context);
+ auto layout_inflater_from = dex->GetOrDeclareMethod(
+ dex::TypeDescriptor::FromClassname("android.view.LayoutInflater"),
+ "from",
+ dex::Prototype{dex::TypeDescriptor::FromClassname("android.view.LayoutInflater"),
+ dex::TypeDescriptor::FromClassname("android.content.Context")});
+ method_->AddInstruction(
+ dex::Instruction::InvokeStaticObject(layout_inflater_from.id, /*dest=*/inflater_, context_));
+
+ // Resources res = context.getResources();
+ auto context_type = dex::TypeDescriptor::FromClassname("android.content.Context");
+ auto resources_type = dex::TypeDescriptor::FromClassname("android.content.res.Resources");
+ auto get_resources =
+ dex->GetOrDeclareMethod(context_type, "getResources", dex::Prototype{resources_type});
+ method_->AddInstruction(dex::Instruction::InvokeVirtualObject(get_resources.id, xml_, context_));
+
+ // XmlResourceParser xml = res.getLayout(resid);
+ auto xml_resource_parser_type =
+ dex::TypeDescriptor::FromClassname("android.content.res.XmlResourceParser");
+ auto get_layout =
+ dex->GetOrDeclareMethod(resources_type,
+ "getLayout",
+ dex::Prototype{xml_resource_parser_type, dex::TypeDescriptor::Int()});
+ method_->AddInstruction(dex::Instruction::InvokeVirtualObject(get_layout.id, xml_, xml_, resid_));
+
+ // AttributeSet attrs = Xml.asAttributeSet(xml);
+ auto as_attribute_set = dex->GetOrDeclareMethod(
+ dex::TypeDescriptor::FromClassname("android.util.Xml"),
+ "asAttributeSet",
+ dex::Prototype{dex::TypeDescriptor::FromClassname("android.util.AttributeSet"),
+ dex::TypeDescriptor::FromClassname("org.xmlpull.v1.XmlPullParser")});
+ method_->AddInstruction(dex::Instruction::InvokeStaticObject(as_attribute_set.id, attrs_, xml_));
+
+ // xml.next(); // start document
+ method_->AddInstruction(dex::Instruction::InvokeInterface(xml_next_.id, {}, xml_));
+}
+
+void DexViewBuilder::Finish() {}
+
+namespace {
+std::string ResolveName(const std::string& name) {
+ if (name == "View") return "android.view.View";
+ if (name == "ViewGroup") return "android.view.ViewGroup";
+ if (name.find(".") == std::string::npos) {
+ return StringPrintf("android.widget.%s", name.c_str());
+ }
+ return name;
+}
+} // namespace
+
+void DexViewBuilder::StartView(const std::string& name, bool is_viewgroup) {
+ bool const is_root_view = view_stack_.empty();
+
+ // xml.next(); // start tag
+ method_->AddInstruction(dex::Instruction::InvokeInterface(xml_next_.id, {}, xml_));
+
+ dex::Value view = AcquireRegister();
+ // try to create the view using the factories
+ method_->BuildConstString(classname_tmp_,
+ name); // TODO: the need to fully qualify the classname
+ if (is_root_view) {
+ dex::Value null = AcquireRegister();
+ method_->BuildConst4(null, 0);
+ method_->AddInstruction(dex::Instruction::InvokeVirtualObject(
+ try_create_view_.id, view, inflater_, null, classname_tmp_, context_, attrs_));
+ ReleaseRegister();
+ } else {
+ method_->AddInstruction(dex::Instruction::InvokeVirtualObject(
+ try_create_view_.id, view, inflater_, GetCurrentView(), classname_tmp_, context_, attrs_));
+ }
+ auto label = method_->MakeLabel();
+ // branch if not null
+ method_->AddInstruction(
+ dex::Instruction::OpWithArgs(dex::Instruction::Op::kBranchNEqz, /*dest=*/{}, view, label));
+
+ // If null, create the class directly.
+ method_->BuildNew(view,
+ dex::TypeDescriptor::FromClassname(ResolveName(name)),
+ dex::Prototype{dex::TypeDescriptor::Void(),
+ dex::TypeDescriptor::FromClassname("android.content.Context"),
+ dex::TypeDescriptor::FromClassname("android.util.AttributeSet")},
+ context_,
+ attrs_);
+
+ method_->AddInstruction(
+ dex::Instruction::OpWithArgs(dex::Instruction::Op::kBindLabel, /*dest=*/{}, label));
+
+ if (is_viewgroup) {
+ // Cast to a ViewGroup so we can add children later.
+ const ir::Type* view_group_def = method_->dex_file()->GetOrAddType(
+ dex::TypeDescriptor::FromClassname("android.view.ViewGroup").descriptor());
+ method_->AddInstruction(dex::Instruction::Cast(view, dex::Value::Type(view_group_def->orig_index)));
+ }
+
+ if (!is_root_view) {
+ // layout_params = parent.generateLayoutParams(attrs);
+ dex::Value layout_params{AcquireRegister()};
+ method_->AddInstruction(dex::Instruction::InvokeVirtualObject(
+ generate_layout_params_.id, layout_params, GetCurrentView(), attrs_));
+ view_stack_.push_back({view, layout_params});
+ } else {
+ view_stack_.push_back({view, {}});
+ }
+}
+
+void DexViewBuilder::FinishView() {
+ if (view_stack_.size() == 1) {
+ method_->BuildReturn(GetCurrentView(), /*is_object=*/true);
+ } else {
+ // parent.add(view, layout_params)
+ method_->AddInstruction(dex::Instruction::InvokeVirtual(
+ add_view_.id, /*dest=*/{}, GetParentView(), GetCurrentView(), GetCurrentLayoutParams()));
+ // xml.next(); // end tag
+ method_->AddInstruction(dex::Instruction::InvokeInterface(xml_next_.id, {}, xml_));
+ }
+ PopViewStack();
+}
+
+dex::Value DexViewBuilder::AcquireRegister() {
+ top_register_++;
+ if (register_stack_.size() == top_register_) {
+ register_stack_.push_back(method_->MakeRegister());
+ }
+ return register_stack_[top_register_];
+}
+
+void DexViewBuilder::ReleaseRegister() { top_register_--; }
+
+dex::Value DexViewBuilder::GetCurrentView() const { return view_stack_.back().view; }
+dex::Value DexViewBuilder::GetCurrentLayoutParams() const {
+ return view_stack_.back().layout_params.value();
+}
+dex::Value DexViewBuilder::GetParentView() const {
+ return view_stack_[view_stack_.size() - 2].view;
+}
+
+void DexViewBuilder::PopViewStack() {
+ const auto& top = view_stack_.back();
+ // release the layout params if we have them
+ if (top.layout_params.has_value()) {
+ ReleaseRegister();
+ }
+ // Unconditionally release the view register.
+ ReleaseRegister();
+ view_stack_.pop_back();
+}
+
+} // namespace startop
\ No newline at end of file
diff --git a/startop/view_compiler/dex_layout_compiler.h b/startop/view_compiler/dex_layout_compiler.h
new file mode 100644
index 0000000..170a1a6
--- /dev/null
+++ b/startop/view_compiler/dex_layout_compiler.h
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+#ifndef DEX_LAYOUT_COMPILER_H_
+#define DEX_LAYOUT_COMPILER_H_
+
+#include "dex_builder.h"
+
+#include <codecvt>
+#include <locale>
+#include <string>
+#include <vector>
+
+namespace startop {
+
+// This visitor does the actual view compilation, using a supplied builder.
+template <typename Builder>
+class LayoutCompilerVisitor {
+ public:
+ explicit LayoutCompilerVisitor(Builder* builder) : builder_{builder} {}
+
+ void VisitStartDocument() { builder_->Start(); }
+ void VisitEndDocument() { builder_->Finish(); }
+ void VisitStartTag(const std::u16string& name) {
+ parent_stack_.push_back(ViewEntry{
+ std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.to_bytes(name), {}});
+ }
+ void VisitEndTag() {
+ auto entry = parent_stack_.back();
+ parent_stack_.pop_back();
+
+ if (parent_stack_.empty()) {
+ GenerateCode(entry);
+ } else {
+ parent_stack_.back().children.push_back(entry);
+ }
+ }
+
+ private:
+ struct ViewEntry {
+ std::string name;
+ std::vector<ViewEntry> children;
+ };
+
+ void GenerateCode(const ViewEntry& view) {
+ builder_->StartView(view.name, !view.children.empty());
+ for (const auto& child : view.children) {
+ GenerateCode(child);
+ }
+ builder_->FinishView();
+ }
+
+ Builder* builder_;
+
+ std::vector<ViewEntry> parent_stack_;
+};
+
+class DexViewBuilder {
+ public:
+ DexViewBuilder(dex::MethodBuilder* method);
+
+ void Start();
+ void Finish();
+ void StartView(const std::string& name, bool is_viewgroup);
+ void FinishView();
+
+ private:
+ // Accessors for the stack of views that are under construction.
+ dex::Value AcquireRegister();
+ void ReleaseRegister();
+ dex::Value GetCurrentView() const;
+ dex::Value GetCurrentLayoutParams() const;
+ dex::Value GetParentView() const;
+ void PopViewStack();
+
+ dex::MethodBuilder* method_;
+
+ // Registers used for code generation
+ dex::Value const context_;
+ dex::Value const resid_;
+ const dex::Value inflater_;
+ const dex::Value xml_;
+ const dex::Value attrs_;
+ const dex::Value classname_tmp_;
+
+ const dex::MethodDeclData xml_next_;
+ const dex::MethodDeclData try_create_view_;
+ const dex::MethodDeclData generate_layout_params_;
+ const dex::MethodDeclData add_view_;
+
+ // used for keeping track of which registers are in use
+ size_t top_register_{0};
+ std::vector<dex::Value> register_stack_;
+
+ // Keep track of the views currently in progress.
+ struct ViewEntry {
+ dex::Value view;
+ std::optional<dex::Value> layout_params;
+ };
+ std::vector<ViewEntry> view_stack_;
+};
+
+} // namespace startop
+
+#endif // DEX_LAYOUT_COMPILER_H_
diff --git a/startop/view_compiler/java_lang_builder.cc b/startop/view_compiler/java_lang_builder.cc
index 0b8754f..920caee 100644
--- a/startop/view_compiler/java_lang_builder.cc
+++ b/startop/view_compiler/java_lang_builder.cc
@@ -67,7 +67,7 @@
"}\n"; // end CompiledView
}
-void JavaLangViewBuilder::StartView(const string& class_name) {
+void JavaLangViewBuilder::StartView(const string& class_name, bool /*is_viewgroup*/) {
const string view_var = MakeVar("view");
const string layout_var = MakeVar("layout");
std::string parent = "null";
diff --git a/startop/view_compiler/java_lang_builder.h b/startop/view_compiler/java_lang_builder.h
index c8d20b2..69356d3 100644
--- a/startop/view_compiler/java_lang_builder.h
+++ b/startop/view_compiler/java_lang_builder.h
@@ -35,7 +35,7 @@
void Finish() const;
// Begin creating a view (i.e. process the opening tag)
- void StartView(const std::string& class_name);
+ void StartView(const std::string& class_name, bool is_viewgroup);
// Finish a view, after all of its child nodes have been processed.
void FinishView();
diff --git a/startop/view_compiler/main.cc b/startop/view_compiler/main.cc
index 609bcf3..ae00187 100644
--- a/startop/view_compiler/main.cc
+++ b/startop/view_compiler/main.cc
@@ -16,8 +16,11 @@
#include "gflags/gflags.h"
+#include "android-base/stringprintf.h"
#include "dex_builder.h"
+#include "dex_layout_compiler.h"
#include "java_lang_builder.h"
+#include "layout_validation.h"
#include "tinyxml_layout_parser.h"
#include "util.h"
@@ -32,6 +35,12 @@
namespace {
using namespace tinyxml2;
+using android::base::StringPrintf;
+using startop::dex::ClassBuilder;
+using startop::dex::DexBuilder;
+using startop::dex::MethodBuilder;
+using startop::dex::Prototype;
+using startop::dex::TypeDescriptor;
using namespace startop::util;
using std::string;
@@ -41,34 +50,44 @@
DEFINE_string(out, kStdoutFilename, "Where to write the generated class");
DEFINE_string(package, "", "The package name for the generated class (required)");
-class ViewCompilerXmlVisitor : public XMLVisitor {
+template <typename Visitor>
+class XmlVisitorAdapter : public XMLVisitor {
public:
- explicit ViewCompilerXmlVisitor(JavaLangViewBuilder* builder) : builder_(builder) {}
+ explicit XmlVisitorAdapter(Visitor* visitor) : visitor_{visitor} {}
bool VisitEnter(const XMLDocument& /*doc*/) override {
- builder_->Start();
+ visitor_->VisitStartDocument();
return true;
}
bool VisitExit(const XMLDocument& /*doc*/) override {
- builder_->Finish();
+ visitor_->VisitEndDocument();
return true;
}
bool VisitEnter(const XMLElement& element, const XMLAttribute* /*firstAttribute*/) override {
- builder_->StartView(element.Name());
+ visitor_->VisitStartTag(
+ std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(
+ element.Name()));
return true;
}
bool VisitExit(const XMLElement& /*element*/) override {
- builder_->FinishView();
+ visitor_->VisitEndTag();
return true;
}
private:
- JavaLangViewBuilder* builder_;
+ Visitor* visitor_;
};
+template <typename Builder>
+void CompileLayout(XMLDocument* xml, Builder* builder) {
+ startop::LayoutCompilerVisitor visitor{builder};
+ XmlVisitorAdapter<decltype(visitor)> adapter{&visitor};
+ xml->Accept(&adapter);
+}
+
} // end namespace
int main(int argc, char** argv) {
@@ -88,16 +107,8 @@
return 1;
}
- if (FLAGS_dex) {
- startop::dex::WriteTestDexFile("test.dex");
- return 0;
- }
-
const char* const filename = argv[kFileNameParam];
- const string layout_name = FindLayoutNameFromFilename(filename);
-
- // We want to generate Java language code to inflate exactly this layout. This means
- // generating code to walk the resource XML too.
+ const string layout_name = startop::util::FindLayoutNameFromFilename(filename);
XMLDocument xml;
xml.LoadFile(filename);
@@ -108,15 +119,34 @@
return 1;
}
+ const bool is_stdout = FLAGS_out == kStdoutFilename;
+
std::ofstream outfile;
- if (FLAGS_out != kStdoutFilename) {
+ if (!is_stdout) {
outfile.open(FLAGS_out);
}
- JavaLangViewBuilder builder{
- FLAGS_package, layout_name, FLAGS_out == kStdoutFilename ? std::cout : outfile};
- ViewCompilerXmlVisitor visitor{&builder};
- xml.Accept(&visitor);
+ if (FLAGS_dex) {
+ DexBuilder dex_file;
+ string class_name = StringPrintf("%s.CompiledView", FLAGS_package.c_str());
+ ClassBuilder compiled_view{dex_file.MakeClass(class_name)};
+ MethodBuilder method{compiled_view.CreateMethod(
+ layout_name,
+ Prototype{TypeDescriptor::FromClassname("android.view.View"),
+ TypeDescriptor::FromClassname("android.content.Context"),
+ TypeDescriptor::Int()})};
+ startop::DexViewBuilder builder{&method};
+ CompileLayout(&xml, &builder);
+ method.Encode();
+ slicer::MemView image{dex_file.CreateImage()};
+
+ (is_stdout ? std::cout : outfile).write(image.ptr<const char>(), image.size());
+ } else {
+ // Generate Java language output.
+ JavaLangViewBuilder builder{FLAGS_package, layout_name, is_stdout ? std::cout : outfile};
+
+ CompileLayout(&xml, &builder);
+ }
return 0;
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 4561ea3..89b646f 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2242,7 +2242,7 @@
* e.g.) To use RSCP by default, set the value to "rscp". The signal strength level will
* then be determined by #KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY
* <p>
- * Currently this only supports the value "rscp"
+ * Currently this supports the value "rscp" and "rssi".
* @hide
*/
// FIXME: this key and related keys must not be exposed without a consistent philosophy for
@@ -2690,7 +2690,7 @@
-95, /* SIGNAL_STRENGTH_GOOD */
-85 /* SIGNAL_STRENGTH_GREAT */
});
- sDefaults.putString(KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING, "");
+ sDefaults.putString(KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING, "rssi");
sDefaults.putBoolean(KEY_CONFIG_SHOW_ORIG_DIAL_STRING_FOR_CDMA_BOOL, false);
sDefaults.putBoolean(KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL, false);
sDefaults.putBoolean(KEY_CALL_FORWARDING_OVER_UT_WARNING_BOOL, false);
diff --git a/telephony/java/android/telephony/CellSignalStrength.java b/telephony/java/android/telephony/CellSignalStrength.java
index a18275f..7d07a73 100644
--- a/telephony/java/android/telephony/CellSignalStrength.java
+++ b/telephony/java/android/telephony/CellSignalStrength.java
@@ -42,6 +42,9 @@
public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
/** @hide */
+ protected static final int NUM_SIGNAL_STRENGTH_THRESHOLDS = NUM_SIGNAL_STRENGTH_BINS - 1;
+
+ /** @hide */
public static final String[] SIGNAL_STRENGTH_NAMES = {
"none", "poor", "moderate", "good", "great"
};
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index 88f6fbc..0760407 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -21,6 +21,7 @@
import android.os.Parcelable;
import android.os.PersistableBundle;
import android.telephony.Rlog;
+import android.text.TextUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -41,8 +42,18 @@
private static final int WCDMA_RSSI_POOR = -107;
private static final int WCDMA_RSSI_MIN = -113;
- private static final int WCDMA_RSCP_MIN = -120;
+ private static final int[] sRssiThresholds = new int[]{
+ WCDMA_RSSI_POOR, WCDMA_RSSI_MODERATE, WCDMA_RSSI_GOOD, WCDMA_RSSI_GREAT};
+
private static final int WCDMA_RSCP_MAX = -24;
+ private static final int WCDMA_RSCP_GREAT = -85;
+ private static final int WCDMA_RSCP_GOOD = -95;
+ private static final int WCDMA_RSCP_MODERATE = -105;
+ private static final int WCDMA_RSCP_POOR = -115;
+ private static final int WCDMA_RSCP_MIN = -120;
+
+ private static final int[] sRscpThresholds = new int[] {
+ WCDMA_RSCP_POOR, WCDMA_RSCP_MODERATE, WCDMA_RSCP_GOOD, WCDMA_RSCP_GREAT};
// TODO: Because these are used as values in CarrierConfig, they should be exposed somehow.
/** @hide */
@@ -54,6 +65,9 @@
/** @hide */
public static final String LEVEL_CALCULATION_METHOD_RSCP = "rscp";
+ // Default to RSSI for backwards compatibility with older devices
+ private static final String sLevelCalculationMethod = LEVEL_CALCULATION_METHOD_RSSI;
+
private int mRssi; // in dBm [-113, 51] or CellInfo.UNAVAILABLE if unknown
private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
// CellInfo.UNAVAILABLE if unknown
@@ -121,10 +135,6 @@
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
- private static final String sLevelCalculationMethod = LEVEL_CALCULATION_METHOD_RSSI;
- private static final int[] sThresholds = new int[]{
- WCDMA_RSSI_POOR, WCDMA_RSSI_GOOD, WCDMA_RSSI_GOOD, WCDMA_RSSI_GREAT};
-
/**
* Retrieve an abstract level value for the overall signal strength.
*
@@ -140,41 +150,46 @@
@Override
public void updateLevel(PersistableBundle cc, ServiceState ss) {
String calcMethod;
- int[] thresholds;
+ int[] rscpThresholds;
if (cc == null) {
calcMethod = sLevelCalculationMethod;
- thresholds = sThresholds;
+ rscpThresholds = sRscpThresholds;
} else {
// TODO: abstract this entire thing into a series of functions
calcMethod = cc.getString(
CarrierConfigManager.KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING,
sLevelCalculationMethod);
- thresholds = cc.getIntArray(
+ if (TextUtils.isEmpty(calcMethod)) calcMethod = sLevelCalculationMethod;
+ rscpThresholds = cc.getIntArray(
CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY);
- if (thresholds == null) thresholds = sThresholds;
+ if (rscpThresholds == null || rscpThresholds.length != NUM_SIGNAL_STRENGTH_THRESHOLDS) {
+ rscpThresholds = sRscpThresholds;
+ }
}
- int level = thresholds.length;
+ int level = NUM_SIGNAL_STRENGTH_THRESHOLDS;
switch (calcMethod) {
case LEVEL_CALCULATION_METHOD_RSCP:
if (mRscp < WCDMA_RSCP_MIN || mRscp > WCDMA_RSCP_MAX) {
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
return;
}
- while (level > 0 && mRscp < thresholds[level - 1]) level--;
+ while (level > 0 && mRscp < rscpThresholds[level - 1]) level--;
mLevel = level;
return;
+ default:
+ loge("Invalid Level Calculation Method for CellSignalStrengthWcdma = "
+ + calcMethod);
+ /** fall through */
case LEVEL_CALCULATION_METHOD_RSSI:
if (mRssi < WCDMA_RSSI_MIN || mRssi > WCDMA_RSSI_MAX) {
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
return;
}
- while (level > 0 && mRssi < thresholds[level - 1]) level--;
+ while (level > 0 && mRssi < sRssiThresholds[level - 1]) level--;
mLevel = level;
return;
- default:
- mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
}
@@ -204,7 +219,7 @@
}
/**
- * Get the signal strength as dBm
+ * Get the RSSI as dBm
*
* @hide
*/
@@ -214,12 +229,32 @@
/**
* Get the RSCP as dBm
+ *
* @hide
*/
public int getRscp() {
return mRscp;
}
+ /**
+ * Get the Ec/No as dB
+ *
+ * @hide
+ */
+ public int getEcNo() {
+ return mEcNo;
+ }
+
+ /**
+ * Return the Bit Error Rate
+ *
+ * @returns the bit error rate (0-7, 99) as defined in TS 27.007 8.5 or UNAVAILABLE.
+ * @hide
+ */
+ public int getBitErrorRate() {
+ return mBitErrorRate;
+ }
+
@Override
public int hashCode() {
return Objects.hash(mRssi, mBitErrorRate, mRscp, mEcNo, mLevel);
@@ -304,9 +339,16 @@
};
/**
- * log
+ * log warning
*/
private static void log(String s) {
Rlog.w(LOG_TAG, s);
}
+
+ /**
+ * log error
+ */
+ private static void loge(String s) {
+ Rlog.e(LOG_TAG, s);
+ }
}
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index b258f52..8373899 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -17,10 +17,11 @@
package android.telephony;
import android.annotation.UnsupportedAppUsage;
+import android.net.LinkProperties;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.TelephonyManager;
-import android.net.LinkProperties;
+
+import java.util.Objects;
/**
* Contains precise data connection state.
@@ -32,7 +33,6 @@
* <li>Network type of the connection.
* <li>APN type.
* <li>APN.
- * <li>Data connection change reason.
* <li>The properties of the network link.
* <li>Data connection fail cause.
* </ul>
@@ -45,7 +45,6 @@
private int mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
private String mAPNType = "";
private String mAPN = "";
- private String mReason = "";
private LinkProperties mLinkProperties = null;
private String mFailCause = "";
@@ -55,14 +54,12 @@
* @hide
*/
@UnsupportedAppUsage
- public PreciseDataConnectionState(int state, int networkType,
- String apnType, String apn, String reason,
- LinkProperties linkProperties, String failCause) {
+ public PreciseDataConnectionState(int state, int networkType, String apnType, String apn,
+ LinkProperties linkProperties, String failCause) {
mState = state;
mNetworkType = networkType;
mAPNType = apnType;
mAPN = apn;
- mReason = reason;
mLinkProperties = linkProperties;
mFailCause = failCause;
}
@@ -83,7 +80,6 @@
mNetworkType = in.readInt();
mAPNType = in.readString();
mAPN = in.readString();
- mReason = in.readString();
mLinkProperties = (LinkProperties)in.readParcelable(null);
mFailCause = in.readString();
}
@@ -144,14 +140,6 @@
}
/**
- * Get data connection change reason.
- */
- @UnsupportedAppUsage
- public String getDataConnectionChangeReason() {
- return mReason;
- }
-
- /**
* Get the properties of the network link.
*/
@UnsupportedAppUsage
@@ -178,7 +166,6 @@
out.writeInt(mNetworkType);
out.writeString(mAPNType);
out.writeString(mAPN);
- out.writeString(mReason);
out.writeParcelable(mLinkProperties, flags);
out.writeString(mFailCause);
}
@@ -197,16 +184,7 @@
@Override
public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + mState;
- result = prime * result + mNetworkType;
- result = prime * result + ((mAPNType == null) ? 0 : mAPNType.hashCode());
- result = prime * result + ((mAPN == null) ? 0 : mAPN.hashCode());
- result = prime * result + ((mReason == null) ? 0 : mReason.hashCode());
- result = prime * result + ((mLinkProperties == null) ? 0 : mLinkProperties.hashCode());
- result = prime * result + ((mFailCause == null) ? 0 : mFailCause.hashCode());
- return result;
+ return Objects.hash(mState, mNetworkType, mAPNType, mAPN, mLinkProperties, mFailCause);
}
@Override
@@ -252,13 +230,6 @@
if (mNetworkType != other.mNetworkType) {
return false;
}
- if (mReason == null) {
- if (other.mReason != null) {
- return false;
- }
- } else if (!mReason.equals(other.mReason)) {
- return false;
- }
if (mState != other.mState) {
return false;
}
@@ -273,7 +244,6 @@
sb.append(", Network type: " + mNetworkType);
sb.append(", APN type: " + mAPNType);
sb.append(", APN: " + mAPN);
- sb.append(", Change reason: " + mReason);
sb.append(", Link properties: " + mLinkProperties);
sb.append(", Fail cause: " + mFailCause);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 2286ce2..739c80f 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -772,7 +772,6 @@
* The {@link #EXTRA_DATA_NETWORK_TYPE} extra indicates the connection network type.
* The {@link #EXTRA_DATA_APN_TYPE} extra indicates the APN type.
* The {@link #EXTRA_DATA_APN} extra indicates the APN.
- * The {@link #EXTRA_DATA_CHANGE_REASON} extra indicates the connection change reason.
* The {@link #EXTRA_DATA_IFACE_PROPERTIES} extra indicates the connection interface.
* The {@link #EXTRA_DATA_FAILURE_CAUSE} extra indicates the connection fail cause.
*
@@ -783,7 +782,6 @@
* @see #EXTRA_DATA_NETWORK_TYPE
* @see #EXTRA_DATA_APN_TYPE
* @see #EXTRA_DATA_APN
- * @see #EXTRA_DATA_CHANGE_REASON
* @see #EXTRA_DATA_IFACE
* @see #EXTRA_DATA_FAILURE_CAUSE
* @hide
@@ -872,18 +870,6 @@
/**
* The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
- * for an String representation of the change reason.
- *
- * <p class="note">
- * Retrieve with
- * {@link android.content.Intent#getStringExtra(String name)}.
- *
- * @hide
- */
- public static final String EXTRA_DATA_CHANGE_REASON = PhoneConstants.STATE_CHANGE_REASON_KEY;
-
- /**
- * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
* for an String representation of the data interface.
*
* <p class="note">
diff --git a/telephony/java/android/telephony/ims/Rcs1To1Thread.java b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
index 5122c7d..709b3aa 100644
--- a/telephony/java/android/telephony/ims/Rcs1To1Thread.java
+++ b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
@@ -23,6 +23,10 @@
* @hide - TODO(sahinc) make this public
*/
public class Rcs1To1Thread extends RcsThread {
+ public Rcs1To1Thread(int threadId) {
+ super(threadId);
+ }
+
public static final Creator<Rcs1To1Thread> CREATOR = new Creator<Rcs1To1Thread>() {
@Override
public Rcs1To1Thread createFromParcel(Parcel in) {
@@ -36,6 +40,7 @@
};
protected Rcs1To1Thread(Parcel in) {
+ super(in);
}
@Override
@@ -45,5 +50,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(RCS_1_TO_1_TYPE);
+ super.writeToParcel(dest, flags);
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThread.java b/telephony/java/android/telephony/ims/RcsGroupThread.java
index 150c4d4..d954b2d 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThread.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThread.java
@@ -36,6 +36,7 @@
};
protected RcsGroupThread(Parcel in) {
+ super(in);
}
@Override
@@ -45,5 +46,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(RCS_GROUP_TYPE);
+ super.writeToParcel(dest, flags);
}
}
diff --git a/telephony/java/android/telephony/ims/RcsMessageStore.java b/telephony/java/android/telephony/ims/RcsMessageStore.java
index 4198c78..1bf6ffd 100644
--- a/telephony/java/android/telephony/ims/RcsMessageStore.java
+++ b/telephony/java/android/telephony/ims/RcsMessageStore.java
@@ -16,6 +16,8 @@
package android.telephony.ims;
+import android.annotation.Nullable;
+import android.annotation.WorkerThread;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.Rlog;
@@ -27,26 +29,93 @@
* @hide - TODO make this public
*/
public class RcsMessageStore {
- private static final String TAG = "RcsMessageStore";
- private static final boolean VDBG = false;
+ static final String TAG = "RcsMessageStore";
/**
- * Delete the RcsThread identified by the given threadId.
+ * Returns the first chunk of existing {@link RcsThread}s in the common storage.
+ * @param queryParameters Parameters to specify to return a subset of all RcsThreads.
+ * Passing a value of null will return all threads.
+ */
+ @WorkerThread
+ public RcsThreadQueryResult getRcsThreads(@Nullable RcsThreadQueryParameters queryParameters) {
+ try {
+ IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService("ircs"));
+ if (iRcs != null) {
+ return iRcs.getRcsThreads(queryParameters);
+ }
+ } catch (RemoteException re) {
+ Rlog.e(TAG, "RcsMessageStore: Exception happened during getRcsThreads", re);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the next chunk of {@link RcsThread}s in the common storage.
+ * @param continuationToken A token to continue the query to get the next chunk. This is
+ * obtained through {@link RcsThreadQueryResult#nextChunkToken}.
+ */
+ @WorkerThread
+ public RcsThreadQueryResult getRcsThreads(RcsThreadQueryContinuationToken continuationToken) {
+ try {
+ IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService("ircs"));
+ if (iRcs != null) {
+ return iRcs.getRcsThreadsWithToken(continuationToken);
+ }
+ } catch (RemoteException re) {
+ Rlog.e(TAG, "RcsMessageStore: Exception happened during getRcsThreads", re);
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a new 1 to 1 thread with the given participant and persists it in the storage.
+ */
+ @WorkerThread
+ public Rcs1To1Thread createRcs1To1Thread(RcsParticipant recipient) {
+ try {
+ IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService("ircs"));
+ if (iRcs != null) {
+ return iRcs.createRcs1To1Thread(recipient);
+ }
+ } catch (RemoteException re) {
+ Rlog.e(TAG, "RcsMessageStore: Exception happened during createRcs1To1Thread", re);
+ }
+
+ return null;
+ }
+
+ /**
+ * Delete the {@link RcsThread} identified by the given threadId.
* @param threadId threadId of the thread to be deleted.
*/
+ @WorkerThread
public void deleteThread(int threadId) {
- if (VDBG) logd("deleteThread: threadId: " + threadId);
try {
IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService("ircs"));
if (iRcs != null) {
iRcs.deleteThread(threadId);
}
} catch (RemoteException re) {
-
+ Rlog.e(TAG, "RcsMessageStore: Exception happened during deleteThread", re);
}
}
- private static void logd(String msg) {
- Rlog.d(TAG, msg);
+ /**
+ * Creates a new participant and persists it in the storage.
+ * @param canonicalAddress The defining address (e.g. phone number) of the participant.
+ */
+ public RcsParticipant createRcsParticipant(String canonicalAddress) {
+ try {
+ IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService("ircs"));
+ if (iRcs != null) {
+ return iRcs.createRcsParticipant(canonicalAddress);
+ }
+ } catch (RemoteException re) {
+ Rlog.e(TAG, "RcsMessageStore: Exception happened during createRcsParticipant", re);
+ }
+
+ return null;
}
}
diff --git a/telephony/java/android/telephony/ims/RcsParticipant.java b/telephony/java/android/telephony/ims/RcsParticipant.java
index 318dba3..70500aa 100644
--- a/telephony/java/android/telephony/ims/RcsParticipant.java
+++ b/telephony/java/android/telephony/ims/RcsParticipant.java
@@ -23,6 +23,16 @@
* @hide - TODO(sahinc) make this public
*/
public class RcsParticipant implements Parcelable {
+ /**
+ * Returns the row id of this participant.
+ *
+ * TODO(sahinc) implement
+ * @hide
+ */
+ public int getId() {
+ return 12345;
+ }
+
public static final Creator<RcsParticipant> CREATOR = new Creator<RcsParticipant>() {
@Override
public RcsParticipant createFromParcel(Parcel in) {
diff --git a/telephony/java/android/telephony/ims/RcsThread.java b/telephony/java/android/telephony/ims/RcsThread.java
index 2969ffd..c0a0d94 100644
--- a/telephony/java/android/telephony/ims/RcsThread.java
+++ b/telephony/java/android/telephony/ims/RcsThread.java
@@ -16,7 +16,9 @@
package android.telephony.ims;
+import android.os.Parcel;
import android.os.Parcelable;
+import android.util.Log;
/**
* RcsThread represents a single RCS conversation thread. It holds messages that were sent and
@@ -24,5 +26,50 @@
* @hide - TODO(sahinc) make this public
*/
public abstract class RcsThread implements Parcelable {
+ // Since this is an abstract class that gets parcelled, the sub-classes need to write these
+ // magic values into the parcel so that we know which type to unparcel into.
+ protected static final int RCS_1_TO_1_TYPE = 998;
+ protected static final int RCS_GROUP_TYPE = 999;
+ protected int mThreadId;
+
+ protected RcsThread(int threadId) {
+ mThreadId = threadId;
+ }
+
+ protected RcsThread(Parcel in) {
+ mThreadId = in.readInt();
+ }
+
+ public static final Creator<RcsThread> CREATOR = new Creator<RcsThread>() {
+ @Override
+ public RcsThread createFromParcel(Parcel in) {
+ int type = in.readInt();
+
+ switch (type) {
+ case RCS_1_TO_1_TYPE:
+ return new Rcs1To1Thread(in);
+ case RCS_GROUP_TYPE:
+ return new RcsGroupThread(in);
+ default:
+ Log.e(RcsMessageStore.TAG, "Cannot unparcel RcsThread, wrong type: " + type);
+ }
+ return null;
+ }
+
+ @Override
+ public RcsThread[] newArray(int size) {
+ return new RcsThread[0];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mThreadId);
+ }
}
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryContinuationToken.aidl b/telephony/java/android/telephony/ims/RcsThreadQueryContinuationToken.aidl
new file mode 100644
index 0000000..7bcebfa
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryContinuationToken.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.ims;
+
+parcelable RcsThreadQueryContinuationToken;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryContinuationToken.java b/telephony/java/android/telephony/ims/RcsThreadQueryContinuationToken.java
new file mode 100644
index 0000000..931e93d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryContinuationToken.java
@@ -0,0 +1,52 @@
+/*
+ * 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.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A continuation token to provide for {@link RcsMessageStore#getRcsThreads}. Use this token to
+ * break large queries into manageable chunks
+ * @hide - TODO make this public
+ */
+public class RcsThreadQueryContinuationToken implements Parcelable {
+ protected RcsThreadQueryContinuationToken(Parcel in) {
+ }
+
+ public static final Creator<RcsThreadQueryContinuationToken> CREATOR =
+ new Creator<RcsThreadQueryContinuationToken>() {
+ @Override
+ public RcsThreadQueryContinuationToken createFromParcel(Parcel in) {
+ return new RcsThreadQueryContinuationToken(in);
+ }
+
+ @Override
+ public RcsThreadQueryContinuationToken[] newArray(int size) {
+ return new RcsThreadQueryContinuationToken[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
new file mode 100644
index 0000000..feb2d4d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryParameters.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.ims;
+
+parcelable RcsThreadQueryParameters;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.java b/telephony/java/android/telephony/ims/RcsThreadQueryParameters.java
new file mode 100644
index 0000000..f2c4ab1
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryParameters.java
@@ -0,0 +1,225 @@
+/*
+ * 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.ims;
+
+import android.annotation.CheckResult;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.security.InvalidParameterException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * The parameters to pass into {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParameters)} in
+ * order to select a subset of {@link RcsThread}s present in the message store.
+ * @hide TODO - make the Builder and builder() public. The rest should stay internal only.
+ */
+public class RcsThreadQueryParameters implements Parcelable {
+ private final boolean mIsGroup;
+ private final Set<RcsParticipant> mRcsParticipants;
+ private final int mLimit;
+ private final boolean mIsAscending;
+
+ RcsThreadQueryParameters(boolean isGroup, Set<RcsParticipant> participants, int limit,
+ boolean isAscending) {
+ mIsGroup = isGroup;
+ mRcsParticipants = participants;
+ mLimit = limit;
+ mIsAscending = isAscending;
+ }
+
+ /**
+ * Returns a new builder to build a query with.
+ * TODO - make public
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * This is used in {@link com.android.internal.telephony.ims.RcsMessageStoreController} to get
+ * the list of participants.
+ * @hide
+ */
+ public Set<RcsParticipant> getRcsParticipants() {
+ return mRcsParticipants;
+ }
+
+ /**
+ * This is used in {@link com.android.internal.telephony.ims.RcsMessageStoreController} to get
+ * whether group threads should be queried
+ * @hide
+ */
+ public boolean isGroupThread() {
+ return mIsGroup;
+ }
+
+ /**
+ * This is used in {@link com.android.internal.telephony.ims.RcsMessageStoreController} to get
+ * the number of tuples the result query should be limited to.
+ */
+ public int getLimit() {
+ return mLimit;
+ }
+
+ /**
+ * This is used in {@link com.android.internal.telephony.ims.RcsMessageStoreController} to
+ * determine the sort order.
+ */
+ public boolean isAscending() {
+ return mIsAscending;
+ }
+
+ /**
+ * A helper class to build the {@link RcsThreadQueryParameters}.
+ */
+ public static class Builder {
+ private boolean mIsGroupThread;
+ private Set<RcsParticipant> mParticipants;
+ private int mLimit = 100;
+ private boolean mIsAscending;
+
+ /**
+ * Package private constructor for {@link RcsThreadQueryParameters.Builder}. To obtain this,
+ * {@link RcsThreadQueryParameters#builder()} needs to be called.
+ */
+ Builder() {
+ mParticipants = new HashSet<>();
+ }
+
+ /**
+ * Limits the query to only return group threads.
+ * @param isGroupThread Whether to limit the query result to group threads.
+ * @return The same instance of the builder to chain parameters.
+ */
+ @CheckResult
+ public Builder isGroupThread(boolean isGroupThread) {
+ mIsGroupThread = isGroupThread;
+ return this;
+ }
+
+ /**
+ * Limits the query to only return threads that contain the given participant.
+ * @param participant The participant that must be included in all of the returned threads.
+ * @return The same instance of the builder to chain parameters.
+ */
+ @CheckResult
+ public Builder withParticipant(RcsParticipant participant) {
+ mParticipants.add(participant);
+ return this;
+ }
+
+ /**
+ * Limits the query to only return threads that contain the given list of participants.
+ * @param participants An iterable list of participants that must be included in all of the
+ * returned threads.
+ * @return The same instance of the builder to chain parameters.
+ */
+ @CheckResult
+ public Builder withParticipants(Iterable<RcsParticipant> participants) {
+ for (RcsParticipant participant : participants) {
+ mParticipants.add(participant);
+ }
+ return this;
+ }
+
+ /**
+ * Desired number of threads to be returned from the query. Passing in 0 will return all
+ * existing threads at once. The limit defaults to 100.
+ * @param limit The number to limit the query result to.
+ * @return The same instance of the builder to chain parameters.
+ * @throws InvalidParameterException If the given limit is negative.
+ */
+ @CheckResult
+ public Builder limitResultsTo(int limit) throws InvalidParameterException {
+ if (limit < 0) {
+ throw new InvalidParameterException("The query limit must be non-negative");
+ }
+
+ mLimit = limit;
+ return this;
+ }
+
+ /**
+ * Sorts the results returned from the query via thread IDs.
+ *
+ * TODO - add sorting support for other fields
+ *
+ * @param isAscending whether to sort in ascending order or not
+ * @return The same instance of the builder to chain parameters.
+ */
+ @CheckResult
+ public Builder sort(boolean isAscending) {
+ mIsAscending = isAscending;
+ return this;
+ }
+
+ /**
+ * Builds the {@link RcsThreadQueryParameters} to use in
+ * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParameters)}
+ *
+ * @return An instance of {@link RcsThreadQueryParameters} to use with the thread query.
+ */
+ public RcsThreadQueryParameters build() {
+ return new RcsThreadQueryParameters(
+ mIsGroupThread, mParticipants, mLimit, mIsAscending);
+ }
+ }
+
+ /**
+ * Parcelable boilerplate below.
+ */
+ protected RcsThreadQueryParameters(Parcel in) {
+ mIsGroup = in.readBoolean();
+
+ ArrayList<RcsParticipant> participantArrayList = new ArrayList<>();
+ in.readTypedList(participantArrayList, RcsParticipant.CREATOR);
+ mRcsParticipants = new HashSet<>(participantArrayList);
+
+ mLimit = in.readInt();
+ mIsAscending = in.readBoolean();
+ }
+
+ public static final Creator<RcsThreadQueryParameters> CREATOR =
+ new Creator<RcsThreadQueryParameters>() {
+ @Override
+ public RcsThreadQueryParameters createFromParcel(Parcel in) {
+ return new RcsThreadQueryParameters(in);
+ }
+
+ @Override
+ public RcsThreadQueryParameters[] newArray(int size) {
+ return new RcsThreadQueryParameters[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeBoolean(mIsGroup);
+ dest.writeTypedList(new ArrayList<>(mRcsParticipants));
+ dest.writeInt(mLimit);
+ dest.writeBoolean(mIsAscending);
+ }
+
+}
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryResult.aidl b/telephony/java/android/telephony/ims/RcsThreadQueryResult.aidl
new file mode 100644
index 0000000..4b06529
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryResult.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.ims;
+
+parcelable RcsThreadQueryResult;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
new file mode 100644
index 0000000..47715f8
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
@@ -0,0 +1,92 @@
+/*
+ * 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.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.List;
+
+/**
+ * The result of a {@link RcsMessageStore#getRcsThreads(RcsThreadQueryContinuationToken,
+ * RcsThreadQueryParameters)}
+ * call. This class allows getting the token for querying the next batch of threads in order to
+ * prevent handling large amounts of data at once.
+ *
+ * @hide
+ */
+public class RcsThreadQueryResult implements Parcelable {
+ private RcsThreadQueryContinuationToken mContinuationToken;
+ private List<RcsThread> mRcsThreads;
+
+ /**
+ * Internal constructor for {@link com.android.internal.telephony.ims.RcsMessageStoreController}
+ * to create query results
+ *
+ * @hide
+ */
+ public RcsThreadQueryResult(
+ RcsThreadQueryContinuationToken continuationToken, List<RcsThread> rcsThreads) {
+ mContinuationToken = continuationToken;
+ mRcsThreads = rcsThreads;
+ }
+
+ /**
+ * Returns a token to call
+ * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryContinuationToken)}
+ * to get the next batch of {@link RcsThread}s.
+ */
+ public RcsThreadQueryContinuationToken nextChunkToken() {
+ return mContinuationToken;
+ }
+
+ /**
+ * Returns all the RcsThreads in the current query result. Call {@link
+ * RcsMessageStore#getRcsThreads(RcsThreadQueryContinuationToken)} to get the next batch of
+ * {@link RcsThread}s.
+ */
+ public List<RcsThread> getThreads() {
+ return mRcsThreads;
+ }
+
+ protected RcsThreadQueryResult(Parcel in) {
+ // TODO - implement
+ }
+
+ public static final Creator<RcsThreadQueryResult> CREATOR =
+ new Creator<RcsThreadQueryResult>() {
+ @Override
+ public RcsThreadQueryResult createFromParcel(Parcel in) {
+ return new RcsThreadQueryResult(in);
+ }
+
+ @Override
+ public RcsThreadQueryResult[] newArray(int size) {
+ return new RcsThreadQueryResult[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ // TODO - implement
+ }
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IRcs.aidl b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
index b2e2fad..9badac5 100644
--- a/telephony/java/android/telephony/ims/aidl/IRcs.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
@@ -16,14 +16,29 @@
package android.telephony.ims.aidl;
+import android.telephony.ims.RcsParticipant;
+import android.telephony.ims.Rcs1To1Thread;
+import android.telephony.ims.RcsThreadQueryContinuationToken;
+import android.telephony.ims.RcsThreadQueryParameters;
+import android.telephony.ims.RcsThreadQueryResult;
+
/**
* RPC definition between RCS storage APIs and phone process.
* {@hide}
*/
interface IRcs {
// RcsMessageStore APIs
+ RcsThreadQueryResult getRcsThreads(in RcsThreadQueryParameters queryParameters);
+
+ RcsThreadQueryResult getRcsThreadsWithToken(
+ in RcsThreadQueryContinuationToken continuationToken);
+
void deleteThread(int threadId);
+ Rcs1To1Thread createRcs1To1Thread(in RcsParticipant participant);
+
+ RcsParticipant createRcsParticipant(String canonicalAddress);
+
// RcsThread APIs
int getMessageCount(int rcsThreadId);
}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 0fdca5d..96f7a1b 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -24,7 +24,7 @@
/**
* IDLE: ready to start data connection setup, default state
* CONNECTING: state of issued startPppd() but not finish yet
- * SCANNING: data connection fails with one apn but other apns are available
+ * RETRYING: data connection fails with one apn but other apns are available
* ready to start data connection on other apns (before INITING)
* CONNECTED: IP connection is setup
* DISCONNECTING: Connection.disconnect() has been called, but PDP
@@ -34,19 +34,16 @@
*
* getDataConnectionState() maps State to DataState
* FAILED or IDLE : DISCONNECTED
- * RETRYING or CONNECTING or SCANNING: CONNECTING
+ * RETRYING or CONNECTING: CONNECTING
* CONNECTED : CONNECTED or DISCONNECTING
*/
public enum State {
IDLE,
CONNECTING,
- SCANNING,
+ RETRYING,
CONNECTED,
DISCONNECTING,
FAILED,
- RETRYING // After moving retry manager to ApnContext, we'll never enter this state!
- // Todo: Remove this state and other places that use this state and then
- // rename SCANNING to RETRYING.
}
public enum Activity {
@@ -81,7 +78,6 @@
public static final int EVENT_RESTART_RADIO = BASE + 26;
public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = BASE + 29;
public static final int EVENT_ICC_CHANGED = BASE + 33;
- public static final int EVENT_DISCONNECT_DC_RETRYING = BASE + 34;
public static final int EVENT_DATA_SETUP_COMPLETE_ERROR = BASE + 35;
public static final int CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA = BASE + 36;
public static final int CMD_ENABLE_MOBILE_PROVISIONING = BASE + 37;
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index d9f5c3f..02a6f31 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -50,13 +50,13 @@
void notifyDataActivity(int state);
void notifyDataActivityForSubscriber(in int subId, int state);
void notifyDataConnection(int state, boolean isDataConnectivityPossible,
- String reason, String apn, String apnType, in LinkProperties linkProperties,
+ String apn, String apnType, in LinkProperties linkProperties,
in NetworkCapabilities networkCapabilities, int networkType, boolean roaming);
void notifyDataConnectionForSubscriber(int subId, int state, boolean isDataConnectivityPossible,
- String reason, String apn, String apnType, in LinkProperties linkProperties,
+ String apn, String apnType, in LinkProperties linkProperties,
in NetworkCapabilities networkCapabilities, int networkType, boolean roaming);
- void notifyDataConnectionFailed(String reason, String apnType);
- void notifyDataConnectionFailedForSubscriber(int subId, String reason, String apnType);
+ void notifyDataConnectionFailed(String apnType);
+ void notifyDataConnectionFailedForSubscriber(int subId, String apnType);
void notifyCellLocation(in Bundle cellLocation);
void notifyCellLocationForSubscriber(in int subId, in Bundle cellLocation);
void notifyOtaspChanged(in int otaspMode);
@@ -67,7 +67,7 @@
void notifyPreciseCallState(int ringingCallState, int foregroundCallState,
int backgroundCallState);
void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause);
- void notifyPreciseDataConnectionFailed(String reason, String apnType, String apn,
+ void notifyPreciseDataConnectionFailed(String apnType, String apn,
String failCause);
void notifyCellInfoForSubscriber(in int subId, in List<CellInfo> cellInfo);
void notifySrvccStateChanged(in int subId, in int lteState);
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 21f3b92..e87d28c 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -79,8 +79,6 @@
public static final int SIM_ACTIVATION_TYPE_DATA = 1;
public static final String PHONE_NAME_KEY = "phoneName";
- public static final String FAILURE_REASON_KEY = "reason";
- public static final String STATE_CHANGE_REASON_KEY = "reason";
public static final String DATA_NETWORK_TYPE_KEY = "networkType";
public static final String DATA_FAILURE_CAUSE_KEY = "failCause";
public static final String DATA_APN_TYPE_KEY = "apnType";
diff --git a/tests/RcsTests/Android.mk b/tests/RcsTests/Android.mk
index adc7cab..7b348d7 100644
--- a/tests/RcsTests/Android.mk
+++ b/tests/RcsTests/Android.mk
@@ -11,7 +11,7 @@
LOCAL_CERTIFICATE := platform
LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit android-support-test mockito-target-minus-junit4
+LOCAL_STATIC_JAVA_LIBRARIES := junit android-support-test mockito-target-minus-junit4 truth-prebuilt
include $(BUILD_PACKAGE)
diff --git a/tests/RcsTests/src/com/android/tests/rcs/RcsMessageStoreTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsMessageStoreTest.java
similarity index 97%
rename from tests/RcsTests/src/com/android/tests/rcs/RcsMessageStoreTest.java
rename to tests/RcsTests/src/com/android/tests/ims/RcsMessageStoreTest.java
index 290e04c..44277ed 100644
--- a/tests/RcsTests/src/com/android/tests/rcs/RcsMessageStoreTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsMessageStoreTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.tests.rcs;
+package com.android.tests.ims;
import android.support.test.runner.AndroidJUnit4;
import android.telephony.ims.RcsMessageStore;
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParametersTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParametersTest.java
new file mode 100644
index 0000000..a890a38
--- /dev/null
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParametersTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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 com.android.tests.ims;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Bundle;
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.ims.RcsParticipant;
+import android.telephony.ims.RcsThreadQueryParameters;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+@RunWith(AndroidJUnit4.class)
+public class RcsThreadQueryParametersTest {
+ private RcsThreadQueryParameters mRcsThreadQueryParameters;
+ @Mock RcsParticipant mMockParticipant;
+
+ @Test
+ public void testUnparceling() {
+ String key = "some key";
+ mRcsThreadQueryParameters = RcsThreadQueryParameters.builder()
+ .isGroupThread(true)
+ .withParticipant(mMockParticipant)
+ .limitResultsTo(50)
+ .sort(true)
+ .build();
+
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(key, mRcsThreadQueryParameters);
+ mRcsThreadQueryParameters = bundle.getParcelable(key);
+
+ assertThat(mRcsThreadQueryParameters.isGroupThread()).isTrue();
+ assertThat(mRcsThreadQueryParameters.getRcsParticipants()).contains(mMockParticipant);
+ assertThat(mRcsThreadQueryParameters.getLimit()).isEqualTo(50);
+ assertThat(mRcsThreadQueryParameters.isAscending()).isTrue();
+ }
+}
diff --git a/tools/aapt/ConfigDescription.h b/tools/aapt/ConfigDescription.h
index 09430f2..b4ea624 100644
--- a/tools/aapt/ConfigDescription.h
+++ b/tools/aapt/ConfigDescription.h
@@ -29,7 +29,7 @@
size = sizeof(android::ResTable_config);
}
- ConfigDescription(const android::ResTable_config&o) { // NOLINT(implicit)
+ ConfigDescription(const android::ResTable_config&o) { // NOLINT(google-explicit-constructor)
*static_cast<android::ResTable_config*>(this) = o;
size = sizeof(android::ResTable_config);
}
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index f064cb1..e0d7abe 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -414,7 +414,7 @@
public:
using xml::ConstVisitor::Visit;
- XmlPrinter(Printer* printer) : printer_(printer) {
+ explicit XmlPrinter(Printer* printer) : printer_(printer) {
}
void Visit(const xml::Element* el) override {
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 1c1aedd..a8ba202 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -108,7 +108,7 @@
ResourceNameRef() = default;
ResourceNameRef(const ResourceNameRef&) = default;
ResourceNameRef(ResourceNameRef&&) = default;
- ResourceNameRef(const ResourceName& rhs); // NOLINT(implicit)
+ ResourceNameRef(const ResourceName& rhs); // NOLINT(google-explicit-constructor)
ResourceNameRef(const android::StringPiece& p, ResourceType t, const android::StringPiece& e);
ResourceNameRef& operator=(const ResourceNameRef& rhs) = default;
ResourceNameRef& operator=(ResourceNameRef&& rhs) = default;
@@ -139,7 +139,7 @@
ResourceId();
ResourceId(const ResourceId& rhs);
- ResourceId(uint32_t res_id); // NOLINT(implicit)
+ ResourceId(uint32_t res_id); // NOLINT(google-explicit-constructor)
ResourceId(uint8_t p, uint8_t t, uint16_t e);
bool is_valid() const;
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index 0b43c5d..7144985 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -645,7 +645,7 @@
class CompileContext : public IAaptContext {
public:
- CompileContext(IDiagnostics* diagnostics) : diagnostics_(diagnostics) {
+ explicit CompileContext(IDiagnostics* diagnostics) : diagnostics_(diagnostics) {
}
PackageType GetPackageType() override {
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 60cab5d..623ba12 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -141,7 +141,7 @@
class LinkContext : public IAaptContext {
public:
- LinkContext(IDiagnostics* diagnostics)
+ explicit LinkContext(IDiagnostics* diagnostics)
: diagnostics_(diagnostics), name_mangler_({}), symbols_(&name_mangler_) {
}
@@ -226,7 +226,7 @@
// See b/37498913.
class FeatureSplitSymbolTableDelegate : public DefaultSymbolTableDelegate {
public:
- FeatureSplitSymbolTableDelegate(IAaptContext* context) : context_(context) {
+ explicit FeatureSplitSymbolTableDelegate(IAaptContext* context) : context_(context) {
}
virtual ~FeatureSplitSymbolTableDelegate() = default;
diff --git a/tools/aapt2/java/ProguardRules.h b/tools/aapt2/java/ProguardRules.h
index 46827ee..c53f307 100644
--- a/tools/aapt2/java/ProguardRules.h
+++ b/tools/aapt2/java/ProguardRules.h
@@ -44,7 +44,7 @@
public:
KeepSet() = default;
- KeepSet(bool conditional_keep_rules) : conditional_keep_rules_(conditional_keep_rules) {
+ explicit KeepSet(bool conditional_keep_rules) : conditional_keep_rules_(conditional_keep_rules) {
}
inline void AddManifestClass(const UsageLocation& file, const std::string& class_name) {
diff --git a/tools/aapt2/link/XmlCompatVersioner.h b/tools/aapt2/link/XmlCompatVersioner.h
index 099e23c..9980618 100644
--- a/tools/aapt2/link/XmlCompatVersioner.h
+++ b/tools/aapt2/link/XmlCompatVersioner.h
@@ -55,7 +55,7 @@
public:
using Rules = std::unordered_map<ResourceId, std::unique_ptr<IDegradeRule>>;
- XmlCompatVersioner(const Rules* rules);
+ explicit XmlCompatVersioner(const Rules* rules);
std::vector<std::unique_ptr<xml::XmlResource>> Process(IAaptContext* context,
xml::XmlResource* doc,
@@ -83,7 +83,7 @@
class DegradeToManyRule : public IDegradeRule {
public:
- DegradeToManyRule(std::vector<ReplacementAttr> attrs);
+ explicit DegradeToManyRule(std::vector<ReplacementAttr> attrs);
virtual ~DegradeToManyRule() = default;
std::vector<DegradeResult> Degrade(const xml::Element& src_el, const xml::Attribute& src_attr,
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index 51a2e37..2d8bd02 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -71,7 +71,7 @@
bool is_dynamic = false;
};
- SymbolTable(NameMangler* mangler);
+ explicit SymbolTable(NameMangler* mangler);
// Overrides the default ISymbolTableDelegate, which allows a custom defined strategy for
// looking up resources from a set of sources.
diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h
index 50b41f1..777ca5c 100644
--- a/tools/aapt2/test/Common.h
+++ b/tools/aapt2/test/Common.h
@@ -173,10 +173,12 @@
template <typename TValue>
class ValueEqMatcher {
public:
+ // NOLINTNEXTLINE(google-explicit-constructor)
ValueEqMatcher(TValue expected) : expected_(std::move(expected)) {
}
template <typename T>
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator ::testing::Matcher<T>() const {
return ::testing::Matcher<T>(new ValueEqImpl<T>(&expected_));
}
@@ -188,10 +190,12 @@
template <typename TValue>
class ValueEqPointerMatcher {
public:
+ // NOLINTNEXTLINE(google-explicit-constructor)
ValueEqPointerMatcher(const TValue* expected) : expected_(expected) {
}
template <typename T>
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator ::testing::Matcher<T>() const {
return ::testing::Matcher<T>(new ValueEqImpl<T>(expected_));
}
diff --git a/tools/aapt2/util/Maybe.h b/tools/aapt2/util/Maybe.h
index 031276c..047e1a5 100644
--- a/tools/aapt2/util/Maybe.h
+++ b/tools/aapt2/util/Maybe.h
@@ -44,12 +44,12 @@
Maybe(const Maybe& rhs);
template <typename U>
- Maybe(const Maybe<U>& rhs); // NOLINT(implicit)
+ Maybe(const Maybe<U>& rhs); // NOLINT(google-explicit-constructor)
Maybe(Maybe&& rhs) noexcept;
template <typename U>
- Maybe(Maybe<U>&& rhs); // NOLINT(implicit)
+ Maybe(Maybe<U>&& rhs); // NOLINT(google-explicit-constructor)
Maybe& operator=(const Maybe& rhs);
@@ -64,12 +64,12 @@
/**
* Construct a Maybe holding a value.
*/
- Maybe(const T& value); // NOLINT(implicit)
+ Maybe(const T& value); // NOLINT(google-explicit-constructor)
/**
* Construct a Maybe holding a value.
*/
- Maybe(T&& value); // NOLINT(implicit)
+ Maybe(T&& value); // NOLINT(google-explicit-constructor)
/**
* True if this holds a value, false if