1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wifi.nan; 18 19import android.content.Context; 20import android.content.pm.PackageManager; 21import android.net.wifi.nan.ConfigRequest; 22import android.net.wifi.nan.IWifiNanEventListener; 23import android.net.wifi.nan.IWifiNanManager; 24import android.net.wifi.nan.IWifiNanSessionListener; 25import android.net.wifi.nan.PublishData; 26import android.net.wifi.nan.PublishSettings; 27import android.net.wifi.nan.SubscribeData; 28import android.net.wifi.nan.SubscribeSettings; 29import android.os.Binder; 30import android.os.HandlerThread; 31import android.os.IBinder; 32import android.os.RemoteException; 33import android.util.Log; 34import android.util.SparseArray; 35 36import java.io.FileDescriptor; 37import java.io.PrintWriter; 38 39public class WifiNanServiceImpl extends IWifiNanManager.Stub { 40 private static final String TAG = "WifiNanService"; 41 private static final boolean DBG = false; 42 private static final boolean VDBG = false; // STOPSHIP if true 43 44 private Context mContext; 45 private WifiNanStateManager mStateManager; 46 private final boolean mNanSupported; 47 48 private final Object mLock = new Object(); 49 private final SparseArray<IBinder.DeathRecipient> mDeathRecipientsByUid = new SparseArray<>(); 50 private int mNextNetworkRequestToken = 1; 51 private int mNextSessionId = 1; 52 53 public WifiNanServiceImpl(Context context) { 54 mContext = context.getApplicationContext(); 55 56 mNanSupported = mContext.getPackageManager() 57 .hasSystemFeature(PackageManager.FEATURE_WIFI_NAN); 58 if (DBG) Log.w(TAG, "WifiNanServiceImpl: mNanSupported=" + mNanSupported); 59 60 mStateManager = WifiNanStateManager.getInstance(); 61 } 62 63 public void start() { 64 Log.i(TAG, "Starting Wi-Fi NAN service"); 65 66 // TODO: share worker thread with other Wi-Fi handlers 67 HandlerThread wifiNanThread = new HandlerThread("wifiNanService"); 68 wifiNanThread.start(); 69 70 mStateManager.start(wifiNanThread.getLooper()); 71 } 72 73 @Override 74 public void connect(final IBinder binder, IWifiNanEventListener listener, int events) { 75 enforceAccessPermission(); 76 enforceChangePermission(); 77 78 final int uid = getCallingUid(); 79 80 if (VDBG) Log.v(TAG, "connect: uid=" + uid); 81 82 83 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 84 @Override 85 public void binderDied() { 86 if (DBG) Log.d(TAG, "binderDied: uid=" + uid); 87 binder.unlinkToDeath(this, 0); 88 89 synchronized (mLock) { 90 mDeathRecipientsByUid.delete(uid); 91 } 92 93 mStateManager.disconnect(uid); 94 } 95 }; 96 synchronized (mLock) { 97 mDeathRecipientsByUid.put(uid, dr); 98 } 99 try { 100 binder.linkToDeath(dr, 0); 101 } catch (RemoteException e) { 102 Log.w(TAG, "Error on linkToDeath - " + e); 103 } 104 105 mStateManager.connect(uid, listener, events); 106 } 107 108 @Override 109 public void disconnect(IBinder binder) { 110 enforceAccessPermission(); 111 enforceChangePermission(); 112 113 int uid = getCallingUid(); 114 115 if (VDBG) Log.v(TAG, "disconnect: uid=" + uid); 116 117 synchronized (mLock) { 118 IBinder.DeathRecipient dr = mDeathRecipientsByUid.get(uid); 119 if (dr != null) { 120 binder.unlinkToDeath(dr, 0); 121 mDeathRecipientsByUid.delete(uid); 122 } 123 } 124 125 mStateManager.disconnect(uid); 126 } 127 128 @Override 129 public void requestConfig(ConfigRequest configRequest) { 130 enforceAccessPermission(); 131 enforceChangePermission(); 132 133 if (VDBG) { 134 Log.v(TAG, 135 "requestConfig: uid=" + getCallingUid() + ", configRequest=" + configRequest); 136 } 137 138 mStateManager.requestConfig(getCallingUid(), configRequest); 139 } 140 141 @Override 142 public void stopSession(int sessionId) { 143 enforceAccessPermission(); 144 enforceChangePermission(); 145 146 if (VDBG) Log.v(TAG, "stopSession: sessionId=" + sessionId + ", uid=" + getCallingUid()); 147 148 mStateManager.stopSession(getCallingUid(), sessionId); 149 } 150 151 @Override 152 public void destroySession(int sessionId) { 153 enforceAccessPermission(); 154 enforceChangePermission(); 155 156 if (VDBG) Log.v(TAG, "destroySession: sessionId=" + sessionId + ", uid=" + getCallingUid()); 157 158 mStateManager.destroySession(getCallingUid(), sessionId); 159 } 160 161 @Override 162 public int createSession(IWifiNanSessionListener listener, int events) { 163 enforceAccessPermission(); 164 enforceChangePermission(); 165 166 if (VDBG) Log.v(TAG, "createSession: uid=" + getCallingUid()); 167 168 int sessionId; 169 synchronized (mLock) { 170 sessionId = mNextSessionId++; 171 } 172 173 mStateManager.createSession(getCallingUid(), sessionId, listener, events); 174 175 return sessionId; 176 } 177 178 @Override 179 public void publish(int sessionId, PublishData publishData, PublishSettings publishSettings) { 180 enforceAccessPermission(); 181 enforceChangePermission(); 182 183 if (VDBG) { 184 Log.v(TAG, "publish: uid=" + getCallingUid() + ", sessionId=" + sessionId + ", data='" 185 + publishData + "', settings=" + publishSettings); 186 } 187 188 mStateManager.publish(getCallingUid(), sessionId, publishData, publishSettings); 189 } 190 191 @Override 192 public void subscribe(int sessionId, SubscribeData subscribeData, 193 SubscribeSettings subscribeSettings) { 194 enforceAccessPermission(); 195 enforceChangePermission(); 196 197 if (VDBG) { 198 Log.v(TAG, "subscribe: uid=" + getCallingUid() + ", sessionId=" + sessionId + ", data='" 199 + subscribeData + "', settings=" + subscribeSettings); 200 } 201 202 mStateManager.subscribe(getCallingUid(), sessionId, subscribeData, subscribeSettings); 203 } 204 205 @Override 206 public void sendMessage(int sessionId, int peerId, byte[] message, int messageLength, 207 int messageId) { 208 enforceAccessPermission(); 209 enforceChangePermission(); 210 211 if (VDBG) { 212 Log.v(TAG, 213 "sendMessage: sessionId=" + sessionId + ", uid=" + getCallingUid() + ", peerId=" 214 + peerId + ", messageLength=" + messageLength + ", messageId=" 215 + messageId); 216 } 217 218 mStateManager.sendMessage(getCallingUid(), sessionId, peerId, message, messageLength, 219 messageId); 220 } 221 222 @Override 223 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 224 if (mContext.checkCallingOrSelfPermission( 225 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { 226 pw.println("Permission Denial: can't dump WifiNanService from pid=" 227 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 228 return; 229 } 230 pw.println("Wi-Fi NAN Service"); 231 pw.println(" mNanSupported: " + mNanSupported); 232 pw.println(" mNextNetworkRequestToken: " + mNextNetworkRequestToken); 233 pw.println(" mNextSessionId: " + mNextSessionId); 234 pw.println(" mDeathRecipientsByUid: " + mDeathRecipientsByUid); 235 mStateManager.dump(fd, pw, args); 236 } 237 238 private void enforceAccessPermission() { 239 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, TAG); 240 } 241 242 private void enforceChangePermission() { 243 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, TAG); 244 } 245} 246