1/*
2 * Copyright (C) 2008 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.dumpeventlog;
18
19import com.android.ddmlib.AdbCommandRejectedException;
20import com.android.ddmlib.AndroidDebugBridge;
21import com.android.ddmlib.IDevice;
22import com.android.ddmlib.Log;
23import com.android.ddmlib.TimeoutException;
24import com.android.ddmlib.Log.ILogOutput;
25import com.android.ddmlib.Log.LogLevel;
26import com.android.ddmlib.log.LogReceiver;
27import com.android.ddmlib.log.LogReceiver.ILogListener;
28import com.android.ddmlib.log.LogReceiver.LogEntry;
29
30import java.io.FileNotFoundException;
31import java.io.FileOutputStream;
32import java.io.IOException;
33
34/**
35 * Connects to a device using ddmlib and dumps its event log as long as the device is connected.
36 */
37public class DumpEventLog {
38
39    /**
40     * Custom {@link ILogListener} to receive and save the event log raw output.
41     */
42    private static class LogWriter implements ILogListener {
43        private FileOutputStream mOutputStream;
44        private LogReceiver mReceiver;
45
46        public LogWriter(String filePath) throws IOException {
47            mOutputStream = new FileOutputStream(filePath);
48        }
49
50        public void newData(byte[] data, int offset, int length) {
51            try {
52                mOutputStream.write(data, offset, length);
53            } catch (IOException e) {
54                if (mReceiver != null) {
55                    mReceiver.cancel();
56                }
57                System.out.println(e);
58            }
59        }
60
61        public void newEntry(LogEntry entry) {
62            // pass
63        }
64
65        public void setReceiver(LogReceiver receiver) {
66            mReceiver = receiver;
67        }
68
69        public void done() throws IOException {
70            mOutputStream.close();
71        }
72    }
73
74    public static void main(String[] args) {
75        if (args.length != 2) {
76            System.out.println("Usage: dumpeventlog <device s/n> <filepath>");
77            return;
78        }
79
80        // redirect the log output to /dev/null
81        Log.setLogOutput(new ILogOutput() {
82            public void printAndPromptLog(LogLevel logLevel, String tag, String message) {
83                // pass
84            }
85
86            public void printLog(LogLevel logLevel, String tag, String message) {
87                // pass
88            }
89        });
90
91        // init the lib
92        AndroidDebugBridge.init(false /* debugger support */);
93
94        try {
95            AndroidDebugBridge bridge = AndroidDebugBridge.createBridge();
96
97            // we can't just ask for the device list right away, as the internal thread getting
98            // them from ADB may not be done getting the first list.
99            // Since we don't really want getDevices() to be blocking, we wait here manually.
100            int count = 0;
101            while (bridge.hasInitialDeviceList() == false) {
102                try {
103                    Thread.sleep(100);
104                    count++;
105                } catch (InterruptedException e) {
106                    // pass
107                }
108
109                // let's not wait > 10 sec.
110                if (count > 100) {
111                    System.err.println("Timeout getting device list!");
112                    return;
113                }
114            }
115
116            // now get the devices
117            IDevice[] devices = bridge.getDevices();
118
119            for (IDevice device : devices) {
120                if (device.getSerialNumber().equals(args[0])) {
121                    try {
122                        grabLogFrom(device, args[1]);
123                    } catch (FileNotFoundException e) {
124                        e.printStackTrace();
125                    } catch (Exception e) {
126                        e.printStackTrace();
127                    }
128                    return;
129                }
130            }
131
132            System.err.println("Could not find " + args[0]);
133        } finally {
134            AndroidDebugBridge.terminate();
135        }
136    }
137
138    private static void grabLogFrom(IDevice device, String filePath) throws IOException,
139            TimeoutException, AdbCommandRejectedException {
140        LogWriter writer = new LogWriter(filePath);
141        LogReceiver receiver = new LogReceiver(writer);
142        writer.setReceiver(receiver);
143
144        device.runEventLogService(receiver);
145
146        writer.done();
147    }
148}
149