summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorEtan Cohen <etancohen@google.com>2017-06-06 20:20:27 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2017-06-06 20:20:33 +0000
commit2d02c0b588eb19935ad87b8dae9d6a9839e667c2 (patch)
treee82b558000eaffcd404b21f8fc35c0d5cd0f731e /service
parentc75b04438e296b818ff3eb315e0ec2093d86d85c (diff)
parent252dbd59df86e3fb329ce6712ce76c2a970330c8 (diff)
Merge "[P2P] Clean-up on requestor death"
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java103
1 files changed, 101 insertions, 2 deletions
diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
index 623a2f0c3..06eae175c 100644
--- a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
+++ b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
@@ -24,6 +24,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.hardware.wifi.V1_0.IWifiP2pIface;
import android.net.ConnectivityManager;
import android.net.DhcpResults;
import android.net.InterfaceConfiguration;
@@ -77,6 +78,7 @@ import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
+import com.android.server.wifi.HalDeviceManager;
import com.android.server.wifi.WifiInjector;
import com.android.server.wifi.WifiStateMachine;
import com.android.server.wifi.util.WifiAsyncChannel;
@@ -91,6 +93,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* WifiP2pService includes a state machine to perform Wi-Fi p2p operations. Applications
@@ -358,6 +361,25 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
}
private ClientHandler mClientHandler;
+ private class DeathHandlerData {
+ DeathHandlerData(DeathRecipient dr, Messenger m) {
+ mDeathRecipient = dr;
+ mMessenger = m;
+ }
+
+ @Override
+ public String toString() {
+ return "deathRecipient=" + mDeathRecipient + ", messenger=" + mMessenger;
+ }
+
+ DeathRecipient mDeathRecipient;
+ Messenger mMessenger;
+ }
+ private Object mLock = new Object();
+ private final Map<IBinder, DeathHandlerData> mDeathDataByBinder = new HashMap<>();
+ private HalDeviceManager mHalDeviceManager;
+ private IWifiP2pIface mIWifiP2pIface;
+
public WifiP2pServiceImpl(Context context) {
mContext = context;
@@ -468,10 +490,47 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
* an AsyncChannel communication with WifiP2pService
*/
@Override
- public Messenger getMessenger() {
+ public Messenger getMessenger(final IBinder binder) {
enforceAccessPermission();
enforceChangePermission();
- return new Messenger(mClientHandler);
+
+ synchronized (mLock) {
+ final Messenger messenger = new Messenger(mClientHandler);
+ if (DBG) {
+ Log.d(TAG, "getMessenger: uid=" + getCallingUid() + ", binder=" + binder
+ + ", messenger=" + messenger);
+ }
+
+ IBinder.DeathRecipient dr = () -> {
+ if (DBG) Log.d(TAG, "binderDied: binder=" + binder);
+ close(binder);
+ };
+
+ try {
+ binder.linkToDeath(dr, 0);
+ mDeathDataByBinder.put(binder, new DeathHandlerData(dr, messenger));
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error on linkToDeath: e=" + e);
+ // fall-through here - won't clean up
+ }
+
+ if (mIWifiP2pIface == null) {
+ if (mHalDeviceManager == null) {
+ if (mWifiInjector == null) {
+ mWifiInjector = WifiInjector.getInstance();
+ }
+ mHalDeviceManager = mWifiInjector.getHalDeviceManager();
+ }
+ mIWifiP2pIface = mHalDeviceManager.createP2pIface(() -> {
+ if (DBG) Log.d(TAG, "IWifiP2pIface destroyedListener");
+ synchronized (mLock) {
+ mIWifiP2pIface = null;
+ }
+ }, mP2pStateMachine.getHandler().getLooper());
+ }
+
+ return messenger;
+ }
}
/**
@@ -487,6 +546,45 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
return new Messenger(mP2pStateMachine.getHandler());
}
+ /**
+ * Clean-up the state and configuration requested by the closing app. Takes same action as
+ * when the app dies (binder death).
+ */
+ @Override
+ public void close(IBinder binder) {
+ enforceAccessPermission();
+ enforceChangePermission();
+
+ DeathHandlerData dhd;
+ synchronized (mLock) {
+ dhd = mDeathDataByBinder.get(binder);
+ if (dhd == null) {
+ Log.w(TAG, "close(): no death recipient for binder");
+ return;
+ }
+
+ binder.unlinkToDeath(dhd.mDeathRecipient, 0);
+ mDeathDataByBinder.remove(binder);
+
+ // clean-up if there are no more clients registered
+ // TODO: what does the WifiStateMachine client do? It isn't tracked through here!
+ if (dhd.mMessenger != null && mDeathDataByBinder.isEmpty()) {
+ try {
+ dhd.mMessenger.send(
+ mClientHandler.obtainMessage(WifiP2pManager.STOP_DISCOVERY));
+ dhd.mMessenger.send(mClientHandler.obtainMessage(WifiP2pManager.REMOVE_GROUP));
+ } catch (RemoteException e) {
+ Log.e(TAG, "close: Failed sending clean-up commands: e=" + e);
+ }
+
+ if (mIWifiP2pIface != null) {
+ mHalDeviceManager.removeIface(mIWifiP2pIface);
+ mIWifiP2pIface = null;
+ }
+ }
+ }
+ }
+
/** This is used to provide information to drivers to optimize performance depending
* on the current mode of operation.
* 0 - disabled
@@ -538,6 +636,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
pw.println("mNetworkInfo " + mNetworkInfo);
pw.println("mTemporarilyDisconnectedWifi " + mTemporarilyDisconnectedWifi);
pw.println("mServiceDiscReqId " + mServiceDiscReqId);
+ pw.println("mDeathDataByBinder " + mDeathDataByBinder);
pw.println();
final IpManager ipManager = mIpManager;