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