blob: 21cc159bf2464c430c122bf822689e80f79b3042 [file] [log] [blame]
/*
* 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.nan;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.NetworkRequest;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import dalvik.system.CloseGuard;
import java.lang.ref.WeakReference;
/**
* This class represents a Wi-Fi NAN session - an attachment to the Wi-Fi NAN service through
* which the app can execute discovery operations.
*
* @hide PROPOSED_NAN_API
*/
public class WifiNanSession {
private static final String TAG = "WifiNanSession";
private static final boolean DBG = false;
private static final boolean VDBG = false; // STOPSHIP if true
private final WeakReference<WifiNanManager> mMgr;
private final Binder mBinder;
private final Looper mLooper;
private final int mClientId;
private boolean mTerminated = true;
private final CloseGuard mCloseGuard = CloseGuard.get();
/** @hide */
public WifiNanSession(WifiNanManager manager, Binder binder, Looper looper, int clientId) {
if (VDBG) Log.v(TAG, "New session created: manager=" + manager + ", clientId=" + clientId);
mMgr = new WeakReference<>(manager);
mBinder = binder;
mLooper = looper;
mClientId = clientId;
mTerminated = false;
mCloseGuard.open("destroy");
}
/**
* Destroy the Wi-Fi NAN service session and, if no other applications are attached to NAN,
* also disable NAN. This method destroys all outstanding operations - i.e. all publish and
* subscribes are terminated, and any outstanding data-links are shut-down. However, it is
* good practice to destroy these discovery sessions and connections explicitly before a
* session-wide destroy.
* <p>
* An application may re-attach after a destroy using
* {@link WifiNanManager#attach(Handler, WifiNanEventCallback)} .
*/
public void destroy() {
WifiNanManager mgr = mMgr.get();
if (mgr == null) {
Log.w(TAG, "destroy: called post GC on WifiNanManager");
return;
}
mgr.disconnect(mClientId, mBinder);
mTerminated = true;
mMgr.clear();
mCloseGuard.close();
}
/** @hide */
@Override
protected void finalize() throws Throwable {
try {
if (!mTerminated) {
mCloseGuard.warnIfOpen();
destroy();
}
} finally {
super.finalize();
}
}
/**
* Issue a request to the NAN service to create a new NAN publish discovery session, using
* the specified {@code publishConfig} configuration. The results of the publish operation
* are routed to the callbacks of {@link WifiNanDiscoverySessionCallback}:
* <ul>
* <li>{@link WifiNanDiscoverySessionCallback#onPublishStarted(WifiNanPublishDiscoverySession)}
* is called when the publish session is created and provides a handle to the session.
* Further operations on the publish session can be executed on that object.
* <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFailed(int)} is called if the
* publish operation failed.
* </ul>
* <p>
* Other results of the publish session operations will also be routed to callbacks
* on the {@code callback} object. The resulting publish session can be modified using
* {@link WifiNanPublishDiscoverySession#updatePublish(PublishConfig)}.
* <p>
* An application must use the {@link WifiNanDiscoveryBaseSession#destroy()} to
* terminate the publish discovery session once it isn't needed. This will free
* resources as well terminate any on-air transmissions.
*
* @param publishConfig The {@link PublishConfig} specifying the
* configuration of the requested publish session.
* @param callback A {@link WifiNanDiscoverySessionCallback} derived object to be used for
* session event callbacks.
*/
public void publish(@NonNull PublishConfig publishConfig,
@NonNull WifiNanDiscoverySessionCallback callback) {
WifiNanManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "publish: called post GC on WifiNanManager");
return;
}
if (mTerminated) {
Log.e(TAG, "publish: called after termination");
return;
}
mgr.publish(mClientId, mLooper, publishConfig, callback);
}
/**
* Issue a request to the NAN service to create a new NAN subscribe discovery session, using
* the specified {@code subscribeConfig} configuration. The results of the subscribe
* operation are routed to the callbacks of {@link WifiNanDiscoverySessionCallback}:
* <ul>
* <li>{@link WifiNanDiscoverySessionCallback#onSubscribeStarted(WifiNanSubscribeDiscoverySession)}
* is called when the subscribe session is created and provides a handle to the session.
* Further operations on the subscribe session can be executed on that object.
* <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFailed(int)} is called if the
* subscribe operation failed.
* </ul>
* <p>
* Other results of the subscribe session operations will also be routed to callbacks
* on the {@code callback} object. The resulting subscribe session can be modified using
* {@link WifiNanSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
* <p>
* An application must use the {@link WifiNanDiscoveryBaseSession#destroy()} to
* terminate the subscribe discovery session once it isn't needed. This will free
* resources as well terminate any on-air transmissions.
*
* @param subscribeConfig The {@link SubscribeConfig} specifying the
* configuration of the requested subscribe session.
* @param callback A {@link WifiNanDiscoverySessionCallback} derived object to be used for
* session event callbacks.
*/
public void subscribe(@NonNull SubscribeConfig subscribeConfig,
@NonNull WifiNanDiscoverySessionCallback callback) {
WifiNanManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "publish: called post GC on WifiNanManager");
return;
}
if (mTerminated) {
Log.e(TAG, "publish: called after termination");
return;
}
mgr.subscribe(mClientId, mLooper, subscribeConfig, callback);
}
/**
* Create a {@link NetworkRequest.Builder#setNetworkSpecifier(String)} for a
* WiFi NAN connection to the specified peer. The
* {@link NetworkRequest.Builder#addTransportType(int)} should be set to
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_NAN}.
* <p>
* This API is targeted for applications which can obtain the peer MAC address using OOB
* (out-of-band) discovery. NAN discovery does not provide the MAC address of the peer -
* when using NAN discovery use the alternative network specifier method -
* {@link WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, int, byte[])}.
*
* @param role The role of this device:
* {@link WifiNanManager#WIFI_NAN_DATA_PATH_ROLE_INITIATOR} or
* {@link WifiNanManager#WIFI_NAN_DATA_PATH_ROLE_RESPONDER}
* @param peer The MAC address of the peer's NAN discovery interface. 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
* on the RESPONDER and matches any peer token. An empty ({@code ""}) token is
* not the same as a null token and requires the peer token to be empty as well.
*
* @return A string to be used to construct
* {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
* {@link android.net.ConnectivityManager#requestNetwork(NetworkRequest, android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
*/
public String createNetworkSpecifier(@WifiNanManager.DataPathRole int role, @Nullable byte[] peer,
@Nullable byte[] token) {
WifiNanManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "createNetworkSpecifier: called post GC on WifiNanManager");
return "";
}
if (mTerminated) {
Log.e(TAG, "createNetworkSpecifier: called after termination");
return "";
}
return mgr.createNetworkSpecifier(mClientId, role, peer, token);
}
}