diff options
23 files changed, 553 insertions, 188 deletions
diff --git a/api/current.txt b/api/current.txt index bb2492e2f78b..ea2cc0ecdfc9 100644 --- a/api/current.txt +++ b/api/current.txt @@ -37011,17 +37011,17 @@ package android.sax { package android.se.omapi { - public class Channel { + public final class Channel implements java.nio.channels.Channel { method public void close(); method public byte[] getSelectResponse(); method public android.se.omapi.Session getSession(); method public boolean isBasicChannel(); - method public boolean isClosed(); + method public boolean isOpen(); method public boolean selectNext() throws java.io.IOException; method public byte[] transmit(byte[]) throws java.io.IOException; } - public class Reader { + public final class Reader { method public void closeSessions(); method public java.lang.String getName(); method public android.se.omapi.SEService getSEService(); @@ -37029,26 +37029,28 @@ package android.se.omapi { method public android.se.omapi.Session openSession() throws java.io.IOException; } - public class SEService { - ctor public SEService(android.content.Context, android.se.omapi.SEService.SecureElementListener); + public final class SEService { + ctor public SEService(android.content.Context, android.se.omapi.SEService.OnConnectedListener); method public android.se.omapi.Reader[] getReaders(); method public java.lang.String getVersion(); method public boolean isConnected(); method public void shutdown(); } - public static abstract interface SEService.SecureElementListener { + public static abstract interface SEService.OnConnectedListener { method public abstract void onServiceConnected(); } - public class Session { + public final class Session { method public void close(); method public void closeChannels(); method public byte[] getATR(); method public android.se.omapi.Reader getReader(); method public boolean isClosed(); method public android.se.omapi.Channel openBasicChannel(byte[], byte) throws java.io.IOException; + method public android.se.omapi.Channel openBasicChannel(byte[]) throws java.io.IOException; method public android.se.omapi.Channel openLogicalChannel(byte[], byte) throws java.io.IOException; + method public android.se.omapi.Channel openLogicalChannel(byte[]) throws java.io.IOException; } } @@ -40386,17 +40388,17 @@ package android.telephony { } public class MbmsDownloadSession implements java.lang.AutoCloseable { - method public int addProgressListener(android.telephony.mbms.DownloadRequest, java.util.concurrent.Executor, android.telephony.mbms.DownloadProgressListener); - method public int addStatusListener(android.telephony.mbms.DownloadRequest, java.util.concurrent.Executor, android.telephony.mbms.DownloadStatusListener); - method public int cancelDownload(android.telephony.mbms.DownloadRequest); + method public void addProgressListener(android.telephony.mbms.DownloadRequest, java.util.concurrent.Executor, android.telephony.mbms.DownloadProgressListener); + method public void addStatusListener(android.telephony.mbms.DownloadRequest, java.util.concurrent.Executor, android.telephony.mbms.DownloadStatusListener); + method public void cancelDownload(android.telephony.mbms.DownloadRequest); method public void close(); method public static android.telephony.MbmsDownloadSession create(android.content.Context, java.util.concurrent.Executor, android.telephony.mbms.MbmsDownloadSessionCallback); method public static android.telephony.MbmsDownloadSession create(android.content.Context, java.util.concurrent.Executor, int, android.telephony.mbms.MbmsDownloadSessionCallback); - method public int download(android.telephony.mbms.DownloadRequest); + method public void download(android.telephony.mbms.DownloadRequest); method public java.io.File getTempFileRootDirectory(); method public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads(); - method public int removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener); - method public int removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener); + method public void removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener); + method public void removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener); method public void requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo); method public void requestUpdateFileServices(java.util.List<java.lang.String>); method public void resetDownloadKnowledge(android.telephony.mbms.DownloadRequest); @@ -41318,6 +41320,7 @@ package android.telephony.mbms { field public static final int ERROR_MIDDLEWARE_NOT_BOUND = 2; // 0x2 field public static final int ERROR_NO_UNIQUE_MIDDLEWARE = 1; // 0x1 field public static final int SUCCESS = 0; // 0x0 + field public static final int UNKNOWN = -1; // 0xffffffff } public static class MbmsErrors.DownloadErrors { diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index 3683d3450b41..f14847f59ed7 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -25,6 +25,8 @@ import android.system.OsConstants; import com.android.okhttp.internalandroidapi.Dns; import com.android.okhttp.internalandroidapi.HttpURLConnectionFactory; +import libcore.io.IoUtils; + import java.io.FileDescriptor; import java.io.IOException; import java.net.DatagramSocket; @@ -136,9 +138,15 @@ public class Network implements Parcelable { for (int i = 0; i < hostAddresses.length; i++) { try { Socket socket = createSocket(); - if (localAddress != null) socket.bind(localAddress); - socket.connect(new InetSocketAddress(hostAddresses[i], port)); - return socket; + boolean failed = true; + try { + if (localAddress != null) socket.bind(localAddress); + socket.connect(new InetSocketAddress(hostAddresses[i], port)); + failed = false; + return socket; + } finally { + if (failed) IoUtils.closeQuietly(socket); + } } catch (IOException e) { if (i == (hostAddresses.length - 1)) throw e; } @@ -155,15 +163,27 @@ public class Network implements Parcelable { public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { Socket socket = createSocket(); - socket.bind(new InetSocketAddress(localAddress, localPort)); - socket.connect(new InetSocketAddress(address, port)); + boolean failed = true; + try { + socket.bind(new InetSocketAddress(localAddress, localPort)); + socket.connect(new InetSocketAddress(address, port)); + failed = false; + } finally { + if (failed) IoUtils.closeQuietly(socket); + } return socket; } @Override public Socket createSocket(InetAddress host, int port) throws IOException { Socket socket = createSocket(); - socket.connect(new InetSocketAddress(host, port)); + boolean failed = true; + try { + socket.connect(new InetSocketAddress(host, port)); + failed = false; + } finally { + if (failed) IoUtils.closeQuietly(socket); + } return socket; } @@ -175,7 +195,13 @@ public class Network implements Parcelable { @Override public Socket createSocket() throws IOException { Socket socket = new Socket(); - bindSocket(socket); + boolean failed = true; + try { + bindSocket(socket); + failed = false; + } finally { + if (failed) IoUtils.closeQuietly(socket); + } return socket; } } diff --git a/core/java/android/se/omapi/Channel.java b/core/java/android/se/omapi/Channel.java index c8efede3419e..5db3c1a9a707 100644 --- a/core/java/android/se/omapi/Channel.java +++ b/core/java/android/se/omapi/Channel.java @@ -39,7 +39,7 @@ import java.io.IOException; * * @see <a href="http://globalplatform.org">GlobalPlatform Open Mobile API</a> */ -public class Channel { +public final class Channel implements java.nio.channels.Channel { private static final String TAG = "OMAPI.Channel"; private Session mSession; @@ -64,7 +64,7 @@ public class Channel { * before closing the channel. */ public void close() { - if (!isClosed()) { + if (isOpen()) { synchronized (mLock) { try { mChannel.close(); @@ -76,21 +76,21 @@ public class Channel { } /** - * Tells if this channel is closed. + * Tells if this channel is open. * - * @return <code>true</code> if the channel is closed or in case of an error. - * <code>false</code> otherwise. + * @return <code>false</code> if the channel is closed or in case of an error. + * <code>true</code> otherwise. */ - public boolean isClosed() { + public boolean isOpen() { if (!mService.isConnected()) { Log.e(TAG, "service not connected to system"); - return true; + return false; } try { - return mChannel.isClosed(); + return !mChannel.isClosed(); } catch (RemoteException e) { Log.e(TAG, "Exception in isClosed()"); - return true; + return false; } } diff --git a/core/java/android/se/omapi/Reader.java b/core/java/android/se/omapi/Reader.java index 9be3da6c6327..80262f7533c8 100644 --- a/core/java/android/se/omapi/Reader.java +++ b/core/java/android/se/omapi/Reader.java @@ -37,7 +37,7 @@ import java.io.IOException; * * @see <a href="http://globalplatform.org">GlobalPlatform Open Mobile API</a> */ -public class Reader { +public final class Reader { private static final String TAG = "OMAPI.Reader"; private final String mName; diff --git a/core/java/android/se/omapi/SEService.java b/core/java/android/se/omapi/SEService.java index 311dc4c7ae10..1f69df898d03 100644 --- a/core/java/android/se/omapi/SEService.java +++ b/core/java/android/se/omapi/SEService.java @@ -40,7 +40,7 @@ import java.util.HashMap; * * @see <a href="http://simalliance.org">SIMalliance Open Mobile API v3.0</a> */ -public class SEService { +public final class SEService { /** * Error code used with ServiceSpecificException. @@ -62,7 +62,7 @@ public class SEService { /** * Interface to send call-backs to the application when the service is connected. */ - public interface SecureElementListener { + public interface OnConnectedListener { /** * Called by the framework when the service is connected. */ @@ -74,7 +74,7 @@ public class SEService { * SEService could be bound to the backend. */ private class SEListener extends ISecureElementListener.Stub { - public SecureElementListener mListener = null; + public OnConnectedListener mListener = null; @Override public IBinder asBinder() { @@ -122,9 +122,9 @@ public class SEService { * the context of the calling application. Cannot be * <code>null</code>. * @param listener - * a SecureElementListener object. + * a OnConnectedListener object. */ - public SEService(@NonNull Context context, @NonNull SecureElementListener listener) { + public SEService(@NonNull Context context, @NonNull OnConnectedListener listener) { if (context == null) { throw new NullPointerException("context must not be null"); @@ -171,12 +171,12 @@ public class SEService { } /** - * Returns the list of available Secure Element readers. + * Returns an array of available Secure Element readers. * There must be no duplicated objects in the returned list. * All available readers shall be listed even if no card is inserted. * - * @return The readers list, as an array of Readers. If there are no - * readers the returned array is of length 0. + * @return An array of Readers. If there are no readers the returned array + * is of length 0. */ public @NonNull Reader[] getReaders() { if (mSecureElementService == null) { @@ -212,7 +212,8 @@ public class SEService { * (including any binding to an underlying service). * As a result isConnected() will return false after shutdown() was called. * After this method call, the SEService object is not connected. - * It is recommended to call this method in the termination method of the calling application + * This method should be called when connection to the Secure Element is not needed + * or in the termination method of the calling application * (or part of this application) which is bound to this SEService. */ public void shutdown() { diff --git a/core/java/android/se/omapi/Session.java b/core/java/android/se/omapi/Session.java index adfeddd504c4..d5f8c82bf47e 100644 --- a/core/java/android/se/omapi/Session.java +++ b/core/java/android/se/omapi/Session.java @@ -39,7 +39,7 @@ import java.util.NoSuchElementException; * * @see <a href="http://simalliance.org">SIMalliance Open Mobile API v3.0</a> */ -public class Session { +public final class Session { private final Object mLock = new Object(); private final SEService mService; @@ -225,6 +225,32 @@ public class Session { } /** + * This method is provided to ease the development of mobile application and for compliancy + * with existing applications. + * This method is equivalent to openBasicChannel(aid, P2=0x00) + * + * @param aid the AID of the Applet to be selected on this channel, as a + * byte array, or null if no Applet is to be selected. + * @throws IOException if there is a communication problem to the reader or + * the Secure Element. + * @throws IllegalStateException if the Secure Element session is used after + * being closed. + * @throws IllegalArgumentException if the aid's length is not within 5 to + * 16 (inclusive). + * @throws SecurityException if the calling application cannot be granted + * access to this AID or the default Applet on this + * session. + * @throws NoSuchElementException if the AID on the Secure Element is not available or cannot be + * selected. + * @throws UnsupportedOperationException if the given P2 parameter is not + * supported by the device + * @return an instance of Channel if available or null. + */ + public @Nullable Channel openBasicChannel(@Nullable byte[] aid) throws IOException { + return openBasicChannel(aid, (byte) 0x00); + } + + /** * Open a logical channel with the Secure Element, selecting the Applet represented by * the given AID. If the AID is null, which means no Applet is to be selected on this * channel, the default Applet is used. It's up to the Secure Element to choose which @@ -304,4 +330,32 @@ public class Session { } } } + + /** + * This method is provided to ease the development of mobile application and for compliancy + * with existing applications. + * This method is equivalent to openLogicalChannel(aid, P2=0x00) + * + * @param aid the AID of the Applet to be selected on this channel, as a + * byte array. + * @throws IOException if there is a communication problem to the reader or + * the Secure Element. + * @throws IllegalStateException if the Secure Element is used after being + * closed. + * @throws IllegalArgumentException if the aid's length is not within 5 to + * 16 (inclusive). + * @throws SecurityException if the calling application cannot be granted + * access to this AID or the default Applet on this + * session. + * @throws NoSuchElementException if the AID on the Secure Element is not + * available or cannot be selected or a logical channel is already + * open to a non-multiselectable Applet. + * @throws UnsupportedOperationException if the given P2 parameter is not + * supported by the device. + * @return an instance of Channel. Null if the Secure Element is unable to + * provide a new logical channel. + */ + public @Nullable Channel openLogicalChannel(@Nullable byte[] aid) throws IOException { + return openLogicalChannel(aid, (byte) 0x00); + } } diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index b83b8e114856..61b88a5d382f 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -501,30 +501,30 @@ <!-- UI debug setting: Select Bluetooth AVRCP Version --> <string name="bluetooth_select_avrcp_version_dialog_title">Select Bluetooth AVRCP Version</string> - <!-- UI debug setting: Select Bluetooth Audio Codec --> + <!-- UI debug setting: Trigger Bluetooth Audio Codec Selection --> <string name="bluetooth_select_a2dp_codec_type">Bluetooth Audio Codec</string> - <!-- UI debug setting: Select Bluetooth Audio Codec --> - <string name="bluetooth_select_a2dp_codec_type_dialog_title">Select Bluetooth Audio Codec</string> + <!-- UI debug setting: Trigger Bluetooth Audio Codec Selection --> + <string name="bluetooth_select_a2dp_codec_type_dialog_title">Trigger Bluetooth Audio Codec\u000ASelection</string> - <!-- UI debug setting: Select Bluetooth Audio Sample Rate --> + <!-- UI debug setting: Trigger Bluetooth Audio Sample Rate Selection --> <string name="bluetooth_select_a2dp_codec_sample_rate">Bluetooth Audio Sample Rate</string> - <!-- UI debug setting: Select Bluetooth Audio Codec: Sample Rate --> - <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title">Select Bluetooth Audio Codec:\u000ASample Rate</string> + <!-- UI debug setting: Trigger Bluetooth Audio Codec Selection: Sample Rate --> + <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title">Trigger Bluetooth Audio Codec\u000ASelection: Sample Rate</string> - <!-- UI debug setting: Select Bluetooth Audio Bits Per Sample --> + <!-- UI debug setting: Trigger Bluetooth Audio Bits Per Sample Selection --> <string name="bluetooth_select_a2dp_codec_bits_per_sample">Bluetooth Audio Bits Per Sample</string> - <!-- UI debug setting: Select Bluetooth Audio Codec: Bits Per Sample --> - <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title">Select Bluetooth Audio Codec:\u000ABits Per Sample</string> + <!-- UI debug setting: Trigger Bluetooth Audio Codec Selection: Bits Per Sample --> + <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title">Trigger Bluetooth Audio Codec\u000ASelection: Bits Per Sample</string> - <!-- UI debug setting: Select Bluetooth Audio Channel Mode --> + <!-- UI debug setting: Trigger Bluetooth Audio Channel Mode Selection --> <string name="bluetooth_select_a2dp_codec_channel_mode">Bluetooth Audio Channel Mode</string> - <!-- UI debug setting: Select Bluetooth Audio Codec: Channel Mode --> - <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title">Select Bluetooth Audio Codec:\u000AChannel Mode</string> + <!-- UI debug setting: Trigger Bluetooth Audio Codec Selection: Channel Mode --> + <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title">Trigger Bluetooth Audio Codec\u000ASelection: Channel Mode</string> - <!-- UI debug setting: Select Bluetooth Audio LDAC Playback Quality --> + <!-- UI debug setting: Trigger Bluetooth Audio LDAC Playback Quality Selection --> <string name="bluetooth_select_a2dp_codec_ldac_playback_quality">Bluetooth Audio LDAC Codec: Playback Quality</string> <!-- UI debug setting: Select Bluetooth Audio LDAC Codec: LDAC Playback Quality --> - <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title">Select Bluetooth Audio LDAC Codec:\u000APlayback Quality</string> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title">Trigger Bluetooth Audio LDAC Codec\u000ASelection: Playback Quality</string> <!-- [CHAR LIMIT=NONE] Label for displaying Bluetooth Audio Codec Parameters while streaming --> <string name="bluetooth_select_a2dp_codec_streaming_label">Streaming: <xliff:g id="streaming_parameter">%1$s</xliff:g></string> diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java index 7d9736ed3fe5..92a09d328255 100644 --- a/services/net/java/android/net/apf/ApfFilter.java +++ b/services/net/java/android/net/apf/ApfFilter.java @@ -16,21 +16,21 @@ package android.net.apf; +import static android.net.util.NetworkConstants.*; import static android.system.OsConstants.*; - import static com.android.internal.util.BitUtils.bytesToBEInt; import static com.android.internal.util.BitUtils.getUint16; import static com.android.internal.util.BitUtils.getUint32; import static com.android.internal.util.BitUtils.getUint8; -import static com.android.internal.util.BitUtils.uint16; import static com.android.internal.util.BitUtils.uint32; -import static com.android.internal.util.BitUtils.uint8; -import android.os.SystemClock; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NetworkUtils; -import android.net.apf.ApfGenerator; import android.net.apf.ApfGenerator.IllegalInstructionException; import android.net.apf.ApfGenerator.Register; import android.net.ip.IpClient; @@ -39,31 +39,29 @@ import android.net.metrics.ApfStats; import android.net.metrics.IpConnectivityLog; import android.net.metrics.RaEvent; import android.net.util.InterfaceParams; +import android.os.PowerManager; +import android.os.SystemClock; import android.system.ErrnoException; import android.system.Os; import android.system.PacketSocketAddress; import android.text.format.DateUtils; import android.util.Log; import android.util.Pair; - import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.HexDump; import com.android.internal.util.IndentingPrintWriter; - import java.io.FileDescriptor; import java.io.IOException; -import java.lang.Thread; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; -import java.nio.ByteBuffer; import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; - import libcore.io.IoBridge; /** @@ -215,10 +213,6 @@ public class ApfFilter { { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN; - private static final int ICMP6_ROUTER_SOLICITATION = 133; - private static final int ICMP6_ROUTER_ADVERTISEMENT = 134; - private static final int ICMP6_NEIGHBOR_SOLICITATION = 135; - private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136; // NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 2; @@ -258,9 +252,26 @@ public class ApfFilter { private long mUniqueCounter; @GuardedBy("this") private boolean mMulticastFilter; + @GuardedBy("this") + private boolean mInDozeMode; private final boolean mDrop802_3Frames; private final int[] mEthTypeBlackList; + // Detects doze mode state transitions. + private final BroadcastReceiver mDeviceIdleReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) { + PowerManager powerManager = + (PowerManager) context.getSystemService(Context.POWER_SERVICE); + final boolean deviceIdle = powerManager.isDeviceIdleMode(); + setDozeMode(deviceIdle); + } + } + }; + private final Context mContext; + // Our IPv4 address, if we have just one, otherwise null. @GuardedBy("this") private byte[] mIPv4Address; @@ -269,13 +280,14 @@ public class ApfFilter { private int mIPv4PrefixLength; @VisibleForTesting - ApfFilter(ApfConfiguration config, InterfaceParams ifParams, + ApfFilter(Context context, ApfConfiguration config, InterfaceParams ifParams, IpClient.Callback ipClientCallback, IpConnectivityLog log) { mApfCapabilities = config.apfCapabilities; mIpClientCallback = ipClientCallback; mInterfaceParams = ifParams; mMulticastFilter = config.multicastFilter; mDrop802_3Frames = config.ieee802_3Filter; + mContext = context; // Now fill the black list from the passed array mEthTypeBlackList = filterEthTypeBlackList(config.ethTypeBlackList); @@ -284,6 +296,10 @@ public class ApfFilter { // TODO: ApfFilter should not generate programs until IpClient sends provisioning success. maybeStartFilter(); + + // Listen for doze-mode transition changes to enable/disable the IPv6 multicast filter. + mContext.registerReceiver(mDeviceIdleReceiver, + new IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)); } private void log(String s) { @@ -522,7 +538,7 @@ public class ApfFilter { // to our packet socket. b/29586253 if (getUint16(mPacket, ETH_ETHERTYPE_OFFSET) != ETH_P_IPV6 || getUint8(mPacket, IPV6_NEXT_HEADER_OFFSET) != IPPROTO_ICMPV6 || - getUint8(mPacket, ICMP6_TYPE_OFFSET) != ICMP6_ROUTER_ADVERTISEMENT) { + getUint8(mPacket, ICMP6_TYPE_OFFSET) != ICMPV6_ROUTER_ADVERTISEMENT) { throw new InvalidRaException("Not an ICMP6 router advertisement"); } @@ -889,10 +905,11 @@ public class ApfFilter { private void generateIPv6FilterLocked(ApfGenerator gen) throws IllegalInstructionException { // Here's a basic summary of what the IPv6 filter program does: // - // if it's not ICMPv6: - // if it's multicast and we're dropping multicast: - // drop - // pass + // if we're dropping multicast + // if it's not IPCMv6 or it's ICMPv6 but we're in doze mode: + // if it's multicast: + // drop + // pass // if it's ICMPv6 RS to any: // drop // if it's ICMPv6 NA to ff02::1: @@ -902,28 +919,44 @@ public class ApfFilter { // Drop multicast if the multicast filter is enabled. if (mMulticastFilter) { - // Don't touch ICMPv6 multicast here, we deal with it in more detail later. - String skipIpv6MulticastFilterLabel = "skipIPv6MulticastFilter"; - gen.addJumpIfR0Equals(IPPROTO_ICMPV6, skipIpv6MulticastFilterLabel); + final String skipIPv6MulticastFilterLabel = "skipIPv6MulticastFilter"; + final String dropAllIPv6MulticastsLabel = "dropAllIPv6Multicast"; + + // While in doze mode, drop ICMPv6 multicast pings, let the others pass. + // While awake, let all ICMPv6 multicasts through. + if (mInDozeMode) { + // Not ICMPv6? -> Proceed to multicast filtering + gen.addJumpIfR0NotEquals(IPPROTO_ICMPV6, dropAllIPv6MulticastsLabel); + + // ICMPv6 but not ECHO? -> Skip the multicast filter. + // (ICMPv6 ECHO requests will go through the multicast filter below). + gen.addLoad8(Register.R0, ICMP6_TYPE_OFFSET); + gen.addJumpIfR0NotEquals(ICMPV6_ECHO_REQUEST_TYPE, skipIPv6MulticastFilterLabel); + } else { + gen.addJumpIfR0Equals(IPPROTO_ICMPV6, skipIPv6MulticastFilterLabel); + } - // Drop all other packets sent to ff00::/8. + // Drop all other packets sent to ff00::/8 (multicast prefix). + gen.defineLabel(dropAllIPv6MulticastsLabel); gen.addLoad8(Register.R0, IPV6_DEST_ADDR_OFFSET); gen.addJumpIfR0Equals(0xff, gen.DROP_LABEL); - // Not multicast and not ICMPv6. Pass. + // Not multicast. Pass. gen.addJump(gen.PASS_LABEL); - gen.defineLabel(skipIpv6MulticastFilterLabel); + gen.defineLabel(skipIPv6MulticastFilterLabel); } else { // If not ICMPv6, pass. gen.addJumpIfR0NotEquals(IPPROTO_ICMPV6, gen.PASS_LABEL); } + // If we got this far, the packet is ICMPv6. Drop some specific types. + // Add unsolicited multicast neighbor announcements filter String skipUnsolicitedMulticastNALabel = "skipUnsolicitedMulticastNA"; gen.addLoad8(Register.R0, ICMP6_TYPE_OFFSET); // Drop all router solicitations (b/32833400) - gen.addJumpIfR0Equals(ICMP6_ROUTER_SOLICITATION, gen.DROP_LABEL); + gen.addJumpIfR0Equals(ICMPV6_ROUTER_SOLICITATION, gen.DROP_LABEL); // If not neighbor announcements, skip filter. - gen.addJumpIfR0NotEquals(ICMP6_NEIGHBOR_ANNOUNCEMENT, skipUnsolicitedMulticastNALabel); + gen.addJumpIfR0NotEquals(ICMPV6_NEIGHBOR_ADVERTISEMENT, skipUnsolicitedMulticastNALabel); // If to ff02::1, drop. // TODO: Drop only if they don't contain the address of on-link neighbours. gen.addLoadImmediate(Register.R0, IPV6_DEST_ADDR_OFFSET); @@ -1167,9 +1200,9 @@ public class ApfFilter { * Create an {@link ApfFilter} if {@code apfCapabilities} indicates support for packet * filtering using APF programs. */ - public static ApfFilter maybeCreate(ApfConfiguration config, + public static ApfFilter maybeCreate(Context context, ApfConfiguration config, InterfaceParams ifParams, IpClient.Callback ipClientCallback) { - if (config == null || ifParams == null) return null; + if (context == null || config == null || ifParams == null) return null; ApfCapabilities apfCapabilities = config.apfCapabilities; if (apfCapabilities == null) return null; if (apfCapabilities.apfVersionSupported == 0) return null; @@ -1186,7 +1219,8 @@ public class ApfFilter { Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported); return null; } - return new ApfFilter(config, ifParams, ipClientCallback, new IpConnectivityLog()); + + return new ApfFilter(context, config, ifParams, ipClientCallback, new IpConnectivityLog()); } public synchronized void shutdown() { @@ -1196,12 +1230,11 @@ public class ApfFilter { mReceiveThread = null; } mRas.clear(); + mContext.unregisterReceiver(mDeviceIdleReceiver); } public synchronized void setMulticastFilter(boolean isEnabled) { - if (mMulticastFilter == isEnabled) { - return; - } + if (mMulticastFilter == isEnabled) return; mMulticastFilter = isEnabled; if (!isEnabled) { mNumProgramUpdatesAllowingMulticast++; @@ -1209,6 +1242,13 @@ public class ApfFilter { installNewProgramLocked(); } + @VisibleForTesting + public synchronized void setDozeMode(boolean isEnabled) { + if (mInDozeMode == isEnabled) return; + mInDozeMode = isEnabled; + installNewProgramLocked(); + } + /** Find the single IPv4 LinkAddress if there is one, otherwise return null. */ private static LinkAddress findIPv4LinkAddress(LinkProperties lp) { LinkAddress ipv4Address = null; diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java index 9863370e3840..a184b227aac4 100644 --- a/services/net/java/android/net/ip/IpClient.java +++ b/services/net/java/android/net/ip/IpClient.java @@ -1490,7 +1490,7 @@ public class IpClient extends StateMachine { mContext.getResources().getBoolean(R.bool.config_apfDrop802_3Frames); apfConfig.ethTypeBlackList = mContext.getResources().getIntArray(R.array.config_apfEthTypeBlackList); - mApfFilter = ApfFilter.maybeCreate(apfConfig, mInterfaceParams, mCallback); + mApfFilter = ApfFilter.maybeCreate(mContext, apfConfig, mInterfaceParams, mCallback); // TODO: investigate the effects of any multicast filtering racing/interfering with the // rest of this IP configuration startup. if (mApfFilter == null) { diff --git a/services/net/java/android/net/util/NetworkConstants.java b/services/net/java/android/net/util/NetworkConstants.java index 984c9f817d75..53fd01f2d8dd 100644 --- a/services/net/java/android/net/util/NetworkConstants.java +++ b/services/net/java/android/net/util/NetworkConstants.java @@ -136,6 +136,8 @@ public final class NetworkConstants { * - https://tools.ietf.org/html/rfc4861 */ public static final int ICMPV6_HEADER_MIN_LEN = 4; + public static final int ICMPV6_ECHO_REQUEST_TYPE = 128; + public static final int ICMPV6_ECHO_REPLY_TYPE = 129; public static final int ICMPV6_ROUTER_SOLICITATION = 133; public static final int ICMPV6_ROUTER_ADVERTISEMENT = 134; public static final int ICMPV6_NEIGHBOR_SOLICITATION = 135; @@ -147,7 +149,6 @@ public final class NetworkConstants { public static final int ICMPV6_ND_OPTION_TLLA = 2; public static final int ICMPV6_ND_OPTION_MTU = 5; - public static final int ICMPV6_ECHO_REQUEST_TYPE = 128; /** * UDP constants. diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java index dc6f0b79f825..d9fdd97e0889 100644 --- a/telephony/java/android/telephony/MbmsDownloadSession.java +++ b/telephony/java/android/telephony/MbmsDownloadSession.java @@ -16,6 +16,8 @@ package android.telephony; +import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; + import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -32,14 +34,14 @@ import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.telephony.mbms.DownloadProgressListener; +import android.telephony.mbms.DownloadRequest; import android.telephony.mbms.DownloadStatusListener; import android.telephony.mbms.FileInfo; -import android.telephony.mbms.DownloadRequest; import android.telephony.mbms.InternalDownloadProgressListener; import android.telephony.mbms.InternalDownloadSessionCallback; import android.telephony.mbms.InternalDownloadStatusListener; -import android.telephony.mbms.MbmsDownloadSessionCallback; import android.telephony.mbms.MbmsDownloadReceiver; +import android.telephony.mbms.MbmsDownloadSessionCallback; import android.telephony.mbms.MbmsErrors; import android.telephony.mbms.MbmsTempFileProvider; import android.telephony.mbms.MbmsUtils; @@ -58,8 +60,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; - /** * This class provides functionality for file download over MBMS. */ @@ -337,6 +337,12 @@ public class MbmsDownloadSession implements AutoCloseable { sIsInitialized.set(false); return; } + if (result == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return an" + + " unknown error code"); + } if (result != MbmsErrors.SUCCESS) { sendErrorToApp(result, "Error returned during initialization"); sIsInitialized.set(false); @@ -388,6 +394,11 @@ public class MbmsDownloadSession implements AutoCloseable { } try { int returnCode = downloadService.requestUpdateFileServices(mSubscriptionId, classList); + if (returnCode == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return an unknown error code"); + } if (returnCode != MbmsErrors.SUCCESS) { sendErrorToApp(returnCode, null); } @@ -443,6 +454,11 @@ public class MbmsDownloadSession implements AutoCloseable { try { int result = downloadService.setTempFileRootDirectory(mSubscriptionId, filePath); + if (result == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return an unknown error code"); + } if (result != MbmsErrors.SUCCESS) { sendErrorToApp(result, null); return; @@ -514,11 +530,13 @@ public class MbmsDownloadSession implements AutoCloseable { * * Asynchronous errors through the callback may include any error not specific to the * streaming use-case. + * + * If no error is delivered via the callback after calling this method, that means that the + * middleware has successfully started the download or scheduled the download, if the download + * is at a future time. * @param request The request that specifies what should be downloaded. - * @return {@link MbmsErrors#SUCCESS} if the operation did not encounter a synchronous error, - * and some other error code otherwise. */ - public int download(@NonNull DownloadRequest request) { + public void download(@NonNull DownloadRequest request) { IMbmsDownloadService downloadService = mService.get(); if (downloadService == null) { throw new IllegalStateException("Middleware not yet bound"); @@ -540,12 +558,19 @@ public class MbmsDownloadSession implements AutoCloseable { int result = downloadService.download(request); if (result == MbmsErrors.SUCCESS) { writeDownloadRequestToken(request); + } else { + if (result == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return an unknown" + + " error code"); + } + sendErrorToApp(result, null); } - return result; } catch (RemoteException e) { mService.set(null); sIsInitialized.set(false); - return MbmsErrors.ERROR_MIDDLEWARE_LOST; + sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null); } } @@ -581,14 +606,15 @@ public class MbmsDownloadSession implements AutoCloseable { * If the middleware is not aware of the specified download request, * this method will throw an {@link IllegalArgumentException}. * + * If the operation encountered an error, the error code will be delivered via + * {@link MbmsDownloadSessionCallback#onError}. + * * @param request The {@link DownloadRequest} that you want updates on. * @param executor The {@link Executor} on which calls to {@code listener } should be executed. * @param listener The listener that should be called when the middleware has information to * share on the status download. - * @return {@link MbmsErrors#SUCCESS} if the operation did not encounter a synchronous error, - * and some other error code otherwise. */ - public int addStatusListener(@NonNull DownloadRequest request, + public void addStatusListener(@NonNull DownloadRequest request, @NonNull Executor executor, @NonNull DownloadStatusListener listener) { IMbmsDownloadService downloadService = mService.get(); if (downloadService == null) { @@ -600,20 +626,25 @@ public class MbmsDownloadSession implements AutoCloseable { try { int result = downloadService.addStatusListener(request, internalListener); + if (result == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return an unknown error code"); + } if (result != MbmsErrors.SUCCESS) { if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) { throw new IllegalArgumentException("Unknown download request."); } - return result; + sendErrorToApp(result, null); + return; } } catch (RemoteException e) { mService.set(null); sIsInitialized.set(false); - return MbmsErrors.ERROR_MIDDLEWARE_LOST; + sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null); + return; } mInternalDownloadStatusListeners.put(listener, internalListener); - return MbmsErrors.SUCCESS; - } /** @@ -625,12 +656,13 @@ public class MbmsDownloadSession implements AutoCloseable { * If the middleware is not aware of the specified download request, * this method will throw an {@link IllegalArgumentException}. * + * If the operation encountered an error, the error code will be delivered via + * {@link MbmsDownloadSessionCallback#onError}. + * * @param request The {@link DownloadRequest} provided during registration * @param listener The listener provided during registration. - * @return {@link MbmsErrors#SUCCESS} if the operation did not encounter a synchronous error, - * and some other error code otherwise. */ - public int removeStatusListener(@NonNull DownloadRequest request, + public void removeStatusListener(@NonNull DownloadRequest request, @NonNull DownloadStatusListener listener) { try { IMbmsDownloadService downloadService = mService.get(); @@ -646,16 +678,24 @@ public class MbmsDownloadSession implements AutoCloseable { try { int result = downloadService.removeStatusListener(request, internalListener); + if (result == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return an" + + " unknown error code"); + } if (result != MbmsErrors.SUCCESS) { if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) { throw new IllegalArgumentException("Unknown download request."); } - return result; + sendErrorToApp(result, null); + return; } } catch (RemoteException e) { mService.set(null); sIsInitialized.set(false); - return MbmsErrors.ERROR_MIDDLEWARE_LOST; + sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null); + return; } } finally { InternalDownloadStatusListener internalCallback = @@ -664,7 +704,6 @@ public class MbmsDownloadSession implements AutoCloseable { internalCallback.stop(); } } - return MbmsErrors.SUCCESS; } /** @@ -676,14 +715,15 @@ public class MbmsDownloadSession implements AutoCloseable { * If the middleware is not aware of the specified download request, * this method will throw an {@link IllegalArgumentException}. * + * If the operation encountered an error, the error code will be delivered via + * {@link MbmsDownloadSessionCallback#onError}. + * * @param request The {@link DownloadRequest} that you want updates on. * @param executor The {@link Executor} on which calls to {@code listener} should be executed. * @param listener The listener that should be called when the middleware has information to * share on the progress of the download. - * @return {@link MbmsErrors#SUCCESS} if the operation did not encounter a synchronous error, - * and some other error code otherwise. */ - public int addProgressListener(@NonNull DownloadRequest request, + public void addProgressListener(@NonNull DownloadRequest request, @NonNull Executor executor, @NonNull DownloadProgressListener listener) { IMbmsDownloadService downloadService = mService.get(); if (downloadService == null) { @@ -695,19 +735,25 @@ public class MbmsDownloadSession implements AutoCloseable { try { int result = downloadService.addProgressListener(request, internalListener); + if (result == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return an unknown error code"); + } if (result != MbmsErrors.SUCCESS) { if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) { throw new IllegalArgumentException("Unknown download request."); } - return result; + sendErrorToApp(result, null); + return; } } catch (RemoteException e) { mService.set(null); sIsInitialized.set(false); - return MbmsErrors.ERROR_MIDDLEWARE_LOST; + sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null); + return; } mInternalDownloadProgressListeners.put(listener, internalListener); - return MbmsErrors.SUCCESS; } /** @@ -719,12 +765,13 @@ public class MbmsDownloadSession implements AutoCloseable { * If the middleware is not aware of the specified download request, * this method will throw an {@link IllegalArgumentException}. * + * If the operation encountered an error, the error code will be delivered via + * {@link MbmsDownloadSessionCallback#onError}. + * * @param request The {@link DownloadRequest} provided during registration * @param listener The listener provided during registration. - * @return {@link MbmsErrors#SUCCESS} if the operation did not encounter a synchronous error, - * and some other error code otherwise. */ - public int removeProgressListener(@NonNull DownloadRequest request, + public void removeProgressListener(@NonNull DownloadRequest request, @NonNull DownloadProgressListener listener) { try { IMbmsDownloadService downloadService = mService.get(); @@ -740,16 +787,24 @@ public class MbmsDownloadSession implements AutoCloseable { try { int result = downloadService.removeProgressListener(request, internalListener); + if (result == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not" + + " return an unknown error code"); + } if (result != MbmsErrors.SUCCESS) { if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) { throw new IllegalArgumentException("Unknown download request."); } - return result; + sendErrorToApp(result, null); + return; } } catch (RemoteException e) { mService.set(null); sIsInitialized.set(false); - return MbmsErrors.ERROR_MIDDLEWARE_LOST; + sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null); + return; } } finally { InternalDownloadProgressListener internalCallback = @@ -758,20 +813,17 @@ public class MbmsDownloadSession implements AutoCloseable { internalCallback.stop(); } } - return MbmsErrors.SUCCESS; } /** * Attempts to cancel the specified {@link DownloadRequest}. * - * If the middleware is not aware of the specified download request, - * this method will throw an {@link IllegalArgumentException}. + * If the operation encountered an error, the error code will be delivered via + * {@link MbmsDownloadSessionCallback#onError}. * * @param downloadRequest The download request that you wish to cancel. - * @return {@link MbmsErrors#SUCCESS} if the operation did not encounter a synchronous error, - * and some other error code otherwise. */ - public int cancelDownload(@NonNull DownloadRequest downloadRequest) { + public void cancelDownload(@NonNull DownloadRequest downloadRequest) { IMbmsDownloadService downloadService = mService.get(); if (downloadService == null) { throw new IllegalStateException("Middleware not yet bound"); @@ -779,18 +831,20 @@ public class MbmsDownloadSession implements AutoCloseable { try { int result = downloadService.cancelDownload(downloadRequest); + if (result == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return an unknown error code"); + } if (result != MbmsErrors.SUCCESS) { - if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) { - throw new IllegalArgumentException("Unknown download request."); - } + sendErrorToApp(result, null); } else { deleteDownloadRequestToken(downloadRequest); } - return result; } catch (RemoteException e) { mService.set(null); sIsInitialized.set(false); - return MbmsErrors.ERROR_MIDDLEWARE_LOST; + sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null); } } @@ -818,6 +872,11 @@ public class MbmsDownloadSession implements AutoCloseable { try { int result = downloadService.requestDownloadState(downloadRequest, fileInfo); + if (result == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return an unknown error code"); + } if (result != MbmsErrors.SUCCESS) { if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) { throw new IllegalArgumentException("Unknown download request."); @@ -862,6 +921,11 @@ public class MbmsDownloadSession implements AutoCloseable { try { int result = downloadService.resetDownloadKnowledge(downloadRequest); + if (result == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return an unknown error code"); + } if (result != MbmsErrors.SUCCESS) { if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) { throw new IllegalArgumentException("Unknown download request."); @@ -978,10 +1042,6 @@ public class MbmsDownloadSession implements AutoCloseable { } private void sendErrorToApp(int errorCode, String message) { - try { - mInternalCallback.onError(errorCode, message); - } catch (RemoteException e) { - // Ignore, should not happen locally. - } + mInternalCallback.onError(errorCode, message); } } diff --git a/telephony/java/android/telephony/MbmsStreamingSession.java b/telephony/java/android/telephony/MbmsStreamingSession.java index 42c760d4dde8..cd465d22d331 100644 --- a/telephony/java/android/telephony/MbmsStreamingSession.java +++ b/telephony/java/android/telephony/MbmsStreamingSession.java @@ -16,6 +16,8 @@ package android.telephony; +import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SdkConstant; @@ -26,8 +28,8 @@ import android.content.Context; import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; -import android.telephony.mbms.InternalStreamingSessionCallback; import android.telephony.mbms.InternalStreamingServiceCallback; +import android.telephony.mbms.InternalStreamingSessionCallback; import android.telephony.mbms.MbmsErrors; import android.telephony.mbms.MbmsStreamingSessionCallback; import android.telephony.mbms.MbmsUtils; @@ -44,8 +46,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; - /** * This class provides functionality for streaming media over MBMS. */ @@ -208,6 +208,11 @@ public class MbmsStreamingSession implements AutoCloseable { try { int returnCode = streamingService.requestUpdateStreamingServices( mSubscriptionId, serviceClassList); + if (returnCode == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return an unknown error code"); + } if (returnCode != MbmsErrors.SUCCESS) { sendErrorToApp(returnCode, null); } @@ -255,6 +260,11 @@ public class MbmsStreamingSession implements AutoCloseable { try { int returnCode = streamingService.startStreaming( mSubscriptionId, serviceInfo.getServiceId(), serviceCallback); + if (returnCode == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return an unknown error code"); + } if (returnCode != MbmsErrors.SUCCESS) { sendErrorToApp(returnCode, null); return null; @@ -301,6 +311,12 @@ public class MbmsStreamingSession implements AutoCloseable { sIsInitialized.set(false); return; } + if (result == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return" + + " an unknown error code"); + } if (result != MbmsErrors.SUCCESS) { sendErrorToApp(result, "Error returned during initialization"); sIsInitialized.set(false); diff --git a/telephony/java/android/telephony/NetworkServiceCallback.java b/telephony/java/android/telephony/NetworkServiceCallback.java index 92ebf367025c..dbad02fd5640 100644 --- a/telephony/java/android/telephony/NetworkServiceCallback.java +++ b/telephony/java/android/telephony/NetworkServiceCallback.java @@ -83,6 +83,8 @@ public class NetworkServiceCallback { } catch (RemoteException e) { Rlog.e(mTag, "Failed to onGetNetworkRegistrationStateComplete on the remote"); } + } else { + Rlog.e(mTag, "Weak reference of callback is null."); } } }
\ No newline at end of file diff --git a/telephony/java/android/telephony/mbms/InternalDownloadSessionCallback.java b/telephony/java/android/telephony/mbms/InternalDownloadSessionCallback.java index c2a79d82f8b6..2916f81c8cd2 100644 --- a/telephony/java/android/telephony/mbms/InternalDownloadSessionCallback.java +++ b/telephony/java/android/telephony/mbms/InternalDownloadSessionCallback.java @@ -17,7 +17,6 @@ package android.telephony.mbms; import android.os.Binder; -import android.os.RemoteException; import java.util.List; import java.util.concurrent.Executor; @@ -36,7 +35,7 @@ public class InternalDownloadSessionCallback extends IMbmsDownloadSessionCallbac } @Override - public void onError(final int errorCode, final String message) throws RemoteException { + public void onError(final int errorCode, final String message) { if (mIsStopped) { return; } @@ -55,7 +54,7 @@ public class InternalDownloadSessionCallback extends IMbmsDownloadSessionCallbac } @Override - public void onFileServicesUpdated(final List<FileServiceInfo> services) throws RemoteException { + public void onFileServicesUpdated(final List<FileServiceInfo> services) { if (mIsStopped) { return; } @@ -74,7 +73,7 @@ public class InternalDownloadSessionCallback extends IMbmsDownloadSessionCallbac } @Override - public void onMiddlewareReady() throws RemoteException { + public void onMiddlewareReady() { if (mIsStopped) { return; } diff --git a/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java b/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java index fe7533f57b12..dd1061f3bd46 100644 --- a/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java +++ b/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java @@ -31,6 +31,8 @@ import android.telephony.MbmsDownloadSession; import android.telephony.mbms.vendor.VendorUtils; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; + import java.io.File; import java.io.FileFilter; import java.io.IOException; @@ -268,7 +270,10 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { Uri finalLocation; try { - finalLocation = moveToFinalLocation(finalTempFile, appSpecifiedDestination); + String relativeLocation = getFileRelativePath(request.getSourceUri().getPath(), + completedFileInfo.getUri().getPath()); + finalLocation = moveToFinalLocation(finalTempFile, appSpecifiedDestination, + relativeLocation); } catch (IOException e) { Log.w(LOG_TAG, "Failed to move temp file to final destination"); setResultCode(RESULT_DOWNLOAD_FINALIZATION_ERROR); @@ -442,7 +447,8 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { /* * Moves a tempfile located at fromPath to its final home where the app wants it */ - private static Uri moveToFinalLocation(Uri fromPath, Path appSpecifiedPath) throws IOException { + private static Uri moveToFinalLocation(Uri fromPath, Path appSpecifiedPath, + String relativeLocation) throws IOException { if (!ContentResolver.SCHEME_FILE.equals(fromPath.getScheme())) { Log.w(LOG_TAG, "Downloaded file location uri " + fromPath + " does not have a file scheme"); @@ -450,16 +456,46 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { } Path fromFile = FileSystems.getDefault().getPath(fromPath.getPath()); - if (!Files.isDirectory(appSpecifiedPath)) { - Files.createDirectory(appSpecifiedPath); + Path toFile = appSpecifiedPath.resolve(relativeLocation); + + if (!Files.isDirectory(toFile.getParent())) { + Files.createDirectories(toFile.getParent()); } - // TODO: do we want to support directory trees within the download directory? - Path result = Files.move(fromFile, appSpecifiedPath.resolve(fromFile.getFileName()), + Path result = Files.move(fromFile, toFile, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE); return Uri.fromFile(result.toFile()); } + /** + * @hide + */ + @VisibleForTesting + public static String getFileRelativePath(String sourceUriPath, String fileInfoPath) { + if (sourceUriPath.endsWith("*")) { + // This is a wildcard path. Strip the last path component and use that as the root of + // the relative path. + int lastSlash = sourceUriPath.lastIndexOf('/'); + sourceUriPath = sourceUriPath.substring(0, lastSlash); + } + if (!fileInfoPath.startsWith(sourceUriPath)) { + Log.e(LOG_TAG, "File location specified in FileInfo does not match the source URI." + + " source: " + sourceUriPath + " fileinfo path: " + fileInfoPath); + return null; + } + if (fileInfoPath.length() == sourceUriPath.length()) { + // This is the single-file download case. Return the name of the file so that the + // receiver puts the file directly into the dest directory. + return sourceUriPath.substring(sourceUriPath.lastIndexOf('/') + 1); + } + + String prefixOmittedPath = fileInfoPath.substring(sourceUriPath.length()); + if (prefixOmittedPath.startsWith("/")) { + prefixOmittedPath = prefixOmittedPath.substring(1); + } + return prefixOmittedPath; + } + private static boolean verifyTempFilePath(Context context, String serviceId, Uri filePath) { if (!ContentResolver.SCHEME_FILE.equals(filePath.getScheme())) { diff --git a/telephony/java/android/telephony/mbms/MbmsDownloadSessionCallback.java b/telephony/java/android/telephony/mbms/MbmsDownloadSessionCallback.java index 77dea6f309e5..5003b576173e 100644 --- a/telephony/java/android/telephony/mbms/MbmsDownloadSessionCallback.java +++ b/telephony/java/android/telephony/mbms/MbmsDownloadSessionCallback.java @@ -16,8 +16,11 @@ package android.telephony.mbms; +import android.annotation.IntDef; import android.telephony.MbmsDownloadSession; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.List; /** @@ -25,6 +28,26 @@ import java.util.List; * cell-broadcast. */ public class MbmsDownloadSessionCallback { + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + MbmsErrors.ERROR_NO_UNIQUE_MIDDLEWARE, + MbmsErrors.ERROR_MIDDLEWARE_LOST, + MbmsErrors.ERROR_MIDDLEWARE_NOT_BOUND, + MbmsErrors.InitializationErrors.ERROR_APP_PERMISSIONS_NOT_GRANTED, + MbmsErrors.InitializationErrors.ERROR_DUPLICATE_INITIALIZE, + MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE, + MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_NOT_YET_READY, + MbmsErrors.GeneralErrors.ERROR_OUT_OF_MEMORY, + MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE, + MbmsErrors.GeneralErrors.ERROR_IN_E911, + MbmsErrors.GeneralErrors.ERROR_NOT_CONNECTED_TO_HOME_CARRIER_LTE, + MbmsErrors.GeneralErrors.ERROR_UNABLE_TO_READ_SIM, + MbmsErrors.GeneralErrors.ERROR_CARRIER_CHANGE_NOT_ALLOWED, + MbmsErrors.DownloadErrors.ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT, + MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST, + MbmsErrors.DownloadErrors.ERROR_UNKNOWN_FILE_INFO}, prefix = { "ERROR_" }) + private @interface DownloadError{} /** * Indicates that the middleware has encountered an asynchronous error. @@ -32,7 +55,7 @@ public class MbmsDownloadSessionCallback { * @param message A message, intended for debugging purposes, describing the error in further * detail. */ - public void onError(int errorCode, String message) { + public void onError(@DownloadError int errorCode, String message) { // default implementation empty } diff --git a/telephony/java/android/telephony/mbms/MbmsErrors.java b/telephony/java/android/telephony/mbms/MbmsErrors.java index b5fec445d853..7c4321ba75c3 100644 --- a/telephony/java/android/telephony/mbms/MbmsErrors.java +++ b/telephony/java/android/telephony/mbms/MbmsErrors.java @@ -19,6 +19,13 @@ package android.telephony.mbms; import android.telephony.MbmsStreamingSession; public class MbmsErrors { + /** + * Indicates that the middleware has sent an error code that is not defined in the version of + * the SDK targeted by your app. This is an illegal value for the middleware to return -- it + * should only ever be generated by the framework. + */ + public static final int UNKNOWN = -1; + /** Indicates that the operation was successful. */ public static final int SUCCESS = 0; diff --git a/telephony/java/android/telephony/mbms/MbmsStreamingSessionCallback.java b/telephony/java/android/telephony/mbms/MbmsStreamingSessionCallback.java index 6e0395730aba..1bdb20bf0823 100644 --- a/telephony/java/android/telephony/mbms/MbmsStreamingSessionCallback.java +++ b/telephony/java/android/telephony/mbms/MbmsStreamingSessionCallback.java @@ -16,11 +16,13 @@ package android.telephony.mbms; +import android.annotation.IntDef; import android.annotation.Nullable; import android.content.Context; -import android.os.Handler; import android.telephony.MbmsStreamingSession; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.concurrent.Executor; @@ -30,13 +32,34 @@ import java.util.concurrent.Executor; * {@link MbmsStreamingSession#create(Context, Executor, int, MbmsStreamingSessionCallback)}. */ public class MbmsStreamingSessionCallback { + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + MbmsErrors.ERROR_NO_UNIQUE_MIDDLEWARE, + MbmsErrors.ERROR_MIDDLEWARE_LOST, + MbmsErrors.ERROR_MIDDLEWARE_NOT_BOUND, + MbmsErrors.InitializationErrors.ERROR_APP_PERMISSIONS_NOT_GRANTED, + MbmsErrors.InitializationErrors.ERROR_DUPLICATE_INITIALIZE, + MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE, + MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_NOT_YET_READY, + MbmsErrors.GeneralErrors.ERROR_OUT_OF_MEMORY, + MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE, + MbmsErrors.GeneralErrors.ERROR_IN_E911, + MbmsErrors.GeneralErrors.ERROR_NOT_CONNECTED_TO_HOME_CARRIER_LTE, + MbmsErrors.GeneralErrors.ERROR_UNABLE_TO_READ_SIM, + MbmsErrors.GeneralErrors.ERROR_CARRIER_CHANGE_NOT_ALLOWED, + MbmsErrors.StreamingErrors.ERROR_CONCURRENT_SERVICE_LIMIT_REACHED, + MbmsErrors.StreamingErrors.ERROR_UNABLE_TO_START_SERVICE, + MbmsErrors.StreamingErrors.ERROR_DUPLICATE_START_STREAM}, prefix = { "ERROR_" }) + private @interface StreamingError{} + /** * Called by the middleware when it has detected an error condition. The possible error codes * are listed in {@link MbmsErrors}. * @param errorCode The error code. * @param message A human-readable message generated by the middleware for debugging purposes. */ - public void onError(int errorCode, @Nullable String message) { + public void onError(@StreamingError int errorCode, @Nullable String message) { // default implementation empty } diff --git a/telephony/java/android/telephony/mbms/MbmsUtils.java b/telephony/java/android/telephony/mbms/MbmsUtils.java index ef317eefb3e3..06b2120b59c1 100644 --- a/telephony/java/android/telephony/mbms/MbmsUtils.java +++ b/telephony/java/android/telephony/mbms/MbmsUtils.java @@ -130,8 +130,12 @@ public class MbmsUtils { * Returns a File linked to the directory used to store temp files for this file service */ public static File getEmbmsTempFileDirForService(Context context, String serviceId) { + // Replace all non-alphanumerics/underscores with an underscore. Some filesystems don't + // like special characters. + String sanitizedServiceId = serviceId.replaceAll("[^a-zA-Z0-9_]", "_"); + File embmsTempFileDir = MbmsTempFileProvider.getEmbmsTempFileDir(context); - return new File(embmsTempFileDir, serviceId); + return new File(embmsTempFileDir, sanitizedServiceId); } } diff --git a/telephony/java/android/telephony/mbms/StreamingServiceCallback.java b/telephony/java/android/telephony/mbms/StreamingServiceCallback.java index 09038244a16a..c265db6fe1ca 100644 --- a/telephony/java/android/telephony/mbms/StreamingServiceCallback.java +++ b/telephony/java/android/telephony/mbms/StreamingServiceCallback.java @@ -16,13 +16,34 @@ package android.telephony.mbms; +import android.annotation.IntDef; import android.annotation.Nullable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * A callback class for use when the application is actively streaming content. The middleware * will provide updates on the status of the stream via this callback. */ public class StreamingServiceCallback { + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + MbmsErrors.ERROR_NO_UNIQUE_MIDDLEWARE, + MbmsErrors.ERROR_MIDDLEWARE_LOST, + MbmsErrors.ERROR_MIDDLEWARE_NOT_BOUND, + MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_NOT_YET_READY, + MbmsErrors.GeneralErrors.ERROR_OUT_OF_MEMORY, + MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE, + MbmsErrors.GeneralErrors.ERROR_IN_E911, + MbmsErrors.GeneralErrors.ERROR_NOT_CONNECTED_TO_HOME_CARRIER_LTE, + MbmsErrors.GeneralErrors.ERROR_UNABLE_TO_READ_SIM, + MbmsErrors.GeneralErrors.ERROR_CARRIER_CHANGE_NOT_ALLOWED, + MbmsErrors.StreamingErrors.ERROR_CONCURRENT_SERVICE_LIMIT_REACHED, + MbmsErrors.StreamingErrors.ERROR_UNABLE_TO_START_SERVICE, + MbmsErrors.StreamingErrors.ERROR_DUPLICATE_START_STREAM}, prefix = { "ERROR_" }) + private @interface StreamingServiceError{} /** * Indicates broadcast signal strength is not available for this service. @@ -39,7 +60,7 @@ public class StreamingServiceCallback { * @param errorCode The error code. * @param message A human-readable message generated by the middleware for debugging purposes. */ - public void onError(int errorCode, @Nullable String message) { + public void onError(@StreamingServiceError int errorCode, @Nullable String message) { // default implementation empty } diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java index f9d7161021e9..a9f10b1b460f 100644 --- a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java +++ b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java @@ -130,6 +130,10 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub { @Override public void onError(int errorCode, String message) { try { + if (errorCode == MbmsErrors.UNKNOWN) { + throw new IllegalArgumentException( + "Middleware cannot send an unknown error."); + } callback.onError(errorCode, message); } catch (RemoteException e) { onAppCallbackDied(uid, subscriptionId); diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java index db177c0c7768..5ce612db49d6 100644 --- a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java +++ b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java @@ -77,6 +77,10 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub { @Override public void onError(final int errorCode, final String message) { try { + if (errorCode == MbmsErrors.UNKNOWN) { + throw new IllegalArgumentException( + "Middleware cannot send an unknown error."); + } callback.onError(errorCode, message); } catch (RemoteException e) { onAppCallbackDied(uid, subscriptionId); @@ -173,6 +177,10 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub { @Override public void onError(final int errorCode, final String message) { try { + if (errorCode == MbmsErrors.UNKNOWN) { + throw new IllegalArgumentException( + "Middleware cannot send an unknown error."); + } callback.onError(errorCode, message); } catch (RemoteException e) { onAppCallbackDied(uid, subscriptionId); diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java index 9b75a509288f..fef702ecb888 100644 --- a/tests/net/java/android/net/apf/ApfTest.java +++ b/tests/net/java/android/net/apf/ApfTest.java @@ -16,6 +16,7 @@ package android.net.apf; +import static android.net.util.NetworkConstants.*; import static android.system.OsConstants.*; import static com.android.internal.util.BitUtils.bytesToBEInt; import static com.android.internal.util.BitUtils.put; @@ -26,6 +27,7 @@ import static org.junit.Assert.fail; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.verify; +import android.content.Context; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NetworkUtils; @@ -82,6 +84,7 @@ public class ApfTest { private static final int TIMEOUT_MS = 500; @Mock IpConnectivityLog mLog; + @Mock Context mContext; @Before public void setUp() throws Exception { @@ -633,9 +636,9 @@ public class ApfTest { private FileDescriptor mWriteSocket; private final long mFixedTimeMs = SystemClock.elapsedRealtime(); - public TestApfFilter(ApfConfiguration config, IpManager.Callback ipManagerCallback, - IpConnectivityLog log) throws Exception { - super(config, InterfaceParams.getByName("lo"), ipManagerCallback, log); + public TestApfFilter(Context context, ApfConfiguration config, + IpManager.Callback ipManagerCallback, IpConnectivityLog log) throws Exception { + super(context, config, InterfaceParams.getByName("lo"), ipManagerCallback, log); } // Pretend an RA packet has been received and show it to ApfFilter. @@ -757,6 +760,17 @@ public class ApfTest { private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2}; private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0}; + // Helper to initialize a default apfFilter. + private ApfFilter setupApfFilter(IpManager.Callback ipManagerCallback, ApfConfiguration config) + throws Exception { + LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); + LinkProperties lp = new LinkProperties(); + lp.addLinkAddress(link); + TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipManagerCallback, mLog); + apfFilter.setLinkProperties(lp); + return apfFilter; + } + @Test public void testApfFilterIPv4() throws Exception { MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); @@ -766,7 +780,7 @@ public class ApfTest { ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; - TestApfFilter apfFilter = new TestApfFilter(config, ipManagerCallback, mLog); + TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipManagerCallback, mLog); apfFilter.setLinkProperties(lp); byte[] program = ipManagerCallback.getApfProgram(); @@ -818,7 +832,7 @@ public class ApfTest { public void testApfFilterIPv6() throws Exception { MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); ApfConfiguration config = getDefaultConfig(); - TestApfFilter apfFilter = new TestApfFilter(config, ipManagerCallback, mLog); + TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipManagerCallback, mLog); byte[] program = ipManagerCallback.getApfProgram(); // Verify empty IPv6 packet is passed @@ -861,7 +875,7 @@ public class ApfTest { ApfConfiguration config = getDefaultConfig(); config.ieee802_3Filter = DROP_802_3_FRAMES; - TestApfFilter apfFilter = new TestApfFilter(config, ipManagerCallback, mLog); + TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipManagerCallback, mLog); apfFilter.setLinkProperties(lp); byte[] program = ipManagerCallback.getApfProgram(); @@ -925,7 +939,7 @@ public class ApfTest { apfFilter.shutdown(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - apfFilter = new TestApfFilter(config, ipManagerCallback, mLog); + apfFilter = new TestApfFilter(mContext, config, ipManagerCallback, mLog); apfFilter.setLinkProperties(lp); program = ipManagerCallback.getApfProgram(); assertDrop(program, mcastv4packet.array()); @@ -941,16 +955,47 @@ public class ApfTest { } @Test - public void testApfFilter802_3() throws Exception { + public void testApfFilterMulticastPingWhileDozing() throws Exception { MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); - LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); - LinkProperties lp = new LinkProperties(); - lp.addLinkAddress(link); + ApfFilter apfFilter = setupApfFilter(ipManagerCallback, getDefaultConfig()); - ApfConfiguration config = getDefaultConfig(); - TestApfFilter apfFilter = new TestApfFilter(config, ipManagerCallback, mLog); - apfFilter.setLinkProperties(lp); + // Construct a multicast ICMPv6 ECHO request. + final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb}; + ByteBuffer packet = ByteBuffer.wrap(new byte[100]); + packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); + packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); + packet.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ECHO_REQUEST_TYPE); + put(packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr); + + // Normally, we let multicast pings alone... + assertPass(ipManagerCallback.getApfProgram(), packet.array()); + + // ...and even while dozing... + apfFilter.setDozeMode(true); + assertPass(ipManagerCallback.getApfProgram(), packet.array()); + + // ...but when the multicast filter is also enabled, drop the multicast pings to save power. + apfFilter.setMulticastFilter(true); + assertDrop(ipManagerCallback.getApfProgram(), packet.array()); + // However, we should still let through all other ICMPv6 types. + ByteBuffer raPacket = ByteBuffer.wrap(packet.array().clone()); + raPacket.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ROUTER_ADVERTISEMENT); + assertPass(ipManagerCallback.getApfProgram(), raPacket.array()); + + // Now wake up from doze mode to ensure that we no longer drop the packets. + // (The multicast filter is still enabled at this point). + apfFilter.setDozeMode(false); + assertPass(ipManagerCallback.getApfProgram(), packet.array()); + + apfFilter.shutdown(); + } + + @Test + public void testApfFilter802_3() throws Exception { + MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); + ApfConfiguration config = getDefaultConfig(); + ApfFilter apfFilter = setupApfFilter(ipManagerCallback, config); byte[] program = ipManagerCallback.getApfProgram(); // Verify empty packet of 100 zero bytes is passed @@ -970,8 +1015,7 @@ public class ApfTest { ipManagerCallback.resetApfProgramWait(); apfFilter.shutdown(); config.ieee802_3Filter = DROP_802_3_FRAMES; - apfFilter = new TestApfFilter(config, ipManagerCallback, mLog); - apfFilter.setLinkProperties(lp); + apfFilter = setupApfFilter(ipManagerCallback, config); program = ipManagerCallback.getApfProgram(); // Verify that IEEE802.3 frame is dropped @@ -992,18 +1036,13 @@ public class ApfTest { @Test public void testApfFilterEthTypeBL() throws Exception { - MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); - LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); - LinkProperties lp = new LinkProperties(); - lp.addLinkAddress(link); final int[] emptyBlackList = {}; final int[] ipv4BlackList = {ETH_P_IP}; final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6}; + MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); ApfConfiguration config = getDefaultConfig(); - TestApfFilter apfFilter = new TestApfFilter(config, ipManagerCallback, mLog); - apfFilter.setLinkProperties(lp); - + ApfFilter apfFilter = setupApfFilter(ipManagerCallback, config); byte[] program = ipManagerCallback.getApfProgram(); // Verify empty packet of 100 zero bytes is passed @@ -1023,8 +1062,7 @@ public class ApfTest { ipManagerCallback.resetApfProgramWait(); apfFilter.shutdown(); config.ethTypeBlackList = ipv4BlackList; - apfFilter = new TestApfFilter(config, ipManagerCallback, mLog); - apfFilter.setLinkProperties(lp); + apfFilter = setupApfFilter(ipManagerCallback, config); program = ipManagerCallback.getApfProgram(); // Verify that IPv4 frame will be dropped @@ -1039,8 +1077,7 @@ public class ApfTest { ipManagerCallback.resetApfProgramWait(); apfFilter.shutdown(); config.ethTypeBlackList = ipv4Ipv6BlackList; - apfFilter = new TestApfFilter(config, ipManagerCallback, mLog); - apfFilter.setLinkProperties(lp); + apfFilter = setupApfFilter(ipManagerCallback, config); program = ipManagerCallback.getApfProgram(); // Verify that IPv4 frame will be dropped @@ -1081,7 +1118,7 @@ public class ApfTest { ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - TestApfFilter apfFilter = new TestApfFilter(config, ipManagerCallback, mLog); + TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipManagerCallback, mLog); // Verify initially ARP request filter is off, and GARP filter is on. verifyArpFilter(ipManagerCallback.getApfProgram(), PASS); @@ -1205,7 +1242,7 @@ public class ApfTest { ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - TestApfFilter apfFilter = new TestApfFilter(config, ipManagerCallback, mLog); + TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipManagerCallback, mLog); byte[] program = ipManagerCallback.getApfProgram(); final int ROUTER_LIFETIME = 1000; @@ -1351,7 +1388,7 @@ public class ApfTest { ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - TestApfFilter apfFilter = new TestApfFilter(config, cb, mLog); + TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog); for (int i = 0; i < 1000; i++) { byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; r.nextBytes(packet); @@ -1372,7 +1409,7 @@ public class ApfTest { ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; - TestApfFilter apfFilter = new TestApfFilter(config, cb, mLog); + TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog); for (int i = 0; i < 1000; i++) { byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; r.nextBytes(packet); |