1 /* 2 * Copyright (C) 2019 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 17 package com.android.networkstack.tethering; 18 19 import static android.Manifest.permission.ACCESS_NETWORK_STATE; 20 import static android.Manifest.permission.NETWORK_SETTINGS; 21 import static android.Manifest.permission.NETWORK_STACK; 22 import static android.Manifest.permission.TETHER_PRIVILEGED; 23 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 24 import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; 25 import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION; 26 import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION; 27 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; 28 import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED; 29 import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR; 30 31 import android.app.Service; 32 import android.bluetooth.BluetoothAdapter; 33 import android.bluetooth.BluetoothManager; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.net.IIntResultListener; 37 import android.net.INetworkStackConnector; 38 import android.net.ITetheringConnector; 39 import android.net.ITetheringEventCallback; 40 import android.net.NetworkStack; 41 import android.net.TetheringRequestParcel; 42 import android.net.dhcp.DhcpServerCallbacks; 43 import android.net.dhcp.DhcpServingParamsParcel; 44 import android.net.ip.IpServer; 45 import android.os.Binder; 46 import android.os.HandlerThread; 47 import android.os.IBinder; 48 import android.os.Looper; 49 import android.os.RemoteException; 50 import android.os.ResultReceiver; 51 import android.util.Log; 52 53 import androidx.annotation.NonNull; 54 import androidx.annotation.Nullable; 55 56 import com.android.internal.annotations.VisibleForTesting; 57 import com.android.networkstack.apishim.SettingsShimImpl; 58 import com.android.networkstack.apishim.common.SettingsShim; 59 60 import java.io.FileDescriptor; 61 import java.io.PrintWriter; 62 63 /** 64 * Android service used to manage tethering. 65 * 66 * <p>The service returns a binder for the system server to communicate with the tethering. 67 */ 68 public class TetheringService extends Service { 69 private static final String TAG = TetheringService.class.getSimpleName(); 70 71 private TetheringConnector mConnector; 72 private SettingsShim mSettingsShim; 73 74 @Override onCreate()75 public void onCreate() { 76 final TetheringDependencies deps = makeTetheringDependencies(); 77 // The Tethering object needs a fully functional context to start, so this can't be done 78 // in the constructor. 79 mConnector = new TetheringConnector(makeTethering(deps), TetheringService.this); 80 81 mSettingsShim = SettingsShimImpl.newInstance(); 82 } 83 84 /** 85 * Make a reference to Tethering object. 86 */ 87 @VisibleForTesting makeTethering(TetheringDependencies deps)88 public Tethering makeTethering(TetheringDependencies deps) { 89 return new Tethering(deps); 90 } 91 92 @NonNull 93 @Override onBind(Intent intent)94 public IBinder onBind(Intent intent) { 95 return mConnector; 96 } 97 98 private static class TetheringConnector extends ITetheringConnector.Stub { 99 private final TetheringService mService; 100 private final Tethering mTethering; 101 TetheringConnector(Tethering tether, TetheringService service)102 TetheringConnector(Tethering tether, TetheringService service) { 103 mTethering = tether; 104 mService = service; 105 } 106 107 @Override tether(String iface, String callerPkg, String callingAttributionTag, IIntResultListener listener)108 public void tether(String iface, String callerPkg, String callingAttributionTag, 109 IIntResultListener listener) { 110 if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; 111 112 mTethering.tether(iface, IpServer.STATE_TETHERED, listener); 113 } 114 115 @Override untether(String iface, String callerPkg, String callingAttributionTag, IIntResultListener listener)116 public void untether(String iface, String callerPkg, String callingAttributionTag, 117 IIntResultListener listener) { 118 if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; 119 120 mTethering.untether(iface, listener); 121 } 122 123 @Override setUsbTethering(boolean enable, String callerPkg, String callingAttributionTag, IIntResultListener listener)124 public void setUsbTethering(boolean enable, String callerPkg, String callingAttributionTag, 125 IIntResultListener listener) { 126 if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; 127 128 mTethering.setUsbTethering(enable, listener); 129 } 130 131 @Override startTethering(TetheringRequestParcel request, String callerPkg, String callingAttributionTag, IIntResultListener listener)132 public void startTethering(TetheringRequestParcel request, String callerPkg, 133 String callingAttributionTag, IIntResultListener listener) { 134 if (checkAndNotifyCommonError(callerPkg, 135 callingAttributionTag, 136 request.exemptFromEntitlementCheck /* onlyAllowPrivileged */, 137 listener)) { 138 return; 139 } 140 141 mTethering.startTethering(request, callerPkg, listener); 142 } 143 144 @Override stopTethering(int type, String callerPkg, String callingAttributionTag, IIntResultListener listener)145 public void stopTethering(int type, String callerPkg, String callingAttributionTag, 146 IIntResultListener listener) { 147 if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; 148 149 try { 150 mTethering.stopTethering(type); 151 listener.onResult(TETHER_ERROR_NO_ERROR); 152 } catch (RemoteException e) { } 153 } 154 155 @Override requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver, boolean showEntitlementUi, String callerPkg, String callingAttributionTag)156 public void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver, 157 boolean showEntitlementUi, String callerPkg, String callingAttributionTag) { 158 if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, receiver)) return; 159 160 mTethering.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi); 161 } 162 163 @Override registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg)164 public void registerTetheringEventCallback(ITetheringEventCallback callback, 165 String callerPkg) { 166 try { 167 if (!hasTetherAccessPermission()) { 168 callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION); 169 return; 170 } 171 mTethering.registerTetheringEventCallback(callback); 172 } catch (RemoteException e) { } 173 } 174 175 @Override unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg)176 public void unregisterTetheringEventCallback(ITetheringEventCallback callback, 177 String callerPkg) { 178 try { 179 if (!hasTetherAccessPermission()) { 180 callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION); 181 return; 182 } 183 mTethering.unregisterTetheringEventCallback(callback); 184 } catch (RemoteException e) { } 185 } 186 187 @Override stopAllTethering(String callerPkg, String callingAttributionTag, IIntResultListener listener)188 public void stopAllTethering(String callerPkg, String callingAttributionTag, 189 IIntResultListener listener) { 190 if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; 191 192 try { 193 mTethering.untetherAll(); 194 listener.onResult(TETHER_ERROR_NO_ERROR); 195 } catch (RemoteException e) { } 196 } 197 198 @Override isTetheringSupported(String callerPkg, String callingAttributionTag, IIntResultListener listener)199 public void isTetheringSupported(String callerPkg, String callingAttributionTag, 200 IIntResultListener listener) { 201 if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; 202 203 try { 204 listener.onResult(TETHER_ERROR_NO_ERROR); 205 } catch (RemoteException e) { } 206 } 207 208 @Override setPreferTestNetworks(boolean prefer, IIntResultListener listener)209 public void setPreferTestNetworks(boolean prefer, IIntResultListener listener) { 210 if (!checkCallingOrSelfPermission(NETWORK_SETTINGS)) { 211 try { 212 listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); 213 } catch (RemoteException e) { } 214 return; 215 } 216 217 mTethering.setPreferTestNetworks(prefer, listener); 218 } 219 220 @Override dump(@onNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args)221 protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, 222 @Nullable String[] args) { 223 mTethering.dump(fd, writer, args); 224 } 225 checkAndNotifyCommonError(final String callerPkg, final String callingAttributionTag, final IIntResultListener listener)226 private boolean checkAndNotifyCommonError(final String callerPkg, 227 final String callingAttributionTag, final IIntResultListener listener) { 228 return checkAndNotifyCommonError(callerPkg, callingAttributionTag, 229 false /* onlyAllowPrivileged */, listener); 230 } 231 checkAndNotifyCommonError(final String callerPkg, final String callingAttributionTag, final boolean onlyAllowPrivileged, final IIntResultListener listener)232 private boolean checkAndNotifyCommonError(final String callerPkg, 233 final String callingAttributionTag, final boolean onlyAllowPrivileged, 234 final IIntResultListener listener) { 235 try { 236 if (!hasTetherChangePermission(callerPkg, callingAttributionTag, 237 onlyAllowPrivileged)) { 238 listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); 239 return true; 240 } 241 if (!mTethering.isTetheringSupported() || !mTethering.isTetheringAllowed()) { 242 listener.onResult(TETHER_ERROR_UNSUPPORTED); 243 return true; 244 } 245 } catch (RemoteException e) { 246 return true; 247 } 248 249 return false; 250 } 251 checkAndNotifyCommonError(final String callerPkg, final String callingAttributionTag, final ResultReceiver receiver)252 private boolean checkAndNotifyCommonError(final String callerPkg, 253 final String callingAttributionTag, final ResultReceiver receiver) { 254 if (!hasTetherChangePermission(callerPkg, callingAttributionTag, 255 false /* onlyAllowPrivileged */)) { 256 receiver.send(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, null); 257 return true; 258 } 259 if (!mTethering.isTetheringSupported() || !mTethering.isTetheringAllowed()) { 260 receiver.send(TETHER_ERROR_UNSUPPORTED, null); 261 return true; 262 } 263 264 return false; 265 } 266 hasNetworkStackPermission()267 private boolean hasNetworkStackPermission() { 268 return checkCallingOrSelfPermission(NETWORK_STACK) 269 || checkCallingOrSelfPermission(PERMISSION_MAINLINE_NETWORK_STACK); 270 } 271 hasTetherPrivilegedPermission()272 private boolean hasTetherPrivilegedPermission() { 273 return checkCallingOrSelfPermission(TETHER_PRIVILEGED); 274 } 275 checkCallingOrSelfPermission(final String permission)276 private boolean checkCallingOrSelfPermission(final String permission) { 277 return mService.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED; 278 } 279 hasTetherChangePermission(final String callerPkg, final String callingAttributionTag, final boolean onlyAllowPrivileged)280 private boolean hasTetherChangePermission(final String callerPkg, 281 final String callingAttributionTag, final boolean onlyAllowPrivileged) { 282 if (onlyAllowPrivileged && !hasNetworkStackPermission()) return false; 283 284 if (hasTetherPrivilegedPermission()) return true; 285 286 if (mTethering.isTetherProvisioningRequired()) return false; 287 288 int uid = Binder.getCallingUid(); 289 290 // If callerPkg's uid is not same as Binder.getCallingUid(), 291 // checkAndNoteWriteSettingsOperation will return false and the operation will be 292 // denied. 293 return mService.checkAndNoteWriteSettingsOperation(mService, uid, callerPkg, 294 callingAttributionTag, false /* throwException */); 295 } 296 hasTetherAccessPermission()297 private boolean hasTetherAccessPermission() { 298 if (hasTetherPrivilegedPermission()) return true; 299 300 return mService.checkCallingOrSelfPermission( 301 ACCESS_NETWORK_STATE) == PERMISSION_GRANTED; 302 } 303 } 304 305 /** 306 * Check if the package is a allowed to write settings. This also accounts that such an access 307 * happened. 308 * 309 * @return {@code true} iff the package is allowed to write settings. 310 */ 311 @VisibleForTesting checkAndNoteWriteSettingsOperation(@onNull Context context, int uid, @NonNull String callingPackage, @Nullable String callingAttributionTag, boolean throwException)312 boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid, 313 @NonNull String callingPackage, @Nullable String callingAttributionTag, 314 boolean throwException) { 315 return mSettingsShim.checkAndNoteWriteSettingsOperation(context, uid, callingPackage, 316 callingAttributionTag, throwException); 317 } 318 319 /** 320 * An injection method for testing. 321 */ 322 @VisibleForTesting makeTetheringDependencies()323 public TetheringDependencies makeTetheringDependencies() { 324 return new TetheringDependencies() { 325 @Override 326 public Looper makeTetheringLooper() { 327 final HandlerThread tetherThread = new HandlerThread("android.tethering"); 328 tetherThread.start(); 329 return tetherThread.getLooper(); 330 } 331 332 @Override 333 public Context getContext() { 334 return TetheringService.this; 335 } 336 337 @Override 338 public IpServer.Dependencies makeIpServerDependencies() { 339 return new IpServer.Dependencies() { 340 @Override 341 public void makeDhcpServer(String ifName, DhcpServingParamsParcel params, 342 DhcpServerCallbacks cb) { 343 try { 344 final INetworkStackConnector service = getNetworkStackConnector(); 345 if (service == null) return; 346 347 service.makeDhcpServer(ifName, params, cb); 348 } catch (RemoteException e) { 349 Log.e(TAG, "Fail to make dhcp server"); 350 try { 351 cb.onDhcpServerCreated(STATUS_UNKNOWN_ERROR, null); 352 } catch (RemoteException re) { } 353 } 354 } 355 }; 356 } 357 358 // TODO: replace this by NetworkStackClient#getRemoteConnector after refactoring 359 // networkStackClient. 360 static final int NETWORKSTACK_TIMEOUT_MS = 60_000; 361 private INetworkStackConnector getNetworkStackConnector() { 362 IBinder connector; 363 try { 364 final long before = System.currentTimeMillis(); 365 while ((connector = NetworkStack.getService()) == null) { 366 if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) { 367 Log.wtf(TAG, "Timeout, fail to get INetworkStackConnector"); 368 return null; 369 } 370 Thread.sleep(200); 371 } 372 } catch (InterruptedException e) { 373 Log.wtf(TAG, "Interrupted, fail to get INetworkStackConnector"); 374 return null; 375 } 376 return INetworkStackConnector.Stub.asInterface(connector); 377 } 378 379 @Override 380 public BluetoothAdapter getBluetoothAdapter() { 381 final BluetoothManager btManager = getSystemService(BluetoothManager.class); 382 if (btManager == null) { 383 return null; 384 } 385 return btManager.getAdapter(); 386 } 387 }; 388 } 389 } 390