diff options
author | Etan Cohen <etancohen@google.com> | 2017-06-06 20:20:27 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2017-06-06 20:20:33 +0000 |
commit | 2d02c0b588eb19935ad87b8dae9d6a9839e667c2 (patch) | |
tree | e82b558000eaffcd404b21f8fc35c0d5cd0f731e /service | |
parent | c75b04438e296b818ff3eb315e0ec2093d86d85c (diff) | |
parent | 252dbd59df86e3fb329ce6712ce76c2a970330c8 (diff) |
Merge "[P2P] Clean-up on requestor death"
Diffstat (limited to 'service')
-rw-r--r-- | service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java | 103 |
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; |