diff options
46 files changed, 2752 insertions, 896 deletions
diff --git a/lowpan/Android.mk b/lowpan/Android.mk deleted file mode 100644 index 0079958d5b83..000000000000 --- a/lowpan/Android.mk +++ /dev/null @@ -1,33 +0,0 @@ -# -# 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. -# - -LOCAL_PATH := $(call my-dir) - -ifneq (,$(findstring lowpan/java,$(FRAMEWORKS_BASE_SUBDIRS))) -include $(CLEAR_VARS) -LOCAL_MODULE := libandroid_net_lowpan -LOCAL_MODULE_TAGS := optional -LOCAL_SHARED_LIBRARIES += libbase -LOCAL_SHARED_LIBRARIES += libbinder -LOCAL_SHARED_LIBRARIES += libutils -LOCAL_AIDL_INCLUDES += frameworks/native/aidl/binder -LOCAL_AIDL_INCLUDES += frameworks/base/lowpan/java -LOCAL_AIDL_INCLUDES += frameworks/base/core/java -LOCAL_SRC_FILES += $(call all-Iaidl-files-under, java/android/net/lowpan) -include $(BUILD_SHARED_LIBRARY) - -include $(call all-makefiles-under,$(LOCAL_PATH)) -endif diff --git a/lowpan/java/android/net/lowpan/ILowpanInterface.aidl b/lowpan/java/android/net/lowpan/ILowpanInterface.aidl index 329e9fa1d743..603dc3cfe641 100644 --- a/lowpan/java/android/net/lowpan/ILowpanInterface.aidl +++ b/lowpan/java/android/net/lowpan/ILowpanInterface.aidl @@ -16,103 +16,39 @@ package android.net.lowpan; +import android.net.IpPrefix; +import android.net.lowpan.ILowpanEnergyScanCallback; import android.net.lowpan.ILowpanInterfaceListener; import android.net.lowpan.ILowpanNetScanCallback; -import android.net.lowpan.ILowpanEnergyScanCallback; -import android.os.PersistableBundle; -import android.net.IpPrefix; +import android.net.lowpan.LowpanBeaconInfo; +import android.net.lowpan.LowpanChannelInfo; +import android.net.lowpan.LowpanCredential; +import android.net.lowpan.LowpanIdentity; +import android.net.lowpan.LowpanProvision; /** {@hide} */ interface ILowpanInterface { - ////////////////////////////////////////////////////////////////////////// - // Permission String Constants - - /* These are here for the sake of C++ interface implementations. */ + // These are here for the sake of C++ interface implementations. const String PERM_ACCESS_LOWPAN_STATE = "android.permission.ACCESS_LOWPAN_STATE"; const String PERM_CHANGE_LOWPAN_STATE = "android.permission.CHANGE_LOWPAN_STATE"; const String PERM_READ_LOWPAN_CREDENTIAL = "android.permission.READ_LOWPAN_CREDENTIAL"; - ////////////////////////////////////////////////////////////////////////// - // Property Key Constants - - /** Type: Boolean */ - const String KEY_INTERFACE_ENABLED = "android.net.lowpan.property.INTERFACE_ENABLED"; - - /** Type: Boolean */ - const String KEY_INTERFACE_UP = "android.net.lowpan.property.INTERFACE_UP"; - - /** Type: Boolean */ - const String KEY_INTERFACE_COMMISSIONED = "android.net.lowpan.property.INTERFACE_COMMISSIONED"; - - /** Type: Boolean */ - const String KEY_INTERFACE_CONNECTED = "android.net.lowpan.property.INTERFACE_CONNECTED"; - - /** Type: String */ - const String KEY_INTERFACE_STATE = "android.net.lowpan.property.INTERFACE_STATE"; - - /** Type: String */ - const String KEY_NETWORK_NAME = "android.net.lowpan.property.NETWORK_NAME"; - - /** Type: Integer */ - const String KEY_NETWORK_TYPE = "android.net.lowpan.property.NETWORK_TYPE"; - - /** Type: Integer */ - const String KEY_NETWORK_PANID = "android.net.lowpan.property.NETWORK_PANID"; - - /** Type: byte[] */ - const String KEY_NETWORK_XPANID = "android.net.lowpan.property.NETWORK_XPANID"; - - /** Type: String */ - const String KEY_NETWORK_ROLE = "android.net.lowpan.property.NETWORK_ROLE"; - - /** Type: byte[] */ - const String KEY_NETWORK_MASTER_KEY = "android.net.lowpan.property.NETWORK_MASTER_KEY"; - - /** Type: Integer */ - const String KEY_NETWORK_MASTER_KEY_INDEX - = "android.net.lowpan.property.NETWORK_MASTER_KEY_INDEX"; - - /** Type: int[] */ - const String KEY_SUPPORTED_CHANNELS = "android.net.lowpan.property.SUPPORTED_CHANNELS"; - - /** Type: Integer */ - const String KEY_CHANNEL = "android.net.lowpan.property.CHANNEL"; - - /** Type: int[] */ + /** + * Channel mask key. + * Used for setting a channel mask when starting a scan. + * Type: int[] + * */ const String KEY_CHANNEL_MASK = "android.net.lowpan.property.CHANNEL_MASK"; - /** Type: Integer */ + /** + * Max Transmit Power Key. + * Used for setting the maximum transmit power when starting a network scan. + * Type: Integer + * */ const String KEY_MAX_TX_POWER = "android.net.lowpan.property.MAX_TX_POWER"; - /** Type: Integer */ - const String KEY_RSSI = "android.net.lowpan.property.RSSI"; - - /** Type: Integer */ - const String KEY_LQI = "android.net.lowpan.property.LQI"; - - /** Type: byte[] */ - const String KEY_BEACON_ADDRESS = "android.net.lowpan.property.BEACON_ORIGIN_ADDRESS"; - - /** Type: Boolean */ - const String KEY_BEACON_CAN_ASSIST = "android.net.lowpan.property.BEACON_CAN_ASSIST"; - - /** Type: String */ - const String DRIVER_VERSION = "android.net.lowpan.property.DRIVER_VERSION"; - - /** Type: String */ - const String NCP_VERSION = "android.net.lowpan.property.NCP_VERSION"; - - /** Type: byte[] - * @hide */ - const String KEY_EXTENDED_ADDRESS = "android.net.lowpan.property.EXTENDED_ADDRESS"; - - /** Type: byte[] - * @hide */ - const String KEY_MAC_ADDRESS = "android.net.lowpan.property.MAC_ADDRESS"; - - ////////////////////////////////////////////////////////////////////////// // Interface States const String STATE_OFFLINE = "offline"; @@ -121,58 +57,87 @@ interface ILowpanInterface { const String STATE_ATTACHED = "attached"; const String STATE_FAULT = "fault"; - ////////////////////////////////////////////////////////////////////////// // Device Roles const String ROLE_END_DEVICE = "end-device"; const String ROLE_ROUTER = "router"; const String ROLE_SLEEPY_END_DEVICE = "sleepy-end-device"; const String ROLE_SLEEPY_ROUTER = "sleepy-router"; - const String ROLE_UNKNOWN = "unknown"; + const String ROLE_LEADER = "leader"; + const String ROLE_COORDINATOR = "coordinator"; + const String ROLE_DETACHED = "detached"; + + const String NETWORK_TYPE_UNKNOWN = "unknown"; + + /** + * Network type for Thread 1.x networks. + * + * @see android.net.lowpan.LowpanIdentity#getType + * @see #getLowpanIdentity + */ + const String NETWORK_TYPE_THREAD_V1 = "org.threadgroup.thread.v1"; - ////////////////////////////////////////////////////////////////////////// // Service-Specific Error Code Constants const int ERROR_UNSPECIFIED = 1; const int ERROR_INVALID_ARGUMENT = 2; const int ERROR_DISABLED = 3; const int ERROR_WRONG_STATE = 4; - const int ERROR_INVALID_TYPE = 5; - const int ERROR_INVALID_VALUE = 6; - const int ERROR_TIMEOUT = 7; - const int ERROR_IO_FAILURE = 8; - const int ERROR_BUSY = 9; - const int ERROR_ALREADY = 10; - const int ERROR_CANCELED = 11; - const int ERROR_CREDENTIAL_NEEDED = 12; - const int ERROR_FEATURE_NOT_SUPPORTED = 14; - const int ERROR_PROPERTY_NOT_FOUND = 16; - const int ERROR_JOIN_FAILED_UNKNOWN = 18; - const int ERROR_JOIN_FAILED_AT_SCAN = 19; - const int ERROR_JOIN_FAILED_AT_AUTH = 20; - const int ERROR_FORM_FAILED_AT_SCAN = 21; - const int ERROR_NCP_PROBLEM = 27; - const int ERROR_PERMISSION_DENIED = 28; - - ////////////////////////////////////////////////////////////////////////// + const int ERROR_TIMEOUT = 5; + const int ERROR_IO_FAILURE = 6; + const int ERROR_NCP_PROBLEM = 7; + const int ERROR_BUSY = 8; + const int ERROR_ALREADY = 9; + const int ERROR_CANCELED = 10; + const int ERROR_FEATURE_NOT_SUPPORTED = 11; + const int ERROR_JOIN_FAILED_UNKNOWN = 12; + const int ERROR_JOIN_FAILED_AT_SCAN = 13; + const int ERROR_JOIN_FAILED_AT_AUTH = 14; + const int ERROR_FORM_FAILED_AT_SCAN = 15; + // Methods @utf8InCpp String getName(); - void join(in Map parameters); - void form(in Map parameters); + @utf8InCpp String getNcpVersion(); + @utf8InCpp String getDriverVersion(); + LowpanChannelInfo[] getSupportedChannels(); + @utf8InCpp String[] getSupportedNetworkTypes(); + byte[] getMacAddress(); + + boolean isEnabled(); + void setEnabled(boolean enabled); + + boolean isUp(); + boolean isCommissioned(); + boolean isConnected(); + @utf8InCpp String getState(); + + @utf8InCpp String getRole(); + @utf8InCpp String getPartitionId(); + byte[] getExtendedAddress(); + + LowpanIdentity getLowpanIdentity(); + LowpanCredential getLowpanCredential(); + + @utf8InCpp String[] getLinkAddresses(); + IpPrefix[] getLinkNetworks(); + + void join(in LowpanProvision provision); + void form(in LowpanProvision provision); + void attach(in LowpanProvision provision); void leave(); void reset(); + void startCommissioningSession(in LowpanBeaconInfo beaconInfo); + void closeCommissioningSession(); + oneway void sendToCommissioner(in byte[] packet); + void beginLowPower(); - void pollForData(); + oneway void pollForData(); oneway void onHostWake(); - @utf8InCpp String[] getPropertyKeys(); - Map getProperties(in @utf8InCpp String[] keys); - void setProperties(in Map properties); - void addListener(ILowpanInterfaceListener listener); oneway void removeListener(ILowpanInterfaceListener listener); @@ -182,14 +147,9 @@ interface ILowpanInterface { void startEnergyScan(in Map properties, ILowpanEnergyScanCallback listener); oneway void stopEnergyScan(); - String[] copyLinkAddresses(); - IpPrefix[] copyLinkNetworks(); - void addOnMeshPrefix(in IpPrefix prefix, int flags); oneway void removeOnMeshPrefix(in IpPrefix prefix); void addExternalRoute(in IpPrefix prefix, int flags); oneway void removeExternalRoute(in IpPrefix prefix); - - @utf8InCpp String getPropertyAsString(@utf8InCpp String key); } diff --git a/lowpan/java/android/net/lowpan/ILowpanInterfaceListener.aidl b/lowpan/java/android/net/lowpan/ILowpanInterfaceListener.aidl index 0ae01a1873b5..5e4049a0fab8 100644 --- a/lowpan/java/android/net/lowpan/ILowpanInterfaceListener.aidl +++ b/lowpan/java/android/net/lowpan/ILowpanInterfaceListener.aidl @@ -17,14 +17,29 @@ package android.net.lowpan; import android.net.IpPrefix; +import android.net.lowpan.LowpanIdentity; /** {@hide} */ interface ILowpanInterfaceListener { - oneway void onPropertiesChanged(in Map properties); + oneway void onEnabledChanged(boolean value); - oneway void onLinkNetworkAdded(in IpPrefix prefix); - oneway void onLinkNetworkRemoved(in IpPrefix prefix); + oneway void onConnectedChanged(boolean value); - oneway void onLinkAddressAdded(in String address); - oneway void onLinkAddressRemoved(in String address); + oneway void onUpChanged(boolean value); + + oneway void onRoleChanged(@utf8InCpp String value); + + oneway void onStateChanged(@utf8InCpp String value); + + oneway void onLowpanIdentityChanged(in LowpanIdentity value); + + oneway void onLinkNetworkAdded(in IpPrefix value); + + oneway void onLinkNetworkRemoved(in IpPrefix value); + + oneway void onLinkAddressAdded(@utf8InCpp String value); + + oneway void onLinkAddressRemoved(@utf8InCpp String value); + + oneway void onReceiveFromCommissioner(in byte[] packet); } diff --git a/lowpan/java/android/net/lowpan/ILowpanNetScanCallback.aidl b/lowpan/java/android/net/lowpan/ILowpanNetScanCallback.aidl index c20a6f8110c8..9743fce0b128 100644 --- a/lowpan/java/android/net/lowpan/ILowpanNetScanCallback.aidl +++ b/lowpan/java/android/net/lowpan/ILowpanNetScanCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * 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. @@ -16,8 +16,10 @@ package android.net.lowpan; +import android.net.lowpan.LowpanBeaconInfo; + /** {@hide} */ interface ILowpanNetScanCallback { - oneway void onNetScanBeacon(in Map parameters); + oneway void onNetScanBeacon(in LowpanBeaconInfo beacon); oneway void onNetScanFinished(); } diff --git a/lowpan/java/android/net/lowpan/InterfaceDisabledException.java b/lowpan/java/android/net/lowpan/InterfaceDisabledException.java new file mode 100644 index 000000000000..e917d4521bae --- /dev/null +++ b/lowpan/java/android/net/lowpan/InterfaceDisabledException.java @@ -0,0 +1,41 @@ +/* + * 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.lowpan; + +/** + * Exception indicating this operation requires the interface to be enabled. + * + * @see LowpanInterface + * @hide + */ +// @SystemApi +public class InterfaceDisabledException extends LowpanException { + + public InterfaceDisabledException() {} + + public InterfaceDisabledException(String message) { + super(message); + } + + public InterfaceDisabledException(String message, Throwable cause) { + super(message, cause); + } + + protected InterfaceDisabledException(Exception cause) { + super(cause); + } +} diff --git a/lowpan/java/android/net/lowpan/JoinFailedAtAuthException.java b/lowpan/java/android/net/lowpan/JoinFailedAtAuthException.java new file mode 100644 index 000000000000..7aceb71e2a85 --- /dev/null +++ b/lowpan/java/android/net/lowpan/JoinFailedAtAuthException.java @@ -0,0 +1,41 @@ +/* + * 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.lowpan; + +/** + * Exception indicating the join operation was unable to find the given network. + * + * @see LowpanInterface + * @hide + */ +// @SystemApi +public class JoinFailedAtAuthException extends JoinFailedException { + + public JoinFailedAtAuthException() {} + + public JoinFailedAtAuthException(String message) { + super(message); + } + + public JoinFailedAtAuthException(String message, Throwable cause) { + super(message, cause); + } + + public JoinFailedAtAuthException(Exception cause) { + super(cause); + } +} diff --git a/lowpan/java/android/net/lowpan/JoinFailedAtScanException.java b/lowpan/java/android/net/lowpan/JoinFailedAtScanException.java new file mode 100644 index 000000000000..a4346f98d719 --- /dev/null +++ b/lowpan/java/android/net/lowpan/JoinFailedAtScanException.java @@ -0,0 +1,41 @@ +/* + * 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.lowpan; + +/** + * Exception indicating the join operation was unable to find the given network. + * + * @see LowpanInterface + * @hide + */ +// @SystemApi +public class JoinFailedAtScanException extends JoinFailedException { + + public JoinFailedAtScanException() {} + + public JoinFailedAtScanException(String message) { + super(message); + } + + public JoinFailedAtScanException(String message, Throwable cause) { + super(message, cause); + } + + public JoinFailedAtScanException(Exception cause) { + super(cause); + } +} diff --git a/lowpan/java/android/net/lowpan/JoinFailedException.java b/lowpan/java/android/net/lowpan/JoinFailedException.java new file mode 100644 index 000000000000..e51d3829f9f1 --- /dev/null +++ b/lowpan/java/android/net/lowpan/JoinFailedException.java @@ -0,0 +1,41 @@ +/* + * 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.lowpan; + +/** + * Exception indicating the join operation has failed. + * + * @see LowpanInterface + * @hide + */ +// @SystemApi +public class JoinFailedException extends LowpanException { + + public JoinFailedException() {} + + public JoinFailedException(String message) { + super(message); + } + + public JoinFailedException(String message, Throwable cause) { + super(message, cause); + } + + protected JoinFailedException(Exception cause) { + super(cause); + } +} diff --git a/lowpan/java/android/net/lowpan/LowpanBeaconInfo.aidl b/lowpan/java/android/net/lowpan/LowpanBeaconInfo.aidl new file mode 100644 index 000000000000..9464fea02d18 --- /dev/null +++ b/lowpan/java/android/net/lowpan/LowpanBeaconInfo.aidl @@ -0,0 +1,19 @@ +/** + * 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.lowpan; + +parcelable LowpanBeaconInfo cpp_header "android/net/lowpan/LowpanBeaconInfo.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanBeaconInfo.java b/lowpan/java/android/net/lowpan/LowpanBeaconInfo.java index e18abd5bf23f..345a4c504b5b 100644 --- a/lowpan/java/android/net/lowpan/LowpanBeaconInfo.java +++ b/lowpan/java/android/net/lowpan/LowpanBeaconInfo.java @@ -16,9 +16,12 @@ package android.net.lowpan; +import android.os.Parcel; +import android.os.Parcelable; import com.android.internal.util.HexDump; +import java.util.Arrays; import java.util.Collection; -import java.util.Map; +import java.util.Objects; import java.util.TreeSet; /** @@ -27,70 +30,93 @@ import java.util.TreeSet; * @hide */ // @SystemApi -public class LowpanBeaconInfo extends LowpanIdentity { +public class LowpanBeaconInfo implements Parcelable { + public static final int UNKNOWN_RSSI = Integer.MAX_VALUE; + public static final int UNKNOWN_LQI = 0; - private int mRssi = UNKNOWN; - private int mLqi = UNKNOWN; + private LowpanIdentity mIdentity; + private int mRssi = UNKNOWN_RSSI; + private int mLqi = UNKNOWN_LQI; private byte[] mBeaconAddress = null; private final TreeSet<Integer> mFlags = new TreeSet<>(); public static final int FLAG_CAN_ASSIST = 1; - static class Builder extends LowpanIdentity.Builder { - private final LowpanBeaconInfo identity = new LowpanBeaconInfo(); + /** @hide */ + public static class Builder { + final LowpanIdentity.Builder mIdentityBuilder = new LowpanIdentity.Builder(); + final LowpanBeaconInfo mBeaconInfo = new LowpanBeaconInfo(); + + public Builder setLowpanIdentity(LowpanIdentity x) { + mIdentityBuilder.setLowpanIdentity(x); + return this; + } + + public Builder setName(String x) { + mIdentityBuilder.setName(x); + return this; + } + + public Builder setXpanid(byte x[]) { + mIdentityBuilder.setXpanid(x); + return this; + } + + public Builder setPanid(int x) { + mIdentityBuilder.setPanid(x); + return this; + } + + public Builder setChannel(int x) { + mIdentityBuilder.setChannel(x); + return this; + } + + public Builder setType(String x) { + mIdentityBuilder.setType(x); + return this; + } public Builder setRssi(int x) { - identity.mRssi = x; + mBeaconInfo.mRssi = x; return this; } public Builder setLqi(int x) { - identity.mLqi = x; + mBeaconInfo.mLqi = x; return this; } public Builder setBeaconAddress(byte x[]) { - identity.mBeaconAddress = x.clone(); + mBeaconInfo.mBeaconAddress = (x != null ? x.clone() : null); return this; } public Builder setFlag(int x) { - identity.mFlags.add(x); + mBeaconInfo.mFlags.add(x); return this; } public Builder setFlags(Collection<Integer> x) { - identity.mFlags.addAll(x); - return this; - } - - /** @hide */ - Builder updateFromMap(Map map) { - if (map.containsKey(LowpanProperties.KEY_RSSI.getName())) { - setRssi(LowpanProperties.KEY_RSSI.getFromMap(map)); - } - if (map.containsKey(LowpanProperties.KEY_LQI.getName())) { - setLqi(LowpanProperties.KEY_LQI.getFromMap(map)); - } - if (map.containsKey(LowpanProperties.KEY_BEACON_ADDRESS.getName())) { - setBeaconAddress(LowpanProperties.KEY_BEACON_ADDRESS.getFromMap(map)); - } - identity.mFlags.clear(); - if (map.containsKey(LowpanProperties.KEY_BEACON_CAN_ASSIST.getName()) - && LowpanProperties.KEY_BEACON_CAN_ASSIST.getFromMap(map).booleanValue()) { - setFlag(FLAG_CAN_ASSIST); - } - super.updateFromMap(map); + mBeaconInfo.mFlags.addAll(x); return this; } public LowpanBeaconInfo build() { - return identity; + mBeaconInfo.mIdentity = mIdentityBuilder.build(); + if (mBeaconInfo.mBeaconAddress == null) { + mBeaconInfo.mBeaconAddress = new byte[0]; + } + return mBeaconInfo; } } private LowpanBeaconInfo() {} + public LowpanIdentity getLowpanIdentity() { + return mIdentity; + } + public int getRssi() { return mRssi; } @@ -112,26 +138,21 @@ public class LowpanBeaconInfo extends LowpanIdentity { } @Override - void addToMap(Map<String, Object> parameters) { - super.addToMap(parameters); - } - - @Override public String toString() { StringBuffer sb = new StringBuffer(); - sb.append(super.toString()); + sb.append(mIdentity.toString()); - if (mRssi != UNKNOWN) { - sb.append(", RSSI: ").append(mRssi); + if (mRssi != UNKNOWN_RSSI) { + sb.append(", RSSI:").append(mRssi).append("dBm"); } - if (mLqi != UNKNOWN) { - sb.append(", LQI: ").append(mLqi); + if (mLqi != UNKNOWN_LQI) { + sb.append(", LQI:").append(mLqi); } - if (mBeaconAddress != null) { - sb.append(", BeaconAddress: ").append(HexDump.toHexString(mBeaconAddress)); + if (mBeaconAddress.length > 0) { + sb.append(", BeaconAddress:").append(HexDump.toHexString(mBeaconAddress)); } for (Integer flag : mFlags) { @@ -147,4 +168,67 @@ public class LowpanBeaconInfo extends LowpanIdentity { return sb.toString(); } + + @Override + public int hashCode() { + return Objects.hash(mIdentity, mRssi, mLqi, Arrays.hashCode(mBeaconAddress), mFlags); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof LowpanBeaconInfo)) { + return false; + } + LowpanBeaconInfo rhs = (LowpanBeaconInfo) obj; + return mIdentity.equals(rhs.mIdentity) + && Arrays.equals(mBeaconAddress, rhs.mBeaconAddress) + && mRssi == rhs.mRssi + && mLqi == rhs.mLqi + && mFlags.equals(rhs.mFlags); + } + + /** Implement the Parcelable interface. */ + @Override + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface. */ + @Override + public void writeToParcel(Parcel dest, int flags) { + mIdentity.writeToParcel(dest, flags); + dest.writeInt(mRssi); + dest.writeInt(mLqi); + dest.writeByteArray(mBeaconAddress); + + dest.writeInt(mFlags.size()); + for (Integer val : mFlags) { + dest.writeInt(val); + } + } + + /** Implement the Parcelable interface. */ + public static final Creator<LowpanBeaconInfo> CREATOR = + new Creator<LowpanBeaconInfo>() { + public LowpanBeaconInfo createFromParcel(Parcel in) { + Builder builder = new Builder(); + + builder.setLowpanIdentity(LowpanIdentity.CREATOR.createFromParcel(in)); + + builder.setRssi(in.readInt()); + builder.setLqi(in.readInt()); + + builder.setBeaconAddress(in.createByteArray()); + + for (int i = in.readInt(); i > 0; i--) { + builder.setFlag(in.readInt()); + } + + return builder.build(); + } + + public LowpanBeaconInfo[] newArray(int size) { + return new LowpanBeaconInfo[size]; + } + }; } diff --git a/lowpan/java/android/net/lowpan/LowpanChannelInfo.aidl b/lowpan/java/android/net/lowpan/LowpanChannelInfo.aidl new file mode 100644 index 000000000000..0676deb6c6df --- /dev/null +++ b/lowpan/java/android/net/lowpan/LowpanChannelInfo.aidl @@ -0,0 +1,19 @@ +/** + * 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.lowpan; + +parcelable LowpanChannelInfo cpp_header "android/net/lowpan/LowpanChannelInfo.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanChannelInfo.java b/lowpan/java/android/net/lowpan/LowpanChannelInfo.java index 621affee6d06..52b1c6d6a3e3 100644 --- a/lowpan/java/android/net/lowpan/LowpanChannelInfo.java +++ b/lowpan/java/android/net/lowpan/LowpanChannelInfo.java @@ -16,22 +16,66 @@ package android.net.lowpan; -/** Provides detailed information about a given channel. */ +import android.os.Parcel; +import android.os.Parcelable; +import java.util.Objects; + +/** + * Provides detailed information about a given channel. + * + * @hide + */ // @SystemApi -public class LowpanChannelInfo { +public class LowpanChannelInfo implements Parcelable { public static final int UNKNOWN_POWER = Integer.MAX_VALUE; + public static final float UNKNOWN_FREQUENCY = 0.0f; + public static final float UNKNOWN_BANDWIDTH = 0.0f; - // Instance Variables - - private String mName = null; private int mIndex = 0; - private boolean mIsMaskedByRegulatoryDomain = false; - private float mSpectrumCenterFrequency = 0.0f; - private float mSpectrumBandwidth = 0.0f; + private String mName = null; + private float mSpectrumCenterFrequency = UNKNOWN_FREQUENCY; + private float mSpectrumBandwidth = UNKNOWN_BANDWIDTH; private int mMaxTransmitPower = UNKNOWN_POWER; + private boolean mIsMaskedByRegulatoryDomain = false; + + /** @hide */ + public static LowpanChannelInfo getChannelInfoForIeee802154Page0(int index) { + LowpanChannelInfo info = new LowpanChannelInfo(); + + if (index < 0) { + info = null; + + } else if (index == 0) { + info.mSpectrumCenterFrequency = 868300000.0f; + info.mSpectrumBandwidth = 600000.0f; + + } else if (index < 11) { + info.mSpectrumCenterFrequency = 906000000.0f - (2000000.0f * 1) + 2000000.0f * (index); + info.mSpectrumBandwidth = 0; // Unknown + + } else if (index < 26) { + info.mSpectrumCenterFrequency = + 2405000000.0f - (5000000.0f * 11) + 5000000.0f * (index); + info.mSpectrumBandwidth = 2000000.0f; + + } else { + info = null; + } + + info.mName = Integer.toString(index); + + return info; + } + + private LowpanChannelInfo() {} - // Public Getters and Setters + private LowpanChannelInfo(int index, String name, float cf, float bw) { + mIndex = index; + mName = name; + mSpectrumCenterFrequency = cf; + mSpectrumBandwidth = bw; + } public String getName() { return mName; @@ -63,22 +107,110 @@ public class LowpanChannelInfo { sb.append("Channel ").append(mIndex); - if (mName != null) { + if (mName != null && !mName.equals(Integer.toString(mIndex))) { sb.append(" (").append(mName).append(")"); } if (mSpectrumCenterFrequency > 0.0f) { - sb.append(", SpectrumCenterFrequency: ").append(mSpectrumCenterFrequency).append("Hz"); + if (mSpectrumCenterFrequency > 1000000000.0f) { + sb.append(", SpectrumCenterFrequency: ") + .append(mSpectrumCenterFrequency / 1000000000.0f) + .append("GHz"); + } else if (mSpectrumCenterFrequency > 1000000.0f) { + sb.append(", SpectrumCenterFrequency: ") + .append(mSpectrumCenterFrequency / 1000000.0f) + .append("MHz"); + } else { + sb.append(", SpectrumCenterFrequency: ") + .append(mSpectrumCenterFrequency / 1000.0f) + .append("kHz"); + } } if (mSpectrumBandwidth > 0.0f) { - sb.append(", SpectrumBandwidth: ").append(mSpectrumBandwidth).append("Hz"); + if (mSpectrumBandwidth > 1000000000.0f) { + sb.append(", SpectrumBandwidth: ") + .append(mSpectrumBandwidth / 1000000000.0f) + .append("GHz"); + } else if (mSpectrumBandwidth > 1000000.0f) { + sb.append(", SpectrumBandwidth: ") + .append(mSpectrumBandwidth / 1000000.0f) + .append("MHz"); + } else { + sb.append(", SpectrumBandwidth: ") + .append(mSpectrumBandwidth / 1000.0f) + .append("kHz"); + } } if (mMaxTransmitPower != UNKNOWN_POWER) { - sb.append(", MaxTransmitPower: ").append(mMaxTransmitPower); + sb.append(", MaxTransmitPower: ").append(mMaxTransmitPower).append("dBm"); } return sb.toString(); } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof LowpanChannelInfo)) { + return false; + } + LowpanChannelInfo rhs = (LowpanChannelInfo) obj; + return Objects.equals(mName, rhs.mName) + && mIndex == rhs.mIndex + && mIsMaskedByRegulatoryDomain == rhs.mIsMaskedByRegulatoryDomain + && mSpectrumCenterFrequency == rhs.mSpectrumCenterFrequency + && mSpectrumBandwidth == rhs.mSpectrumBandwidth + && mMaxTransmitPower == rhs.mMaxTransmitPower; + } + + @Override + public int hashCode() { + return Objects.hash( + mName, + mIndex, + mIsMaskedByRegulatoryDomain, + mSpectrumCenterFrequency, + mSpectrumBandwidth, + mMaxTransmitPower); + } + + /** Implement the Parcelable interface. */ + @Override + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface. */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mIndex); + dest.writeString(mName); + dest.writeFloat(mSpectrumCenterFrequency); + dest.writeFloat(mSpectrumBandwidth); + dest.writeInt(mMaxTransmitPower); + dest.writeBoolean(mIsMaskedByRegulatoryDomain); + } + + /** Implement the Parcelable interface. */ + public static final Creator<LowpanChannelInfo> CREATOR = + new Creator<LowpanChannelInfo>() { + + public LowpanChannelInfo createFromParcel(Parcel in) { + LowpanChannelInfo info = new LowpanChannelInfo(); + + info.mIndex = in.readInt(); + info.mName = in.readString(); + info.mSpectrumCenterFrequency = in.readFloat(); + info.mSpectrumBandwidth = in.readFloat(); + info.mMaxTransmitPower = in.readInt(); + info.mIsMaskedByRegulatoryDomain = in.readBoolean(); + + return info; + } + + public LowpanChannelInfo[] newArray(int size) { + return new LowpanChannelInfo[size]; + } + }; } diff --git a/lowpan/java/android/net/lowpan/LowpanCommissioningSession.java b/lowpan/java/android/net/lowpan/LowpanCommissioningSession.java index ee75f1aece5c..8f75e8db6243 100644 --- a/lowpan/java/android/net/lowpan/LowpanCommissioningSession.java +++ b/lowpan/java/android/net/lowpan/LowpanCommissioningSession.java @@ -18,9 +18,11 @@ package android.net.lowpan; import android.annotation.NonNull; import android.annotation.Nullable; -import android.net.Network; +import android.net.IpPrefix; +import android.os.DeadObjectException; import android.os.Handler; -import java.net.InetSocketAddress; +import android.os.Looper; +import android.os.RemoteException; /** * Commissioning Session. @@ -31,8 +33,15 @@ import java.net.InetSocketAddress; * @hide */ // @SystemApi -public abstract class LowpanCommissioningSession { - public LowpanCommissioningSession() {} +public class LowpanCommissioningSession { + + private final ILowpanInterface mBinder; + private final LowpanBeaconInfo mBeaconInfo; + private final ILowpanInterfaceListener mInternalCallback = new InternalCallback(); + private final Looper mLooper; + private Handler mHandler; + private Callback mCallback = null; + private volatile boolean mIsClosed = false; /** * Callback base class for {@link LowpanCommissioningSession} @@ -40,34 +49,175 @@ public abstract class LowpanCommissioningSession { * @hide */ // @SystemApi - public static abstract class Callback { + public abstract static class Callback { public void onReceiveFromCommissioner(@NonNull byte[] packet) {}; public void onClosed() {}; } + private class InternalCallback extends ILowpanInterfaceListener.Stub { + @Override + public void onStateChanged(String value) { + if (!mIsClosed) { + switch (value) { + case ILowpanInterface.STATE_OFFLINE: + case ILowpanInterface.STATE_FAULT: + synchronized (LowpanCommissioningSession.this) { + lockedCleanup(); + } + } + } + } + + @Override + public void onReceiveFromCommissioner(byte[] packet) { + mHandler.post( + () -> { + synchronized (LowpanCommissioningSession.this) { + if (!mIsClosed && (mCallback != null)) { + mCallback.onReceiveFromCommissioner(packet); + } + } + }); + } + + // We ignore all other callbacks. + @Override + public void onEnabledChanged(boolean value) {} + + @Override + public void onConnectedChanged(boolean value) {} + + @Override + public void onUpChanged(boolean value) {} + + @Override + public void onRoleChanged(String value) {} + + @Override + public void onLowpanIdentityChanged(LowpanIdentity value) {} + + @Override + public void onLinkNetworkAdded(IpPrefix value) {} + + @Override + public void onLinkNetworkRemoved(IpPrefix value) {} + + @Override + public void onLinkAddressAdded(String value) {} + + @Override + public void onLinkAddressRemoved(String value) {} + } + + LowpanCommissioningSession( + ILowpanInterface binder, LowpanBeaconInfo beaconInfo, Looper looper) { + mBinder = binder; + mBeaconInfo = beaconInfo; + mLooper = looper; + + if (mLooper != null) { + mHandler = new Handler(mLooper); + } else { + mHandler = new Handler(); + } + + try { + mBinder.addListener(mInternalCallback); + + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); + } + } + + private void lockedCleanup() { + // Note: this method is only called from synchronized contexts. + + if (!mIsClosed) { + try { + mBinder.removeListener(mInternalCallback); + + } catch (DeadObjectException x) { + /* We don't care if we receive a DOE at this point. + * DOE is as good as success as far as we are concerned. + */ + + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); + } + + if (mCallback != null) { + mHandler.post(() -> mCallback.onClosed()); + } + } + + mCallback = null; + mIsClosed = true; + } + /** TODO: doc */ @NonNull - public abstract LowpanBeaconInfo getBeaconInfo(); + public LowpanBeaconInfo getBeaconInfo() { + return mBeaconInfo; + } /** TODO: doc */ - public abstract void sendToCommissioner(@NonNull byte[] packet); + public void sendToCommissioner(@NonNull byte[] packet) { + if (!mIsClosed) { + try { + mBinder.sendToCommissioner(packet); + + } catch (DeadObjectException x) { + /* This method is a best-effort delivery. + * We don't care if we receive a DOE at this point. + */ + + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); + } + } + } /** TODO: doc */ - public abstract void setCallback(@Nullable Callback cb, @Nullable Handler handler); + public synchronized void setCallback(@Nullable Callback cb, @Nullable Handler handler) { + if (!mIsClosed) { + /* This class can be created with or without a default looper. + * Also, this method can be called with or without a specific + * handler. If a handler is specified, it is to always be used. + * Otherwise, if there was a Looper specified when this object + * was created, we create a new handle based on that looper. + * Otherwise we just create a default handler object. Since we + * don't really know how the previous handler was created, we + * end up always replacing it here. This isn't a huge problem + * because this method should be called infrequently. + */ + if (handler != null) { + mHandler = handler; + } else if (mLooper != null) { + mHandler = new Handler(mLooper); + } else { + mHandler = new Handler(); + } + mCallback = cb; + } + } /** TODO: doc */ - public abstract void close(); + public synchronized void close() { + if (!mIsClosed) { + try { + mBinder.closeCommissioningSession(); - /** - * This method is largely for Nest Weave, as an alternative to {@link #sendToCommissioner()} - * and @{link Callback#onReceiveFromCommissioner()}. - * - * <p>When used with the Network instance obtained from getNetwork(), the caller can use the - * given InetSocketAddress to communicate with the commissioner using a UDP (or, under certain - * circumstances, TCP) socket. - */ - public abstract @Nullable InetSocketAddress getInetSocketAddress(); + lockedCleanup(); - public abstract @Nullable Network getNetwork(); + } catch (DeadObjectException x) { + /* We don't care if we receive a DOE at this point. + * DOE is as good as success as far as we are concerned. + */ + + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); + } + } + } } diff --git a/lowpan/java/android/net/lowpan/LowpanCredential.aidl b/lowpan/java/android/net/lowpan/LowpanCredential.aidl new file mode 100644 index 000000000000..af0c2d63474a --- /dev/null +++ b/lowpan/java/android/net/lowpan/LowpanCredential.aidl @@ -0,0 +1,19 @@ +/** + * 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.lowpan; + +parcelable LowpanCredential cpp_header "android/net/lowpan/LowpanCredential.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanCredential.java b/lowpan/java/android/net/lowpan/LowpanCredential.java index ca8602151515..e9126f9f2f7b 100644 --- a/lowpan/java/android/net/lowpan/LowpanCredential.java +++ b/lowpan/java/android/net/lowpan/LowpanCredential.java @@ -16,7 +16,11 @@ package android.net.lowpan; -import java.util.Map; +import android.os.Parcel; +import android.os.Parcelable; +import com.android.internal.util.HexDump; +import java.util.Arrays; +import java.util.Objects; /** * Describes a credential for a LoWPAN network. @@ -24,7 +28,7 @@ import java.util.Map; * @hide */ // @SystemApi -public class LowpanCredential { +public class LowpanCredential implements Parcelable { public static final int UNSPECIFIED_KEY_INDEX = 0; @@ -49,18 +53,18 @@ public class LowpanCredential { return new LowpanCredential(masterKey, keyIndex); } - public void setMasterKey(byte[] masterKey) { + void setMasterKey(byte[] masterKey) { if (masterKey != null) { masterKey = masterKey.clone(); } mMasterKey = masterKey; } - public void setMasterKeyIndex(int keyIndex) { + void setMasterKeyIndex(int keyIndex) { mMasterKeyIndex = keyIndex; } - public void setMasterKey(byte[] masterKey, int keyIndex) { + void setMasterKey(byte[] masterKey, int keyIndex) { setMasterKey(masterKey); setMasterKeyIndex(keyIndex); } @@ -80,12 +84,89 @@ public class LowpanCredential { return mMasterKey != null; } - void addToMap(Map<String, Object> parameters) throws LowpanException { + public String toSensitiveString() { + StringBuffer sb = new StringBuffer(); + + sb.append("<LowpanCredential"); + + if (isMasterKey()) { + sb.append(" MasterKey:").append(HexDump.toHexString(mMasterKey)); + if (mMasterKeyIndex != UNSPECIFIED_KEY_INDEX) { + sb.append(", Index:").append(mMasterKeyIndex); + } + } else { + sb.append(" empty"); + } + + sb.append(">"); + + return sb.toString(); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + + sb.append("<LowpanCredential"); + if (isMasterKey()) { - LowpanProperties.KEY_NETWORK_MASTER_KEY.putInMap(parameters, getMasterKey()); - LowpanProperties.KEY_NETWORK_MASTER_KEY_INDEX.putInMap(parameters, getMasterKeyIndex()); + // We don't print out the contents of the key here, + // we only do that in toSensitiveString. + sb.append(" MasterKey"); + if (mMasterKeyIndex != UNSPECIFIED_KEY_INDEX) { + sb.append(", Index:").append(mMasterKeyIndex); + } } else { - throw new LowpanException("Unsupported Network Credential"); + sb.append(" empty"); } + + sb.append(">"); + + return sb.toString(); } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof LowpanCredential)) { + return false; + } + LowpanCredential rhs = (LowpanCredential) obj; + return Arrays.equals(mMasterKey, rhs.mMasterKey) && mMasterKeyIndex == rhs.mMasterKeyIndex; + } + + @Override + public int hashCode() { + return Objects.hash(Arrays.hashCode(mMasterKey), mMasterKeyIndex); + } + + /** Implement the Parcelable interface. */ + @Override + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface. */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeByteArray(mMasterKey); + dest.writeInt(mMasterKeyIndex); + } + + /** Implement the Parcelable interface. */ + public static final Creator<LowpanCredential> CREATOR = + new Creator<LowpanCredential>() { + + public LowpanCredential createFromParcel(Parcel in) { + LowpanCredential credential = new LowpanCredential(); + + credential.mMasterKey = in.createByteArray(); + credential.mMasterKeyIndex = in.readInt(); + + return credential; + } + + public LowpanCredential[] newArray(int size) { + return new LowpanCredential[size]; + } + }; } diff --git a/lowpan/java/android/net/lowpan/LowpanEnergyScanResult.java b/lowpan/java/android/net/lowpan/LowpanEnergyScanResult.java index 91ed19c488eb..da87752008c9 100644 --- a/lowpan/java/android/net/lowpan/LowpanEnergyScanResult.java +++ b/lowpan/java/android/net/lowpan/LowpanEnergyScanResult.java @@ -28,7 +28,7 @@ public class LowpanEnergyScanResult { private int mChannel = UNKNOWN; private int mMaxRssi = UNKNOWN; - public LowpanEnergyScanResult() {} + LowpanEnergyScanResult() {} public int getChannel() { return mChannel; @@ -38,11 +38,11 @@ public class LowpanEnergyScanResult { return mMaxRssi; } - public void setChannel(int x) { + void setChannel(int x) { mChannel = x; } - public void setMaxRssi(int x) { + void setMaxRssi(int x) { mMaxRssi = x; } diff --git a/lowpan/java/android/net/lowpan/LowpanException.java b/lowpan/java/android/net/lowpan/LowpanException.java index 5a1f72993fb5..5dfce48d3f17 100644 --- a/lowpan/java/android/net/lowpan/LowpanException.java +++ b/lowpan/java/android/net/lowpan/LowpanException.java @@ -28,245 +28,65 @@ import android.util.AndroidException; */ // @SystemApi public class LowpanException extends AndroidException { - // Make the eclipse warning about serializable exceptions go away - private static final long serialVersionUID = 0x31863cbe562b0e11l; // randomly generated + public LowpanException() {} - public static final int LOWPAN_ERROR = 1; - public static final int LOWPAN_CREDENTIAL_NEEDED = 2; - public static final int LOWPAN_DEAD = 3; - public static final int LOWPAN_DISABLED = 4; - public static final int LOWPAN_WRONG_STATE = 5; - public static final int LOWPAN_BUSY = 7; - public static final int LOWPAN_NCP_PROBLEM = 8; - public static final int LOWPAN_ALREADY = 9; - public static final int LOWPAN_CANCELED = 10; - public static final int LOWPAN_FEATURE_NOT_SUPPORTED = 12; - public static final int LOWPAN_PROPERTY_NOT_FOUND = 13; - public static final int LOWPAN_JOIN_FAILED_UNKNOWN = 14; - public static final int LOWPAN_JOIN_FAILED_AT_SCAN = 15; - public static final int LOWPAN_JOIN_FAILED_AT_AUTH = 16; - public static final int LOWPAN_FORM_FAILED_AT_SCAN = 17; + public LowpanException(String message) { + super(message); + } - public static LowpanException rethrowAsLowpanException(ServiceSpecificException e) - throws LowpanException { - int reason; - switch (e.errorCode) { - case ILowpanInterface.ERROR_INVALID_ARGUMENT: - case ILowpanInterface.ERROR_INVALID_TYPE: - case ILowpanInterface.ERROR_INVALID_VALUE: - throw new IllegalArgumentException(e.getMessage(), e); + public LowpanException(String message, Throwable cause) { + super(message, cause); + } - case ILowpanInterface.ERROR_PERMISSION_DENIED: - throw new SecurityException(e.getMessage(), e); + public LowpanException(Exception cause) { + super(cause); + } + /* This method returns LowpanException so that the caller + * can add "throw" before the invocation of this method. + * This might seem superfluous, but it is actually to + * help provide a hint to the java compiler that this + * function will not return. + */ + static LowpanException rethrowFromServiceSpecificException(ServiceSpecificException e) + throws LowpanException { + switch (e.errorCode) { case ILowpanInterface.ERROR_DISABLED: - reason = LowpanException.LOWPAN_DISABLED; - break; + throw new InterfaceDisabledException(e); case ILowpanInterface.ERROR_WRONG_STATE: - reason = LowpanException.LOWPAN_WRONG_STATE; - break; - - case ILowpanInterface.ERROR_BUSY: - reason = LowpanException.LOWPAN_BUSY; - break; - - case ILowpanInterface.ERROR_ALREADY: - reason = LowpanException.LOWPAN_ALREADY; - break; + throw new WrongStateException(e); case ILowpanInterface.ERROR_CANCELED: - reason = LowpanException.LOWPAN_CANCELED; - break; - - case ILowpanInterface.ERROR_CREDENTIAL_NEEDED: - reason = LowpanException.LOWPAN_CREDENTIAL_NEEDED; - break; - - case ILowpanInterface.ERROR_FEATURE_NOT_SUPPORTED: - reason = LowpanException.LOWPAN_FEATURE_NOT_SUPPORTED; - break; - - case ILowpanInterface.ERROR_PROPERTY_NOT_FOUND: - reason = LowpanException.LOWPAN_PROPERTY_NOT_FOUND; - break; + throw new OperationCanceledException(e); case ILowpanInterface.ERROR_JOIN_FAILED_UNKNOWN: - reason = LowpanException.LOWPAN_JOIN_FAILED_UNKNOWN; - break; + throw new JoinFailedException(e); case ILowpanInterface.ERROR_JOIN_FAILED_AT_SCAN: - reason = LowpanException.LOWPAN_JOIN_FAILED_AT_SCAN; - break; + throw new JoinFailedAtScanException(e); case ILowpanInterface.ERROR_JOIN_FAILED_AT_AUTH: - reason = LowpanException.LOWPAN_JOIN_FAILED_AT_AUTH; - break; + throw new JoinFailedAtAuthException(e); case ILowpanInterface.ERROR_FORM_FAILED_AT_SCAN: - reason = LowpanException.LOWPAN_FORM_FAILED_AT_SCAN; - break; + throw new NetworkAlreadyExistsException(e); - case ILowpanInterface.ERROR_TIMEOUT: - case ILowpanInterface.ERROR_NCP_PROBLEM: - reason = LowpanException.LOWPAN_NCP_PROBLEM; - break; - case ILowpanInterface.ERROR_UNSPECIFIED: - default: - reason = LOWPAN_ERROR; - break; - } - throw new LowpanException(reason, e.getMessage(), e); - } - - private final int mReason; - - public final int getReason() { - return mReason; - } - - public LowpanException(int problem) { - super(getDefaultMessage(problem)); - mReason = problem; - } - - public LowpanException(String message) { - super(getCombinedMessage(LOWPAN_ERROR, message)); - mReason = LOWPAN_ERROR; - } - - public LowpanException(int problem, String message, Throwable cause) { - super(getCombinedMessage(problem, message), cause); - mReason = problem; - } - - public LowpanException(int problem, Throwable cause) { - super(getDefaultMessage(problem), cause); - mReason = problem; - } - - /** @hide */ - public static String getDefaultMessage(int problem) { - String problemString; - - // TODO: Does this need localization? - - switch (problem) { - case LOWPAN_DEAD: - problemString = "LoWPAN interface is no longer alive"; - break; - case LOWPAN_DISABLED: - problemString = "LoWPAN interface is disabled"; - break; - case LOWPAN_WRONG_STATE: - problemString = "LoWPAN interface in wrong state to perfom requested action"; - break; - case LOWPAN_BUSY: - problemString = - "LoWPAN interface was unable to perform the requestion action because it was busy"; - break; - case LOWPAN_NCP_PROBLEM: - problemString = - "The Network Co-Processor associated with this interface has experienced a problem"; - break; - case LOWPAN_ALREADY: - problemString = "The LoWPAN interface is already in the given state"; - break; - case LOWPAN_CANCELED: - problemString = "This operation was canceled"; - break; - case LOWPAN_CREDENTIAL_NEEDED: - problemString = "Additional credentials are required to complete this operation"; - break; - case LOWPAN_FEATURE_NOT_SUPPORTED: - problemString = - "A dependent feature required to perform the given action is not currently supported"; - break; - case LOWPAN_PROPERTY_NOT_FOUND: - problemString = "The given property was not found"; - break; - case LOWPAN_JOIN_FAILED_UNKNOWN: - problemString = "The join operation failed for an unspecified reason"; - break; - case LOWPAN_JOIN_FAILED_AT_SCAN: - problemString = - "The join operation failed because it could not communicate with any peers"; - break; - case LOWPAN_JOIN_FAILED_AT_AUTH: - problemString = - "The join operation failed because the credentials were not accepted by any peers"; - break; - case LOWPAN_FORM_FAILED_AT_SCAN: - problemString = "Network form failed"; - break; - case LOWPAN_ERROR: - default: - problemString = "The requested LoWPAN operation failed"; - break; - } - - return problemString; - } + case ILowpanInterface.ERROR_FEATURE_NOT_SUPPORTED: + throw new LowpanException( + e.getMessage() != null ? e.getMessage() : "Feature not supported", e); - private static String getCombinedMessage(int problem, String message) { - String problemString = getProblemString(problem); - return String.format("%s (%d): %s", problemString, problem, message); - } + case ILowpanInterface.ERROR_NCP_PROBLEM: + throw new LowpanRuntimeException( + e.getMessage() != null ? e.getMessage() : "NCP problem", e); - private static String getProblemString(int problem) { - String problemString; + case ILowpanInterface.ERROR_INVALID_ARGUMENT: + throw new LowpanRuntimeException( + e.getMessage() != null ? e.getMessage() : "Invalid argument", e); - switch (problem) { - case LOWPAN_ERROR: - problemString = "LOWPAN_ERROR"; - break; - case LOWPAN_DEAD: - problemString = "LOWPAN_DEAD"; - break; - case LOWPAN_DISABLED: - problemString = "LOWPAN_DISABLED"; - break; - case LOWPAN_WRONG_STATE: - problemString = "LOWPAN_WRONG_STATE"; - break; - case LOWPAN_BUSY: - problemString = "LOWPAN_BUSY"; - break; - case LOWPAN_NCP_PROBLEM: - problemString = "LOWPAN_NCP_PROBLEM"; - break; - case LOWPAN_ALREADY: - problemString = "LOWPAN_ALREADY"; - break; - case LOWPAN_CANCELED: - problemString = "LOWPAN_CANCELED"; - break; - case LOWPAN_CREDENTIAL_NEEDED: - problemString = "LOWPAN_CREDENTIAL_NEEDED"; - break; - case LOWPAN_FEATURE_NOT_SUPPORTED: - problemString = "LOWPAN_FEATURE_NOT_SUPPORTED"; - break; - case LOWPAN_PROPERTY_NOT_FOUND: - problemString = "LOWPAN_PROPERTY_NOT_FOUND"; - break; - case LOWPAN_JOIN_FAILED_UNKNOWN: - problemString = "LOWPAN_JOIN_FAILED_UNKNOWN"; - break; - case LOWPAN_JOIN_FAILED_AT_SCAN: - problemString = "LOWPAN_JOIN_FAILED_AT_SCAN"; - break; - case LOWPAN_JOIN_FAILED_AT_AUTH: - problemString = "LOWPAN_JOIN_FAILED_AT_AUTH"; - break; - case LOWPAN_FORM_FAILED_AT_SCAN: - problemString = "LOWPAN_FORM_FAILED_AT_SCAN"; - break; + case ILowpanInterface.ERROR_UNSPECIFIED: default: - problemString = "LOWPAN_ERROR_CODE_" + problem; - break; + throw new LowpanRuntimeException(e); } - - return problemString; } } diff --git a/lowpan/java/android/net/lowpan/LowpanIdentity.aidl b/lowpan/java/android/net/lowpan/LowpanIdentity.aidl new file mode 100644 index 000000000000..fcef98f5c496 --- /dev/null +++ b/lowpan/java/android/net/lowpan/LowpanIdentity.aidl @@ -0,0 +1,19 @@ +/** + * 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.lowpan; + +parcelable LowpanIdentity cpp_header "android/net/lowpan/LowpanIdentity.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanIdentity.java b/lowpan/java/android/net/lowpan/LowpanIdentity.java index 2d36f7fa9789..6cb1f987c5d9 100644 --- a/lowpan/java/android/net/lowpan/LowpanIdentity.java +++ b/lowpan/java/android/net/lowpan/LowpanIdentity.java @@ -16,8 +16,16 @@ package android.net.lowpan; +import android.annotation.NonNull; +import android.icu.text.StringPrep; +import android.icu.text.StringPrepParseException; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; import com.android.internal.util.HexDump; -import java.util.Map; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Objects; /** * Describes an instance of a LoWPAN network. @@ -25,76 +33,100 @@ import java.util.Map; * @hide */ // @SystemApi -public class LowpanIdentity { +public class LowpanIdentity implements Parcelable { + private static final String TAG = LowpanIdentity.class.getSimpleName(); // Constants + public static final int UNSPECIFIED_CHANNEL = -1; + public static final int UNSPECIFIED_PANID = 0xFFFFFFFF; + // Builder /** @hide */ - public static final int TYPE_ZIGBEE = 1; - - /** @hide */ - public static final int TYPE_ZIGBEE_IP = 2; + // @SystemApi + public static class Builder { + private static final StringPrep stringPrep = + StringPrep.getInstance(StringPrep.RFC3920_RESOURCEPREP); + + final LowpanIdentity mIdentity = new LowpanIdentity(); + + private static String escape(@NonNull byte[] bytes) { + StringBuffer sb = new StringBuffer(); + for (byte b : bytes) { + if (b >= 32 && b <= 126) { + sb.append((char) b); + } else { + sb.append(String.format("\\0x%02x", b & 0xFF)); + } + } + return sb.toString(); + } - /** @hide */ - public static final int TYPE_THREAD = 3; + public Builder setLowpanIdentity(@NonNull LowpanIdentity x) { + Objects.requireNonNull(x); + setRawName(x.getRawName()); + setXpanid(x.getXpanid()); + setPanid(x.getPanid()); + setChannel(x.getChannel()); + setType(x.getType()); + return this; + } - public static final int UNKNOWN = Integer.MAX_VALUE; + public Builder setName(@NonNull String name) { + Objects.requireNonNull(name); + try { + mIdentity.mName = stringPrep.prepare(name, StringPrep.DEFAULT); + mIdentity.mRawName = mIdentity.mName.getBytes(StandardCharsets.UTF_8); + mIdentity.mIsNameValid = true; + } catch (StringPrepParseException x) { + Log.w(TAG, x.toString()); + setRawName(name.getBytes(StandardCharsets.UTF_8)); + } + return this; + } - // Builder + public Builder setRawName(@NonNull byte[] name) { + Objects.requireNonNull(name); + mIdentity.mRawName = name.clone(); + mIdentity.mName = new String(name, StandardCharsets.UTF_8); + try { + String nameCheck = stringPrep.prepare(mIdentity.mName, StringPrep.DEFAULT); + mIdentity.mIsNameValid = + Arrays.equals(nameCheck.getBytes(StandardCharsets.UTF_8), name); + } catch (StringPrepParseException x) { + Log.w(TAG, x.toString()); + mIdentity.mIsNameValid = false; + } - /** @hide */ - // @SystemApi - public static class Builder { - private final LowpanIdentity identity = new LowpanIdentity(); + // Non-normal names must be rendered differently to avoid confusion. + if (!mIdentity.mIsNameValid) { + mIdentity.mName = "«" + escape(name) + "»"; + } - public Builder setName(String x) { - identity.mName = x; return this; } public Builder setXpanid(byte x[]) { - identity.mXpanid = (x != null ? x.clone() : null); + mIdentity.mXpanid = (x != null ? x.clone() : null); return this; } public Builder setPanid(int x) { - identity.mPanid = x; + mIdentity.mPanid = x; return this; } - /** @hide */ - public Builder setType(int x) { - identity.mType = x; + public Builder setType(@NonNull String x) { + mIdentity.mType = x; return this; } public Builder setChannel(int x) { - identity.mChannel = x; - return this; - } - - /** @hide */ - Builder updateFromMap(Map map) { - if (map.containsKey(ILowpanInterface.KEY_NETWORK_NAME)) { - setName(LowpanProperties.KEY_NETWORK_NAME.getFromMap(map)); - } - if (map.containsKey(ILowpanInterface.KEY_NETWORK_PANID)) { - setPanid(LowpanProperties.KEY_NETWORK_PANID.getFromMap(map)); - } - if (map.containsKey(ILowpanInterface.KEY_NETWORK_XPANID)) { - setXpanid(LowpanProperties.KEY_NETWORK_XPANID.getFromMap(map)); - } - if (map.containsKey(ILowpanInterface.KEY_CHANNEL)) { - setChannel(LowpanProperties.KEY_CHANNEL.getFromMap(map)); - } - if (map.containsKey(ILowpanInterface.KEY_NETWORK_TYPE)) { - setType(LowpanProperties.KEY_NETWORK_TYPE.getFromMap(map)); - } + mIdentity.mChannel = x; return this; } public LowpanIdentity build() { - return identity; + return mIdentity; } } @@ -102,28 +134,37 @@ public class LowpanIdentity { // Instance Variables - private String mName = null; - private byte[] mXpanid = null; - private int mType = UNKNOWN; - private int mPanid = UNKNOWN; - private int mChannel = UNKNOWN; + private String mName = ""; + private boolean mIsNameValid = true; + private byte[] mRawName = new byte[0]; + private String mType = ""; + private byte[] mXpanid = new byte[0]; + private int mPanid = UNSPECIFIED_PANID; + private int mChannel = UNSPECIFIED_CHANNEL; - // Public Getters and Setters + // Public Getters public String getName() { return mName; } + public boolean isNameValid() { + return mIsNameValid; + } + + public byte[] getRawName() { + return mRawName.clone(); + } + public byte[] getXpanid() { - return mXpanid != null ? mXpanid.clone() : null; + return mXpanid.clone(); } public int getPanid() { return mPanid; } - /** @hide */ - public int getType() { + public String getType() { return mType; } @@ -131,43 +172,84 @@ public class LowpanIdentity { return mChannel; } - static void addToMap(Map<String, Object> parameters, LowpanIdentity networkInfo) { - if (networkInfo.getName() != null) { - LowpanProperties.KEY_NETWORK_NAME.putInMap(parameters, networkInfo.getName()); + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + + sb.append("Name:").append(getName()); + + if (mType.length() > 0) { + sb.append(", Type:").append(mType); } - if (networkInfo.getPanid() != LowpanIdentity.UNKNOWN) { - LowpanProperties.KEY_NETWORK_PANID.putInMap(parameters, networkInfo.getPanid()); + + if (mXpanid.length > 0) { + sb.append(", XPANID:").append(HexDump.toHexString(mXpanid)); } - if (networkInfo.getChannel() != LowpanIdentity.UNKNOWN) { - LowpanProperties.KEY_CHANNEL.putInMap(parameters, networkInfo.getChannel()); + + if (mPanid != UNSPECIFIED_PANID) { + sb.append(", PANID:").append(String.format("0x%04X", mPanid)); } - if (networkInfo.getXpanid() != null) { - LowpanProperties.KEY_NETWORK_XPANID.putInMap(parameters, networkInfo.getXpanid()); + + if (mChannel != UNSPECIFIED_CHANNEL) { + sb.append(", Channel:").append(mChannel); } + + return sb.toString(); } - void addToMap(Map<String, Object> parameters) { - addToMap(parameters, this); + @Override + public boolean equals(Object obj) { + if (!(obj instanceof LowpanIdentity)) { + return false; + } + LowpanIdentity rhs = (LowpanIdentity) obj; + return Arrays.equals(mRawName, rhs.mRawName) + && Arrays.equals(mXpanid, rhs.mXpanid) + && mType.equals(rhs.mType) + && mPanid == rhs.mPanid + && mChannel == rhs.mChannel; } @Override - public String toString() { - StringBuffer sb = new StringBuffer(); + public int hashCode() { + return Objects.hash( + Arrays.hashCode(mRawName), mType, Arrays.hashCode(mXpanid), mPanid, mChannel); + } - sb.append("Name: ").append(mName == null ? "<none>" : mName); + /** Implement the Parcelable interface. */ + @Override + public int describeContents() { + return 0; + } - if (mXpanid != null) { - sb.append(", XPANID: ").append(HexDump.toHexString(mXpanid)); - } + /** Implement the Parcelable interface. */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeByteArray(mRawName); + dest.writeString(mType); + dest.writeByteArray(mXpanid); + dest.writeInt(mPanid); + dest.writeInt(mChannel); + } - if (mPanid != UNKNOWN) { - sb.append(", PANID: ").append(String.format("0x%04X", mPanid)); - } + /** Implement the Parcelable interface. */ + public static final Creator<LowpanIdentity> CREATOR = + new Creator<LowpanIdentity>() { - if (mChannel != UNKNOWN) { - sb.append(", Channel: ").append(mChannel); - } + public LowpanIdentity createFromParcel(Parcel in) { + Builder builder = new Builder(); - return sb.toString(); - } + builder.setRawName(in.createByteArray()); + builder.setType(in.readString()); + builder.setXpanid(in.createByteArray()); + builder.setPanid(in.readInt()); + builder.setChannel(in.readInt()); + + return builder.build(); + } + + public LowpanIdentity[] newArray(int size) { + return new LowpanIdentity[size]; + } + }; } diff --git a/lowpan/java/android/net/lowpan/LowpanInterface.java b/lowpan/java/android/net/lowpan/LowpanInterface.java index 55bf3994574d..57e91357b237 100644 --- a/lowpan/java/android/net/lowpan/LowpanInterface.java +++ b/lowpan/java/android/net/lowpan/LowpanInterface.java @@ -28,8 +28,6 @@ import android.os.RemoteException; import android.os.ServiceSpecificException; import android.util.Log; import java.util.HashMap; -import java.util.Map; -import java.util.Set; /** * Class for managing a specific Low-power Wireless Personal Area Network (LoWPAN) interface. @@ -41,13 +39,13 @@ public class LowpanInterface { private static final String TAG = LowpanInterface.class.getSimpleName(); /** Detached role. The interface is not currently attached to a network. */ - public static final String ROLE_DETACHED = "detached"; + public static final String ROLE_DETACHED = ILowpanInterface.ROLE_DETACHED; /** End-device role. End devices do not route traffic for other nodes. */ - public static final String ROLE_END_DEVICE = "end-device"; + public static final String ROLE_END_DEVICE = ILowpanInterface.ROLE_END_DEVICE; /** Router role. Routers help route traffic around the mesh network. */ - public static final String ROLE_ROUTER = "router"; + public static final String ROLE_ROUTER = ILowpanInterface.ROLE_ROUTER; /** * Sleepy End-Device role. @@ -57,7 +55,7 @@ public class LowpanInterface { * extraordinarilly low power consumption, but packet latency can be on the order of dozens of * seconds(depending on how the node is configured). */ - public static final String ROLE_SLEEPY_END_DEVICE = "sleepy-end-device"; + public static final String ROLE_SLEEPY_END_DEVICE = ILowpanInterface.ROLE_SLEEPY_END_DEVICE; /** * Sleepy-router role. @@ -65,13 +63,13 @@ public class LowpanInterface { * <p>Routers with this role are nominally asleep, waking up periodically to check in with other * routers and their children. */ - public static final String ROLE_SLEEPY_ROUTER = "sleepy-router"; + public static final String ROLE_SLEEPY_ROUTER = ILowpanInterface.ROLE_SLEEPY_ROUTER; /** TODO: doc */ - public static final String ROLE_LEADER = "leader"; + public static final String ROLE_LEADER = ILowpanInterface.ROLE_LEADER; /** TODO: doc */ - public static final String ROLE_COORDINATOR = "coordinator"; + public static final String ROLE_COORDINATOR = ILowpanInterface.ROLE_COORDINATOR; /** * Offline state. @@ -86,7 +84,7 @@ public class LowpanInterface { * @see #getState() * @see #STATE_FAULT */ - public static final String STATE_OFFLINE = "offline"; + public static final String STATE_OFFLINE = ILowpanInterface.STATE_OFFLINE; /** * Commissioning state. @@ -98,7 +96,7 @@ public class LowpanInterface { * @see #getState() * @hide */ - public static final String STATE_COMMISSIONING = "commissioning"; + public static final String STATE_COMMISSIONING = ILowpanInterface.STATE_COMMISSIONING; /** * Attaching state. @@ -116,7 +114,7 @@ public class LowpanInterface { * @see #STATE_ATTACHED * @see #getState() */ - public static final String STATE_ATTACHING = "attaching"; + public static final String STATE_ATTACHING = ILowpanInterface.STATE_ATTACHING; /** * Attached state. @@ -127,7 +125,7 @@ public class LowpanInterface { * @see #STATE_ATTACHING * @see #getState() */ - public static final String STATE_ATTACHED = "attached"; + public static final String STATE_ATTACHED = ILowpanInterface.STATE_ATTACHED; /** * Fault state. @@ -141,7 +139,7 @@ public class LowpanInterface { * @see #getState * @see #STATE_OFFLINE */ - public static final String STATE_FAULT = "fault"; + public static final String STATE_FAULT = ILowpanInterface.STATE_FAULT; /** * Network type for Thread 1.x networks. @@ -150,23 +148,9 @@ public class LowpanInterface { * @see #getLowpanIdentity * @hide */ - public static final String NETWORK_TYPE_THREAD = "org.threadgroup.thread.v1"; + public static final String NETWORK_TYPE_THREAD_V1 = ILowpanInterface.NETWORK_TYPE_THREAD_V1; - /** - * Network type for ZigBeeIP 1.x networks. - * - * @see android.net.lowpan.LowpanIdentity#getType - * @see #getLowpanIdentity - * @hide - */ - public static final String NETWORK_TYPE_ZIGBEE_IP = "org.zigbee.zigbeeip.v1"; - - private static final String NETWORK_PROPERTY_KEYS[] = { - LowpanProperties.KEY_NETWORK_NAME.getName(), - LowpanProperties.KEY_NETWORK_PANID.getName(), - LowpanProperties.KEY_NETWORK_XPANID.getName(), - LowpanProperties.KEY_CHANNEL.getName() - }; + public static final String EMPTY_PARTITION_ID = ""; /** * Callback base class for LowpanInterface @@ -187,8 +171,13 @@ public class LowpanInterface { public void onLowpanIdentityChanged(@NonNull LowpanIdentity value) {} - /** @hide */ - public void onPropertiesChanged(@NonNull Map properties) {} + public void onLinkNetworkAdded(IpPrefix prefix) {} + + public void onLinkNetworkRemoved(IpPrefix prefix) {} + + public void onLinkAddressAdded(LinkAddress address) {} + + public void onLinkAddressRemoved(LinkAddress address) {} } private final ILowpanInterface mBinder; @@ -222,74 +211,6 @@ public class LowpanInterface { return mBinder; } - // Private Property Helpers - - void setProperties(Map properties) throws LowpanException { - try { - mBinder.setProperties(properties); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowAsLowpanException(x); - } - } - - @NonNull - Map<String, Object> getProperties(String keys[]) throws LowpanException { - try { - return mBinder.getProperties(keys); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowAsLowpanException(x); - } - } - - /** @hide */ - public <T> void setProperty(LowpanProperty<T> key, T value) throws LowpanException { - HashMap<String, T> prop = new HashMap<>(); - prop.put(key.getName(), value); - setProperties(prop); - } - - /** @hide */ - @Nullable - public <T> T getProperty(LowpanProperty<T> key) throws LowpanException { - Map<String, Object> map = getProperties(new String[] {key.getName()}); - if (map != null && !map.isEmpty()) { - // We know there is only one value. - return (T) map.values().iterator().next(); - } - return null; - } - - @Nullable - <T> String getPropertyAsString(LowpanProperty<T> key) throws LowpanException { - try { - return mBinder.getPropertyAsString(key.getName()); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowAsLowpanException(x); - } - } - - int getPropertyAsInt(LowpanProperty<Integer> key) throws LowpanException { - Integer value = getProperty(key); - return (value != null) ? value : 0; - } - - boolean getPropertyAsBoolean(LowpanProperty<Boolean> key) throws LowpanException { - Boolean value = getProperty(key); - return (value != null) ? value : false; - } - // Public Actions /** @@ -306,15 +227,13 @@ public class LowpanInterface { */ public void form(@NonNull LowpanProvision provision) throws LowpanException { try { - Map<String, Object> parameters = new HashMap(); - provision.addToMap(parameters); - mBinder.form(parameters); + mBinder.form(provision); } catch (RemoteException x) { throw x.rethrowAsRuntimeException(); } catch (ServiceSpecificException x) { - throw LowpanException.rethrowAsLowpanException(x); + throw LowpanException.rethrowFromServiceSpecificException(x); } } @@ -328,15 +247,13 @@ public class LowpanInterface { */ public void join(@NonNull LowpanProvision provision) throws LowpanException { try { - Map<String, Object> parameters = new HashMap(); - provision.addToMap(parameters); - mBinder.join(parameters); + mBinder.join(provision); } catch (RemoteException x) { throw x.rethrowAsRuntimeException(); } catch (ServiceSpecificException x) { - throw LowpanException.rethrowAsLowpanException(x); + throw LowpanException.rethrowFromServiceSpecificException(x); } } @@ -348,13 +265,14 @@ public class LowpanInterface { * <p>This method will block execution until the operation has completed. */ public void attach(@NonNull LowpanProvision provision) throws LowpanException { - if (ROLE_DETACHED.equals(getRole())) { - Map<String, Object> parameters = new HashMap(); - provision.addToMap(parameters); - setProperties(parameters); - setUp(true); - } else { - throw new LowpanException(LowpanException.LOWPAN_ALREADY); + try { + mBinder.attach(provision); + + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); + + } catch (ServiceSpecificException x) { + throw LowpanException.rethrowFromServiceSpecificException(x); } } @@ -372,7 +290,7 @@ public class LowpanInterface { throw x.rethrowAsRuntimeException(); } catch (ServiceSpecificException x) { - throw LowpanException.rethrowAsLowpanException(x); + throw LowpanException.rethrowFromServiceSpecificException(x); } } @@ -382,9 +300,17 @@ public class LowpanInterface { */ public @NonNull LowpanCommissioningSession startCommissioningSession( @NonNull LowpanBeaconInfo beaconInfo) throws LowpanException { + try { + mBinder.startCommissioningSession(beaconInfo); + + return new LowpanCommissioningSession(mBinder, beaconInfo, mLooper); + + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); - /* TODO: Implement startCommissioningSession */ - throw new LowpanException(LowpanException.LOWPAN_FEATURE_NOT_SUPPORTED); + } catch (ServiceSpecificException x) { + throw LowpanException.rethrowFromServiceSpecificException(x); + } } /** @@ -403,7 +329,7 @@ public class LowpanInterface { throw x.rethrowAsRuntimeException(); } catch (ServiceSpecificException x) { - throw LowpanException.rethrowAsLowpanException(x); + throw LowpanException.rethrowFromServiceSpecificException(x); } } @@ -415,6 +341,9 @@ public class LowpanInterface { try { return mBinder.getName(); + } catch (DeadObjectException x) { + return ""; + } catch (RemoteException x) { throw x.rethrowAsRuntimeException(); } @@ -428,9 +357,13 @@ public class LowpanInterface { */ public boolean isEnabled() { try { - return getPropertyAsBoolean(LowpanProperties.KEY_INTERFACE_ENABLED); - } catch (LowpanException x) { + return mBinder.isEnabled(); + + } catch (DeadObjectException x) { return false; + + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); } } @@ -444,7 +377,15 @@ public class LowpanInterface { * @hide */ public void setEnabled(boolean enabled) throws LowpanException { - setProperty(LowpanProperties.KEY_INTERFACE_ENABLED, enabled); + try { + mBinder.setEnabled(enabled); + + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); + + } catch (ServiceSpecificException x) { + throw LowpanException.rethrowFromServiceSpecificException(x); + } } /** @@ -454,22 +395,14 @@ public class LowpanInterface { */ public boolean isUp() { try { - return getPropertyAsBoolean(LowpanProperties.KEY_INTERFACE_UP); - } catch (LowpanException x) { + return mBinder.isUp(); + + } catch (DeadObjectException x) { return false; - } - } - /** - * Bring up or shut down the network interface. - * - * <p>This method brings up or shuts down the network interface, attaching or (gracefully) - * detaching from the currently configured LoWPAN network as appropriate. - * - * @hide - */ - public void setUp(boolean interfaceUp) throws LowpanException { - setProperty(LowpanProperties.KEY_INTERFACE_UP, interfaceUp); + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); + } } /** @@ -480,9 +413,13 @@ public class LowpanInterface { */ public boolean isConnected() { try { - return getPropertyAsBoolean(LowpanProperties.KEY_INTERFACE_CONNECTED); - } catch (LowpanException x) { + return mBinder.isConnected(); + + } catch (DeadObjectException x) { return false; + + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); } } @@ -492,9 +429,13 @@ public class LowpanInterface { */ public boolean isCommissioned() { try { - return getPropertyAsBoolean(LowpanProperties.KEY_INTERFACE_COMMISSIONED); - } catch (LowpanException x) { + return mBinder.isCommissioned(); + + } catch (DeadObjectException x) { return false; + + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); } } @@ -514,90 +455,89 @@ public class LowpanInterface { */ public String getState() { try { - return getProperty(LowpanProperties.KEY_INTERFACE_STATE); - } catch (LowpanException x) { - Log.e(TAG, x.toString()); + return mBinder.getState(); + + } catch (DeadObjectException x) { return STATE_FAULT; + + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); + } + } + + /** Get network partition/fragment identifier. */ + public String getPartitionId() { + try { + return mBinder.getPartitionId(); + + } catch (DeadObjectException x) { + return EMPTY_PARTITION_ID; + + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); } } /** TODO: doc */ public LowpanIdentity getLowpanIdentity() { - LowpanIdentity.Builder builder = new LowpanIdentity.Builder(); try { - builder.updateFromMap(getProperties(NETWORK_PROPERTY_KEYS)); - } catch (LowpanException x) { - // We ignore all LoWPAN-specitic exceptions here. - } + return mBinder.getLowpanIdentity(); - return builder.build(); - } + } catch (DeadObjectException x) { + return new LowpanIdentity(); - /** - * TODO: doc - * - * @hide - */ - public void setLowpanIdentity(LowpanIdentity network) throws LowpanException { - Map<String, Object> map = new HashMap(); - LowpanIdentity.addToMap(map, network); - setProperties(map); + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); + } } /** TODO: doc */ @NonNull public String getRole() { - String role = null; - try { - role = getProperty(LowpanProperties.KEY_NETWORK_ROLE); - } catch (LowpanException x) { - // We ignore all LoWPAN-specitic exceptions here. - Log.e(TAG, x.toString()); - } + return mBinder.getRole(); - if (role == null) { - role = ROLE_DETACHED; - } + } catch (DeadObjectException x) { + return ROLE_DETACHED; - return role; + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); + } } /** TODO: doc */ @Nullable public LowpanCredential getLowpanCredential() { - LowpanCredential credential = null; - try { - Integer keyIndex = getProperty(LowpanProperties.KEY_NETWORK_MASTER_KEY_INDEX); - - if (keyIndex == null) { - credential = - LowpanCredential.createMasterKey( - getProperty(LowpanProperties.KEY_NETWORK_MASTER_KEY)); - } else { - credential = - LowpanCredential.createMasterKey( - getProperty(LowpanProperties.KEY_NETWORK_MASTER_KEY), - keyIndex.intValue()); - } - } catch (LowpanException x) { - // We ignore all LoWPAN-specitic exceptions here. - Log.e(TAG, x.toString()); + return mBinder.getLowpanCredential(); + + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); } + } + + public @NonNull String[] getSupportedNetworkTypes() throws LowpanException { + try { + return mBinder.getSupportedNetworkTypes(); - return credential; + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); + + } catch (ServiceSpecificException x) { + throw LowpanException.rethrowFromServiceSpecificException(x); + } } - /** - * TODO: doc - * - * @hide - */ - public void setLowpanCredential(LowpanCredential networkCredential) throws LowpanException { - Map<String, Object> map = new HashMap(); - networkCredential.addToMap(map); - setProperties(map); + public @NonNull LowpanChannelInfo[] getSupportedChannels() throws LowpanException { + try { + return mBinder.getSupportedChannels(); + + } catch (RemoteException x) { + throw x.rethrowAsRuntimeException(); + + } catch (ServiceSpecificException x) { + throw LowpanException.rethrowFromServiceSpecificException(x); + } } // Listener Support @@ -627,57 +567,80 @@ public class LowpanInterface { } } - @Override public void onPropertiesChanged(Map properties) { - Runnable runnable = - () -> { - for (String key : (Set<String>) properties.keySet()) { - Object value = properties.get(key); - switch (key) { - case ILowpanInterface.KEY_INTERFACE_ENABLED: - cb.onEnabledChanged( - ((Boolean) value).booleanValue()); - break; - case ILowpanInterface.KEY_INTERFACE_UP: - cb.onUpChanged(((Boolean) value).booleanValue()); - break; - case ILowpanInterface.KEY_INTERFACE_CONNECTED: - cb.onConnectedChanged( - ((Boolean) value).booleanValue()); - break; - case ILowpanInterface.KEY_INTERFACE_STATE: - cb.onStateChanged((String) value); - break; - case ILowpanInterface.KEY_NETWORK_NAME: - case ILowpanInterface.KEY_NETWORK_PANID: - case ILowpanInterface.KEY_NETWORK_XPANID: - case ILowpanInterface.KEY_CHANNEL: - cb.onLowpanIdentityChanged(getLowpanIdentity()); - break; - case ILowpanInterface.KEY_NETWORK_ROLE: - cb.onRoleChanged(value.toString()); - break; - } - } - cb.onPropertiesChanged(properties); - }; - - mHandler.post(runnable); + @Override + public void onEnabledChanged(boolean value) { + mHandler.post(() -> cb.onEnabledChanged(value)); + } + + @Override + public void onConnectedChanged(boolean value) { + mHandler.post(() -> cb.onConnectedChanged(value)); + } + + @Override + public void onUpChanged(boolean value) { + mHandler.post(() -> cb.onUpChanged(value)); } - @Override public void onLinkNetworkAdded(IpPrefix prefix) { - // Support for this event isn't yet implemented. + @Override + public void onRoleChanged(String value) { + mHandler.post(() -> cb.onRoleChanged(value)); } - @Override public void onLinkNetworkRemoved(IpPrefix prefix) { - // Support for this event isn't yet implemented. + @Override + public void onStateChanged(String value) { + mHandler.post(() -> cb.onStateChanged(value)); } - @Override public void onLinkAddressAdded(String address) { - // Support for this event isn't yet implemented. + @Override + public void onLowpanIdentityChanged(LowpanIdentity value) { + mHandler.post(() -> cb.onLowpanIdentityChanged(value)); + } + + @Override + public void onLinkNetworkAdded(IpPrefix value) { + mHandler.post(() -> cb.onLinkNetworkAdded(value)); + } + + @Override + public void onLinkNetworkRemoved(IpPrefix value) { + mHandler.post(() -> cb.onLinkNetworkRemoved(value)); + } + + @Override + public void onLinkAddressAdded(String value) { + LinkAddress la; + try { + la = new LinkAddress(value); + } catch (IllegalArgumentException x) { + Log.e( + TAG, + "onLinkAddressAdded: Bad LinkAddress \"" + value + "\", " + x); + return; + } + mHandler.post(() -> cb.onLinkAddressAdded(la)); + } + + @Override + public void onLinkAddressRemoved(String value) { + LinkAddress la; + try { + la = new LinkAddress(value); + } catch (IllegalArgumentException x) { + Log.e( + TAG, + "onLinkAddressRemoved: Bad LinkAddress \"" + + value + + "\", " + + x); + return; + } + mHandler.post(() -> cb.onLinkAddressRemoved(la)); } - @Override public void onLinkAddressRemoved(String address) { - // Support for this event isn't yet implemented. + @Override + public void onReceiveFromCommissioner(byte[] packet) { + // This is only used by the LowpanCommissioningSession. } }; try { @@ -752,9 +715,9 @@ public class LowpanInterface { * * @hide */ - public LinkAddress[] copyLinkAddresses() throws LowpanException { + public LinkAddress[] getLinkAddresses() throws LowpanException { try { - String[] linkAddressStrings = mBinder.copyLinkAddresses(); + String[] linkAddressStrings = mBinder.getLinkAddresses(); LinkAddress[] ret = new LinkAddress[linkAddressStrings.length]; int i = 0; for (String str : linkAddressStrings) { @@ -766,7 +729,7 @@ public class LowpanInterface { throw x.rethrowAsRuntimeException(); } catch (ServiceSpecificException x) { - throw LowpanException.rethrowAsLowpanException(x); + throw LowpanException.rethrowFromServiceSpecificException(x); } } @@ -775,15 +738,15 @@ public class LowpanInterface { * * @hide */ - public IpPrefix[] copyLinkNetworks() throws LowpanException { + public IpPrefix[] getLinkNetworks() throws LowpanException { try { - return mBinder.copyLinkNetworks(); + return mBinder.getLinkNetworks(); } catch (RemoteException x) { throw x.rethrowAsRuntimeException(); } catch (ServiceSpecificException x) { - throw LowpanException.rethrowAsLowpanException(x); + throw LowpanException.rethrowFromServiceSpecificException(x); } } @@ -800,7 +763,7 @@ public class LowpanInterface { throw x.rethrowAsRuntimeException(); } catch (ServiceSpecificException x) { - throw LowpanException.rethrowAsLowpanException(x); + throw LowpanException.rethrowFromServiceSpecificException(x); } } @@ -837,7 +800,7 @@ public class LowpanInterface { throw x.rethrowAsRuntimeException(); } catch (ServiceSpecificException x) { - throw LowpanException.rethrowAsLowpanException(x); + throw LowpanException.rethrowFromServiceSpecificException(x); } } diff --git a/lowpan/java/android/net/lowpan/LowpanProperties.java b/lowpan/java/android/net/lowpan/LowpanProperties.java index f835260b842e..cc45ff85f723 100644 --- a/lowpan/java/android/net/lowpan/LowpanProperties.java +++ b/lowpan/java/android/net/lowpan/LowpanProperties.java @@ -16,74 +16,14 @@ package android.net.lowpan; -import android.net.IpPrefix; -import android.net.LinkAddress; - /** {@hide} */ public final class LowpanProperties { - public static final LowpanProperty<Boolean> KEY_INTERFACE_ENABLED = - new LowpanStandardProperty( - "android.net.lowpan.property.INTERFACE_ENABLED", Boolean.class); - public static final LowpanProperty<Boolean> KEY_INTERFACE_COMMISSIONED = - new LowpanStandardProperty( - "android.net.lowpan.property.INTERFACE_COMMISSIONED", Boolean.class); - public static final LowpanProperty<Boolean> KEY_INTERFACE_CONNECTED = - new LowpanStandardProperty( - "android.net.lowpan.property.INTERFACE_CONNECTED", Boolean.class); - public static final LowpanProperty<Boolean> KEY_INTERFACE_UP = - new LowpanStandardProperty("android.net.lowpan.property.INTERFACE_UP", Boolean.class); - public static final LowpanProperty<String> KEY_INTERFACE_STATE = - new LowpanStandardProperty("android.net.lowpan.property.INTERFACE_STATE", String.class); - - public static final LowpanProperty<String> KEY_NETWORK_NAME = - new LowpanStandardProperty("android.net.lowpan.property.NETWORK_NAME", Boolean.class); - public static final LowpanProperty<Integer> KEY_NETWORK_PANID = - new LowpanStandardProperty("android.net.lowpan.property.NETWORK_PANID", Integer.class); - public static final LowpanProperty<byte[]> KEY_NETWORK_XPANID = - new LowpanStandardProperty("android.net.lowpan.property.NETWORK_XPANID", byte[].class); - public static final LowpanProperty<byte[]> KEY_NETWORK_MASTER_KEY = - new LowpanStandardProperty( - "android.net.lowpan.property.NETWORK_MASTER_KEY", byte[].class); - public static final LowpanProperty<Integer> KEY_NETWORK_MASTER_KEY_INDEX = - new LowpanStandardProperty( - "android.net.lowpan.property.NETWORK_MASTER_KEY_INDEX", Integer.class); - public static final LowpanProperty<Integer> KEY_NETWORK_TYPE = - new LowpanStandardProperty("android.net.lowpan.property.NETWORK_TYPE", Integer.class); - public static final LowpanProperty<String> KEY_NETWORK_ROLE = - new LowpanStandardProperty("android.net.lowpan.property.NETWORK_ROLE", String.class); - - public static final LowpanProperty<Integer> KEY_CHANNEL = - new LowpanStandardProperty("android.net.lowpan.property.CHANNEL", Integer.class); public static final LowpanProperty<int[]> KEY_CHANNEL_MASK = new LowpanStandardProperty("android.net.lowpan.property.CHANNEL_MASK", int[].class); + public static final LowpanProperty<Integer> KEY_MAX_TX_POWER = new LowpanStandardProperty("android.net.lowpan.property.MAX_TX_POWER", Integer.class); - public static final LowpanProperty<Integer> KEY_RSSI = - new LowpanStandardProperty("android.net.lowpan.property.RSSI", Integer.class); - - public static final LowpanProperty<Integer> KEY_LQI = - new LowpanStandardProperty("android.net.lowpan.property.LQI", Integer.class); - public static final LowpanProperty<byte[]> KEY_BEACON_ADDRESS = - new LowpanStandardProperty("android.net.lowpan.property.BEACON_ADDRESS", byte[].class); - public static final LowpanProperty<Boolean> KEY_BEACON_CAN_ASSIST = - new LowpanStandardProperty( - "android.net.lowpan.property.BEACON_CAN_ASSIST", Boolean.class); - - public static final LowpanProperty<String> KEY_DRIVER_VERSION = - new LowpanStandardProperty("android.net.lowpan.property.DRIVER_VERSION", String.class); - - public static final LowpanProperty<String> KEY_NCP_VERSION = - new LowpanStandardProperty("android.net.lowpan.property.NCP_VERSION", String.class); - - /** @hide */ - public static final LowpanProperty<byte[]> KEY_EXTENDED_ADDRESS = - new LowpanStandardProperty( - "android.net.lowpan.property.EXTENDED_ADDRESS", byte[].class); - - /** @hide */ - public static final LowpanProperty<byte[]> KEY_MAC_ADDRESS = - new LowpanStandardProperty("android.net.lowpan.property.MAC_ADDRESS", byte[].class); /** @hide */ private LowpanProperties() {} diff --git a/lowpan/java/android/net/lowpan/LowpanProvision.aidl b/lowpan/java/android/net/lowpan/LowpanProvision.aidl new file mode 100644 index 000000000000..100e9dc8cc4a --- /dev/null +++ b/lowpan/java/android/net/lowpan/LowpanProvision.aidl @@ -0,0 +1,19 @@ +/** + * 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.lowpan; + +parcelable LowpanProvision cpp_header "android/net/lowpan/LowpanProvision.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanProvision.java b/lowpan/java/android/net/lowpan/LowpanProvision.java index 7028807679a1..f1260037b331 100644 --- a/lowpan/java/android/net/lowpan/LowpanProvision.java +++ b/lowpan/java/android/net/lowpan/LowpanProvision.java @@ -18,7 +18,9 @@ package android.net.lowpan; import android.annotation.NonNull; import android.annotation.Nullable; -import java.util.Map; +import android.os.Parcel; +import android.os.Parcelable; +import java.util.Objects; /** * Describes the information needed to describe a network @@ -26,7 +28,7 @@ import java.util.Map; * @hide */ // @SystemApi -public class LowpanProvision { +public class LowpanProvision implements Parcelable { // Builder @@ -69,20 +71,6 @@ public class LowpanProvision { return mCredential; } - // LoWPAN-Internal Methods - - static void addToMap(Map<String, Object> parameters, LowpanProvision provision) - throws LowpanException { - provision.mIdentity.addToMap(parameters); - if (provision.mCredential != null) { - provision.mCredential.addToMap(parameters); - } - } - - void addToMap(Map<String, Object> parameters) throws LowpanException { - addToMap(parameters, this); - } - @Override public String toString() { StringBuffer sb = new StringBuffer(); @@ -90,11 +78,72 @@ public class LowpanProvision { sb.append("LowpanProvision { identity => ").append(mIdentity.toString()); if (mCredential != null) { - sb.append(", credential: ").append(mCredential.toString()); + sb.append(", credential => ").append(mCredential.toString()); } sb.append("}"); return sb.toString(); } + + @Override + public int hashCode() { + return Objects.hash(mIdentity, mCredential); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof LowpanProvision)) { + return false; + } + LowpanProvision rhs = (LowpanProvision) obj; + + if (!mIdentity.equals(rhs.mIdentity)) { + return false; + } + + if (!Objects.equals(mCredential, rhs.mCredential)) { + return false; + } + + return true; + } + + /** Implement the Parcelable interface. */ + @Override + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface. */ + @Override + public void writeToParcel(Parcel dest, int flags) { + mIdentity.writeToParcel(dest, flags); + if (mCredential == null) { + dest.writeBoolean(false); + } else { + dest.writeBoolean(true); + mCredential.writeToParcel(dest, flags); + } + } + + /** Implement the Parcelable interface. */ + public static final Creator<LowpanProvision> CREATOR = + new Creator<LowpanProvision>() { + public LowpanProvision createFromParcel(Parcel in) { + Builder builder = new Builder(); + + builder.setLowpanIdentity(LowpanIdentity.CREATOR.createFromParcel(in)); + + if (in.readBoolean()) { + builder.setLowpanCredential(LowpanCredential.CREATOR.createFromParcel(in)); + } + + return builder.build(); + } + + public LowpanProvision[] newArray(int size) { + return new LowpanProvision[size]; + } + }; }; diff --git a/lowpan/java/android/net/lowpan/LowpanRuntimeException.java b/lowpan/java/android/net/lowpan/LowpanRuntimeException.java new file mode 100644 index 000000000000..71a5a1397a4e --- /dev/null +++ b/lowpan/java/android/net/lowpan/LowpanRuntimeException.java @@ -0,0 +1,42 @@ +/* + * 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.lowpan; + +import android.util.AndroidRuntimeException; + +/** + * Generic runtime exception for LoWPAN operations. + * + * @hide + */ +// @SystemApi +public class LowpanRuntimeException extends AndroidRuntimeException { + + public LowpanRuntimeException() {} + + public LowpanRuntimeException(String message) { + super(message); + } + + public LowpanRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public LowpanRuntimeException(Exception cause) { + super(cause); + } +} diff --git a/lowpan/java/android/net/lowpan/LowpanScanner.java b/lowpan/java/android/net/lowpan/LowpanScanner.java index b0557ee5c19b..59156c429010 100644 --- a/lowpan/java/android/net/lowpan/LowpanScanner.java +++ b/lowpan/java/android/net/lowpan/LowpanScanner.java @@ -21,7 +21,6 @@ import android.annotation.Nullable; import android.os.Handler; import android.os.RemoteException; import android.os.ServiceSpecificException; -import android.util.Log; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -37,7 +36,7 @@ import java.util.Map; */ // @SystemApi public class LowpanScanner { - private static final String TAG = LowpanInterface.class.getSimpleName(); + private static final String TAG = LowpanScanner.class.getSimpleName(); // Public Classes @@ -174,7 +173,7 @@ public class LowpanScanner { ILowpanNetScanCallback binderListener = new ILowpanNetScanCallback.Stub() { - public void onNetScanBeacon(Map parameters) { + public void onNetScanBeacon(LowpanBeaconInfo beaconInfo) { Callback callback; Handler handler; @@ -187,12 +186,7 @@ public class LowpanScanner { return; } - Runnable runnable = - () -> - callback.onNetScanBeacon( - new LowpanBeaconInfo.Builder() - .updateFromMap(parameters) - .build()); + Runnable runnable = () -> callback.onNetScanBeacon(beaconInfo); if (handler != null) { handler.post(runnable); @@ -231,7 +225,7 @@ public class LowpanScanner { throw x.rethrowAsRuntimeException(); } catch (ServiceSpecificException x) { - throw LowpanException.rethrowAsLowpanException(x); + throw LowpanException.rethrowFromServiceSpecificException(x); } } @@ -246,9 +240,6 @@ public class LowpanScanner { } catch (RemoteException x) { throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - Log.e(TAG, x.toString()); } } @@ -315,7 +306,7 @@ public class LowpanScanner { throw x.rethrowAsRuntimeException(); } catch (ServiceSpecificException x) { - throw LowpanException.rethrowAsLowpanException(x); + throw LowpanException.rethrowFromServiceSpecificException(x); } } @@ -330,9 +321,6 @@ public class LowpanScanner { } catch (RemoteException x) { throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - Log.e(TAG, x.toString()); } } } diff --git a/lowpan/java/android/net/lowpan/NetworkAlreadyExistsException.java b/lowpan/java/android/net/lowpan/NetworkAlreadyExistsException.java new file mode 100644 index 000000000000..90ef498baaba --- /dev/null +++ b/lowpan/java/android/net/lowpan/NetworkAlreadyExistsException.java @@ -0,0 +1,41 @@ +/* + * 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.lowpan; + +/** + * Exception indicating the form operation found a network nearby with the same identity. + * + * @see LowpanInterface + * @hide + */ +// @SystemApi +public class NetworkAlreadyExistsException extends LowpanException { + + public NetworkAlreadyExistsException() {} + + public NetworkAlreadyExistsException(String message) { + super(message, null); + } + + public NetworkAlreadyExistsException(String message, Throwable cause) { + super(message, cause); + } + + public NetworkAlreadyExistsException(Exception cause) { + super(cause); + } +} diff --git a/lowpan/java/android/net/lowpan/OperationCanceledException.java b/lowpan/java/android/net/lowpan/OperationCanceledException.java new file mode 100644 index 000000000000..fcafe3ae9b8f --- /dev/null +++ b/lowpan/java/android/net/lowpan/OperationCanceledException.java @@ -0,0 +1,41 @@ +/* + * 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.lowpan; + +/** + * Exception indicating this operation was canceled by the driver before it could finish. + * + * @see LowpanInterface + * @hide + */ +// @SystemApi +public class OperationCanceledException extends LowpanException { + + public OperationCanceledException() {} + + public OperationCanceledException(String message) { + super(message); + } + + public OperationCanceledException(String message, Throwable cause) { + super(message, cause); + } + + protected OperationCanceledException(Exception cause) { + super(cause); + } +} diff --git a/lowpan/java/android/net/lowpan/WrongStateException.java b/lowpan/java/android/net/lowpan/WrongStateException.java new file mode 100644 index 000000000000..35654194e32b --- /dev/null +++ b/lowpan/java/android/net/lowpan/WrongStateException.java @@ -0,0 +1,41 @@ +/* + * 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.lowpan; + +/** + * Exception indicating the interface is the wrong state for an operation. + * + * @see LowpanInterface + * @hide + */ +// @SystemApi +public class WrongStateException extends LowpanException { + + public WrongStateException() {} + + public WrongStateException(String message) { + super(message); + } + + public WrongStateException(String message, Throwable cause) { + super(message, cause); + } + + protected WrongStateException(Exception cause) { + super(cause); + } +} diff --git a/lowpan/tests/Android.mk b/lowpan/tests/Android.mk index bb0a944b5e7d..1ea471a4cc00 100644 --- a/lowpan/tests/Android.mk +++ b/lowpan/tests/Android.mk @@ -54,8 +54,35 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ mockito-target-minus-junit4 \ frameworks-base-testutils \ -LOCAL_JAVA_LIBRARIES := \ - android.test.runner \ +LOCAL_JNI_SHARED_LIBRARIES += libframeworkslowpantestsjni +LOCAL_JNI_SHARED_LIBRARIES += libandroid_net_lowpan +LOCAL_JNI_SHARED_LIBRARIES += \ + libbacktrace \ + libbase \ + libbinder \ + libc++ \ + libcutils \ + liblog \ + liblzma \ + libnativehelper \ + libnetdaidl \ + libui \ + libunwind \ + libutils \ + libvndksupport \ + libcrypto \ + libhidl-gen-utils \ + libhidlbase \ + libhidltransport \ + libpackagelistparser \ + libpcre2 \ + libselinux \ + libtinyxml2 \ + libvintf \ + libhwbinder \ + android.hidl.token@1.0 + +LOCAL_JAVA_LIBRARIES := android.test.runner LOCAL_PACKAGE_NAME := FrameworksLowpanApiTests LOCAL_COMPATIBILITY_SUITE := device-tests @@ -63,3 +90,25 @@ LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_CERTIFICATE := platform LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk include $(BUILD_PACKAGE) + +######################################################################### +# Build JNI Shared Library +######################################################################### + +LOCAL_PATH:= $(LOCAL_PATH)/jni + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_CFLAGS := -Wall -Wextra -Werror + +LOCAL_SRC_FILES := $(call all-cpp-files-under) + +LOCAL_SHARED_LIBRARIES += libandroid_net_lowpan +LOCAL_SHARED_LIBRARIES += libbinder +LOCAL_SHARED_LIBRARIES += liblog + +LOCAL_MODULE := libframeworkslowpantestsjni + +include $(BUILD_SHARED_LIBRARY) diff --git a/lowpan/tests/java/android/net/lowpan/LowpanBeaconInfoTest.java b/lowpan/tests/java/android/net/lowpan/LowpanBeaconInfoTest.java new file mode 100644 index 000000000000..6dbb3ed5de65 --- /dev/null +++ b/lowpan/tests/java/android/net/lowpan/LowpanBeaconInfoTest.java @@ -0,0 +1,134 @@ +/* + * 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.lowpan; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertArrayEquals; + +import android.os.Parcel; +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.SmallTest; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class LowpanBeaconInfoTest { + + static { + System.loadLibrary("frameworkslowpantestsjni"); + } + + private static native byte[] readAndWriteNative(byte[] inParcel); + + public void testNativeParcelUnparcel(LowpanBeaconInfo original) { + byte[] inParcel = marshall(original); + byte[] outParcel = readAndWriteNative(inParcel); + LowpanBeaconInfo roundTrip = unmarshall(outParcel); + + assertEquals(original, roundTrip); + assertArrayEquals(inParcel, outParcel); + } + + @Test + public void testNativeParcelUnparcel() { + testNativeParcelUnparcel( + new LowpanBeaconInfo.Builder() + .setName("TestNet1") + .setPanid(0x1234) + .setXpanid( + new byte[] { + (byte) 0x00, + (byte) 0x11, + (byte) 0x22, + (byte) 0x33, + (byte) 0x44, + (byte) 0x55, + (byte) 0x66, + (byte) 0x77 + }) + .setType(LowpanInterface.NETWORK_TYPE_THREAD_V1) + .setChannel(15) + .setBeaconAddress( + new byte[] { + (byte) 0x88, + (byte) 0x99, + (byte) 0xaa, + (byte) 0xbb, + (byte) 0xcc, + (byte) 0xdd, + (byte) 0xee, + (byte) 0xff + }) + .build()); + + testNativeParcelUnparcel( + new LowpanBeaconInfo.Builder() + .setName("TestNet2") + .setPanid(0x5678) + .setXpanid( + new byte[] { + (byte) 0x88, + (byte) 0x99, + (byte) 0xaa, + (byte) 0xbb, + (byte) 0xcc, + (byte) 0xdd, + (byte) 0xee, + (byte) 0xff + }) + .setType("bork-bork-bork") + .setChannel(16) + .setBeaconAddress( + new byte[] { + (byte) 0x00, + (byte) 0x11, + (byte) 0x22, + (byte) 0x33, + (byte) 0x44, + (byte) 0x55, + (byte) 0x66, + (byte) 0x77 + }) + .setFlag(LowpanBeaconInfo.FLAG_CAN_ASSIST) + .build()); + } + + /** + * Write a {@link LowpanBeaconInfo} into an empty parcel and return the underlying data. + * + * @see unmarshall(byte[]) + */ + private static byte[] marshall(LowpanBeaconInfo addr) { + Parcel p = Parcel.obtain(); + addr.writeToParcel(p, /* flags */ 0); + p.setDataPosition(0); + return p.marshall(); + } + + /** + * Read raw bytes into a parcel, and read a {@link LowpanBeaconInfo} back out of them. + * + * @see marshall(LowpanBeaconInfo) + */ + private static LowpanBeaconInfo unmarshall(byte[] data) { + Parcel p = Parcel.obtain(); + p.unmarshall(data, 0, data.length); + p.setDataPosition(0); + return LowpanBeaconInfo.CREATOR.createFromParcel(p); + } +} diff --git a/lowpan/tests/java/android/net/lowpan/LowpanChannelInfoTest.java b/lowpan/tests/java/android/net/lowpan/LowpanChannelInfoTest.java new file mode 100644 index 000000000000..eac4398088a8 --- /dev/null +++ b/lowpan/tests/java/android/net/lowpan/LowpanChannelInfoTest.java @@ -0,0 +1,78 @@ +/* + * 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.lowpan; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertArrayEquals; + +import android.os.Parcel; +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.SmallTest; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class LowpanChannelInfoTest { + + static { + System.loadLibrary("frameworkslowpantestsjni"); + } + + private static native byte[] readAndWriteNative(byte[] inParcel); + + public void testNativeParcelUnparcel(LowpanChannelInfo original) { + byte[] inParcel = marshall(original); + byte[] outParcel = readAndWriteNative(inParcel); + LowpanChannelInfo roundTrip = unmarshall(outParcel); + + assertEquals(original, roundTrip); + assertArrayEquals(inParcel, outParcel); + } + + @Test + public void testNativeParcelUnparcel() { + int i; + for (i = 1; i < 26; i++) { + testNativeParcelUnparcel(LowpanChannelInfo.getChannelInfoForIeee802154Page0(i)); + } + } + + /** + * Write a {@link LowpanChannelInfo} into an empty parcel and return the underlying data. + * + * @see unmarshall(byte[]) + */ + private static byte[] marshall(LowpanChannelInfo addr) { + Parcel p = Parcel.obtain(); + addr.writeToParcel(p, /* flags */ 0); + p.setDataPosition(0); + return p.marshall(); + } + + /** + * Read raw bytes into a parcel, and read a {@link LowpanChannelInfo} back out of them. + * + * @see marshall(LowpanChannelInfo) + */ + private static LowpanChannelInfo unmarshall(byte[] data) { + Parcel p = Parcel.obtain(); + p.unmarshall(data, 0, data.length); + p.setDataPosition(0); + return LowpanChannelInfo.CREATOR.createFromParcel(p); + } +} diff --git a/lowpan/tests/java/android/net/lowpan/LowpanCredentialTest.java b/lowpan/tests/java/android/net/lowpan/LowpanCredentialTest.java new file mode 100644 index 000000000000..26e33349ddac --- /dev/null +++ b/lowpan/tests/java/android/net/lowpan/LowpanCredentialTest.java @@ -0,0 +1,92 @@ +/* + * 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.lowpan; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertArrayEquals; + +import android.os.Parcel; +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.SmallTest; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class LowpanCredentialTest { + + static { + System.loadLibrary("frameworkslowpantestsjni"); + } + + private static native byte[] readAndWriteNative(byte[] inParcel); + + public void testNativeParcelUnparcel(LowpanCredential original) { + byte[] inParcel = marshall(original); + byte[] outParcel = readAndWriteNative(inParcel); + LowpanCredential roundTrip = unmarshall(outParcel); + + assertEquals(original, roundTrip); + assertArrayEquals(inParcel, outParcel); + } + + @Test + public void testNativeParcelUnparcel() { + testNativeParcelUnparcel( + LowpanCredential.createMasterKey( + new byte[] { + (byte) 0x88, + (byte) 0x99, + (byte) 0xaa, + (byte) 0xbb, + (byte) 0xcc, + (byte) 0xdd, + (byte) 0xee, + (byte) 0xff + })); + testNativeParcelUnparcel( + LowpanCredential.createMasterKey( + new byte[] { + (byte) 0x88, (byte) 0x99, (byte) 0xaa, (byte) 0xbb, (byte) 0xcc + }, + 15)); + } + + /** + * Write a {@link LowpanCredential} into an empty parcel and return the underlying data. + * + * @see unmarshall(byte[]) + */ + private static byte[] marshall(LowpanCredential addr) { + Parcel p = Parcel.obtain(); + addr.writeToParcel(p, /* flags */ 0); + p.setDataPosition(0); + return p.marshall(); + } + + /** + * Read raw bytes into a parcel, and read a {@link LowpanCredential} back out of them. + * + * @see marshall(LowpanCredential) + */ + private static LowpanCredential unmarshall(byte[] data) { + Parcel p = Parcel.obtain(); + p.unmarshall(data, 0, data.length); + p.setDataPosition(0); + return LowpanCredential.CREATOR.createFromParcel(p); + } +} diff --git a/lowpan/tests/java/android/net/lowpan/LowpanIdentityTest.java b/lowpan/tests/java/android/net/lowpan/LowpanIdentityTest.java new file mode 100644 index 000000000000..1242e55055f3 --- /dev/null +++ b/lowpan/tests/java/android/net/lowpan/LowpanIdentityTest.java @@ -0,0 +1,199 @@ +/* + * 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.lowpan; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import android.os.Parcel; +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.SmallTest; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class LowpanIdentityTest { + + static { + System.loadLibrary("frameworkslowpantestsjni"); + } + + private static native byte[] readAndWriteNative(byte[] inParcel); + + public void testNativeParcelUnparcel(LowpanIdentity original) { + byte[] inParcel = marshall(original); + byte[] outParcel = readAndWriteNative(inParcel); + LowpanIdentity roundTrip = unmarshall(outParcel); + + assertEquals(original, roundTrip); + assertEquals(original.hashCode(), roundTrip.hashCode()); + assertEquals(original.getName(), roundTrip.getName()); + assertArrayEquals(inParcel, outParcel); + } + + @Test + public void testNativeParcelUnparcel1() { + testNativeParcelUnparcel( + new LowpanIdentity.Builder() + .setName("TestNet1") + .setPanid(0x1234) + .setXpanid( + new byte[] { + (byte) 0x00, + (byte) 0x11, + (byte) 0x22, + (byte) 0x33, + (byte) 0x44, + (byte) 0x55, + (byte) 0x66, + (byte) 0x77 + }) + .setType(LowpanInterface.NETWORK_TYPE_THREAD_V1) + .setChannel(15) + .build()); + } + + @Test + public void testNativeParcelUnparcel2() { + testNativeParcelUnparcel( + new LowpanIdentity.Builder() + .setName("TestNet2") + .setPanid(0x5678) + .setXpanid( + new byte[] { + (byte) 0x88, + (byte) 0x99, + (byte) 0xaa, + (byte) 0xbb, + (byte) 0xcc, + (byte) 0xdd, + (byte) 0xee, + (byte) 0xff + }) + .setType("bork-bork-bork") + .setChannel(16) + .build()); + } + + @Test + public void testNativeParcelUnparcel3() { + testNativeParcelUnparcel(new LowpanIdentity.Builder().setName("TestNet3").build()); + } + + @Test + public void testNativeParcelUnparcel4() { + testNativeParcelUnparcel(new LowpanIdentity.Builder().build()); + } + + @Test + public void testNativeParcelUnparcel5() { + testNativeParcelUnparcel( + new LowpanIdentity.Builder() + .setRawName( + new byte[] { + (byte) 0x66, + (byte) 0x6F, + (byte) 0x6F, + (byte) 0xC2, + (byte) 0xAD, + (byte) 0xCD, + (byte) 0x8F, + (byte) 0xE1, + (byte) 0xA0, + (byte) 0x86, + (byte) 0xE1, + (byte) 0xA0, + (byte) 0x8B + }) + .build()); + } + + @Test + public void testStringPrep1() { + LowpanIdentity identity = + new LowpanIdentity.Builder() + .setRawName( + new byte[] { + (byte) 0x66, + (byte) 0x6F, + (byte) 0x6F, + (byte) 0x20, + (byte) 0xC2, + (byte) 0xAD, + (byte) 0xCD, + (byte) 0x8F, + (byte) 0xE1, + (byte) 0xA0, + (byte) 0x86, + (byte) 0xE1, + (byte) 0xA0, + (byte) 0x8B + }) + .build(); + + assertFalse(identity.isNameValid()); + } + + @Test + public void testStringPrep2() { + LowpanIdentity identity = + new LowpanIdentity.Builder() + .setRawName( + new byte[] { + (byte) 0x66, (byte) 0x6F, (byte) 0x6F, (byte) 0x20, (byte) 0x6F + }) + .build(); + + assertEquals("foo o", identity.getName()); + assertTrue(identity.isNameValid()); + } + + @Test + public void testStringPrep3() { + LowpanIdentity identity = new LowpanIdentity.Builder().setName("foo o").build(); + + assertTrue(identity.isNameValid()); + assertEquals("foo o", identity.getName()); + } + + /** + * Write a {@link LowpanIdentity} into an empty parcel and return the underlying data. + * + * @see unmarshall(byte[]) + */ + private static byte[] marshall(LowpanIdentity addr) { + Parcel p = Parcel.obtain(); + addr.writeToParcel(p, /* flags */ 0); + p.setDataPosition(0); + return p.marshall(); + } + + /** + * Read raw bytes into a parcel, and read a {@link LowpanIdentity} back out of them. + * + * @see marshall(LowpanIdentity) + */ + private static LowpanIdentity unmarshall(byte[] data) { + Parcel p = Parcel.obtain(); + p.unmarshall(data, 0, data.length); + p.setDataPosition(0); + return LowpanIdentity.CREATOR.createFromParcel(p); + } +} diff --git a/lowpan/tests/src/android/net/lowpan/LowpanInterfaceTest.java b/lowpan/tests/java/android/net/lowpan/LowpanInterfaceTest.java index 455ee08547bf..f26a37ed71ce 100644 --- a/lowpan/tests/src/android/net/lowpan/LowpanInterfaceTest.java +++ b/lowpan/tests/java/android/net/lowpan/LowpanInterfaceTest.java @@ -16,26 +16,22 @@ package android.net.lowpan; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.*; import android.content.Context; import android.content.pm.ApplicationInfo; +import android.net.LinkAddress; import android.os.Handler; import android.os.IBinder; import android.os.test.TestLooper; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; +import java.util.Map; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import java.util.Map; -import java.util.HashMap; /** Unit tests for android.net.lowpan.LowpanInterface. */ @RunWith(AndroidJUnit4.class) @@ -64,7 +60,8 @@ public class LowpanInterfaceTest { when(mLowpanInterfaceService.getName()).thenReturn("wpan0"); when(mLowpanInterfaceService.asBinder()).thenReturn(mLowpanInterfaceBinder); - mLowpanInterface = new LowpanInterface(mContext, mLowpanInterfaceService, mTestLooper.getLooper()); + mLowpanInterface = + new LowpanInterface(mContext, mLowpanInterfaceService, mTestLooper.getLooper()); } @Test @@ -81,12 +78,8 @@ public class LowpanInterfaceTest { return listener instanceof ILowpanInterfaceListener; })); - // Build a changed property map - Map<String, Object> changedProperties = new HashMap<>(); - LowpanProperties.KEY_INTERFACE_STATE.putInMap(changedProperties, LowpanInterface.STATE_OFFLINE); - // Change some properties - mInterfaceListener.onPropertiesChanged(changedProperties); + mInterfaceListener.onStateChanged(LowpanInterface.STATE_OFFLINE); mTestLooper.dispatchAll(); // Verify that the property was changed @@ -94,4 +87,66 @@ public class LowpanInterfaceTest { .onStateChanged( argThat(stateString -> stateString.equals(LowpanInterface.STATE_OFFLINE))); } + + @Test + public void testLinkAddressCallback() throws Exception { + // Register our callback + mLowpanInterface.registerCallback(mLowpanInterfaceCallback); + + // Verify a listener was added + verify(mLowpanInterfaceService) + .addListener( + argThat( + listener -> { + mInterfaceListener = listener; + return listener instanceof ILowpanInterfaceListener; + })); + + final LinkAddress linkAddress = new LinkAddress("fe80::1/64"); + + // Change some properties + mInterfaceListener.onLinkAddressAdded(linkAddress.toString()); + mTestLooper.dispatchAll(); + + // Verify that the property was changed + verify(mLowpanInterfaceCallback) + .onLinkAddressAdded(argThat(addr -> addr.equals(linkAddress))); + + // Change some properties + mInterfaceListener.onLinkAddressRemoved(linkAddress.toString()); + mTestLooper.dispatchAll(); + + // Verify that the property was changed + verify(mLowpanInterfaceCallback) + .onLinkAddressRemoved(argThat(addr -> addr.equals(linkAddress))); + } + + @Test + public void testBogusLinkAddressCallback() throws Exception { + // Register our callback + mLowpanInterface.registerCallback(mLowpanInterfaceCallback); + + // Verify a listener was added + verify(mLowpanInterfaceService) + .addListener( + argThat( + listener -> { + mInterfaceListener = listener; + return listener instanceof ILowpanInterfaceListener; + })); + + // Change some properties + mInterfaceListener.onLinkAddressAdded("fe80:::1/640"); + mTestLooper.dispatchAll(); + + // Verify that no callback was called. + verifyNoMoreInteractions(mLowpanInterfaceCallback); + + // Change some properties + mInterfaceListener.onLinkAddressRemoved("fe80:::1/640"); + mTestLooper.dispatchAll(); + + // Verify that no callback was called. + verifyNoMoreInteractions(mLowpanInterfaceCallback); + } } diff --git a/lowpan/tests/src/android/net/lowpan/LowpanManagerTest.java b/lowpan/tests/java/android/net/lowpan/LowpanManagerTest.java index 481ad76e6790..3dd7504d8332 100644 --- a/lowpan/tests/src/android/net/lowpan/LowpanManagerTest.java +++ b/lowpan/tests/java/android/net/lowpan/LowpanManagerTest.java @@ -16,10 +16,9 @@ package android.net.lowpan; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.*; import android.content.Context; diff --git a/lowpan/tests/java/android/net/lowpan/LowpanProvisionTest.java b/lowpan/tests/java/android/net/lowpan/LowpanProvisionTest.java new file mode 100644 index 000000000000..3be2f26e93ab --- /dev/null +++ b/lowpan/tests/java/android/net/lowpan/LowpanProvisionTest.java @@ -0,0 +1,128 @@ +/* + * 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.lowpan; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertArrayEquals; + +import android.os.Parcel; +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.SmallTest; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class LowpanProvisionTest { + + static { + System.loadLibrary("frameworkslowpantestsjni"); + } + + private static native byte[] readAndWriteNative(byte[] inParcel); + + public void testNativeParcelUnparcel(LowpanProvision original) { + byte[] inParcel = marshall(original); + byte[] outParcel = readAndWriteNative(inParcel); + LowpanProvision roundTrip = unmarshall(outParcel); + + assertEquals(original, roundTrip); + assertArrayEquals(inParcel, outParcel); + } + + @Test + public void testNativeParcelUnparcel() { + testNativeParcelUnparcel( + new LowpanProvision.Builder() + .setLowpanIdentity( + new LowpanIdentity.Builder() + .setName("TestNet1") + .setPanid(0x1234) + .setXpanid( + new byte[] { + (byte) 0x00, + (byte) 0x11, + (byte) 0x22, + (byte) 0x33, + (byte) 0x44, + (byte) 0x55, + (byte) 0x66, + (byte) 0x77 + }) + .setType(LowpanInterface.NETWORK_TYPE_THREAD_V1) + .setChannel(15) + .build()) + .build()); + testNativeParcelUnparcel( + new LowpanProvision.Builder() + .setLowpanIdentity( + new LowpanIdentity.Builder() + .setName("TestNet2") + .setPanid(0x5678) + .setXpanid( + new byte[] { + (byte) 0x88, + (byte) 0x99, + (byte) 0xaa, + (byte) 0xbb, + (byte) 0xcc, + (byte) 0xdd, + (byte) 0xee, + (byte) 0xff + }) + .setType("bork-bork-bork") + .setChannel(16) + .build()) + .setLowpanCredential( + LowpanCredential.createMasterKey( + new byte[] { + (byte) 0x88, + (byte) 0x99, + (byte) 0xaa, + (byte) 0xbb, + (byte) 0xcc, + (byte) 0xdd, + (byte) 0xee, + (byte) 0xff + })) + .build()); + } + + /** + * Write a {@link LowpanProvision} into an empty parcel and return the underlying data. + * + * @see unmarshall(byte[]) + */ + private static byte[] marshall(LowpanProvision addr) { + Parcel p = Parcel.obtain(); + addr.writeToParcel(p, /* flags */ 0); + p.setDataPosition(0); + return p.marshall(); + } + + /** + * Read raw bytes into a parcel, and read a {@link LowpanProvision} back out of them. + * + * @see marshall(LowpanProvision) + */ + private static LowpanProvision unmarshall(byte[] data) { + Parcel p = Parcel.obtain(); + p.unmarshall(data, 0, data.length); + p.setDataPosition(0); + return LowpanProvision.CREATOR.createFromParcel(p); + } +} diff --git a/lowpan/tests/jni/LowpanBeaconInfoTest.cpp b/lowpan/tests/jni/LowpanBeaconInfoTest.cpp new file mode 100644 index 000000000000..efc5f1835497 --- /dev/null +++ b/lowpan/tests/jni/LowpanBeaconInfoTest.cpp @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#include <memory> + +#include <binder/Parcel.h> + +#include "LowpanBeaconInfoTest.h" + +using android::net::lowpan::LowpanBeaconInfo; + +/** + * Reads exactly one LowpanBeaconInfo from 'parcelData' assuming that it is a Parcel. Any bytes afterward + * are ignored. + */ +static LowpanBeaconInfo unmarshall(JNIEnv* env, jbyteArray parcelData) { + const int length = env->GetArrayLength(parcelData); + + std::unique_ptr<uint8_t> bytes(new uint8_t[length]); + env->GetByteArrayRegion(parcelData, 0, length, reinterpret_cast<jbyte*>(bytes.get())); + + android::Parcel p; + p.setData(bytes.get(), length); + + LowpanBeaconInfo value; + value.readFromParcel(&p); + return value; +} + +/** + * Creates a Java byte[] array and writes the contents of 'addr' to it as a Parcel containing + * exactly one object. + * + * Every LowpanBeaconInfo maps to a unique parcel object, so both 'marshall(e, unmarshall(e, x))' and + * 'unmarshall(e, marshall(e, x))' should be fixed points. + */ +static jbyteArray marshall(JNIEnv* env, const LowpanBeaconInfo& addr) { + android::Parcel p; + addr.writeToParcel(&p); + const int length = p.dataSize(); + + jbyteArray parcelData = env->NewByteArray(length); + env->SetByteArrayRegion(parcelData, 0, length, reinterpret_cast<const jbyte*>(p.data())); + + return parcelData; +} + +extern "C" +JNIEXPORT jbyteArray Java_android_net_lowpan_LowpanBeaconInfoTest_readAndWriteNative(JNIEnv* env, jclass, + jbyteArray inParcel) { + const LowpanBeaconInfo value = unmarshall(env, inParcel); + return marshall(env, value); +} diff --git a/lowpan/tests/jni/LowpanBeaconInfoTest.h b/lowpan/tests/jni/LowpanBeaconInfoTest.h new file mode 100644 index 000000000000..1ba8eafc0802 --- /dev/null +++ b/lowpan/tests/jni/LowpanBeaconInfoTest.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef _ANDROID_NET_LOWPANBEACONINFOTEST_H_ +#define _ANDROID_NET_LOWPANBEACONINFOTEST_H_ + +#include <jni.h> +#include <android/net/lowpan/LowpanBeaconInfo.h> + +extern "C" +JNIEXPORT jbyteArray Java_android_net_lowpan_LowpanBeaconInfoTest_readAndWriteNative(JNIEnv* env, jclass, + jbyteArray inParcel); + +#endif // _ANDROID_NET_LOWPANBEACONINFOTEST_H_ diff --git a/lowpan/tests/jni/LowpanChannelInfoTest.cpp b/lowpan/tests/jni/LowpanChannelInfoTest.cpp new file mode 100644 index 000000000000..03bb72a6f95b --- /dev/null +++ b/lowpan/tests/jni/LowpanChannelInfoTest.cpp @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#include <memory> + +#include <binder/Parcel.h> + +#include "LowpanChannelInfoTest.h" + +using android::net::lowpan::LowpanChannelInfo; + +/** + * Reads exactly one LowpanChannelInfo from 'parcelData' assuming that it is a Parcel. Any bytes afterward + * are ignored. + */ +static LowpanChannelInfo unmarshall(JNIEnv* env, jbyteArray parcelData) { + const int length = env->GetArrayLength(parcelData); + + std::unique_ptr<uint8_t> bytes(new uint8_t[length]); + env->GetByteArrayRegion(parcelData, 0, length, reinterpret_cast<jbyte*>(bytes.get())); + + android::Parcel p; + p.setData(bytes.get(), length); + + LowpanChannelInfo value; + value.readFromParcel(&p); + return value; +} + +/** + * Creates a Java byte[] array and writes the contents of 'addr' to it as a Parcel containing + * exactly one object. + * + * Every LowpanChannelInfo maps to a unique parcel object, so both 'marshall(e, unmarshall(e, x))' and + * 'unmarshall(e, marshall(e, x))' should be fixed points. + */ +static jbyteArray marshall(JNIEnv* env, const LowpanChannelInfo& addr) { + android::Parcel p; + addr.writeToParcel(&p); + const int length = p.dataSize(); + + jbyteArray parcelData = env->NewByteArray(length); + env->SetByteArrayRegion(parcelData, 0, length, reinterpret_cast<const jbyte*>(p.data())); + + return parcelData; +} + +extern "C" +JNIEXPORT jbyteArray Java_android_net_lowpan_LowpanChannelInfoTest_readAndWriteNative(JNIEnv* env, jclass, + jbyteArray inParcel) { + const LowpanChannelInfo value = unmarshall(env, inParcel); + return marshall(env, value); +} diff --git a/lowpan/tests/jni/LowpanChannelInfoTest.h b/lowpan/tests/jni/LowpanChannelInfoTest.h new file mode 100644 index 000000000000..3b29a90c3cdf --- /dev/null +++ b/lowpan/tests/jni/LowpanChannelInfoTest.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef _ANDROID_NET_LOWPANCHANNELINFOTEST_H_ +#define _ANDROID_NET_LOWPANCHANNELINFOTEST_H_ + +#include <jni.h> +#include <android/net/lowpan/LowpanChannelInfo.h> + +extern "C" +JNIEXPORT jbyteArray Java_android_net_lowpan_LowpanChannelInfoTest_readAndWriteNative(JNIEnv* env, jclass, + jbyteArray inParcel); + +#endif // _ANDROID_NET_LOWPANCHANNELINFOTEST_H_ diff --git a/lowpan/tests/jni/LowpanCredentialTest.cpp b/lowpan/tests/jni/LowpanCredentialTest.cpp new file mode 100644 index 000000000000..fc860b29661e --- /dev/null +++ b/lowpan/tests/jni/LowpanCredentialTest.cpp @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#include <memory> + +#include <binder/Parcel.h> + +#include "LowpanCredentialTest.h" + +using android::net::lowpan::LowpanCredential; + +/** + * Reads exactly one LowpanCredential from 'parcelData' assuming that it is a Parcel. Any bytes afterward + * are ignored. + */ +static LowpanCredential unmarshall(JNIEnv* env, jbyteArray parcelData) { + const int length = env->GetArrayLength(parcelData); + + std::unique_ptr<uint8_t> bytes(new uint8_t[length]); + env->GetByteArrayRegion(parcelData, 0, length, reinterpret_cast<jbyte*>(bytes.get())); + + android::Parcel p; + p.setData(bytes.get(), length); + + LowpanCredential value; + value.readFromParcel(&p); + return value; +} + +/** + * Creates a Java byte[] array and writes the contents of 'addr' to it as a Parcel containing + * exactly one object. + * + * Every LowpanCredential maps to a unique parcel object, so both 'marshall(e, unmarshall(e, x))' and + * 'unmarshall(e, marshall(e, x))' should be fixed points. + */ +static jbyteArray marshall(JNIEnv* env, const LowpanCredential& addr) { + android::Parcel p; + addr.writeToParcel(&p); + const int length = p.dataSize(); + + jbyteArray parcelData = env->NewByteArray(length); + env->SetByteArrayRegion(parcelData, 0, length, reinterpret_cast<const jbyte*>(p.data())); + + return parcelData; +} + +extern "C" +JNIEXPORT jbyteArray Java_android_net_lowpan_LowpanCredentialTest_readAndWriteNative(JNIEnv* env, jclass, + jbyteArray inParcel) { + const LowpanCredential value = unmarshall(env, inParcel); + return marshall(env, value); +} diff --git a/lowpan/tests/jni/LowpanCredentialTest.h b/lowpan/tests/jni/LowpanCredentialTest.h new file mode 100644 index 000000000000..9dd988938675 --- /dev/null +++ b/lowpan/tests/jni/LowpanCredentialTest.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef _ANDROID_NET_LOWPANCREDENTIALTEST_H_ +#define _ANDROID_NET_LOWPANCREDENTIALTEST_H_ + +#include <jni.h> +#include <android/net/lowpan/LowpanCredential.h> + +extern "C" +JNIEXPORT jbyteArray Java_android_net_lowpan_LowpanCredentialTest_readAndWriteNative(JNIEnv* env, jclass, + jbyteArray inParcel); + +#endif // _ANDROID_NET_LOWPANCREDENTIALTEST_H_ diff --git a/lowpan/tests/jni/LowpanIdentityTest.cpp b/lowpan/tests/jni/LowpanIdentityTest.cpp new file mode 100644 index 000000000000..1a9ad3338b04 --- /dev/null +++ b/lowpan/tests/jni/LowpanIdentityTest.cpp @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#include <memory> + +#include <binder/Parcel.h> + +#include "LowpanIdentityTest.h" + +using android::net::lowpan::LowpanIdentity; + +/** + * Reads exactly one LowpanIdentity from 'parcelData' assuming that it is a Parcel. Any bytes afterward + * are ignored. + */ +static LowpanIdentity unmarshall(JNIEnv* env, jbyteArray parcelData) { + const int length = env->GetArrayLength(parcelData); + + std::unique_ptr<uint8_t> bytes(new uint8_t[length]); + env->GetByteArrayRegion(parcelData, 0, length, reinterpret_cast<jbyte*>(bytes.get())); + + android::Parcel p; + p.setData(bytes.get(), length); + + LowpanIdentity value; + value.readFromParcel(&p); + return value; +} + +/** + * Creates a Java byte[] array and writes the contents of 'addr' to it as a Parcel containing + * exactly one object. + * + * Every LowpanIdentity maps to a unique parcel object, so both 'marshall(e, unmarshall(e, x))' and + * 'unmarshall(e, marshall(e, x))' should be fixed points. + */ +static jbyteArray marshall(JNIEnv* env, const LowpanIdentity& addr) { + android::Parcel p; + addr.writeToParcel(&p); + const int length = p.dataSize(); + + jbyteArray parcelData = env->NewByteArray(length); + env->SetByteArrayRegion(parcelData, 0, length, reinterpret_cast<const jbyte*>(p.data())); + + return parcelData; +} + +extern "C" +JNIEXPORT jbyteArray Java_android_net_lowpan_LowpanIdentityTest_readAndWriteNative(JNIEnv* env, jclass, + jbyteArray inParcel) { + const LowpanIdentity value = unmarshall(env, inParcel); + return marshall(env, value); +} diff --git a/lowpan/tests/jni/LowpanIdentityTest.h b/lowpan/tests/jni/LowpanIdentityTest.h new file mode 100644 index 000000000000..1d2c4659108d --- /dev/null +++ b/lowpan/tests/jni/LowpanIdentityTest.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef _ANDROID_NET_LOWPANIDENTITYTEST_H_ +#define _ANDROID_NET_LOWPANIDENTITYTEST_H_ + +#include <jni.h> +#include <android/net/lowpan/LowpanIdentity.h> + +extern "C" +JNIEXPORT jbyteArray Java_android_net_lowpan_LowpanIdentityTest_readAndWriteNative(JNIEnv* env, jclass, + jbyteArray inParcel); + +#endif // _ANDROID_NET_LOWPANIDENTITYTEST_H_ diff --git a/lowpan/tests/jni/LowpanProvisionTest.cpp b/lowpan/tests/jni/LowpanProvisionTest.cpp new file mode 100644 index 000000000000..95f64b6bd15a --- /dev/null +++ b/lowpan/tests/jni/LowpanProvisionTest.cpp @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#include <memory> + +#include <binder/Parcel.h> + +#include "LowpanProvisionTest.h" + +using android::net::lowpan::LowpanProvision; + +/** + * Reads exactly one LowpanProvision from 'parcelData' assuming that it is a Parcel. Any bytes afterward + * are ignored. + */ +static LowpanProvision unmarshall(JNIEnv* env, jbyteArray parcelData) { + const int length = env->GetArrayLength(parcelData); + + std::unique_ptr<uint8_t> bytes(new uint8_t[length]); + env->GetByteArrayRegion(parcelData, 0, length, reinterpret_cast<jbyte*>(bytes.get())); + + android::Parcel p; + p.setData(bytes.get(), length); + + LowpanProvision value; + value.readFromParcel(&p); + return value; +} + +/** + * Creates a Java byte[] array and writes the contents of 'addr' to it as a Parcel containing + * exactly one object. + * + * Every LowpanProvision maps to a unique parcel object, so both 'marshall(e, unmarshall(e, x))' and + * 'unmarshall(e, marshall(e, x))' should be fixed points. + */ +static jbyteArray marshall(JNIEnv* env, const LowpanProvision& addr) { + android::Parcel p; + addr.writeToParcel(&p); + const int length = p.dataSize(); + + jbyteArray parcelData = env->NewByteArray(length); + env->SetByteArrayRegion(parcelData, 0, length, reinterpret_cast<const jbyte*>(p.data())); + + return parcelData; +} + +extern "C" +JNIEXPORT jbyteArray Java_android_net_lowpan_LowpanProvisionTest_readAndWriteNative(JNIEnv* env, jclass, + jbyteArray inParcel) { + const LowpanProvision value = unmarshall(env, inParcel); + return marshall(env, value); +} diff --git a/lowpan/tests/jni/LowpanProvisionTest.h b/lowpan/tests/jni/LowpanProvisionTest.h new file mode 100644 index 000000000000..49211b5ee45c --- /dev/null +++ b/lowpan/tests/jni/LowpanProvisionTest.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef _ANDROID_NET_LOWPANPROVISIONTEST_H_ +#define _ANDROID_NET_LOWPANPROVISIONTEST_H_ + +#include <jni.h> +#include <android/net/lowpan/LowpanProvision.h> + +extern "C" +JNIEXPORT jbyteArray Java_android_net_lowpan_LowpanProvisionTest_readAndWriteNative(JNIEnv* env, jclass, + jbyteArray inParcel); + +#endif // _ANDROID_NET_LOWPANPROVISIONTEST_H_ |