OSDN Git Service

lowpan: Make various data classes Parcelable
authorRobert Quattlebaum <rquattle@google.com>
Fri, 14 Jul 2017 19:02:19 +0000 (12:02 -0700)
committerRobert Quattlebaum <rquattle@google.com>
Tue, 18 Jul 2017 02:38:01 +0000 (19:38 -0700)
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

lowpan/java/android/net/lowpan/LowpanBeaconInfo.aidl [new file with mode: 0644]
lowpan/java/android/net/lowpan/LowpanBeaconInfo.java
lowpan/java/android/net/lowpan/LowpanChannelInfo.aidl [new file with mode: 0644]
lowpan/java/android/net/lowpan/LowpanChannelInfo.java
lowpan/java/android/net/lowpan/LowpanCredential.aidl [new file with mode: 0644]
lowpan/java/android/net/lowpan/LowpanCredential.java
lowpan/java/android/net/lowpan/LowpanIdentity.aidl [new file with mode: 0644]
lowpan/java/android/net/lowpan/LowpanIdentity.java
lowpan/java/android/net/lowpan/LowpanProvision.aidl [new file with mode: 0644]
lowpan/java/android/net/lowpan/LowpanProvision.java

diff --git a/lowpan/java/android/net/lowpan/LowpanBeaconInfo.aidl b/lowpan/java/android/net/lowpan/LowpanBeaconInfo.aidl
new file mode 100644 (file)
index 0000000..9464fea
--- /dev/null
@@ -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";
index e18abd5..345a4c5 100644 (file)
 
 package android.net.lowpan;
 
+import android.os.Parcel;
+import android.os.Parcelable;
 import com.android.internal.util.HexDump;
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.Map;
+import java.util.Objects;
 import java.util.TreeSet;
 
 /**
@@ -27,70 +30,93 @@ import java.util.TreeSet;
  * @hide
  */
 // @SystemApi
