1 /* 2 * Copyright (C) 2022 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 17 #include <android-base/file.h> 18 #include <log/log.h> 19 #include <mutex> 20 21 namespace android { 22 namespace hardware { 23 namespace contexthub { 24 25 /** 26 * Class to help request and synchronize dumping CHRE debug information. 27 */ 28 class DebugDumpHelper { 29 public: ~DebugDumpHelper()30 virtual ~DebugDumpHelper() {} 31 32 /** 33 * Implementation specific method to send a debug dump request. 34 * 35 * @return true on a successful request, false otherwise. 36 */ 37 virtual bool requestDebugDump() = 0; 38 39 /** 40 * Implementation specific method to write a string to a debug file. 41 * Note that this function must only be called after a debug dump request 42 * has been initiated via 'startDebugDump()'. 43 * 44 * @param str String to be written to the debug dump file. MUST be NULL 45 * terminated. 46 */ 47 virtual void writeToDebugFile(const char *str) = 0; 48 49 /** 50 * Optional implementation specific method to write any debug info private to 51 * said implementation. 52 * Note that this function must only be called after a debug dump request 53 * has been initiated via 'startDebugDump()'. 54 */ debugDumpFinish()55 virtual void debugDumpFinish() {} 56 checkDebugFd()57 bool checkDebugFd() { 58 return mDebugFd != kInvalidFd; 59 } 60 getDebugFd()61 int getDebugFd() const { 62 return mDebugFd; 63 } 64 invalidateDebugFd()65 void invalidateDebugFd() { 66 mDebugFd = kInvalidFd; 67 } 68 69 /** 70 * Initiate a debug dump request. 71 * 72 * @param fd Posix file descriptor to write debug information into. 73 */ debugDumpStart(int fd)74 void debugDumpStart(int fd) { 75 // Timeout inside CHRE is typically 5 seconds, grant 500ms extra here to let 76 // the data reach us 77 constexpr auto kDebugDumpTimeout = std::chrono::milliseconds(5500); 78 mDebugFd = fd; 79 if (mDebugFd < 0) { 80 ALOGW("Can't dump debug info to invalid fd %d", mDebugFd); 81 } else { 82 writeToDebugFile("-- Dumping CHRE debug info --\n"); 83 84 ALOGV("Sending debug dump request"); 85 std::unique_lock<std::mutex> lock(mDebugDumpMutex); 86 mDebugDumpPending = true; 87 if (!requestDebugDump()) { 88 ALOGW("Couldn't send debug dump request"); 89 } else { 90 mDebugDumpCond.wait_for(lock, kDebugDumpTimeout, 91 [this]() { return !mDebugDumpPending; }); 92 if (mDebugDumpPending) { 93 ALOGE("Timed out waiting on debug dump data"); 94 mDebugDumpPending = false; 95 } 96 } 97 } 98 } 99 100 /** 101 * Append to a debug dump file asynchronously. Note that a call to this 102 * function will only go through if a debug dump request was already 103 * initiated via debugDumpStart(). 104 * 105 * @param str Debug string to append to the file. 106 */ debugDumpAppend(std::string & str)107 void debugDumpAppend(std::string &str) { 108 if (mDebugFd == kInvalidFd) { 109 ALOGW("Got unexpected debug dump data message"); 110 } else { 111 writeToDebugFile(str.c_str()); 112 } 113 } 114 115 /** 116 * Called at the end of a debug dump request. 117 */ debugDumpComplete()118 void debugDumpComplete() { 119 std::lock_guard<std::mutex> lock(mDebugDumpMutex); 120 if (!mDebugDumpPending) { 121 ALOGI("Ignoring duplicate/unsolicited debug dump response"); 122 } else { 123 mDebugDumpPending = false; 124 mDebugDumpCond.notify_all(); 125 invalidateDebugFd(); 126 } 127 } 128 129 private: 130 static constexpr int kInvalidFd = -1; 131 int mDebugFd = kInvalidFd; 132 bool mDebugDumpPending = false; 133 std::mutex mDebugDumpMutex; 134 std::condition_variable mDebugDumpCond; 135 }; 136 137 } // namespace contexthub 138 } // namespace hardware 139 } // namespace android