diff options
-rw-r--r-- | service/java/com/android/server/wifi/RttService.java | 108 |
1 files changed, 85 insertions, 23 deletions
diff --git a/service/java/com/android/server/wifi/RttService.java b/service/java/com/android/server/wifi/RttService.java index 3eafc77f6..7b3d9f955 100644 --- a/service/java/com/android/server/wifi/RttService.java +++ b/service/java/com/android/server/wifi/RttService.java @@ -5,10 +5,12 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; import android.net.wifi.IRttManager; import android.net.wifi.RttManager; import android.net.wifi.RttManager.ResponderConfig; import android.net.wifi.WifiManager; +import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; @@ -16,16 +18,20 @@ import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; +import android.util.ArrayMap; import android.util.Log; import android.util.Slog; +import com.android.internal.annotations.GuardedBy; import com.android.internal.util.AsyncChannel; +import com.android.internal.util.IState; import com.android.internal.util.Protocol; import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.server.SystemService; -import java.util.HashMap; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; @@ -65,20 +71,27 @@ public final class RttService extends SystemService { if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); } if (DBG) Slog.d(TAG, "closing client " + msg.replyTo); - ClientInfo ci = mClients.remove(msg.replyTo); - if (ci != null) ci.cleanup(); + synchronized (mLock) { + ClientInfo ci = mClients.remove(msg.replyTo); + if (ci != null) ci.cleanup(); + } return; case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: AsyncChannel ac = new AsyncChannel(); ac.connected(mContext, this, msg.replyTo); - ClientInfo client = new ClientInfo(ac, msg.replyTo); - mClients.put(msg.replyTo, client); + ClientInfo client = new ClientInfo(ac, msg.sendingUid); + synchronized (mLock) { + mClients.put(msg.replyTo, client); + } ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, AsyncChannel.STATUS_SUCCESSFUL); return; } - ClientInfo ci = mClients.get(msg.replyTo); + ClientInfo ci; + synchronized (mLock) { + ci = mClients.get(msg.replyTo); + } if (ci == null) { Slog.e(TAG, "Could not find client info for message " + msg.replyTo); replyFailed(msg, RttManager.REASON_INVALID_LISTENER, "Could not find listener"); @@ -170,15 +183,15 @@ public final class RttService extends SystemService { private class ClientInfo { private final AsyncChannel mChannel; - private final Messenger mMessenger; - HashMap<Integer, RttRequest> mRequests = new HashMap<Integer, - RttRequest>(); + private final int mUid; + + ArrayMap<Integer, RttRequest> mRequests = new ArrayMap<>(); // Client keys of all outstanding responders. Set<Integer> mResponderRequests = new HashSet<>(); - ClientInfo(AsyncChannel c, Messenger m) { - mChannel = c; - mMessenger = m; + ClientInfo(AsyncChannel channel, int uid) { + mChannel = channel; + mUid = uid; } void addResponderRequest(int key) { @@ -215,7 +228,7 @@ public final class RttService extends SystemService { void reportResponderEnableFailed(int key, int reason) { mChannel.sendMessage(RttManager.CMD_OP_ENALBE_RESPONDER_FAILED, reason, key); - mResponderRequests.remove(key); + removeResponderRequest(key); } void reportResult(RttRequest request, RttManager.RttResult[] results) { @@ -224,7 +237,7 @@ public final class RttService extends SystemService { mChannel.sendMessage(RttManager.CMD_OP_SUCCEEDED, 0, request.key, parcelableResults); - mRequests.remove(request.key); + removeRttRequest(request.key); } void reportFailed(RttRequest request, int reason, String description) { @@ -235,7 +248,7 @@ public final class RttService extends SystemService { Bundle bundle = new Bundle(); bundle.putString(RttManager.DESCRIPTION_KEY, description); mChannel.sendMessage(RttManager.CMD_OP_FAILED, key, reason, bundle); - mRequests.remove(key); + removeRttRequest(key); } void reportAborted(int key) { @@ -252,10 +265,19 @@ public final class RttService extends SystemService { mResponderRequests.clear(); mStateMachine.sendMessage(RttManager.CMD_OP_DISABLE_RESPONDER); } + + @Override + public String toString() { + return "ClientInfo [uid=" + mUid + ", channel=" + mChannel + "]"; + } } - private Queue<RttRequest> mRequestQueue = new LinkedList<RttRequest>(); - private HashMap<Messenger, ClientInfo> mClients = new HashMap<Messenger, ClientInfo>(4); + private Queue<RttRequest> mRequestQueue = new LinkedList<>(); + + @GuardedBy("mLock") + private ArrayMap<Messenger, ClientInfo> mClients = new ArrayMap<>(); + // Lock for mClients. + private final Object mLock = new Object(); private static final int BASE = Protocol.BASE_WIFI_RTT_SERVICE; @@ -305,7 +327,11 @@ public final class RttService extends SystemService { case RttManager.CMD_OP_STOP_RANGING: return HANDLED; case RttManager.CMD_OP_ENABLE_RESPONDER: - ClientInfo client = mClients.get(msg.replyTo); + + ClientInfo client; + synchronized (mLock) { + client = mClients.get(msg.replyTo); + } if (client == null) { Log.e(TAG, "client not connected yet!"); break; @@ -327,7 +353,10 @@ public final class RttService extends SystemService { @Override public boolean processMessage(Message msg) { if (DBG) Log.d(TAG, "EnabledState got" + msg); - ClientInfo ci = mClients.get(msg.replyTo); + ClientInfo ci; + synchronized (mLock) { + ci = mClients.get(msg.replyTo); + } switch (msg.what) { case CMD_DRIVER_UNLOADED: @@ -455,9 +484,11 @@ public final class RttService extends SystemService { // Check if there are still outstanding responder requests from any client. private boolean hasOutstandingReponderRequests() { - for (ClientInfo client : mClients.values()) { - if (!client.mResponderRequests.isEmpty()) { - return true; + synchronized (mLock) { + for (ClientInfo client : mClients.values()) { + if (!client.mResponderRequests.isEmpty()) { + return true; + } } } return false; @@ -470,7 +501,10 @@ public final class RttService extends SystemService { @Override public boolean processMessage(Message msg) { if (DBG) Log.d(TAG, "ResponderEnabledState got " + msg); - ClientInfo ci = mClients.get(msg.replyTo); + ClientInfo ci; + synchronized (mLock) { + ci = mClients.get(msg.replyTo); + } int key = msg.arg2; switch(msg.what) { case RttManager.CMD_OP_ENABLE_RESPONDER: @@ -503,6 +537,14 @@ public final class RttService extends SystemService { } } } + + /** + * Returns name of current state. + */ + String currentState() { + IState state = getCurrentState(); + return state == null ? "null" : state.getName(); + } } void replySucceeded(Message msg, Object obj) { @@ -551,6 +593,26 @@ public final class RttService extends SystemService { return true; } + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump RttService from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid() + + " without permission " + + android.Manifest.permission.DUMP); + return; + } + pw.println("current state: " + mStateMachine.currentState()); + pw.println("clients:"); + synchronized (mLock) { + for (ClientInfo client : mClients.values()) { + pw.println(" " + client); + } + } + } + private WifiNative.RttEventHandler mEventHandler = new WifiNative.RttEventHandler() { @Override public void onRttResults(RttManager.RttResult[] result) { |