[P2P] Public API to clean-up resources of P2P
1. Add public API to close a Channel and allow configuration to be
cleaned-up. Actual clean-up will only happen when the last p2p
client executes close or terminates (binder death is triggered
for the service).
2. Add Close Guard to verify that API is called - issue warning
otherwise. Note that to actually get the warning an app needs
to use the StrictMode policy:
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedClosableObjects().build());
Bug: 37443149
Test: (new) unit tests, CtsVerifier, Settings/WFD app
Change-Id: I9590101ef7f7ba0a90812634ac1b931d1482fe72
This commit is contained in:
@@ -27070,7 +27070,8 @@ package android.net.wifi.p2p {
|
||||
method public abstract void onSuccess();
|
||||
}
|
||||
|
||||
public static class WifiP2pManager.Channel {
|
||||
public static class WifiP2pManager.Channel implements java.lang.AutoCloseable {
|
||||
method public void close();
|
||||
}
|
||||
|
||||
public static abstract interface WifiP2pManager.ChannelListener {
|
||||
|
||||
@@ -29866,7 +29866,8 @@ package android.net.wifi.p2p {
|
||||
method public abstract void onSuccess();
|
||||
}
|
||||
|
||||
public static class WifiP2pManager.Channel {
|
||||
public static class WifiP2pManager.Channel implements java.lang.AutoCloseable {
|
||||
method public void close();
|
||||
}
|
||||
|
||||
public static abstract interface WifiP2pManager.ChannelListener {
|
||||
|
||||
@@ -27181,7 +27181,8 @@ package android.net.wifi.p2p {
|
||||
method public abstract void onSuccess();
|
||||
}
|
||||
|
||||
public static class WifiP2pManager.Channel {
|
||||
public static class WifiP2pManager.Channel implements java.lang.AutoCloseable {
|
||||
method public void close();
|
||||
}
|
||||
|
||||
public static abstract interface WifiP2pManager.ChannelListener {
|
||||
|
||||
@@ -41,6 +41,8 @@ import android.util.Log;
|
||||
import com.android.internal.util.AsyncChannel;
|
||||
import com.android.internal.util.Protocol;
|
||||
|
||||
import dalvik.system.CloseGuard;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -668,15 +670,21 @@ public class WifiP2pManager {
|
||||
* Most p2p operations require a Channel as an argument. An instance of Channel is obtained
|
||||
* by doing a call on {@link #initialize}
|
||||
*/
|
||||
public static class Channel {
|
||||
Channel(Context context, Looper looper, ChannelListener l, Binder binder) {
|
||||
public static class Channel implements AutoCloseable {
|
||||
/** @hide */
|
||||
public Channel(Context context, Looper looper, ChannelListener l, Binder binder,
|
||||
WifiP2pManager p2pManager) {
|
||||
mAsyncChannel = new AsyncChannel();
|
||||
mHandler = new P2pHandler(looper);
|
||||
mChannelListener = l;
|
||||
mContext = context;
|
||||
mBinder = binder;
|
||||
mP2pManager = p2pManager;
|
||||
|
||||
mCloseGuard.open("close");
|
||||
}
|
||||
private final static int INVALID_LISTENER_KEY = 0;
|
||||
private final WifiP2pManager mP2pManager;
|
||||
private ChannelListener mChannelListener;
|
||||
private ServiceResponseListener mServRspListener;
|
||||
private DnsSdServiceResponseListener mDnsSdServRspListener;
|
||||
@@ -686,6 +694,41 @@ public class WifiP2pManager {
|
||||
private final Object mListenerMapLock = new Object();
|
||||
private int mListenerKey = 0;
|
||||
|
||||
private final CloseGuard mCloseGuard = CloseGuard.get();
|
||||
|
||||
/**
|
||||
* Close the current P2P connection and indicate to the P2P service that connections
|
||||
* created by the app can be removed.
|
||||
*/
|
||||
public void close() {
|
||||
if (mP2pManager == null) {
|
||||
Log.w(TAG, "Channel.close(): Null mP2pManager!?");
|
||||
} else {
|
||||
try {
|
||||
mP2pManager.mService.close(mBinder);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
mAsyncChannel.disconnect();
|
||||
mCloseGuard.close();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
if (mCloseGuard != null) {
|
||||
mCloseGuard.warnIfOpen();
|
||||
}
|
||||
|
||||
close();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ final Binder mBinder;
|
||||
|
||||
private AsyncChannel mAsyncChannel;
|
||||
@@ -913,11 +956,12 @@ public class WifiP2pManager {
|
||||
Messenger messenger, Binder binder) {
|
||||
if (messenger == null) return null;
|
||||
|
||||
Channel c = new Channel(srcContext, srcLooper, listener, binder);
|
||||
Channel c = new Channel(srcContext, srcLooper, listener, binder, this);
|
||||
if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)
|
||||
== AsyncChannel.STATUS_SUCCESSFUL) {
|
||||
return c;
|
||||
} else {
|
||||
c.close();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1421,24 +1465,6 @@ public class WifiP2pManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the current P2P connection and clean-up any configuration requested by the
|
||||
* current app. Takes same action as taken when the app dies.
|
||||
*
|
||||
* @param c is the channel created at {@link #initialize}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void close(Channel c) {
|
||||
try {
|
||||
if (c != null) {
|
||||
mService.close(c.mBinder);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a handover request message for use in WFA NFC Handover transfer.
|
||||
* @hide
|
||||
|
||||
@@ -50,6 +50,7 @@ LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := $(jacoco_exclude)
|
||||
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||
android-support-test \
|
||||
core-test-rules \
|
||||
guava \
|
||||
mockito-target-minus-junit4 \
|
||||
frameworks-base-testutils \
|
||||
|
||||
82
wifi/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java
Normal file
82
wifi/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.p2p;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.test.TestLooper;
|
||||
|
||||
import libcore.junit.util.ResourceLeakageDetector;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
/**
|
||||
* Unit test harness for WifiP2pManager.
|
||||
*/
|
||||
public class WifiP2pManagerTest {
|
||||
private WifiP2pManager mDut;
|
||||
private TestLooper mTestLooper;
|
||||
|
||||
@Mock
|
||||
public Context mContextMock;
|
||||
@Mock
|
||||
IWifiP2pManager mP2pServiceMock;
|
||||
|
||||
@Rule
|
||||
public ResourceLeakageDetector.LeakageDetectorRule leakageDetectorRule =
|
||||
ResourceLeakageDetector.getRule();
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mDut = new WifiP2pManager(mP2pServiceMock);
|
||||
mTestLooper = new TestLooper();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that on finalize we close the channel and flag a resource leakage.
|
||||
*/
|
||||
@Test
|
||||
public void testChannelFinalize() throws Exception {
|
||||
WifiP2pManager.Channel channel = new WifiP2pManager.Channel(mContextMock,
|
||||
mTestLooper.getLooper(), null, null, mDut);
|
||||
|
||||
leakageDetectorRule.assertUnreleasedResourceCount(channel, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that when close is called on a channel it frees up resources (i.e. don't
|
||||
* get flagged again on finalize).
|
||||
*/
|
||||
@Test
|
||||
public void testChannelClose() throws Exception {
|
||||
WifiP2pManager.Channel channel = new WifiP2pManager.Channel(mContextMock,
|
||||
mTestLooper.getLooper(), null, null, mDut);
|
||||
|
||||
channel.close();
|
||||
verify(mP2pServiceMock).close(any());
|
||||
|
||||
leakageDetectorRule.assertUnreleasedResourceCount(channel, 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user