Merge "Use the new refined DexOptNeeded codes."
diff --git a/api/current.txt b/api/current.txt
index 21ff787..f736bc0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -37222,6 +37222,7 @@
method public int getCallState();
method public android.telephony.CellLocation getCellLocation();
method public int getDataActivity();
+ method public boolean getDataEnabled();
method public int getDataNetworkType();
method public int getDataState();
method public java.lang.String getDeviceId();
@@ -37266,6 +37267,7 @@
method public boolean isWorldPhone();
method public void listen(android.telephony.PhoneStateListener, int);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
+ method public void setDataEnabled(boolean);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
method public boolean setPreferredNetworkTypeToGlobal();
@@ -37273,6 +37275,7 @@
field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
+ field public static final java.lang.String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
field public static final int APPTYPE_CSIM = 4; // 0x4
field public static final int APPTYPE_ISIM = 5; // 0x5
field public static final int APPTYPE_RUIM = 3; // 0x3
@@ -37292,11 +37295,15 @@
field public static final int DATA_CONNECTING = 1; // 0x1
field public static final int DATA_DISCONNECTED = 0; // 0x0
field public static final int DATA_SUSPENDED = 3; // 0x3
+ field public static final java.lang.String EXTRA_CALL_VOICEMAIL_INTENT = "android.telephony.extra.CALL_VOICEMAIL_INTENT";
field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number";
+ field public static final java.lang.String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
+ field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
field public static final java.lang.String EXTRA_STATE = "state";
field public static final java.lang.String EXTRA_STATE_IDLE;
field public static final java.lang.String EXTRA_STATE_OFFHOOK;
field public static final java.lang.String EXTRA_STATE_RINGING;
+ field public static final java.lang.String EXTRA_VOICEMAIL_NUMBER = "android.telephony.extra.VOICEMAIL_NUMBER";
field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
diff --git a/api/test-current.txt b/api/test-current.txt
index 5301443..4af0615 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -37299,6 +37299,7 @@
method public int getCallState();
method public android.telephony.CellLocation getCellLocation();
method public int getDataActivity();
+ method public boolean getDataEnabled();
method public int getDataNetworkType();
method public int getDataState();
method public java.lang.String getDeviceId();
@@ -37343,6 +37344,7 @@
method public boolean isWorldPhone();
method public void listen(android.telephony.PhoneStateListener, int);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
+ method public void setDataEnabled(boolean);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
method public boolean setPreferredNetworkTypeToGlobal();
@@ -37350,6 +37352,7 @@
field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
+ field public static final java.lang.String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
field public static final int APPTYPE_CSIM = 4; // 0x4
field public static final int APPTYPE_ISIM = 5; // 0x5
field public static final int APPTYPE_RUIM = 3; // 0x3
@@ -37369,11 +37372,15 @@
field public static final int DATA_CONNECTING = 1; // 0x1
field public static final int DATA_DISCONNECTED = 0; // 0x0
field public static final int DATA_SUSPENDED = 3; // 0x3
+ field public static final java.lang.String EXTRA_CALL_VOICEMAIL_INTENT = "android.telephony.extra.CALL_VOICEMAIL_INTENT";
field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number";
+ field public static final java.lang.String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
+ field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
field public static final java.lang.String EXTRA_STATE = "state";
field public static final java.lang.String EXTRA_STATE_IDLE;
field public static final java.lang.String EXTRA_STATE_OFFHOOK;
field public static final java.lang.String EXTRA_STATE_RINGING;
+ field public static final java.lang.String EXTRA_VOICEMAIL_NUMBER = "android.telephony.extra.VOICEMAIL_NUMBER";
field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 6a73829..ef2db4a 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -16,17 +16,19 @@
package android.app;
+import android.os.Build;
import android.os.Trace;
import android.util.ArrayMap;
import com.android.internal.os.PathClassLoaderFactory;
import dalvik.system.PathClassLoader;
-class ApplicationLoaders {
+/** @hide */
+public class ApplicationLoaders {
public static ApplicationLoaders getDefault() {
return gApplicationLoaders;
}
- public ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
+ ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
String librarySearchPath, String libraryPermittedPath,
ClassLoader parent) {
/*
@@ -80,6 +82,19 @@
}
}
+ /**
+ * Creates a classloader for the WebView APK and places it in the cache of loaders maintained
+ * by this class. This is used in the WebView zygote, where its presence in the cache speeds up
+ * startup and enables memory sharing.
+ */
+ public ClassLoader createAndCacheWebViewClassLoader(String packagePath, String libsPath) {
+ // The correct paths are calculated by WebViewZygote in the system server and passed to
+ // us here. We hardcode the other parameters: WebView always targets the current SDK,
+ // does not need to use non-public system libraries, and uses the base classloader as its
+ // parent to permit usage of the cache.
+ return getClassLoader(packagePath, Build.VERSION.SDK_INT, false, libsPath, null, null);
+ }
+
private static native void setupVulkanLayerPath(ClassLoader classLoader, String librarySearchPath);
/**
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index b889c8f..8824c981 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -339,39 +339,43 @@
* concatenation of both apps' shared library lists.
*/
- String instrumentationPackageName = activityThread.mInstrumentationPackageName;
- String instrumentationAppDir = activityThread.mInstrumentationAppDir;
- String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
- String instrumentationLibDir = activityThread.mInstrumentationLibDir;
-
- String instrumentedAppDir = activityThread.mInstrumentedAppDir;
- String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
- String instrumentedLibDir = activityThread.mInstrumentedLibDir;
String[] instrumentationLibs = null;
+ // activityThread will be null when called from the WebView zygote; just assume
+ // no instrumentation applies in this case.
+ if (activityThread != null) {
+ String instrumentationPackageName = activityThread.mInstrumentationPackageName;
+ String instrumentationAppDir = activityThread.mInstrumentationAppDir;
+ String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
+ String instrumentationLibDir = activityThread.mInstrumentationLibDir;
- if (appDir.equals(instrumentationAppDir)
- || appDir.equals(instrumentedAppDir)) {
- outZipPaths.clear();
- outZipPaths.add(instrumentationAppDir);
- if (instrumentationSplitAppDirs != null) {
- Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
- }
- if (!instrumentationAppDir.equals(instrumentedAppDir)) {
- outZipPaths.add(instrumentedAppDir);
- if (instrumentedSplitAppDirs != null) {
- Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
+ String instrumentedAppDir = activityThread.mInstrumentedAppDir;
+ String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
+ String instrumentedLibDir = activityThread.mInstrumentedLibDir;
+
+ if (appDir.equals(instrumentationAppDir)
+ || appDir.equals(instrumentedAppDir)) {
+ outZipPaths.clear();
+ outZipPaths.add(instrumentationAppDir);
+ if (instrumentationSplitAppDirs != null) {
+ Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
}
- }
-
- if (outLibPaths != null) {
- outLibPaths.add(instrumentationLibDir);
- if (!instrumentationLibDir.equals(instrumentedLibDir)) {
- outLibPaths.add(instrumentedLibDir);
+ if (!instrumentationAppDir.equals(instrumentedAppDir)) {
+ outZipPaths.add(instrumentedAppDir);
+ if (instrumentedSplitAppDirs != null) {
+ Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
+ }
}
- }
- if (!instrumentedAppDir.equals(instrumentationAppDir)) {
- instrumentationLibs = getLibrariesFor(instrumentationPackageName);
+ if (outLibPaths != null) {
+ outLibPaths.add(instrumentationLibDir);
+ if (!instrumentationLibDir.equals(instrumentedLibDir)) {
+ outLibPaths.add(instrumentedLibDir);
+ }
+ }
+
+ if (!instrumentedAppDir.equals(instrumentationAppDir)) {
+ instrumentationLibs = getLibrariesFor(instrumentationPackageName);
+ }
}
}
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 5d27662..94d03e5 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -235,6 +235,7 @@
// >=0: registered and advertising started
private int mAdvertiserId;
private boolean mIsAdvertising = false;
+ private int registrationError = AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR;
public AdvertiseCallbackWrapper(AdvertiseCallback advertiseCallback,
AdvertiseData advertiseData, AdvertiseData scanResponse,
@@ -262,12 +263,11 @@
mLeAdvertisers.put(mAdvertiseCallback, this);
} else if (mAdvertiserId < 0) {
- // Registration timeout, reset mClientIf to -1 so no subsequent operations can
+ // Registration timeout, reset mClientIf to -2 so no subsequent operations can
// proceed.
- if (mAdvertiserId == 0) mAdvertiserId = -2;
+ if (mAdvertiserId == -1) mAdvertiserId = -2;
// Post internal error if registration failed.
- postStartFailure(mAdvertiseCallback,
- AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
+ postStartFailure(mAdvertiseCallback, registrationError);
} else {
// Unregister application if it's already registered but advertise failed.
try {
@@ -318,6 +318,8 @@
} catch (RemoteException e) {
Log.e(TAG, "failed to start advertising", e);
}
+ } else if (status == AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS) {
+ registrationError = status;
}
// Registration failed.
mAdvertiserId = -2;
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 1ac9fca..e7436be 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -108,6 +108,26 @@
*/
public static final int TAG_SYSTEM_RESTORE = 0xFFFFFF04;
+ /** @hide */
+ public static final int TAG_SYSTEM_DHCP = 0xFFFFFF05;
+ /** @hide */
+ public static final int TAG_SYSTEM_NTP = 0xFFFFFF06;
+ /** @hide */
+ public static final int TAG_SYSTEM_PROBE = 0xFFFFFF07;
+ /** @hide */
+ public static final int TAG_SYSTEM_NEIGHBOR = 0xFFFFFF08;
+ /** @hide */
+ public static final int TAG_SYSTEM_GPS = 0xFFFFFF09;
+ /** @hide */
+ public static final int TAG_SYSTEM_PAC = 0xFFFFFF0A;
+
+ /**
+ * Sockets that are strictly local on device; never hits network.
+ *
+ * @hide
+ */
+ public static final int TAG_SYSTEM_LOCAL = 0xFFFFFFAA;
+
private static INetworkStatsService sStatsService;
private synchronized static INetworkStatsService getStatsService() {
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index ea8ba2f..50a3f4c 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -129,6 +129,17 @@
return sTransactionTracker;
}
+ /** @hide */
+ public static IBinder allowBlocking(IBinder binder) {
+ // NOTE: real implementation on internal branch
+ return binder;
+ }
+
+ /** @hide */
+ public static void copyAllowBlocking(IBinder fromBinder, IBinder toBinder) {
+ // NOTE: real implementation on internal branch
+ }
+
/* mObject is used by native code, do not remove or rename */
private long mObject;
private IInterface mOwner;
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 1479035..e47c238 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -39,6 +39,7 @@
private static native boolean native_get_boolean(String key, boolean def);
private static native void native_set(String key, String def);
private static native void native_add_change_callback();
+ private static native void native_report_sysprop_change();
/**
* Get the value for the given key.
@@ -151,4 +152,11 @@
}
}
}
+
+ /*
+ * Notifies listeners that a system property has changed
+ */
+ public static void reportSyspropChanged() {
+ native_report_sysprop_change();
+ }
}
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index f41a838..f1e8fc2d 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -56,7 +56,9 @@
@SystemApi
public final class WebViewFactory {
- private static final String CHROMIUM_WEBVIEW_FACTORY =
+ // visible for WebViewZygoteInit to look up the class by reflection and call preloadInZygote.
+ /** @hide */
+ public static final String CHROMIUM_WEBVIEW_FACTORY =
"com.android.webview.chromium.WebViewChromiumFactoryProvider";
private static final String NULL_WEBVIEW_FACTORY =
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index bc6e7b4..c206974 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -16,14 +16,19 @@
package android.webkit;
+import android.app.LoadedApk;
import android.content.pm.PackageInfo;
import android.os.Build;
import android.os.SystemService;
import android.os.ZygoteProcess;
+import android.text.TextUtils;
import android.util.Log;
+import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.concurrent.TimeoutException;
/** @hide */
@@ -122,11 +127,21 @@
try {
sZygote = new ZygoteProcess("webview_zygote", null);
- String packagePath = sPackage.applicationInfo.sourceDir;
- String libsPath = sPackage.applicationInfo.nativeLibraryDir;
+ // All the work below is usually done by LoadedApk, but the zygote can't talk to
+ // PackageManager or construct a LoadedApk since it's single-threaded pre-fork, so
+ // doesn't have an ActivityThread and can't use Binder.
+ // Instead, figure out the paths here, in the system server where we have access to
+ // the package manager. Reuse the logic from LoadedApk to determine the correct
+ // paths and pass them to the zygote as strings.
+ final List<String> zipPaths = new ArrayList<>(10);
+ final List<String> libPaths = new ArrayList<>(10);
+ LoadedApk.makePaths(null, sPackage.applicationInfo, zipPaths, libPaths);
+ final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
+ final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
+ TextUtils.join(File.pathSeparator, zipPaths);
- Log.d(LOGTAG, "Preloading package " + packagePath + " " + libsPath);
- sZygote.preloadPackageForAbi(packagePath, libsPath, Build.SUPPORTED_ABIS[0]);
+ Log.d(LOGTAG, "Preloading package " + zip + " " + librarySearchPath);
+ sZygote.preloadPackageForAbi(zip, librarySearchPath, Build.SUPPORTED_ABIS[0]);
} catch (Exception e) {
Log.e(LOGTAG, "Error connecting to " + serviceName, e);
sZygote = null;
diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java
index 11dd0e8..d968e3c 100644
--- a/core/java/com/android/internal/os/WebViewZygoteInit.java
+++ b/core/java/com/android/internal/os/WebViewZygoteInit.java
@@ -16,14 +16,17 @@
package com.android.internal.os;
+import android.app.ApplicationLoaders;
import android.net.LocalSocket;
import android.os.Build;
import android.system.ErrnoException;
import android.system.Os;
import android.text.TextUtils;
import android.util.Log;
+import android.webkit.WebViewFactory;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
/**
* Startup class for the WebView zygote process.
@@ -52,7 +55,27 @@
@Override
protected boolean handlePreloadPackage(String packagePath, String libsPath) {
- // TODO: Use preload information to setup the ClassLoader.
+ // Ask ApplicationLoaders to create and cache a classloader for the WebView APK so that
+ // our children will reuse the same classloader instead of creating their own.
+ // This enables us to preload Java and native code in the webview zygote process and
+ // have the preloaded versions actually be used post-fork.
+ ClassLoader loader = ApplicationLoaders.getDefault().createAndCacheWebViewClassLoader(
+ packagePath, libsPath);
+
+ // Once we have the classloader, look up the WebViewFactoryProvider implementation and
+ // call preloadInZygote() on it to give it the opportunity to preload the native library
+ // and perform any other initialisation work that should be shared among the children.
+ try {
+ Class providerClass = Class.forName(WebViewFactory.CHROMIUM_WEBVIEW_FACTORY, true,
+ loader);
+ Object result = providerClass.getMethod("preloadInZygote").invoke(null);
+ if (!((Boolean)result).booleanValue()) {
+ Log.e(TAG, "preloadInZygote returned false");
+ }
+ } catch (ClassNotFoundException | NoSuchMethodException | SecurityException |
+ IllegalAccessException | InvocationTargetException e) {
+ Log.e(TAG, "Exception while preloading package", e);
+ }
return false;
}
}
diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp
index 5dace6b..8844fb0 100644
--- a/core/jni/android_os_SystemProperties.cpp
+++ b/core/jni/android_os_SystemProperties.cpp
@@ -220,6 +220,11 @@
}
}
+static void SystemProperties_report_sysprop_change(JNIEnv /**env*/, jobject /*clazz*/)
+{
+ report_sysprop_change();
+}
+
static const JNINativeMethod method_table[] = {
{ "native_get", "(Ljava/lang/String;)Ljava/lang/String;",
(void*) SystemProperties_getS },
@@ -235,6 +240,8 @@
(void*) SystemProperties_set },
{ "native_add_change_callback", "()V",
(void*) SystemProperties_add_change_callback },
+ { "native_report_sysprop_change", "()V",
+ (void*) SystemProperties_report_sysprop_change },
};
int register_android_os_SystemProperties(JNIEnv *env)
diff --git a/media/mca/filterfw/jni/jni_gl_environment.cpp b/media/mca/filterfw/jni/jni_gl_environment.cpp
index 096120e..823e88a 100644
--- a/media/mca/filterfw/jni/jni_gl_environment.cpp
+++ b/media/mca/filterfw/jni/jni_gl_environment.cpp
@@ -63,7 +63,8 @@
};
jboolean Java_android_filterfw_core_GLEnvironment_nativeAllocate(JNIEnv* env, jobject thiz) {
- return ToJBool(WrapObjectInJava(new GLEnv(), env, thiz, true));
+ std::unique_ptr<GLEnv> glEnv(new GLEnv());
+ return ToJBool(WrapOwnedObjectInJava(std::move(glEnv), env, thiz, true));
}
jboolean Java_android_filterfw_core_GLEnvironment_nativeDeallocate(JNIEnv* env, jobject thiz) {
diff --git a/media/mca/filterfw/jni/jni_gl_frame.cpp b/media/mca/filterfw/jni/jni_gl_frame.cpp
index b55bc5d..27b4cd2 100644
--- a/media/mca/filterfw/jni/jni_gl_frame.cpp
+++ b/media/mca/filterfw/jni/jni_gl_frame.cpp
@@ -48,13 +48,11 @@
jint height) {
GLEnv* gl_env_ptr = ConvertFromJava<GLEnv>(env, gl_env);
if (!gl_env_ptr) return JNI_FALSE;
- GLFrame* frame = new GLFrame(gl_env_ptr);
+ std::unique_ptr<GLFrame> frame(new GLFrame(gl_env_ptr));
if (frame->Init(width, height)) {
- return ToJBool(WrapObjectInJava(frame, env, thiz, true));
- } else {
- delete frame;
- return JNI_FALSE;
+ return ToJBool(WrapOwnedObjectInJava(std::move(frame), env, thiz, true));
}
+ return JNI_FALSE;
}
jboolean Java_android_filterfw_core_GLFrame_nativeAllocateWithTexture(JNIEnv* env,
@@ -65,13 +63,11 @@
jint height) {
GLEnv* gl_env_ptr = ConvertFromJava<GLEnv>(env, gl_env);
if (!gl_env_ptr) return JNI_FALSE;
- GLFrame* frame = new GLFrame(gl_env_ptr);
+ std::unique_ptr<GLFrame> frame(new GLFrame(gl_env_ptr));
if (frame->InitWithTexture(tex_id, width, height)) {
- return ToJBool(WrapObjectInJava(frame, env, thiz, true));
- } else {
- delete frame;
- return JNI_FALSE;
+ return ToJBool(WrapOwnedObjectInJava(std::move(frame), env, thiz, true));
}
+ return JNI_FALSE;
}
jboolean Java_android_filterfw_core_GLFrame_nativeAllocateWithFbo(JNIEnv* env,
@@ -82,13 +78,11 @@
jint height) {
GLEnv* gl_env_ptr = ConvertFromJava<GLEnv>(env, gl_env);
if (!gl_env_ptr) return JNI_FALSE;
- GLFrame* frame = new GLFrame(gl_env_ptr);
+ std::unique_ptr<GLFrame> frame(new GLFrame(gl_env_ptr));
if (frame->InitWithFbo(fbo_id, width, height)) {
- return ToJBool(WrapObjectInJava(frame, env, thiz, true));
- } else {
- delete frame;
- return JNI_FALSE;
+ return ToJBool(WrapOwnedObjectInJava(std::move(frame), env, thiz, true));
}
+ return JNI_FALSE;
}
jboolean Java_android_filterfw_core_GLFrame_nativeAllocateExternal(JNIEnv* env,
@@ -96,13 +90,11 @@
jobject gl_env) {
GLEnv* gl_env_ptr = ConvertFromJava<GLEnv>(env, gl_env);
if (!gl_env_ptr) return JNI_FALSE;
- GLFrame* frame = new GLFrame(gl_env_ptr);
+ std::unique_ptr<GLFrame> frame(new GLFrame(gl_env_ptr));
if (frame->InitWithExternalTexture()) {
- return ToJBool(WrapObjectInJava(frame, env, thiz, true));
- } else {
- delete frame;
- return JNI_FALSE;
+ return ToJBool(WrapOwnedObjectInJava(std::move(frame), env, thiz, true));
}
+ return JNI_FALSE;
}
jboolean Java_android_filterfw_core_GLFrame_nativeDeallocate(JNIEnv* env, jobject thiz) {
diff --git a/media/mca/filterfw/jni/jni_native_frame.cpp b/media/mca/filterfw/jni/jni_native_frame.cpp
index c8f2352..1a11a19 100644
--- a/media/mca/filterfw/jni/jni_native_frame.cpp
+++ b/media/mca/filterfw/jni/jni_native_frame.cpp
@@ -35,7 +35,8 @@
jboolean Java_android_filterfw_core_NativeFrame_nativeAllocate(JNIEnv* env,
jobject thiz,
jint size) {
- return ToJBool(WrapObjectInJava(new NativeFrame(size), env, thiz, true));
+ std::unique_ptr<NativeFrame> frame(new NativeFrame(size));
+ return ToJBool(WrapOwnedObjectInJava(std::move(frame), env, thiz, true));
}
jboolean Java_android_filterfw_core_NativeFrame_nativeDeallocate(JNIEnv* env, jobject thiz) {
diff --git a/media/mca/filterfw/jni/jni_native_program.cpp b/media/mca/filterfw/jni/jni_native_program.cpp
index b30b769..1424607 100644
--- a/media/mca/filterfw/jni/jni_native_program.cpp
+++ b/media/mca/filterfw/jni/jni_native_program.cpp
@@ -28,7 +28,8 @@
using android::filterfw::NativeProgram;
jboolean Java_android_filterfw_core_NativeProgram_allocate(JNIEnv* env, jobject thiz) {
- return ToJBool(WrapObjectInJava(new NativeProgram(), env, thiz, true));
+ std::unique_ptr<NativeProgram> program(new NativeProgram());
+ return ToJBool(WrapOwnedObjectInJava(std::move(program), env, thiz, true));
}
jboolean Java_android_filterfw_core_NativeProgram_deallocate(JNIEnv* env, jobject thiz) {
diff --git a/media/mca/filterfw/jni/jni_shader_program.cpp b/media/mca/filterfw/jni/jni_shader_program.cpp
index 19f43cd..98be04c 100644
--- a/media/mca/filterfw/jni/jni_shader_program.cpp
+++ b/media/mca/filterfw/jni/jni_shader_program.cpp
@@ -46,21 +46,14 @@
// Create the shader
if (!fragment_shader || !gl_env_ptr)
return false;
- else if (!vertex_shader)
- return ToJBool(WrapObjectInJava(new ShaderProgram(
- gl_env_ptr,
- ToCppString(env, fragment_shader)),
- env,
- thiz,
- true));
+
+ std::unique_ptr<ShaderProgram> shader;
+ if (!vertex_shader)
+ shader.reset(new ShaderProgram(gl_env_ptr, ToCppString(env, fragment_shader)));
else
- return ToJBool(WrapObjectInJava(new ShaderProgram(
- gl_env_ptr,
- ToCppString(env, vertex_shader),
- ToCppString(env, fragment_shader)),
- env,
- thiz,
- true));
+ shader.reset(new ShaderProgram(gl_env_ptr, ToCppString(env, vertex_shader),
+ ToCppString(env, fragment_shader)));
+ return ToJBool(WrapOwnedObjectInJava(std::move(shader), env, thiz, true));
}
jboolean Java_android_filterfw_core_ShaderProgram_deallocate(JNIEnv* env, jobject thiz) {
diff --git a/media/mca/filterfw/jni/jni_util.h b/media/mca/filterfw/jni/jni_util.h
index 11c0871..803ed29 100644
--- a/media/mca/filterfw/jni/jni_util.h
+++ b/media/mca/filterfw/jni/jni_util.h
@@ -16,6 +16,7 @@
#include <jni.h>
+#include <memory>
#include <unordered_map>
#include <string>
@@ -214,6 +215,17 @@
return pool ? pool->WrapObject(c_object, env, j_object, owns) : false;
}
+// Calls WrapObjectInJava, safely freeing c_object if object creation fails.
+template<typename T>
+bool WrapOwnedObjectInJava(std::unique_ptr<T> c_object, JNIEnv* env,
+ jobject j_object, bool owns) {
+ if (!WrapObjectInJava<T>(c_object.get(), env, j_object, owns))
+ return false;
+ // If we succeeded, a Java object now owns our c object; don't free it.
+ c_object.release();
+ return true;
+}
+
// Creates a new Java instance, which wraps the passed C++ instance. Returns
// the wrapped object or JNI_NULL if there was an error. Pass true to owns, if
// the Java layer should own the object.
diff --git a/media/mca/filterfw/jni/jni_vertex_frame.cpp b/media/mca/filterfw/jni/jni_vertex_frame.cpp
index caae938..d0439fe 100644
--- a/media/mca/filterfw/jni/jni_vertex_frame.cpp
+++ b/media/mca/filterfw/jni/jni_vertex_frame.cpp
@@ -24,7 +24,8 @@
jboolean Java_android_filterfw_core_VertexFrame_nativeAllocate(JNIEnv* env,
jobject thiz,
jint size) {
- return ToJBool(WrapObjectInJava(new VertexFrame(size), env, thiz, true));
+ std::unique_ptr<VertexFrame> frame(new VertexFrame(size));
+ return ToJBool(WrapOwnedObjectInJava(std::move(frame), env, thiz, true));
}
jboolean Java_android_filterfw_core_VertexFrame_nativeDeallocate(JNIEnv* env, jobject thiz) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c6ed04c..ca17c06 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -678,42 +678,49 @@
public static final String EXTRA_DATA_FAILURE_CAUSE = PhoneConstants.DATA_FAILURE_CAUSE_KEY;
/**
- * Broadcast intent action for letting custom component know to show voicemail notification.
- * @hide
+ * Broadcast intent action for letting the default dialer to know to show voicemail
+ * notification.
+ *
+ * <p>
+ * The {@link #EXTRA_NOTIFICATION_COUNT} extra indicates the total numbers of unheard
+ * voicemails.
+ * The {@link #EXTRA_VOICEMAIL_NUMBER} extra indicates the voicemail number if available.
+ * The {@link #EXTRA_CALL_VOICEMAIL_INTENT} extra is a {@link android.app.PendingIntent} that
+ * will call the voicemail number when sent. This extra will be empty if the voicemail number
+ * is not set, and {@link #EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT} will be set instead.
+ * The {@link #EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT} extra is a
+ * {@link android.app.PendingIntent} that will launch the voicemail settings. This extra is only
+ * available when the voicemail number is not set.
+ *
+ * @see #EXTRA_NOTIFICATION_COUNT
+ * @see #EXTRA_VOICEMAIL_NUMBER
+ * @see #EXTRA_CALL_VOICEMAIL_INTENT
+ * @see #EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT
*/
- @SystemApi
public static final String ACTION_SHOW_VOICEMAIL_NOTIFICATION =
"android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
/**
* The number of voice messages associated with the notification.
- * @hide
*/
- @SystemApi
public static final String EXTRA_NOTIFICATION_COUNT =
"android.telephony.extra.NOTIFICATION_COUNT";
/**
* The voicemail number.
- * @hide
*/
- @SystemApi
public static final String EXTRA_VOICEMAIL_NUMBER =
"android.telephony.extra.VOICEMAIL_NUMBER";
/**
* The intent to call voicemail.
- * @hide
*/
- @SystemApi
public static final String EXTRA_CALL_VOICEMAIL_INTENT =
"android.telephony.extra.CALL_VOICEMAIL_INTENT";
/**
* The intent to launch voicemail settings.
- * @hide
*/
- @SystemApi
public static final String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT =
"android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
@@ -4550,10 +4557,19 @@
return false;
}
- /** @hide */
- @SystemApi
+ /**
+ * Turns mobile data on or off.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+ * calling app has carrier privileges.
+ *
+ * @param enable Whether to enable mobile data.
+ *
+ * @see #hasCarrierPrivileges
+ */
public void setDataEnabled(boolean enable) {
- setDataEnabled(SubscriptionManager.getDefaultDataSubscriptionId(), enable);
+ setDataEnabled(getSubId(), enable);
}
/** @hide */
@@ -4569,10 +4585,20 @@
}
}
- /** @hide */
- @SystemApi
+ /**
+ * Returns whether mobile data is enabled or not.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE ACCESS_NETWORK_STATE},
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}, or that the
+ * calling app has carrier privileges.
+ *
+ * @return true if mobile data is enabled.
+ *
+ * @see #hasCarrierPrivileges
+ */
public boolean getDataEnabled() {
- return getDataEnabled(SubscriptionManager.getDefaultDataSubscriptionId());
+ return getDataEnabled(getSubId());
}
/** @hide */
diff --git a/test-runner/src/junit/MODULE_LICENSE_CPL b/test-runner/src/junit/MODULE_LICENSE_CPL
deleted file mode 100644
index 541dbb5..0000000
--- a/test-runner/src/junit/MODULE_LICENSE_CPL
+++ /dev/null
@@ -1 +0,0 @@
-http://www.opensource.org/licenses/cpl1.0.php
diff --git a/test-runner/src/junit/runner/ClassPathTestCollector.java b/test-runner/src/junit/runner/ClassPathTestCollector.java
deleted file mode 100644
index f48ddee..0000000
--- a/test-runner/src/junit/runner/ClassPathTestCollector.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package junit.runner;
-
-import java.util.*;
-import java.io.*;
-
-/**
- * An implementation of a TestCollector that consults the
- * class path. It considers all classes on the class path
- * excluding classes in JARs. It leaves it up to subclasses
- * to decide whether a class is a runnable Test.
- *
- * @see TestCollector
- * {@hide} - Not needed for 1.0 SDK
- */
-public abstract class ClassPathTestCollector implements TestCollector {
-
- static final int SUFFIX_LENGTH= ".class".length();
-
- public ClassPathTestCollector() {
- }
-
- public Enumeration collectTests() {
- String classPath= System.getProperty("java.class.path");
- Hashtable result = collectFilesInPath(classPath);
- return result.elements();
- }
-
- public Hashtable collectFilesInPath(String classPath) {
- Hashtable result= collectFilesInRoots(splitClassPath(classPath));
- return result;
- }
-
- Hashtable collectFilesInRoots(Vector roots) {
- Hashtable result= new Hashtable(100);
- Enumeration e= roots.elements();
- while (e.hasMoreElements())
- gatherFiles(new File((String)e.nextElement()), "", result);
- return result;
- }
-
- void gatherFiles(File classRoot, String classFileName, Hashtable result) {
- File thisRoot= new File(classRoot, classFileName);
- if (thisRoot.isFile()) {
- if (isTestClass(classFileName)) {
- String className= classNameFromFile(classFileName);
- result.put(className, className);
- }
- return;
- }
- String[] contents= thisRoot.list();
- if (contents != null) {
- for (int i= 0; i < contents.length; i++)
- gatherFiles(classRoot, classFileName+File.separatorChar+contents[i], result);
- }
- }
-
- Vector splitClassPath(String classPath) {
- Vector result= new Vector();
- String separator= System.getProperty("path.separator");
- StringTokenizer tokenizer= new StringTokenizer(classPath, separator);
- while (tokenizer.hasMoreTokens())
- result.addElement(tokenizer.nextToken());
- return result;
- }
-
- protected boolean isTestClass(String classFileName) {
- return
- classFileName.endsWith(".class") &&
- classFileName.indexOf('$') < 0 &&
- classFileName.indexOf("Test") > 0;
- }
-
- protected String classNameFromFile(String classFileName) {
- // convert /a/b.class to a.b
- String s= classFileName.substring(0, classFileName.length()-SUFFIX_LENGTH);
- String s2= s.replace(File.separatorChar, '.');
- if (s2.startsWith("."))
- return s2.substring(1);
- return s2;
- }
-}
diff --git a/test-runner/src/junit/runner/FailureDetailView.java b/test-runner/src/junit/runner/FailureDetailView.java
deleted file mode 100644
index c846191..0000000
--- a/test-runner/src/junit/runner/FailureDetailView.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package junit.runner;
-
-// The following line was removed for compatibility with Android libraries.
-//import java.awt.Component;
-
-import junit.framework.*;
-
-/**
- * A view to show a details about a failure
- * {@hide} - Not needed for 1.0 SDK
- */
-public interface FailureDetailView {
- // The following definition was removed for compatibility with Android
- // libraries.
- // /**
- // * Returns the component used to present the TraceView
- // */
- // public Component getComponent();
-
- /**
- * Shows details of a TestFailure
- */
- public void showFailure(TestFailure failure);
- /**
- * Clears the view
- */
- public void clear();
-}
diff --git a/test-runner/src/junit/runner/LoadingTestCollector.java b/test-runner/src/junit/runner/LoadingTestCollector.java
deleted file mode 100644
index 9101900..0000000
--- a/test-runner/src/junit/runner/LoadingTestCollector.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package junit.runner;
-
-import java.lang.reflect.*;
-import junit.framework.*;
-
-/**
- * An implementation of a TestCollector that loads
- * all classes on the class path and tests whether
- * it is assignable from Test or provides a static suite method.
- * @see TestCollector
- * {@hide} - Not needed for 1.0 SDK
- */
-public class LoadingTestCollector extends ClassPathTestCollector {
-
- TestCaseClassLoader fLoader;
-
- public LoadingTestCollector() {
- fLoader= new TestCaseClassLoader();
- }
-
- protected boolean isTestClass(String classFileName) {
- try {
- if (classFileName.endsWith(".class")) {
- Class testClass= classFromFile(classFileName);
- return (testClass != null) && isTestClass(testClass);
- }
- }
- catch (ClassNotFoundException expected) {
- }
- catch (NoClassDefFoundError notFatal) {
- }
- return false;
- }
-
- Class classFromFile(String classFileName) throws ClassNotFoundException {
- String className= classNameFromFile(classFileName);
- if (!fLoader.isExcluded(className))
- return fLoader.loadClass(className, false);
- return null;
- }
-
- boolean isTestClass(Class testClass) {
- if (hasSuiteMethod(testClass))
- return true;
- if (Test.class.isAssignableFrom(testClass) &&
- Modifier.isPublic(testClass.getModifiers()) &&
- hasPublicConstructor(testClass))
- return true;
- return false;
- }
-
- boolean hasSuiteMethod(Class testClass) {
- try {
- testClass.getMethod(BaseTestRunner.SUITE_METHODNAME, new Class[0]);
- } catch(Exception e) {
- return false;
- }
- return true;
- }
-
- boolean hasPublicConstructor(Class testClass) {
- try {
- TestSuite.getTestConstructor(testClass);
- } catch(NoSuchMethodException e) {
- return false;
- }
- return true;
- }
-}
diff --git a/test-runner/src/junit/runner/ReloadingTestSuiteLoader.java b/test-runner/src/junit/runner/ReloadingTestSuiteLoader.java
deleted file mode 100644
index c4d80d0..0000000
--- a/test-runner/src/junit/runner/ReloadingTestSuiteLoader.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package junit.runner;
-
-/**
- * A TestSuite loader that can reload classes.
- * {@hide} - Not needed for 1.0 SDK
- */
-public class ReloadingTestSuiteLoader implements TestSuiteLoader {
-
- public Class load(String suiteClassName) throws ClassNotFoundException {
- return createLoader().loadClass(suiteClassName, true);
- }
-
- public Class reload(Class aClass) throws ClassNotFoundException {
- return createLoader().loadClass(aClass.getName(), true);
- }
-
- protected TestCaseClassLoader createLoader() {
- return new TestCaseClassLoader();
- }
-}
diff --git a/test-runner/src/junit/runner/SimpleTestCollector.java b/test-runner/src/junit/runner/SimpleTestCollector.java
deleted file mode 100644
index 6cb0e19..0000000
--- a/test-runner/src/junit/runner/SimpleTestCollector.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package junit.runner;
-
-/**
- * An implementation of a TestCollector that considers
- * a class to be a test class when it contains the
- * pattern "Test" in its name
- * @see TestCollector
- * {@hide} - Not needed for 1.0 SDK
- */
-public class SimpleTestCollector extends ClassPathTestCollector {
-
- public SimpleTestCollector() {
- }
-
- protected boolean isTestClass(String classFileName) {
- return
- classFileName.endsWith(".class") &&
- classFileName.indexOf('$') < 0 &&
- classFileName.indexOf("Test") > 0;
- }
-}
diff --git a/test-runner/src/junit/runner/Sorter.java b/test-runner/src/junit/runner/Sorter.java
deleted file mode 100644
index 8d9341d..0000000
--- a/test-runner/src/junit/runner/Sorter.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package junit.runner;
-
-import java.util.*;
-
-/**
- * A custom quick sort with support to customize the swap behaviour.
- * NOTICE: We can't use the the sorting support from the JDK 1.2 collection
- * classes because of the JDK 1.1.7 compatibility.
- * {@hide} - Not needed for 1.0 SDK
- */
-public class Sorter {
- public static interface Swapper {
- public void swap(Vector values, int left, int right);
- }
-
- public static void sortStrings(Vector values , int left, int right, Swapper swapper) {
- int oleft= left;
- int oright= right;
- String mid= (String)values.elementAt((left + right) / 2);
- do {
- while (((String)(values.elementAt(left))).compareTo(mid) < 0)
- left++;
- while (mid.compareTo((String)(values.elementAt(right))) < 0)
- right--;
- if (left <= right) {
- swapper.swap(values, left, right);
- left++;
- right--;
- }
- } while (left <= right);
-
- if (oleft < right)
- sortStrings(values, oleft, right, swapper);
- if (left < oright)
- sortStrings(values, left, oright, swapper);
- }
-}
diff --git a/test-runner/src/junit/runner/TestCaseClassLoader.java b/test-runner/src/junit/runner/TestCaseClassLoader.java
deleted file mode 100644
index 09eec7f..0000000
--- a/test-runner/src/junit/runner/TestCaseClassLoader.java
+++ /dev/null
@@ -1,225 +0,0 @@
-package junit.runner;
-
-import java.util.*;
-import java.io.*;
-import java.net.URL;
-import java.util.zip.*;
-
-/**
- * A custom class loader which enables the reloading
- * of classes for each test run. The class loader
- * can be configured with a list of package paths that
- * should be excluded from loading. The loading
- * of these packages is delegated to the system class
- * loader. They will be shared across test runs.
- * <p>
- * The list of excluded package paths is specified in
- * a properties file "excluded.properties" that is located in
- * the same place as the TestCaseClassLoader class.
- * <p>
- * <b>Known limitation:</b> the TestCaseClassLoader cannot load classes
- * from jar files.
- * {@hide} - Not needed for 1.0 SDK
- */
-public class TestCaseClassLoader extends ClassLoader {
- /** scanned class path */
- private Vector fPathItems;
- /** default excluded paths */
- private String[] defaultExclusions= {
- "junit.framework.",
- "junit.extensions.",
- "junit.runner."
- };
- /** name of excluded properties file */
- static final String EXCLUDED_FILE= "excluded.properties";
- /** excluded paths */
- private Vector fExcluded;
-
- /**
- * Constructs a TestCaseLoader. It scans the class path
- * and the excluded package paths
- */
- public TestCaseClassLoader() {
- this(System.getProperty("java.class.path"));
- }
-
- /**
- * Constructs a TestCaseLoader. It scans the class path
- * and the excluded package paths
- */
- public TestCaseClassLoader(String classPath) {
- scanPath(classPath);
- readExcludedPackages();
- }
-
- private void scanPath(String classPath) {
- String separator= System.getProperty("path.separator");
- fPathItems= new Vector(10);
- StringTokenizer st= new StringTokenizer(classPath, separator);
- while (st.hasMoreTokens()) {
- fPathItems.addElement(st.nextToken());
- }
- }
-
- public URL getResource(String name) {
- return ClassLoader.getSystemResource(name);
- }
-
- public InputStream getResourceAsStream(String name) {
- return ClassLoader.getSystemResourceAsStream(name);
- }
-
- public boolean isExcluded(String name) {
- for (int i= 0; i < fExcluded.size(); i++) {
- if (name.startsWith((String) fExcluded.elementAt(i))) {
- return true;
- }
- }
- return false;
- }
-
- public synchronized Class loadClass(String name, boolean resolve)
- throws ClassNotFoundException {
-
- Class c= findLoadedClass(name);
- if (c != null)
- return c;
- //
- // Delegate the loading of excluded classes to the
- // standard class loader.
- //
- if (isExcluded(name)) {
- try {
- c= findSystemClass(name);
- return c;
- } catch (ClassNotFoundException e) {
- // keep searching
- }
- }
- if (c == null) {
- byte[] data= lookupClassData(name);
- if (data == null)
- throw new ClassNotFoundException();
- c= defineClass(name, data, 0, data.length);
- }
- if (resolve)
- resolveClass(c);
- return c;
- }
-
- private byte[] lookupClassData(String className) throws ClassNotFoundException {
- byte[] data= null;
- for (int i= 0; i < fPathItems.size(); i++) {
- String path= (String) fPathItems.elementAt(i);
- String fileName= className.replace('.', '/')+".class";
- if (isJar(path)) {
- data= loadJarData(path, fileName);
- } else {
- data= loadFileData(path, fileName);
- }
- if (data != null)
- return data;
- }
- throw new ClassNotFoundException(className);
- }
-
- boolean isJar(String pathEntry) {
- return pathEntry.endsWith(".jar") ||
- pathEntry.endsWith(".apk") ||
- pathEntry.endsWith(".zip");
- }
-
- private byte[] loadFileData(String path, String fileName) {
- File file= new File(path, fileName);
- if (file.exists()) {
- return getClassData(file);
- }
- return null;
- }
-
- private byte[] getClassData(File f) {
- try {
- FileInputStream stream= new FileInputStream(f);
- ByteArrayOutputStream out= new ByteArrayOutputStream(1000);
- byte[] b= new byte[1000];
- int n;
- while ((n= stream.read(b)) != -1)
- out.write(b, 0, n);
- stream.close();
- out.close();
- return out.toByteArray();
-
- } catch (IOException e) {
- }
- return null;
- }
-
- private byte[] loadJarData(String path, String fileName) {
- ZipFile zipFile= null;
- InputStream stream= null;
- File archive= new File(path);
- if (!archive.exists())
- return null;
- try {
- zipFile= new ZipFile(archive);
- } catch(IOException io) {
- return null;
- }
- ZipEntry entry= zipFile.getEntry(fileName);
- if (entry == null)
- return null;
- int size= (int) entry.getSize();
- try {
- stream= zipFile.getInputStream(entry);
- byte[] data= new byte[size];
- int pos= 0;
- while (pos < size) {
- int n= stream.read(data, pos, data.length - pos);
- pos += n;
- }
- zipFile.close();
- return data;
- } catch (IOException e) {
- } finally {
- try {
- if (stream != null)
- stream.close();
- } catch (IOException e) {
- }
- }
- return null;
- }
-
- private void readExcludedPackages() {
- fExcluded= new Vector(10);
- for (int i= 0; i < defaultExclusions.length; i++)
- fExcluded.addElement(defaultExclusions[i]);
-
- InputStream is= getClass().getResourceAsStream(EXCLUDED_FILE);
- if (is == null)
- return;
- Properties p= new Properties();
- try {
- p.load(is);
- }
- catch (IOException e) {
- return;
- } finally {
- try {
- is.close();
- } catch (IOException e) {
- }
- }
- for (Enumeration e= p.propertyNames(); e.hasMoreElements(); ) {
- String key= (String)e.nextElement();
- if (key.startsWith("excluded.")) {
- String path= p.getProperty(key);
- path= path.trim();
- if (path.endsWith("*"))
- path= path.substring(0, path.length()-1);
- if (path.length() > 0)
- fExcluded.addElement(path);
- }
- }
- }
-}
diff --git a/test-runner/src/junit/runner/TestCollector.java b/test-runner/src/junit/runner/TestCollector.java
deleted file mode 100644
index 3ac9d9e..0000000
--- a/test-runner/src/junit/runner/TestCollector.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package junit.runner;
-
-import java.util.*;
-
-
-/**
- * Collects Test class names to be presented
- * by the TestSelector.
- * @see TestSelector
- * {@hide} - Not needed for 1.0 SDK
- */
-public interface TestCollector {
- /**
- * Returns an enumeration of Strings with qualified class names
- */
- public Enumeration collectTests();
-}
diff --git a/test-runner/src/junit/runner/excluded.properties b/test-runner/src/junit/runner/excluded.properties
deleted file mode 100644
index 3284628..0000000
--- a/test-runner/src/junit/runner/excluded.properties
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# The list of excluded package paths for the TestCaseClassLoader
-#
-excluded.0=sun.*
-excluded.1=com.sun.*
-excluded.2=org.omg.*
-excluded.3=javax.*
-excluded.4=sunw.*
-excluded.5=java.*
-excluded.6=org.w3c.dom.*
-excluded.7=org.xml.sax.*
-excluded.8=net.jini.*
diff --git a/test-runner/src/junit/runner/package.html b/test-runner/src/junit/runner/package.html
deleted file mode 100644
index f08fa70..0000000
--- a/test-runner/src/junit/runner/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<HTML>
-<BODY>
-Utility classes supporting the junit test framework.
-</BODY>
-</HTML>
diff --git a/test-runner/src/junit/textui/package.html b/test-runner/src/junit/textui/package.html
deleted file mode 100644
index 723f2ae..0000000
--- a/test-runner/src/junit/textui/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<HTML>
-<BODY>
-Utility classes supporting the junit test framework.
-{@hide} - Not needed for 1.0 SDK
-</BODY>
-</HTML>
diff --git a/wifi/java/android/net/wifi/aware/PublishConfig.java b/wifi/java/android/net/wifi/aware/PublishConfig.java
index 5d3ad058..ba493a0 100644
--- a/wifi/java/android/net/wifi/aware/PublishConfig.java
+++ b/wifi/java/android/net/wifi/aware/PublishConfig.java
@@ -32,9 +32,8 @@
/**
* Defines the configuration of a Aware publish session. Built using
* {@link PublishConfig.Builder}. A publish session is created using
- * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
- * WifiAwareDiscoverySessionCallback)}
- * or updated using
+ * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
+ * android.os.Handler)} or updated using
* {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)}.
*
* @hide PROPOSED_AWARE_API
diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
index 2a6cc93..5e14f8f 100644
--- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
@@ -32,9 +32,8 @@
/**
* Defines the configuration of a Aware subscribe session. Built using
* {@link SubscribeConfig.Builder}. Subscribe is done using
- * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
- * WifiAwareDiscoverySessionCallback)}
- * or
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
+ * android.os.Handler)} or
* {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
*
* @hide PROPOSED_AWARE_API
@@ -403,8 +402,8 @@
* Sets the match style of the subscription - how are matches from a
* single match session (corresponding to the same publish action on the
* peer) reported to the host (using the
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
- * ). The options are: only report the first match and ignore the rest
+ * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * byte[], byte[])}). The options are: only report the first match and ignore the rest
* {@link SubscribeConfig#MATCH_STYLE_FIRST_ONLY} or report every single
* match {@link SubscribeConfig#MATCH_STYLE_ALL} (the default).
*
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java b/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java
index 2cace61..1e8dbd9 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java
@@ -18,7 +18,7 @@
/**
* Base class for Aware attach callbacks. Should be extended by applications and set when calling
- * {@link WifiAwareManager#attach(android.os.Handler, WifiAwareAttachCallback)}. These are callbacks
+ * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}. These are callbacks
* applying to the Aware connection as a whole - not to specific publish or subscribe sessions -
* for that see {@link WifiAwareDiscoverySessionCallback}.
*
@@ -27,7 +27,7 @@
public class WifiAwareAttachCallback {
/**
* Called when Aware attach operation
- * {@link WifiAwareManager#attach(android.os.Handler, WifiAwareAttachCallback)}
+ * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}
* is completed and that we can now start discovery sessions or connections.
*
* @param session The Aware object on which we can execute further Aware operations - e.g.
@@ -39,7 +39,7 @@
/**
* Called when Aware attach operation
- * {@link WifiAwareManager#attach(android.os.Handler, WifiAwareAttachCallback)} failed.
+ * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)} failed.
*/
public void onAttachFailed() {
/* empty */
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java b/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
index 6232c14..072ccab 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
@@ -58,7 +58,8 @@
* message exchange. Restricts the parameters of the
* {@link PublishConfig.Builder#setServiceSpecificInfo(byte[])},
* {@link SubscribeConfig.Builder#setServiceSpecificInfo(byte[])}, and
- * {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[])} variants.
+ * {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, byte[])}
+ * variants.
*
* @return A positive integer, maximum length of byte array for Aware messaging.
*/
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java b/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
index 07f7523..e8335d1 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
@@ -32,10 +32,10 @@
* {@link WifiAwarePublishDiscoverySession} and {@link WifiAwareSubscribeDiscoverySession}. This
* class provides functionality common to both publish and subscribe discovery sessions:
* <ul>
- * <li>Sending messages: {@link #sendMessage(Object, int, byte[])} or
- * {@link #sendMessage(Object, int, byte[], int)} methods.
+ * <li>Sending messages: {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[])} or
+ * {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)} methods.
* <li>Creating a network-specifier when requesting a Aware connection:
- * {@link #createNetworkSpecifier(int, Object, byte[])}.
+ * {@link #createNetworkSpecifier(int, WifiAwareManager.PeerHandle, byte[])}.
* </ul>
* The {@link #destroy()} method must be called to destroy discovery sessions once they are
* no longer needed.
@@ -62,7 +62,7 @@
/**
* Return the maximum permitted retry count when sending messages using
- * {@link #sendMessage(Object, int, byte[], int)}.
+ * {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)}.
*
* @return Maximum retry count when sending messages.
*/
@@ -139,21 +139,24 @@
/**
* Sends a message to the specified destination. Aware messages are transmitted in the context
* of a discovery session - executed subsequent to a publish/subscribe
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} event.
+ * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * byte[], byte[])} event.
* <p>
* Aware messages are not guaranteed delivery. Callbacks on
* {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully,
- * {@link WifiAwareDiscoverySessionCallback#onMessageSent(int)}, or transmission failed
- * (possibly after several retries) -
+ * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission
+ * failed (possibly after several retries) -
* {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)}.
* <p>
* The peer will get a callback indicating a message was received using
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])}.
+ * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * byte[])}.
*
* @param peerHandle The peer's handle for the message. Must be a result of an
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
- * or
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])} events.
+ * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * byte[], byte[])} or
+ * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * byte[])} events.
* @param messageId An arbitrary integer used by the caller to identify the message. The same
* integer ID will be returned in the callbacks indicating message send success or
* failure. The {@code messageId} is not used internally by the Aware service - it
@@ -164,8 +167,8 @@
* (note: no retransmissions are attempted in other failure cases). A value of 0
* indicates no retries. Max permitted value is {@link #getMaxSendRetryCount()}.
*/
- public void sendMessage(@NonNull Object peerHandle, int messageId, @Nullable byte[] message,
- int retryCount) {
+ public void sendMessage(@NonNull WifiAwareManager.PeerHandle peerHandle, int messageId,
+ @Nullable byte[] message, int retryCount) {
if (mTerminated) {
Log.w(TAG, "sendMessage: called on terminated session");
return;
@@ -183,37 +186,43 @@
/**
* Sends a message to the specified destination. Aware messages are transmitted in the context
* of a discovery session - executed subsequent to a publish/subscribe
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} event.
+ * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * byte[], byte[])} event.
* <p>
* Aware messages are not guaranteed delivery. Callbacks on
* {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully,
- * {@link WifiAwareDiscoverySessionCallback#onMessageSent(int)}, or transmission failed
- * (possibly after several retries) -
+ * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission
+ * failed (possibly after several retries) -
* {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)}.
* <p>
- * The peer will get a callback indicating a message was received using
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])}.
- * Equivalent to {@link #sendMessage(Object, int, byte[], int)} with a {@code retryCount} of
- * 0.
+ * The peer will get a callback indicating a message was received using
+ * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * byte[])}.
+ * Equivalent to {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)}
+ * with a {@code retryCount} of 0.
*
* @param peerHandle The peer's handle for the message. Must be a result of an
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
- * or
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])} events.
+ * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * byte[], byte[])} or
+ * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * byte[])} events.
* @param messageId An arbitrary integer used by the caller to identify the message. The same
* integer ID will be returned in the callbacks indicating message send success or
* failure. The {@code messageId} is not used internally by the Aware service - it
* can be arbitrary and non-unique.
* @param message The message to be transmitted.
*/
- public void sendMessage(@NonNull Object peerHandle, int messageId, @Nullable byte[] message) {
+ public void sendMessage(@NonNull WifiAwareManager.PeerHandle peerHandle, int messageId,
+ @Nullable byte[] message) {
sendMessage(peerHandle, messageId, message, 0);
}
/**
* Start a ranging operation with the specified peers. The peer IDs are obtained from an
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} or
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])} operation - can
+ * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * byte[], byte[])} or
+ * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * byte[])} operation - can
* only range devices which are part of an ongoing discovery session.
*
* @param params RTT parameters - each corresponding to a specific peer ID (the array sizes
@@ -256,11 +265,12 @@
* {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
* {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
* @param peerHandle The peer's handle obtained through
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} or
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])}. On a RESPONDER
- * this value is used to gate the acceptance of a connection request from only
- * that peer. A RESPONDER may specified a null - indicating that it will accept
- * connection requests from any device.
+ * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * byte[], byte[])} or
+ * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
+ * from only that peer. A RESPONDER may specified a null - indicating that
+ * it will accept connection requests from any device.
* @param token An arbitrary token (message) to be used to match connection initiation request
* to a responder setup. A RESPONDER is set up with a {@code token} which must
* be matched by the token provided by the INITIATOR. A null token is permitted
@@ -274,7 +284,7 @@
* [or other varieties of that API].
*/
public String createNetworkSpecifier(@WifiAwareManager.DataPathRole int role,
- @Nullable Object peerHandle, @Nullable byte[] token) {
+ @Nullable WifiAwareManager.PeerHandle peerHandle, @Nullable byte[] token) {
if (mTerminated) {
Log.w(TAG, "createNetworkSpecifier: called on terminated session");
return null;
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java
index 9dfa24f..6331c9c 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java
@@ -26,11 +26,10 @@
* Base class for Aware session events callbacks. Should be extended by
* applications wanting notifications. The callbacks are set when a
* publish or subscribe session is created using
- * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
- * WifiAwareDiscoverySessionCallback)}
- * or
- * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
- * WifiAwareDiscoverySessionCallback)} .
+ * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
+ * android.os.Handler)} or
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
+ * android.os.Handler)}.
* <p>
* A single callback is set at session creation - it cannot be replaced.
*
@@ -62,9 +61,8 @@
/**
* Called when a publish operation is started successfully in response to a
- * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
- * WifiAwareDiscoverySessionCallback)}
- * operation.
+ * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
+ * android.os.Handler)} operation.
*
* @param session The {@link WifiAwarePublishDiscoverySession} used to control the
* discovery session.
@@ -75,9 +73,8 @@
/**
* Called when a subscribe operation is started successfully in response to a
- * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
- * WifiAwareDiscoverySessionCallback)}
- * operation.
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
+ * android.os.Handler)} operation.
*
* @param session The {@link WifiAwareSubscribeDiscoverySession} used to control the
* discovery session.
@@ -98,12 +95,10 @@
/**
* Called when a publish or subscribe discovery session cannot be created:
- * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
- * WifiAwareDiscoverySessionCallback)}
- * or
- * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
- * WifiAwareDiscoverySessionCallback)},
- * or when a configuration update fails:
+ * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
+ * android.os.Handler)} or
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
+ * android.os.Handler)}, or when a configuration update fails:
* {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} or
* {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
* <p>
@@ -138,13 +133,14 @@
* @param matchFilter The filter (Tx on advertiser and Rx on listener) which
* resulted in this service discovery.
*/
- public void onServiceDiscovered(Object peerHandle, byte[] serviceSpecificInfo,
- byte[] matchFilter) {
+ public void onServiceDiscovered(WifiAwareManager.PeerHandle peerHandle,
+ byte[] serviceSpecificInfo, byte[] matchFilter) {
/* empty */
}
/**
- * Called in response to {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[])}
+ * Called in response to
+ * {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, byte[])}
* when a message is transmitted successfully - i.e. when it was received successfully by the
* peer (corresponds to an ACK being received).
* <p>
@@ -154,18 +150,18 @@
*
* @param messageId The arbitrary message ID specified when sending the message.
*/
- public void onMessageSent(@SuppressWarnings("unused") int messageId) {
+ public void onMessageSendSucceeded(@SuppressWarnings("unused") int messageId) {
/* empty */
}
/**
* Called when message transmission fails - when no ACK is received from the peer.
* Retries when ACKs are not received are done by hardware, MAC, and in the Aware stack (using
- * the {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[], int)} method) -
- * this event is received after all retries are exhausted.
+ * the {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int,
+ * byte[], int)} method) - this event is received after all retries are exhausted.
* <p>
* Note that either this callback or
- * {@link WifiAwareDiscoverySessionCallback#onMessageSent(int)} will be received
+ * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)} will be received
* - never both.
*
* @param messageId The arbitrary message ID specified when sending the message.
@@ -176,13 +172,14 @@
/**
* Called when a message is received from a discovery session peer - in response to the
- * peer's {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[])} or
- * {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[], int)}.
+ * peer's {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int,
+ * byte[])} or {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle,
+ * int, byte[], int)}.
*
* @param peerHandle An opaque handle to the peer matching our discovery operation.
* @param message A byte array containing the message.
*/
- public void onMessageReceived(Object peerHandle, byte[] message) {
+ public void onMessageReceived(WifiAwareManager.PeerHandle peerHandle, byte[] message) {
/* empty */
}
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 10b70ab..a34ef47 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -56,14 +56,14 @@
* The class provides access to:
* <ul>
* <li>Initialize a Aware cluster (peer-to-peer synchronization). Refer to
- * {@link #attach(Handler, WifiAwareAttachCallback)}.
+ * {@link #attach(WifiAwareAttachCallback, Handler)}.
* <li>Create discovery sessions (publish or subscribe sessions). Refer to
- * {@link WifiAwareSession#publish(Handler, PublishConfig, WifiAwareDiscoverySessionCallback)} and
- * {@link WifiAwareSession#subscribe(Handler, SubscribeConfig, WifiAwareDiscoverySessionCallback)}.
+ * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, Handler)} and
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, Handler)}.
* <li>Create a Aware network specifier to be used with
* {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)}
* to set-up a Aware connection with a peer. Refer to
- * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])} and
+ * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, PeerHandle, byte[])} and
* {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])}.
* </ul>
* <p>
@@ -73,7 +73,7 @@
* broadcast. Note that this broadcast is not sticky - you should register for it and then
* check the above API to avoid a race condition.
* <p>
- * An application must use {@link #attach(Handler, WifiAwareAttachCallback)} to initialize a
+ * An application must use {@link #attach(WifiAwareAttachCallback, Handler)} to initialize a
* Aware cluster - before making any other Aware operation. Aware cluster membership is a
* device-wide operation - the API guarantees that the device is in a cluster or joins a
* Aware cluster (or starts one if none can be found). Information about attach success (or
@@ -86,12 +86,11 @@
* application detaches.
* <p>
* Once a Aware attach is confirmed use the
- * {@link WifiAwareSession#publish(Handler, PublishConfig, WifiAwareDiscoverySessionCallback)}
+ * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, Handler)}
* or
- * {@link WifiAwareSession#subscribe(Handler, SubscribeConfig,
- * WifiAwareDiscoverySessionCallback)}
- * to create publish or subscribe Aware discovery sessions. Events are called on the provided
- * callback object {@link WifiAwareDiscoverySessionCallback}. Specifically, the
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
+ * Handler)} to create publish or subscribe Aware discovery sessions. Events are called on the
+ * provided callback object {@link WifiAwareDiscoverySessionCallback}. Specifically, the
* {@link WifiAwareDiscoverySessionCallback#onPublishStarted(WifiAwarePublishDiscoverySession)}
* and
* {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(
@@ -102,7 +101,7 @@
* the session {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} and
* {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can
* also be used to send messages using the
- * {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[])} APIs. When an
+ * {@link WifiAwareDiscoveryBaseSession#sendMessage(PeerHandle, int, byte[])} APIs. When an
* application is finished with a discovery session it <b>must</b> terminate it using the
* {@link WifiAwareDiscoveryBaseSession#destroy()} API.
* <p>
@@ -115,7 +114,7 @@
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <li>{@link NetworkRequest.Builder#setNetworkSpecifier(String)} using
* {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])} or
- * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])}.
+ * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, PeerHandle, byte[])}.
* </ul>
*
* @hide PROPOSED_AWARE_API
@@ -225,7 +224,7 @@
* Connection creation role is that of INITIATOR. Used to create a network specifier string
* when requesting a Aware network.
*
- * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])
+ * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, PeerHandle, byte[])
* @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])
*/
public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0;
@@ -234,7 +233,7 @@
* Connection creation role is that of RESPONDER. Used to create a network specifier string
* when requesting a Aware network.
*
- * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])
+ * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, PeerHandle, byte[])
* @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])
*/
public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1;
@@ -326,13 +325,13 @@
* then this function will simply indicate success immediately using the same {@code
* attachCallback}.
*
+ * @param attachCallback A callback for attach events, extended from
+ * {@link WifiAwareAttachCallback}.
* @param handler The Handler on whose thread to execute the callbacks of the {@code
* attachCallback} object. If a null is provided then the application's main thread will be
* used.
- * @param attachCallback A callback for attach events, extended from
- * {@link WifiAwareAttachCallback}.
*/
- public void attach(@Nullable Handler handler, @NonNull WifiAwareAttachCallback attachCallback) {
+ public void attach(@NonNull WifiAwareAttachCallback attachCallback, @Nullable Handler handler) {
attach(handler, null, attachCallback, null);
}
@@ -352,20 +351,21 @@
* on startup and whenever it is updated (it is randomized at regular intervals for privacy).
* The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
* permission to execute this attach request. Otherwise, use the
- * {@link #attach(Handler, WifiAwareAttachCallback)} version. Note that aside from permission
+ * {@link #attach(WifiAwareAttachCallback, Handler)} version. Note that aside from permission
* requirements this listener will wake up the host at regular intervals causing higher power
* consumption, do not use it unless the information is necessary (e.g. for OOB discovery).
*
- * @param handler The Handler on whose thread to execute the callbacks of the {@code
- * attachCallback} and {@code identityChangedListener} objects. If a null is provided then the
- * application's main thread will be used.
* @param attachCallback A callback for attach events, extended from
* {@link WifiAwareAttachCallback}.
* @param identityChangedListener A listener for changed identity, extended from
* {@link WifiAwareIdentityChangedListener}.
+ * @param handler The Handler on whose thread to execute the callbacks of the {@code
+ * attachCallback} and {@code identityChangedListener} objects. If a null is provided then the
+ * application's main thread will be used.
*/
- public void attach(@Nullable Handler handler, @NonNull WifiAwareAttachCallback attachCallback,
- @NonNull WifiAwareIdentityChangedListener identityChangedListener) {
+ public void attach(@NonNull WifiAwareAttachCallback attachCallback,
+ @NonNull WifiAwareIdentityChangedListener identityChangedListener,
+ @Nullable Handler handler) {
attach(handler, null, attachCallback, identityChangedListener);
}
@@ -481,7 +481,7 @@
}
/** @hide */
- public void sendMessage(int clientId, int sessionId, Object peerHandle, byte[] message,
+ public void sendMessage(int clientId, int sessionId, PeerHandle peerHandle, byte[] message,
int messageId, int retryCount) {
if (peerHandle == null) {
throw new IllegalArgumentException(
@@ -490,13 +490,13 @@
if (VDBG) {
Log.v(TAG, "sendMessage(): clientId=" + clientId + ", sessionId=" + sessionId
- + ", peerHandle=" + ((OpaquePeerHandle) peerHandle).peerId + ", messageId="
+ + ", peerHandle=" + peerHandle.peerId + ", messageId="
+ messageId + ", retryCount=" + retryCount);
}
try {
- mService.sendMessage(clientId, sessionId, ((OpaquePeerHandle) peerHandle).peerId,
- message, messageId, retryCount);
+ mService.sendMessage(clientId, sessionId, peerHandle.peerId, message, messageId,
+ retryCount);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -524,12 +524,12 @@
}
/** @hide */
- public String createNetworkSpecifier(int clientId, int role, int sessionId, Object peerHandle,
- byte[] token) {
+ public String createNetworkSpecifier(int clientId, int role, int sessionId,
+ PeerHandle peerHandle, byte[] token) {
if (VDBG) {
Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId
- + ", peerHandle=" + ((peerHandle == null) ? peerHandle
- : ((OpaquePeerHandle) peerHandle).peerId) + ", token=" + token);
+ + ", peerHandle=" + ((peerHandle == null) ? peerHandle : peerHandle.peerId)
+ + ", token=" + token);
}
int type;
@@ -569,7 +569,7 @@
json.put(NETWORK_SPECIFIER_KEY_CLIENT_ID, clientId);
json.put(NETWORK_SPECIFIER_KEY_SESSION_ID, sessionId);
if (peerHandle != null) {
- json.put(NETWORK_SPECIFIER_KEY_PEER_ID, ((OpaquePeerHandle) peerHandle).peerId);
+ json.put(NETWORK_SPECIFIER_KEY_PEER_ID, peerHandle.peerId);
}
if (token != null) {
json.put(NETWORK_SPECIFIER_KEY_TOKEN,
@@ -876,18 +876,18 @@
break;
case CALLBACK_MATCH:
mOriginalCallback.onServiceDiscovered(
- new OpaquePeerHandle(msg.arg1),
+ new PeerHandle(msg.arg1),
msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE),
msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2));
break;
case CALLBACK_MESSAGE_SEND_SUCCESS:
- mOriginalCallback.onMessageSent(msg.arg1);
+ mOriginalCallback.onMessageSendSucceeded(msg.arg1);
break;
case CALLBACK_MESSAGE_SEND_FAIL:
mOriginalCallback.onMessageSendFailed(msg.arg1);
break;
case CALLBACK_MESSAGE_RECEIVED:
- mOriginalCallback.onMessageReceived(new OpaquePeerHandle(msg.arg1),
+ mOriginalCallback.onMessageReceived(new PeerHandle(msg.arg1),
(byte[]) msg.obj);
break;
}
@@ -1019,12 +1019,14 @@
}
}
- /** @hide */
- public static class OpaquePeerHandle {
- public OpaquePeerHandle(int peerId) {
+ /** @hide PROPOSED_AWARE_API */
+ public static class PeerHandle {
+ /** @hide */
+ public PeerHandle(int peerId) {
this.peerId = peerId;
}
+ /** @hide */
public int peerId;
}
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java b/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java
index 610a92c..68786d1 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java
@@ -21,9 +21,8 @@
/**
* A class representing a Aware publish session. Created when
- * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
- * WifiAwareDiscoverySessionCallback)}
- * is called and a discovery session is created and returned in
+ * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
+ * android.os.Handler)} is called and a discovery session is created and returned in
* {@link WifiAwareDiscoverySessionCallback#onPublishStarted(WifiAwarePublishDiscoverySession)}. See
* baseline functionality of all discovery sessions in {@link WifiAwareDiscoveryBaseSession}. This
* object allows updating an existing/running publish discovery session using
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
index 357bd43..acb60a4 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -65,7 +65,7 @@
* session-wide destroy.
* <p>
* An application may re-attach after a destroy using
- * {@link WifiAwareManager#attach(Handler, WifiAwareAttachCallback)} .
+ * {@link WifiAwareManager#attach(WifiAwareAttachCallback, Handler)} .
*/
public void destroy() {
WifiAwareManager mgr = mMgr.get();
@@ -116,15 +116,15 @@
* <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
* permission to start a publish discovery session.
*
- * @param handler The Handler on whose thread to execute the callbacks of the {@code
- * callback} object. If a null is provided then the application's main thread will be used.
* @param publishConfig The {@link PublishConfig} specifying the
* configuration of the requested publish session.
* @param callback A {@link WifiAwareDiscoverySessionCallback} derived object to be used for
* session event callbacks.
+ * @param handler The Handler on whose thread to execute the callbacks of the {@code
+ * callback} object. If a null is provided then the application's main thread will be used.
*/
- public void publish(@Nullable Handler handler, @NonNull PublishConfig publishConfig,
- @NonNull WifiAwareDiscoverySessionCallback callback) {
+ public void publish(@NonNull PublishConfig publishConfig,
+ @NonNull WifiAwareDiscoverySessionCallback callback, @Nullable Handler handler) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "publish: called post GC on WifiAwareManager");
@@ -162,15 +162,15 @@
* <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
* permission to start a subscribe discovery session.
*
- * @param handler The Handler on whose thread to execute the callbacks of the {@code
- * callback} object. If a null is provided then the application's main thread will be used.
* @param subscribeConfig The {@link SubscribeConfig} specifying the
* configuration of the requested subscribe session.
* @param callback A {@link WifiAwareDiscoverySessionCallback} derived object to be used for
* session event callbacks.
+ * @param handler The Handler on whose thread to execute the callbacks of the {@code
+ * callback} object. If a null is provided then the application's main thread will be used.
*/
- public void subscribe(@Nullable Handler handler, @NonNull SubscribeConfig subscribeConfig,
- @NonNull WifiAwareDiscoverySessionCallback callback) {
+ public void subscribe(@NonNull SubscribeConfig subscribeConfig,
+ @NonNull WifiAwareDiscoverySessionCallback callback, @Nullable Handler handler) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "publish: called post GC on WifiAwareManager");
@@ -193,7 +193,8 @@
* This API is targeted for applications which can obtain the peer MAC address using OOB
* (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer -
* when using Aware discovery use the alternative network specifier method -
- * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])}.
+ * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int,
+ * WifiAwareManager.PeerHandle, byte[])}.
*
* @param role The role of this device:
* {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java b/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java
index 7c48f54..a0ec809 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java
@@ -21,8 +21,8 @@
/**
* A class representing a Aware subscribe session. Created when
- * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
- * WifiAwareDiscoverySessionCallback)}
+ * {@link WifiAwareSession#subscribe(SubscribeConfig,
+ * WifiAwareDiscoverySessionCallback, android.os.Handler)}
* is called and a discovery session is created and returned in
* {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(WifiAwareSubscribeDiscoverySession)}.
* See baseline functionality of all discovery sessions in {@link WifiAwareDiscoveryBaseSession}.
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index a62a0fb..643753a 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -36,6 +36,27 @@
public HomeSP homeSp = null;
public Credential credential = null;
+ /**
+ * Constructor for creating PasspointConfiguration with default values.
+ */
+ public PasspointConfiguration() {}
+
+ /**
+ * Copy constructor.
+ *
+ * @param source The source to copy from
+ */
+ public PasspointConfiguration(PasspointConfiguration source) {
+ if (source != null) {
+ if (source.homeSp != null) {
+ homeSp = new HomeSP(source.homeSp);
+ }
+ if (source.credential != null) {
+ credential = new Credential(source.credential);
+ }
+ }
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index 57e65eb..790dfaf 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -109,6 +109,25 @@
*/
public String nonEapInnerMethod = null;
+ /**
+ * Constructor for creating UserCredential with default values.
+ */
+ public UserCredential() {}
+
+ /**
+ * Copy constructor.
+ *
+ * @param source The source to copy from
+ */
+ public UserCredential(UserCredential source) {
+ if (source != null) {
+ username = source.username;
+ password = source.password;
+ eapType = source.eapType;
+ nonEapInnerMethod = source.nonEapInnerMethod;
+ }
+ }
+
@Override
public int describeContents() {
return 0;
@@ -221,6 +240,26 @@
*/
public byte[] certSha256FingerPrint = null;
+ /**
+ * Constructor for creating CertificateCredential with default values.
+ */
+ public CertificateCredential() {}
+
+ /**
+ * Copy constructor.
+ *
+ * @param source The source to copy from
+ */
+ public CertificateCredential(CertificateCredential source) {
+ if (source != null) {
+ certType = source.certType;
+ if (source.certSha256FingerPrint != null) {
+ certSha256FingerPrint = Arrays.copyOf(source.certSha256FingerPrint,
+ source.certSha256FingerPrint.length);
+ }
+ }
+ }
+
@Override
public int describeContents() {
return 0;
@@ -307,6 +346,23 @@
*/
public int eapType = Integer.MIN_VALUE;
+ /**
+ * Constructor for creating SimCredential with default values.
+ */
+ public SimCredential() {}
+
+ /**
+ * Copy constructor
+ *
+ * @param source The source to copy from
+ */
+ public SimCredential(SimCredential source) {
+ if (source != null) {
+ imsi = source.imsi;
+ eapType = source.eapType;
+ }
+ }
+
@Override
public int describeContents() {
return 0;
@@ -422,6 +478,37 @@
*/
public PrivateKey clientPrivateKey = null;
+ /**
+ * Constructor for creating Credential with default values.
+ */
+ public Credential() {}
+
+ /**
+ * Copy constructor.
+ *
+ * @param source The source to copy from
+ */
+ public Credential(Credential source) {
+ if (source != null) {
+ realm = source.realm;
+ if (source.userCredential != null) {
+ userCredential = new UserCredential(source.userCredential);
+ }
+ if (source.certCredential != null) {
+ certCredential = new CertificateCredential(source.certCredential);
+ }
+ if (source.simCredential != null) {
+ simCredential = new SimCredential(source.simCredential);
+ }
+ if (source.clientCertificateChain != null) {
+ clientCertificateChain = Arrays.copyOf(source.clientCertificateChain,
+ source.clientCertificateChain.length);
+ }
+ caCertificate = source.caCertificate;
+ clientPrivateKey = source.clientPrivateKey;
+ }
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java
index 5837c06..d4a5792 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java
@@ -53,6 +53,27 @@
*/
public long[] roamingConsortiumOIs = null;
+ /**
+ * Constructor for creating HomeSP with default values.
+ */
+ public HomeSP() {}
+
+ /**
+ * Copy constructor.
+ *
+ * @param source The source to copy from
+ */
+ public HomeSP(HomeSP source) {
+ if (source != null) {
+ fqdn = source.fqdn;
+ friendlyName = source.friendlyName;
+ if (source.roamingConsortiumOIs != null) {
+ roamingConsortiumOIs = Arrays.copyOf(source.roamingConsortiumOIs,
+ source.roamingConsortiumOIs.length);
+ }
+ }
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java b/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java
new file mode 100644
index 0000000..4b6957b
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java
@@ -0,0 +1,225 @@
+/*
+ * 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 android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ErrorCollector;
+
+/**
+ * Unit test harness for TlvBufferUtils class.
+ */
+@SmallTest
+public class TlvBufferUtilsTest {
+ @Rule
+ public ErrorCollector collector = new ErrorCollector();
+
+ /*
+ * TlvBufferUtils Tests
+ */
+
+ @Test
+ public void testTlvBuild() {
+ TlvBufferUtils.TlvConstructor tlv11 = new TlvBufferUtils.TlvConstructor(1, 1);
+ tlv11.allocate(15);
+ tlv11.putByte(0, (byte) 2);
+ tlv11.putByteArray(2, new byte[] {
+ 0, 1, 2 });
+
+ collector.checkThat("tlv11-correct-construction",
+ tlv11.getArray(), equalTo(new byte[]{0, 1, 2, 2, 3, 0, 1, 2}));
+
+ LvBufferUtils.LvConstructor tlv01 = new LvBufferUtils.LvConstructor(1);
+ tlv01.allocate(15);
+ tlv01.putByte((byte) 2);
+ tlv01.putByteArray(2, new byte[] {
+ 0, 1, 2 });
+
+ collector.checkThat("tlv01-correct-construction",
+ tlv01.getArray(), equalTo(new byte[] {1, 2, 3, 0, 1, 2 }));
+
+ collector.checkThat("tlv11-valid",
+ TlvBufferUtils.isValid(tlv11.getArray(), 1, 1),
+ equalTo(true));
+ collector.checkThat("tlv01-valid",
+ LvBufferUtils.isValid(tlv01.getArray(), 1),
+ equalTo(true));
+ }
+
+ @Test
+ public void testTlvIterate() {
+ final String ascii = "ABC";
+ final String nonAscii = "何かもっと複雑な";
+
+ TlvBufferUtils.TlvConstructor tlv22 = new TlvBufferUtils.TlvConstructor(2, 2);
+ tlv22.allocate(18);
+ tlv22.putInt(0, 2);
+ tlv22.putShort(2, (short) 3);
+ tlv22.putZeroLengthElement(55);
+
+ TlvBufferUtils.TlvIterable tlv22It = new TlvBufferUtils.TlvIterable(2, 2, tlv22.getArray());
+ int count = 0;
+ for (TlvBufferUtils.TlvElement tlv : tlv22It) {
+ if (count == 0) {
+ collector.checkThat("tlv22-correct-iteration-mType", tlv.type, equalTo(0));
+ collector.checkThat("tlv22-correct-iteration-mLength", tlv.length, equalTo(4));
+ collector.checkThat("tlv22-correct-iteration-DATA", tlv.getInt(), equalTo(2));
+ } else if (count == 1) {
+ collector.checkThat("tlv22-correct-iteration-mType", tlv.type, equalTo(2));
+ collector.checkThat("tlv22-correct-iteration-mLength", tlv.length, equalTo(2));
+ collector.checkThat("tlv22-correct-iteration-DATA", (int) tlv.getShort(),
+ equalTo(3));
+ } else if (count == 2) {
+ collector.checkThat("tlv22-correct-iteration-mType", tlv.type, equalTo(55));
+ collector.checkThat("tlv22-correct-iteration-mLength", tlv.length, equalTo(0));
+ } else {
+ collector.checkThat("Invalid number of iterations in loop - tlv22", true,
+ equalTo(false));
+ }
+ ++count;
+ }
+ if (count != 3) {
+ collector.checkThat("Invalid number of iterations outside loop - tlv22", true,
+ equalTo(false));
+ }
+
+ TlvBufferUtils.TlvConstructor tlv02 = new TlvBufferUtils.TlvConstructor(0, 2);
+ tlv02.allocate(100);
+ tlv02.putByte(0, (byte) 2);
+ tlv02.putString(0, ascii);
+ tlv02.putString(0, nonAscii);
+
+ TlvBufferUtils.TlvIterable tlv02It = new TlvBufferUtils.TlvIterable(0, 2, tlv02.getArray());
+ count = 0;
+ for (TlvBufferUtils.TlvElement tlv : tlv02It) {
+ if (count == 0) {
+ collector.checkThat("tlv02-correct-iteration-mLength", tlv.length, equalTo(1));
+ collector.checkThat("tlv02-correct-iteration-DATA", (int) tlv.getByte(),
+ equalTo(2));
+ } else if (count == 1) {
+ collector.checkThat("tlv02-correct-iteration-mLength", tlv.length,
+ equalTo(ascii.length()));
+ collector.checkThat("tlv02-correct-iteration-DATA", tlv.getString().equals(ascii),
+ equalTo(true));
+ } else if (count == 2) {
+ collector.checkThat("tlv02-correct-iteration-mLength", tlv.length,
+ equalTo(nonAscii.getBytes().length));
+ collector.checkThat("tlv02-correct-iteration-DATA",
+ tlv.getString().equals(nonAscii), equalTo(true));
+ } else {
+ collector.checkThat("Invalid number of iterations in loop - tlv02", true,
+ equalTo(false));
+ }
+ ++count;
+ }
+ collector.checkThat("Invalid number of iterations outside loop - tlv02", count,
+ equalTo(3));
+
+ collector.checkThat("tlv22-valid",
+ TlvBufferUtils.isValid(tlv22.getArray(), 2, 2),
+ equalTo(true));
+ collector.checkThat("tlv02-valid",
+ LvBufferUtils.isValid(tlv02.getArray(), 2),
+ equalTo(true));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testTlvInvalidSizeT1L0() {
+ TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(1, 0);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testTlvInvalidSizeTm3L2() {
+ TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(-3, 2);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testTlvInvalidSizeT1Lm2() {
+ TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(1, -2);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testTlvInvalidSizeT1L3() {
+ TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(1, 3);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testTlvInvalidSizeT3L1() {
+ TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(3, 1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testTlvItInvalidSizeT1L0() {
+ final byte[] dummy = {
+ 0, 1, 2 };
+ final int dummyLength = 3;
+ TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, 0, dummy);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testTlvItInvalidSizeTm3L2() {
+ final byte[] dummy = {
+ 0, 1, 2 };
+ final int dummyLength = 3;
+ TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(-3, 2, dummy);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testTlvItInvalidSizeT1Lm2() {
+ final byte[] dummy = {
+ 0, 1, 2 };
+ final int dummyLength = 3;
+ TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, -2, dummy);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testTlvItInvalidSizeT1L3() {
+ final byte[] dummy = {
+ 0, 1, 2 };
+ final int dummyLength = 3;
+ TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, 3, dummy);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testTlvItInvalidSizeT3L1() {
+ final byte[] dummy = {
+ 0, 1, 2 };
+ final int dummyLength = 3;
+ TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(3, 1, dummy);
+ }
+
+ /**
+ * Validate that a malformed byte array fails the TLV validity test.
+ */
+ @Test
+ public void testTlvInvalidByteArray() {
+ LvBufferUtils.LvConstructor tlv01 = new LvBufferUtils.LvConstructor(1);
+ tlv01.allocate(15);
+ tlv01.putByte((byte) 2);
+ tlv01.putByteArray(2, new byte[]{0, 1, 2});
+
+ byte[] array = tlv01.getArray();
+ array[0] = 10;
+
+ collector.checkThat("tlv01-invalid",
+ LvBufferUtils.isValid(array, 1), equalTo(false));
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
new file mode 100644
index 0000000..b30ecf7
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -0,0 +1,1054 @@
+/*
+ * 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 static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.wifi.RttManager;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.test.TestLooper;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Base64;
+
+import libcore.util.HexEncoding;
+
+import org.json.JSONObject;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ErrorCollector;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit test harness for WifiAwareManager class.
+ */
+@SmallTest
+public class WifiAwareManagerTest {
+ private WifiAwareManager mDut;
+ private TestLooper mMockLooper;
+ private Handler mMockLooperHandler;
+
+ @Rule
+ public ErrorCollector collector = new ErrorCollector();
+
+ @Mock
+ public Context mockContext;
+
+ @Mock
+ public WifiAwareAttachCallback mockCallback;
+
+ @Mock
+ public WifiAwareDiscoverySessionCallback mockSessionCallback;
+
+ @Mock
+ public IWifiAwareManager mockAwareService;
+
+ @Mock
+ public WifiAwarePublishDiscoverySession mockPublishSession;
+
+ @Mock
+ public WifiAwareSubscribeDiscoverySession mockSubscribeSession;
+
+ @Mock
+ public RttManager.RttListener mockRttListener;
+
+ private static final int AWARE_STATUS_ERROR = -1;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mDut = new WifiAwareManager(mockContext, mockAwareService);
+ mMockLooper = new TestLooper();
+ mMockLooperHandler = new Handler(mMockLooper.getLooper());
+ }
+
+ /*
+ * Straight pass-through tests
+ */
+
+ /**
+ * Validate pass-through of enableUsage() API.
+ */
+ @Test
+ public void testEnableUsage() throws Exception {
+ mDut.enableUsage();
+
+ verify(mockAwareService).enableUsage();
+ }
+
+ /**
+ * Validate pass-through of disableUsage() API.
+ */
+ @Test
+ public void testDisableUsage() throws Exception {
+ mDut.disableUsage();
+
+ verify(mockAwareService).disableUsage();
+ }
+
+ /**
+ * Validate pass-through of isUsageEnabled() API.
+ */
+ @Test
+ public void testIsUsageEnable() throws Exception {
+ mDut.isAvailable();
+
+ verify(mockAwareService).isUsageEnabled();
+ }
+
+ /**
+ * Validate pass-through of getCharacteristics() API.
+ */
+ @Test
+ public void testGetCharacteristics() throws Exception {
+ mDut.getCharacteristics();
+
+ verify(mockAwareService).getCharacteristics();
+ }
+
+ /*
+ * WifiAwareEventCallbackProxy Tests
+ */
+
+ /**
+ * Validate the successful connect flow: (1) connect + success (2) publish, (3) disconnect
+ * (4) try publishing on old session (5) connect again
+ */
+ @Test
+ public void testConnectFlow() throws Exception {
+ final int clientId = 4565;
+
+ InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService);
+ ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareEventCallback.class);
+ ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
+ WifiAwareSession.class);
+ ArgumentCaptor<IBinder> binder = ArgumentCaptor.forClass(IBinder.class);
+
+ // (1) connect + success
+ mDut.attach(mockCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).connect(binder.capture(), anyString(),
+ clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+ clientProxyCallback.getValue().onConnectSuccess(clientId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
+ WifiAwareSession session = sessionCaptor.getValue();
+
+ // (2) publish - should succeed
+ PublishConfig publishConfig = new PublishConfig.Builder().build();
+ session.publish(publishConfig, mockSessionCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
+ any(IWifiAwareDiscoverySessionCallback.class));
+
+ // (3) disconnect
+ session.destroy();
+ inOrder.verify(mockAwareService).disconnect(eq(clientId), eq(binder.getValue()));
+
+ // (4) try publishing again - fails silently
+ session.publish(new PublishConfig.Builder().build(), mockSessionCallback,
+ mMockLooperHandler);
+
+ // (5) connect
+ mDut.attach(mockCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).connect(binder.capture(), anyString(),
+ any(IWifiAwareEventCallback.class), (ConfigRequest) isNull(), eq(false));
+
+ verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService);
+ }
+
+ /**
+ * Validate the failed connect flow: (1) connect + failure, (2) connect + success (3) subscribe
+ */
+ @Test
+ public void testConnectFailure() throws Exception {
+ final int clientId = 4565;
+ final int reason = AWARE_STATUS_ERROR;
+
+ InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService);
+ ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
+ WifiAwareSession.class);
+ ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareEventCallback.class);
+
+ // (1) connect + failure
+ mDut.attach(mockCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
+ clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+ clientProxyCallback.getValue().onConnectFail(reason);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onAttachFailed();
+
+ // (2) connect + success
+ mDut.attach(mockCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
+ clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+ clientProxyCallback.getValue().onConnectSuccess(clientId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
+ WifiAwareSession session = sessionCaptor.getValue();
+
+ // (4) subscribe: should succeed
+ SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
+ session.subscribe(subscribeConfig, mockSessionCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig),
+ any(IWifiAwareDiscoverySessionCallback.class));
+
+ verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService);
+ }
+
+ /**
+ * Validate that can call connect to create multiple sessions: (1) connect
+ * + success, (2) try connect again
+ */
+ @Test
+ public void testInvalidConnectSequence() throws Exception {
+ final int clientId = 4565;
+
+ InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService);
+ ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareEventCallback.class);
+
+ // (1) connect + success
+ mDut.attach(mockCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
+ clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+ clientProxyCallback.getValue().onConnectSuccess(clientId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onAttached(any(WifiAwareSession.class));
+
+ // (2) connect + success
+ mDut.attach(mockCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
+ clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+ clientProxyCallback.getValue().onConnectSuccess(clientId + 1);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onAttached(any(WifiAwareSession.class));
+
+ verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService);
+ }
+
+ /*
+ * WifiAwareDiscoverySessionCallbackProxy Tests
+ */
+
+ /**
+ * Validate the publish flow: (0) connect + success, (1) publish, (2)
+ * success creates session, (3) pass through everything, (4) update publish
+ * through session, (5) terminate locally, (6) try another command -
+ * ignored.
+ */
+ @Test
+ public void testPublishFlow() throws Exception {
+ final int clientId = 4565;
+ final int sessionId = 123;
+ final ConfigRequest configRequest = new ConfigRequest.Builder().build();
+ final PublishConfig publishConfig = new PublishConfig.Builder().build();
+ final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(873);
+ final String string1 = "hey from here...";
+ final String string2 = "some other arbitrary string...";
+ final int messageId = 2123;
+ final int reason = AWARE_STATUS_ERROR;
+
+ InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
+ mockPublishSession);
+ ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
+ WifiAwareSession.class);
+ ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareEventCallback.class);
+ ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareDiscoverySessionCallback.class);
+ ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor
+ .forClass(WifiAwarePublishDiscoverySession.class);
+ ArgumentCaptor<WifiAwareManager.PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(
+ WifiAwareManager.PeerHandle.class);
+
+ // (0) connect + success
+ mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
+ inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
+ clientProxyCallback.capture(), eq(configRequest), eq(false));
+ clientProxyCallback.getValue().onConnectSuccess(clientId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
+ WifiAwareSession session = sessionCaptor.getValue();
+
+ // (1) publish
+ session.publish(publishConfig, mockSessionCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
+ sessionProxyCallback.capture());
+
+ // (2) publish session created
+ sessionProxyCallback.getValue().onSessionStarted(sessionId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
+
+ // (3) ...
+ publishSession.getValue().sendMessage(peerHandle, messageId, string1.getBytes());
+ sessionProxyCallback.getValue().onMatch(peerHandle.peerId, string1.getBytes(),
+ string2.getBytes());
+ sessionProxyCallback.getValue().onMessageReceived(peerHandle.peerId, string1.getBytes());
+ sessionProxyCallback.getValue().onMessageSendFail(messageId, reason);
+ sessionProxyCallback.getValue().onMessageSendSuccess(messageId);
+ mMockLooper.dispatchAll();
+
+ inOrder.verify(mockAwareService).sendMessage(eq(clientId), eq(sessionId),
+ eq(peerHandle.peerId), eq(string1.getBytes()), eq(messageId), eq(0));
+ inOrder.verify(mockSessionCallback).onServiceDiscovered(peerIdCaptor.capture(),
+ eq(string1.getBytes()), eq(string2.getBytes()));
+ assertEquals(((WifiAwareManager.PeerHandle) peerIdCaptor.getValue()).peerId,
+ peerHandle.peerId);
+ inOrder.verify(mockSessionCallback).onMessageReceived(peerIdCaptor.capture(),
+ eq(string1.getBytes()));
+ assertEquals(((WifiAwareManager.PeerHandle) peerIdCaptor.getValue()).peerId,
+ peerHandle.peerId);
+ inOrder.verify(mockSessionCallback).onMessageSendFailed(eq(messageId));
+ inOrder.verify(mockSessionCallback).onMessageSendSucceeded(eq(messageId));
+
+ // (4) update publish
+ publishSession.getValue().updatePublish(publishConfig);
+ sessionProxyCallback.getValue().onSessionConfigFail(reason);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockAwareService).updatePublish(eq(clientId), eq(sessionId),
+ eq(publishConfig));
+ inOrder.verify(mockSessionCallback).onSessionConfigFailed();
+
+ // (5) terminate
+ publishSession.getValue().destroy();
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockAwareService).terminateSession(clientId, sessionId);
+
+ // (6) try an update (nothing)
+ publishSession.getValue().updatePublish(publishConfig);
+ mMockLooper.dispatchAll();
+
+ verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
+ mockPublishSession);
+ }
+
+ /**
+ * Validate race condition of session terminate and session action: (1)
+ * connect, (2) publish success + terminate, (3) update.
+ */
+ @Test
+ public void testPublishRemoteTerminate() throws Exception {
+ final int clientId = 4565;
+ final int sessionId = 123;
+ final ConfigRequest configRequest = new ConfigRequest.Builder().build();
+ final PublishConfig publishConfig = new PublishConfig.Builder().build();
+ final int reason = WifiAwareDiscoverySessionCallback.TERMINATE_REASON_DONE;
+
+ InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
+ mockPublishSession);
+ ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
+ WifiAwareSession.class);
+ ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareEventCallback.class);
+ ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareDiscoverySessionCallback.class);
+ ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor
+ .forClass(WifiAwarePublishDiscoverySession.class);
+
+ // (1) connect successfully
+ mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
+ inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
+ clientProxyCallback.capture(), eq(configRequest), eq(false));
+ clientProxyCallback.getValue().onConnectSuccess(clientId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
+ WifiAwareSession session = sessionCaptor.getValue();
+
+ // (2) publish: successfully - then terminated
+ session.publish(publishConfig, mockSessionCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
+ sessionProxyCallback.capture());
+ sessionProxyCallback.getValue().onSessionStarted(sessionId);
+ sessionProxyCallback.getValue().onSessionTerminated(reason);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
+ inOrder.verify(mockSessionCallback).onSessionTerminated(reason);
+
+ // (3) failure when trying to update: NOP
+ publishSession.getValue().updatePublish(publishConfig);
+
+ verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
+ mockPublishSession);
+ }
+
+ /**
+ * Validate the subscribe flow: (0) connect + success, (1) subscribe, (2)
+ * success creates session, (3) pass through everything, (4) update
+ * subscribe through session, (5) terminate locally, (6) try another command
+ * - ignored.
+ */
+ @Test
+ public void testSubscribeFlow() throws Exception {
+ final int clientId = 4565;
+ final int sessionId = 123;
+ final ConfigRequest configRequest = new ConfigRequest.Builder().build();
+ final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
+ final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(873);
+ final String string1 = "hey from here...";
+ final String string2 = "some other arbitrary string...";
+ final int messageId = 2123;
+ final int reason = AWARE_STATUS_ERROR;
+
+ InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
+ mockSubscribeSession);
+ ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
+ WifiAwareSession.class);
+ ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareEventCallback.class);
+ ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareDiscoverySessionCallback.class);
+ ArgumentCaptor<WifiAwareSubscribeDiscoverySession> subscribeSession = ArgumentCaptor
+ .forClass(WifiAwareSubscribeDiscoverySession.class);
+ ArgumentCaptor<WifiAwareManager.PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(
+ WifiAwareManager.PeerHandle.class);
+
+ // (0) connect + success
+ mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
+ inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
+ clientProxyCallback.capture(), eq(configRequest), eq(false));
+ clientProxyCallback.getValue().onConnectSuccess(clientId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
+ WifiAwareSession session = sessionCaptor.getValue();
+
+ // (1) subscribe
+ session.subscribe(subscribeConfig, mockSessionCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig),
+ sessionProxyCallback.capture());
+
+ // (2) subscribe session created
+ sessionProxyCallback.getValue().onSessionStarted(sessionId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onSubscribeStarted(subscribeSession.capture());
+
+ // (3) ...
+ subscribeSession.getValue().sendMessage(peerHandle, messageId, string1.getBytes());
+ sessionProxyCallback.getValue().onMatch(peerHandle.peerId, string1.getBytes(),
+ string2.getBytes());
+ sessionProxyCallback.getValue().onMessageReceived(peerHandle.peerId, string1.getBytes());
+ sessionProxyCallback.getValue().onMessageSendFail(messageId, reason);
+ sessionProxyCallback.getValue().onMessageSendSuccess(messageId);
+ mMockLooper.dispatchAll();
+
+ inOrder.verify(mockAwareService).sendMessage(eq(clientId), eq(sessionId),
+ eq(peerHandle.peerId), eq(string1.getBytes()), eq(messageId), eq(0));
+ inOrder.verify(mockSessionCallback).onServiceDiscovered(peerIdCaptor.capture(),
+ eq(string1.getBytes()), eq(string2.getBytes()));
+ assertEquals(((WifiAwareManager.PeerHandle) peerIdCaptor.getValue()).peerId,
+ peerHandle.peerId);
+ inOrder.verify(mockSessionCallback).onMessageReceived(peerIdCaptor.capture(),
+ eq(string1.getBytes()));
+ assertEquals(((WifiAwareManager.PeerHandle) peerIdCaptor.getValue()).peerId,
+ peerHandle.peerId);
+ inOrder.verify(mockSessionCallback).onMessageSendFailed(eq(messageId));
+ inOrder.verify(mockSessionCallback).onMessageSendSucceeded(eq(messageId));
+
+ // (4) update subscribe
+ subscribeSession.getValue().updateSubscribe(subscribeConfig);
+ sessionProxyCallback.getValue().onSessionConfigFail(reason);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockAwareService).updateSubscribe(eq(clientId), eq(sessionId),
+ eq(subscribeConfig));
+ inOrder.verify(mockSessionCallback).onSessionConfigFailed();
+
+ // (5) terminate
+ subscribeSession.getValue().destroy();
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockAwareService).terminateSession(clientId, sessionId);
+
+ // (6) try an update (nothing)
+ subscribeSession.getValue().updateSubscribe(subscribeConfig);
+ mMockLooper.dispatchAll();
+
+ verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
+ mockSubscribeSession);
+ }
+
+ /**
+ * Validate race condition of session terminate and session action: (1)
+ * connect, (2) subscribe success + terminate, (3) update.
+ */
+ @Test
+ public void testSubscribeRemoteTerminate() throws Exception {
+ final int clientId = 4565;
+ final int sessionId = 123;
+ final ConfigRequest configRequest = new ConfigRequest.Builder().build();
+ final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
+ final int reason = WifiAwareDiscoverySessionCallback.TERMINATE_REASON_DONE;
+
+ InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
+ mockSubscribeSession);
+ ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
+ WifiAwareSession.class);
+ ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareEventCallback.class);
+ ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareDiscoverySessionCallback.class);
+ ArgumentCaptor<WifiAwareSubscribeDiscoverySession> subscribeSession = ArgumentCaptor
+ .forClass(WifiAwareSubscribeDiscoverySession.class);
+
+ // (1) connect successfully
+ mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
+ inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
+ clientProxyCallback.capture(), eq(configRequest), eq(false));
+ clientProxyCallback.getValue().onConnectSuccess(clientId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
+ WifiAwareSession session = sessionCaptor.getValue();
+
+ // (2) subscribe: successfully - then terminated
+ session.subscribe(subscribeConfig, mockSessionCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig),
+ sessionProxyCallback.capture());
+ sessionProxyCallback.getValue().onSessionStarted(sessionId);
+ sessionProxyCallback.getValue().onSessionTerminated(reason);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onSubscribeStarted(subscribeSession.capture());
+ inOrder.verify(mockSessionCallback).onSessionTerminated(reason);
+
+ // (3) failure when trying to update: NOP
+ subscribeSession.getValue().updateSubscribe(subscribeConfig);
+
+ verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
+ mockSubscribeSession);
+ }
+
+ /*
+ * ConfigRequest Tests
+ */
+
+ @Test
+ public void testConfigRequestBuilderDefaults() {
+ ConfigRequest configRequest = new ConfigRequest.Builder().build();
+
+ collector.checkThat("mClusterHigh", ConfigRequest.CLUSTER_ID_MAX,
+ equalTo(configRequest.mClusterHigh));
+ collector.checkThat("mClusterLow", ConfigRequest.CLUSTER_ID_MIN,
+ equalTo(configRequest.mClusterLow));
+ collector.checkThat("mMasterPreference", 0,
+ equalTo(configRequest.mMasterPreference));
+ collector.checkThat("mSupport5gBand", false, equalTo(configRequest.mSupport5gBand));
+ }
+
+ @Test
+ public void testConfigRequestBuilder() {
+ final int clusterHigh = 100;
+ final int clusterLow = 5;
+ final int masterPreference = 55;
+ final boolean supportBand5g = true;
+
+ ConfigRequest configRequest = new ConfigRequest.Builder().setClusterHigh(clusterHigh)
+ .setClusterLow(clusterLow).setMasterPreference(masterPreference)
+ .setSupport5gBand(supportBand5g)
+ .build();
+
+ collector.checkThat("mClusterHigh", clusterHigh, equalTo(configRequest.mClusterHigh));
+ collector.checkThat("mClusterLow", clusterLow, equalTo(configRequest.mClusterLow));
+ collector.checkThat("mMasterPreference", masterPreference,
+ equalTo(configRequest.mMasterPreference));
+ collector.checkThat("mSupport5gBand", supportBand5g, equalTo(configRequest.mSupport5gBand));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testConfigRequestBuilderMasterPrefNegative() {
+ ConfigRequest.Builder builder = new ConfigRequest.Builder();
+ builder.setMasterPreference(-1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testConfigRequestBuilderMasterPrefReserved1() {
+ new ConfigRequest.Builder().setMasterPreference(1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testConfigRequestBuilderMasterPrefReserved255() {
+ new ConfigRequest.Builder().setMasterPreference(255);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testConfigRequestBuilderMasterPrefTooLarge() {
+ new ConfigRequest.Builder().setMasterPreference(256);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testConfigRequestBuilderClusterLowNegative() {
+ new ConfigRequest.Builder().setClusterLow(-1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testConfigRequestBuilderClusterHighNegative() {
+ new ConfigRequest.Builder().setClusterHigh(-1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testConfigRequestBuilderClusterLowAboveMax() {
+ new ConfigRequest.Builder().setClusterLow(ConfigRequest.CLUSTER_ID_MAX + 1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testConfigRequestBuilderClusterHighAboveMax() {
+ new ConfigRequest.Builder().setClusterHigh(ConfigRequest.CLUSTER_ID_MAX + 1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testConfigRequestBuilderClusterLowLargerThanHigh() {
+ new ConfigRequest.Builder().setClusterLow(100).setClusterHigh(5).build();
+ }
+
+ @Test
+ public void testConfigRequestParcel() {
+ final int clusterHigh = 189;
+ final int clusterLow = 25;
+ final int masterPreference = 177;
+ final boolean supportBand5g = true;
+
+ ConfigRequest configRequest = new ConfigRequest.Builder().setClusterHigh(clusterHigh)
+ .setClusterLow(clusterLow).setMasterPreference(masterPreference)
+ .setSupport5gBand(supportBand5g)
+ .build();
+
+ Parcel parcelW = Parcel.obtain();
+ configRequest.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ ConfigRequest rereadConfigRequest = ConfigRequest.CREATOR.createFromParcel(parcelR);
+
+ assertEquals(configRequest, rereadConfigRequest);
+ }
+
+ /*
+ * SubscribeConfig Tests
+ */
+
+ @Test
+ public void testSubscribeConfigBuilderDefaults() {
+ SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
+
+ collector.checkThat("mServiceName", subscribeConfig.mServiceName, equalTo(null));
+ collector.checkThat("mSubscribeType", subscribeConfig.mSubscribeType,
+ equalTo(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE));
+ collector.checkThat("mSubscribeCount", subscribeConfig.mSubscribeCount, equalTo(0));
+ collector.checkThat("mTtlSec", subscribeConfig.mTtlSec, equalTo(0));
+ collector.checkThat("mMatchStyle", subscribeConfig.mMatchStyle,
+ equalTo(SubscribeConfig.MATCH_STYLE_ALL));
+ collector.checkThat("mEnableTerminateNotification",
+ subscribeConfig.mEnableTerminateNotification, equalTo(true));
+ }
+
+ @Test
+ public void testSubscribeConfigBuilder() {
+ final String serviceName = "some_service_or_other";
+ final String serviceSpecificInfo = "long arbitrary string with some info";
+ final byte[] matchFilter = {
+ 0, 1, 16, 1, 22 };
+ final int subscribeType = SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE;
+ final int subscribeCount = 10;
+ final int subscribeTtl = 15;
+ final int matchStyle = SubscribeConfig.MATCH_STYLE_FIRST_ONLY;
+ final boolean enableTerminateNotification = false;
+
+ SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName)
+ .setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(matchFilter)
+ .setSubscribeType(subscribeType)
+ .setSubscribeCount(subscribeCount).setTtlSec(subscribeTtl).setMatchStyle(matchStyle)
+ .setTerminateNotificationEnabled(enableTerminateNotification).build();
+
+ collector.checkThat("mServiceName", serviceName.getBytes(),
+ equalTo(subscribeConfig.mServiceName));
+ collector.checkThat("mServiceSpecificInfo",
+ serviceSpecificInfo.getBytes(), equalTo(subscribeConfig.mServiceSpecificInfo));
+ collector.checkThat("mMatchFilter", matchFilter, equalTo(subscribeConfig.mMatchFilter));
+ collector.checkThat("mSubscribeType", subscribeType,
+ equalTo(subscribeConfig.mSubscribeType));
+ collector.checkThat("mSubscribeCount", subscribeCount,
+ equalTo(subscribeConfig.mSubscribeCount));
+ collector.checkThat("mTtlSec", subscribeTtl, equalTo(subscribeConfig.mTtlSec));
+ collector.checkThat("mMatchStyle", matchStyle, equalTo(subscribeConfig.mMatchStyle));
+ collector.checkThat("mEnableTerminateNotification", enableTerminateNotification,
+ equalTo(subscribeConfig.mEnableTerminateNotification));
+ }
+
+ @Test
+ public void testSubscribeConfigParcel() {
+ final String serviceName = "some_service_or_other";
+ final String serviceSpecificInfo = "long arbitrary string with some info";
+ final byte[] matchFilter = {
+ 0, 1, 16, 1, 22 };
+ final int subscribeType = SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE;
+ final int subscribeCount = 10;
+ final int subscribeTtl = 15;
+ final int matchStyle = SubscribeConfig.MATCH_STYLE_FIRST_ONLY;
+ final boolean enableTerminateNotification = true;
+
+ SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName)
+ .setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(matchFilter)
+ .setSubscribeType(subscribeType)
+ .setSubscribeCount(subscribeCount).setTtlSec(subscribeTtl).setMatchStyle(matchStyle)
+ .setTerminateNotificationEnabled(enableTerminateNotification).build();
+
+ Parcel parcelW = Parcel.obtain();
+ subscribeConfig.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ SubscribeConfig rereadSubscribeConfig = SubscribeConfig.CREATOR.createFromParcel(parcelR);
+
+ assertEquals(subscribeConfig, rereadSubscribeConfig);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSubscribeConfigBuilderBadSubscribeType() {
+ new SubscribeConfig.Builder().setSubscribeType(10);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSubscribeConfigBuilderNegativeCount() {
+ new SubscribeConfig.Builder().setSubscribeCount(-1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSubscribeConfigBuilderNegativeTtl() {
+ new SubscribeConfig.Builder().setTtlSec(-100);
+ }
+
+ /**
+ * Validate that a bad match style configuration throws an exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testSubscribeConfigBuilderBadMatchStyle() {
+ new SubscribeConfig.Builder().setMatchStyle(10);
+ }
+
+ /*
+ * PublishConfig Tests
+ */
+
+ @Test
+ public void testPublishConfigBuilderDefaults() {
+ PublishConfig publishConfig = new PublishConfig.Builder().build();
+
+ collector.checkThat("mServiceName", publishConfig.mServiceName, equalTo(null));
+ collector.checkThat("mPublishType", publishConfig.mPublishType,
+ equalTo(PublishConfig.PUBLISH_TYPE_UNSOLICITED));
+ collector.checkThat("mPublishCount", publishConfig.mPublishCount, equalTo(0));
+ collector.checkThat("mTtlSec", publishConfig.mTtlSec, equalTo(0));
+ collector.checkThat("mEnableTerminateNotification",
+ publishConfig.mEnableTerminateNotification, equalTo(true));
+ }
+
+ @Test
+ public void testPublishConfigBuilder() {
+ final String serviceName = "some_service_or_other";
+ final String serviceSpecificInfo = "long arbitrary string with some info";
+ final byte[] matchFilter = {
+ 0, 1, 16, 1, 22 };
+ final int publishType = PublishConfig.PUBLISH_TYPE_SOLICITED;
+ final int publishCount = 10;
+ final int publishTtl = 15;
+ final boolean enableTerminateNotification = false;
+
+ PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(serviceName)
+ .setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(matchFilter)
+ .setPublishType(publishType)
+ .setPublishCount(publishCount).setTtlSec(publishTtl)
+ .setTerminateNotificationEnabled(enableTerminateNotification).build();
+
+ collector.checkThat("mServiceName", serviceName.getBytes(),
+ equalTo(publishConfig.mServiceName));
+ collector.checkThat("mServiceSpecificInfo",
+ serviceSpecificInfo.getBytes(), equalTo(publishConfig.mServiceSpecificInfo));
+ collector.checkThat("mMatchFilter", matchFilter, equalTo(publishConfig.mMatchFilter));
+ collector.checkThat("mPublishType", publishType, equalTo(publishConfig.mPublishType));
+ collector.checkThat("mPublishCount", publishCount, equalTo(publishConfig.mPublishCount));
+ collector.checkThat("mTtlSec", publishTtl, equalTo(publishConfig.mTtlSec));
+ collector.checkThat("mEnableTerminateNotification", enableTerminateNotification,
+ equalTo(publishConfig.mEnableTerminateNotification));
+ }
+
+ @Test
+ public void testPublishConfigParcel() {
+ final String serviceName = "some_service_or_other";
+ final String serviceSpecificInfo = "long arbitrary string with some info";
+ final byte[] matchFilter = {
+ 0, 1, 16, 1, 22 };
+ final int publishType = PublishConfig.PUBLISH_TYPE_SOLICITED;
+ final int publishCount = 10;
+ final int publishTtl = 15;
+ final boolean enableTerminateNotification = false;
+
+ PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(serviceName)
+ .setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(matchFilter)
+ .setPublishType(publishType)
+ .setPublishCount(publishCount).setTtlSec(publishTtl)
+ .setTerminateNotificationEnabled(enableTerminateNotification).build();
+
+ Parcel parcelW = Parcel.obtain();
+ publishConfig.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ PublishConfig rereadPublishConfig = PublishConfig.CREATOR.createFromParcel(parcelR);
+
+ assertEquals(publishConfig, rereadPublishConfig);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testPublishConfigBuilderBadPublishType() {
+ new PublishConfig.Builder().setPublishType(5);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testPublishConfigBuilderNegativeCount() {
+ new PublishConfig.Builder().setPublishCount(-4);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testPublishConfigBuilderNegativeTtl() {
+ new PublishConfig.Builder().setTtlSec(-10);
+ }
+
+ /*
+ * Ranging tests
+ */
+
+ /**
+ * Validate ranging + success flow: (1) connect, (2) create a (publish) session, (3) start
+ * ranging, (4) ranging success callback, (5) ranging aborted callback ignored (since
+ * listener removed).
+ */
+ @Test
+ public void testRangingCallbacks() throws Exception {
+ final int clientId = 4565;
+ final int sessionId = 123;
+ final int rangingId = 3482;
+ final ConfigRequest configRequest = new ConfigRequest.Builder().build();
+ final PublishConfig publishConfig = new PublishConfig.Builder().build();
+ final RttManager.RttParams rttParams = new RttManager.RttParams();
+ rttParams.deviceType = RttManager.RTT_PEER_NAN;
+ rttParams.bssid = Integer.toString(1234);
+ final RttManager.RttResult rttResults = new RttManager.RttResult();
+ rttResults.distance = 10;
+
+ when(mockAwareService.startRanging(anyInt(), anyInt(),
+ any(RttManager.ParcelableRttParams.class))).thenReturn(rangingId);
+
+ InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
+ mockPublishSession, mockRttListener);
+ ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
+ WifiAwareSession.class);
+ ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareEventCallback.class);
+ ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareDiscoverySessionCallback.class);
+ ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor
+ .forClass(WifiAwarePublishDiscoverySession.class);
+ ArgumentCaptor<RttManager.ParcelableRttParams> rttParamCaptor = ArgumentCaptor
+ .forClass(RttManager.ParcelableRttParams.class);
+ ArgumentCaptor<RttManager.RttResult[]> rttResultsCaptor = ArgumentCaptor
+ .forClass(RttManager.RttResult[].class);
+
+ // (1) connect successfully
+ mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
+ inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
+ clientProxyCallback.capture(), eq(configRequest), eq(false));
+ clientProxyCallback.getValue().onConnectSuccess(clientId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
+ WifiAwareSession session = sessionCaptor.getValue();
+
+ // (2) publish successfully
+ session.publish(publishConfig, mockSessionCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
+ sessionProxyCallback.capture());
+ sessionProxyCallback.getValue().onSessionStarted(sessionId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
+
+ // (3) start ranging
+ publishSession.getValue().startRanging(new RttManager.RttParams[]{rttParams},
+ mockRttListener);
+ inOrder.verify(mockAwareService).startRanging(eq(clientId), eq(sessionId),
+ rttParamCaptor.capture());
+ collector.checkThat("RttParams.deviceType", rttParams.deviceType,
+ equalTo(rttParamCaptor.getValue().mParams[0].deviceType));
+ collector.checkThat("RttParams.bssid", rttParams.bssid,
+ equalTo(rttParamCaptor.getValue().mParams[0].bssid));
+
+ // (4) ranging success callback
+ clientProxyCallback.getValue().onRangingSuccess(rangingId,
+ new RttManager.ParcelableRttResults(new RttManager.RttResult[] { rttResults }));
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockRttListener).onSuccess(rttResultsCaptor.capture());
+ collector.checkThat("RttResult.distance", rttResults.distance,
+ equalTo(rttResultsCaptor.getValue()[0].distance));
+
+ // (5) ranging aborted callback (should be ignored since listener cleared on first callback)
+ clientProxyCallback.getValue().onRangingAborted(rangingId);
+ mMockLooper.dispatchAll();
+
+ verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
+ mockPublishSession, mockRttListener);
+ }
+
+ /*
+ * Data-path tests
+ */
+
+ /**
+ * Validate that correct network specifier is generated for client-based data-path.
+ */
+ @Test
+ public void testNetworkSpecifierWithClient() throws Exception {
+ final int clientId = 4565;
+ final int sessionId = 123;
+ final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(123412);
+ final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR;
+ final String token = "Some arbitrary token string - can really be anything";
+ final ConfigRequest configRequest = new ConfigRequest.Builder().build();
+ final PublishConfig publishConfig = new PublishConfig.Builder().build();
+
+ String tokenB64 = Base64.encodeToString(token.getBytes(), Base64.DEFAULT);
+
+ ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
+ WifiAwareSession.class);
+ ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareEventCallback.class);
+ ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareDiscoverySessionCallback.class);
+ ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor
+ .forClass(WifiAwarePublishDiscoverySession.class);
+
+ InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
+ mockPublishSession, mockRttListener);
+
+ // (1) connect successfully
+ mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
+ inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
+ clientProxyCallback.capture(), eq(configRequest), eq(false));
+ clientProxyCallback.getValue().onConnectSuccess(clientId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
+ WifiAwareSession session = sessionCaptor.getValue();
+
+ // (2) publish successfully
+ session.publish(publishConfig, mockSessionCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
+ sessionProxyCallback.capture());
+ sessionProxyCallback.getValue().onSessionStarted(sessionId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
+
+ // (3) request a network specifier from the session
+ String networkSpecifier = publishSession.getValue().createNetworkSpecifier(role, peerHandle,
+ token.getBytes());
+
+ // validate format
+ JSONObject jsonObject = new JSONObject(networkSpecifier);
+ collector.checkThat("role", role,
+ equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
+ collector.checkThat("client_id", clientId,
+ equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
+ collector.checkThat("session_id", sessionId,
+ equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
+ collector.checkThat("peer_id", peerHandle.peerId,
+ equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
+ collector.checkThat("token", tokenB64,
+ equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_TOKEN)));
+
+ verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
+ mockPublishSession, mockRttListener);
+ }
+
+ /**
+ * Validate that correct network specifier is generated for a direct data-path (i.e.
+ * specifying MAC address as opposed to a client-based oqaque specification).
+ */
+ @Test
+ public void testNetworkSpecifierDirect() throws Exception {
+ final int clientId = 134;
+ final ConfigRequest configRequest = new ConfigRequest.Builder().build();
+ final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false);
+ final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR;
+ final String token = "Some arbitrary token string - can really be anything";
+
+ String tokenB64 = Base64.encodeToString(token.getBytes(), Base64.DEFAULT);
+
+ ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
+ WifiAwareSession.class);
+ ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareEventCallback.class);
+
+ InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
+ mockPublishSession, mockRttListener);
+
+ // (1) connect successfully
+ mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
+ inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
+ clientProxyCallback.capture(), eq(configRequest), eq(false));
+ clientProxyCallback.getValue().onConnectSuccess(clientId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
+ WifiAwareSession session = sessionCaptor.getValue();
+
+ /* (2) request a direct network specifier*/
+ String networkSpecifier = session.createNetworkSpecifier(role, someMac, token.getBytes());
+
+ /* validate format*/
+ JSONObject jsonObject = new JSONObject(networkSpecifier);
+ collector.checkThat("role", role,
+ equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
+ collector.checkThat("client_id", clientId,
+ equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
+ collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
+ jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
+ false)));
+ collector.checkThat("token", tokenB64,
+ equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_TOKEN)));
+
+ verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
+ mockPublishSession, mockRttListener);
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index b4a3acf..2350d32 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -33,6 +33,11 @@
@SmallTest
public class PasspointConfigurationTest {
+ /**
+ * Utility function for creating a {@link android.net.wifi.hotspot2.pps.HomeSP}.
+ *
+ * @return {@link android.net.wifi.hotspot2.pps.HomeSP}
+ */
private static HomeSP createHomeSp() {
HomeSP homeSp = new HomeSP();
homeSp.fqdn = "fqdn";
@@ -41,6 +46,11 @@
return homeSp;
}
+ /**
+ * Utility function for creating a {@link android.net.wifi.hotspot2.pps.Credential}.
+ *
+ * @return {@link android.net.wifi.hotspot2.pps.Credential}
+ */
private static Credential createCredential() {
Credential cred = new Credential();
cred.realm = "realm";
@@ -55,6 +65,12 @@
return cred;
}
+ /**
+ * Verify parcel write and read consistency for the given configuration.
+ *
+ * @param writeConfig The configuration to verify
+ * @throws Exception
+ */
private static void verifyParcel(PasspointConfiguration writeConfig) throws Exception {
Parcel parcel = Parcel.obtain();
writeConfig.writeToParcel(parcel, 0);
@@ -77,6 +93,7 @@
/**
* Verify parcel read/write for a configuration that contained both HomeSP and Credential.
+ *
* @throws Exception
*/
@Test
@@ -158,4 +175,30 @@
config.credential = createCredential();
assertTrue(config.validate());
}
-}
\ No newline at end of file
+
+ /**
+ * Verify that copy constructor works when pass in a null source.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateCopyConstructorWithNullSource() throws Exception {
+ PasspointConfiguration copyConfig = new PasspointConfiguration(null);
+ PasspointConfiguration defaultConfig = new PasspointConfiguration();
+ assertTrue(copyConfig.equals(defaultConfig));
+ }
+
+ /**
+ * Verify that copy constructor works when pass in a valid source.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateCopyConstructorWithValidSource() throws Exception {
+ PasspointConfiguration sourceConfig = new PasspointConfiguration();
+ sourceConfig.homeSp = createHomeSp();
+ sourceConfig.credential = createCredential();
+ PasspointConfiguration copyConfig = new PasspointConfiguration(sourceConfig);
+ assertTrue(copyConfig.equals(sourceConfig));
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
index 223aa52..9c8b749 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -470,4 +470,52 @@
cred.simCredential.eapType = EAPConstants.EAP_SIM;
assertFalse(cred.validate());
}
+
+ /**
+ * Verify that copy constructor works when pass in a null source.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateCopyConstructorWithNullSource() throws Exception {
+ Credential copyCred = new Credential(null);
+ Credential defaultCred = new Credential();
+ assertTrue(copyCred.equals(defaultCred));
+ }
+
+ /**
+ * Verify that copy constructor works when pass in a source with user credential.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateCopyConstructorWithSourceWithUserCred() throws Exception {
+ Credential sourceCred = createCredentialWithUserCredential();
+ Credential copyCred = new Credential(sourceCred);
+ assertTrue(copyCred.equals(sourceCred));
+ }
+
+ /**
+ * Verify that copy constructor works when pass in a source with certificate credential.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateCopyConstructorWithSourceWithCertCred() throws Exception {
+ Credential sourceCred = createCredentialWithCertificateCredential();
+ Credential copyCred = new Credential(sourceCred);
+ assertTrue(copyCred.equals(sourceCred));
+ }
+
+ /**
+ * Verify that copy constructor works when pass in a source with SIM credential.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateCopyConstructorWithSourceWithSimCred() throws Exception {
+ Credential sourceCred = createCredentialWithSimCredential();
+ Credential copyCred = new Credential(sourceCred);
+ assertTrue(copyCred.equals(sourceCred));
+ }
}
\ No newline at end of file
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java
index fff1477..c707993 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java
@@ -118,4 +118,31 @@
homeSp.roamingConsortiumOIs = new long[] {0x55, 0x66};
assertTrue(homeSp.validate());
}
+
+ /**
+ * Verify that copy constructor works when pass in a null source.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateCopyConstructorFromNullSource() throws Exception {
+ HomeSP copySp = new HomeSP(null);
+ HomeSP defaultSp = new HomeSP();
+ assertTrue(copySp.equals(defaultSp));
+ }
+
+ /**
+ * Verify that copy constructor works when pass in a valid source.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateCopyConstructorFromValidSource() throws Exception {
+ HomeSP sourceSp = new HomeSP();
+ sourceSp.fqdn = "fqdn";
+ sourceSp.friendlyName = "friendlyName";
+ sourceSp.roamingConsortiumOIs = new long[] {0x55, 0x66};
+ HomeSP copySp = new HomeSP(sourceSp);
+ assertTrue(copySp.equals(sourceSp));
+ }
}