Merge "[AWARE] Add a group network specifier allowing matches to multiple requests" into oc-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
185a91c7ef
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* 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.wifi.aware;
|
||||
|
||||
import android.net.NetworkSpecifier;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
|
||||
import libcore.util.HexEncoding;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* A network specifier object used to represent the capabilities of an network agent. A collection
|
||||
* of multiple WifiAwareNetworkSpecifier objects whose matching critiera (satisfiedBy) is an OR:
|
||||
* a match on any of the network specifiers in the collection is a match.
|
||||
*
|
||||
* This class is not intended for use in network requests.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class WifiAwareAgentNetworkSpecifier extends NetworkSpecifier implements Parcelable {
|
||||
private static final String TAG = "WifiAwareAgentNs";
|
||||
|
||||
private static final boolean VDBG = false; // STOPSHIP if true
|
||||
|
||||
private Set<ByteArrayWrapper> mNetworkSpecifiers = new HashSet<>();
|
||||
private MessageDigest mDigester;
|
||||
|
||||
public WifiAwareAgentNetworkSpecifier() {
|
||||
// do nothing, already initialized to empty
|
||||
}
|
||||
|
||||
public WifiAwareAgentNetworkSpecifier(WifiAwareNetworkSpecifier ns) {
|
||||
initialize();
|
||||
mNetworkSpecifiers.add(convert(ns));
|
||||
}
|
||||
|
||||
public WifiAwareAgentNetworkSpecifier(WifiAwareNetworkSpecifier[] nss) {
|
||||
initialize();
|
||||
for (WifiAwareNetworkSpecifier ns : nss) {
|
||||
mNetworkSpecifiers.add(convert(ns));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return mNetworkSpecifiers.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeArray(mNetworkSpecifiers.toArray());
|
||||
}
|
||||
|
||||
public static final Creator<WifiAwareAgentNetworkSpecifier> CREATOR =
|
||||
new Creator<WifiAwareAgentNetworkSpecifier>() {
|
||||
@Override
|
||||
public WifiAwareAgentNetworkSpecifier createFromParcel(Parcel in) {
|
||||
WifiAwareAgentNetworkSpecifier agentNs = new WifiAwareAgentNetworkSpecifier();
|
||||
Object[] objs = in.readArray(null);
|
||||
for (Object obj : objs) {
|
||||
agentNs.mNetworkSpecifiers.add((ByteArrayWrapper) obj);
|
||||
}
|
||||
return agentNs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WifiAwareAgentNetworkSpecifier[] newArray(int size) {
|
||||
return new WifiAwareAgentNetworkSpecifier[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mNetworkSpecifiers.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof WifiAwareAgentNetworkSpecifier)) {
|
||||
return false;
|
||||
}
|
||||
return mNetworkSpecifiers.equals(((WifiAwareAgentNetworkSpecifier) obj).mNetworkSpecifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringJoiner sj = new StringJoiner(",");
|
||||
for (ByteArrayWrapper baw: mNetworkSpecifiers) {
|
||||
sj.add(baw.toString());
|
||||
}
|
||||
return sj.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean satisfiedBy(NetworkSpecifier other) {
|
||||
if (!(other instanceof WifiAwareAgentNetworkSpecifier)) {
|
||||
return false;
|
||||
}
|
||||
WifiAwareAgentNetworkSpecifier otherNs = (WifiAwareAgentNetworkSpecifier) other;
|
||||
|
||||
// called as old.satifiedBy(new): satisfied if old contained in new
|
||||
for (ByteArrayWrapper baw: mNetworkSpecifiers) {
|
||||
if (!otherNs.mNetworkSpecifiers.contains(baw)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean satisfiesAwareNetworkSpecifier(WifiAwareNetworkSpecifier ns) {
|
||||
if (VDBG) Log.v(TAG, "satisfiesAwareNetworkSpecifier: ns=" + ns);
|
||||
ByteArrayWrapper nsBytes = convert(ns);
|
||||
return mNetworkSpecifiers.contains(nsBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertValidFromUid(int requestorUid) {
|
||||
throw new SecurityException(
|
||||
"WifiAwareAgentNetworkSpecifier should not be used in network requests");
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
try {
|
||||
mDigester = MessageDigest.getInstance("SHA-256");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
Log.e(TAG, "Can not instantiate a SHA-256 digester!? Will match nothing.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private ByteArrayWrapper convert(WifiAwareNetworkSpecifier ns) {
|
||||
if (mDigester == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Parcel parcel = Parcel.obtain();
|
||||
ns.writeToParcel(parcel, 0);
|
||||
byte[] bytes = parcel.marshall();
|
||||
|
||||
mDigester.reset();
|
||||
mDigester.update(bytes);
|
||||
return new ByteArrayWrapper(mDigester.digest());
|
||||
}
|
||||
|
||||
private static class ByteArrayWrapper implements Parcelable {
|
||||
private byte[] mData;
|
||||
|
||||
ByteArrayWrapper(byte[] data) {
|
||||
mData = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(mData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof ByteArrayWrapper)) {
|
||||
return false;
|
||||
}
|
||||
return Arrays.equals(((ByteArrayWrapper) obj).mData, mData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeBlob(mData);
|
||||
}
|
||||
|
||||
public static final Creator<ByteArrayWrapper> CREATOR =
|
||||
new Creator<ByteArrayWrapper>() {
|
||||
@Override
|
||||
public ByteArrayWrapper createFromParcel(Parcel in) {
|
||||
return new ByteArrayWrapper(in.readBlob());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteArrayWrapper[] newArray(int size) {
|
||||
return new ByteArrayWrapper[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new String(HexEncoding.encode(mData));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -193,6 +193,9 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements
|
||||
@Override
|
||||
public boolean satisfiedBy(NetworkSpecifier other) {
|
||||
// MatchAllNetworkSpecifier is taken care in NetworkCapabilities#satisfiedBySpecifier.
|
||||
if (other instanceof WifiAwareAgentNetworkSpecifier) {
|
||||
return ((WifiAwareAgentNetworkSpecifier) other).satisfiesAwareNetworkSpecifier(this);
|
||||
}
|
||||
return equals(other);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.wifi.aware;
|
||||
|
||||
import static org.hamcrest.core.IsEqual.equalTo;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ErrorCollector;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Unit test harness for WifiAwareAgentNetworkSpecifier class.
|
||||
*/
|
||||
@SmallTest
|
||||
public class WifiAwareAgentNetworkSpecifierTest {
|
||||
@Rule
|
||||
public ErrorCollector collector = new ErrorCollector();
|
||||
|
||||
@Test
|
||||
public void testParcel() {
|
||||
final int numNs = 10;
|
||||
|
||||
Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>();
|
||||
for (int i = 0; i < numNs; ++i) {
|
||||
nsSet.add(getDummyNetworkSpecifier(10 + i));
|
||||
}
|
||||
WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier(
|
||||
nsSet.toArray(new WifiAwareNetworkSpecifier[numNs]));
|
||||
|
||||
Parcel parcelW = Parcel.obtain();
|
||||
dut.writeToParcel(parcelW, 0);
|
||||
byte[] bytes = parcelW.marshall();
|
||||
parcelW.recycle();
|
||||
|
||||
Parcel parcelR = Parcel.obtain();
|
||||
parcelR.unmarshall(bytes, 0, bytes.length);
|
||||
parcelR.setDataPosition(0);
|
||||
WifiAwareAgentNetworkSpecifier rereadDut =
|
||||
WifiAwareAgentNetworkSpecifier.CREATOR.createFromParcel(parcelR);
|
||||
|
||||
assertEquals(dut, rereadDut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that an empty agent network specifier doesn't match any base network specifier.
|
||||
*/
|
||||
@Test
|
||||
public void testEmptyDoesntMatchAnything() {
|
||||
WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier();
|
||||
WifiAwareNetworkSpecifier ns = getDummyNetworkSpecifier(6);
|
||||
collector.checkThat("No match expected", ns.satisfiedBy(dut), equalTo(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that an agent network specifier constructed with a single entry matches that entry,
|
||||
* and only that entry.
|
||||
*/
|
||||
@Test
|
||||
public void testSingleMatch() {
|
||||
WifiAwareNetworkSpecifier nsThis = getDummyNetworkSpecifier(6);
|
||||
WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier(nsThis);
|
||||
WifiAwareNetworkSpecifier nsOther = getDummyNetworkSpecifier(8);
|
||||
collector.checkThat("Match expected", nsThis.satisfiedBy(dut), equalTo(true));
|
||||
collector.checkThat("No match expected", nsOther.satisfiedBy(dut), equalTo(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that an agent network specifier constructed with multiple entries matches all those
|
||||
* entries - but none other.
|
||||
*/
|
||||
@Test
|
||||
public void testMultipleMatchesAllMembers() {
|
||||
final int numNs = 10;
|
||||
|
||||
Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>();
|
||||
for (int i = 0; i < numNs; ++i) {
|
||||
nsSet.add(getDummyNetworkSpecifier(10 + i));
|
||||
}
|
||||
|
||||
WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier(
|
||||
nsSet.toArray(new WifiAwareNetworkSpecifier[numNs]));
|
||||
WifiAwareNetworkSpecifier nsOther = getDummyNetworkSpecifier(10000);
|
||||
|
||||
for (WifiAwareNetworkSpecifier nsThis: nsSet) {
|
||||
collector.checkThat("Match expected", nsThis.satisfiedBy(dut), equalTo(true));
|
||||
}
|
||||
collector.checkThat("No match expected", nsOther.satisfiedBy(dut), equalTo(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that agent network specifier matches against a super-set.
|
||||
*/
|
||||
@Test
|
||||
public void testMatchSuperset() {
|
||||
final int numNs = 10;
|
||||
|
||||
Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>();
|
||||
for (int i = 0; i < numNs; ++i) {
|
||||
nsSet.add(getDummyNetworkSpecifier(10 + i));
|
||||
}
|
||||
|
||||
WifiAwareAgentNetworkSpecifier oldNs = new WifiAwareAgentNetworkSpecifier(
|
||||
nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()]));
|
||||
|
||||
nsSet.add(getDummyNetworkSpecifier(100 + numNs));
|
||||
WifiAwareAgentNetworkSpecifier newNs = new WifiAwareAgentNetworkSpecifier(
|
||||
nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()]));
|
||||
|
||||
collector.checkThat("Match expected", oldNs.satisfiedBy(newNs), equalTo(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that agent network specifier does not match against a sub-set.
|
||||
*/
|
||||
@Test
|
||||
public void testNoMatchSubset() {
|
||||
final int numNs = 10;
|
||||
|
||||
Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>();
|
||||
for (int i = 0; i < numNs; ++i) {
|
||||
nsSet.add(getDummyNetworkSpecifier(10 + i));
|
||||
}
|
||||
|
||||
WifiAwareAgentNetworkSpecifier newNs = new WifiAwareAgentNetworkSpecifier(
|
||||
nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()]));
|
||||
|
||||
nsSet.add(getDummyNetworkSpecifier(100 + numNs));
|
||||
WifiAwareAgentNetworkSpecifier oldNs = new WifiAwareAgentNetworkSpecifier(
|
||||
nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()]));
|
||||
|
||||
collector.checkThat("Match unexpected", oldNs.satisfiedBy(newNs), equalTo(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that agent network specifier cannot be used as in network requests - i.e. that
|
||||
* throws an exception when queried for UID validity.
|
||||
*/
|
||||
@Test(expected = SecurityException.class)
|
||||
public void testNoUsageInRequest() {
|
||||
WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier();
|
||||
|
||||
dut.assertValidFromUid(0);
|
||||
}
|
||||
|
||||
// utilities
|
||||
|
||||
/**
|
||||
* Returns a WifiAwareNetworkSpecifier with dummy (but valid) entries. Each can be
|
||||
* differentiated (made unique) by specifying a different client ID.
|
||||
*/
|
||||
WifiAwareNetworkSpecifier getDummyNetworkSpecifier(int clientId) {
|
||||
return new WifiAwareNetworkSpecifier(WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB,
|
||||
WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, clientId, 0, 0, new byte[6],
|
||||
null, null, 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user