From 80aca1e3b3d3f7afd64a7f18cb2f3ae556f46ccf Mon Sep 17 00:00:00 2001 From: Robert Quattlebaum Date: Fri, 14 Jul 2017 12:02:19 -0700 Subject: lowpan: Make various data classes Parcelable This change updates several of the data classes in `android.net.lowpan` to be parcelable. This allows them to be used directly for inter-process communication. Bug: b/63707448 b/63708348 Change-Id: Ib5e8cad153534948ff4b43a2fda82f3db250839e Test: Confirmed with unit tests from change id I41d590b1e77dc41873c4b9e9bf1b7f1bf859f74e --- .../java/android/net/lowpan/LowpanBeaconInfo.aidl | 19 ++ .../java/android/net/lowpan/LowpanBeaconInfo.java | 172 +++++++++++---- .../java/android/net/lowpan/LowpanChannelInfo.aidl | 19 ++ .../java/android/net/lowpan/LowpanChannelInfo.java | 158 ++++++++++++-- .../java/android/net/lowpan/LowpanCredential.aidl | 19 ++ .../java/android/net/lowpan/LowpanCredential.java | 99 ++++++++- lowpan/java/android/net/lowpan/LowpanIdentity.aidl | 19 ++ lowpan/java/android/net/lowpan/LowpanIdentity.java | 236 ++++++++++++++------- .../java/android/net/lowpan/LowpanProvision.aidl | 19 ++ .../java/android/net/lowpan/LowpanProvision.java | 83 ++++++-- 10 files changed, 683 insertions(+), 160 deletions(-) create mode 100644 lowpan/java/android/net/lowpan/LowpanBeaconInfo.aidl create mode 100644 lowpan/java/android/net/lowpan/LowpanChannelInfo.aidl create mode 100644 lowpan/java/android/net/lowpan/LowpanCredential.aidl create mode 100644 lowpan/java/android/net/lowpan/LowpanIdentity.aidl create mode 100644 lowpan/java/android/net/lowpan/LowpanProvision.aidl (limited to 'lowpan') diff --git a/lowpan/java/android/net/lowpan/LowpanBeaconInfo.aidl b/lowpan/java/android/net/lowpan/LowpanBeaconInfo.aidl new file mode 100644 index 000000000000..9464fea02d18 --- /dev/null +++ b/lowpan/java/android/net/lowpan/LowpanBeaconInfo.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.lowpan; + +parcelable LowpanBeaconInfo cpp_header "android/net/lowpan/LowpanBeaconInfo.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanBeaconInfo.java b/lowpan/java/android/net/lowpan/LowpanBeaconInfo.java index e18abd5bf23f..345a4c504b5b 100644 --- a/lowpan/java/android/net/lowpan/LowpanBeaconInfo.java +++ b/lowpan/java/android/net/lowpan/LowpanBeaconInfo.java @@ -16,9 +16,12 @@ package android.net.lowpan; +import android.os.Parcel; +import android.os.Parcelable; import com.android.internal.util.HexDump; +import java.util.Arrays; import java.util.Collection; -import java.util.Map; +import java.util.Objects; import java.util.TreeSet; /** @@ -27,70 +30,93 @@ import java.util.TreeSet; * @hide */ // @SystemApi -public class LowpanBeaconInfo extends LowpanIdentity { +public class LowpanBeaconInfo implements Parcelable { + public static final int UNKNOWN_RSSI = Integer.MAX_VALUE; + public static final int UNKNOWN_LQI = 0; - private int mRssi = UNKNOWN; - private int mLqi = UNKNOWN; + private LowpanIdentity mIdentity; + private int mRssi = UNKNOWN_RSSI; + private int mLqi = UNKNOWN_LQI; private byte[] mBeaconAddress = null; private final TreeSet 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 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; } @@ -111,27 +137,22 @@ public class LowpanBeaconInfo extends LowpanIdentity { return mFlags.contains(flag); } - @Override - void addToMap(Map parameters) { - super.addToMap(parameters); - } - @Override public String toString() { StringBuffer sb = new StringBuffer(); - sb.append(super.toString()); + sb.append(mIdentity.toString()); - if (mRssi != UNKNOWN) { - sb.append(", RSSI: ").append(mRssi); + if (mRssi != UNKNOWN_RSSI) { + sb.append(", RSSI:").append(mRssi).append("dBm"); } - if (mLqi != UNKNOWN) { - sb.append(", LQI: ").append(mLqi); + if (mLqi != UNKNOWN_LQI) { + sb.append(", LQI:").append(mLqi); } - if (mBeaconAddress != null) { - sb.append(", BeaconAddress: ").append(HexDump.toHexString(mBeaconAddress)); + if (mBeaconAddress.length > 0) { + sb.append(", BeaconAddress:").append(HexDump.toHexString(mBeaconAddress)); } for (Integer flag : mFlags) { @@ -147,4 +168,67 @@ public class LowpanBeaconInfo extends LowpanIdentity { return sb.toString(); } + + @Override + public int hashCode() { + return Objects.hash(mIdentity, mRssi, mLqi, Arrays.hashCode(mBeaconAddress), mFlags); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof LowpanBeaconInfo)) { + return false; + } + LowpanBeaconInfo rhs = (LowpanBeaconInfo) obj; + return mIdentity.equals(rhs.mIdentity) + && Arrays.equals(mBeaconAddress, rhs.mBeaconAddress) + && mRssi == rhs.mRssi + && mLqi == rhs.mLqi + && mFlags.equals(rhs.mFlags); + } + + /** Implement the Parcelable interface. */ + @Override + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface. */ + @Override + public void writeToParcel(Parcel dest, int flags) { + mIdentity.writeToParcel(dest, flags); + dest.writeInt(mRssi); + dest.writeInt(mLqi); + dest.writeByteArray(mBeaconAddress); + + dest.writeInt(mFlags.size()); + for (Integer val : mFlags) { + dest.writeInt(val); + } + } + + /** Implement the Parcelable interface. */ + public static final Creator CREATOR = + new Creator() { + public LowpanBeaconInfo createFromParcel(Parcel in) { + Builder builder = new Builder(); + + builder.setLowpanIdentity(LowpanIdentity.CREATOR.createFromParcel(in)); + + builder.setRssi(in.readInt()); + builder.setLqi(in.readInt()); + + builder.setBeaconAddress(in.createByteArray()); + + for (int i = in.readInt(); i > 0; i--) { + builder.setFlag(in.readInt()); + } + + return builder.build(); + } + + public LowpanBeaconInfo[] newArray(int size) { + return new LowpanBeaconInfo[size]; + } + }; } diff --git a/lowpan/java/android/net/lowpan/LowpanChannelInfo.aidl b/lowpan/java/android/net/lowpan/LowpanChannelInfo.aidl new file mode 100644 index 000000000000..0676deb6c6df --- /dev/null +++ b/lowpan/java/android/net/lowpan/LowpanChannelInfo.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.lowpan; + +parcelable LowpanChannelInfo cpp_header "android/net/lowpan/LowpanChannelInfo.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanChannelInfo.java b/lowpan/java/android/net/lowpan/LowpanChannelInfo.java index 621affee6d06..52b1c6d6a3e3 100644 --- a/lowpan/java/android/net/lowpan/LowpanChannelInfo.java +++ b/lowpan/java/android/net/lowpan/LowpanChannelInfo.java @@ -16,22 +16,66 @@ package android.net.lowpan; -/** Provides detailed information about a given channel. */ +import android.os.Parcel; +import android.os.Parcelable; +import java.util.Objects; + +/** + * Provides detailed information about a given channel. + * + * @hide + */ // @SystemApi -public class LowpanChannelInfo { +public class LowpanChannelInfo implements Parcelable { public static final int UNKNOWN_POWER = Integer.MAX_VALUE; + public static final float UNKNOWN_FREQUENCY = 0.0f; + public static final float UNKNOWN_BANDWIDTH = 0.0f; - // Instance Variables - - private String mName = null; private int mIndex = 0; - private boolean mIsMaskedByRegulatoryDomain = false; - private float mSpectrumCenterFrequency = 0.0f; - private float mSpectrumBandwidth = 0.0f; + private String mName = null; + private float mSpectrumCenterFrequency = UNKNOWN_FREQUENCY; + private float mSpectrumBandwidth = UNKNOWN_BANDWIDTH; private int mMaxTransmitPower = UNKNOWN_POWER; + private boolean mIsMaskedByRegulatoryDomain = false; + + /** @hide */ + public static LowpanChannelInfo getChannelInfoForIeee802154Page0(int index) { + LowpanChannelInfo info = new LowpanChannelInfo(); + + if (index < 0) { + info = null; + + } else if (index == 0) { + info.mSpectrumCenterFrequency = 868300000.0f; + info.mSpectrumBandwidth = 600000.0f; + + } else if (index < 11) { + info.mSpectrumCenterFrequency = 906000000.0f - (2000000.0f * 1) + 2000000.0f * (index); + info.mSpectrumBandwidth = 0; // Unknown + + } else if (index < 26) { + info.mSpectrumCenterFrequency = + 2405000000.0f - (5000000.0f * 11) + 5000000.0f * (index); + info.mSpectrumBandwidth = 2000000.0f; + + } else { + info = null; + } + + info.mName = Integer.toString(index); + + return info; + } + + private LowpanChannelInfo() {} - // Public Getters and Setters + private LowpanChannelInfo(int index, String name, float cf, float bw) { + mIndex = index; + mName = name; + mSpectrumCenterFrequency = cf; + mSpectrumBandwidth = bw; + } public String getName() { return mName; @@ -63,22 +107,110 @@ public class LowpanChannelInfo { sb.append("Channel ").append(mIndex); - if (mName != null) { + if (mName != null && !mName.equals(Integer.toString(mIndex))) { sb.append(" (").append(mName).append(")"); } if (mSpectrumCenterFrequency > 0.0f) { - sb.append(", SpectrumCenterFrequency: ").append(mSpectrumCenterFrequency).append("Hz"); + if (mSpectrumCenterFrequency > 1000000000.0f) { + sb.append(", SpectrumCenterFrequency: ") + .append(mSpectrumCenterFrequency / 1000000000.0f) + .append("GHz"); + } else if (mSpectrumCenterFrequency > 1000000.0f) { + sb.append(", SpectrumCenterFrequency: ") + .append(mSpectrumCenterFrequency / 1000000.0f) + .append("MHz"); + } else { + sb.append(", SpectrumCenterFrequency: ") + .append(mSpectrumCenterFrequency / 1000.0f) + .append("kHz"); + } } if (mSpectrumBandwidth > 0.0f) { - sb.append(", SpectrumBandwidth: ").append(mSpectrumBandwidth).append("Hz"); + if (mSpectrumBandwidth > 1000000000.0f) { + sb.append(", SpectrumBandwidth: ") + .append(mSpectrumBandwidth / 1000000000.0f) + .append("GHz"); + } else if (mSpectrumBandwidth > 1000000.0f) { + sb.append(", SpectrumBandwidth: ") + .append(mSpectrumBandwidth / 1000000.0f) + .append("MHz"); + } else { + sb.append(", SpectrumBandwidth: ") + .append(mSpectrumBandwidth / 1000.0f) + .append("kHz"); + } } if (mMaxTransmitPower != UNKNOWN_POWER) { - sb.append(", MaxTransmitPower: ").append(mMaxTransmitPower); + sb.append(", MaxTransmitPower: ").append(mMaxTransmitPower).append("dBm"); } return sb.toString(); } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof LowpanChannelInfo)) { + return false; + } + LowpanChannelInfo rhs = (LowpanChannelInfo) obj; + return Objects.equals(mName, rhs.mName) + && mIndex == rhs.mIndex + && mIsMaskedByRegulatoryDomain == rhs.mIsMaskedByRegulatoryDomain + && mSpectrumCenterFrequency == rhs.mSpectrumCenterFrequency + && mSpectrumBandwidth == rhs.mSpectrumBandwidth + && mMaxTransmitPower == rhs.mMaxTransmitPower; + } + + @Override + public int hashCode() { + return Objects.hash( + mName, + mIndex, + mIsMaskedByRegulatoryDomain, + mSpectrumCenterFrequency, + mSpectrumBandwidth, + mMaxTransmitPower); + } + + /** Implement the Parcelable interface. */ + @Override + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface. */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mIndex); + dest.writeString(mName); + dest.writeFloat(mSpectrumCenterFrequency); + dest.writeFloat(mSpectrumBandwidth); + dest.writeInt(mMaxTransmitPower); + dest.writeBoolean(mIsMaskedByRegulatoryDomain); + } + + /** Implement the Parcelable interface. */ + public static final Creator CREATOR = + new Creator() { + + 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/LowpanCredential.aidl b/lowpan/java/android/net/lowpan/LowpanCredential.aidl new file mode 100644 index 000000000000..af0c2d63474a --- /dev/null +++ b/lowpan/java/android/net/lowpan/LowpanCredential.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.lowpan; + +parcelable LowpanCredential cpp_header "android/net/lowpan/LowpanCredential.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanCredential.java b/lowpan/java/android/net/lowpan/LowpanCredential.java index ca8602151515..e9126f9f2f7b 100644 --- a/lowpan/java/android/net/lowpan/LowpanCredential.java +++ b/lowpan/java/android/net/lowpan/LowpanCredential.java @@ -16,7 +16,11 @@ package android.net.lowpan; -import java.util.Map; +import android.os.Parcel; +import android.os.Parcelable; +import com.android.internal.util.HexDump; +import java.util.Arrays; +import java.util.Objects; /** * Describes a credential for a LoWPAN network. @@ -24,7 +28,7 @@ import java.util.Map; * @hide */ // @SystemApi -public class LowpanCredential { +public class LowpanCredential implements Parcelable { public static final int UNSPECIFIED_KEY_INDEX = 0; @@ -49,18 +53,18 @@ public class LowpanCredential { return new LowpanCredential(masterKey, keyIndex); } - public void setMasterKey(byte[] masterKey) { + void setMasterKey(byte[] masterKey) { if (masterKey != null) { masterKey = masterKey.clone(); } mMasterKey = masterKey; } - public void setMasterKeyIndex(int keyIndex) { + void setMasterKeyIndex(int keyIndex) { mMasterKeyIndex = keyIndex; } - public void setMasterKey(byte[] masterKey, int keyIndex) { + void setMasterKey(byte[] masterKey, int keyIndex) { setMasterKey(masterKey); setMasterKeyIndex(keyIndex); } @@ -80,12 +84,89 @@ public class LowpanCredential { return mMasterKey != null; } - void addToMap(Map parameters) throws LowpanException { + public String toSensitiveString() { + StringBuffer sb = new StringBuffer(); + + sb.append(""); + + return sb.toString(); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + + 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 CREATOR = + new Creator() { + + 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/LowpanIdentity.aidl b/lowpan/java/android/net/lowpan/LowpanIdentity.aidl new file mode 100644 index 000000000000..fcef98f5c496 --- /dev/null +++ b/lowpan/java/android/net/lowpan/LowpanIdentity.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.lowpan; + +parcelable LowpanIdentity cpp_header "android/net/lowpan/LowpanIdentity.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanIdentity.java b/lowpan/java/android/net/lowpan/LowpanIdentity.java index 2d36f7fa9789..6cb1f987c5d9 100644 --- a/lowpan/java/android/net/lowpan/LowpanIdentity.java +++ b/lowpan/java/android/net/lowpan/LowpanIdentity.java @@ -16,8 +16,16 @@ package android.net.lowpan; +import android.annotation.NonNull; +import android.icu.text.StringPrep; +import android.icu.text.StringPrepParseException; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; import com.android.internal.util.HexDump; -import java.util.Map; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Objects; /** * Describes an instance of a LoWPAN network. @@ -25,76 +33,100 @@ import java.util.Map; * @hide */ // @SystemApi -public class LowpanIdentity { +public class LowpanIdentity implements Parcelable { + private static final String TAG = LowpanIdentity.class.getSimpleName(); // Constants + public static final int UNSPECIFIED_CHANNEL = -1; + public static final int UNSPECIFIED_PANID = 0xFFFFFFFF; + // Builder /** @hide */ - public static final int TYPE_ZIGBEE = 1; - - /** @hide */ - public static final int TYPE_ZIGBEE_IP = 2; + // @SystemApi + public static class Builder { + private static final StringPrep stringPrep = + StringPrep.getInstance(StringPrep.RFC3920_RESOURCEPREP); + + final LowpanIdentity mIdentity = new LowpanIdentity(); + + private static String escape(@NonNull byte[] bytes) { + StringBuffer sb = new StringBuffer(); + for (byte b : bytes) { + if (b >= 32 && b <= 126) { + sb.append((char) b); + } else { + sb.append(String.format("\\0x%02x", b & 0xFF)); + } + } + return sb.toString(); + } - /** @hide */ - public static final int TYPE_THREAD = 3; + public Builder setLowpanIdentity(@NonNull LowpanIdentity x) { + Objects.requireNonNull(x); + setRawName(x.getRawName()); + setXpanid(x.getXpanid()); + setPanid(x.getPanid()); + setChannel(x.getChannel()); + setType(x.getType()); + return this; + } - public static final int UNKNOWN = Integer.MAX_VALUE; + public Builder setName(@NonNull String name) { + Objects.requireNonNull(name); + try { + mIdentity.mName = stringPrep.prepare(name, StringPrep.DEFAULT); + mIdentity.mRawName = mIdentity.mName.getBytes(StandardCharsets.UTF_8); + mIdentity.mIsNameValid = true; + } catch (StringPrepParseException x) { + Log.w(TAG, x.toString()); + setRawName(name.getBytes(StandardCharsets.UTF_8)); + } + return this; + } - // Builder + public Builder setRawName(@NonNull byte[] name) { + Objects.requireNonNull(name); + mIdentity.mRawName = name.clone(); + mIdentity.mName = new String(name, StandardCharsets.UTF_8); + try { + String nameCheck = stringPrep.prepare(mIdentity.mName, StringPrep.DEFAULT); + mIdentity.mIsNameValid = + Arrays.equals(nameCheck.getBytes(StandardCharsets.UTF_8), name); + } catch (StringPrepParseException x) { + Log.w(TAG, x.toString()); + mIdentity.mIsNameValid = false; + } - /** @hide */ - // @SystemApi - public static class Builder { - private final LowpanIdentity identity = new LowpanIdentity(); + // Non-normal names must be rendered differently to avoid confusion. + if (!mIdentity.mIsNameValid) { + mIdentity.mName = "«" + escape(name) + "»"; + } - public Builder setName(String x) { - identity.mName = x; return this; } public Builder setXpanid(byte x[]) { - identity.mXpanid = (x != null ? x.clone() : null); + mIdentity.mXpanid = (x != null ? x.clone() : null); return this; } public Builder setPanid(int x) { - identity.mPanid = x; + mIdentity.mPanid = x; return this; } - /** @hide */ - public Builder setType(int x) { - identity.mType = x; + public Builder setType(@NonNull String x) { + mIdentity.mType = x; return this; } public Builder setChannel(int x) { - identity.mChannel = x; - return this; - } - - /** @hide */ - Builder updateFromMap(Map map) { - if (map.containsKey(ILowpanInterface.KEY_NETWORK_NAME)) { - setName(LowpanProperties.KEY_NETWORK_NAME.getFromMap(map)); - } - if (map.containsKey(ILowpanInterface.KEY_NETWORK_PANID)) { - setPanid(LowpanProperties.KEY_NETWORK_PANID.getFromMap(map)); - } - if (map.containsKey(ILowpanInterface.KEY_NETWORK_XPANID)) { - setXpanid(LowpanProperties.KEY_NETWORK_XPANID.getFromMap(map)); - } - if (map.containsKey(ILowpanInterface.KEY_CHANNEL)) { - setChannel(LowpanProperties.KEY_CHANNEL.getFromMap(map)); - } - if (map.containsKey(ILowpanInterface.KEY_NETWORK_TYPE)) { - setType(LowpanProperties.KEY_NETWORK_TYPE.getFromMap(map)); - } + mIdentity.mChannel = x; return this; } public LowpanIdentity build() { - return identity; + return mIdentity; } } @@ -102,28 +134,37 @@ public class LowpanIdentity { // Instance Variables - private String mName = null; - private byte[] mXpanid = null; - private int mType = UNKNOWN; - private int mPanid = UNKNOWN; - private int mChannel = UNKNOWN; + private String mName = ""; + private boolean mIsNameValid = true; + private byte[] mRawName = new byte[0]; + private String mType = ""; + private byte[] mXpanid = new byte[0]; + private int mPanid = UNSPECIFIED_PANID; + private int mChannel = UNSPECIFIED_CHANNEL; - // Public Getters and Setters + // Public Getters public String getName() { return mName; } + public boolean isNameValid() { + return mIsNameValid; + } + + public byte[] getRawName() { + return mRawName.clone(); + } + public byte[] getXpanid() { - return mXpanid != null ? mXpanid.clone() : null; + return mXpanid.clone(); } public int getPanid() { return mPanid; } - /** @hide */ - public int getType() { + public String getType() { return mType; } @@ -131,43 +172,84 @@ public class LowpanIdentity { return mChannel; } - static void addToMap(Map parameters, LowpanIdentity networkInfo) { - if (networkInfo.getName() != null) { - LowpanProperties.KEY_NETWORK_NAME.putInMap(parameters, networkInfo.getName()); + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + + sb.append("Name:").append(getName()); + + if (mType.length() > 0) { + sb.append(", Type:").append(mType); } - if (networkInfo.getPanid() != LowpanIdentity.UNKNOWN) { - LowpanProperties.KEY_NETWORK_PANID.putInMap(parameters, networkInfo.getPanid()); + + if (mXpanid.length > 0) { + sb.append(", XPANID:").append(HexDump.toHexString(mXpanid)); } - if (networkInfo.getChannel() != LowpanIdentity.UNKNOWN) { - LowpanProperties.KEY_CHANNEL.putInMap(parameters, networkInfo.getChannel()); + + if (mPanid != UNSPECIFIED_PANID) { + sb.append(", PANID:").append(String.format("0x%04X", mPanid)); } - if (networkInfo.getXpanid() != null) { - LowpanProperties.KEY_NETWORK_XPANID.putInMap(parameters, networkInfo.getXpanid()); + + if (mChannel != UNSPECIFIED_CHANNEL) { + sb.append(", Channel:").append(mChannel); } + + return sb.toString(); } - void addToMap(Map parameters) { - addToMap(parameters, this); + @Override + public boolean equals(Object obj) { + if (!(obj instanceof LowpanIdentity)) { + return false; + } + LowpanIdentity rhs = (LowpanIdentity) obj; + return Arrays.equals(mRawName, rhs.mRawName) + && Arrays.equals(mXpanid, rhs.mXpanid) + && mType.equals(rhs.mType) + && mPanid == rhs.mPanid + && mChannel == rhs.mChannel; } @Override - public String toString() { - StringBuffer sb = new StringBuffer(); + public int hashCode() { + return Objects.hash( + Arrays.hashCode(mRawName), mType, Arrays.hashCode(mXpanid), mPanid, mChannel); + } - sb.append("Name: ").append(mName == null ? "" : mName); + /** Implement the Parcelable interface. */ + @Override + public int describeContents() { + return 0; + } - if (mXpanid != null) { - sb.append(", XPANID: ").append(HexDump.toHexString(mXpanid)); - } + /** Implement the Parcelable interface. */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeByteArray(mRawName); + dest.writeString(mType); + dest.writeByteArray(mXpanid); + dest.writeInt(mPanid); + dest.writeInt(mChannel); + } - if (mPanid != UNKNOWN) { - sb.append(", PANID: ").append(String.format("0x%04X", mPanid)); - } + /** Implement the Parcelable interface. */ + public static final Creator CREATOR = + new Creator() { - if (mChannel != UNKNOWN) { - sb.append(", Channel: ").append(mChannel); - } + public LowpanIdentity createFromParcel(Parcel in) { + Builder builder = new Builder(); - return sb.toString(); - } + builder.setRawName(in.createByteArray()); + builder.setType(in.readString()); + builder.setXpanid(in.createByteArray()); + builder.setPanid(in.readInt()); + builder.setChannel(in.readInt()); + + return builder.build(); + } + + public LowpanIdentity[] newArray(int size) { + return new LowpanIdentity[size]; + } + }; } diff --git a/lowpan/java/android/net/lowpan/LowpanProvision.aidl b/lowpan/java/android/net/lowpan/LowpanProvision.aidl new file mode 100644 index 000000000000..100e9dc8cc4a --- /dev/null +++ b/lowpan/java/android/net/lowpan/LowpanProvision.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.lowpan; + +parcelable LowpanProvision cpp_header "android/net/lowpan/LowpanProvision.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanProvision.java b/lowpan/java/android/net/lowpan/LowpanProvision.java index 7028807679a1..f1260037b331 100644 --- a/lowpan/java/android/net/lowpan/LowpanProvision.java +++ b/lowpan/java/android/net/lowpan/LowpanProvision.java @@ -18,7 +18,9 @@ package android.net.lowpan; import android.annotation.NonNull; import android.annotation.Nullable; -import java.util.Map; +import android.os.Parcel; +import android.os.Parcelable; +import java.util.Objects; /** * Describes the information needed to describe a network @@ -26,7 +28,7 @@ import java.util.Map; * @hide */ // @SystemApi -public class LowpanProvision { +public class LowpanProvision implements Parcelable { // Builder @@ -69,20 +71,6 @@ public class LowpanProvision { return mCredential; } - // LoWPAN-Internal Methods - - static void addToMap(Map parameters, LowpanProvision provision) - throws LowpanException { - provision.mIdentity.addToMap(parameters); - if (provision.mCredential != null) { - provision.mCredential.addToMap(parameters); - } - } - - void addToMap(Map parameters) throws LowpanException { - addToMap(parameters, this); - } - @Override public String toString() { StringBuffer sb = new StringBuffer(); @@ -90,11 +78,72 @@ public class LowpanProvision { sb.append("LowpanProvision { identity => ").append(mIdentity.toString()); if (mCredential != null) { - sb.append(", credential: ").append(mCredential.toString()); + sb.append(", credential => ").append(mCredential.toString()); } sb.append("}"); return sb.toString(); } + + @Override + public int hashCode() { + return Objects.hash(mIdentity, mCredential); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof LowpanProvision)) { + return false; + } + LowpanProvision rhs = (LowpanProvision) obj; + + if (!mIdentity.equals(rhs.mIdentity)) { + return false; + } + + if (!Objects.equals(mCredential, rhs.mCredential)) { + return false; + } + + return true; + } + + /** Implement the Parcelable interface. */ + @Override + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface. */ + @Override + public void writeToParcel(Parcel dest, int flags) { + mIdentity.writeToParcel(dest, flags); + if (mCredential == null) { + dest.writeBoolean(false); + } else { + dest.writeBoolean(true); + mCredential.writeToParcel(dest, flags); + } + } + + /** Implement the Parcelable interface. */ + public static final Creator CREATOR = + new Creator() { + 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]; + } + }; }; -- cgit v1.2.3