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