1 /* 2 * Copyright (C) 2018 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 package com.android.server.adb; 17 18 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; 19 20 import android.annotation.NonNull; 21 import android.annotation.UserIdInt; 22 import android.content.ContentResolver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.PackageManager; 26 import android.database.ContentObserver; 27 import android.debug.AdbManager; 28 import android.debug.AdbManagerInternal; 29 import android.debug.AdbTransportType; 30 import android.debug.FingerprintAndPairDevice; 31 import android.debug.IAdbCallback; 32 import android.debug.IAdbManager; 33 import android.debug.IAdbTransport; 34 import android.debug.PairDevice; 35 import android.hardware.usb.UsbManager; 36 import android.net.Uri; 37 import android.os.Binder; 38 import android.os.IBinder; 39 import android.os.ParcelFileDescriptor; 40 import android.os.RemoteCallbackList; 41 import android.os.RemoteException; 42 import android.os.SystemProperties; 43 import android.os.UserHandle; 44 import android.provider.Settings; 45 import android.service.adb.AdbServiceDumpProto; 46 import android.sysprop.AdbProperties; 47 import android.util.ArrayMap; 48 import android.util.ArraySet; 49 import android.util.Slog; 50 import android.util.proto.ProtoOutputStream; 51 52 import com.android.internal.util.DumpUtils; 53 import com.android.internal.util.IndentingPrintWriter; 54 import com.android.internal.util.Preconditions; 55 import com.android.internal.util.dump.DualDumpOutputStream; 56 import com.android.server.FgThread; 57 import com.android.server.LocalServices; 58 import com.android.server.SystemService; 59 import com.android.server.testharness.TestHarnessModeService; 60 61 import java.io.File; 62 import java.io.FileDescriptor; 63 import java.io.PrintWriter; 64 import java.util.Collections; 65 import java.util.Map; 66 import java.util.concurrent.atomic.AtomicInteger; 67 68 /** 69 * The Android Debug Bridge (ADB) service. This controls the availability of ADB and authorization 70 * of devices allowed to connect to ADB. 71 */ 72 public class AdbService extends IAdbManager.Stub { 73 /** 74 * Adb native daemon. 75 */ 76 static final String ADBD = "adbd"; 77 78 /** 79 * Command to start native service. 80 */ 81 static final String CTL_START = "ctl.start"; 82 83 /** 84 * Command to start native service. 85 */ 86 static final String CTL_STOP = "ctl.stop"; 87 88 // The tcp port adb is currently using 89 AtomicInteger mConnectionPort = new AtomicInteger(-1); 90 91 private final AdbConnectionPortListener mPortListener = new AdbConnectionPortListener(); 92 private AdbDebuggingManager.AdbConnectionPortPoller mConnectionPortPoller; 93 94 private final RemoteCallbackList<IAdbCallback> mCallbacks = new RemoteCallbackList<>(); 95 /** 96 * Manages the service lifecycle for {@code AdbService} in {@code SystemServer}. 97 */ 98 public static class Lifecycle extends SystemService { 99 private AdbService mAdbService; 100 Lifecycle(Context context)101 public Lifecycle(Context context) { 102 super(context); 103 } 104 105 @Override onStart()106 public void onStart() { 107 mAdbService = new AdbService(getContext()); 108 publishBinderService(Context.ADB_SERVICE, mAdbService); 109 } 110 111 @Override onBootPhase(int phase)112 public void onBootPhase(int phase) { 113 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { 114 mAdbService.systemReady(); 115 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { 116 FgThread.getHandler().sendMessage(obtainMessage( 117 AdbService::bootCompleted, mAdbService)); 118 } 119 } 120 } 121 122 private class AdbManagerInternalImpl extends AdbManagerInternal { 123 @Override registerTransport(IAdbTransport transport)124 public void registerTransport(IAdbTransport transport) { 125 mTransports.put(transport.asBinder(), transport); 126 } 127 128 @Override unregisterTransport(IAdbTransport transport)129 public void unregisterTransport(IAdbTransport transport) { 130 mTransports.remove(transport.asBinder()); 131 } 132 133 @Override isAdbEnabled(byte transportType)134 public boolean isAdbEnabled(byte transportType) { 135 if (transportType == AdbTransportType.USB) { 136 return mIsAdbUsbEnabled; 137 } else if (transportType == AdbTransportType.WIFI) { 138 return mIsAdbWifiEnabled; 139 } 140 throw new IllegalArgumentException( 141 "isAdbEnabled called with unimplemented transport type=" + transportType); 142 } 143 144 @Override getAdbKeysFile()145 public File getAdbKeysFile() { 146 return mDebuggingManager == null ? null : mDebuggingManager.getUserKeyFile(); 147 } 148 149 @Override getAdbTempKeysFile()150 public File getAdbTempKeysFile() { 151 return mDebuggingManager == null ? null : mDebuggingManager.getAdbTempKeysFile(); 152 } 153 154 @Override notifyKeyFilesUpdated()155 public void notifyKeyFilesUpdated() { 156 if (mDebuggingManager == null) { 157 return; 158 } 159 mDebuggingManager.notifyKeyFilesUpdated(); 160 } 161 162 @Override startAdbdForTransport(byte transportType)163 public void startAdbdForTransport(byte transportType) { 164 FgThread.getHandler().sendMessage(obtainMessage( 165 AdbService::setAdbdEnabledForTransport, AdbService.this, true, transportType)); 166 } 167 168 @Override stopAdbdForTransport(byte transportType)169 public void stopAdbdForTransport(byte transportType) { 170 FgThread.getHandler().sendMessage(obtainMessage( 171 AdbService::setAdbdEnabledForTransport, AdbService.this, false, transportType)); 172 } 173 } 174 registerContentObservers()175 private void registerContentObservers() { 176 try { 177 // register observer to listen for settings changes 178 mObserver = new AdbSettingsObserver(); 179 mContentResolver.registerContentObserver( 180 Settings.Global.getUriFor(Settings.Global.ADB_ENABLED), 181 false, mObserver); 182 mContentResolver.registerContentObserver( 183 Settings.Global.getUriFor(Settings.Global.ADB_WIFI_ENABLED), 184 false, mObserver); 185 } catch (Exception e) { 186 Slog.e(TAG, "Error in registerContentObservers", e); 187 } 188 } 189 containsFunction(String functions, String function)190 private static boolean containsFunction(String functions, String function) { 191 int index = functions.indexOf(function); 192 if (index < 0) return false; 193 if (index > 0 && functions.charAt(index - 1) != ',') return false; 194 int charAfter = index + function.length(); 195 if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false; 196 return true; 197 } 198 199 private class AdbSettingsObserver extends ContentObserver { 200 private final Uri mAdbUsbUri = Settings.Global.getUriFor(Settings.Global.ADB_ENABLED); 201 private final Uri mAdbWifiUri = Settings.Global.getUriFor(Settings.Global.ADB_WIFI_ENABLED); 202 AdbSettingsObserver()203 AdbSettingsObserver() { 204 super(null); 205 } 206 207 @Override onChange(boolean selfChange, @NonNull Uri uri, @UserIdInt int userId)208 public void onChange(boolean selfChange, @NonNull Uri uri, @UserIdInt int userId) { 209 if (mAdbUsbUri.equals(uri)) { 210 boolean shouldEnable = (Settings.Global.getInt(mContentResolver, 211 Settings.Global.ADB_ENABLED, 0) > 0); 212 FgThread.getHandler().sendMessage(obtainMessage( 213 AdbService::setAdbEnabled, AdbService.this, shouldEnable, 214 AdbTransportType.USB)); 215 } else if (mAdbWifiUri.equals(uri)) { 216 boolean shouldEnable = (Settings.Global.getInt(mContentResolver, 217 Settings.Global.ADB_WIFI_ENABLED, 0) > 0); 218 FgThread.getHandler().sendMessage(obtainMessage( 219 AdbService::setAdbEnabled, AdbService.this, shouldEnable, 220 AdbTransportType.WIFI)); 221 } 222 } 223 } 224 225 private static final String TAG = "AdbService"; 226 private static final boolean DEBUG = false; 227 228 /** 229 * The persistent property which stores whether adb is enabled or not. 230 * May also contain vendor-specific default functions for testing purposes. 231 */ 232 private static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config"; 233 private static final String WIFI_PERSISTENT_CONFIG_PROPERTY = "persist.adb.tls_server.enable"; 234 235 private final Context mContext; 236 private final ContentResolver mContentResolver; 237 private final ArrayMap<IBinder, IAdbTransport> mTransports = new ArrayMap<>(); 238 239 private boolean mIsAdbUsbEnabled; 240 private boolean mIsAdbWifiEnabled; 241 private AdbDebuggingManager mDebuggingManager; 242 243 private ContentObserver mObserver; 244 AdbService(Context context)245 private AdbService(Context context) { 246 mContext = context; 247 mContentResolver = context.getContentResolver(); 248 mDebuggingManager = new AdbDebuggingManager(context); 249 250 registerContentObservers(); 251 LocalServices.addService(AdbManagerInternal.class, new AdbManagerInternalImpl()); 252 } 253 254 /** 255 * Called in response to {@code SystemService.PHASE_ACTIVITY_MANAGER_READY} from {@code 256 * SystemServer}. 257 */ systemReady()258 public void systemReady() { 259 if (DEBUG) Slog.d(TAG, "systemReady"); 260 261 /* 262 * Use the normal bootmode persistent prop to maintain state of adb across 263 * all boot modes. 264 */ 265 mIsAdbUsbEnabled = containsFunction( 266 SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY, ""), 267 UsbManager.USB_FUNCTION_ADB); 268 boolean shouldEnableAdbUsb = mIsAdbUsbEnabled 269 || SystemProperties.getBoolean( 270 TestHarnessModeService.TEST_HARNESS_MODE_PROPERTY, false); 271 mIsAdbWifiEnabled = "1".equals( 272 SystemProperties.get(WIFI_PERSISTENT_CONFIG_PROPERTY, "0")); 273 274 // make sure the ADB_ENABLED setting value matches the current state 275 try { 276 Settings.Global.putInt(mContentResolver, 277 Settings.Global.ADB_ENABLED, shouldEnableAdbUsb ? 1 : 0); 278 Settings.Global.putInt(mContentResolver, 279 Settings.Global.ADB_WIFI_ENABLED, mIsAdbWifiEnabled ? 1 : 0); 280 } catch (SecurityException e) { 281 // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't be changed. 282 Slog.d(TAG, "ADB_ENABLED is restricted."); 283 } 284 } 285 286 /** 287 * Called in response to {@code SystemService.PHASE_BOOT_COMPLETED} from {@code SystemServer}. 288 */ bootCompleted()289 public void bootCompleted() { 290 if (DEBUG) Slog.d(TAG, "boot completed"); 291 if (mDebuggingManager != null) { 292 mDebuggingManager.setAdbEnabled(mIsAdbUsbEnabled, AdbTransportType.USB); 293 mDebuggingManager.setAdbEnabled(mIsAdbWifiEnabled, AdbTransportType.WIFI); 294 } 295 } 296 297 @Override allowDebugging(boolean alwaysAllow, @NonNull String publicKey)298 public void allowDebugging(boolean alwaysAllow, @NonNull String publicKey) { 299 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null); 300 Preconditions.checkStringNotEmpty(publicKey); 301 if (mDebuggingManager != null) { 302 mDebuggingManager.allowDebugging(alwaysAllow, publicKey); 303 } 304 } 305 306 @Override denyDebugging()307 public void denyDebugging() { 308 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null); 309 if (mDebuggingManager != null) { 310 mDebuggingManager.denyDebugging(); 311 } 312 } 313 314 @Override clearDebuggingKeys()315 public void clearDebuggingKeys() { 316 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null); 317 if (mDebuggingManager != null) { 318 mDebuggingManager.clearDebuggingKeys(); 319 } else { 320 throw new RuntimeException("Cannot clear ADB debugging keys, " 321 + "AdbDebuggingManager not enabled"); 322 } 323 } 324 325 /** 326 * @return true if the device supports secure ADB over Wi-Fi or Ethernet. 327 * @hide 328 */ 329 @Override isAdbWifiSupported()330 public boolean isAdbWifiSupported() { 331 mContext.enforceCallingPermission( 332 android.Manifest.permission.MANAGE_DEBUGGING, "AdbService"); 333 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI) || 334 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_ETHERNET); 335 } 336 337 /** 338 * @return true if the device supports secure ADB over Wi-Fi and device pairing by 339 * QR code. 340 * @hide 341 */ 342 @Override isAdbWifiQrSupported()343 public boolean isAdbWifiQrSupported() { 344 mContext.enforceCallingPermission( 345 android.Manifest.permission.MANAGE_DEBUGGING, "AdbService"); 346 return isAdbWifiSupported() && mContext.getPackageManager().hasSystemFeature( 347 PackageManager.FEATURE_CAMERA_ANY); 348 } 349 350 @Override allowWirelessDebugging(boolean alwaysAllow, @NonNull String bssid)351 public void allowWirelessDebugging(boolean alwaysAllow, @NonNull String bssid) { 352 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null); 353 Preconditions.checkStringNotEmpty(bssid); 354 if (mDebuggingManager != null) { 355 mDebuggingManager.allowWirelessDebugging(alwaysAllow, bssid); 356 } 357 } 358 359 @Override denyWirelessDebugging()360 public void denyWirelessDebugging() { 361 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null); 362 if (mDebuggingManager != null) { 363 mDebuggingManager.denyWirelessDebugging(); 364 } 365 } 366 367 @Override getPairedDevices()368 public FingerprintAndPairDevice[] getPairedDevices() { 369 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null); 370 if (mDebuggingManager == null) { 371 return null; 372 } 373 Map<String, PairDevice> map = mDebuggingManager.getPairedDevices(); 374 FingerprintAndPairDevice[] ret = new FingerprintAndPairDevice[map.size()]; 375 int i = 0; 376 for (Map.Entry<String, PairDevice> entry : map.entrySet()) { 377 ret[i] = new FingerprintAndPairDevice(); 378 ret[i].keyFingerprint = entry.getKey(); 379 ret[i].device = entry.getValue(); 380 i++; 381 } 382 return ret; 383 } 384 385 @Override unpairDevice(@onNull String fingerprint)386 public void unpairDevice(@NonNull String fingerprint) { 387 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null); 388 Preconditions.checkStringNotEmpty(fingerprint); 389 if (mDebuggingManager != null) { 390 mDebuggingManager.unpairDevice(fingerprint); 391 } 392 } 393 394 @Override enablePairingByPairingCode()395 public void enablePairingByPairingCode() { 396 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null); 397 if (mDebuggingManager != null) { 398 mDebuggingManager.enablePairingByPairingCode(); 399 } 400 } 401 402 @Override enablePairingByQrCode(@onNull String serviceName, @NonNull String password)403 public void enablePairingByQrCode(@NonNull String serviceName, @NonNull String password) { 404 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null); 405 Preconditions.checkStringNotEmpty(serviceName); 406 Preconditions.checkStringNotEmpty(password); 407 if (mDebuggingManager != null) { 408 mDebuggingManager.enablePairingByQrCode(serviceName, password); 409 } 410 } 411 412 @Override disablePairing()413 public void disablePairing() { 414 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null); 415 if (mDebuggingManager != null) { 416 mDebuggingManager.disablePairing(); 417 } 418 } 419 420 @Override getAdbWirelessPort()421 public int getAdbWirelessPort() { 422 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null); 423 if (mDebuggingManager != null) { 424 return mDebuggingManager.getAdbWirelessPort(); 425 } 426 // If ro.adb.secure=0 427 return mConnectionPort.get(); 428 } 429 430 @Override registerCallback(IAdbCallback callback)431 public void registerCallback(IAdbCallback callback) throws RemoteException { 432 if (DEBUG) { 433 Slog.d(TAG, "Registering callback " + callback); 434 } 435 mCallbacks.register(callback); 436 } 437 438 @Override unregisterCallback(IAdbCallback callback)439 public void unregisterCallback(IAdbCallback callback) throws RemoteException { 440 if (DEBUG) { 441 Slog.d(TAG, "Unregistering callback " + callback); 442 } 443 mCallbacks.unregister(callback); 444 } 445 /** 446 * This listener is only used when ro.adb.secure=0. Otherwise, AdbDebuggingManager will 447 * do this. 448 */ 449 class AdbConnectionPortListener implements AdbDebuggingManager.AdbConnectionPortListener { onPortReceived(int port)450 public void onPortReceived(int port) { 451 if (port > 0 && port <= 65535) { 452 mConnectionPort.set(port); 453 } else { 454 mConnectionPort.set(-1); 455 // Turn off wifi debugging, since the server did not start. 456 try { 457 Settings.Global.putInt(mContentResolver, 458 Settings.Global.ADB_WIFI_ENABLED, 0); 459 } catch (SecurityException e) { 460 // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't 461 // be changed. 462 Slog.d(TAG, "ADB_ENABLED is restricted."); 463 } 464 } 465 broadcastPortInfo(mConnectionPort.get()); 466 } 467 } 468 broadcastPortInfo(int port)469 private void broadcastPortInfo(int port) { 470 Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION); 471 intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, (port >= 0) 472 ? AdbManager.WIRELESS_STATUS_CONNECTED 473 : AdbManager.WIRELESS_STATUS_DISCONNECTED); 474 intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port); 475 AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL); 476 Slog.i(TAG, "sent port broadcast port=" + port); 477 } 478 startAdbd()479 private void startAdbd() { 480 SystemProperties.set(CTL_START, ADBD); 481 } 482 stopAdbd()483 private void stopAdbd() { 484 if (!mIsAdbUsbEnabled && !mIsAdbWifiEnabled) { 485 SystemProperties.set(CTL_STOP, ADBD); 486 } 487 } 488 setAdbdEnabledForTransport(boolean enable, byte transportType)489 private void setAdbdEnabledForTransport(boolean enable, byte transportType) { 490 if (transportType == AdbTransportType.USB) { 491 mIsAdbUsbEnabled = enable; 492 } else if (transportType == AdbTransportType.WIFI) { 493 mIsAdbWifiEnabled = enable; 494 } 495 if (enable) { 496 startAdbd(); 497 } else { 498 stopAdbd(); 499 } 500 } 501 setAdbEnabled(boolean enable, byte transportType)502 private void setAdbEnabled(boolean enable, byte transportType) { 503 if (DEBUG) { 504 Slog.d(TAG, "setAdbEnabled(" + enable + "), mIsAdbUsbEnabled=" + mIsAdbUsbEnabled 505 + ", mIsAdbWifiEnabled=" + mIsAdbWifiEnabled + ", transportType=" 506 + transportType); 507 } 508 509 if (transportType == AdbTransportType.USB && enable != mIsAdbUsbEnabled) { 510 mIsAdbUsbEnabled = enable; 511 } else if (transportType == AdbTransportType.WIFI && enable != mIsAdbWifiEnabled) { 512 mIsAdbWifiEnabled = enable; 513 if (mIsAdbWifiEnabled) { 514 if (!AdbProperties.secure().orElse(false) && mDebuggingManager == null) { 515 // Start adbd. If this is secure adb, then we defer enabling adb over WiFi. 516 SystemProperties.set(WIFI_PERSISTENT_CONFIG_PROPERTY, "1"); 517 mConnectionPortPoller = 518 new AdbDebuggingManager.AdbConnectionPortPoller(mPortListener); 519 mConnectionPortPoller.start(); 520 } 521 } else { 522 // Stop adb over WiFi. 523 SystemProperties.set(WIFI_PERSISTENT_CONFIG_PROPERTY, "0"); 524 if (mConnectionPortPoller != null) { 525 mConnectionPortPoller.cancelAndWait(); 526 mConnectionPortPoller = null; 527 } 528 } 529 } else { 530 // No change 531 return; 532 } 533 534 if (enable) { 535 startAdbd(); 536 } else { 537 stopAdbd(); 538 } 539 540 for (IAdbTransport transport : mTransports.values()) { 541 try { 542 transport.onAdbEnabled(enable, transportType); 543 } catch (RemoteException e) { 544 Slog.w(TAG, "Unable to send onAdbEnabled to transport " + transport.toString()); 545 } 546 } 547 548 if (mDebuggingManager != null) { 549 mDebuggingManager.setAdbEnabled(enable, transportType); 550 } 551 552 if (DEBUG) { 553 Slog.d(TAG, "Broadcasting enable = " + enable + ", type = " + transportType); 554 } 555 mCallbacks.broadcast((callback) -> { 556 if (DEBUG) { 557 Slog.d(TAG, "Sending enable = " + enable + ", type = " + transportType 558 + " to " + callback); 559 } 560 try { 561 callback.onDebuggingChanged(enable, transportType); 562 } catch (RemoteException ex) { 563 if (DEBUG) { 564 Slog.d(TAG, "Unable to send onDebuggingChanged:", ex); 565 } 566 } 567 }); 568 } 569 570 @Override handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out, ParcelFileDescriptor err, String[] args)571 public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out, 572 ParcelFileDescriptor err, String[] args) { 573 return new AdbShellCommand(this).exec( 574 this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), 575 args); 576 } 577 578 @Override dump(FileDescriptor fd, PrintWriter writer, String[] args)579 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 580 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return; 581 582 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 583 final long ident = Binder.clearCallingIdentity(); 584 try { 585 ArraySet<String> argsSet = new ArraySet<>(); 586 Collections.addAll(argsSet, args); 587 588 boolean dumpAsProto = false; 589 if (argsSet.contains("--proto")) { 590 dumpAsProto = true; 591 } 592 593 if (argsSet.size() == 0 || argsSet.contains("-a") || dumpAsProto) { 594 DualDumpOutputStream dump; 595 if (dumpAsProto) { 596 dump = new DualDumpOutputStream(new ProtoOutputStream(fd)); 597 } else { 598 pw.println("ADB MANAGER STATE (dumpsys adb):"); 599 600 dump = new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")); 601 } 602 603 if (mDebuggingManager != null) { 604 mDebuggingManager.dump(dump, "debugging_manager", 605 AdbServiceDumpProto.DEBUGGING_MANAGER); 606 } 607 608 dump.flush(); 609 } else { 610 pw.println("Dump current ADB state"); 611 pw.println(" No commands available"); 612 } 613 } finally { 614 Binder.restoreCallingIdentity(ident); 615 } 616 } 617 } 618