1/* 2 * Copyright (C) 2013 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#define LOG_TAG "MediaLog" 18//#define LOG_NDEBUG 0 19 20#include <sys/mman.h> 21#include <utils/Log.h> 22#include <binder/PermissionCache.h> 23#include <media/nbaio/NBLog.h> 24#include <private/android_filesystem_config.h> 25#include "MediaLogService.h" 26 27namespace android { 28 29static const char kDeadlockedString[] = "MediaLogService may be deadlocked\n"; 30 31void MediaLogService::registerWriter(const sp<IMemory>& shared, size_t size, const char *name) 32{ 33 if (IPCThreadState::self()->getCallingUid() != AID_AUDIOSERVER || shared == 0 || 34 size < kMinSize || size > kMaxSize || name == NULL || 35 shared->size() < NBLog::Timeline::sharedSize(size)) { 36 return; 37 } 38 sp<NBLog::Reader> reader(new NBLog::Reader(size, shared)); 39 NamedReader namedReader(reader, name); 40 Mutex::Autolock _l(mLock); 41 mNamedReaders.add(namedReader); 42} 43 44void MediaLogService::unregisterWriter(const sp<IMemory>& shared) 45{ 46 if (IPCThreadState::self()->getCallingUid() != AID_AUDIOSERVER || shared == 0) { 47 return; 48 } 49 Mutex::Autolock _l(mLock); 50 for (size_t i = 0; i < mNamedReaders.size(); ) { 51 if (mNamedReaders[i].reader()->isIMemory(shared)) { 52 mNamedReaders.removeAt(i); 53 } else { 54 i++; 55 } 56 } 57} 58 59bool MediaLogService::dumpTryLock(Mutex& mutex) 60{ 61 bool locked = false; 62 for (int i = 0; i < kDumpLockRetries; ++i) { 63 if (mutex.tryLock() == NO_ERROR) { 64 locked = true; 65 break; 66 } 67 usleep(kDumpLockSleepUs); 68 } 69 return locked; 70} 71 72status_t MediaLogService::dump(int fd, const Vector<String16>& args __unused) 73{ 74 // FIXME merge with similar but not identical code at services/audioflinger/ServiceUtilities.cpp 75 static const String16 sDump("android.permission.DUMP"); 76 if (!(IPCThreadState::self()->getCallingUid() == AID_AUDIOSERVER || 77 PermissionCache::checkCallingPermission(sDump))) { 78 dprintf(fd, "Permission Denial: can't dump media.log from pid=%d, uid=%d\n", 79 IPCThreadState::self()->getCallingPid(), 80 IPCThreadState::self()->getCallingUid()); 81 return NO_ERROR; 82 } 83 84 Vector<NamedReader> namedReaders; 85 { 86 bool locked = dumpTryLock(mLock); 87 88 // failed to lock - MediaLogService is probably deadlocked 89 if (!locked) { 90 String8 result(kDeadlockedString); 91 if (fd >= 0) { 92 write(fd, result.string(), result.size()); 93 } else { 94 ALOGW("%s:", result.string()); 95 } 96 return NO_ERROR; 97 } 98 namedReaders = mNamedReaders; 99 mLock.unlock(); 100 } 101 102 for (size_t i = 0; i < namedReaders.size(); i++) { 103 const NamedReader& namedReader = namedReaders[i]; 104 if (fd >= 0) { 105 dprintf(fd, "\n%s:\n", namedReader.name()); 106 } else { 107 ALOGI("%s:", namedReader.name()); 108 } 109 namedReader.reader()->dump(fd, 0 /*indent*/); 110 } 111 return NO_ERROR; 112} 113 114status_t MediaLogService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, 115 uint32_t flags) 116{ 117 return BnMediaLogService::onTransact(code, data, reply, flags); 118} 119 120} // namespace android 121