blob: 020b32adcfd73df63f26855fffd59ef282f5a20e [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
17package com.android.server.connectivity.tethering;
18
markchien6d06f6d2019-12-16 20:15:20 +080019import static android.content.pm.PackageManager.PERMISSION_GRANTED;
20import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION;
21import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
22import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
23import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
markchien986750b2019-12-06 15:24:53 +080024import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR;
markchien6d06f6d2019-12-16 20:15:20 +080025
markchien0df2ebc42019-09-30 14:40:57 +080026import android.app.Service;
markchien3fe660b2019-12-05 12:04:59 +080027import android.bluetooth.BluetoothAdapter;
markchien0df2ebc42019-09-30 14:40:57 +080028import android.content.Context;
29import android.content.Intent;
markchien6d06f6d2019-12-16 20:15:20 +080030import android.net.IIntResultListener;
31import android.net.INetworkStackConnector;
markchien0df2ebc42019-09-30 14:40:57 +080032import android.net.ITetheringConnector;
markchien6d06f6d2019-12-16 20:15:20 +080033import android.net.ITetheringEventCallback;
markchien87d3f7d2020-01-08 20:58:23 +080034import android.net.NetworkCapabilities;
markchien0df2ebc42019-09-30 14:40:57 +080035import android.net.NetworkRequest;
markchien06889172020-01-20 19:31:56 +080036import android.net.TetheringRequestParcel;
markchien6d06f6d2019-12-16 20:15:20 +080037import android.net.dhcp.DhcpServerCallbacks;
38import android.net.dhcp.DhcpServingParamsParcel;
39import android.net.ip.IpServer;
markchien0df2ebc42019-09-30 14:40:57 +080040import android.net.util.SharedLog;
markchien6d06f6d2019-12-16 20:15:20 +080041import android.os.Binder;
markchien0df2ebc42019-09-30 14:40:57 +080042import android.os.HandlerThread;
43import android.os.IBinder;
44import android.os.Looper;
markchien6d06f6d2019-12-16 20:15:20 +080045import android.os.RemoteException;
markchien0df2ebc42019-09-30 14:40:57 +080046import android.os.ResultReceiver;
47import android.os.SystemProperties;
markchien6d06f6d2019-12-16 20:15:20 +080048import android.os.UserManager;
markchien0df2ebc42019-09-30 14:40:57 +080049import android.provider.Settings;
markchien6d06f6d2019-12-16 20:15:20 +080050import android.util.Log;
markchien0df2ebc42019-09-30 14:40:57 +080051
52import androidx.annotation.NonNull;
53import androidx.annotation.Nullable;
54
55import com.android.internal.annotations.VisibleForTesting;
56
57import java.io.FileDescriptor;
58import java.io.PrintWriter;
59
60/**
61 * Android service used to manage tethering.
62 *
63 * <p>The service returns a binder for the system server to communicate with the tethering.
64 */
65public class TetheringService extends Service {
66 private static final String TAG = TetheringService.class.getSimpleName();
67
68 private final SharedLog mLog = new SharedLog(TAG);
69 private TetheringConnector mConnector;
70 private Context mContext;
71 private TetheringDependencies mDeps;
72 private Tethering mTethering;
markchien6d06f6d2019-12-16 20:15:20 +080073 private UserManager mUserManager;
markchien0df2ebc42019-09-30 14:40:57 +080074
75 @Override
76 public void onCreate() {
77 mLog.mark("onCreate");
78 mDeps = getTetheringDependencies();
79 mContext = mDeps.getContext();
markchien6d06f6d2019-12-16 20:15:20 +080080 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
markchien5f7b3be2020-01-31 14:04:36 +080081 mTethering = makeTethering(mDeps);
markchien0df2ebc42019-09-30 14:40:57 +080082 }
83
84 /**
85 * Make a reference to Tethering object.
86 */
87 @VisibleForTesting
88 public Tethering makeTethering(TetheringDependencies deps) {
markchien771c3e92019-12-07 22:02:28 +080089 System.loadLibrary("tetherutilsjni");
markchien0df2ebc42019-09-30 14:40:57 +080090 return new Tethering(deps);
91 }
92
93 /**
94 * Create a binder connector for the system server to communicate with the tethering.
95 */
96 private synchronized IBinder makeConnector() {
97 if (mConnector == null) {
markchien6d06f6d2019-12-16 20:15:20 +080098 mConnector = new TetheringConnector(mTethering, TetheringService.this);
markchien0df2ebc42019-09-30 14:40:57 +080099 }
100 return mConnector;
101 }
102
103 @NonNull
104 @Override
105 public IBinder onBind(Intent intent) {
106 mLog.mark("onBind");
107 return makeConnector();
108 }
109
110 private static class TetheringConnector extends ITetheringConnector.Stub {
markchien6d06f6d2019-12-16 20:15:20 +0800111 private final TetheringService mService;
112 private final Tethering mTethering;
markchien0df2ebc42019-09-30 14:40:57 +0800113
markchien6d06f6d2019-12-16 20:15:20 +0800114 TetheringConnector(Tethering tether, TetheringService service) {
115 mTethering = tether;
116 mService = service;
markchien0df2ebc42019-09-30 14:40:57 +0800117 }
118
119 @Override
markchien6d06f6d2019-12-16 20:15:20 +0800120 public void tether(String iface, String callerPkg, IIntResultListener listener) {
121 if (checkAndNotifyCommonError(callerPkg, listener)) return;
122
123 try {
124 listener.onResult(mTethering.tether(iface));
125 } catch (RemoteException e) { }
markchien0df2ebc42019-09-30 14:40:57 +0800126 }
127
128 @Override
markchien6d06f6d2019-12-16 20:15:20 +0800129 public void untether(String iface, String callerPkg, IIntResultListener listener) {
130 if (checkAndNotifyCommonError(callerPkg, listener)) return;
131
132 try {
133 listener.onResult(mTethering.untether(iface));
134 } catch (RemoteException e) { }
markchien0df2ebc42019-09-30 14:40:57 +0800135 }
136
137 @Override
markchien6d06f6d2019-12-16 20:15:20 +0800138 public void setUsbTethering(boolean enable, String callerPkg, IIntResultListener listener) {
139 if (checkAndNotifyCommonError(callerPkg, listener)) return;
140
141 try {
142 listener.onResult(mTethering.setUsbTethering(enable));
143 } catch (RemoteException e) { }
markchien0df2ebc42019-09-30 14:40:57 +0800144 }
145
146 @Override
markchien06889172020-01-20 19:31:56 +0800147 public void startTethering(TetheringRequestParcel request, String callerPkg,
148 IIntResultListener listener) {
149 if (checkAndNotifyCommonError(callerPkg, listener)) return;
markchien6d06f6d2019-12-16 20:15:20 +0800150
markchien06889172020-01-20 19:31:56 +0800151 mTethering.startTethering(request, listener);
markchien0df2ebc42019-09-30 14:40:57 +0800152 }
153
154 @Override
markchien6d06f6d2019-12-16 20:15:20 +0800155 public void stopTethering(int type, String callerPkg, IIntResultListener listener) {
156 if (checkAndNotifyCommonError(callerPkg, listener)) return;
157
158 try {
159 mTethering.stopTethering(type);
160 listener.onResult(TETHER_ERROR_NO_ERROR);
161 } catch (RemoteException e) { }
markchien0df2ebc42019-09-30 14:40:57 +0800162 }
163
164 @Override
165 public void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
markchien6d06f6d2019-12-16 20:15:20 +0800166 boolean showEntitlementUi, String callerPkg) {
167 if (checkAndNotifyCommonError(callerPkg, receiver)) return;
168
169 mTethering.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
markchien0df2ebc42019-09-30 14:40:57 +0800170 }
171
172 @Override
markchien6d06f6d2019-12-16 20:15:20 +0800173 public void registerTetheringEventCallback(ITetheringEventCallback callback,
174 String callerPkg) {
175 try {
176 if (!mService.hasTetherAccessPermission()) {
177 callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
178 return;
179 }
180 mTethering.registerTetheringEventCallback(callback);
181 } catch (RemoteException e) { }
markchien0df2ebc42019-09-30 14:40:57 +0800182 }
markchien6d06f6d2019-12-16 20:15:20 +0800183
184 @Override
185 public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
186 String callerPkg) {
187 try {
188 if (!mService.hasTetherAccessPermission()) {
189 callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
190 return;
191 }
192 mTethering.unregisterTetheringEventCallback(callback);
193 } catch (RemoteException e) { }
194 }
195
196 @Override
197 public void stopAllTethering(String callerPkg, IIntResultListener listener) {
198 if (checkAndNotifyCommonError(callerPkg, listener)) return;
199
200 try {
201 mTethering.untetherAll();
202 listener.onResult(TETHER_ERROR_NO_ERROR);
203 } catch (RemoteException e) { }
204 }
205
206 @Override
207 public void isTetheringSupported(String callerPkg, IIntResultListener listener) {
208 if (checkAndNotifyCommonError(callerPkg, listener)) return;
209
210 try {
211 listener.onResult(TETHER_ERROR_NO_ERROR);
212 } catch (RemoteException e) { }
213 }
214
215 @Override
216 protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
217 @Nullable String[] args) {
218 mTethering.dump(fd, writer, args);
219 }
220
221 private boolean checkAndNotifyCommonError(String callerPkg, IIntResultListener listener) {
222 try {
223 if (!mService.hasTetherChangePermission(callerPkg)) {
224 listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
225 return true;
226 }
227 if (!mService.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
238 private boolean checkAndNotifyCommonError(String callerPkg, ResultReceiver receiver) {
239 if (!mService.hasTetherChangePermission(callerPkg)) {
240 receiver.send(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, null);
241 return true;
242 }
243 if (!mService.isTetheringSupported()) {
244 receiver.send(TETHER_ERROR_UNSUPPORTED, null);
245 return true;
246 }
247
248 return false;
249 }
250
markchien0df2ebc42019-09-30 14:40:57 +0800251 }
252
markchien6d06f6d2019-12-16 20:15:20 +0800253 // if ro.tether.denied = true we default to no tethering
254 // gservices could set the secure setting to 1 though to enable it on a build where it
255 // had previously been turned off.
256 private boolean isTetheringSupported() {
257 final int defaultVal =
258 SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
259 final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
260 Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
261 final boolean tetherEnabledInSettings = tetherSupported
262 && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
263
264 return tetherEnabledInSettings && mTethering.hasTetherableConfiguration();
markchien0df2ebc42019-09-30 14:40:57 +0800265 }
266
markchien6d06f6d2019-12-16 20:15:20 +0800267 private boolean hasTetherChangePermission(String callerPkg) {
268 if (checkCallingOrSelfPermission(
269 android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) {
270 return true;
271 }
272
273 if (mTethering.isTetherProvisioningRequired()) return false;
274
275
276 int uid = Binder.getCallingUid();
277 // If callerPkg's uid is not same as Binder.getCallingUid(),
278 // checkAndNoteWriteSettingsOperation will return false and the operation will be denied.
279 if (Settings.checkAndNoteWriteSettingsOperation(mContext, uid, callerPkg,
280 false /* throwException */)) {
281 return true;
282 }
283
284 return false;
285 }
286
287 private boolean hasTetherAccessPermission() {
288 if (checkCallingOrSelfPermission(
289 android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) {
290 return true;
291 }
292
293 if (checkCallingOrSelfPermission(
294 android.Manifest.permission.ACCESS_NETWORK_STATE) == PERMISSION_GRANTED) {
295 return true;
296 }
297
298 return false;
299 }
300
301
markchien0df2ebc42019-09-30 14:40:57 +0800302 /**
303 * An injection method for testing.
304 */
305 @VisibleForTesting
306 public TetheringDependencies getTetheringDependencies() {
307 if (mDeps == null) {
308 mDeps = new TetheringDependencies() {
309 @Override
310 public NetworkRequest getDefaultNetworkRequest() {
markchien87d3f7d2020-01-08 20:58:23 +0800311 // TODO: b/147280869, add a proper system API to replace this.
312 final NetworkRequest trackDefaultRequest = new NetworkRequest.Builder()
313 .clearCapabilities()
314 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
315 .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
316 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
317 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
318 .build();
319 return trackDefaultRequest;
markchien0df2ebc42019-09-30 14:40:57 +0800320 }
321
322 @Override
323 public Looper getTetheringLooper() {
324 final HandlerThread tetherThread = new HandlerThread("android.tethering");
325 tetherThread.start();
326 return tetherThread.getLooper();
327 }
328
329 @Override
330 public boolean isTetheringSupported() {
markchien6d06f6d2019-12-16 20:15:20 +0800331 return TetheringService.this.isTetheringSupported();
markchien0df2ebc42019-09-30 14:40:57 +0800332 }
333
334 @Override
335 public Context getContext() {
336 return TetheringService.this;
337 }
markchien6d06f6d2019-12-16 20:15:20 +0800338
339 @Override
340 public IpServer.Dependencies getIpServerDependencies() {
341 return new IpServer.Dependencies() {
342 @Override
343 public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
344 DhcpServerCallbacks cb) {
345 try {
346 final INetworkStackConnector service = getNetworkStackConnector();
347 if (service == null) return;
348
349 service.makeDhcpServer(ifName, params, cb);
350 } catch (RemoteException e) {
markchien986750b2019-12-06 15:24:53 +0800351 Log.e(TAG, "Fail to make dhcp server");
352 try {
353 cb.onDhcpServerCreated(STATUS_UNKNOWN_ERROR, null);
354 } catch (RemoteException re) { }
markchien6d06f6d2019-12-16 20:15:20 +0800355 }
356 }
357 };
358 }
359
360 // TODO: replace this by NetworkStackClient#getRemoteConnector after refactoring
361 // networkStackClient.
362 static final int NETWORKSTACK_TIMEOUT_MS = 60_000;
363 private INetworkStackConnector getNetworkStackConnector() {
364 IBinder connector;
365 try {
366 final long before = System.currentTimeMillis();
markchien67430df2020-01-14 18:25:33 +0800367 while ((connector = (IBinder) mContext.getSystemService(
markchien6d06f6d2019-12-16 20:15:20 +0800368 Context.NETWORK_STACK_SERVICE)) == null) {
369 if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
370 Log.wtf(TAG, "Timeout, fail to get INetworkStackConnector");
371 return null;
372 }
373 Thread.sleep(200);
374 }
375 } catch (InterruptedException e) {
376 Log.wtf(TAG, "Interrupted, fail to get INetworkStackConnector");
377 return null;
378 }
379 return INetworkStackConnector.Stub.asInterface(connector);
380 }
markchien3fe660b2019-12-05 12:04:59 +0800381
382 @Override
383 public BluetoothAdapter getBluetoothAdapter() {
384 return BluetoothAdapter.getDefaultAdapter();
385 }
markchien0df2ebc42019-09-30 14:40:57 +0800386 };
387 }
markchien0df2ebc42019-09-30 14:40:57 +0800388 return mDeps;
389 }
390}