-public class LowpanBeaconInfo extends LowpanIdentity {
+public class LowpanBeaconInfo implements Parcelable {
+    public static final int UNKNOWN_RSSI = Integer.MAX_VALUE;
+    public static final int UNKNOWN_LQI = 0;
 
-    private int mRssi = UNKNOWN;
-    private int mLqi = UNKNOWN;
+    private LowpanIdentity mIdentity;
+    private int mRssi = UNKNOWN_RSSI;
+    private int mLqi = UNKNOWN_LQI;
     private byte[] mBeaconAddress = null;
     private final TreeSet<Integer> mFlags = new TreeSet<>();
 
     public static final int FLAG_CAN_ASSIST = 1;
 
-    static class Builder extends LowpanIdentity.Builder {
-        private final LowpanBeaconInfo identity = new LowpanBeaconInfo();
+    /** @hide */
+    public static class Builder {
+        final LowpanIdentity.Builder mIdentityBuilder = new LowpanIdentity.Builder();
+        final LowpanBeaconInfo mBeaconInfo = new LowpanBeaconInfo();
+
+        public Builder setLowpanIdentity(LowpanIdentity x) {
+            mIdentityBuilder.setLowpanIdentity(x);
+            return this;
+        }
+
+        public Builder setName(String x) {
+            mIdentityBuilder.setName(x);
+            return this;
+        }
+
+        public Builder setXpanid(byte x[]) {
+            mIdentityBuilder.setXpanid(x);
+            return this;
+        }
+
+        public Builder setPanid(int x) {
+            mIdentityBuilder.setPanid(x);
+            return this;
+        }
+
+        public Builder setChannel(int x) {
+            mIdentityBuilder.setChannel(x);
+            return this;
+        }
+
+        public Builder setType(String x) {
+            mIdentityBuilder.setType(x);
+            return this;
+        }
 
         public Builder setRssi(int x) {
-            identity.mRssi = x;
+            mBeaconInfo.mRssi = x;
             return this;
         }
 
         public Builder setLqi(int x) {
-            identity.mLqi = x;
+            mBeaconInfo.mLqi = x;
             return this;
         }
 
         public Builder setBeaconAddress(byte x[]) {
-            identity.mBeaconAddress = x.clone();
+            mBeaconInfo.mBeaconAddress = (x != null ? x.clone() : null);
             return this;
         }
 
         public Builder setFlag(int x) {
-            identity.mFlags.add(x);
+            mBeaconInfo.mFlags.add(x);
             return this;
         }
 
         public Builder setFlags(Collection<Integer> x) {
-            identity.mFlags.addAll(x);
-            return this;
-        }
-
-        /** @hide */
-        Builder updateFromMap(Map map) {
-            if (map.containsKey(LowpanProperties.KEY_RSSI.getName())) {
-                setRssi(LowpanProperties.KEY_RSSI.getFromMap(map));
-            }
-            if (map.containsKey(LowpanProperties.KEY_LQI.getName())) {
-                setLqi(LowpanProperties.KEY_LQI.getFromMap(map));
-            }
-            if (map.containsKey(LowpanProperties.KEY_BEACON_ADDRESS.getName())) {
-                setBeaconAddress(LowpanProperties.KEY_BEACON_ADDRESS.getFromMap(map));
-            }
-            identity.mFlags.clear();
-            if (map.containsKey(LowpanProperties.KEY_BEACON_CAN_ASSIST.getName())
-                    && LowpanProperties.KEY_BEACON_CAN_ASSIST.getFromMap(map).booleanValue()) {
-                setFlag(FLAG_CAN_ASSIST);
-            }
-            super.updateFromMap(map);
+            mBeaconInfo.mFlags.addAll(x);
             return this;
         }
 
         public LowpanBeaconInfo build() {
-            return identity;
+            mBeaconInfo.mIdentity = mIdentityBuilder.build();
+            if (mBeaconInfo.mBeaconAddress == null) {
+                mBeaconInfo.mBeaconAddress = new byte[0];
+            }
+            return mBeaconInfo;
         }
     }
 
     private LowpanBeaconInfo() {}
 
+    public LowpanIdentity getLowpanIdentity() {
+        return mIdentity;
+    }
+
     public int getRssi() {
         return mRssi;
     }
@@ -112,26 +138,21 @@ public class LowpanBeaconInfo extends LowpanIdentity {
     }
 
     @Override
-    void addToMap(Map<String, Object> parameters) {
-        super.addToMap(parameters);
-    }
-
-    @Override
     public String toString() {
         StringBuffer sb = new StringBuffer();
 
-        sb.append(super.toString());
+        sb.append(mIdentity.toString());
 
-        if (mRssi != UNKNOWN) {
-            sb.append(", RSSI: ").append(mRssi);
+        if (mRssi != UNKNOWN_RSSI) {
+            sb.append(", RSSI:").append(mRssi).append("dBm");
         }
 
-        if (mLqi != UNKNOWN) {
-            sb.append(", LQI: ").append(mLqi);
+        if (mLqi != UNKNOWN_LQI) {
+            sb.append(", LQI:").append(mLqi);
         }
 
-        if (mBeaconAddress != null) {
-            sb.append(", BeaconAddress: ").append(HexDump.toHexString(mBeaconAddress));
+        if (mBeaconAddress.length > 0) {
+            sb.append(", BeaconAddress:").append(HexDump.toHexString(mBeaconAddress));
         }
 
         for (Integer flag : mFlags) {
@@ -147,4 +168,67 @@ public class LowpanBeaconInfo extends LowpanIdentity {
 
         return sb.toString();
     }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mIdentity, mRssi, mLqi, Arrays.hashCode(mBeaconAddress), mFlags);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof LowpanBeaconInfo)) {
+            return false;
+        }
+        LowpanBeaconInfo rhs = (LowpanBeaconInfo) obj;
+        return mIdentity.equals(rhs.mIdentity)
+                && Arrays.equals(mBeaconAddress, rhs.mBeaconAddress)
+                && mRssi == rhs.mRssi
+                && mLqi == rhs.mLqi
+                && mFlags.equals(rhs.mFlags);
+    }
+
+    /** Implement the Parcelable interface. */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface. */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        mIdentity.writeToParcel(dest, flags);
+        dest.writeInt(mRssi);
+        dest.writeInt(mLqi);
+        dest.writeByteArray(mBeaconAddress);
+
+        dest.writeInt(mFlags.size());
+        for (Integer val : mFlags) {
+            dest.writeInt(val);
+        }
+    }
+
+    /** Implement the Parcelable interface. */
+    public static final Creator<LowpanBeaconInfo> CREATOR =
+            new Creator<LowpanBeaconInfo>() {
+                public LowpanBeaconInfo createFromParcel(Parcel in) {
+                    Builder builder = new Builder();
+
+                    builder.setLowpanIdentity(LowpanIdentity.CREATOR.createFromParcel(in));
+
+                    builder.setRssi(in.readInt());
+                    builder.setLqi(in.readInt());
+
+                    builder.setBeaconAddress(in.createByteArray());
+
+                    for (int i = in.readInt(); i > 0; i--) {
+                        builder.setFlag(in.readInt());
+                    }
+
+                    return builder.build();
+                }
+
+                public LowpanBeaconInfo[] newArray(int size) {
+                    return new LowpanBeaconInfo[size];
+                }
+            };
 }
diff --git a/lowpan/java/android/net/lowpan/LowpanChannelInfo.aidl b/lowpan/java/android/net/lowpan/LowpanChannelInfo.aidl
new file mode 100644 (file)
index 0000000..0676deb
--- /dev/null
@@ -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";
index 621affe..52b1c6d 100644 (file)
 
 package android.net.lowpan;
 
-/** Provides detailed information about a given channel. */
+import android.os.Parcel;
+import android.os.Parcelable;
+import java.util.Objects;
+
+/**
+ * Provides detailed information about a given channel.
+ *
+ * @hide
+ */
 // @SystemApi
-public class LowpanChannelInfo {
+public class LowpanChannelInfo implements Parcelable {
 
     public static final int UNKNOWN_POWER = Integer.MAX_VALUE;
+    public static final float UNKNOWN_FREQUENCY = 0.0f;
+    public static final float UNKNOWN_BANDWIDTH = 0.0f;
 
-    // Instance Variables
-
-    private String mName = null;
     private int mIndex = 0;
-    private boolean mIsMaskedByRegulatoryDomain = false;
-    private float mSpectrumCenterFrequency = 0.0f;
-    private float mSpectrumBandwidth = 0.0f;
+    private String mName = null;
+    private float mSpectrumCenterFrequency = UNKNOWN_FREQUENCY;
+    private float mSpectrumBandwidth = UNKNOWN_BANDWIDTH;
     private int mMaxTransmitPower = UNKNOWN_POWER;
+    private boolean mIsMaskedByRegulatoryDomain = false;
+
+    /** @hide */
+    public static LowpanChannelInfo getChannelInfoForIeee802154Page0(int index) {
+        LowpanChannelInfo info = new LowpanChannelInfo();
+
+        if (index < 0) {
+            info = null;
+
+        } else if (index == 0) {
+            info.mSpectrumCenterFrequency = 868300000.0f;
+            info.mSpectrumBandwidth = 600000.0f;
+
+        } else if (index < 11) {
+            info.mSpectrumCenterFrequency = 906000000.0f - (2000000.0f * 1) + 2000000.0f * (index);
+            info.mSpectrumBandwidth = 0; // Unknown
+
+        } else if (index < 26) {
+            info.mSpectrumCenterFrequency =
+                    2405000000.0f - (5000000.0f * 11) + 5000000.0f * (index);
+            info.mSpectrumBandwidth = 2000000.0f;
+
+        } else {
+            info = null;
+        }
+
+        info.mName = Integer.toString(index);
+
+        return info;
+    }
+
+    private LowpanChannelInfo() {}
 
-    // Public Getters and Setters
+    private LowpanChannelInfo(int index, String name, float cf, float bw) {
+        mIndex = index;
+        mName = name;
+        mSpectrumCenterFrequency = cf;
+        mSpectrumBandwidth = bw;
+    }
 
     public String getName() {
         return mName;
@@ -63,22 +107,110 @@ public class LowpanChannelInfo {
 
         sb.append("Channel ").append(mIndex);
 
-        if (mName != null) {
+        if (mName != null && !mName.equals(Integer.toString(mIndex))) {
             sb.append(" (").append(mName).append(")");
         }
 
         if (mSpectrumCenterFrequency > 0.0f) {
-            sb.append(", SpectrumCenterFrequency: ").append(mSpectrumCenterFrequency).append("Hz");
+            if (mSpectrumCenterFrequency > 1000000000.0f) {
+                sb.append(", SpectrumCenterFrequency: ")
+                        .append(mSpectrumCenterFrequency / 1000000000.0f)
+                        .append("GHz");
+            } else if (mSpectrumCenterFrequency > 1000000.0f) {
+                sb.append(", SpectrumCenterFrequency: ")
+                        .append(mSpectrumCenterFrequency / 1000000.0f)
+                        .append("MHz");
+            } else {
+                sb.append(", SpectrumCenterFrequency: ")
+                        .append(mSpectrumCenterFrequency / 1000.0f)
+                        .append("kHz");
+            }
         }
 
         if (mSpectrumBandwidth > 0.0f) {
-            sb.append(", SpectrumBandwidth: ").append(mSpectrumBandwidth).append("Hz");
+            if (mSpectrumBandwidth > 1000000000.0f) {
+                sb.append(", SpectrumBandwidth: ")
+                        .append(mSpectrumBandwidth / 1000000000.0f)
+                        .append("GHz");
+            } else if (mSpectrumBandwidth > 1000000.0f) {
+                sb.append(", SpectrumBandwidth: ")
+                        .append(mSpectrumBandwidth / 1000000.0f)
+                        .append("MHz");
+            } else {
+                sb.append(", SpectrumBandwidth: ")
+                        .append(mSpectrumBandwidth / 1000.0f)
+                        .append("kHz");
+            }
         }
 
         if (mMaxTransmitPower != UNKNOWN_POWER) {
-            sb.append(", MaxTransmitPower: ").append(mMaxTransmitPower);
+            sb.append(", MaxTransmitPower: ").append(mMaxTransmitPower).append("dBm");
         }
 
         return sb.toString();
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof LowpanChannelInfo)) {
+            return false;
+        }
+        LowpanChannelInfo rhs = (LowpanChannelInfo) obj;
+        return Objects.equals(mName, rhs.mName)
+                && mIndex == rhs.mIndex
+                && mIsMaskedByRegulatoryDomain == rhs.mIsMaskedByRegulatoryDomain
+                && mSpectrumCenterFrequency == rhs.mSpectrumCenterFrequency
+                && mSpectrumBandwidth == rhs.mSpectrumBandwidth
+                && mMaxTransmitPower == rhs.mMaxTransmitPower;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(
+                mName,
+                mIndex,
+                mIsMaskedByRegulatoryDomain,
+                mSpectrumCenterFrequency,
+                mSpectrumBandwidth,
+                mMaxTransmitPower);
+    }
+
+    /** Implement the Parcelable interface. */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface. */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mIndex);
+        dest.writeString(mName);
+        dest.writeFloat(mSpectrumCenterFrequency);
+        dest.writeFloat(mSpectrumBandwidth);
+        dest.writeInt(mMaxTransmitPower);
+        dest.writeBoolean(mIsMaskedByRegulatoryDomain);
+    }
+
+    /** Implement the Parcelable interface. */
+    public static final Creator<LowpanChannelInfo> CREATOR =
+            new Creator<LowpanChannelInfo>() {
+
+                public LowpanChannelInfo createFromParcel(Parcel in) {
+                    LowpanChannelInfo info = new LowpanChannelInfo();
+
+                    info.mIndex = in.readInt();
+                    info.mName = in.readString();
+                    info.mSpectrumCenterFrequency = in.readFloat();
+                    info.mSpectrumBandwidth = in.readFloat();
+                    info.mMaxTransmitPower = in.readInt();
+                    info.mIsMaskedByRegulatoryDomain = in.readBoolean();
+
+                    return info;
+                }
+
+                public LowpanChannelInfo[] newArray(int size) {
+                    return new LowpanChannelInfo[size];
+                }
+            };
 }
diff --git a/lowpan/java/android/net/lowpan/LowpanCredential.aidl b/lowpan/java/android/net/lowpan/LowpanCredential.aidl
new file mode 100644 (file)
index 0000000..af0c2d6
--- /dev/null
@@ -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";
index ca86021..e9126f9 100644 (file)
 
 package android.net.lowpan;
 
-import java.util.Map;
+import android.os.Parcel;
+import android.os.Parcelable;
+import com.android.internal.util.HexDump;
+import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * Describes a credential for a LoWPAN network.
@@ -24,7 +28,7 @@ import java.util.Map;
  * @hide
  */
 // @SystemApi
-public class LowpanCredential {
+public class LowpanCredential implements Parcelable {
 
     public static final int UNSPECIFIED_KEY_INDEX = 0;
 
@@ -49,18 +53,18 @@ public class LowpanCredential {
         return new LowpanCredential(masterKey, keyIndex);
     }
 
-    public void setMasterKey(byte[] masterKey) {
+    void setMasterKey(byte[] masterKey) {
         if (masterKey != null) {
             masterKey = masterKey.clone();
         }
         mMasterKey = masterKey;
     }
 
-    public void setMasterKeyIndex(int keyIndex) {
+    void setMasterKeyIndex(int keyIndex) {
         mMasterKeyIndex = keyIndex;
     }
 
-    public void setMasterKey(byte[] masterKey, int keyIndex) {
+    void setMasterKey(byte[] masterKey, int keyIndex) {
         setMasterKey(masterKey);
         setMasterKeyIndex(keyIndex);
     }
@@ -80,12 +84,89 @@ public class LowpanCredential {
         return mMasterKey != null;
     }
 
-    void addToMap(Map<String, Object> parameters) throws LowpanException {
+    public String toSensitiveString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append("<LowpanCredential");
+
+        if (isMasterKey()) {
+            sb.append(" MasterKey:").append(HexDump.toHexString(mMasterKey));
+            if (mMasterKeyIndex != UNSPECIFIED_KEY_INDEX) {
+                sb.append(", Index:").append(mMasterKeyIndex);
+            }
+        } else {
+            sb.append(" empty");
+        }
+
+        sb.append(">");
+
+        return sb.toString();
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append("<LowpanCredential");
+
         if (isMasterKey()) {
-            LowpanProperties.KEY_NETWORK_MASTER_KEY.putInMap(parameters, getMasterKey());
-            LowpanProperties.KEY_NETWORK_MASTER_KEY_INDEX.putInMap(parameters, getMasterKeyIndex());
+            // We don't print out the contents of the key here,
+            // we only do that in toSensitiveString.
+            sb.append(" MasterKey");
+            if (mMasterKeyIndex != UNSPECIFIED_KEY_INDEX) {
+                sb.append(", Index:").append(mMasterKeyIndex);
+            }
         } else {
-            throw new LowpanException("Unsupported Network Credential");
+            sb.append(" empty");
         }
+
+        sb.append(">");
+
+        return sb.toString();
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof LowpanCredential)) {
+            return false;
+        }
+        LowpanCredential rhs = (LowpanCredential) obj;
+        return Arrays.equals(mMasterKey, rhs.mMasterKey) && mMasterKeyIndex == rhs.mMasterKeyIndex;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(Arrays.hashCode(mMasterKey), mMasterKeyIndex);
+    }
+
+    /** Implement the Parcelable interface. */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface. */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeByteArray(mMasterKey);
+        dest.writeInt(mMasterKeyIndex);
+    }
+
+    /** Implement the Parcelable interface. */
+    public static final Creator<LowpanCredential> CREATOR =
+            new Creator<LowpanCredential>() {
+
+                public LowpanCredential createFromParcel(Parcel in) {
+                    LowpanCredential credential = new LowpanCredential();
+
+                    credential.mMasterKey = in.createByteArray();
+                    credential.mMasterKeyIndex = in.readInt();
+
+                    return credential;
+                }
+
+                public LowpanCredential[] newArray(int size) {
+                    return new LowpanCredential[size];
+                }
+            };
 }
diff --git a/lowpan/java/android/net/lowpan/LowpanIdentity.aidl b/lowpan/java/android/net/lowpan/LowpanIdentity.aidl
new file mode 100644 (file)
index 0000000..fcef98f
--- /dev/null
@@ -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";
index 2d36f7f..6cb1f98 100644 (file)
 
 package android.net.lowpan;
 
+import android.annotation.NonNull;
+import android.icu.text.StringPrep;
+import android.icu.text.StringPrepParseException;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
 import com.android.internal.util.HexDump;
-import java.util.Map;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * Describes an instance of a LoWPAN network.
@@ -25,76 +33,100 @@ import java.util.Map;
  * @hide
  */
 // @SystemApi
-public class LowpanIdentity {
+public class LowpanIdentity implements Parcelable {
+    private static final String TAG = LowpanIdentity.class.getSimpleName();
 
     // Constants
+    public static final int UNSPECIFIED_CHANNEL = -1;
+    public static final int UNSPECIFIED_PANID = 0xFFFFFFFF;
+    // Builder
 
     /** @hide */
-    public static final int TYPE_ZIGBEE = 1;
-
-    /** @hide */
-    public static final int TYPE_ZIGBEE_IP = 2;
+    // @SystemApi
+    public static class Builder {
+        private static final StringPrep stringPrep =
+                StringPrep.getInstance(StringPrep.RFC3920_RESOURCEPREP);
+
+        final LowpanIdentity mIdentity = new LowpanIdentity();
+
+        private static String escape(@NonNull byte[] bytes) {
+            StringBuffer sb = new StringBuffer();
+            for (byte b : bytes) {
+                if (b >= 32 && b <= 126) {
+                    sb.append((char) b);
+                } else {
+                    sb.append(String.format("\\0x%02x", b & 0xFF));
+                }
+            }
+            return sb.toString();
+        }
 
-    /** @hide */
-    public static final int TYPE_THREAD = 3;
+        public Builder setLowpanIdentity(@NonNull LowpanIdentity x) {
+            Objects.requireNonNull(x);
+            setRawName(x.getRawName());
+            setXpanid(x.getXpanid());
+            setPanid(x.getPanid());
+            setChannel(x.getChannel());
+            setType(x.getType());
+            return this;
+        }
 
-    public static final int UNKNOWN = Integer.MAX_VALUE;
+        public Builder setName(@NonNull String name) {
+            Objects.requireNonNull(name);
+            try {
+                mIdentity.mName = stringPrep.prepare(name, StringPrep.DEFAULT);
+                mIdentity.mRawName = mIdentity.mName.getBytes(StandardCharsets.UTF_8);
+                mIdentity.mIsNameValid = true;
+            } catch (StringPrepParseException x) {
+                Log.w(TAG, x.toString());
+                setRawName(name.getBytes(StandardCharsets.UTF_8));
+            }
+            return this;
+        }
 
-    // Builder
+        public Builder setRawName(@NonNull byte[] name) {
+            Objects.requireNonNull(name);
+            mIdentity.mRawName = name.clone();
+            mIdentity.mName = new String(name, StandardCharsets.UTF_8);
+            try {
+                String nameCheck = stringPrep.prepare(mIdentity.mName, StringPrep.DEFAULT);
+                mIdentity.mIsNameValid =
+                        Arrays.equals(nameCheck.getBytes(StandardCharsets.UTF_8), name);
+            } catch (StringPrepParseException x) {
+                Log.w(TAG, x.toString());
+                mIdentity.mIsNameValid = false;
+            }
 
-    /** @hide */
-    // @SystemApi
-    public static class Builder {
-        private final LowpanIdentity identity = new LowpanIdentity();
+            // Non-normal names must be rendered differently to avoid confusion.
+            if (!mIdentity.mIsNameValid) {
+                mIdentity.mName = "«" + escape(name) + "»";
+            }
 
-        public Builder setName(String x) {
-            identity.mName = x;
             return this;
         }
 
         public Builder setXpanid(byte x[]) {
-            identity.mXpanid = (x != null ? x.clone() : null);
+            mIdentity.mXpanid = (x != null ? x.clone() : null);
             return this;
         }
 
         public Builder setPanid(int x) {
-            identity.mPanid = x;
+            mIdentity.mPanid = x;
             return this;
         }
 
-        /** @hide */
-        public Builder setType(int x) {
-            identity.mType = x;
+        public Builder setType(@NonNull String x) {
+            mIdentity.mType = x;
             return this;
         }
 
         public Builder setChannel(int x) {
-            identity.mChannel = x;
-            return this;
-        }
-
-        /** @hide */
-        Builder updateFromMap(Map map) {
-            if (map.containsKey(ILowpanInterface.KEY_NETWORK_NAME)) {
-                setName(LowpanProperties.KEY_NETWORK_NAME.getFromMap(map));
-            }
-            if (map.containsKey(ILowpanInterface.KEY_NETWORK_PANID)) {
-                setPanid(LowpanProperties.KEY_NETWORK_PANID.getFromMap(map));
-            }
-            if (map.containsKey(ILowpanInterface.KEY_NETWORK_XPANID)) {
-                setXpanid(LowpanProperties.KEY_NETWORK_XPANID.getFromMap(map));
-            }
-            if (map.containsKey(ILowpanInterface.KEY_CHANNEL)) {
-                setChannel(LowpanProperties.KEY_CHANNEL.getFromMap(map));
-            }
-            if (map.containsKey(ILowpanInterface.KEY_NETWORK_TYPE)) {
-                setType(LowpanProperties.KEY_NETWORK_TYPE.getFromMap(map));
-            }
+            mIdentity.mChannel = x;
             return this;
         }
 
         public LowpanIdentity build() {
-            return identity;
+            return mIdentity;
         }
     }
 
@@ -102,28 +134,37 @@ public class LowpanIdentity {
 
     // Instance Variables
 
-    private String mName = null;
-    private byte[] mXpanid = null;
-    private int mType = UNKNOWN;
-    private int mPanid = UNKNOWN;
-    private int mChannel = UNKNOWN;
+    private String mName = "";
+    private boolean mIsNameValid = true;
+    private byte[] mRawName = new byte[0];
+    private String mType = "";
+    private byte[] mXpanid = new byte[0];
+    private int mPanid = UNSPECIFIED_PANID;
+    private int mChannel = UNSPECIFIED_CHANNEL;
 
-    // Public Getters and Setters
+    // Public Getters
 
     public String getName() {
         return mName;
     }
 
+    public boolean isNameValid() {
+        return mIsNameValid;
+    }
+
+    public byte[] getRawName() {
+        return mRawName.clone();
+    }
+
     public byte[] getXpanid() {
-        return mXpanid != null ? mXpanid.clone() : null;
+        return mXpanid.clone();
     }
 
     public int getPanid() {
         return mPanid;
     }
 
-    /** @hide */
-    public int getType() {
+    public String getType() {
         return mType;
     }
 
@@ -131,43 +172,84 @@ public class LowpanIdentity {
         return mChannel;
     }
 
-    static void addToMap(Map<String, Object> parameters, LowpanIdentity networkInfo) {
-        if (networkInfo.getName() != null) {
-            LowpanProperties.KEY_NETWORK_NAME.putInMap(parameters, networkInfo.getName());
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append("Name:").append(getName());
+
+        if (mType.length() > 0) {
+            sb.append(", Type:").append(mType);
         }
-        if (networkInfo.getPanid() != LowpanIdentity.UNKNOWN) {
-            LowpanProperties.KEY_NETWORK_PANID.putInMap(parameters, networkInfo.getPanid());
+
+        if (mXpanid.length > 0) {
+            sb.append(", XPANID:").append(HexDump.toHexString(mXpanid));
         }
-        if (networkInfo.getChannel() != LowpanIdentity.UNKNOWN) {
-            LowpanProperties.KEY_CHANNEL.putInMap(parameters, networkInfo.getChannel());
+
+        if (mPanid != UNSPECIFIED_PANID) {
+            sb.append(", PANID:").append(String.format("0x%04X", mPanid));
         }
-        if (networkInfo.getXpanid() != null) {
-            LowpanProperties.KEY_NETWORK_XPANID.putInMap(parameters, networkInfo.getXpanid());
+
+        if (mChannel != UNSPECIFIED_CHANNEL) {
+            sb.append(", Channel:").append(mChannel);
         }
+
+        return sb.toString();
     }
 
-    void addToMap(Map<String, Object> parameters) {
-        addToMap(parameters, this);
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof LowpanIdentity)) {
+            return false;
+        }
+        LowpanIdentity rhs = (LowpanIdentity) obj;
+        return Arrays.equals(mRawName, rhs.mRawName)
+                && Arrays.equals(mXpanid, rhs.mXpanid)
+                && mType.equals(rhs.mType)
+                && mPanid == rhs.mPanid
+                && mChannel == rhs.mChannel;
     }
 
     @Override
-    public String toString() {
-        StringBuffer sb = new StringBuffer();
+    public int hashCode() {
+        return Objects.hash(
+                Arrays.hashCode(mRawName), mType, Arrays.hashCode(mXpanid), mPanid, mChannel);
+    }
 
-        sb.append("Name: ").append(mName == null ? "<none>" : mName);
+    /** Implement the Parcelable interface. */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
 
-        if (mXpanid != null) {
-            sb.append(", XPANID: ").append(HexDump.toHexString(mXpanid));
-        }
+    /** Implement the Parcelable interface. */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeByteArray(mRawName);
+        dest.writeString(mType);
+        dest.writeByteArray(mXpanid);
+        dest.writeInt(mPanid);
+        dest.writeInt(mChannel);
+    }
 
-        if (mPanid != UNKNOWN) {
-            sb.append(", PANID: ").append(String.format("0x%04X", mPanid));
-        }
+    /** Implement the Parcelable interface. */
+    public static final Creator<LowpanIdentity> CREATOR =
+            new Creator<LowpanIdentity>() {
 
-        if (mChannel != UNKNOWN) {
-            sb.append(", Channel: ").append(mChannel);
-        }
+                public LowpanIdentity createFromParcel(Parcel in) {
+                    Builder builder = new Builder();
 
-        return sb.toString();
-    }
+                    builder.setRawName(in.createByteArray());
+                    builder.setType(in.readString());
+                    builder.setXpanid(in.createByteArray());
+                    builder.setPanid(in.readInt());
+                    builder.setChannel(in.readInt());
+
+                    return builder.build();
+                }
+
+                public LowpanIdentity[] newArray(int size) {
+                    return new LowpanIdentity[size];
+                }
+            };
 }
diff --git a/lowpan/java/android/net/lowpan/LowpanProvision.aidl b/lowpan/java/android/net/lowpan/LowpanProvision.aidl
new file mode 100644 (file)
index 0000000..100e9dc
--- /dev/null
@@ -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";
index 7028807..f126003 100644 (file)
@@ -18,7 +18,9 @@ package android.net.lowpan;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import java.util.Map;
+import android.os.Parcel;
+import android.os.Parcelable;
+import java.util.Objects;
 
 /**
  * Describes the information needed to describe a network
@@ -26,7 +28,7 @@ import java.util.Map;
  * @hide
  */
 // @SystemApi
-public class LowpanProvision {
+public class LowpanProvision implements Parcelable {
 
     // Builder
 
@@ -69,20 +71,6 @@ public class LowpanProvision {
         return mCredential;
     }
 
-    // LoWPAN-Internal Methods
-
-    static void addToMap(Map<String, Object> parameters, LowpanProvision provision)
-            throws LowpanException {
-        provision.mIdentity.addToMap(parameters);
-        if (provision.mCredential != null) {
-            provision.mCredential.addToMap(parameters);
-        }
-    }
-
-    void addToMap(Map<String, Object> parameters) throws LowpanException {
-        addToMap(parameters, this);
-    }
-
     @Override
     public String toString() {
         StringBuffer sb = new StringBuffer();
@@ -90,11 +78,72 @@ public class LowpanProvision {
         sb.append("LowpanProvision { identity => ").append(mIdentity.toString());
 
         if (mCredential != null) {
-            sb.append(", credential: ").append(mCredential.toString());
+            sb.append(", credential => ").append(mCredential.toString());
         }
 
         sb.append("}");
 
         return sb.toString();
     }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mIdentity, mCredential);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof LowpanProvision)) {
+            return false;
+        }
+        LowpanProvision rhs = (LowpanProvision) obj;
+
+        if (!mIdentity.equals(rhs.mIdentity)) {
+            return false;
+        }
+
+        if (!Objects.equals(mCredential, rhs.mCredential)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /** Implement the Parcelable interface. */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface. */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        mIdentity.writeToParcel(dest, flags);
+        if (mCredential == null) {
+            dest.writeBoolean(false);
+        } else {
+            dest.writeBoolean(true);
+            mCredential.writeToParcel(dest, flags);
+        }
+    }
+
+    /** Implement the Parcelable interface. */
+    public static final Creator<LowpanProvision> CREATOR =
+            new Creator<LowpanProvision>() {
+                public LowpanProvision createFromParcel(Parcel in) {
+                    Builder builder = new Builder();
+
+                    builder.setLowpanIdentity(LowpanIdentity.CREATOR.createFromParcel(in));
+
+                    if (in.readBoolean()) {
+                        builder.setLowpanCredential(LowpanCredential.CREATOR.createFromParcel(in));
+                    }
+
+                    return builder.build();
+                }
+
+                public LowpanProvision[] newArray(int size) {
+                    return new LowpanProvision[size];
+                }
+            };
 };