Merge "Clarify API doc for BluetoothGattServer::addService"
diff --git a/Android.bp b/Android.bp
index 98e52a9..254c5fc 100644
--- a/Android.bp
+++ b/Android.bp
@@ -991,3 +991,27 @@
":hwbinder-stubs-docs",
],
}
+
+filegroup {
+ name: "apache-http-stubs-sources",
+ srcs: [
+ "core/java/org/apache/http/conn/ConnectTimeoutException.java",
+ "core/java/org/apache/http/conn/scheme/HostNameResolver.java",
+ "core/java/org/apache/http/conn/scheme/LayeredSocketFactory.java",
+ "core/java/org/apache/http/conn/scheme/SocketFactory.java",
+ "core/java/org/apache/http/conn/ssl/AbstractVerifier.java",
+ "core/java/org/apache/http/conn/ssl/AllowAllHostnameVerifier.java",
+ "core/java/org/apache/http/conn/ssl/AndroidDistinguishedNameParser.java",
+ "core/java/org/apache/http/conn/ssl/BrowserCompatHostnameVerifier.java",
+ "core/java/org/apache/http/conn/ssl/SSLSocketFactory.java",
+ "core/java/org/apache/http/conn/ssl/StrictHostnameVerifier.java",
+ "core/java/org/apache/http/conn/ssl/X509HostnameVerifier.java",
+ "core/java/org/apache/http/params/CoreConnectionPNames.java",
+ "core/java/org/apache/http/params/HttpConnectionParams.java",
+ "core/java/org/apache/http/params/HttpParams.java",
+ "core/java/android/net/http/HttpResponseCache.java",
+ "core/java/android/net/http/SslCertificate.java",
+ "core/java/android/net/http/SslError.java",
+ "core/java/com/android/internal/util/HexDump.java",
+ ],
+}
diff --git a/api/current.txt b/api/current.txt
index 7f076cb..b9ae497 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -35306,6 +35306,7 @@
field public static final java.lang.String PARENTAL_CONTROL_ENABLED = "parental_control_enabled";
field public static final java.lang.String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update";
field public static final java.lang.String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
+ field public static final java.lang.String RTT_CALLING_MODE = "rtt_calling_mode";
field public static final java.lang.String SELECTED_INPUT_METHOD_SUBTYPE = "selected_input_method_subtype";
field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname";
field public static final java.lang.String SKIP_FIRST_USE_HINTS = "skip_first_use_hints";
@@ -35411,7 +35412,6 @@
field public static final deprecated java.lang.String RADIO_NFC = "nfc";
field public static final deprecated java.lang.String RADIO_WIFI = "wifi";
field public static final java.lang.String RINGTONE = "ringtone";
- field public static final java.lang.String RTT_CALLING_MODE = "rtt_calling_mode";
field public static final java.lang.String SCREEN_BRIGHTNESS = "screen_brightness";
field public static final java.lang.String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
field public static final int SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1; // 0x1
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 6aabe18..3d95669 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -80,8 +80,7 @@
* {@link #getBondedDevices()}; start device discovery with
* {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
* listen for incoming RFComm connection requests with {@link
- * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented
- * Channels (CoC) connection requests with listenUsingL2capCoc(int)}; or start a scan for
+ * #listenUsingRfcommWithServiceRecord(String, UUID)}; or start a scan for
* Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
* </p>
* <p>This class is thread safe.</p>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2b5353d..534f9c4 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3673,17 +3673,6 @@
public static final Validator TTY_MODE_VALIDATOR = new InclusiveIntegerRangeValidator(0, 3);
/**
- * User-selected RTT mode. When on, outgoing and incoming calls will be answered as RTT
- * calls when supported by the device and carrier. Boolean value.
- * 0 = OFF
- * 1 = ON
- */
- public static final String RTT_CALLING_MODE = "rtt_calling_mode";
-
- /** @hide */
- public static final Validator RTT_CALLING_MODE_VALIDATOR = sBooleanValidator;
-
- /**
* Whether the sounds effects (key clicks, lid open ...) are enabled. The value is
* boolean (1 or 0).
*/
@@ -4003,7 +3992,6 @@
DTMF_TONE_WHEN_DIALING,
DTMF_TONE_TYPE_WHEN_DIALING,
HEARING_AID,
- RTT_CALLING_MODE,
TTY_MODE,
MASTER_MONO,
SOUND_EFFECTS_ENABLED,
@@ -4187,7 +4175,6 @@
VALIDATORS.put(DTMF_TONE_TYPE_WHEN_DIALING, DTMF_TONE_TYPE_WHEN_DIALING_VALIDATOR);
VALIDATORS.put(HEARING_AID, HEARING_AID_VALIDATOR);
VALIDATORS.put(TTY_MODE, TTY_MODE_VALIDATOR);
- VALIDATORS.put(RTT_CALLING_MODE, RTT_CALLING_MODE_VALIDATOR);
VALIDATORS.put(NOTIFICATION_LIGHT_PULSE, NOTIFICATION_LIGHT_PULSE_VALIDATOR);
VALIDATORS.put(POINTER_LOCATION, POINTER_LOCATION_VALIDATOR);
VALIDATORS.put(SHOW_TOUCHES, SHOW_TOUCHES_VALIDATOR);
@@ -6262,6 +6249,15 @@
public static final String TTY_MODE_ENABLED = "tty_mode_enabled";
/**
+ * User-selected RTT mode. When on, outgoing and incoming calls will be answered as RTT
+ * calls when supported by the device and carrier. Boolean value.
+ * 0 = OFF
+ * 1 = ON
+ */
+ public static final String RTT_CALLING_MODE = "rtt_calling_mode";
+
+ /**
+ /**
* Controls whether settings backup is enabled.
* Type: int ( 0 = disabled, 1 = enabled )
* @hide
@@ -7218,6 +7214,7 @@
PREFERRED_TTY_MODE,
ENHANCED_VOICE_PRIVACY_ENABLED,
TTY_MODE_ENABLED,
+ RTT_CALLING_MODE,
INCALL_POWER_BUTTON_BEHAVIOR,
NIGHT_DISPLAY_CUSTOM_START_TIME,
NIGHT_DISPLAY_CUSTOM_END_TIME,
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 7f6d19b..bd6ad2c 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -810,12 +810,6 @@
addOption("-Ximage-compiler-option");
addOption("--image-classes=/system/etc/preloaded-classes");
- // If there is a compiled-classes file, push it.
- if (hasFile("/system/etc/compiled-classes")) {
- addOption("-Ximage-compiler-option");
- addOption("--compiled-classes=/system/etc/compiled-classes");
- }
-
// If there is a dirty-image-objects file, push it.
if (hasFile("/system/etc/dirty-image-objects")) {
addOption("-Ximage-compiler-option");
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 0af187c..f2fe654 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -56,6 +56,8 @@
</privapp-permissions>
<privapp-permissions package="com.android.emergency">
+ <!-- Required to place emergency calls from emergency info screen. -->
+ <permission name="android.permission.CALL_PRIVILEGED"/>
<permission name="android.permission.MANAGE_USERS"/>
</privapp-permissions>
diff --git a/media/java/android/media/AudioPlaybackConfiguration.java b/media/java/android/media/AudioPlaybackConfiguration.java
index 8a36f91..7dfdb20 100644
--- a/media/java/android/media/AudioPlaybackConfiguration.java
+++ b/media/java/android/media/AudioPlaybackConfiguration.java
@@ -43,6 +43,8 @@
/** @hide */
public static final int PLAYER_PIID_INVALID = -1;
/** @hide */
+ public static final int PLAYER_PIID_UNASSIGNED = 0;
+ /** @hide */
public static final int PLAYER_UPID_INVALID = -1;
// information about the implementation
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index 09449a1..d8ebd71 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -31,6 +31,7 @@
import android.os.ServiceManager;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
@@ -58,20 +59,29 @@
protected float mRightVolume = 1.0f;
protected float mAuxEffectSendLevel = 0.0f;
- // for AppOps
- private IAppOpsService mAppOps; // may be null
- private IAppOpsCallback mAppOpsCallback;
- private boolean mHasAppOpsPlayAudio = true; // sync'd on mLock
+ // NEVER call into AudioService (see getService()) with mLock held: PlayerBase can run in
+ // the same process as AudioService, which can synchronously call back into this class,
+ // causing deadlocks between the two
private final Object mLock = new Object();
+ // for AppOps
+ private @Nullable IAppOpsService mAppOps;
+ private IAppOpsCallback mAppOpsCallback;
+ @GuardedBy("mLock")
+ private boolean mHasAppOpsPlayAudio = true;
+
private final int mImplType;
// uniquely identifies the Player Interface throughout the system (P I Id)
- private int mPlayerIId;
+ private int mPlayerIId = AudioPlaybackConfiguration.PLAYER_PIID_UNASSIGNED;
- private int mState; // sync'd on mLock
- private int mStartDelayMs = 0; // sync'd on mLock
- private float mPanMultiplierL = 1.0f; // sync'd on mLock
- private float mPanMultiplierR = 1.0f; // sync'd on mLock
+ @GuardedBy("mLock")
+ private int mState;
+ @GuardedBy("mLock")
+ private int mStartDelayMs = 0;
+ @GuardedBy("mLock")
+ private float mPanMultiplierL = 1.0f;
+ @GuardedBy("mLock")
+ private float mPanMultiplierR = 1.0f;
/**
* Constructor. Must be given audio attributes, as they are required for AppOps.
@@ -133,16 +143,24 @@
}
}
+ private void updateState(int state) {
+ final int piid;
+ synchronized (mLock) {
+ mState = state;
+ piid = mPlayerIId;
+ }
+ try {
+ getService().playerEvent(piid, state);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to audio service, "
+ + AudioPlaybackConfiguration.toLogFriendlyPlayerState(state)
+ + " state will not be tracked for piid=" + piid, e);
+ }
+ }
+
void baseStart() {
if (DEBUG) { Log.v(TAG, "baseStart() piid=" + mPlayerIId); }
- try {
- synchronized (mLock) {
- mState = AudioPlaybackConfiguration.PLAYER_STATE_STARTED;
- getService().playerEvent(mPlayerIId, mState);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error talking to audio service, STARTED state will not be tracked", e);
- }
+ updateState(AudioPlaybackConfiguration.PLAYER_STATE_STARTED);
synchronized (mLock) {
if (isRestricted_sync()) {
playerSetVolume(true/*muting*/,0, 0);
@@ -164,26 +182,12 @@
void basePause() {
if (DEBUG) { Log.v(TAG, "basePause() piid=" + mPlayerIId); }
- try {
- synchronized (mLock) {
- mState = AudioPlaybackConfiguration.PLAYER_STATE_PAUSED;
- getService().playerEvent(mPlayerIId, mState);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error talking to audio service, PAUSED state will not be tracked", e);
- }
+ updateState(AudioPlaybackConfiguration.PLAYER_STATE_PAUSED);
}
void baseStop() {
if (DEBUG) { Log.v(TAG, "baseStop() piid=" + mPlayerIId); }
- try {
- synchronized (mLock) {
- mState = AudioPlaybackConfiguration.PLAYER_STATE_STOPPED;
- getService().playerEvent(mPlayerIId, mState);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error talking to audio service, STOPPED state will not be tracked", e);
- }
+ updateState(AudioPlaybackConfiguration.PLAYER_STATE_STOPPED);
}
void baseSetPan(float pan) {
@@ -227,12 +231,16 @@
*/
void baseRelease() {
if (DEBUG) { Log.v(TAG, "baseRelease() piid=" + mPlayerIId + " state=" + mState); }
+ boolean releasePlayer = false;
+ synchronized (mLock) {
+ if (mState != AudioPlaybackConfiguration.PLAYER_STATE_RELEASED) {
+ releasePlayer = true;
+ mState = AudioPlaybackConfiguration.PLAYER_STATE_RELEASED;
+ }
+ }
try {
- synchronized (mLock) {
- if (mState != AudioPlaybackConfiguration.PLAYER_STATE_RELEASED) {
- getService().releasePlayer(mPlayerIId);
- mState = AudioPlaybackConfiguration.PLAYER_STATE_RELEASED;
- }
+ if (releasePlayer) {
+ getService().releasePlayer(mPlayerIId);
}
} catch (RemoteException e) {
Log.e(TAG, "Error talking to audio service, the player will still be tracked", e);
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 92a09d3..92d3709 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -522,7 +522,7 @@
ICMP6_4_BYTE_LIFETIME_OFFSET, ICMP6_4_BYTE_LIFETIME_LEN);
}
- // Note that this parses RA and may throw IllegalArgumentException (from
+ // Note that this parses RA and may throw InvalidRaException (from
// Buffer.position(int) or due to an invalid-length option) or IndexOutOfBoundsException
// (from ByteBuffer.get(int) ) if parsing encounters something non-compliant with
// specifications.
@@ -986,9 +986,8 @@
*/
@GuardedBy("this")
private ApfGenerator beginProgramLocked() throws IllegalInstructionException {
- ApfGenerator gen = new ApfGenerator();
- // This is guaranteed to return true because of the check in maybeCreate.
- gen.setApfVersion(mApfCapabilities.apfVersionSupported);
+ // This is guaranteed to succeed because of the check in maybeCreate.
+ ApfGenerator gen = new ApfGenerator(mApfCapabilities.apfVersionSupported);
// Here's a basic summary of what the initial program does:
//
@@ -1215,7 +1214,7 @@
// 1. the program generator will need its offsets adjusted.
// 2. the packet filter attached to our packet socket will need its offset adjusted.
if (apfCapabilities.apfPacketFormat != ARPHRD_ETHER) return null;
- if (!new ApfGenerator().setApfVersion(apfCapabilities.apfVersionSupported)) {
+ if (!ApfGenerator.supportsVersion(apfCapabilities.apfVersionSupported)) {
Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported);
return null;
}
diff --git a/services/net/java/android/net/apf/ApfGenerator.java b/services/net/java/android/net/apf/ApfGenerator.java
index ca8f727..fcfb19c 100644
--- a/services/net/java/android/net/apf/ApfGenerator.java
+++ b/services/net/java/android/net/apf/ApfGenerator.java
@@ -58,7 +58,9 @@
JLT(18), // Compare less than and branch, e.g. "jlt R0,5,label"
JSET(19), // Compare any bits set and branch, e.g. "jset R0,5,label"
JNEBS(20), // Compare not equal byte sequence, e.g. "jnebs R0,5,label,0x1122334455"
- EXT(21); // Followed by immediate indicating ExtendedOpcodes.
+ EXT(21), // Followed by immediate indicating ExtendedOpcodes.
+ LDDW(22), // Load 4 bytes from data memory address (register + immediate): "lddw R0, [5]R1"
+ STDW(23); // Store 4 bytes to data memory address (register + immediate): "stdw R0, [5]R1"
final int value;
@@ -355,19 +357,38 @@
*/
public static final int LAST_PREFILLED_MEMORY_SLOT = FILTER_AGE_MEMORY_SLOT;
+ // This version number syncs up with APF_VERSION in hardware/google/apf/apf_interpreter.h
+ private static final int MIN_APF_VERSION = 2;
+
private final ArrayList<Instruction> mInstructions = new ArrayList<Instruction>();
private final HashMap<String, Instruction> mLabels = new HashMap<String, Instruction>();
private final Instruction mDropLabel = new Instruction(Opcodes.LABEL);
private final Instruction mPassLabel = new Instruction(Opcodes.LABEL);
+ private final int mVersion;
private boolean mGenerated;
/**
- * Set version of APF instruction set to generate instructions for. Returns {@code true}
- * if generating for this version is supported, {@code false} otherwise.
+ * Creates an ApfGenerator instance which is able to emit instructions for the specified
+ * {@code version} of the APF interpreter. Throws {@code IllegalInstructionException} if
+ * the requested version is unsupported.
*/
- public boolean setApfVersion(int version) {
- // This version number syncs up with APF_VERSION in hardware/google/apf/apf_interpreter.h
- return version >= 2;
+ ApfGenerator(int version) throws IllegalInstructionException {
+ mVersion = version;
+ requireApfVersion(MIN_APF_VERSION);
+ }
+
+ /**
+ * Returns true if the specified {@code version} is supported by the ApfGenerator, otherwise
+ * false.
+ */
+ public static boolean supportsVersion(int version) {
+ return version >= MIN_APF_VERSION;
+ }
+
+ private void requireApfVersion(int minimumVersion) throws IllegalInstructionException {
+ if (mVersion < minimumVersion) {
+ throw new IllegalInstructionException("Requires APF >= " + minimumVersion);
+ }
}
private void addInstruction(Instruction instruction) {
@@ -819,6 +840,36 @@
}
/**
+ * Add an instruction to the end of the program to load 32 bits from the data memory into
+ * {@code register}. The source address is computed by adding @{code offset} to the other
+ * register.
+ * Requires APF v3 or greater.
+ */
+ public ApfGenerator addLoadData(Register destinationRegister, int offset)
+ throws IllegalInstructionException {
+ requireApfVersion(3);
+ Instruction instruction = new Instruction(Opcodes.LDDW, destinationRegister);
+ instruction.setUnsignedImm(offset);
+ addInstruction(instruction);
+ return this;
+ }
+
+ /**
+ * Add an instruction to the end of the program to store 32 bits from {@code register} into the
+ * data memory. The destination address is computed by adding @{code offset} to the other
+ * register.
+ * Requires APF v3 or greater.
+ */
+ public ApfGenerator addStoreData(Register sourceRegister, int offset)
+ throws IllegalInstructionException {
+ requireApfVersion(3);
+ Instruction instruction = new Instruction(Opcodes.STDW, sourceRegister);
+ instruction.setUnsignedImm(offset);
+ addInstruction(instruction);
+ return this;
+ }
+
+ /**
* Updates instruction offset fields using latest instruction sizes.
* @return current program length in bytes.
*/
diff --git a/test-base/Android.bp b/test-base/Android.bp
index 4d149f7..a0e3985 100644
--- a/test-base/Android.bp
+++ b/test-base/Android.bp
@@ -81,3 +81,38 @@
"junit",
],
}
+
+droiddoc {
+ name: "android-test-base-api-stubs-gen-docs",
+ srcs: [
+ "src/**/*.java",
+ ],
+ custom_template: "droiddoc-templates-sdk",
+ installable: false,
+ args: "-stubpackages android.test:" +
+ "android.test.suitebuilder.annotation:" +
+ "com.android.internal.util:" +
+ "junit.framework -stubsourceonly -nodocs",
+ sdk_version: "current",
+ api_tag_name: "ANDROID_TEST_BASE",
+ api_filename: "android-test-base-api.txt",
+ removed_api_filename: "android-test-base-removed.txt",
+}
+
+// Build the android.test.base.stubs library
+// =========================================
+java_library_static {
+ name: "android.test.base.stubs",
+ srcs: [
+ ":android-test-base-api-stubs-gen-docs",
+ ],
+ product_variables: {
+ pdk: {
+ enabled: false,
+ },
+ unbundled_build: {
+ enabled: false,
+ },
+ },
+ sdk_version: "current",
+}
diff --git a/test-base/Android.mk b/test-base/Android.mk
index ebb33de..baf5726 100644
--- a/test-base/Android.mk
+++ b/test-base/Android.mk
@@ -19,59 +19,10 @@
# For unbundled build we'll use the prebuilt jar from prebuilts/sdk.
ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
-# Generate the stub source files for android.test.base.stubs
-# ==========================================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/src
-
-ANDROID_TEST_BASE_OUTPUT_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.base.stubs_intermediates/api.txt
-ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.base.stubs_intermediates/removed.txt
-
ANDROID_TEST_BASE_API_FILE := $(LOCAL_PATH)/api/android-test-base-current.txt
ANDROID_TEST_BASE_REMOVED_API_FILE := $(LOCAL_PATH)/api/android-test-base-removed.txt
-LOCAL_DROIDDOC_OPTIONS:= \
- -stubpackages android.test:android.test.suitebuilder.annotation:com.android.internal.util:junit.framework \
- -stubsourceonly \
- -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.base.stubs_intermediates/src \
- -nodocs \
- -api $(ANDROID_TEST_BASE_OUTPUT_API_FILE) \
- -removedApi $(ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE) \
-
-LOCAL_UNINSTALLABLE_MODULE := true
-LOCAL_MODULE := android-test-base-api-stubs-gen
-
-include $(BUILD_DROIDDOC)
-
-# Remember the target that will trigger the code generation.
-android_test_base_gen_stamp := $(full_target)
-
-# Add some additional dependencies
-$(ANDROID_TEST_BASE_OUTPUT_API_FILE): $(full_target)
-$(ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE): $(full_target)
-
-# Build the android.test.base.stubs library
-# =========================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := android.test.base.stubs
-
-LOCAL_SOURCE_FILES_ALL_GENERATED := true
-LOCAL_SDK_VERSION := current
-
-# Make sure to run droiddoc first to generate the stub source files.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(android_test_base_gen_stamp)
-android_test_base_gen_stamp :=
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
+full_classes_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,android.test.base.stubs,,COMMON)/classes.jar
# Archive a copy of the classes.jar in SDK build.
$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.base.stubs.jar)
@@ -83,16 +34,16 @@
$(eval $(call check-api, \
check-android-test-base-api-current, \
$(ANDROID_TEST_BASE_API_FILE), \
- $(ANDROID_TEST_BASE_OUTPUT_API_FILE), \
+ $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_API_FILE), \
$(ANDROID_TEST_BASE_REMOVED_API_FILE), \
- $(ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE), \
+ $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_REMOVED_API_FILE), \
-error 2 -error 3 -error 4 -error 5 -error 6 \
-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \
-error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \
-error 25 -error 26 -error 27, \
cat $(LOCAL_PATH)/api/apicheck_msg_android_test_base.txt, \
check-android-test-base-api, \
- $(call doc-timestamp-for,android-test-base-api-stubs-gen) \
+ $(OUT_DOCS)/android-test-base-api-stubs-gen-docs-stubs.srcjar \
))
.PHONY: check-android-test-base-api
@@ -101,11 +52,11 @@
.PHONY: update-android-test-base-api
update-api: update-android-test-base-api
-update-android-test-base-api: $(ANDROID_TEST_BASE_OUTPUT_API_FILE) | $(ACP)
+update-android-test-base-api: $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_API_FILE) | $(ACP)
@echo Copying current.txt
- $(hide) $(ACP) $(ANDROID_TEST_BASE_OUTPUT_API_FILE) $(ANDROID_TEST_BASE_API_FILE)
+ $(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_API_FILE) $(ANDROID_TEST_BASE_API_FILE)
@echo Copying removed.txt
- $(hide) $(ACP) $(ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE) $(ANDROID_TEST_BASE_REMOVED_API_FILE)
+ $(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_REMOVED_API_FILE) $(ANDROID_TEST_BASE_REMOVED_API_FILE)
endif # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index 9364ec8..082f310 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -30,7 +30,6 @@
import android.content.Context;
import android.net.LinkAddress;
import android.net.LinkProperties;
-import android.net.NetworkUtils;
import android.net.apf.ApfFilter.ApfConfiguration;
import android.net.apf.ApfGenerator.IllegalInstructionException;
import android.net.apf.ApfGenerator.Register;
@@ -42,22 +41,13 @@
import android.os.Parcelable;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.system.ErrnoException;
import android.system.Os;
import android.text.format.DateUtils;
-
import com.android.frameworks.tests.net.R;
import com.android.internal.util.HexDump;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
@@ -68,9 +58,14 @@
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Random;
-
import libcore.io.IoUtils;
import libcore.io.Streams;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
/**
* Tests for APF program generator and interpreter.
@@ -82,6 +77,7 @@
@SmallTest
public class ApfTest {
private static final int TIMEOUT_MS = 500;
+ private final static int MIN_APF_VERSION = 2;
@Mock IpConnectivityLog mLog;
@Mock Context mContext;
@@ -131,11 +127,11 @@
}
private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) {
- assertReturnCodesEqual(expected, apfSimulate(program, packet, filterAge));
+ assertReturnCodesEqual(expected, apfSimulate(program, packet, null, filterAge));
}
private void assertVerdict(int expected, byte[] program, byte[] packet) {
- assertReturnCodesEqual(expected, apfSimulate(program, packet, 0));
+ assertReturnCodesEqual(expected, apfSimulate(program, packet, null, 0));
}
private void assertPass(byte[] program, byte[] packet, int filterAge) {
@@ -154,9 +150,24 @@
assertVerdict(DROP, program, packet);
}
+ private void assertDataMemoryContents(
+ int expected, byte[] program, byte[] packet, byte[] data, byte[] expected_data)
+ throws IllegalInstructionException, Exception {
+ assertReturnCodesEqual(expected, apfSimulate(program, packet, data, 0 /* filterAge */));
+
+ // assertArrayEquals() would only print one byte, making debugging difficult.
+ if (!java.util.Arrays.equals(expected_data, data)) {
+ throw new Exception(
+ "program: " + HexDump.toHexString(program) +
+ "\ndata memory: " + HexDump.toHexString(data) +
+ "\nexpected: " + HexDump.toHexString(expected_data));
+ }
+ }
+
private void assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge)
throws IllegalInstructionException {
- assertReturnCodesEqual(expected, apfSimulate(gen.generate(), packet, filterAge));
+ assertReturnCodesEqual(expected, apfSimulate(gen.generate(), packet, null,
+ filterAge));
}
private void assertPass(ApfGenerator gen, byte[] packet, int filterAge)
@@ -189,11 +200,11 @@
// Empty program should pass because having the program counter reach the
// location immediately after the program indicates the packet should be
// passed to the AP.
- ApfGenerator gen = new ApfGenerator();
+ ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION);
assertPass(gen);
// Test jumping to pass label.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addJump(gen.PASS_LABEL);
byte[] program = gen.generate();
assertEquals(1, program.length);
@@ -201,7 +212,7 @@
assertPass(program, new byte[MIN_PKT_SIZE], 0);
// Test jumping to drop label.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addJump(gen.DROP_LABEL);
program = gen.generate();
assertEquals(2, program.length);
@@ -210,121 +221,121 @@
assertDrop(program, new byte[15], 15);
// Test jumping if equal to 0.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if not equal to 0.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
assertPass(gen);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if registers equal.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addJumpIfR0EqualsR1(gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if registers not equal.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
assertPass(gen);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
assertDrop(gen);
// Test load immediate.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test add.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addAdd(1234567890);
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test subtract.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addAdd(-1234567890);
gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test or.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addOr(1234567890);
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test and.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addAnd(123456789);
gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
assertDrop(gen);
// Test left shift.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addLeftShift(1);
gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
assertDrop(gen);
// Test right shift.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addRightShift(1);
gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
assertDrop(gen);
// Test multiply.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addMul(2);
gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
assertDrop(gen);
// Test divide.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addDiv(2);
gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
assertDrop(gen);
// Test divide by zero.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addDiv(0);
gen.addJump(gen.DROP_LABEL);
assertPass(gen);
// Test add.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R1, 1234567890);
gen.addAddR1();
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test subtract.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R1, -1234567890);
gen.addAddR1();
gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test or.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R1, 1234567890);
gen.addOrR1();
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test and.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addLoadImmediate(Register.R1, 123456789);
gen.addAndR1();
@@ -332,7 +343,7 @@
assertDrop(gen);
// Test left shift.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addLoadImmediate(Register.R1, 1);
gen.addLeftShiftR1();
@@ -340,7 +351,7 @@
assertDrop(gen);
// Test right shift.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addLoadImmediate(Register.R1, -1);
gen.addLeftShiftR1();
@@ -348,7 +359,7 @@
assertDrop(gen);
// Test multiply.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addLoadImmediate(Register.R1, 2);
gen.addMulR1();
@@ -356,7 +367,7 @@
assertDrop(gen);
// Test divide.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addLoadImmediate(Register.R1, 2);
gen.addDivR1();
@@ -364,136 +375,136 @@
assertDrop(gen);
// Test divide by zero.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addDivR1();
gen.addJump(gen.DROP_LABEL);
assertPass(gen);
// Test byte load.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoad8(Register.R0, 1);
gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
// Test out of bounds load.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoad8(Register.R0, 16);
gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
// Test half-word load.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoad16(Register.R0, 1);
gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
// Test word load.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoad32(Register.R0, 1);
gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
// Test byte indexed load.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R1, 1);
gen.addLoad8Indexed(Register.R0, 0);
gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
// Test out of bounds indexed load.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R1, 8);
gen.addLoad8Indexed(Register.R0, 8);
gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
// Test half-word indexed load.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R1, 1);
gen.addLoad16Indexed(Register.R0, 0);
gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
// Test word indexed load.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R1, 1);
gen.addLoad32Indexed(Register.R0, 0);
gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
// Test jumping if greater than.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
assertPass(gen);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if less than.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addJumpIfR0LessThan(0, gen.DROP_LABEL);
assertPass(gen);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addJumpIfR0LessThan(1, gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if any bits set.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
assertPass(gen);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
assertDrop(gen);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 3);
gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if register greater than.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
assertPass(gen);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 2);
gen.addLoadImmediate(Register.R1, 1);
gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if register less than.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
assertPass(gen);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R1, 1);
gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if any bits set in register.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R1, 3);
gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
assertPass(gen);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R1, 3);
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
assertDrop(gen);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R1, 3);
gen.addLoadImmediate(Register.R0, 3);
gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
assertDrop(gen);
// Test load from memory.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadFromMemory(Register.R0, 0);
gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
assertDrop(gen);
// Test store to memory.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R1, 1234567890);
gen.addStoreToMemory(Register.R1, 12);
gen.addLoadFromMemory(Register.R0, 12);
@@ -501,63 +512,63 @@
assertDrop(gen);
// Test filter age pre-filled memory.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890);
// Test packet size pre-filled memory.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
gen.addJumpIfR0Equals(MIN_PKT_SIZE, gen.DROP_LABEL);
assertDrop(gen);
// Test IPv4 header size pre-filled memory.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
gen.addJumpIfR0Equals(20, gen.DROP_LABEL);
assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x45}, 0);
// Test not.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addNot(Register.R0);
gen.addJumpIfR0Equals(~1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test negate.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addNeg(Register.R0);
gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test move.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R1, 1234567890);
gen.addMove(Register.R0);
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addMove(Register.R1);
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test swap.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R1, 1234567890);
gen.addSwap();
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addSwap();
gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
assertDrop(gen);
// Test jump if bytes not equal.
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
program = gen.generate();
@@ -569,25 +580,152 @@
assertEquals(1, program[4]);
assertEquals(123, program[5]);
assertDrop(program, new byte[MIN_PKT_SIZE], 0);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
byte[] packet123 = {0,123,0,0,0,0,0,0,0,0,0,0,0,0,0};
assertPass(gen, packet123, 0);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
assertDrop(gen, packet123, 0);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL);
byte[] packet12345 = {0,1,2,3,4,5,0,0,0,0,0,0,0,0,0};
assertDrop(gen, packet12345, 0);
- gen = new ApfGenerator();
+ gen = new ApfGenerator(MIN_APF_VERSION);
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,3,4,5}, gen.DROP_LABEL);
assertPass(gen, packet12345, 0);
}
+ @Test(expected = ApfGenerator.IllegalInstructionException.class)
+ public void testApfGeneratorWantsV2OrGreater() throws Exception {
+ // The minimum supported APF version is 2.
+ new ApfGenerator(1);
+ }
+
+ @Test
+ public void testApfDataOpcodesWantApfV3() throws IllegalInstructionException, Exception {
+ ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION);
+ try {
+ gen.addStoreData(Register.R0, 0);
+ fail();
+ } catch (IllegalInstructionException expected) {
+ /* pass */
+ }
+ try {
+ gen.addLoadData(Register.R0, 0);
+ fail();
+ } catch (IllegalInstructionException expected) {
+ /* pass */
+ }
+ }
+
+ @Test
+ public void testApfDataWrite() throws IllegalInstructionException, Exception {
+ byte[] packet = new byte[MIN_PKT_SIZE];
+ byte[] data = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
+ byte[] expected_data = data.clone();
+
+ // No memory access instructions: should leave the data segment untouched.
+ ApfGenerator gen = new ApfGenerator(3);
+ assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
+
+ // Expect value 0x87654321 to be stored starting from address 3 + 2, in big-endian order.
+ gen = new ApfGenerator(3);
+ gen.addLoadImmediate(Register.R0, 0x87654321);
+ gen.addLoadImmediate(Register.R1, 2);
+ gen.addStoreData(Register.R0, 3);
+ expected_data[5] = (byte)0x87;
+ expected_data[6] = (byte)0x65;
+ expected_data[7] = (byte)0x43;
+ expected_data[8] = (byte)0x21;
+ assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
+ }
+
+ @Test
+ public void testApfDataRead() throws IllegalInstructionException, Exception {
+ // Program that DROPs if address 11 (7 + 3) contains 0x87654321.
+ ApfGenerator gen = new ApfGenerator(3);
+ gen.addLoadImmediate(Register.R1, 3);
+ gen.addLoadData(Register.R0, 7);
+ gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL);
+ byte[] program = gen.generate();
+ byte[] packet = new byte[MIN_PKT_SIZE];
+
+ // Content is incorrect (last byte does not match) -> PASS
+ byte[] data = new byte[32];
+ data[10] = (byte)0x87;
+ data[11] = (byte)0x65;
+ data[12] = (byte)0x43;
+ data[13] = (byte)0x00; // != 0x21
+ byte[] expected_data = data.clone();
+ assertDataMemoryContents(PASS, program, packet, data, expected_data);
+
+ // Fix the last byte -> conditional jump taken -> DROP
+ data[13] = (byte)0x21;
+ expected_data = data;
+ assertDataMemoryContents(DROP, program, packet, data, expected_data);
+ }
+
+ @Test
+ public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception {
+ ApfGenerator gen = new ApfGenerator(3);
+ gen.addLoadImmediate(Register.R1, 3);
+ gen.addLoadData(Register.R0, 7); // Load from address 7 + 3 = 10
+ gen.addAdd(0x78453412); // 87654321 + 78453412 = FFAA7733
+ gen.addStoreData(Register.R0, 11); // Write back to address 11 + 3 = 14
+
+ byte[] packet = new byte[MIN_PKT_SIZE];
+ byte[] data = new byte[32];
+ data[10] = (byte)0x87;
+ data[11] = (byte)0x65;
+ data[12] = (byte)0x43;
+ data[13] = (byte)0x21;
+ byte[] expected_data = data.clone();
+ expected_data[14] = (byte)0xFF;
+ expected_data[15] = (byte)0xAA;
+ expected_data[16] = (byte)0x77;
+ expected_data[17] = (byte)0x33;
+ assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
+ }
+
+ @Test
+ public void testApfDataBoundChecking() throws IllegalInstructionException, Exception {
+ byte[] packet = new byte[MIN_PKT_SIZE];
+ byte[] data = new byte[32];
+ byte[] expected_data = data;
+
+ // Program that DROPs unconditionally. This is our the baseline.
+ ApfGenerator gen = new ApfGenerator(3);
+ gen.addLoadImmediate(Register.R0, 3);
+ gen.addLoadData(Register.R1, 7);
+ gen.addJump(gen.DROP_LABEL);
+ assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
+
+ // Same program as before, but this time we're trying to load past the end of the data.
+ gen = new ApfGenerator(3);
+ gen.addLoadImmediate(Register.R0, 20);
+ gen.addLoadData(Register.R1, 15); // 20 + 15 > 32
+ gen.addJump(gen.DROP_LABEL); // Not reached.
+ assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
+
+ // Subtracting an immediate should work...
+ gen = new ApfGenerator(3);
+ gen.addLoadImmediate(Register.R0, 20);
+ gen.addLoadData(Register.R1, -4);
+ gen.addJump(gen.DROP_LABEL);
+ assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
+
+ // ...but underflowing isn't allowed.
+ gen = new ApfGenerator(3);
+ gen.addLoadImmediate(Register.R0, 20);
+ gen.addLoadData(Register.R1, -30);
+ gen.addJump(gen.DROP_LABEL); // Not reached.
+ assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
+ }
+
/**
* Generate some BPF programs, translate them to APF, then run APF and BPF programs
* over packet traces and verify both programs filter out the same packets.
@@ -1422,10 +1560,11 @@
}
/**
- * Call the APF interpreter the run {@code program} on {@code packet} pretending the
- * filter was installed {@code filter_age} seconds ago.
+ * Call the APF interpreter to run {@code program} on {@code packet} with persistent memory
+ * segment {@data} pretending the filter was installed {@code filter_age} seconds ago.
*/
- private native static int apfSimulate(byte[] program, byte[] packet, int filter_age);
+ private native static int apfSimulate(byte[] program, byte[] packet, byte[] data,
+ int filter_age);
/**
* Compile a tcpdump human-readable filter (e.g. "icmp" or "tcp port 54") into a BPF
diff --git a/tests/net/java/android/net/apf/Bpf2Apf.java b/tests/net/java/android/net/apf/Bpf2Apf.java
index 220e54d..5d57cde 100644
--- a/tests/net/java/android/net/apf/Bpf2Apf.java
+++ b/tests/net/java/android/net/apf/Bpf2Apf.java
@@ -307,7 +307,7 @@
* program and return it.
*/
public static byte[] convert(String bpf) throws IllegalInstructionException {
- ApfGenerator gen = new ApfGenerator();
+ ApfGenerator gen = new ApfGenerator(3);
for (String line : bpf.split("\\n")) convertLine(line, gen);
return gen.generate();
}
@@ -320,7 +320,7 @@
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line = null;
StringBuilder responseData = new StringBuilder();
- ApfGenerator gen = new ApfGenerator();
+ ApfGenerator gen = new ApfGenerator(3);
while ((line = in.readLine()) != null) convertLine(line, gen);
System.out.write(gen.generate());
}
diff --git a/tests/net/jni/apf_jni.cpp b/tests/net/jni/apf_jni.cpp
index 152e6c3..79444e3 100644
--- a/tests/net/jni/apf_jni.cpp
+++ b/tests/net/jni/apf_jni.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2016, The Android Open Source Project
+ * 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.
@@ -28,15 +28,22 @@
// JNI function acting as simply call-through to native APF interpreter.
static jint com_android_server_ApfTest_apfSimulate(
- JNIEnv* env, jclass, jbyteArray program, jbyteArray packet, jint filter_age) {
- return accept_packet(
- (uint8_t*)env->GetByteArrayElements(program, NULL),
- env->GetArrayLength(program),
- (uint8_t*)env->GetByteArrayElements(packet, NULL),
- env->GetArrayLength(packet),
- nullptr,
- 0,
- filter_age);
+ JNIEnv* env, jclass, jbyteArray program, jbyteArray packet,
+ jbyteArray data, jint filter_age) {
+ uint8_t* program_raw = (uint8_t*)env->GetByteArrayElements(program, nullptr);
+ uint8_t* packet_raw = (uint8_t*)env->GetByteArrayElements(packet, nullptr);
+ uint8_t* data_raw = (uint8_t*)(data ? env->GetByteArrayElements(data, nullptr) : nullptr);
+ uint32_t program_len = env->GetArrayLength(program);
+ uint32_t packet_len = env->GetArrayLength(packet);
+ uint32_t data_len = data ? env->GetArrayLength(data) : 0;
+ jint result = accept_packet(program_raw, program_len, packet_raw,
+ packet_len, data_raw, data_len, filter_age);
+ if (data) {
+ env->ReleaseByteArrayElements(data, (jbyte*)data_raw, 0 /* copy back */);
+ }
+ env->ReleaseByteArrayElements(packet, (jbyte*)packet_raw, JNI_ABORT);
+ env->ReleaseByteArrayElements(program, (jbyte*)program_raw, JNI_ABORT);
+ return result;
}
class ScopedPcap {
@@ -170,7 +177,7 @@
}
static JNINativeMethod gMethods[] = {
- { "apfSimulate", "([B[BI)I",
+ { "apfSimulate", "([B[B[BI)I",
(void*)com_android_server_ApfTest_apfSimulate },
{ "compileToBpf", "(Ljava/lang/String;)Ljava/lang/String;",
(void*)com_android_server_ApfTest_compileToBpf },