Merge "Fix documentation generation with OpenJDK 9 javadoc."
diff --git a/Android.bp b/Android.bp
index 6b61467..0b09b46 100644
--- a/Android.bp
+++ b/Android.bp
@@ -16,8 +16,6 @@
cc_library {
name: "libplatformprotos",
host_supported: true,
- // b/34740546, work around clang-tidy segmentation fault.
- tidy_checks: ["-modernize*"],
proto: {
export_proto_headers: true,
include_dirs: ["external/protobuf/src"],
@@ -63,3 +61,25 @@
optional_subdirs = [
"core/tests/utiltests/jni",
]
+
+java_library {
+ name: "hwbinder",
+ no_framework_libs: true,
+
+ srcs: [
+ "core/java/android/os/HidlSupport.java",
+ "core/java/android/annotation/NonNull.java",
+ "core/java/android/os/HwBinder.java",
+ "core/java/android/os/HwBlob.java",
+ "core/java/android/os/HwParcel.java",
+ "core/java/android/os/IHwBinder.java",
+ "core/java/android/os/IHwInterface.java",
+ "core/java/android/os/DeadObjectException.java",
+ "core/java/android/os/DeadSystemException.java",
+ "core/java/android/os/RemoteException.java",
+ "core/java/android/util/AndroidException.java",
+ ],
+
+ dxflags: ["--core-library"],
+ installable: false,
+}
diff --git a/Android.mk b/Android.mk
index b92f31e..d9a175c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -611,32 +611,6 @@
framework_built := $(call java-lib-deps,framework)
-# HwBinder
-# =======================================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- core/java/android/os/HidlSupport.java \
- core/java/android/annotation/NonNull.java \
- core/java/android/os/HwBinder.java \
- core/java/android/os/HwBlob.java \
- core/java/android/os/HwParcel.java \
- core/java/android/os/IHwBinder.java \
- core/java/android/os/IHwInterface.java \
- core/java/android/os/DeadObjectException.java \
- core/java/android/os/DeadSystemException.java \
- core/java/android/os/RemoteException.java \
- core/java/android/util/AndroidException.java \
-
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := hwbinder
-
-LOCAL_DX_FLAGS := --core-library
-LOCAL_UNINSTALLABLE_MODULE := true
-include $(BUILD_JAVA_LIBRARY)
-
# Copy AIDL files to be preprocessed and included in the SDK,
# specified relative to the root of the build tree.
# ============================================================
diff --git a/api/current.txt b/api/current.txt
index c1f05e5..df4f8b7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -40510,8 +40510,13 @@
public class DownloadStateCallback {
ctor public DownloadStateCallback();
+ ctor public DownloadStateCallback(int);
+ method public final boolean isFilterFlagSet(int);
method public void onProgressUpdated(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo, int, int, int, int);
method public void onStateUpdated(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo, int);
+ field public static final int ALL_UPDATES = 0; // 0x0
+ field public static final int PROGRESS_UPDATES = 1; // 0x1
+ field public static final int STATE_UPDATES = 2; // 0x2
}
public final class FileInfo implements android.os.Parcelable {
@@ -40585,6 +40590,7 @@
public class ServiceInfo {
method public java.util.List<java.util.Locale> getLocales();
method public java.lang.CharSequence getNameForLocale(java.util.Locale);
+ method public java.util.Set<java.util.Locale> getNamedContentLocales();
method public java.lang.String getServiceClassName();
method public java.lang.String getServiceId();
method public java.util.Date getSessionEndTime();
@@ -52139,6 +52145,8 @@
field public static final int OP_CONST_CLASS = 28; // 0x1c
field public static final int OP_CONST_CLASS_JUMBO = 255; // 0xff
field public static final int OP_CONST_HIGH16 = 21; // 0x15
+ field public static final int OP_CONST_METHOD_HANDLE = 254; // 0xfe
+ field public static final int OP_CONST_METHOD_TYPE = 255; // 0xff
field public static final int OP_CONST_STRING = 26; // 0x1a
field public static final int OP_CONST_STRING_JUMBO = 27; // 0x1b
field public static final int OP_CONST_WIDE = 24; // 0x18
diff --git a/api/system-current.txt b/api/system-current.txt
index 0ce7908..16fa870 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -44029,8 +44029,13 @@
public class DownloadStateCallback {
ctor public DownloadStateCallback();
+ ctor public DownloadStateCallback(int);
+ method public final boolean isFilterFlagSet(int);
method public void onProgressUpdated(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo, int, int, int, int);
method public void onStateUpdated(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo, int);
+ field public static final int ALL_UPDATES = 0; // 0x0
+ field public static final int PROGRESS_UPDATES = 1; // 0x1
+ field public static final int STATE_UPDATES = 2; // 0x2
}
public final class FileInfo implements android.os.Parcelable {
@@ -44113,6 +44118,7 @@
public class ServiceInfo {
method public java.util.List<java.util.Locale> getLocales();
method public java.lang.CharSequence getNameForLocale(java.util.Locale);
+ method public java.util.Set<java.util.Locale> getNamedContentLocales();
method public java.lang.String getServiceClassName();
method public java.lang.String getServiceId();
method public java.util.Date getSessionEndTime();
@@ -56119,6 +56125,8 @@
field public static final int OP_CONST_CLASS = 28; // 0x1c
field public static final int OP_CONST_CLASS_JUMBO = 255; // 0xff
field public static final int OP_CONST_HIGH16 = 21; // 0x15
+ field public static final int OP_CONST_METHOD_HANDLE = 254; // 0xfe
+ field public static final int OP_CONST_METHOD_TYPE = 255; // 0xff
field public static final int OP_CONST_STRING = 26; // 0x1a
field public static final int OP_CONST_STRING_JUMBO = 27; // 0x1b
field public static final int OP_CONST_WIDE = 24; // 0x18
diff --git a/api/test-current.txt b/api/test-current.txt
index 685e06a..cf8b8b3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -40732,8 +40732,13 @@
public class DownloadStateCallback {
ctor public DownloadStateCallback();
+ ctor public DownloadStateCallback(int);
+ method public final boolean isFilterFlagSet(int);
method public void onProgressUpdated(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo, int, int, int, int);
method public void onStateUpdated(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo, int);
+ field public static final int ALL_UPDATES = 0; // 0x0
+ field public static final int PROGRESS_UPDATES = 1; // 0x1
+ field public static final int STATE_UPDATES = 2; // 0x2
}
public final class FileInfo implements android.os.Parcelable {
@@ -40807,6 +40812,7 @@
public class ServiceInfo {
method public java.util.List<java.util.Locale> getLocales();
method public java.lang.CharSequence getNameForLocale(java.util.Locale);
+ method public java.util.Set<java.util.Locale> getNamedContentLocales();
method public java.lang.String getServiceClassName();
method public java.lang.String getServiceId();
method public java.util.Date getSessionEndTime();
@@ -52563,6 +52569,8 @@
field public static final int OP_CONST_CLASS = 28; // 0x1c
field public static final int OP_CONST_CLASS_JUMBO = 255; // 0xff
field public static final int OP_CONST_HIGH16 = 21; // 0x15
+ field public static final int OP_CONST_METHOD_HANDLE = 254; // 0xfe
+ field public static final int OP_CONST_METHOD_TYPE = 255; // 0xff
field public static final int OP_CONST_STRING = 26; // 0x1a
field public static final int OP_CONST_STRING_JUMBO = 27; // 0x1b
field public static final int OP_CONST_WIDE = 24; // 0x18
diff --git a/compiled-classes-phone b/config/compiled-classes-phone
similarity index 99%
rename from compiled-classes-phone
rename to config/compiled-classes-phone
index 71fc5c1..063276d 100644
--- a/compiled-classes-phone
+++ b/config/compiled-classes-phone
@@ -26,7 +26,7 @@
# to your device.mk, e.g.,
#
# PRODUCT_COPY_FILES += \
-# frameworks/base/compiled-classes-phone:system/etc/compiled-classes
+# frameworks/base/config/compiled-classes-phone:system/etc/compiled-classes
#
android.R$styleable
android.accessibilityservice.AccessibilityServiceInfo
diff --git a/dirty-image-objects b/config/dirty-image-objects
similarity index 100%
rename from dirty-image-objects
rename to config/dirty-image-objects
diff --git a/preloaded-classes b/config/preloaded-classes
similarity index 99%
rename from preloaded-classes
rename to config/preloaded-classes
index c1896aa..8233b03 100644
--- a/preloaded-classes
+++ b/config/preloaded-classes
@@ -2286,6 +2286,7 @@
android.util.Log
android.util.Log$1
android.util.Log$ImmediateLogWriter
+android.util.Log$PreloadHolder
android.util.Log$TerribleFailure
android.util.Log$TerribleFailureHandler
android.util.LogPrinter
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 70591d4..84765f6 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1134,6 +1134,29 @@
}
/**
+ * Sets the {@link BluetoothClass} Bluetooth Class of Device (CoD) of
+ * the local Bluetooth adapter.
+ *
+ * @param bluetoothClass {@link BluetoothClass} to set the local Bluetooth adapter to.
+ * @return true if successful, false if unsuccessful.
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public boolean setBluetoothClass(BluetoothClass bluetoothClass) {
+ if (getState() != STATE_ON) return false;
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null) return mService.setBluetoothClass(bluetoothClass);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ return false;
+ }
+
+ /**
* Get the current Bluetooth scan mode of the local Bluetooth adapter.
* <p>The Bluetooth scan mode determines if the local adapter is
* connectable and/or discoverable from remote Bluetooth devices.
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
index 57e4abb..f22ea6e 100755
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ b/core/java/android/bluetooth/BluetoothClass.java
@@ -19,6 +19,10 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+
/**
* Represents a Bluetooth class, which describes general characteristics
* and capabilities of a device. For example, a Bluetooth class will
@@ -275,6 +279,48 @@
return (mClass & Device.BITMASK);
}
+ /**
+ * Return the Bluetooth Class of Device (CoD) value including the
+ * {@link BluetoothClass.Service}, {@link BluetoothClass.Device.Major} and
+ * minor device fields.
+ *
+ * <p>This value is an integer representation of Bluetooth CoD as in
+ * Bluetooth specification.
+ *
+ * @see <a href="Bluetooth CoD">https://www.bluetooth.com/specifications/assigned-numbers/baseband</a>
+ *
+ * @hide
+ */
+ public int getClassOfDevice() {
+ return mClass;
+ }
+
+ /**
+ * Return the Bluetooth Class of Device (CoD) value including the
+ * {@link BluetoothClass.Service}, {@link BluetoothClass.Device.Major} and
+ * minor device fields.
+ *
+ * <p>This value is a byte array representation of Bluetooth CoD as in
+ * Bluetooth specification.
+ *
+ * <p>Bluetooth COD information is 3 bytes, but stored as an int. Hence the
+ * MSB is useless and needs to be thrown away. The lower 3 bytes are
+ * converted into a byte array MSB to LSB. Hence, using BIG_ENDIAN.
+ *
+ * @see <a href="Bluetooth CoD">https://www.bluetooth.com/specifications/assigned-numbers/baseband</a>
+ *
+ * @hide
+ */
+ public byte[] getClassOfDeviceBytes() {
+ byte[] bytes = ByteBuffer.allocate(4)
+ .order(ByteOrder.BIG_ENDIAN)
+ .putInt(mClass)
+ .array();
+
+ // Discard the top byte
+ return Arrays.copyOfRange(bytes, 1, bytes.length);
+ }
+
/** @hide */
public static final int PROFILE_HEADSET = 0;
/** @hide */
diff --git a/core/java/android/bluetooth/BluetoothInputHost.java b/core/java/android/bluetooth/BluetoothInputHost.java
index 37f0427..e18d9d1 100644
--- a/core/java/android/bluetooth/BluetoothInputHost.java
+++ b/core/java/android/bluetooth/BluetoothInputHost.java
@@ -74,7 +74,7 @@
public static final byte SUBCLASS2_GAMEPAD = (byte) 0x02;
public static final byte SUBCLASS2_REMOTE_CONTROL = (byte) 0x03;
public static final byte SUBCLASS2_SENSING_DEVICE = (byte) 0x04;
- public static final byte SUBCLASS2_DIGITIZER_TABLED = (byte) 0x05;
+ public static final byte SUBCLASS2_DIGITIZER_TABLET = (byte) 0x05;
public static final byte SUBCLASS2_CARD_READER = (byte) 0x06;
/**
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index 19f5198..a1a9347 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -16,6 +16,7 @@
package android.bluetooth;
+import android.annotation.SdkConstant;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -53,35 +54,32 @@
private static final boolean DBG = true;
private static final boolean VDBG = false;
- /** int extra for PBAP_STATE_CHANGED_ACTION */
- public static final String PBAP_STATE =
- "android.bluetooth.pbap.intent.PBAP_STATE";
- /** int extra for PBAP_STATE_CHANGED_ACTION */
- public static final String PBAP_PREVIOUS_STATE =
- "android.bluetooth.pbap.intent.PBAP_PREVIOUS_STATE";
-
/**
- * Indicates the state of a pbap connection state has changed.
- * This intent will always contain PBAP_STATE, PBAP_PREVIOUS_STATE and
- * BluetoothIntent.ADDRESS extras.
+ * Intent used to broadcast the change in connection state of the PBAP
+ * profile.
+ *
+ * <p>This intent will have 3 extras:
+ * <ul>
+ * <li> {@link BluetoothProfile#EXTRA_STATE} - The current state of the profile. </li>
+ * <li> {@link BluetoothProfile#EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+ * </ul>
+ * <p>{@link BluetoothProfile#EXTRA_STATE} or {@link BluetoothProfile#EXTRA_PREVIOUS_STATE}
+ * can be any of {@link BluetoothProfile#STATE_DISCONNECTED},
+ * {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_CONNECTED},
+ * {@link BluetoothProfile#STATE_DISCONNECTING}.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
*/
- public static final String PBAP_STATE_CHANGED_ACTION =
- "android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED";
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_CONNECTION_STATE_CHANGED =
+ "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
private volatile IBluetoothPbap mService;
private final Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
- /** There was an error trying to obtain the state */
- public static final int STATE_ERROR = -1;
- /** No client currently connected */
- public static final int STATE_DISCONNECTED = 0;
- /** Connection attempt in progress */
- public static final int STATE_CONNECTING = 1;
- /** Client is currently connected */
- public static final int STATE_CONNECTED = 2;
-
public static final int RESULT_FAILURE = 0;
public static final int RESULT_SUCCESS = 1;
/** Connection canceled before completion. */
@@ -209,8 +207,8 @@
/**
* Get the current state of the BluetoothPbap service.
*
- * @return One of the STATE_ return codes, or STATE_ERROR if this proxy object is currently not
- * connected to the Pbap service.
+ * @return One of the STATE_ return codes, or {@link BluetoothProfile#STATE_DISCONNECTED}
+ * if this proxy object is currently not connected to the Pbap service.
*/
public int getState() {
if (VDBG) log("getState()");
@@ -225,7 +223,7 @@
Log.w(TAG, "Proxy not attached to service");
if (DBG) log(Log.getStackTraceString(new Throwable()));
}
- return BluetoothPbap.STATE_ERROR;
+ return BluetoothProfile.STATE_DISCONNECTED;
}
/**
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
index 00a15f3..01b3f6e 100644
--- a/core/java/android/bluetooth/BluetoothPbapClient.java
+++ b/core/java/android/bluetooth/BluetoothPbapClient.java
@@ -40,7 +40,7 @@
private static final boolean VDBG = false;
public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
+ "android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED";
private volatile IBluetoothPbapClient mService;
private final Context mContext;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 583cf32..0ccebc1c 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2084,16 +2084,30 @@
* {@code ro.tether.denied} system property, Settings.TETHER_SUPPORTED or
* due to device configuration.
*
+ * <p>If this app does not have permission to use this API, it will always
+ * return false rather than throw an exception.</p>
+ *
+ * <p>If the device has a hotspot provisioning app, the caller is required to hold the
+ * {@link android.Manifest.permission.TETHER_PRIVILEGED} permission.</p>
+ *
+ * <p>Otherwise, this method requires the caller to hold the ability to modify system
+ * settings as determined by {@link android.provider.Settings.System#canWrite}.</p>
+ *
* @return a boolean - {@code true} indicating Tethering is supported.
*
* {@hide}
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+ @RequiresPermission(anyOf = {android.Manifest.permission.TETHER_PRIVILEGED,
+ android.Manifest.permission.WRITE_SETTINGS})
public boolean isTetheringSupported() {
+ String pkgName = mContext.getOpPackageName();
try {
- String pkgName = mContext.getOpPackageName();
return mService.isTetheringSupported(pkgName);
+ } catch (SecurityException e) {
+ // This API is not available to this caller, but for backward-compatibility
+ // this will just return false instead of throwing.
+ return false;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index ead406c..79310e2 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -24,6 +24,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
/**
* IpSecAlgorithm specifies a single algorithm that can be applied to an IpSec Transform. Refer to
@@ -75,13 +76,7 @@
public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
/** @hide */
- @StringDef({
- CRYPT_AES_CBC,
- AUTH_HMAC_MD5,
- AUTH_HMAC_SHA1,
- AUTH_HMAC_SHA256,
- AUTH_HMAC_SHA512
- })
+ @StringDef({CRYPT_AES_CBC, AUTH_HMAC_MD5, AUTH_HMAC_SHA1, AUTH_HMAC_SHA256, AUTH_HMAC_SHA512})
@Retention(RetentionPolicy.SOURCE)
public @interface AlgorithmName {}
@@ -197,4 +192,12 @@
.append("}")
.toString();
}
+
+ /** package */
+ static boolean equals(IpSecAlgorithm lhs, IpSecAlgorithm rhs) {
+ if (lhs == null || rhs == null) return (lhs == rhs);
+ return (lhs.mName.equals(rhs.mName)
+ && Arrays.equals(lhs.mKey, rhs.mKey)
+ && lhs.mTruncLenBits == rhs.mTruncLenBits);
+ }
};
diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java
index 5a5c740..632b7fc 100644
--- a/core/java/android/net/IpSecConfig.java
+++ b/core/java/android/net/IpSecConfig.java
@@ -17,105 +17,170 @@
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
+
+import com.android.internal.annotations.VisibleForTesting;
/** @hide */
public final class IpSecConfig implements Parcelable {
private static final String TAG = "IpSecConfig";
- //MODE_TRANSPORT or MODE_TUNNEL
- int mode;
+ // MODE_TRANSPORT or MODE_TUNNEL
+ private int mMode = IpSecTransform.MODE_TRANSPORT;
- // For tunnel mode
- InetAddress localAddress;
+ // Needs to be valid only for tunnel mode
+ // Preventing this from being null simplifies Java->Native binder
+ private String mLocalAddress = "";
- InetAddress remoteAddress;
+ // Preventing this from being null simplifies Java->Native binder
+ private String mRemoteAddress = "";
- // Limit selection by network interface
- Network network;
+ // The underlying Network that represents the "gateway" Network
+ // for outbound packets. It may also be used to select packets.
+ private Network mNetwork;
public static class Flow {
// Minimum requirements for identifying a transform
// SPI identifying the IPsec flow in packet processing
// and a remote IP address
- int spiResourceId;
+ private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID;
// Encryption Algorithm
- IpSecAlgorithm encryption;
+ private IpSecAlgorithm mEncryption;
// Authentication Algorithm
- IpSecAlgorithm authentication;
+ private IpSecAlgorithm mAuthentication;
@Override
public String toString() {
return new StringBuilder()
- .append("{spiResourceId=")
- .append(spiResourceId)
- .append(", encryption=")
- .append(encryption)
- .append(", authentication=")
- .append(authentication)
+ .append("{mSpiResourceId=")
+ .append(mSpiResourceId)
+ .append(", mEncryption=")
+ .append(mEncryption)
+ .append(", mAuthentication=")
+ .append(mAuthentication)
.append("}")
.toString();
}
+
+ static boolean equals(IpSecConfig.Flow lhs, IpSecConfig.Flow rhs) {
+ if (lhs == null || rhs == null) return (lhs == rhs);
+ return (lhs.mSpiResourceId == rhs.mSpiResourceId
+ && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption)
+ && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication));
+ }
}
- final Flow[] flow = new Flow[] {new Flow(), new Flow()};
+ private final Flow[] mFlow = new Flow[] {new Flow(), new Flow()};
// For tunnel mode IPv4 UDP Encapsulation
// IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE
- int encapType;
- int encapLocalPortResourceId;
- int encapRemotePort;
+ private int mEncapType = IpSecTransform.ENCAP_NONE;
+ private int mEncapSocketResourceId = IpSecManager.INVALID_RESOURCE_ID;
+ private int mEncapRemotePort;
// An interval, in seconds between the NattKeepalive packets
- int nattKeepaliveInterval;
+ private int mNattKeepaliveInterval;
+
+ /** Set the mode for this IPsec transform */
+ public void setMode(int mode) {
+ mMode = mode;
+ }
+
+ /** Set the local IP address for Tunnel mode */
+ public void setLocalAddress(String localAddress) {
+ if (localAddress == null) {
+ throw new IllegalArgumentException("localAddress may not be null!");
+ }
+ mLocalAddress = localAddress;
+ }
+
+ /** Set the remote IP address for this IPsec transform */
+ public void setRemoteAddress(String remoteAddress) {
+ if (remoteAddress == null) {
+ throw new IllegalArgumentException("remoteAddress may not be null!");
+ }
+ mRemoteAddress = remoteAddress;
+ }
+
+ /** Set the SPI for a given direction by resource ID */
+ public void setSpiResourceId(int direction, int resourceId) {
+ mFlow[direction].mSpiResourceId = resourceId;
+ }
+
+ /** Set the encryption algorithm for a given direction */
+ public void setEncryption(int direction, IpSecAlgorithm encryption) {
+ mFlow[direction].mEncryption = encryption;
+ }
+
+ /** Set the authentication algorithm for a given direction */
+ public void setAuthentication(int direction, IpSecAlgorithm authentication) {
+ mFlow[direction].mAuthentication = authentication;
+ }
+
+ public void setNetwork(Network network) {
+ mNetwork = network;
+ }
+
+ public void setEncapType(int encapType) {
+ mEncapType = encapType;
+ }
+
+ public void setEncapSocketResourceId(int resourceId) {
+ mEncapSocketResourceId = resourceId;
+ }
+
+ public void setEncapRemotePort(int port) {
+ mEncapRemotePort = port;
+ }
+
+ public void setNattKeepaliveInterval(int interval) {
+ mNattKeepaliveInterval = interval;
+ }
// Transport or Tunnel
public int getMode() {
- return mode;
+ return mMode;
}
- public InetAddress getLocalAddress() {
- return localAddress;
+ public String getLocalAddress() {
+ return mLocalAddress;
}
public int getSpiResourceId(int direction) {
- return flow[direction].spiResourceId;
+ return mFlow[direction].mSpiResourceId;
}
- public InetAddress getRemoteAddress() {
- return remoteAddress;
+ public String getRemoteAddress() {
+ return mRemoteAddress;
}
public IpSecAlgorithm getEncryption(int direction) {
- return flow[direction].encryption;
+ return mFlow[direction].mEncryption;
}
public IpSecAlgorithm getAuthentication(int direction) {
- return flow[direction].authentication;
+ return mFlow[direction].mAuthentication;
}
public Network getNetwork() {
- return network;
+ return mNetwork;
}
public int getEncapType() {
- return encapType;
+ return mEncapType;
}
- public int getEncapLocalResourceId() {
- return encapLocalPortResourceId;
+ public int getEncapSocketResourceId() {
+ return mEncapSocketResourceId;
}
public int getEncapRemotePort() {
- return encapRemotePort;
+ return mEncapRemotePort;
}
public int getNattKeepaliveInterval() {
- return nattKeepaliveInterval;
+ return mNattKeepaliveInterval;
}
// Parcelable Methods
@@ -127,82 +192,70 @@
@Override
public void writeToParcel(Parcel out, int flags) {
- // TODO: Use a byte array or other better method for storing IPs that can also include scope
- out.writeString((localAddress != null) ? localAddress.getHostAddress() : null);
- // TODO: Use a byte array or other better method for storing IPs that can also include scope
- out.writeString((remoteAddress != null) ? remoteAddress.getHostAddress() : null);
- out.writeParcelable(network, flags);
- out.writeInt(flow[IpSecTransform.DIRECTION_IN].spiResourceId);
- out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].encryption, flags);
- out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].authentication, flags);
- out.writeInt(flow[IpSecTransform.DIRECTION_OUT].spiResourceId);
- out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].encryption, flags);
- out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].authentication, flags);
- out.writeInt(encapType);
- out.writeInt(encapLocalPortResourceId);
- out.writeInt(encapRemotePort);
+ out.writeInt(mMode);
+ out.writeString(mLocalAddress);
+ out.writeString(mRemoteAddress);
+ out.writeParcelable(mNetwork, flags);
+ out.writeInt(mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId);
+ out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mEncryption, flags);
+ out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthentication, flags);
+ out.writeInt(mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId);
+ out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mEncryption, flags);
+ out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication, flags);
+ out.writeInt(mEncapType);
+ out.writeInt(mEncapSocketResourceId);
+ out.writeInt(mEncapRemotePort);
+ out.writeInt(mNattKeepaliveInterval);
}
- // Package Private: Used by the IpSecTransform.Builder;
- // there should be no public constructor for this object
- IpSecConfig() {}
-
- private static InetAddress readInetAddressFromParcel(Parcel in) {
- String addrString = in.readString();
- if (addrString == null) {
- return null;
- }
- try {
- return InetAddress.getByName(addrString);
- } catch (UnknownHostException e) {
- Log.wtf(TAG, "Invalid IpAddress " + addrString);
- return null;
- }
- }
+ @VisibleForTesting
+ public IpSecConfig() {}
private IpSecConfig(Parcel in) {
- localAddress = readInetAddressFromParcel(in);
- remoteAddress = readInetAddressFromParcel(in);
- network = (Network) in.readParcelable(Network.class.getClassLoader());
- flow[IpSecTransform.DIRECTION_IN].spiResourceId = in.readInt();
- flow[IpSecTransform.DIRECTION_IN].encryption =
+ mMode = in.readInt();
+ mLocalAddress = in.readString();
+ mRemoteAddress = in.readString();
+ mNetwork = (Network) in.readParcelable(Network.class.getClassLoader());
+ mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId = in.readInt();
+ mFlow[IpSecTransform.DIRECTION_IN].mEncryption =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- flow[IpSecTransform.DIRECTION_IN].authentication =
+ mFlow[IpSecTransform.DIRECTION_IN].mAuthentication =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- flow[IpSecTransform.DIRECTION_OUT].spiResourceId = in.readInt();
- flow[IpSecTransform.DIRECTION_OUT].encryption =
+ mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId = in.readInt();
+ mFlow[IpSecTransform.DIRECTION_OUT].mEncryption =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- flow[IpSecTransform.DIRECTION_OUT].authentication =
+ mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- encapType = in.readInt();
- encapLocalPortResourceId = in.readInt();
- encapRemotePort = in.readInt();
+ mEncapType = in.readInt();
+ mEncapSocketResourceId = in.readInt();
+ mEncapRemotePort = in.readInt();
+ mNattKeepaliveInterval = in.readInt();
}
@Override
public String toString() {
StringBuilder strBuilder = new StringBuilder();
strBuilder
- .append("{mode=")
- .append(mode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT")
- .append(", localAddress=")
- .append(localAddress)
- .append(", remoteAddress=")
- .append(remoteAddress)
- .append(", network=")
- .append(network)
- .append(", encapType=")
- .append(encapType)
- .append(", encapLocalPortResourceId=")
- .append(encapLocalPortResourceId)
- .append(", encapRemotePort=")
- .append(encapRemotePort)
- .append(", nattKeepaliveInterval=")
- .append(nattKeepaliveInterval)
- .append(", flow[OUT]=")
- .append(flow[IpSecTransform.DIRECTION_OUT])
- .append(", flow[IN]=")
- .append(flow[IpSecTransform.DIRECTION_IN])
+ .append("{mMode=")
+ .append(mMode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT")
+ .append(", mLocalAddress=")
+ .append(mLocalAddress)
+ .append(", mRemoteAddress=")
+ .append(mRemoteAddress)
+ .append(", mNetwork=")
+ .append(mNetwork)
+ .append(", mEncapType=")
+ .append(mEncapType)
+ .append(", mEncapSocketResourceId=")
+ .append(mEncapSocketResourceId)
+ .append(", mEncapRemotePort=")
+ .append(mEncapRemotePort)
+ .append(", mNattKeepaliveInterval=")
+ .append(mNattKeepaliveInterval)
+ .append(", mFlow[OUT]=")
+ .append(mFlow[IpSecTransform.DIRECTION_OUT])
+ .append(", mFlow[IN]=")
+ .append(mFlow[IpSecTransform.DIRECTION_IN])
.append("}");
return strBuilder.toString();
@@ -218,4 +271,23 @@
return new IpSecConfig[size];
}
};
+
+ @VisibleForTesting
+ /** Equals method used for testing */
+ public static boolean equals(IpSecConfig lhs, IpSecConfig rhs) {
+ if (lhs == null || rhs == null) return (lhs == rhs);
+ return (lhs.mMode == rhs.mMode
+ && lhs.mLocalAddress.equals(rhs.mLocalAddress)
+ && lhs.mRemoteAddress.equals(rhs.mRemoteAddress)
+ && ((lhs.mNetwork != null && lhs.mNetwork.equals(rhs.mNetwork))
+ || (lhs.mNetwork == rhs.mNetwork))
+ && lhs.mEncapType == rhs.mEncapType
+ && lhs.mEncapSocketResourceId == rhs.mEncapSocketResourceId
+ && lhs.mEncapRemotePort == rhs.mEncapRemotePort
+ && lhs.mNattKeepaliveInterval == rhs.mNattKeepaliveInterval
+ && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_OUT],
+ rhs.mFlow[IpSecTransform.DIRECTION_OUT])
+ && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_IN],
+ rhs.mFlow[IpSecTransform.DIRECTION_IN]));
+ }
}
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index d7908c8..d7b3256 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -26,6 +26,8 @@
import android.util.AndroidException;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import dalvik.system.CloseGuard;
import java.io.FileDescriptor;
@@ -188,7 +190,8 @@
}
/** @hide */
- int getResourceId() {
+ @VisibleForTesting
+ public int getResourceId() {
return mResourceId;
}
}
@@ -489,7 +492,8 @@
}
/** @hide */
- int getResourceId() {
+ @VisibleForTesting
+ public int getResourceId() {
return mResourceId;
}
};
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 62fd65b..e15a2c6 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -68,10 +68,10 @@
public @interface TransformDirection {}
/** @hide */
- public static final int MODE_TUNNEL = 0;
+ public static final int MODE_TRANSPORT = 0;
/** @hide */
- public static final int MODE_TRANSPORT = 1;
+ public static final int MODE_TUNNEL = 1;
/** @hide */
public static final int ENCAP_NONE = 0;
@@ -113,7 +113,11 @@
return IIpSecService.Stub.asInterface(b);
}
- private void checkResultStatusAndThrow(int status)
+ /**
+ * Checks the result status and throws an appropriate exception if
+ * the status is not Status.OK.
+ */
+ private void checkResultStatus(int status)
throws IOException, IpSecManager.ResourceUnavailableException,
IpSecManager.SpiUnavailableException {
switch (status) {
@@ -141,7 +145,7 @@
IpSecTransformResponse result =
svc.createTransportModeTransform(mConfig, new Binder());
int status = result.status;
- checkResultStatusAndThrow(status);
+ checkResultStatus(status);
mResourceId = result.resourceId;
/* Keepalive will silently fail if not needed by the config; but, if needed and
@@ -243,61 +247,20 @@
/* Package */
void startKeepalive(Context c) {
- // FIXME: NO_KEEPALIVE needs to be a constant
- if (mConfig.getNattKeepaliveInterval() == 0) {
- return;
- }
-
- ConnectivityManager cm =
- (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
-
- if (mKeepalive != null) {
- Log.wtf(TAG, "Keepalive already started for this IpSecTransform.");
- return;
- }
-
- synchronized (mKeepaliveSyncLock) {
- mKeepalive =
- cm.startNattKeepalive(
- mConfig.getNetwork(),
- mConfig.getNattKeepaliveInterval(),
- mKeepaliveCallback,
- mConfig.getLocalAddress(),
- 0x1234, /* FIXME: get the real port number again,
- which we need to retrieve from the provided
- EncapsulationSocket, and which isn't currently
- stashed in IpSecConfig */
- mConfig.getRemoteAddress());
- try {
- // FIXME: this is still a horrible way to fudge the synchronous callback
- mKeepaliveSyncLock.wait(2000);
- } catch (InterruptedException e) {
- }
- }
- if (mKeepaliveStatus != ConnectivityManager.PacketKeepalive.SUCCESS) {
- throw new UnsupportedOperationException("Packet Keepalive cannot be started");
+ if (mConfig.getNattKeepaliveInterval() != 0) {
+ Log.wtf(TAG, "Keepalive not yet supported.");
}
}
- /* Package */
- int getResourceId() {
+ /** @hide */
+ @VisibleForTesting
+ public int getResourceId() {
return mResourceId;
}
/* Package */
void stopKeepalive() {
- if (mKeepalive == null) {
- return;
- }
- mKeepalive.stop();
- synchronized (mKeepaliveSyncLock) {
- if (mKeepaliveStatus == ConnectivityManager.PacketKeepalive.SUCCESS) {
- try {
- mKeepaliveSyncLock.wait(2000);
- } catch (InterruptedException e) {
- }
- }
- }
+ return;
}
/**
@@ -323,7 +286,7 @@
*/
public IpSecTransform.Builder setEncryption(
@TransformDirection int direction, IpSecAlgorithm algo) {
- mConfig.flow[direction].encryption = algo;
+ mConfig.setEncryption(direction, algo);
return this;
}
@@ -338,7 +301,7 @@
*/
public IpSecTransform.Builder setAuthentication(
@TransformDirection int direction, IpSecAlgorithm algo) {
- mConfig.flow[direction].authentication = algo;
+ mConfig.setAuthentication(direction, algo);
return this;
}
@@ -361,9 +324,7 @@
*/
public IpSecTransform.Builder setSpi(
@TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) {
- // TODO: convert to using the resource Id of the SPI. Then build() can validate
- // the owner in the IpSecService
- mConfig.flow[direction].spiResourceId = spi.getResourceId();
+ mConfig.setSpiResourceId(direction, spi.getResourceId());
return this;
}
@@ -378,7 +339,7 @@
*/
@SystemApi
public IpSecTransform.Builder setUnderlyingNetwork(Network net) {
- mConfig.network = net;
+ mConfig.setNetwork(net);
return this;
}
@@ -395,10 +356,9 @@
*/
public IpSecTransform.Builder setIpv4Encapsulation(
IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
- // TODO: check encap type is valid.
- mConfig.encapType = ENCAP_ESPINUDP;
- mConfig.encapLocalPortResourceId = localSocket.getResourceId();
- mConfig.encapRemotePort = remotePort;
+ mConfig.setEncapType(ENCAP_ESPINUDP);
+ mConfig.setEncapSocketResourceId(localSocket.getResourceId());
+ mConfig.setEncapRemotePort(remotePort);
return this;
}
@@ -416,7 +376,7 @@
*/
@SystemApi
public IpSecTransform.Builder setNattKeepalive(int intervalSeconds) {
- mConfig.nattKeepaliveInterval = intervalSeconds;
+ mConfig.setNattKeepaliveInterval(intervalSeconds);
return this;
}
@@ -449,10 +409,8 @@
public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress)
throws IpSecManager.ResourceUnavailableException,
IpSecManager.SpiUnavailableException, IOException {
- //FIXME: argument validation here
- //throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation");
- mConfig.mode = MODE_TRANSPORT;
- mConfig.remoteAddress = remoteAddress;
+ mConfig.setMode(MODE_TRANSPORT);
+ mConfig.setRemoteAddress(remoteAddress.getHostAddress());
return new IpSecTransform(mContext, mConfig).activate();
}
@@ -473,9 +431,9 @@
InetAddress localAddress, InetAddress remoteAddress) {
//FIXME: argument validation here
//throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation");
- mConfig.localAddress = localAddress;
- mConfig.remoteAddress = remoteAddress;
- mConfig.mode = MODE_TUNNEL;
+ mConfig.setLocalAddress(localAddress.getHostAddress());
+ mConfig.setRemoteAddress(remoteAddress.getHostAddress());
+ mConfig.setMode(MODE_TUNNEL);
return new IpSecTransform(mContext, mConfig);
}
@@ -489,14 +447,5 @@
mContext = context;
mConfig = new IpSecConfig();
}
-
- /**
- * Return an {@link IpSecConfig} object for testing purposes.
- * @hide
- */
- @VisibleForTesting
- public IpSecConfig getIpSecConfig() {
- return mConfig;
- }
}
}
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 951aa8d..e01a1a6 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -391,7 +391,7 @@
// and the length of the tag.
// Note: we implicitly accept possible truncation for Modified-UTF8 differences. It
// is too expensive to compute that ahead of time.
- int bufferSize = NoPreloadHolder.LOGGER_ENTRY_MAX_PAYLOAD // Base.
+ int bufferSize = PreloadHolder.LOGGER_ENTRY_MAX_PAYLOAD // Base.
- 2 // Two terminators.
- (tag != null ? tag.length() : 0) // Tag length.
- 32; // Some slack.
@@ -428,10 +428,10 @@
}
/**
- * NoPreloadHelper class. Caches the LOGGER_ENTRY_MAX_PAYLOAD value to avoid
+ * PreloadHelper class. Caches the LOGGER_ENTRY_MAX_PAYLOAD value to avoid
* a JNI call during logging.
*/
- static class NoPreloadHolder {
+ static class PreloadHolder {
public final static int LOGGER_ENTRY_MAX_PAYLOAD =
logger_entry_max_payload_native();
}
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 18f3177..09e37e1 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -40,6 +40,7 @@
#include "android_view_InputChannel.h"
#include "android_view_KeyEvent.h"
+#include "android-base/stringprintf.h"
#include "nativebridge/native_bridge.h"
#include "nativeloader/native_loader.h"
@@ -265,6 +266,8 @@
// ------------------------------------------------------------------------
+static thread_local std::string g_error_msg;
+
static jlong
loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
jobject messageQueue, jstring internalDataDir, jstring obbDir,
@@ -277,7 +280,6 @@
ScopedUtfChars pathStr(env, path);
std::unique_ptr<NativeCode> code;
bool needs_native_bridge = false;
- std::string error_msg;
void* handle = OpenNativeLibrary(env,
sdkVersion,
@@ -285,12 +287,12 @@
classLoader,
libraryPath,
&needs_native_bridge,
- &error_msg);
+ &g_error_msg);
if (handle == nullptr) {
ALOGW("NativeActivity LoadNativeLibrary(\"%s\") failed: %s",
pathStr.c_str(),
- error_msg.c_str());
+ g_error_msg.c_str());
return 0;
}
@@ -306,19 +308,22 @@
env->ReleaseStringUTFChars(funcName, funcStr);
if (code->createActivityFunc == NULL) {
- ALOGW("ANativeActivity_onCreate not found");
+ g_error_msg = needs_native_bridge ? NativeBridgeGetError() : dlerror();
+ ALOGW("ANativeActivity_onCreate not found: %s", g_error_msg.c_str());
return 0;
}
code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
if (code->messageQueue == NULL) {
- ALOGW("Unable to retrieve native MessageQueue");
+ g_error_msg = "Unable to retrieve native MessageQueue";
+ ALOGW("%s", g_error_msg.c_str());
return 0;
}
int msgpipe[2];
if (pipe(msgpipe)) {
- ALOGW("could not create pipe: %s", strerror(errno));
+ g_error_msg = android::base::StringPrintf("could not create pipe: %s", strerror(errno));
+ ALOGW("%s", g_error_msg.c_str());
return 0;
}
code->mainWorkRead = msgpipe[0];
@@ -334,7 +339,8 @@
code->ANativeActivity::callbacks = &code->callbacks;
if (env->GetJavaVM(&code->vm) < 0) {
- ALOGW("NativeActivity GetJavaVM failed");
+ g_error_msg = "NativeActivity GetJavaVM failed";
+ ALOGW("%s", g_error_msg.c_str());
return 0;
}
code->env = env;
@@ -381,7 +387,9 @@
}
static jstring getDlError_native(JNIEnv* env, jobject clazz) {
- return env->NewStringUTF(dlerror());
+ jstring result = env->NewStringUTF(g_error_msg.c_str());
+ g_error_msg.clear();
+ return result;
}
static void
diff --git a/core/jni/android_os_VintfRuntimeInfo.cpp b/core/jni/android_os_VintfRuntimeInfo.cpp
index 315eac1..9379ea6 100644
--- a/core/jni/android_os_VintfRuntimeInfo.cpp
+++ b/core/jni/android_os_VintfRuntimeInfo.cpp
@@ -29,28 +29,33 @@
using vintf::RuntimeInfo;
using vintf::VintfObject;
-#define MAP_STRING_METHOD(javaMethod, cppString) \
+#define MAP_STRING_METHOD(javaMethod, cppString, flags) \
static jstring android_os_VintfRuntimeInfo_##javaMethod(JNIEnv* env, jclass clazz) \
{ \
- std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo(); \
+ std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo( \
+ false /* skipCache */, flags); \
if (info == nullptr) return nullptr; \
return env->NewStringUTF((cppString).c_str()); \
} \
-MAP_STRING_METHOD(getCpuInfo, info->cpuInfo());
-MAP_STRING_METHOD(getOsName, info->osName());
-MAP_STRING_METHOD(getNodeName, info->nodeName());
-MAP_STRING_METHOD(getOsRelease, info->osRelease());
-MAP_STRING_METHOD(getOsVersion, info->osVersion());
-MAP_STRING_METHOD(getHardwareId, info->hardwareId());
-MAP_STRING_METHOD(getKernelVersion, vintf::to_string(info->kernelVersion()));
-MAP_STRING_METHOD(getBootAvbVersion, vintf::to_string(info->bootAvbVersion()));
-MAP_STRING_METHOD(getBootVbmetaAvbVersion, vintf::to_string(info->bootVbmetaAvbVersion()));
+MAP_STRING_METHOD(getCpuInfo, info->cpuInfo(), RuntimeInfo::FetchFlag::CPU_INFO);
+MAP_STRING_METHOD(getOsName, info->osName(), RuntimeInfo::FetchFlag::CPU_VERSION);
+MAP_STRING_METHOD(getNodeName, info->nodeName(), RuntimeInfo::FetchFlag::CPU_VERSION);
+MAP_STRING_METHOD(getOsRelease, info->osRelease(), RuntimeInfo::FetchFlag::CPU_VERSION);
+MAP_STRING_METHOD(getOsVersion, info->osVersion(), RuntimeInfo::FetchFlag::CPU_VERSION);
+MAP_STRING_METHOD(getHardwareId, info->hardwareId(), RuntimeInfo::FetchFlag::CPU_VERSION);
+MAP_STRING_METHOD(getKernelVersion, vintf::to_string(info->kernelVersion()),
+ RuntimeInfo::FetchFlag::CPU_VERSION);
+MAP_STRING_METHOD(getBootAvbVersion, vintf::to_string(info->bootAvbVersion()),
+ RuntimeInfo::FetchFlag::AVB);
+MAP_STRING_METHOD(getBootVbmetaAvbVersion, vintf::to_string(info->bootVbmetaAvbVersion()),
+ RuntimeInfo::FetchFlag::AVB);
static jlong android_os_VintfRuntimeInfo_getKernelSepolicyVersion(JNIEnv *env, jclass clazz)
{
- std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo();
+ std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo(
+ false /* skipCache */, RuntimeInfo::FetchFlag::POLICYVERS);
if (info == nullptr) return 0;
return static_cast<jlong>(info->kernelSepolicyVersion());
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0668b8b..29f67a8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -203,8 +203,8 @@
android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY" />
<protected-broadcast
android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
- <protected-broadcast android:name="android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.btopp.intent.action.INCOMING_FILE_NOTIFICATION" />
<protected-broadcast android:name="android.btopp.intent.action.USER_CONFIRMATION_TIMEOUT" />
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
index 2784193..c5e112b 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
@@ -33,29 +33,17 @@
$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
-LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
- -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-
-#################################
-include $(BUILD_SYSTEM)/configure_local_jack.mk
-#################################
-
-ifdef LOCAL_JACK_ENABLED
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
-endif
LOCAL_MIN_SDK_VERSION := 8
include $(BUILD_PACKAGE)
-ifndef LOCAL_JACK_ENABLED
$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
$(hide) mkdir -p $(dir $@)
$(MAINDEXCLASSES) $< 1>$@
echo "com/android/multidexlegacytestapp/Test.class" >> $@
$(built_dex_intermediate): $(mainDexList)
-endif
## The application with a full main dex
include $(CLEAR_VARS)
@@ -76,26 +64,14 @@
$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList2)
-LOCAL_JACK_FLAGS := -D jack.dex.output.policy=multidex -D jack.preprocessor=true\
- -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-
-#################################
-include $(BUILD_SYSTEM)/configure_local_jack.mk
-#################################
-
-ifdef LOCAL_JACK_ENABLED
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
-endif
LOCAL_MIN_SDK_VERSION := 8
include $(BUILD_PACKAGE)
-ifndef LOCAL_JACK_ENABLED
$(mainDexList2): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
$(hide) mkdir -p $(dir $@)
$(MAINDEXCLASSES) $< 1>$@
echo "com/android/multidexlegacytestapp/Test.class" >> $@
$(built_dex_intermediate): $(mainDexList2)
-endif
\ No newline at end of file
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/test.jpp
deleted file mode 100644
index a1f5656..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/test.jpp
+++ /dev/null
@@ -1,3 +0,0 @@
-test:
- @@com.android.jack.annotations.ForceInMainDex
- class com.android.multidexlegacytestapp.Test
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
index 1c7d807..da48df9 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
@@ -32,24 +32,12 @@
$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
-LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
- -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-
-#################################
-include $(BUILD_SYSTEM)/configure_local_jack.mk
-#################################
-
-ifdef LOCAL_JACK_ENABLED
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
-endif
include $(BUILD_PACKAGE)
-ifndef LOCAL_JACK_ENABLED
$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
$(hide) mkdir -p $(dir $@)
$(MAINDEXCLASSES) $< 1>$@
echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
$(built_dex_intermediate): $(mainDexList)
-endif
\ No newline at end of file
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/test.jpp
deleted file mode 100644
index 6d384e3..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/test.jpp
+++ /dev/null
@@ -1,3 +0,0 @@
-test:
- @@com.android.jack.annotations.ForceInMainDex
- class com.android.framework.multidexlegacyversionedtestapp.MultiDexUpdateTest
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
index b77cf31..02b3f53 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
@@ -32,24 +32,12 @@
$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
-LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
- -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-
-#################################
-include $(BUILD_SYSTEM)/configure_local_jack.mk
-#################################
-
-ifdef LOCAL_JACK_ENABLED
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
-endif
include $(BUILD_PACKAGE)
-ifndef LOCAL_JACK_ENABLED
$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
$(hide) mkdir -p $(dir $@)
$(MAINDEXCLASSES) $< 1>$@
echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
$(built_dex_intermediate): $(mainDexList)
-endif
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/test.jpp
deleted file mode 100644
index 6d384e3..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/test.jpp
+++ /dev/null
@@ -1,3 +0,0 @@
-test:
- @@com.android.jack.annotations.ForceInMainDex
- class com.android.framework.multidexlegacyversionedtestapp.MultiDexUpdateTest
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
index 3631626..4808684 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
@@ -32,25 +32,13 @@
LOCAL_DEX_PREOPT := false
LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
-LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
- -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-
-#################################
-include $(BUILD_SYSTEM)/configure_local_jack.mk
-#################################
-
-ifdef LOCAL_JACK_ENABLED
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
-endif
include $(BUILD_PACKAGE)
-ifndef LOCAL_JACK_ENABLED
$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
$(hide) mkdir -p $(dir $@)
$(MAINDEXCLASSES) $< 1>$@
echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
$(built_dex_intermediate): $(mainDexList)
-endif
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/test.jpp
deleted file mode 100644
index 6d384e3..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/test.jpp
+++ /dev/null
@@ -1,3 +0,0 @@
-test:
- @@com.android.jack.annotations.ForceInMainDex
- class com.android.framework.multidexlegacyversionedtestapp.MultiDexUpdateTest
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index e764034..c4c14c9e 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -79,7 +79,7 @@
"libutils",
],
shared_libs: [
- "libz-host",
+ "libz",
],
},
windows: {
diff --git a/media/java/android/media/AmrInputStream.java b/media/java/android/media/AmrInputStream.java
index fb91bbb..efaf224 100644
--- a/media/java/android/media/AmrInputStream.java
+++ b/media/java/android/media/AmrInputStream.java
@@ -25,12 +25,12 @@
/**
- * AmrInputStream
+ * DO NOT USE
* @hide
*/
public final class AmrInputStream extends InputStream {
private final static String TAG = "AmrInputStream";
-
+
// frame is 20 msec at 8.000 khz
private final static int SAMPLES_PER_FRAME = 8000 * 20 / 1000;
@@ -51,10 +51,10 @@
private byte[] mOneByte = new byte[1];
/**
- * Create a new AmrInputStream, which converts 16 bit PCM to AMR
- * @param inputStream InputStream containing 16 bit PCM.
+ * DO NOT USE - use MediaCodec instead
*/
public AmrInputStream(InputStream inputStream) {
+ Log.w(TAG, "@@@@ AmrInputStream is not a public API @@@@");
mInputStream = inputStream;
MediaFormat format = new MediaFormat();
@@ -83,17 +83,26 @@
mInfo = new BufferInfo();
}
+ /**
+ * DO NOT USE
+ */
@Override
public int read() throws IOException {
int rtn = read(mOneByte, 0, 1);
return rtn == 1 ? (0xff & mOneByte[0]) : -1;
}
+ /**
+ * DO NOT USE
+ */
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
+ /**
+ * DO NOT USE
+ */
@Override
public int read(byte[] b, int offset, int length) throws IOException {
if (mCodec == null) {
@@ -131,19 +140,15 @@
}
}
- // now read encoded data from the encoder (blocking, since we just filled up the
- // encoder's input with data it should be able to output at least one buffer)
- while (true) {
- int index = mCodec.dequeueOutputBuffer(mInfo, -1);
- if (index >= 0) {
- mBufIn = mInfo.size;
- ByteBuffer out = mCodec.getOutputBuffer(index);
- out.get(mBuf, 0 /* offset */, mBufIn /* length */);
- mCodec.releaseOutputBuffer(index, false /* render */);
- if ((mInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- mSawOutputEOS = true;
- }
- break;
+ // now read encoded data from the encoder
+ int index = mCodec.dequeueOutputBuffer(mInfo, 0);
+ if (index >= 0) {
+ mBufIn = mInfo.size;
+ ByteBuffer out = mCodec.getOutputBuffer(index);
+ out.get(mBuf, 0 /* offset */, mBufIn /* length */);
+ mCodec.releaseOutputBuffer(index, false /* render */);
+ if ((mInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+ mSawOutputEOS = true;
}
}
}
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 56a5737..8437d03 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -838,6 +838,33 @@
return MtpConstants.RESPONSE_OK;
}
+ private int moveObject(int handle, int newParent, String newPath) {
+ String[] whereArgs = new String[] { Integer.toString(handle) };
+
+ // do not allow renaming any of the special subdirectories
+ if (isStorageSubDirectory(newPath)) {
+ return MtpConstants.RESPONSE_OBJECT_WRITE_PROTECTED;
+ }
+
+ // update database
+ ContentValues values = new ContentValues();
+ values.put(Files.FileColumns.DATA, newPath);
+ values.put(Files.FileColumns.PARENT, newParent);
+ int updated = 0;
+ try {
+ // note - we are relying on a special case in MediaProvider.update() to update
+ // the paths for all children in the case where this is a directory.
+ updated = mMediaProvider.update(mObjectsUri, values, ID_WHERE, whereArgs);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in mMediaProvider.update", e);
+ }
+ if (updated == 0) {
+ Log.e(TAG, "Unable to update path for " + handle + " to " + newPath);
+ return MtpConstants.RESPONSE_GENERAL_ERROR;
+ }
+ return MtpConstants.RESPONSE_OK;
+ }
+
private int setObjectProperty(int handle, int property,
long intValue, String stringValue) {
switch (property) {
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index cf4458a..b9d3d8f 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -68,6 +68,7 @@
static jmethodID method_getObjectInfo;
static jmethodID method_getObjectFilePath;
static jmethodID method_deleteFile;
+static jmethodID method_moveObject;
static jmethodID method_getObjectReferences;
static jmethodID method_setObjectReferences;
static jmethodID method_sessionStarted;
@@ -178,6 +179,9 @@
virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property);
+ virtual MtpResponseCode moveObject(MtpObjectHandle handle, MtpObjectHandle newParent,
+ MtpString& newPath);
+
virtual void sessionStarted();
virtual void sessionEnded();
@@ -993,6 +997,18 @@
return result;
}
+MtpResponseCode MyMtpDatabase::moveObject(MtpObjectHandle handle, MtpObjectHandle newParent,
+ MtpString &newPath) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ jstring stringValue = env->NewStringUTF((const char *) newPath);
+ MtpResponseCode result = env->CallIntMethod(mDatabase, method_moveObject,
+ (jint)handle, (jint)newParent, stringValue);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ env->DeleteLocalRef(stringValue);
+ return result;
+}
+
struct PropertyTableEntry {
MtpObjectProperty property;
int type;
@@ -1358,6 +1374,11 @@
ALOGE("Can't find deleteFile");
return -1;
}
+ method_moveObject = env->GetMethodID(clazz, "moveObject", "(IILjava/lang/String;)I");
+ if (method_moveObject == NULL) {
+ ALOGE("Can't find moveObject");
+ return -1;
+ }
method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I");
if (method_getObjectReferences == NULL) {
ALOGE("Can't find getObjectReferences");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 50e4f3d..05e0c9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1440,6 +1440,11 @@
}
};
+ if (hideAnimatedList.isEmpty()) {
+ animationFinishAction.run();
+ return;
+ }
+
// let's disable our normal animations
mStackScroller.setDismissAllInProgress(true);
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 3056831..2e1f142 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -33,6 +33,7 @@
import android.net.IpSecTransform;
import android.net.IpSecTransformResponse;
import android.net.IpSecUdpEncapResponse;
+import android.net.NetworkUtils;
import android.net.util.NetdService;
import android.os.Binder;
import android.os.IBinder;
@@ -42,11 +43,14 @@
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
+
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
@@ -54,6 +58,7 @@
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.concurrent.atomic.AtomicInteger;
+
import libcore.io.IoUtils;
/** @hide */
@@ -252,7 +257,11 @@
return (mReferenceCount.get() > 0);
}
- public void checkOwnerOrSystemAndThrow() {
+ /**
+ * Ensures that the caller is either the owner of this resource or has the system UID and
+ * throws a SecurityException otherwise.
+ */
+ public void checkOwnerOrSystem() {
if (uid != Binder.getCallingUid()
&& android.os.Process.SYSTEM_UID != Binder.getCallingUid()) {
throw new SecurityException("Only the owner may access managed resources!");
@@ -335,12 +344,12 @@
private class ManagedResourceArray<T extends ManagedResource> {
SparseArray<T> mArray = new SparseArray<>();
- T get(int key) {
+ T getAndCheckOwner(int key) {
T val = mArray.get(key);
// The value should never be null unless the resource doesn't exist
// (since we do not allow null resources to be added).
if (val != null) {
- val.checkOwnerOrSystemAndThrow();
+ val.checkOwnerOrSystem();
}
return val;
}
@@ -405,12 +414,8 @@
.ipSecDeleteSecurityAssociation(
mResourceId,
direction,
- (mConfig.getLocalAddress() != null)
- ? mConfig.getLocalAddress().getHostAddress()
- : "",
- (mConfig.getRemoteAddress() != null)
- ? mConfig.getRemoteAddress().getHostAddress()
- : "",
+ mConfig.getLocalAddress(),
+ mConfig.getRemoteAddress(),
spi);
} catch (ServiceSpecificException e) {
// FIXME: get the error code and throw is at an IOException from Errno Exception
@@ -638,11 +643,45 @@
}
}
+ /**
+ * Checks that the provided InetAddress is valid for use in an IPsec SA. The address must not be
+ * a wildcard address and must be in a numeric form such as 1.2.3.4 or 2001::1.
+ */
+ private static void checkInetAddress(String inetAddress) {
+ if (TextUtils.isEmpty(inetAddress)) {
+ throw new IllegalArgumentException("Unspecified address");
+ }
+
+ InetAddress checkAddr = NetworkUtils.numericToInetAddress(inetAddress);
+
+ if (checkAddr.isAnyLocalAddress()) {
+ throw new IllegalArgumentException("Inappropriate wildcard address: " + inetAddress);
+ }
+ }
+
+ /**
+ * Checks the user-provided direction field and throws an IllegalArgumentException if it is not
+ * DIRECTION_IN or DIRECTION_OUT
+ */
+ private static void checkDirection(int direction) {
+ switch (direction) {
+ case IpSecTransform.DIRECTION_OUT:
+ case IpSecTransform.DIRECTION_IN:
+ return;
+ }
+ throw new IllegalArgumentException("Invalid Direction: " + direction);
+ }
+
@Override
/** Get a new SPI and maintain the reservation in the system server */
public synchronized IpSecSpiResponse reserveSecurityParameterIndex(
int direction, String remoteAddress, int requestedSpi, IBinder binder)
throws RemoteException {
+ checkDirection(direction);
+ checkInetAddress(remoteAddress);
+ /* requestedSpi can be anything in the int range, so no check is needed. */
+ checkNotNull(binder, "Null Binder passed to reserveSecurityParameterIndex");
+
int resourceId = mNextResourceId.getAndIncrement();
int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
@@ -651,9 +690,7 @@
try {
if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).spi.isAvailable()) {
return new IpSecSpiResponse(
- IpSecManager.Status.RESOURCE_UNAVAILABLE,
- INVALID_RESOURCE_ID,
- spi);
+ IpSecManager.Status.RESOURCE_UNAVAILABLE, INVALID_RESOURCE_ID, spi);
}
spi =
mSrvConfig
@@ -686,7 +723,7 @@
throws RemoteException {
// We want to non-destructively get so that we can check credentials before removing
// this from the records.
- T record = resArray.get(resourceId);
+ T record = resArray.getAndCheckOwner(resourceId);
if (record == null) {
throw new IllegalArgumentException(
@@ -751,6 +788,8 @@
throw new IllegalArgumentException(
"Specified port number must be a valid non-reserved UDP port");
}
+ checkNotNull(binder, "Null Binder passed to openUdpEncapsulationSocket");
+
int resourceId = mNextResourceId.getAndIncrement();
FileDescriptor sockFd = null;
try {
@@ -792,6 +831,68 @@
}
/**
+ * Checks an IpSecConfig parcel to ensure that the contents are sane and throws an
+ * IllegalArgumentException if they are not.
+ */
+ private void checkIpSecConfig(IpSecConfig config) {
+ if (config.getLocalAddress() == null) {
+ throw new IllegalArgumentException("Invalid null Local InetAddress");
+ }
+
+ if (config.getRemoteAddress() == null) {
+ throw new IllegalArgumentException("Invalid null Remote InetAddress");
+ }
+
+ switch (config.getMode()) {
+ case IpSecTransform.MODE_TRANSPORT:
+ if (!config.getLocalAddress().isEmpty()) {
+ throw new IllegalArgumentException("Non-empty Local Address");
+ }
+ // Must be valid, and not a wildcard
+ checkInetAddress(config.getRemoteAddress());
+ break;
+ case IpSecTransform.MODE_TUNNEL:
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Invalid IpSecTransform.mode: " + config.getMode());
+ }
+
+ switch (config.getEncapType()) {
+ case IpSecTransform.ENCAP_NONE:
+ break;
+ case IpSecTransform.ENCAP_ESPINUDP:
+ case IpSecTransform.ENCAP_ESPINUDP_NON_IKE:
+ if (mUdpSocketRecords.getAndCheckOwner(
+ config.getEncapSocketResourceId()) == null) {
+ throw new IllegalStateException(
+ "No Encapsulation socket for Resource Id: "
+ + config.getEncapSocketResourceId());
+ }
+
+ int port = config.getEncapRemotePort();
+ if (port <= 0 || port > 0xFFFF) {
+ throw new IllegalArgumentException("Invalid remote UDP port: " + port);
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid Encap Type: " + config.getEncapType());
+ }
+
+ for (int direction : DIRECTIONS) {
+ IpSecAlgorithm crypt = config.getEncryption(direction);
+ IpSecAlgorithm auth = config.getAuthentication(direction);
+ if (crypt == null && auth == null) {
+ throw new IllegalArgumentException("Encryption and Authentication are both null");
+ }
+
+ if (mSpiRecords.getAndCheckOwner(config.getSpiResourceId(direction)) == null) {
+ throw new IllegalStateException("No SPI for specified Resource Id");
+ }
+ }
+ }
+
+ /**
* Create a transport mode transform, which represent two security associations (one in each
* direction) in the kernel. The transform will be cached by the system server and must be freed
* when no longer needed. It is possible to free one, deleting the SA from underneath sockets
@@ -801,17 +902,19 @@
@Override
public synchronized IpSecTransformResponse createTransportModeTransform(
IpSecConfig c, IBinder binder) throws RemoteException {
+ checkIpSecConfig(c);
+ checkNotNull(binder, "Null Binder passed to createTransportModeTransform");
int resourceId = mNextResourceId.getAndIncrement();
if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).transform.isAvailable()) {
return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
}
SpiRecord[] spis = new SpiRecord[DIRECTIONS.length];
- // TODO: Basic input validation here since it's coming over the Binder
+
int encapType, encapLocalPort = 0, encapRemotePort = 0;
UdpSocketRecord socketRecord = null;
encapType = c.getEncapType();
if (encapType != IpSecTransform.ENCAP_NONE) {
- socketRecord = mUdpSocketRecords.get(c.getEncapLocalResourceId());
+ socketRecord = mUdpSocketRecords.getAndCheckOwner(c.getEncapSocketResourceId());
encapLocalPort = socketRecord.getPort();
encapRemotePort = c.getEncapRemotePort();
}
@@ -820,23 +923,18 @@
IpSecAlgorithm auth = c.getAuthentication(direction);
IpSecAlgorithm crypt = c.getEncryption(direction);
- spis[direction] = mSpiRecords.get(c.getSpiResourceId(direction));
+ spis[direction] = mSpiRecords.getAndCheckOwner(c.getSpiResourceId(direction));
int spi = spis[direction].getSpi();
try {
- mSrvConfig.getNetdInstance()
+ mSrvConfig
+ .getNetdInstance()
.ipSecAddSecurityAssociation(
resourceId,
c.getMode(),
direction,
- (c.getLocalAddress() != null)
- ? c.getLocalAddress().getHostAddress()
- : "",
- (c.getRemoteAddress() != null)
- ? c.getRemoteAddress().getHostAddress()
- : "",
- (c.getNetwork() != null)
- ? c.getNetwork().getNetworkHandle()
- : 0,
+ c.getLocalAddress(),
+ c.getRemoteAddress(),
+ (c.getNetwork() != null) ? c.getNetwork().getNetworkHandle() : 0,
spi,
(auth != null) ? auth.getName() : "",
(auth != null) ? auth.getKey() : null,
@@ -879,7 +977,7 @@
// Synchronize liberally here because we are using ManagedResources in this block
TransformRecord info;
// FIXME: this code should be factored out into a security check + getter
- info = mTransformRecords.get(resourceId);
+ info = mTransformRecords.getAndCheckOwner(resourceId);
if (info == null) {
throw new IllegalArgumentException("Transform " + resourceId + " is not active");
@@ -899,12 +997,8 @@
socket.getFileDescriptor(),
resourceId,
direction,
- (c.getLocalAddress() != null)
- ? c.getLocalAddress().getHostAddress()
- : "",
- (c.getRemoteAddress() != null)
- ? c.getRemoteAddress().getHostAddress()
- : "",
+ c.getLocalAddress(),
+ c.getRemoteAddress(),
info.getSpiRecord(direction).getSpi());
}
} catch (ServiceSpecificException e) {
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index f0528bc..355e949 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1980,8 +1980,12 @@
final String[] domainStrs = domains == null ? new String[0] : domains.split(" ");
final int[] params = { sampleValidity, successThreshold, minSamples, maxSamples };
+ final boolean useTls = false;
+ final String tlsHostname = "";
+ final String[] tlsFingerprints = new String[0];
try {
- mNetdService.setResolverConfiguration(netId, servers, domainStrs, params);
+ mNetdService.setResolverConfiguration(netId, servers, domainStrs, params,
+ useTls, tlsHostname, tlsFingerprints);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index b8fe884..108cd325 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -500,11 +500,12 @@
if (DEBUG) {
Slog.d(TAG, "Receieved: " + action);
}
+ final String pkgName = getPackageName(intent);
+ final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+
if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
// Purge the app's jobs if the whole package was just disabled. When this is
// the case the component name will be a bare package name.
- final String pkgName = getPackageName(intent);
- final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
if (pkgName != null && pkgUid != -1) {
final String[] changedComponents = intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
@@ -524,7 +525,8 @@
Slog.d(TAG, "Removing jobs for package " + pkgName
+ " in user " + userId);
}
- cancelJobsForUid(pkgUid, "app package state changed");
+ cancelJobsForPackageAndUid(pkgName, pkgUid,
+ "app disabled");
}
} catch (RemoteException|IllegalArgumentException e) {
/*
@@ -553,7 +555,7 @@
if (DEBUG) {
Slog.d(TAG, "Removing jobs for uid: " + uidRemoved);
}
- cancelJobsForUid(uidRemoved, "app uninstalled");
+ cancelJobsForPackageAndUid(pkgName, uidRemoved, "app uninstalled");
}
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
@@ -564,8 +566,6 @@
} else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
// Has this package scheduled any jobs, such that we will take action
// if it were to be force-stopped?
- final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
- final String pkgName = intent.getData().getSchemeSpecificPart();
if (pkgUid != -1) {
List<JobStatus> jobsForUid;
synchronized (mLock) {
@@ -584,13 +584,11 @@
}
} else if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) {
// possible force-stop
- final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
- final String pkgName = intent.getData().getSchemeSpecificPart();
if (pkgUid != -1) {
if (DEBUG) {
Slog.d(TAG, "Removing jobs for pkg " + pkgName + " at uid " + pkgUid);
}
- cancelJobsForPackageAndUid(pkgName, pkgUid);
+ cancelJobsForPackageAndUid(pkgName, pkgUid, "app force stopped");
}
}
}
@@ -759,13 +757,17 @@
}
}
- void cancelJobsForPackageAndUid(String pkgName, int uid) {
+ void cancelJobsForPackageAndUid(String pkgName, int uid, String reason) {
+ if ("android".equals(pkgName)) {
+ Slog.wtfStack(TAG, "Can't cancel all jobs for system package");
+ return;
+ }
synchronized (mLock) {
final List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
for (int i = jobsForUid.size() - 1; i >= 0; i--) {
final JobStatus job = jobsForUid.get(i);
if (job.getSourcePackageName().equals(pkgName)) {
- cancelJobImplLocked(job, null, "app force stopped");
+ cancelJobImplLocked(job, null, reason);
}
}
}
@@ -779,6 +781,10 @@
*
*/
public void cancelJobsForUid(int uid, String reason) {
+ if (uid == Process.SYSTEM_UID) {
+ Slog.wtfStack(TAG, "Can't cancel all jobs for system uid");
+ return;
+ }
synchronized (mLock) {
final List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
for (int i=0; i<jobsForUid.size(); i++) {
diff --git a/services/net/java/android/net/ip/ConnectivityPacketTracker.java b/services/net/java/android/net/ip/ConnectivityPacketTracker.java
index 884a8a7..0230f36 100644
--- a/services/net/java/android/net/ip/ConnectivityPacketTracker.java
+++ b/services/net/java/android/net/ip/ConnectivityPacketTracker.java
@@ -61,11 +61,11 @@
private static final String MARK_STOP = "--- STOP ---";
private final String mTag;
- private final Handler mHandler;
private final LocalLog mLog;
private final BlockingSocketReader mPacketListener;
+ private boolean mRunning;
- public ConnectivityPacketTracker(NetworkInterface netif, LocalLog log) {
+ public ConnectivityPacketTracker(Handler h, NetworkInterface netif, LocalLog log) {
final String ifname;
final int ifindex;
final byte[] hwaddr;
@@ -81,44 +81,40 @@
}
mTag = TAG + "." + ifname;
- mHandler = new Handler();
mLog = log;
- mPacketListener = new PacketListener(ifindex, hwaddr, mtu);
+ mPacketListener = new PacketListener(h, ifindex, hwaddr, mtu);
}
public void start() {
- mLog.log(MARK_START);
+ mRunning = true;
mPacketListener.start();
}
public void stop() {
mPacketListener.stop();
- mLog.log(MARK_STOP);
+ mRunning = false;
}
private final class PacketListener extends BlockingSocketReader {
private final int mIfIndex;
private final byte mHwAddr[];
- PacketListener(int ifindex, byte[] hwaddr, int mtu) {
- super(mtu);
+ PacketListener(Handler h, int ifindex, byte[] hwaddr, int mtu) {
+ super(h, mtu);
mIfIndex = ifindex;
mHwAddr = hwaddr;
}
@Override
- protected FileDescriptor createSocket() {
+ protected FileDescriptor createFd() {
FileDescriptor s = null;
try {
- // TODO: Evaluate switching to SOCK_DGRAM and changing the
- // BlockingSocketReader's read() to recvfrom(), so that this
- // might work on non-ethernet-like links (via SLL).
s = Os.socket(AF_PACKET, SOCK_RAW, 0);
NetworkUtils.attachControlPacketFilter(s, ARPHRD_ETHER);
Os.bind(s, new PacketSocketAddress((short) ETH_P_ALL, mIfIndex));
} catch (ErrnoException | IOException e) {
logError("Failed to create packet tracking socket: ", e);
- closeSocket(s);
+ closeFd(s);
return null;
}
return s;
@@ -136,13 +132,27 @@
}
@Override
+ protected void onStart() {
+ mLog.log(MARK_START);
+ }
+
+ @Override
+ protected void onStop() {
+ if (mRunning) {
+ mLog.log(MARK_STOP);
+ } else {
+ mLog.log(MARK_STOP + " (packet listener stopped unexpectedly)");
+ }
+ }
+
+ @Override
protected void logError(String msg, Exception e) {
Log.e(mTag, msg, e);
addLogEntry(msg + e);
}
private void addLogEntry(String entry) {
- mHandler.post(() -> mLog.log(entry));
+ mLog.log(entry);
}
}
}
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index b1eb085..bc07b81 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -1515,7 +1515,8 @@
private ConnectivityPacketTracker createPacketTracker() {
try {
- return new ConnectivityPacketTracker(mNetworkInterface, mConnectivityPacketLog);
+ return new ConnectivityPacketTracker(
+ getHandler(), mNetworkInterface, mConnectivityPacketLog);
} catch (IllegalArgumentException e) {
return null;
}
diff --git a/services/net/java/android/net/util/BlockingSocketReader.java b/services/net/java/android/net/util/BlockingSocketReader.java
index 12fa1e5..99bf469 100644
--- a/services/net/java/android/net/util/BlockingSocketReader.java
+++ b/services/net/java/android/net/util/BlockingSocketReader.java
@@ -16,81 +16,106 @@
package android.net.util;
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
+
import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.MessageQueue;
+import android.os.MessageQueue.OnFileDescriptorEventListener;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
-import libcore.io.IoBridge;
+import libcore.io.IoUtils;
import java.io.FileDescriptor;
-import java.io.InterruptedIOException;
import java.io.IOException;
/**
- * A thread that reads from a socket and passes the received packets to a
- * subclass's handlePacket() method. The packet receive buffer is recycled
- * on every read call, so subclasses should make any copies they would like
- * inside their handlePacket() implementation.
+ * This class encapsulates the mechanics of registering a file descriptor
+ * with a thread's Looper and handling read events (and errors).
*
- * All public methods may be called from any thread.
+ * Subclasses MUST implement createFd() and SHOULD override handlePacket().
+
+ * Subclasses can expect a call life-cycle like the following:
+ *
+ * [1] start() calls createFd() and (if all goes well) onStart()
+ *
+ * [2] yield, waiting for read event or error notification:
+ *
+ * [a] readPacket() && handlePacket()
+ *
+ * [b] if (no error):
+ * goto 2
+ * else:
+ * goto 3
+ *
+ * [3] stop() calls onStop() if not previously stopped
+ *
+ * The packet receive buffer is recycled on every read call, so subclasses
+ * should make any copies they would like inside their handlePacket()
+ * implementation.
+ *
+ * All public methods MUST only be called from the same thread with which
+ * the Handler constructor argument is associated.
+ *
+ * TODO: rename this class to something more correctly descriptive (something
+ * like [or less horrible than] FdReadEventsHandler?).
*
* @hide
*/
public abstract class BlockingSocketReader {
+ private static final int FD_EVENTS = EVENT_INPUT | EVENT_ERROR;
+ private static final int UNREGISTER_THIS_FD = 0;
+
public static final int DEFAULT_RECV_BUF_SIZE = 2 * 1024;
+ private final Handler mHandler;
+ private final MessageQueue mQueue;
private final byte[] mPacket;
- private final Thread mThread;
- private volatile FileDescriptor mSocket;
- private volatile boolean mRunning;
- private volatile long mPacketsReceived;
+ private FileDescriptor mFd;
+ private long mPacketsReceived;
- // Make it slightly easier for subclasses to properly close a socket
- // without having to know this incantation.
- public static final void closeSocket(@Nullable FileDescriptor fd) {
- try {
- IoBridge.closeAndSignalBlockedThreads(fd);
- } catch (IOException ignored) {}
+ protected static void closeFd(FileDescriptor fd) {
+ IoUtils.closeQuietly(fd);
}
- protected BlockingSocketReader() {
- this(DEFAULT_RECV_BUF_SIZE);
+ protected BlockingSocketReader(Handler h) {
+ this(h, DEFAULT_RECV_BUF_SIZE);
}
- protected BlockingSocketReader(int recvbufsize) {
- if (recvbufsize < DEFAULT_RECV_BUF_SIZE) {
- recvbufsize = DEFAULT_RECV_BUF_SIZE;
+ protected BlockingSocketReader(Handler h, int recvbufsize) {
+ mHandler = h;
+ mQueue = mHandler.getLooper().getQueue();
+ mPacket = new byte[Math.max(recvbufsize, DEFAULT_RECV_BUF_SIZE)];
+ }
+
+ public final void start() {
+ if (onCorrectThread()) {
+ createAndRegisterFd();
+ } else {
+ mHandler.post(() -> {
+ logError("start() called from off-thread", null);
+ createAndRegisterFd();
+ });
}
- mPacket = new byte[recvbufsize];
- mThread = new Thread(() -> { mainLoop(); });
- }
-
- public final boolean start() {
- if (mSocket != null) return false;
-
- try {
- mSocket = createSocket();
- } catch (Exception e) {
- logError("Failed to create socket: ", e);
- return false;
- }
-
- if (mSocket == null) return false;
-
- mRunning = true;
- mThread.start();
- return true;
}
public final void stop() {
- mRunning = false;
- closeSocket(mSocket);
- mSocket = null;
+ if (onCorrectThread()) {
+ unregisterAndDestroyFd();
+ } else {
+ mHandler.post(() -> {
+ logError("stop() called from off-thread", null);
+ unregisterAndDestroyFd();
+ });
+ }
}
- public final boolean isRunning() { return mRunning; }
+ public final int recvBufSize() { return mPacket.length; }
public final long numPacketsReceived() { return mPacketsReceived; }
@@ -98,11 +123,21 @@
* Subclasses MUST create the listening socket here, including setting
* all desired socket options, interface or address/port binding, etc.
*/
- protected abstract FileDescriptor createSocket();
+ protected abstract FileDescriptor createFd();
+
+ /**
+ * Subclasses MAY override this to change the default read() implementation
+ * in favour of, say, recvfrom().
+ *
+ * Implementations MUST return the bytes read or throw an Exception.
+ */
+ protected int readPacket(FileDescriptor fd, byte[] packetBuffer) throws Exception {
+ return Os.read(fd, packetBuffer, 0, packetBuffer.length);
+ }
/**
* Called by the main loop for every packet. Any desired copies of
- * |recvbuf| should be made in here, and the underlying byte array is
+ * |recvbuf| should be made in here, as the underlying byte array is
* reused across all reads.
*/
protected void handlePacket(byte[] recvbuf, int length) {}
@@ -113,43 +148,102 @@
protected void logError(String msg, Exception e) {}
/**
- * Called by the main loop just prior to exiting.
+ * Called by start(), if successful, just prior to returning.
*/
- protected void onExit() {}
+ protected void onStart() {}
- private final void mainLoop() {
+ /**
+ * Called by stop() just prior to returning.
+ */
+ protected void onStop() {}
+
+ private void createAndRegisterFd() {
+ if (mFd != null) return;
+
+ try {
+ mFd = createFd();
+ if (mFd != null) {
+ // Force the socket to be non-blocking.
+ IoUtils.setBlocking(mFd, false);
+ }
+ } catch (Exception e) {
+ logError("Failed to create socket: ", e);
+ closeFd(mFd);
+ mFd = null;
+ return;
+ }
+
+ if (mFd == null) return;
+
+ mQueue.addOnFileDescriptorEventListener(
+ mFd,
+ FD_EVENTS,
+ new OnFileDescriptorEventListener() {
+ @Override
+ public int onFileDescriptorEvents(FileDescriptor fd, int events) {
+ // Always call handleInput() so read/recvfrom are given
+ // a proper chance to encounter a meaningful errno and
+ // perhaps log a useful error message.
+ if (!isRunning() || !handleInput()) {
+ unregisterAndDestroyFd();
+ return UNREGISTER_THIS_FD;
+ }
+ return FD_EVENTS;
+ }
+ });
+ onStart();
+ }
+
+ private boolean isRunning() { return (mFd != null) && mFd.valid(); }
+
+ // Keep trying to read until we get EAGAIN/EWOULDBLOCK or some fatal error.
+ private boolean handleInput() {
while (isRunning()) {
final int bytesRead;
try {
- // Blocking read.
- // TODO: See if this can be converted to recvfrom.
- bytesRead = Os.read(mSocket, mPacket, 0, mPacket.length);
+ bytesRead = readPacket(mFd, mPacket);
if (bytesRead < 1) {
if (isRunning()) logError("Socket closed, exiting", null);
break;
}
mPacketsReceived++;
} catch (ErrnoException e) {
- if (e.errno != OsConstants.EINTR) {
- if (isRunning()) logError("read error: ", e);
+ if (e.errno == OsConstants.EAGAIN) {
+ // We've read everything there is to read this time around.
+ return true;
+ } else if (e.errno == OsConstants.EINTR) {
+ continue;
+ } else {
+ if (isRunning()) logError("readPacket error: ", e);
break;
}
- continue;
- } catch (IOException ioe) {
- if (isRunning()) logError("read error: ", ioe);
- continue;
+ } catch (Exception e) {
+ if (isRunning()) logError("readPacket error: ", e);
+ break;
}
try {
handlePacket(mPacket, bytesRead);
} catch (Exception e) {
- logError("Unexpected exception: ", e);
+ logError("handlePacket error: ", e);
break;
}
}
- stop();
- onExit();
+ return false;
+ }
+
+ private void unregisterAndDestroyFd() {
+ if (mFd == null) return;
+
+ mQueue.removeOnFileDescriptorEventListener(mFd);
+ closeFd(mFd);
+ mFd = null;
+ onStop();
+ }
+
+ private boolean onCorrectThread() {
+ return (mHandler.getLooper() == Looper.myLooper());
}
}
diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java
index ebac041..764b7b2 100644
--- a/telephony/java/android/telephony/MbmsDownloadSession.java
+++ b/telephony/java/android/telephony/MbmsDownloadSession.java
@@ -522,8 +522,7 @@
* @param handler The {@link Handler} on which calls to {@code callback} should be enqueued on.
*/
public void registerStateCallback(@NonNull DownloadRequest request,
- @NonNull DownloadStateCallback callback,
- @NonNull Handler handler) {
+ @NonNull DownloadStateCallback callback, @NonNull Handler handler) {
IMbmsDownloadService downloadService = mService.get();
if (downloadService == null) {
throw new IllegalStateException("Middleware not yet bound");
@@ -533,7 +532,8 @@
new InternalDownloadStateCallback(callback, handler);
try {
- int result = downloadService.registerStateCallback(request, internalCallback);
+ int result = downloadService.registerStateCallback(request, internalCallback,
+ callback.getCallbackFilterFlags());
if (result != MbmsErrors.SUCCESS) {
if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
throw new IllegalArgumentException("Unknown download request.");
diff --git a/telephony/java/android/telephony/mbms/DownloadStateCallback.java b/telephony/java/android/telephony/mbms/DownloadStateCallback.java
index 86920bd..892fbf0 100644
--- a/telephony/java/android/telephony/mbms/DownloadStateCallback.java
+++ b/telephony/java/android/telephony/mbms/DownloadStateCallback.java
@@ -16,8 +16,12 @@
package android.telephony.mbms;
+import android.annotation.IntDef;
import android.telephony.MbmsDownloadSession;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* A optional listener class used by download clients to track progress. Apps should extend this
* class and pass an instance into
@@ -29,6 +33,71 @@
public class DownloadStateCallback {
/**
+ * Bitmask flags used for filtering out callback methods. Used when constructing the
+ * DownloadStateCallback as an optional parameter.
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({ALL_UPDATES, PROGRESS_UPDATES, STATE_UPDATES})
+ public @interface FilterFlag {}
+
+ /**
+ * Receive all callbacks.
+ * Default value.
+ */
+ public static final int ALL_UPDATES = 0x00;
+ /**
+ * Receive callbacks for {@link #onProgressUpdated}.
+ */
+ public static final int PROGRESS_UPDATES = 0x01;
+ /**
+ * Receive callbacks for {@link #onStateUpdated}.
+ */
+ public static final int STATE_UPDATES = 0x02;
+
+ private final int mCallbackFilterFlags;
+
+ /**
+ * Creates a DownloadStateCallback that will receive all callbacks.
+ */
+ public DownloadStateCallback() {
+ mCallbackFilterFlags = ALL_UPDATES;
+ }
+
+ /**
+ * Creates a DownloadStateCallback that will only receive callbacks for the methods specified
+ * via the filterFlags parameter.
+ * @param filterFlags A bitmask of filter flags that will specify which callback this instance
+ * is interested in.
+ */
+ public DownloadStateCallback(int filterFlags) {
+ mCallbackFilterFlags = filterFlags;
+ }
+
+ /**
+ * Return the currently set filter flags.
+ * @return An integer containing the bitmask of flags that this instance is interested in.
+ * @hide
+ */
+ public int getCallbackFilterFlags() {
+ return mCallbackFilterFlags;
+ }
+
+ /**
+ * Returns true if a filter flag is set for a particular callback method. If the flag is set,
+ * the callback will be delivered to the listening process.
+ * @param flag A filter flag specifying whether or not a callback method is registered to
+ * receive callbacks.
+ * @return true if registered to receive callbacks in the listening process, false if not.
+ */
+ public final boolean isFilterFlagSet(@FilterFlag int flag) {
+ if (mCallbackFilterFlags == ALL_UPDATES) {
+ return true;
+ }
+ return (mCallbackFilterFlags & flag) > 0;
+ }
+
+ /**
* Called when the middleware wants to report progress for a file in a {@link DownloadRequest}.
*
* @param request a {@link DownloadRequest}, indicating which download is being referenced.
diff --git a/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java b/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
index 61415b5..fe27537 100644
--- a/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
+++ b/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
@@ -165,6 +165,12 @@
Log.w(LOG_TAG, "Download result did not include a result code. Ignoring.");
return false;
}
+ // We do not need to verify below extras if the result is not success.
+ if (MbmsDownloadSession.RESULT_SUCCESSFUL !=
+ intent.getIntExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT,
+ MbmsDownloadSession.RESULT_CANCELLED)) {
+ return true;
+ }
if (!intent.hasExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST)) {
Log.w(LOG_TAG, "Download result did not include the associated request. Ignoring.");
return false;
diff --git a/telephony/java/android/telephony/mbms/ServiceInfo.java b/telephony/java/android/telephony/mbms/ServiceInfo.java
index 9a01ed0..8529f52 100644
--- a/telephony/java/android/telephony/mbms/ServiceInfo.java
+++ b/telephony/java/android/telephony/mbms/ServiceInfo.java
@@ -23,6 +23,7 @@
import android.text.TextUtils;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@@ -62,12 +63,6 @@
throw new RuntimeException("bad locales length " + newLocales.size());
}
- for (Locale l : newLocales) {
- if (!newNames.containsKey(l)) {
- throw new IllegalArgumentException("A name must be provided for each locale");
- }
- }
-
names = new HashMap(newNames.size());
names.putAll(newNames);
className = newClassName;
@@ -127,7 +122,7 @@
* Get the user-displayable name for this cell-broadcast service corresponding to the
* provided {@link Locale}.
* @param locale The {@link Locale} in which you want the name of the service. This must be a
- * value from the list returned by {@link #getLocales()} -- an
+ * value from the set returned by {@link #getNamedContentLocales()} -- an
* {@link java.util.NoSuchElementException} may be thrown otherwise.
* @return The {@link CharSequence} providing the name of the service in the given
* {@link Locale}
@@ -140,6 +135,17 @@
}
/**
+ * Return an unmodifiable set of the current {@link Locale}s that have a user-displayable name
+ * associated with them. The user-displayable name associated with any {@link Locale} in this
+ * set can be retrieved with {@link #getNameForLocale(Locale)}.
+ * @return An unmodifiable set of {@link Locale} objects corresponding to a user-displayable
+ * content name in that locale.
+ */
+ public @NonNull Set<Locale> getNamedContentLocales() {
+ return Collections.unmodifiableSet(names.keySet());
+ }
+
+ /**
* The class name for this service - used to categorize and filter
*/
public String getServiceClassName() {
diff --git a/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl b/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl
index ed5e826..cb93542 100755
--- a/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl
+++ b/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl
@@ -36,7 +36,8 @@
int download(in DownloadRequest downloadRequest);
- int registerStateCallback(in DownloadRequest downloadRequest, IDownloadStateCallback listener);
+ int registerStateCallback(in DownloadRequest downloadRequest, IDownloadStateCallback listener,
+ int flags);
int unregisterStateCallback(in DownloadRequest downloadRequest,
IDownloadStateCallback listener);
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
index d845a57..2f85a1d 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
@@ -46,6 +46,47 @@
private final Map<IBinder, DownloadStateCallback> mDownloadCallbackBinderMap = new HashMap<>();
private final Map<IBinder, DeathRecipient> mDownloadCallbackDeathRecipients = new HashMap<>();
+
+ // Filters the DownloadStateCallbacks by its configuration from the app.
+ private abstract static class FilteredDownloadStateCallback extends DownloadStateCallback {
+
+ private final IDownloadStateCallback mCallback;
+ public FilteredDownloadStateCallback(IDownloadStateCallback callback, int callbackFlags) {
+ super(callbackFlags);
+ mCallback = callback;
+ }
+
+ @Override
+ public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
+ int currentDownloadSize, int fullDownloadSize, int currentDecodedSize,
+ int fullDecodedSize) {
+ if (!isFilterFlagSet(PROGRESS_UPDATES)) {
+ return;
+ }
+ try {
+ mCallback.onProgressUpdated(request, fileInfo, currentDownloadSize,
+ fullDownloadSize, currentDecodedSize, fullDecodedSize);
+ } catch (RemoteException e) {
+ onRemoteException(e);
+ }
+ }
+
+ @Override
+ public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
+ @MbmsDownloadSession.DownloadStatus int state) {
+ if (!isFilterFlagSet(STATE_UPDATES)) {
+ return;
+ }
+ try {
+ mCallback.onStateUpdated(request, fileInfo, state);
+ } catch (RemoteException e) {
+ onRemoteException(e);
+ }
+ }
+
+ protected abstract void onRemoteException(RemoteException e);
+ }
+
/**
* Initialize the download service for this app and subId, registering the listener.
*
@@ -196,9 +237,8 @@
* @hide
*/
@Override
- public final int registerStateCallback(
- final DownloadRequest downloadRequest, final IDownloadStateCallback callback)
- throws RemoteException {
+ public final int registerStateCallback(final DownloadRequest downloadRequest,
+ final IDownloadStateCallback callback, int flags) throws RemoteException {
final int uid = Binder.getCallingUid();
DeathRecipient deathRecipient = new DeathRecipient() {
@Override
@@ -211,28 +251,10 @@
mDownloadCallbackDeathRecipients.put(callback.asBinder(), deathRecipient);
callback.asBinder().linkToDeath(deathRecipient, 0);
- DownloadStateCallback exposedCallback = new DownloadStateCallback() {
+ DownloadStateCallback exposedCallback = new FilteredDownloadStateCallback(callback, flags) {
@Override
- public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo, int
- currentDownloadSize, int fullDownloadSize, int currentDecodedSize, int
- fullDecodedSize) {
- try {
- callback.onProgressUpdated(request, fileInfo, currentDownloadSize,
- fullDownloadSize,
- currentDecodedSize, fullDecodedSize);
- } catch (RemoteException e) {
- onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
- }
- }
-
- @Override
- public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
- @MbmsDownloadSession.DownloadStatus int state) {
- try {
- callback.onStateUpdated(request, fileInfo, state);
- } catch (RemoteException e) {
- onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
- }
+ protected void onRemoteException(RemoteException e) {
+ onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
}
};
diff --git a/telephony/java/android/telephony/mbms/vendor/VendorUtils.java b/telephony/java/android/telephony/mbms/vendor/VendorUtils.java
index 8fb27b2..a43f122 100644
--- a/telephony/java/android/telephony/mbms/vendor/VendorUtils.java
+++ b/telephony/java/android/telephony/mbms/vendor/VendorUtils.java
@@ -38,8 +38,9 @@
/**
* The MBMS middleware should send this when a download of single file has completed or
- * failed. Mandatory extras are
+ * failed. The only mandatory extra is
* {@link MbmsDownloadSession#EXTRA_MBMS_DOWNLOAD_RESULT}
+ * and the following are required when the download has completed:
* {@link MbmsDownloadSession#EXTRA_MBMS_FILE_INFO}
* {@link MbmsDownloadSession#EXTRA_MBMS_DOWNLOAD_REQUEST}
* {@link #EXTRA_TEMP_LIST}
diff --git a/tests/net/java/android/net/IpSecConfigTest.java b/tests/net/java/android/net/IpSecConfigTest.java
new file mode 100644
index 0000000..1b4bef5
--- /dev/null
+++ b/tests/net/java/android/net/IpSecConfigTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link IpSecConfig}. */
+@SmallTest
+@RunWith(JUnit4.class)
+public class IpSecConfigTest {
+
+ @Test
+ public void testDefaults() throws Exception {
+ IpSecConfig c = new IpSecConfig();
+ assertEquals(IpSecTransform.MODE_TRANSPORT, c.getMode());
+ assertEquals("", c.getLocalAddress());
+ assertEquals("", c.getRemoteAddress());
+ assertNull(c.getNetwork());
+ assertEquals(IpSecTransform.ENCAP_NONE, c.getEncapType());
+ assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getEncapSocketResourceId());
+ assertEquals(0, c.getEncapRemotePort());
+ assertEquals(0, c.getNattKeepaliveInterval());
+ for (int direction :
+ new int[] {IpSecTransform.DIRECTION_OUT, IpSecTransform.DIRECTION_IN}) {
+ assertNull(c.getEncryption(direction));
+ assertNull(c.getAuthentication(direction));
+ assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getSpiResourceId(direction));
+ }
+ }
+
+ @Test
+ public void testParcelUnparcel() throws Exception {
+ assertParcelingIsLossless(new IpSecConfig());
+
+ IpSecConfig c = new IpSecConfig();
+ c.setMode(IpSecTransform.MODE_TUNNEL);
+ c.setLocalAddress("0.0.0.0");
+ c.setRemoteAddress("1.2.3.4");
+ c.setEncapType(android.system.OsConstants.UDP_ENCAP_ESPINUDP);
+ c.setEncapSocketResourceId(7);
+ c.setEncapRemotePort(22);
+ c.setNattKeepaliveInterval(42);
+ c.setEncryption(
+ IpSecTransform.DIRECTION_OUT,
+ new IpSecAlgorithm(
+ IpSecAlgorithm.CRYPT_AES_CBC,
+ new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF}));
+ c.setAuthentication(
+ IpSecTransform.DIRECTION_OUT,
+ new IpSecAlgorithm(
+ IpSecAlgorithm.AUTH_HMAC_SHA1,
+ new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0}));
+ c.setSpiResourceId(IpSecTransform.DIRECTION_OUT, 1984);
+ c.setEncryption(
+ IpSecTransform.DIRECTION_IN,
+ new IpSecAlgorithm(
+ IpSecAlgorithm.CRYPT_AES_CBC,
+ new byte[] {2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF}));
+ c.setAuthentication(
+ IpSecTransform.DIRECTION_IN,
+ new IpSecAlgorithm(
+ IpSecAlgorithm.AUTH_HMAC_SHA1,
+ new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 1}));
+ c.setSpiResourceId(IpSecTransform.DIRECTION_IN, 99);
+ assertParcelingIsLossless(c);
+ }
+
+ private void assertParcelingIsLossless(IpSecConfig ci) throws Exception {
+ Parcel p = Parcel.obtain();
+ ci.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ IpSecConfig co = IpSecConfig.CREATOR.createFromParcel(p);
+ assertTrue(IpSecConfig.equals(co, ci));
+ }
+}
diff --git a/tests/net/java/android/net/util/BlockingSocketReaderTest.java b/tests/net/java/android/net/util/BlockingSocketReaderTest.java
index e03350f..1aad453 100644
--- a/tests/net/java/android/net/util/BlockingSocketReaderTest.java
+++ b/tests/net/java/android/net/util/BlockingSocketReaderTest.java
@@ -16,8 +16,11 @@
package android.net.util;
+import static android.net.util.BlockingSocketReader.DEFAULT_RECV_BUF_SIZE;
import static android.system.OsConstants.*;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructTimeval;
@@ -27,6 +30,7 @@
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet6Address;
@@ -53,61 +57,83 @@
protected FileDescriptor mLocalSocket;
protected InetSocketAddress mLocalSockName;
protected byte[] mLastRecvBuf;
- protected boolean mExited;
+ protected boolean mStopped;
+ protected HandlerThread mHandlerThread;
protected BlockingSocketReader mReceiver;
+ class UdpLoopbackReader extends BlockingSocketReader {
+ public UdpLoopbackReader(Handler h) {
+ super(h);
+ }
+
+ @Override
+ protected FileDescriptor createFd() {
+ FileDescriptor s = null;
+ try {
+ s = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ Os.bind(s, LOOPBACK6, 0);
+ mLocalSockName = (InetSocketAddress) Os.getsockname(s);
+ Os.setsockoptTimeval(s, SOL_SOCKET, SO_SNDTIMEO, TIMEO);
+ } catch (ErrnoException|SocketException e) {
+ closeFd(s);
+ fail();
+ return null;
+ }
+
+ mLocalSocket = s;
+ return s;
+ }
+
+ @Override
+ protected void handlePacket(byte[] recvbuf, int length) {
+ mLastRecvBuf = Arrays.copyOf(recvbuf, length);
+ mLatch.countDown();
+ }
+
+ @Override
+ protected void onStart() {
+ mStopped = false;
+ mLatch.countDown();
+ }
+
+ @Override
+ protected void onStop() {
+ mStopped = true;
+ mLatch.countDown();
+ }
+ };
+
@Override
public void setUp() {
resetLatch();
mLocalSocket = null;
mLocalSockName = null;
mLastRecvBuf = null;
- mExited = false;
+ mStopped = false;
- mReceiver = new BlockingSocketReader() {
- @Override
- protected FileDescriptor createSocket() {
- FileDescriptor s = null;
- try {
- s = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
- Os.bind(s, LOOPBACK6, 0);
- mLocalSockName = (InetSocketAddress) Os.getsockname(s);
- Os.setsockoptTimeval(s, SOL_SOCKET, SO_SNDTIMEO, TIMEO);
- } catch (ErrnoException|SocketException e) {
- closeSocket(s);
- fail();
- return null;
- }
-
- mLocalSocket = s;
- return s;
- }
-
- @Override
- protected void handlePacket(byte[] recvbuf, int length) {
- mLastRecvBuf = Arrays.copyOf(recvbuf, length);
- mLatch.countDown();
- }
-
- @Override
- protected void onExit() {
- mExited = true;
- mLatch.countDown();
- }
- };
+ mHandlerThread = new HandlerThread(BlockingSocketReaderTest.class.getSimpleName());
+ mHandlerThread.start();
}
@Override
- public void tearDown() {
- if (mReceiver != null) mReceiver.stop();
+ public void tearDown() throws Exception {
+ if (mReceiver != null) {
+ mHandlerThread.getThreadHandler().post(() -> { mReceiver.stop(); });
+ waitForActivity();
+ }
mReceiver = null;
+ mHandlerThread.quit();
+ mHandlerThread = null;
}
void resetLatch() { mLatch = new CountDownLatch(1); }
void waitForActivity() throws Exception {
- assertTrue(mLatch.await(500, TimeUnit.MILLISECONDS));
- resetLatch();
+ try {
+ mLatch.await(1000, TimeUnit.MILLISECONDS);
+ } finally {
+ resetLatch();
+ }
}
void sendPacket(byte[] contents) throws Exception {
@@ -118,31 +144,54 @@
}
public void testBasicWorking() throws Exception {
- assertTrue(mReceiver.start());
+ final Handler h = mHandlerThread.getThreadHandler();
+ mReceiver = new UdpLoopbackReader(h);
+
+ h.post(() -> { mReceiver.start(); });
+ waitForActivity();
assertTrue(mLocalSockName != null);
assertEquals(LOOPBACK6, mLocalSockName.getAddress());
assertTrue(0 < mLocalSockName.getPort());
assertTrue(mLocalSocket != null);
- assertFalse(mExited);
+ assertFalse(mStopped);
final byte[] one = "one 1".getBytes("UTF-8");
sendPacket(one);
waitForActivity();
assertEquals(1, mReceiver.numPacketsReceived());
assertTrue(Arrays.equals(one, mLastRecvBuf));
- assertFalse(mExited);
+ assertFalse(mStopped);
final byte[] two = "two 2".getBytes("UTF-8");
sendPacket(two);
waitForActivity();
assertEquals(2, mReceiver.numPacketsReceived());
assertTrue(Arrays.equals(two, mLastRecvBuf));
- assertFalse(mExited);
+ assertFalse(mStopped);
mReceiver.stop();
waitForActivity();
assertEquals(2, mReceiver.numPacketsReceived());
assertTrue(Arrays.equals(two, mLastRecvBuf));
- assertTrue(mExited);
+ assertTrue(mStopped);
+ mReceiver = null;
+ }
+
+ class NullBlockingSocketReader extends BlockingSocketReader {
+ public NullBlockingSocketReader(Handler h, int recvbufsize) {
+ super(h, recvbufsize);
+ }
+
+ @Override
+ public FileDescriptor createFd() { return null; }
+ }
+
+ public void testMinimalRecvBufSize() throws Exception {
+ final Handler h = mHandlerThread.getThreadHandler();
+
+ for (int i : new int[]{-1, 0, 1, DEFAULT_RECV_BUF_SIZE-1}) {
+ final BlockingSocketReader b = new NullBlockingSocketReader(h, i);
+ assertEquals(DEFAULT_RECV_BUF_SIZE, b.recvBufSize());
+ }
}
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 9c498c7..335e6240 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -121,7 +121,6 @@
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.BooleanSupplier;
import java.util.function.Predicate;
/**
@@ -3212,68 +3211,68 @@
}
@SmallTest
- public void testNetworkRequestMaximum() {
+ public void testNetworkCallbackMaximum() {
final int MAX_REQUESTS = 100;
- // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
+ final int CALLBACKS = 90;
+ final int INTENTS = 10;
+ assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
+
NetworkRequest networkRequest = new NetworkRequest.Builder().build();
- ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>();
- try {
- for (int i = 0; i < MAX_REQUESTS; i++) {
- NetworkCallback networkCallback = new NetworkCallback();
- mCm.requestNetwork(networkRequest, networkCallback);
- networkCallbacks.add(networkCallback);
- }
- fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
- } catch (TooManyRequestsException expected) {}
- for (NetworkCallback networkCallback : networkCallbacks) {
- mCm.unregisterNetworkCallback(networkCallback);
- }
- networkCallbacks.clear();
+ ArrayList<Object> registered = new ArrayList<>();
- try {
- for (int i = 0; i < MAX_REQUESTS; i++) {
- NetworkCallback networkCallback = new NetworkCallback();
- mCm.registerNetworkCallback(networkRequest, networkCallback);
- networkCallbacks.add(networkCallback);
- }
- fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
- } catch (TooManyRequestsException expected) {}
- for (NetworkCallback networkCallback : networkCallbacks) {
- mCm.unregisterNetworkCallback(networkCallback);
+ int j = 0;
+ while (j++ < CALLBACKS / 2) {
+ NetworkCallback cb = new NetworkCallback();
+ mCm.requestNetwork(networkRequest, cb);
+ registered.add(cb);
}
- networkCallbacks.clear();
+ while (j++ < CALLBACKS) {
+ NetworkCallback cb = new NetworkCallback();
+ mCm.registerNetworkCallback(networkRequest, cb);
+ registered.add(cb);
+ }
+ j = 0;
+ while (j++ < INTENTS / 2) {
+ PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
+ mCm.requestNetwork(networkRequest, pi);
+ registered.add(pi);
+ }
+ while (j++ < INTENTS) {
+ PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
+ mCm.registerNetworkCallback(networkRequest, pi);
+ registered.add(pi);
+ }
- ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
+ // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
try {
- for (int i = 0; i < MAX_REQUESTS + 1; i++) {
- PendingIntent pendingIntent =
- PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
- mCm.requestNetwork(networkRequest, pendingIntent);
- pendingIntents.add(pendingIntent);
- }
- fail("Registering " + MAX_REQUESTS +
- " PendingIntent NetworkRequests did not throw exception");
+ mCm.requestNetwork(networkRequest, new NetworkCallback());
+ fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
} catch (TooManyRequestsException expected) {}
- for (PendingIntent pendingIntent : pendingIntents) {
- mCm.unregisterNetworkCallback(pendingIntent);
- }
- pendingIntents.clear();
+ try {
+ mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
+ fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
+ } catch (TooManyRequestsException expected) {}
+ try {
+ mCm.requestNetwork(networkRequest,
+ PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
+ fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
+ } catch (TooManyRequestsException expected) {}
+ try {
+ mCm.registerNetworkCallback(networkRequest,
+ PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
+ fail("Registering " + MAX_REQUESTS
+ + " PendingIntent callbacks did not throw exception");
+ } catch (TooManyRequestsException expected) {}
- try {
- for (int i = 0; i < MAX_REQUESTS + 1; i++) {
- PendingIntent pendingIntent =
- PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
- mCm.registerNetworkCallback(networkRequest, pendingIntent);
- pendingIntents.add(pendingIntent);
+ for (Object o : registered) {
+ if (o instanceof NetworkCallback) {
+ mCm.unregisterNetworkCallback((NetworkCallback)o);
}
- fail("Registering " + MAX_REQUESTS +
- " PendingIntent NetworkCallbacks did not throw exception");
- } catch (TooManyRequestsException expected) {}
- for (PendingIntent pendingIntent : pendingIntents) {
- mCm.unregisterNetworkCallback(pendingIntent);
+ if (o instanceof PendingIntent) {
+ mCm.unregisterNetworkCallback((PendingIntent)o);
+ }
}
- pendingIntents.clear();
- waitForIdle(5000);
+ waitForIdle();
// Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
for (int i = 0; i < MAX_REQUESTS; i++) {
@@ -3281,23 +3280,23 @@
mCm.requestNetwork(networkRequest, networkCallback);
mCm.unregisterNetworkCallback(networkCallback);
}
- waitForIdle();
+
for (int i = 0; i < MAX_REQUESTS; i++) {
NetworkCallback networkCallback = new NetworkCallback();
mCm.registerNetworkCallback(networkRequest, networkCallback);
mCm.unregisterNetworkCallback(networkCallback);
}
- waitForIdle();
+
for (int i = 0; i < MAX_REQUESTS; i++) {
PendingIntent pendingIntent =
- PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
+ PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
mCm.requestNetwork(networkRequest, pendingIntent);
mCm.unregisterNetworkCallback(pendingIntent);
}
- waitForIdle();
+
for (int i = 0; i < MAX_REQUESTS; i++) {
PendingIntent pendingIntent =
- PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
+ PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
mCm.registerNetworkCallback(networkRequest, pendingIntent);
mCm.unregisterNetworkCallback(pendingIntent);
}
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
new file mode 100644
index 0000000..9057a10
--- /dev/null
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2017 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.server;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.INetd;
+import android.net.IpSecAlgorithm;
+import android.net.IpSecConfig;
+import android.net.IpSecManager;
+import android.net.IpSecSpiResponse;
+import android.net.IpSecTransform;
+import android.net.IpSecTransformResponse;
+import android.net.NetworkUtils;
+import android.os.Binder;
+import android.os.ParcelFileDescriptor;
+import android.support.test.filters.SmallTest;
+import android.system.OsConstants;
+
+import java.net.Socket;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/** Unit tests for {@link IpSecService}. */
+@SmallTest
+@RunWith(Parameterized.class)
+public class IpSecServiceParameterizedTest {
+
+ private static final int DROID_SPI = 0xD1201D;
+ private static final int DROID_SPI2 = DROID_SPI + 1;
+
+ private final String mRemoteAddr;
+
+ @Parameterized.Parameters
+ public static Collection ipSecConfigs() {
+ return Arrays.asList(new Object[][] {{"8.8.4.4"}, {"2601::10"}});
+ }
+
+ private static final byte[] CRYPT_KEY = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
+ };
+ private static final byte[] AUTH_KEY = {
+ 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
+ };
+
+ Context mMockContext;
+ INetd mMockNetd;
+ IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
+ IpSecService mIpSecService;
+
+ public IpSecServiceParameterizedTest(String remoteAddr) {
+ mRemoteAddr = remoteAddr;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mMockContext = mock(Context.class);
+ mMockNetd = mock(INetd.class);
+ mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class);
+ mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig);
+
+ // Injecting mock netd
+ when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd);
+ }
+
+ @Test
+ public void testIpSecServiceReserveSpi() throws Exception {
+ when(mMockNetd.ipSecAllocateSpi(
+ anyInt(),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ eq(mRemoteAddr),
+ eq(DROID_SPI)))
+ .thenReturn(DROID_SPI);
+
+ IpSecSpiResponse spiResp =
+ mIpSecService.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_OUT, mRemoteAddr, DROID_SPI, new Binder());
+ assertEquals(IpSecManager.Status.OK, spiResp.status);
+ assertEquals(DROID_SPI, spiResp.spi);
+ }
+
+ @Test
+ public void testReleaseSecurityParameterIndex() throws Exception {
+ when(mMockNetd.ipSecAllocateSpi(
+ anyInt(),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ eq(mRemoteAddr),
+ eq(DROID_SPI)))
+ .thenReturn(DROID_SPI);
+
+ IpSecSpiResponse spiResp =
+ mIpSecService.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_OUT, mRemoteAddr, DROID_SPI, new Binder());
+
+ mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId);
+
+ verify(mMockNetd)
+ .ipSecDeleteSecurityAssociation(
+ eq(spiResp.resourceId), anyInt(), anyString(), anyString(), eq(DROID_SPI));
+ }
+
+ IpSecConfig buildIpSecConfig() throws Exception {
+ IpSecManager ipSecManager = new IpSecManager(mIpSecService);
+
+ // Mocking the netd to allocate SPI
+ when(mMockNetd.ipSecAllocateSpi(anyInt(), anyInt(), anyString(), anyString(), anyInt()))
+ .thenReturn(DROID_SPI)
+ .thenReturn(DROID_SPI2);
+
+ IpSecAlgorithm encryptAlgo = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
+ IpSecAlgorithm authAlgo =
+ new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 8);
+
+ /** Allocate and add SPI records in the IpSecService through IpSecManager interface. */
+ IpSecManager.SecurityParameterIndex outSpi =
+ ipSecManager.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_OUT,
+ NetworkUtils.numericToInetAddress(mRemoteAddr));
+ IpSecManager.SecurityParameterIndex inSpi =
+ ipSecManager.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_IN,
+ NetworkUtils.numericToInetAddress(mRemoteAddr));
+
+ IpSecConfig config = new IpSecConfig();
+ config.setSpiResourceId(IpSecTransform.DIRECTION_IN, inSpi.getResourceId());
+ config.setSpiResourceId(IpSecTransform.DIRECTION_OUT, outSpi.getResourceId());
+ config.setEncryption(IpSecTransform.DIRECTION_OUT, encryptAlgo);
+ config.setAuthentication(IpSecTransform.DIRECTION_OUT, authAlgo);
+ config.setEncryption(IpSecTransform.DIRECTION_IN, encryptAlgo);
+ config.setAuthentication(IpSecTransform.DIRECTION_IN, authAlgo);
+ config.setRemoteAddress(mRemoteAddr);
+ return config;
+ }
+
+ @Test
+ public void testCreateTransportModeTransform() throws Exception {
+ IpSecConfig ipSecConfig = buildIpSecConfig();
+
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
+ assertEquals(IpSecManager.Status.OK, createTransformResp.status);
+
+ verify(mMockNetd)
+ .ipSecAddSecurityAssociation(
+ eq(createTransformResp.resourceId),
+ anyInt(),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ anyString(),
+ anyLong(),
+ eq(DROID_SPI),
+ eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
+ eq(AUTH_KEY),
+ anyInt(),
+ eq(IpSecAlgorithm.CRYPT_AES_CBC),
+ eq(CRYPT_KEY),
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ anyInt());
+ verify(mMockNetd)
+ .ipSecAddSecurityAssociation(
+ eq(createTransformResp.resourceId),
+ anyInt(),
+ eq(IpSecTransform.DIRECTION_IN),
+ anyString(),
+ anyString(),
+ anyLong(),
+ eq(DROID_SPI2),
+ eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
+ eq(AUTH_KEY),
+ anyInt(),
+ eq(IpSecAlgorithm.CRYPT_AES_CBC),
+ eq(CRYPT_KEY),
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ anyInt());
+ }
+
+ @Test
+ public void testDeleteTransportModeTransform() throws Exception {
+ IpSecConfig ipSecConfig = buildIpSecConfig();
+
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
+ mIpSecService.deleteTransportModeTransform(createTransformResp.resourceId);
+
+ verify(mMockNetd)
+ .ipSecDeleteSecurityAssociation(
+ eq(createTransformResp.resourceId),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ anyString(),
+ eq(DROID_SPI));
+ verify(mMockNetd)
+ .ipSecDeleteSecurityAssociation(
+ eq(createTransformResp.resourceId),
+ eq(IpSecTransform.DIRECTION_IN),
+ anyString(),
+ anyString(),
+ eq(DROID_SPI2));
+ }
+
+ @Test
+ public void testApplyTransportModeTransform() throws Exception {
+ IpSecConfig ipSecConfig = buildIpSecConfig();
+
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
+ ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
+
+ int resourceId = createTransformResp.resourceId;
+ mIpSecService.applyTransportModeTransform(pfd, resourceId);
+
+ verify(mMockNetd)
+ .ipSecApplyTransportModeTransform(
+ eq(pfd.getFileDescriptor()),
+ eq(resourceId),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ anyString(),
+ eq(DROID_SPI));
+ verify(mMockNetd)
+ .ipSecApplyTransportModeTransform(
+ eq(pfd.getFileDescriptor()),
+ eq(resourceId),
+ eq(IpSecTransform.DIRECTION_IN),
+ anyString(),
+ anyString(),
+ eq(DROID_SPI2));
+ }
+
+ @Test
+ public void testRemoveTransportModeTransform() throws Exception {
+ ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
+ mIpSecService.removeTransportModeTransform(pfd, 1);
+
+ verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
+ }
+}
diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java
index 23fee28..efc58cc 100644
--- a/tests/net/java/com/android/server/IpSecServiceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceTest.java
@@ -23,34 +23,28 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.INetd;
-import android.net.IpSecAlgorithm;
-import android.net.IpSecConfig;
import android.net.IpSecManager;
import android.net.IpSecSpiResponse;
import android.net.IpSecTransform;
-import android.net.IpSecTransformResponse;
import android.net.IpSecUdpEncapResponse;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
import android.support.test.filters.SmallTest;
import android.system.ErrnoException;
import android.system.Os;
+
import java.io.FileDescriptor;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -62,13 +56,8 @@
public class IpSecServiceTest {
private static final int DROID_SPI = 0xD1201D;
- private static final int DROID_SPI2 = DROID_SPI + 1;
private static final int TEST_UDP_ENCAP_INVALID_PORT = 100;
private static final int TEST_UDP_ENCAP_PORT_OUT_RANGE = 100000;
- private static final int TEST_UDP_ENCAP_PORT = 34567;
-
- private static final String IPV4_LOOPBACK = "127.0.0.1";
- private static final String IPV4_ADDR = "192.168.0.2";
private static final InetAddress INADDR_ANY;
@@ -80,21 +69,6 @@
}
}
- private static final int[] DIRECTIONS =
- new int[] {IpSecTransform.DIRECTION_OUT, IpSecTransform.DIRECTION_IN};
- private static final byte[] CRYPT_KEY = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
- };
- private static final byte[] AUTH_KEY = {
- 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
- 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
- };
-
Context mMockContext;
INetd mMockNetd;
IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
@@ -118,44 +92,6 @@
}
@Test
- public void testIpSecServiceReserveSpi() throws Exception {
- when(mMockNetd.ipSecAllocateSpi(
- anyInt(),
- eq(IpSecTransform.DIRECTION_OUT),
- anyString(),
- eq(IPV4_LOOPBACK),
- eq(DROID_SPI)))
- .thenReturn(DROID_SPI);
-
- IpSecSpiResponse spiResp =
- mIpSecService.reserveSecurityParameterIndex(
- IpSecTransform.DIRECTION_OUT, IPV4_LOOPBACK, DROID_SPI, new Binder());
- assertEquals(IpSecManager.Status.OK, spiResp.status);
- assertEquals(DROID_SPI, spiResp.spi);
- }
-
- @Test
- public void testReleaseSecurityParameterIndex() throws Exception {
- when(mMockNetd.ipSecAllocateSpi(
- anyInt(),
- eq(IpSecTransform.DIRECTION_OUT),
- anyString(),
- eq(IPV4_LOOPBACK),
- eq(DROID_SPI)))
- .thenReturn(DROID_SPI);
-
- IpSecSpiResponse spiResp =
- mIpSecService.reserveSecurityParameterIndex(
- IpSecTransform.DIRECTION_OUT, IPV4_LOOPBACK, DROID_SPI, new Binder());
-
- mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId);
-
- verify(mMockNetd)
- .ipSecDeleteSecurityAssociation(
- eq(spiResp.resourceId), anyInt(), anyString(), anyString(), eq(DROID_SPI));
- }
-
- @Test
public void testReleaseInvalidSecurityParameterIndex() throws Exception {
try {
mIpSecService.releaseSecurityParameterIndex(1);
@@ -285,108 +221,6 @@
}
}
- IpSecConfig buildIpSecConfig() throws Exception {
- IpSecManager ipSecManager = new IpSecManager(mIpSecService);
-
- // Mocking the netd to allocate SPI
- when(mMockNetd.ipSecAllocateSpi(anyInt(), anyInt(), anyString(), anyString(), anyInt()))
- .thenReturn(DROID_SPI)
- .thenReturn(DROID_SPI2);
-
- IpSecAlgorithm encryptAlgo = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
- IpSecAlgorithm authAlgo =
- new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 8);
-
- InetAddress localAddr = InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
-
- /** Allocate and add SPI records in the IpSecService through IpSecManager interface. */
- IpSecManager.SecurityParameterIndex outSpi =
- ipSecManager.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, localAddr);
- IpSecManager.SecurityParameterIndex inSpi =
- ipSecManager.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_IN, localAddr);
-
- IpSecConfig ipSecConfig =
- new IpSecTransform.Builder(mMockContext)
- .setSpi(IpSecTransform.DIRECTION_OUT, outSpi)
- .setSpi(IpSecTransform.DIRECTION_IN, inSpi)
- .setEncryption(IpSecTransform.DIRECTION_OUT, encryptAlgo)
- .setAuthentication(IpSecTransform.DIRECTION_OUT, authAlgo)
- .setEncryption(IpSecTransform.DIRECTION_IN, encryptAlgo)
- .setAuthentication(IpSecTransform.DIRECTION_IN, authAlgo)
- .getIpSecConfig();
- return ipSecConfig;
- }
-
- @Test
- public void testCreateTransportModeTransform() throws Exception {
- IpSecConfig ipSecConfig = buildIpSecConfig();
-
- IpSecTransformResponse createTransformResp =
- mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
- assertEquals(IpSecManager.Status.OK, createTransformResp.status);
-
- verify(mMockNetd)
- .ipSecAddSecurityAssociation(
- eq(createTransformResp.resourceId),
- anyInt(),
- eq(IpSecTransform.DIRECTION_OUT),
- anyString(),
- anyString(),
- anyLong(),
- eq(DROID_SPI),
- eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
- eq(AUTH_KEY),
- anyInt(),
- eq(IpSecAlgorithm.CRYPT_AES_CBC),
- eq(CRYPT_KEY),
- anyInt(),
- anyInt(),
- anyInt(),
- anyInt());
- verify(mMockNetd)
- .ipSecAddSecurityAssociation(
- eq(createTransformResp.resourceId),
- anyInt(),
- eq(IpSecTransform.DIRECTION_IN),
- anyString(),
- anyString(),
- anyLong(),
- eq(DROID_SPI2),
- eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
- eq(AUTH_KEY),
- anyInt(),
- eq(IpSecAlgorithm.CRYPT_AES_CBC),
- eq(CRYPT_KEY),
- anyInt(),
- anyInt(),
- anyInt(),
- anyInt());
- }
-
- @Test
- public void testDeleteTransportModeTransform() throws Exception {
- IpSecConfig ipSecConfig = buildIpSecConfig();
-
- IpSecTransformResponse createTransformResp =
- mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
- mIpSecService.deleteTransportModeTransform(createTransformResp.resourceId);
-
- verify(mMockNetd)
- .ipSecDeleteSecurityAssociation(
- eq(createTransformResp.resourceId),
- eq(IpSecTransform.DIRECTION_OUT),
- anyString(),
- anyString(),
- eq(DROID_SPI));
- verify(mMockNetd)
- .ipSecDeleteSecurityAssociation(
- eq(createTransformResp.resourceId),
- eq(IpSecTransform.DIRECTION_IN),
- anyString(),
- anyString(),
- eq(DROID_SPI2));
- }
-
@Test
public void testDeleteInvalidTransportModeTransform() throws Exception {
try {
@@ -397,39 +231,31 @@
}
@Test
- public void testApplyTransportModeTransform() throws Exception {
- IpSecConfig ipSecConfig = buildIpSecConfig();
-
- IpSecTransformResponse createTransformResp =
- mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
- ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
-
- int resourceId = createTransformResp.resourceId;
- mIpSecService.applyTransportModeTransform(pfd, resourceId);
-
- verify(mMockNetd)
- .ipSecApplyTransportModeTransform(
- eq(pfd.getFileDescriptor()),
- eq(resourceId),
- eq(IpSecTransform.DIRECTION_OUT),
- anyString(),
- anyString(),
- eq(DROID_SPI));
- verify(mMockNetd)
- .ipSecApplyTransportModeTransform(
- eq(pfd.getFileDescriptor()),
- eq(resourceId),
- eq(IpSecTransform.DIRECTION_IN),
- anyString(),
- anyString(),
- eq(DROID_SPI2));
- }
-
- @Test
public void testRemoveTransportModeTransform() throws Exception {
ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
mIpSecService.removeTransportModeTransform(pfd, 1);
verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
}
+
+ @Test
+ public void testValidateIpAddresses() throws Exception {
+ String[] invalidAddresses =
+ new String[] {"www.google.com", "::", "2001::/64", "0.0.0.0", ""};
+ for (String address : invalidAddresses) {
+ try {
+ IpSecSpiResponse spiResp =
+ mIpSecService.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_OUT, address, DROID_SPI, new Binder());
+ fail("Invalid address was passed through IpSecService validation: " + address);
+ } catch (IllegalArgumentException e) {
+ } catch (Exception e) {
+ fail(
+ "Invalid InetAddress was not caught in validation: "
+ + address
+ + ", Exception: "
+ + e);
+ }
+ }
+ }
}
diff --git a/tests/net/java/com/android/server/NsdServiceTest.java b/tests/net/java/com/android/server/NsdServiceTest.java
index 2e49c98..b88c784 100644
--- a/tests/net/java/com/android/server/NsdServiceTest.java
+++ b/tests/net/java/com/android/server/NsdServiceTest.java
@@ -77,7 +77,10 @@
@After
public void tearDown() throws Exception {
- mThread.quit();
+ if (mThread != null) {
+ mThread.quit();
+ mThread = null;
+ }
}
@Test
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index 5f586a1..627a231 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -1246,7 +1246,7 @@
if (kIsDebug) {
printf("Adding 9-patch info...\n");
}
- strcpy((char*)unknowns[p_index].name, "npTc");
+ memcpy((char*)unknowns[p_index].name, "npTc", 5);
unknowns[p_index].data = (png_byte*)imageInfo.serialize9patch();
unknowns[p_index].size = imageInfo.info9Patch.serializedSize();
// TODO: remove the check below when everything works
@@ -1254,7 +1254,7 @@
// automatically generated 9 patch outline data
int chunk_size = sizeof(png_uint_32) * 6;
- strcpy((char*)unknowns[o_index].name, "npOl");
+ memcpy((char*)unknowns[o_index].name, "npOl", 5);
unknowns[o_index].data = (png_byte*) calloc(chunk_size, 1);
png_byte outputData[chunk_size];
memcpy(&outputData, &imageInfo.outlineInsetsLeft, 4 * sizeof(png_uint_32));
@@ -1266,7 +1266,7 @@
// optional optical inset / layout bounds data
if (imageInfo.haveLayoutBounds) {
int chunk_size = sizeof(png_uint_32) * 4;
- strcpy((char*)unknowns[b_index].name, "npLb");
+ memcpy((char*)unknowns[b_index].name, "npLb", 5);
unknowns[b_index].data = (png_byte*) calloc(chunk_size, 1);
memcpy(unknowns[b_index].data, &imageInfo.layoutBoundsLeft, chunk_size);
unknowns[b_index].size = chunk_size;
diff --git a/tools/aapt2/compile/Png.cpp b/tools/aapt2/compile/Png.cpp
index 6d6147d..33122dc 100644
--- a/tools/aapt2/compile/Png.cpp
+++ b/tools/aapt2/compile/Png.cpp
@@ -538,7 +538,7 @@
if (kDebug) {
diag->Note(DiagMessage() << "adding 9-patch info..");
}
- strcpy((char*)unknowns[pIndex].name, "npTc");
+ memcpy((char*)unknowns[pIndex].name, "npTc", 5);
unknowns[pIndex].data = (png_byte*)info->serialize9Patch();
unknowns[pIndex].size = info->info9Patch.serializedSize();
// TODO: remove the check below when everything works
@@ -546,7 +546,7 @@
// automatically generated 9 patch outline data
int chunkSize = sizeof(png_uint_32) * 6;
- strcpy((char*)unknowns[oIndex].name, "npOl");
+ memcpy((char*)unknowns[oIndex].name, "npOl", 5);
unknowns[oIndex].data = (png_byte*)calloc(chunkSize, 1);
png_byte outputData[chunkSize];
memcpy(&outputData, &info->outlineInsetsLeft, 4 * sizeof(png_uint_32));
@@ -558,7 +558,7 @@
// optional optical inset / layout bounds data
if (info->haveLayoutBounds) {
int chunkSize = sizeof(png_uint_32) * 4;
- strcpy((char*)unknowns[bIndex].name, "npLb");
+ memcpy((char*)unknowns[bIndex].name, "npLb", 5);
unknowns[bIndex].data = (png_byte*)calloc(chunkSize, 1);
memcpy(unknowns[bIndex].data, &info->layoutBoundsLeft, chunkSize);
unknowns[bIndex].size = chunkSize;
diff --git a/tools/incident_report/Android.bp b/tools/incident_report/Android.bp
index 6f21605..ab55dbd 100644
--- a/tools/incident_report/Android.bp
+++ b/tools/incident_report/Android.bp
@@ -32,7 +32,4 @@
],
cflags: ["-Wno-unused-parameter"],
-
- // b/34740546, work around clang-tidy segmentation fault.
- tidy_checks: ["-modernize*"],
}
diff --git a/tools/incident_section_gen/Android.bp b/tools/incident_section_gen/Android.bp
index 7f8151f..1756e06 100644
--- a/tools/incident_section_gen/Android.bp
+++ b/tools/incident_section_gen/Android.bp
@@ -19,8 +19,6 @@
// ==========================================================
cc_binary_host {
name: "incident-section-gen",
- // b/34740546, work around clang-tidy segmentation fault.
- tidy_checks: ["-modernize*"],
cflags: [
"-g",
"-O0",