1 /*
2  * Copyright (C) 2012 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.tradefed.device;
17 
18 import com.android.tradefed.log.LogUtil;
19 import com.android.tradefed.result.InputStreamSource;
20 import com.android.tradefed.util.SystemUtil;
21 
22 import com.google.errorprone.annotations.MustBeClosed;
23 
24 /**
25  * Class that collects logcat in background. Continues to capture logcat even if device goes
26  * offline then online.
27  */
28 public class LogcatReceiver implements ILogcatReceiver {
29     private BackgroundDeviceAction mDeviceAction;
30     private LargeOutputReceiver mReceiver;
31 
32     private static final String LOGCAT_DESC = "logcat";
33 
34     /**
35      * Creates an instance with any specified logcat command
36      * @param device the device to start logcat on
37      * @param logcatCmd the logcat command to run (including 'logcat' part), see details on
38      *        available options in logcat help message
39      * @param maxFileSize maximum file size, earlier lines will be discarded once size is reached
40      * @param logStartDelay the delay to wait after the device becomes online
41      */
LogcatReceiver(ITestDevice device, String logcatCmd, long maxFileSize, int logStartDelay)42     public LogcatReceiver(ITestDevice device, String logcatCmd,
43             long maxFileSize, int logStartDelay) {
44         mReceiver = new LargeOutputReceiver(LOGCAT_DESC, device.getSerialNumber(),
45                 maxFileSize);
46         // FIXME: remove mLogStartDelay. Currently delay starting logcat, as starting
47         // immediately after a device comes online has caused adb instability
48         mDeviceAction = new BackgroundDeviceAction(logcatCmd, LOGCAT_DESC, device,
49                 mReceiver, logStartDelay);
50     }
51 
52     /**
53      * Creates an instance with default logcat 'threadtime' format
54      * @param device the device to start logcat on
55      * @param maxFileSize maximum file size, earlier lines will be discarded once size is reached
56      * @param logStartDelay the delay to wait after the device becomes online
57      */
LogcatReceiver(ITestDevice device, long maxFileSize, int logStartDelay)58     public LogcatReceiver(ITestDevice device, long maxFileSize, int logStartDelay) {
59         this(device, getDefaultLogcatCmd(device), maxFileSize, logStartDelay);
60     }
61 
62     @Override
start()63     public void start() {
64         mDeviceAction.start();
65     }
66 
67     @Override
stop()68     public void stop() {
69         mDeviceAction.cancel();
70         mReceiver.cancel();
71         mReceiver.delete();
72     }
73 
74     @MustBeClosed
75     @Override
getLogcatData()76     public InputStreamSource getLogcatData() {
77         return mReceiver.getData();
78     }
79 
80     @MustBeClosed
81     @Override
getLogcatData(int maxBytes)82     public InputStreamSource getLogcatData(int maxBytes) {
83         return mReceiver.getData(maxBytes);
84     }
85 
86     @Override
getLogcatData(int maxBytes, int offset)87     public InputStreamSource getLogcatData(int maxBytes, int offset) {
88         return mReceiver.getData(maxBytes, offset);
89     }
90 
91     @Override
clear()92     public void clear() {
93         mReceiver.clear();
94     }
95 
96     /** Get the default logcat command, only append uid format if api level > 24. */
getDefaultLogcatCmd(ITestDevice device)97     public static String getDefaultLogcatCmd(ITestDevice device) {
98         String logcatCmd = "logcat -b all -v threadtime";
99         // Logcat format support UID started from api level 24.
100         try {
101             if (SystemUtil.isLocalMode() || device.getApiLevel() >= 24) {
102                 logcatCmd = logcatCmd + ",uid";
103             }
104         } catch (DeviceNotAvailableException e) {
105             LogUtil.CLog.e("Use logcat command without UID format due to: ");
106             LogUtil.CLog.e(e);
107         }
108 
109         return logcatCmd;
110     }
111 }
112