blob: d07c555f66cda37b099fde6f6528b6933aef85d0 [file] [log] [blame]
markchien0df2ebc42019-09-30 14:40:57 +08001/*
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
markchien503be612020-04-12 21:41:29 +080017package com.android.networkstack.tethering;
markchien0df2ebc42019-09-30 14:40:57 +080018
markchien5788f2a2020-05-08 18:55:26 +080019import static android.Manifest.permission.ACCESS_NETWORK_STATE;
20import static android.Manifest.permission.TETHER_PRIVILEGED;
markchien6d06f6d2019-12-16 20:15:20 +080021import static android.content.pm.PackageManager.PERMISSION_GRANTED;
22import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION;
23import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
24import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
25import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
markchien986750b2019-12-06 15:24:53 +080026import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR;
markchien6d06f6d2019-12-16 20:15:20 +080027
markchien0df2ebc42019-09-30 14:40:57 +080028import android.app.Service;
markchien3fe660b2019-12-05 12:04:59 +080029import android.bluetooth.BluetoothAdapter;
markchien0df2ebc42019-09-30 14:40:57 +080030import android.content.Context;
31import android.content.Intent;
markchien6d06f6d2019-12-16 20:15:20 +080032import android.net.IIntResultListener;
33import android.net.INetworkStackConnector;
markchien0df2ebc42019-09-30 14:40:57 +080034import android.net.ITetheringConnector;
markchien6d06f6d2019-12-16 20:15:20 +080035import android.net.ITetheringEventCallback;
markchien87d3f7d2020-01-08 20:58:23 +080036import android.net.NetworkCapabilities;
markchien0df2ebc42019-09-30 14:40:57 +080037import android.net.NetworkRequest;
Remi NGUYEN VAN438018d2020-03-18 18:31:39 +090038import android.net.NetworkStack;
markchien06889172020-01-20 19:31:56 +080039import android.net.TetheringRequestParcel;
markchien6d06f6d2019-12-16 20:15:20 +080040import android.net.dhcp.DhcpServerCallbacks;
41import android.net.dhcp.DhcpServingParamsParcel;
42import android.net.ip.IpServer;
markchien0df2ebc42019-09-30 14:40:57 +080043import android.net.util.SharedLog;
markchien6d06f6d2019-12-16 20:15:20 +080044import android.os.Binder;
markchien0df2ebc42019-09-30 14:40:57 +080045import android.os.HandlerThread;
46import android.os.IBinder;
47import android.os.Looper;
markchien6d06f6d2019-12-16 20:15:20 +080048import android.os.RemoteException;
markchien0df2ebc42019-09-30 14:40:57 +080049import android.os.ResultReceiver;
50import android.os.SystemProperties;
markchien6d06f6d2019-12-16 20:15:20 +080051import android.os.UserManager;
markchien0df2ebc42019-09-30 14:40:57 +080052import android.provider.Settings;
markchien6d06f6d2019-12-16 20:15:20 +080053import android.util.Log;
markchien0df2ebc42019-09-30 14:40:57 +080054
55import androidx.annotation.NonNull;
56import androidx.annotation.Nullable;
57
58import com.android.internal.annotations.VisibleForTesting;
59
60import java.io.FileDescriptor;
61import 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 */
68public class TetheringService extends Service {
69 private static final String TAG = TetheringService.class.getSimpleName();
70
71 private final SharedLog mLog = new SharedLog(TAG);
72 private TetheringConnector mConnector;
73 private Context mContext;
74 private TetheringDependencies mDeps;
75 private Tethering mTethering;
markchien6d06f6d2019-12-16 20:15:20 +080076 private UserManager mUserManager;
markchien0df2ebc42019-09-30 14:40:57 +080077
78 @Override
79 public void onCreate() {
80 mLog.mark("onCreate");
81 mDeps = getTetheringDependencies();
82 mContext = mDeps.getContext();
markchien6d06f6d2019-12-16 20:15:20 +080083 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
markchien5f7b3be2020-01-31 14:04:36 +080084 mTethering = makeTethering(mDeps);
Mark Chien674a0122020-03-27 09:37:01 +000085 mTethering.startStateMachineUpdaters();
markchien0df2ebc42019-09-30 14:40:57 +080086 }
87
88 /**
89 * Make a reference to Tethering object.
90 */
91 @VisibleForTesting
92 public Tethering makeTethering(TetheringDependencies deps) {
markchien771c3e92019-12-07 22:02:28 +080093 System.loadLibrary("tetherutilsjni");
markchien0df2ebc42019-09-30 14:40:57 +080094 return new Tethering(deps);
95 }
96
97 /**
98 * Create a binder connector for the system server to communicate with the tethering.
99 */
100 private synchronized IBinder makeConnector() {
101 if (mConnector == null) {
markchien6d06f6d2019-12-16 20:15:20 +0800102 mConnector = new TetheringConnector(mTethering, TetheringService.this);
markchien0df2ebc42019-09-30 14:40:57 +0800103 }
104 return mConnector;
105 }
106
107 @NonNull
108 @Override
109 public IBinder onBind(Intent intent) {
110 mLog.mark("onBind");
111 return makeConnector();
112 }
113
114 private static class TetheringConnector extends ITetheringConnector.Stub {
markchien6d06f6d2019-12-16 20:15:20 +0800115 private final TetheringService mService;
116 private final Tethering mTethering;
markchien0df2ebc42019-09-30 14:40:57 +0800117
markchien6d06f6d2019-12-16 20:15:20 +0800118 TetheringConnector(Tethering tether, TetheringService service) {
119 mTethering = tether;
120 mService = service;
markchien0df2ebc42019-09-30 14:40:57 +0800121 }
122
123 @Override
markchien6d06f6d2019-12-16 20:15:20 +0800124 public void tether(String iface, String callerPkg, IIntResultListener listener) {
125 if (checkAndNotifyCommonError(callerPkg, listener)) return;
126
127 try {
128 listener.onResult(mTethering.tether(iface));
129 } catch (RemoteException e) { }
markchien0df2ebc42019-09-30 14:40:57 +0800130 }
131
132 @Override
markchien6d06f6d2019-12-16 20:15:20 +0800133 public void untether(String iface, String callerPkg, IIntResultListener listener) {
134 if (checkAndNotifyCommonError(callerPkg, listener)) return;
135
136 try {
137 listener.onResult(mTethering.untether(iface));
138 } catch (RemoteException e) { }
markchien0df2ebc42019-09-30 14:40:57 +0800139 }
140
141 @Override
markchien6d06f6d2019-12-16 20:15:20 +0800142 public void setUsbTethering(boolean enable, String callerPkg, IIntResultListener listener) {
143 if (checkAndNotifyCommonError(callerPkg, listener)) return;
144
145 try {
146 listener.onResult(mTethering.setUsbTethering(enable));
147 } catch (RemoteException e) { }
markchien0df2ebc42019-09-30 14:40:57 +0800148 }
149
150 @Override
markchien06889172020-01-20 19:31:56 +0800151 public void startTethering(TetheringRequestParcel request, String callerPkg,
152 IIntResultListener listener) {
markchien5788f2a2020-05-08 18:55:26 +0800153 if (checkAndNotifyCommonError(callerPkg,
154 request.exemptFromEntitlementCheck /* onlyAllowPrivileged */,
155 listener)) {
156 return;
157 }
markchien6d06f6d2019-12-16 20:15:20 +0800158
markchien06889172020-01-20 19:31:56 +0800159 mTethering.startTethering(request, listener);
markchien0df2ebc42019-09-30 14:40:57 +0800160 }
161
162 @Override
markchien6d06f6d2019-12-16 20:15:20 +0800163 public void stopTethering(int type, String callerPkg, IIntResultListener listener) {
164 if (checkAndNotifyCommonError(callerPkg, listener)) return;
165
166 try {
167 mTethering.stopTethering(type);
168 listener.onResult(TETHER_ERROR_NO_ERROR);
169 } catch (RemoteException e) { }
markchien0df2ebc42019-09-30 14:40:57 +0800170 }
171
172 @Override
173 public void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
markchien6d06f6d2019-12-16 20:15:20 +0800174 boolean showEntitlementUi, String callerPkg) {
175 if (checkAndNotifyCommonError(callerPkg, receiver)) return;
176
177 mTethering.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
markchien0df2ebc42019-09-30 14:40:57 +0800178 }
179
180 @Override
markchien6d06f6d2019-12-16 20:15:20 +0800181 public void registerTetheringEventCallback(ITetheringEventCallback callback,
182 String callerPkg) {
183 try {
markchien5788f2a2020-05-08 18:55:26 +0800184 if (!hasTetherAccessPermission()) {
markchien6d06f6d2019-12-16 20:15:20 +0800185 callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
186 return;
187 }
188 mTethering.registerTetheringEventCallback(callback);
189 } catch (RemoteException e) { }
markchien0df2ebc42019-09-30 14:40:57 +0800190 }
markchien6d06f6d2019-12-16 20:15:20 +0800191
192 @Override
193 public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
194 String callerPkg) {
195 try {
markchien5788f2a2020-05-08 18:55:26 +0800196 if (!hasTetherAccessPermission()) {
markchien6d06f6d2019-12-16 20:15:20 +0800197 callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
198 return;
199 }
200 mTethering.unregisterTetheringEventCallback(callback);
201 } catch (RemoteException e) { }
202 }
203
204 @Override
205 public void stopAllTethering(String callerPkg, IIntResultListener listener) {
206 if (checkAndNotifyCommonError(callerPkg, listener)) return;
207
208 try {
209 mTethering.untetherAll();
210 listener.onResult(TETHER_ERROR_NO_ERROR);
211 } catch (RemoteException e) { }
212 }
213
214 @Override
215 public void isTetheringSupported(String callerPkg, IIntResultListener listener) {
216 if (checkAndNotifyCommonError(callerPkg, listener)) return;
217
218 try {
219 listener.onResult(TETHER_ERROR_NO_ERROR);
220 } catch (RemoteException e) { }
221 }
222
223 @Override
224 protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
225 @Nullable String[] args) {
226 mTethering.dump(fd, writer, args);
227 }
228
229 private boolean checkAndNotifyCommonError(String callerPkg, IIntResultListener listener) {
markchien5788f2a2020-05-08 18:55:26 +0800230 return checkAndNotifyCommonError(callerPkg, false /* onlyAllowPrivileged */, listener);
231 }
232
233 private boolean checkAndNotifyCommonError(final String callerPkg,
234 final boolean onlyAllowPrivileged, final IIntResultListener listener) {
markchien6d06f6d2019-12-16 20:15:20 +0800235 try {
markchien5788f2a2020-05-08 18:55:26 +0800236 if (!hasTetherChangePermission(callerPkg, onlyAllowPrivileged)) {
markchien6d06f6d2019-12-16 20:15:20 +0800237 listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
238 return true;
239 }
240 if (!mService.isTetheringSupported()) {
241 listener.onResult(TETHER_ERROR_UNSUPPORTED);
242 return true;
243 }
244 } catch (RemoteException e) {
245 return true;
246 }
247
248 return false;
249 }
250
251 private boolean checkAndNotifyCommonError(String callerPkg, ResultReceiver receiver) {
markchien5788f2a2020-05-08 18:55:26 +0800252 if (!hasTetherChangePermission(callerPkg, false /* onlyAllowPrivileged */)) {
markchien6d06f6d2019-12-16 20:15:20 +0800253 receiver.send(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, null);
254 return true;
255 }
256 if (!mService.isTetheringSupported()) {
257 receiver.send(TETHER_ERROR_UNSUPPORTED, null);
258 return true;
259 }
260
261 return false;
262 }
263
markchien5788f2a2020-05-08 18:55:26 +0800264 private boolean hasTetherPrivilegedPermission() {
265 return mService.checkCallingOrSelfPermission(TETHER_PRIVILEGED) == PERMISSION_GRANTED;
266 }
267
268 private boolean hasTetherChangePermission(final String callerPkg,
269 final boolean onlyAllowPrivileged) {
270 if (hasTetherPrivilegedPermission()) return true;
271
272 if (onlyAllowPrivileged || mTethering.isTetherProvisioningRequired()) return false;
273
274 int uid = Binder.getCallingUid();
275 // If callerPkg's uid is not same as Binder.getCallingUid(),
276 // checkAndNoteWriteSettingsOperation will return false and the operation will be
277 // denied.
278 return Settings.checkAndNoteWriteSettingsOperation(mService, uid, callerPkg,
279 false /* throwException */);
280 }
281
282 private boolean hasTetherAccessPermission() {
283 if (hasTetherPrivilegedPermission()) return true;
284
285 return mService.checkCallingOrSelfPermission(
286 ACCESS_NETWORK_STATE) == PERMISSION_GRANTED;
287 }
markchien0df2ebc42019-09-30 14:40:57 +0800288 }
289
markchien6d06f6d2019-12-16 20:15:20 +0800290 // if ro.tether.denied = true we default to no tethering
291 // gservices could set the secure setting to 1 though to enable it on a build where it
292 // had previously been turned off.
293 private boolean isTetheringSupported() {
294 final int defaultVal =
295 SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
296 final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
297 Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
298 final boolean tetherEnabledInSettings = tetherSupported
299 && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
300
301 return tetherEnabledInSettings && mTethering.hasTetherableConfiguration();
markchien0df2ebc42019-09-30 14:40:57 +0800302 }
303
304 /**
305 * An injection method for testing.
306 */
307 @VisibleForTesting
308 public TetheringDependencies getTetheringDependencies() {
309 if (mDeps == null) {
310 mDeps = new TetheringDependencies() {
311 @Override
312 public NetworkRequest getDefaultNetworkRequest() {
markchien87d3f7d2020-01-08 20:58:23 +0800313 // TODO: b/147280869, add a proper system API to replace this.
314 final NetworkRequest trackDefaultRequest = new NetworkRequest.Builder()
315 .clearCapabilities()
316 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
317 .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
318 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
319 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
320 .build();
321 return trackDefaultRequest;
markchien0df2ebc42019-09-30 14:40:57 +0800322 }
323
324 @Override
325 public Looper getTetheringLooper() {
326 final HandlerThread tetherThread = new HandlerThread("android.tethering");
327 tetherThread.start();
328 return tetherThread.getLooper();
329 }
330
331 @Override
332 public boolean isTetheringSupported() {
markchien6d06f6d2019-12-16 20:15:20 +0800333 return TetheringService.this.isTetheringSupported();
markchien0df2ebc42019-09-30 14:40:57 +0800334 }
335
336 @Override
337 public Context getContext() {
338 return TetheringService.this;
339 }
markchien6d06f6d2019-12-16 20:15:20 +0800340
341 @Override
342 public IpServer.Dependencies getIpServerDependencies() {
343 return new IpServer.Dependencies() {
344 @Override
345 public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
346 DhcpServerCallbacks cb) {
347 try {
348 final INetworkStackConnector service = getNetworkStackConnector();
349 if (service == null) return;
350
351 service.makeDhcpServer(ifName, params, cb);
352 } catch (RemoteException e) {
markchien986750b2019-12-06 15:24:53 +0800353 Log.e(TAG, "Fail to make dhcp server");
354 try {
355 cb.onDhcpServerCreated(STATUS_UNKNOWN_ERROR, null);
356 } catch (RemoteException re) { }
markchien6d06f6d2019-12-16 20:15:20 +0800357 }
358 }
359 };
360 }
361
362 // TODO: replace this by NetworkStackClient#getRemoteConnector after refactoring
363 // networkStackClient.
364 static final int NETWORKSTACK_TIMEOUT_MS = 60_000;
365 private INetworkStackConnector getNetworkStackConnector() {
366 IBinder connector;
367 try {
368 final long before = System.currentTimeMillis();
Remi NGUYEN VAN438018d2020-03-18 18:31:39 +0900369 while ((connector = NetworkStack.getService()) == null) {
markchien6d06f6d2019-12-16 20:15:20 +0800370 if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
371 Log.wtf(TAG, "Timeout, fail to get INetworkStackConnector");
372 return null;
373 }
374 Thread.sleep(200);
375 }
376 } catch (InterruptedException e) {
377 Log.wtf(TAG, "Interrupted, fail to get INetworkStackConnector");
378 return null;
379 }
380 return INetworkStackConnector.Stub.asInterface(connector);
381 }
markchien3fe660b2019-12-05 12:04:59 +0800382
383 @Override
384 public BluetoothAdapter getBluetoothAdapter() {
385 return BluetoothAdapter.getDefaultAdapter();
386 }
markchien0df2ebc42019-09-30 14:40:57 +0800387 };
388 }
markchien0df2ebc42019-09-30 14:40:57 +0800389 return mDeps;
390 }
391}