Merge changes from topic 'android-lowpan-next'
* changes:
lowpan: AIDL refactor to no longer use property design pattern
LowpanException: Refactor exception handling
lowpan: Introduce new unit tests for data classes
lowpan: Make various data classes Parcelable
lowpan: Remove libandroid_net_lowpan from platform/frameworks/base
LowpanEnergyScanResult: Remove `public` designation from setChannel/setMaxRssi
diff --git a/lowpan/Android.mk b/lowpan/Android.mk
deleted file mode 100644
index 0079958..0000000
--- 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 329e9fa..603dc3c 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 @@
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 @@
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 0ae01a1..5e4049a 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 c20a6f8..9743fce 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 0000000..e917d45
--- /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 0000000..7aceb71
--- /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 0000000..a4346f98
--- /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 0000000..e51d382
--- /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 0000000..9464fea
--- /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 e18abd5..345a4c5 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 @@
* @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 @@
}
@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 @@
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 0000000..0676deb
--- /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 621affe..52b1c6d 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;
- // Public Getters and Setters
+ /** @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() {}
+
+ 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 @@
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 ee75f1a..8f75e8d 100644
--- a/lowpan/java/android/net/lowpan/LowpanCommissioningSession.java
+++ b/lowpan/java/android/net/lowpan/LowpanCommissioningSession.java
@@ -18,9 +18,11 @@
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 @@
* @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 @@
* @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 0000000..af0c2d6
--- /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 ca860215..e9126f9 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 @@
* @hide
*/
// @SystemApi
-public class LowpanCredential {
+public class LowpanCredential implements Parcelable {
public static final int UNSPECIFIED_KEY_INDEX = 0;
@@ -49,18 +53,18 @@
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 @@
return mMasterKey != null;
}
- void addToMap(Map<String, Object> parameters) throws LowpanException {
+ public String toSensitiveString() {
+ 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());
+ sb.append(" MasterKey:").append(HexDump.toHexString(mMasterKey));
+ 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 String toString() {
+ StringBuffer sb = new StringBuffer();
+
+ sb.append("<LowpanCredential");
+
+ if (isMasterKey()) {
+ // 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 {
+ 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 91ed19c..da87752 100644
--- a/lowpan/java/android/net/lowpan/LowpanEnergyScanResult.java
+++ b/lowpan/java/android/net/lowpan/LowpanEnergyScanResult.java
@@ -28,7 +28,7 @@
private int mChannel = UNKNOWN;
private int mMaxRssi = UNKNOWN;
- public LowpanEnergyScanResult() {}
+ LowpanEnergyScanResult() {}
public int getChannel() {
return mChannel;
@@ -38,11 +38,11 @@
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 5a1f729..5dfce48 100644
--- a/lowpan/java/android/net/lowpan/LowpanException.java
+++ b/lowpan/java/android/net/lowpan/LowpanException.java
@@ -28,245 +28,65 @@
*/
// @SystemApi
public class LowpanException extends AndroidException {
- // Make the eclipse warning about serializable exceptions go away
- private static final long serialVersionUID = 0x31863cbe562b0e11l; // randomly generated
-
- 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 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);
-
- case ILowpanInterface.ERROR_PERMISSION_DENIED:
- throw new SecurityException(e.getMessage(), e);
-
- case ILowpanInterface.ERROR_DISABLED:
- reason = LowpanException.LOWPAN_DISABLED;
- break;
-
- 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;
-
- 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;
-
- case ILowpanInterface.ERROR_JOIN_FAILED_UNKNOWN:
- reason = LowpanException.LOWPAN_JOIN_FAILED_UNKNOWN;
- break;
-
- case ILowpanInterface.ERROR_JOIN_FAILED_AT_SCAN:
- reason = LowpanException.LOWPAN_JOIN_FAILED_AT_SCAN;
- break;
-
- case ILowpanInterface.ERROR_JOIN_FAILED_AT_AUTH:
- reason = LowpanException.LOWPAN_JOIN_FAILED_AT_AUTH;
- break;
-
- case ILowpanInterface.ERROR_FORM_FAILED_AT_SCAN:
- reason = LowpanException.LOWPAN_FORM_FAILED_AT_SCAN;
- break;
-
- 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() {}
public LowpanException(String message) {
- super(getCombinedMessage(LOWPAN_ERROR, message));
- mReason = LOWPAN_ERROR;
+ super(message);
}
- public LowpanException(int problem, String message, Throwable cause) {
- super(getCombinedMessage(problem, message), cause);
- mReason = problem;
+ public LowpanException(String message, Throwable cause) {
+ super(message, cause);
}
- public LowpanException(int problem, Throwable cause) {
- super(getDefaultMessage(problem), cause);
- mReason = problem;
+ public LowpanException(Exception cause) {
+ super(cause);
}
- /** @hide */
- public static String getDefaultMessage(int problem) {
- String problemString;
+ /* 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:
+ throw new InterfaceDisabledException(e);
- // TODO: Does this need localization?
+ case ILowpanInterface.ERROR_WRONG_STATE:
+ throw new WrongStateException(e);
- 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:
+ case ILowpanInterface.ERROR_CANCELED:
+ throw new OperationCanceledException(e);
+
+ case ILowpanInterface.ERROR_JOIN_FAILED_UNKNOWN:
+ throw new JoinFailedException(e);
+
+ case ILowpanInterface.ERROR_JOIN_FAILED_AT_SCAN:
+ throw new JoinFailedAtScanException(e);
+
+ case ILowpanInterface.ERROR_JOIN_FAILED_AT_AUTH:
+ throw new JoinFailedAtAuthException(e);
+
+ case ILowpanInterface.ERROR_FORM_FAILED_AT_SCAN:
+ throw new NetworkAlreadyExistsException(e);
+
+ case ILowpanInterface.ERROR_FEATURE_NOT_SUPPORTED:
+ throw new LowpanException(
+ e.getMessage() != null ? e.getMessage() : "Feature not supported", e);
+
+ case ILowpanInterface.ERROR_NCP_PROBLEM:
+ throw new LowpanRuntimeException(
+ e.getMessage() != null ? e.getMessage() : "NCP problem", e);
+
+ case ILowpanInterface.ERROR_INVALID_ARGUMENT:
+ throw new LowpanRuntimeException(
+ e.getMessage() != null ? e.getMessage() : "Invalid argument", e);
+
+ case ILowpanInterface.ERROR_UNSPECIFIED:
default:
- problemString = "The requested LoWPAN operation failed";
- break;
+ throw new LowpanRuntimeException(e);
}
-
- return problemString;
- }
-
- private static String getCombinedMessage(int problem, String message) {
- String problemString = getProblemString(problem);
- return String.format("%s (%d): %s", problemString, problem, message);
- }
-
- private static String getProblemString(int problem) {
- String problemString;
-
- 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;
- default:
- problemString = "LOWPAN_ERROR_CODE_" + problem;
- break;
- }
-
- 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 0000000..fcef98f
--- /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 2d36f7f..6cb1f98 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 @@
* @hide
*/
// @SystemApi
-public class LowpanIdentity {
+public class LowpanIdentity implements Parcelable {
+ private static final String TAG = LowpanIdentity.class.getSimpleName();
// Constants
-
- /** @hide */
- public static final int TYPE_ZIGBEE = 1;
-
- /** @hide */
- public static final int TYPE_ZIGBEE_IP = 2;
-
- /** @hide */
- public static final int TYPE_THREAD = 3;
-
- public static final int UNKNOWN = Integer.MAX_VALUE;
-
+ public static final int UNSPECIFIED_CHANNEL = -1;
+ public static final int UNSPECIFIED_PANID = 0xFFFFFFFF;
// Builder
/** @hide */
// @SystemApi
public static class Builder {
- private final LowpanIdentity identity = new LowpanIdentity();
+ private static final StringPrep stringPrep =
+ StringPrep.getInstance(StringPrep.RFC3920_RESOURCEPREP);
- public Builder setName(String x) {
- identity.mName = x;
+ 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();
+ }
+
+ 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 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;
+ }
+
+ 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;
+ }
+
+ // Non-normal names must be rendered differently to avoid confusion.
+ if (!mIdentity.mIsNameValid) {
+ mIdentity.mName = "«" + escape(name) + "»";
+ }
+
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 @@
// 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 @@
return mChannel;
}
- static void addToMap(Map<String, Object> parameters, LowpanIdentity networkInfo) {
- if (networkInfo.getName() != null) {
- LowpanProperties.KEY_NETWORK_NAME.putInMap(parameters, networkInfo.getName());
- }
- if (networkInfo.getPanid() != LowpanIdentity.UNKNOWN) {
- LowpanProperties.KEY_NETWORK_PANID.putInMap(parameters, networkInfo.getPanid());
- }
- if (networkInfo.getChannel() != LowpanIdentity.UNKNOWN) {
- LowpanProperties.KEY_CHANNEL.putInMap(parameters, networkInfo.getChannel());
- }
- if (networkInfo.getXpanid() != null) {
- LowpanProperties.KEY_NETWORK_XPANID.putInMap(parameters, networkInfo.getXpanid());
- }
- }
-
- void addToMap(Map<String, Object> parameters) {
- addToMap(parameters, this);
- }
-
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
- sb.append("Name: ").append(mName == null ? "<none>" : mName);
+ sb.append("Name:").append(getName());
- if (mXpanid != null) {
- sb.append(", XPANID: ").append(HexDump.toHexString(mXpanid));
+ if (mType.length() > 0) {
+ sb.append(", Type:").append(mType);
}
- if (mPanid != UNKNOWN) {
- sb.append(", PANID: ").append(String.format("0x%04X", mPanid));
+ if (mXpanid.length > 0) {
+ sb.append(", XPANID:").append(HexDump.toHexString(mXpanid));
}
- if (mChannel != UNKNOWN) {
- sb.append(", Channel: ").append(mChannel);
+ if (mPanid != UNSPECIFIED_PANID) {
+ sb.append(", PANID:").append(String.format("0x%04X", mPanid));
+ }
+
+ if (mChannel != UNSPECIFIED_CHANNEL) {
+ sb.append(", Channel:").append(mChannel);
}
return sb.toString();
}
+
+ @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 int hashCode() {
+ return Objects.hash(
+ Arrays.hashCode(mRawName), mType, Arrays.hashCode(mXpanid), mPanid, mChannel);
+ }
+
+ /** Implement the Parcelable interface. */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** 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);
+ }
+
+ /** Implement the Parcelable interface. */
+ public static final Creator<LowpanIdentity> CREATOR =
+ new Creator<LowpanIdentity>() {
+
+ public LowpanIdentity createFromParcel(Parcel in) {
+ Builder builder = new Builder();
+
+ 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 55bf399..57e9135 100644
--- a/lowpan/java/android/net/lowpan/LowpanInterface.java
+++ b/lowpan/java/android/net/lowpan/LowpanInterface.java
@@ -28,8 +28,6 @@
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 @@
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 @@
* 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 @@
* <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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 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 @@
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 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 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 @@
* <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 @@
throw x.rethrowAsRuntimeException();
} catch (ServiceSpecificException x) {
- throw LowpanException.rethrowAsLowpanException(x);
+ throw LowpanException.rethrowFromServiceSpecificException(x);
}
}
@@ -382,9 +300,17 @@
*/
public @NonNull LowpanCommissioningSession startCommissioningSession(
@NonNull LowpanBeaconInfo beaconInfo) throws LowpanException {
+ try {
+ mBinder.startCommissioningSession(beaconInfo);
- /* TODO: Implement startCommissioningSession */
- throw new LowpanException(LowpanException.LOWPAN_FEATURE_NOT_SUPPORTED);
+ return new LowpanCommissioningSession(mBinder, beaconInfo, mLooper);
+
+ } catch (RemoteException x) {
+ throw x.rethrowAsRuntimeException();
+
+ } catch (ServiceSpecificException x) {
+ throw LowpanException.rethrowFromServiceSpecificException(x);
+ }
}
/**
@@ -403,7 +329,7 @@
throw x.rethrowAsRuntimeException();
} catch (ServiceSpecificException x) {
- throw LowpanException.rethrowAsLowpanException(x);
+ throw LowpanException.rethrowFromServiceSpecificException(x);
}
}
@@ -415,6 +341,9 @@
try {
return mBinder.getName();
+ } catch (DeadObjectException x) {
+ return "";
+
} catch (RemoteException x) {
throw x.rethrowAsRuntimeException();
}
@@ -428,9 +357,13 @@
*/
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 @@
* @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 boolean isUp() {
try {
- return getPropertyAsBoolean(LowpanProperties.KEY_INTERFACE_UP);
- } catch (LowpanException x) {
- return false;
- }
- }
+ return mBinder.isUp();
- /**
- * 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 (DeadObjectException x) {
+ return false;
+
+ } catch (RemoteException x) {
+ throw x.rethrowAsRuntimeException();
+ }
}
/**
@@ -480,9 +413,13 @@
*/
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 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 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();
+
+ } catch (DeadObjectException x) {
+ return new LowpanIdentity();
+
+ } catch (RemoteException x) {
+ throw x.rethrowAsRuntimeException();
}
-
- return builder.build();
- }
-
- /**
- * TODO: doc
- *
- * @hide
- */
- public void setLowpanIdentity(LowpanIdentity network) throws LowpanException {
- Map<String, Object> map = new HashMap();
- LowpanIdentity.addToMap(map, network);
- setProperties(map);
}
/** 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);
+ return mBinder.getLowpanCredential();
- 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());
+ } catch (RemoteException x) {
+ throw x.rethrowAsRuntimeException();
}
-
- return credential;
}
- /**
- * TODO: doc
- *
- * @hide
- */
- public void setLowpanCredential(LowpanCredential networkCredential) throws LowpanException {
- Map<String, Object> map = new HashMap();
- networkCredential.addToMap(map);
- setProperties(map);
+ public @NonNull String[] getSupportedNetworkTypes() throws LowpanException {
+ try {
+ return mBinder.getSupportedNetworkTypes();
+
+ } catch (RemoteException x) {
+ throw x.rethrowAsRuntimeException();
+
+ } catch (ServiceSpecificException x) {
+ throw LowpanException.rethrowFromServiceSpecificException(x);
+ }
+ }
+
+ 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 @@
}
}
- @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 onLinkNetworkAdded(IpPrefix prefix) {
- // Support for this event isn't yet implemented.
+ @Override
+ public void onConnectedChanged(boolean value) {
+ mHandler.post(() -> cb.onConnectedChanged(value));
}
- @Override public void onLinkNetworkRemoved(IpPrefix prefix) {
- // Support for this event isn't yet implemented.
+ @Override
+ public void onUpChanged(boolean value) {
+ mHandler.post(() -> cb.onUpChanged(value));
}
- @Override public void onLinkAddressAdded(String address) {
- // Support for this event isn't yet implemented.
+ @Override
+ public void onRoleChanged(String value) {
+ mHandler.post(() -> cb.onRoleChanged(value));
}
- @Override public void onLinkAddressRemoved(String address) {
- // Support for this event isn't yet implemented.
+ @Override
+ public void onStateChanged(String value) {
+ mHandler.post(() -> cb.onStateChanged(value));
+ }
+
+ @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 onReceiveFromCommissioner(byte[] packet) {
+ // This is only used by the LowpanCommissioningSession.
}
};
try {
@@ -752,9 +715,9 @@
*
* @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 @@
throw x.rethrowAsRuntimeException();
} catch (ServiceSpecificException x) {
- throw LowpanException.rethrowAsLowpanException(x);
+ throw LowpanException.rethrowFromServiceSpecificException(x);
}
}
@@ -775,15 +738,15 @@
*
* @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 @@
throw x.rethrowAsRuntimeException();
} catch (ServiceSpecificException x) {
- throw LowpanException.rethrowAsLowpanException(x);
+ throw LowpanException.rethrowFromServiceSpecificException(x);
}
}
@@ -837,7 +800,7 @@
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 f835260..cc45ff85 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 0000000..100e9dc
--- /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 7028807..f126003 100644
--- a/lowpan/java/android/net/lowpan/LowpanProvision.java
+++ b/lowpan/java/android/net/lowpan/LowpanProvision.java
@@ -18,7 +18,9 @@
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 @@
* @hide
*/
// @SystemApi
-public class LowpanProvision {
+public class LowpanProvision implements Parcelable {
// Builder
@@ -69,20 +71,6 @@
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 @@
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 0000000..71a5a13
--- /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 b0557ee..59156c4 100644
--- a/lowpan/java/android/net/lowpan/LowpanScanner.java
+++ b/lowpan/java/android/net/lowpan/LowpanScanner.java
@@ -21,7 +21,6 @@
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 @@
*/
// @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 @@
ILowpanNetScanCallback binderListener =
new ILowpanNetScanCallback.Stub() {
- public void onNetScanBeacon(Map parameters) {
+ public void onNetScanBeacon(LowpanBeaconInfo beaconInfo) {
Callback callback;
Handler handler;
@@ -187,12 +186,7 @@
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 @@
throw x.rethrowAsRuntimeException();
} catch (ServiceSpecificException x) {
- throw LowpanException.rethrowAsLowpanException(x);
+ throw LowpanException.rethrowFromServiceSpecificException(x);
}
}
@@ -246,9 +240,6 @@
} catch (RemoteException x) {
throw x.rethrowAsRuntimeException();
-
- } catch (ServiceSpecificException x) {
- Log.e(TAG, x.toString());
}
}
@@ -315,7 +306,7 @@
throw x.rethrowAsRuntimeException();
} catch (ServiceSpecificException x) {
- throw LowpanException.rethrowAsLowpanException(x);
+ throw LowpanException.rethrowFromServiceSpecificException(x);
}
}
@@ -330,9 +321,6 @@
} 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 0000000..90ef498
--- /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 0000000..fcafe3a
--- /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 0000000..3565419
--- /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 bb0a944..1ea471a 100644
--- a/lowpan/tests/Android.mk
+++ b/lowpan/tests/Android.mk
@@ -54,8 +54,35 @@
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_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 0000000..6dbb3ed
--- /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 0000000..eac4398
--- /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 0000000..26e3334
--- /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 0000000..1242e55
--- /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/java/android/net/lowpan/LowpanInterfaceTest.java b/lowpan/tests/java/android/net/lowpan/LowpanInterfaceTest.java
new file mode 100644
index 0000000..f26a37e
--- /dev/null
+++ b/lowpan/tests/java/android/net/lowpan/LowpanInterfaceTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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.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;
+
+/** Unit tests for android.net.lowpan.LowpanInterface. */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class LowpanInterfaceTest {
+ private static final String TEST_PACKAGE_NAME = "TestPackage";
+
+ @Mock Context mContext;
+ @Mock ILowpanInterface mLowpanInterfaceService;
+ @Mock IBinder mLowpanInterfaceBinder;
+ @Mock ApplicationInfo mApplicationInfo;
+ @Mock IBinder mAppBinder;
+ @Mock LowpanInterface.Callback mLowpanInterfaceCallback;
+
+ private Handler mHandler;
+ private final TestLooper mTestLooper = new TestLooper();
+ private ILowpanInterfaceListener mInterfaceListener;
+ private LowpanInterface mLowpanInterface;
+ private Map<String, Object> mPropertyMap;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo);
+ when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(mLowpanInterfaceService.getName()).thenReturn("wpan0");
+ when(mLowpanInterfaceService.asBinder()).thenReturn(mLowpanInterfaceBinder);
+
+ mLowpanInterface =
+ new LowpanInterface(mContext, mLowpanInterfaceService, mTestLooper.getLooper());
+ }
+
+ @Test
+ public void testStateChangedCallback() 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.onStateChanged(LowpanInterface.STATE_OFFLINE);
+ mTestLooper.dispatchAll();
+
+ // Verify that the property was changed
+ verify(mLowpanInterfaceCallback)
+ .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
similarity index 99%
rename from lowpan/tests/src/android/net/lowpan/LowpanManagerTest.java
rename to lowpan/tests/java/android/net/lowpan/LowpanManagerTest.java
index 481ad76..3dd7504 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 0000000..3be2f26
--- /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 0000000..efc5f18
--- /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 0000000..1ba8eaf
--- /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 0000000..03bb72a
--- /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 0000000..3b29a90
--- /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 0000000..fc860b2
--- /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 0000000..9dd9889
--- /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 0000000..1a9ad33
--- /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 0000000..1d2c465
--- /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 0000000..95f64b6
--- /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 0000000..49211b5
--- /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_
diff --git a/lowpan/tests/src/android/net/lowpan/LowpanInterfaceTest.java b/lowpan/tests/src/android/net/lowpan/LowpanInterfaceTest.java
deleted file mode 100644
index 455ee08..0000000
--- a/lowpan/tests/src/android/net/lowpan/LowpanInterfaceTest.java
+++ /dev/null
@@ -1,97 +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.
- */
-
-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.os.Handler;
-import android.os.IBinder;
-import android.os.test.TestLooper;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.SmallTest;
-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)
-@SmallTest
-public class LowpanInterfaceTest {
- private static final String TEST_PACKAGE_NAME = "TestPackage";
-
- @Mock Context mContext;
- @Mock ILowpanInterface mLowpanInterfaceService;
- @Mock IBinder mLowpanInterfaceBinder;
- @Mock ApplicationInfo mApplicationInfo;
- @Mock IBinder mAppBinder;
- @Mock LowpanInterface.Callback mLowpanInterfaceCallback;
-
- private Handler mHandler;
- private final TestLooper mTestLooper = new TestLooper();
- private ILowpanInterfaceListener mInterfaceListener;
- private LowpanInterface mLowpanInterface;
- private Map<String, Object> mPropertyMap;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo);
- when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME);
- when(mLowpanInterfaceService.getName()).thenReturn("wpan0");
- when(mLowpanInterfaceService.asBinder()).thenReturn(mLowpanInterfaceBinder);
-
- mLowpanInterface = new LowpanInterface(mContext, mLowpanInterfaceService, mTestLooper.getLooper());
- }
-
- @Test
- public void testStateChangedCallback() throws Exception {
- // Register our callback
- mLowpanInterface.registerCallback(mLowpanInterfaceCallback);
-
- // Verify a listener was added
- verify(mLowpanInterfaceService)
- .addListener(
- argThat(
- listener -> {
- mInterfaceListener = listener;
- 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);
- mTestLooper.dispatchAll();
-
- // Verify that the property was changed
- verify(mLowpanInterfaceCallback)
- .onStateChanged(
- argThat(stateString -> stateString.equals(LowpanInterface.STATE_OFFLINE)));
- }
-}