19c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase/* 29c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * Copyright (C) 2011 The Android Open Source Project 39c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * 49c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * Licensed under the Apache License, Version 2.0 (the "License"); 59c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * you may not use this file except in compliance with the License. 69c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * You may obtain a copy of the License at 79c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * 89c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * http://www.apache.org/licenses/LICENSE-2.0 99c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * 109c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * Unless required by applicable law or agreed to in writing, software 119c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * distributed under the License is distributed on an "AS IS" BASIS, 129c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * See the License for the specific language governing permissions and 149c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * limitations under the License. 159c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase */ 169c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase 179c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase#include "DisplayListLogBuffer.h" 189c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase 199c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase// BUFFER_SIZE size must be one more than a multiple of COMMAND_SIZE to ensure 209c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase// that mStart always points at the next command, not just the next item 219c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase#define NUM_COMMANDS 50 222af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik#define BUFFER_SIZE ((NUM_COMMANDS) + 1) 239c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase 249c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase/** 259c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * DisplayListLogBuffer is a utility class which logs the most recent display 269c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * list operations in a circular buffer. The log is process-wide, because we 279c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * only care about the most recent operations, not the operations on a per-window 289c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * basis for a given activity. The purpose of the log is to provide more debugging 299c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * information in a bug report, by telling us not just where a process hung (which 309c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * generally is just reported as a stack trace at the Java level) or crashed, but 319c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * also what happened immediately before that hang or crash. This may help track down 329c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * problems in the native rendering code or driver interaction related to the display 339c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * list operations that led up to the hang or crash. 349c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * 359c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * The log is implemented as a circular buffer for both space and performance 369c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * reasons - we only care about the last several operations to give us context 379c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * leading up to the problem, and we don't want to constantly copy data around or do 389c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * additional mallocs to keep the most recent operations logged. Only numbers are 399c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * logged to make the operation fast. If and when the log is output, we process this 409c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * data into meaningful strings. 419c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * 429c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * There is an assumption about the format of the command (currently 2 ints: the 439c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * opcode and the nesting level). If the type of information logged changes (for example, 449c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * we may want to save a timestamp), then the size of the buffer and the way the 459c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * information is recorded in writeCommand() should change to suit. 469c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase */ 479c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase 489c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haasenamespace android { 499c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase 509c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase#ifdef USE_OPENGL_RENDERER 519c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haaseusing namespace uirenderer; 529c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet HaaseANDROID_SINGLETON_STATIC_INSTANCE(DisplayListLogBuffer); 539c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase#endif 549c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase 559c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haasenamespace uirenderer { 569c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase 579c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase 589c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet HaaseDisplayListLogBuffer::DisplayListLogBuffer() { 592af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik mBufferFirst = (OpLog*) malloc(BUFFER_SIZE * sizeof(OpLog)); 609c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase mStart = mBufferFirst; 619c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase mBufferLast = mBufferFirst + BUFFER_SIZE - 1; 629c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase mEnd = mStart; 639c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase} 649c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase 659c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet HaaseDisplayListLogBuffer::~DisplayListLogBuffer() { 669c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase free(mBufferFirst); 679c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase} 689c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase 699c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase/** 709c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * Called from DisplayListRenderer to output the current buffer into the 719c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * specified FILE. This only happens in a dumpsys/bugreport operation. 729c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase */ 732af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craikvoid DisplayListLogBuffer::outputCommands(FILE *file) 749c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase{ 752af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik OpLog* tmpBufferPtr = mStart; 769c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase while (true) { 779c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase if (tmpBufferPtr == mEnd) { 789c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase break; 799c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase } 80d4b43b3cf3ee109a5251228dcc1d9bc3c25ff150Chris Craik 81d4b43b3cf3ee109a5251228dcc1d9bc3c25ff150Chris Craik fprintf(file, "%*s%s\n", 2 * tmpBufferPtr->level, "", tmpBufferPtr->label); 82d4b43b3cf3ee109a5251228dcc1d9bc3c25ff150Chris Craik 832af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik OpLog* nextOp = tmpBufferPtr++; 849c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase if (tmpBufferPtr > mBufferLast) { 859c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase tmpBufferPtr = mBufferFirst; 869c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase } 872af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik } 889c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase} 899c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase 909c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase/** 912af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik * Store the given level and label in the buffer and increment/wrap the mEnd 922af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik * and mStart values as appropriate. Label should point to static memory. 939c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase */ 942af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craikvoid DisplayListLogBuffer::writeCommand(int level, const char* label) { 952af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik mEnd->level = level; 962af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik mEnd->label = label; 972af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 989c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase if (mEnd == mBufferLast) { 999c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase mEnd = mBufferFirst; 1009c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase } else { 1019c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase mEnd++; 1029c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase } 1039c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase if (mEnd == mStart) { 1049c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase mStart++; 1059c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase if (mStart > mBufferLast) { 1069c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase mStart = mBufferFirst; 1079c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase } 1089c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase } 1099c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase} 1109c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase 1119c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase}; // namespace uirenderer 1129c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase}; // namespace android 113