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