diff options
56 files changed, 962 insertions, 1657 deletions
diff --git a/cmds/keystore/Android.mk b/cmds/keystore/Android.mk index 67dd9f8679..5a9b979c64 100644 --- a/cmds/keystore/Android.mk +++ b/cmds/keystore/Android.mk @@ -14,8 +14,6 @@ # limitations under the License. # -ifneq ($(TARGET_SIMULATOR),true) - LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) @@ -32,5 +30,3 @@ LOCAL_SHARED_LIBRARIES := libcutils libcrypto LOCAL_MODULE:= keystore_cli LOCAL_MODULE_TAGS := debug include $(BUILD_EXECUTABLE) - -endif diff --git a/cmds/runtime/Android.mk b/cmds/runtime/Android.mk deleted file mode 100644 index 6a72d10708..0000000000 --- a/cmds/runtime/Android.mk +++ /dev/null @@ -1,30 +0,0 @@ -ifeq ($(TARGET_SIMULATOR),true) - -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - ServiceManager.cpp \ - SignalHandler.cpp \ - main_runtime.cpp - -LOCAL_SHARED_LIBRARIES := \ - libutils \ - libbinder \ - libandroid_runtime \ - libcutils \ - libui \ - libsystem_server \ - libhardware_legacy - -LOCAL_C_INCLUDES := \ - $(JNI_H_INCLUDE) - -ifeq ($(TARGET_OS),linux) - LOCAL_CFLAGS += -DXP_UNIX -endif - -LOCAL_MODULE:= runtime - -include $(BUILD_EXECUTABLE) -endif diff --git a/cmds/runtime/MODULE_LICENSE_APACHE2 b/cmds/runtime/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29bb2..0000000000 --- a/cmds/runtime/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/cmds/runtime/NOTICE b/cmds/runtime/NOTICE deleted file mode 100644 index c5b1efa7aa..0000000000 --- a/cmds/runtime/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/cmds/runtime/ServiceManager.cpp b/cmds/runtime/ServiceManager.cpp deleted file mode 100644 index b2bef07ff7..0000000000 --- a/cmds/runtime/ServiceManager.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright 2005 The Android Open Source Project -// - -#define LOG_TAG "ServiceManager" - -#include "ServiceManager.h" -#include "SignalHandler.h" - -#include <utils/Debug.h> -#include <utils/Log.h> -#include <binder/Parcel.h> -#include <utils/String8.h> -#include <binder/ProcessState.h> - -#include <private/utils/Static.h> - -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/stat.h> - -namespace android { - -BServiceManager::BServiceManager() -{ -} - -sp<IBinder> BServiceManager::getService(const String16& name) const -{ - AutoMutex _l(mLock); - ssize_t i = mServices.indexOfKey(name); - LOGV("ServiceManager: getService(%s) -> %d\n", String8(name).string(), i); - if (i >= 0) return mServices.valueAt(i); - return NULL; -} - -sp<IBinder> BServiceManager::checkService(const String16& name) const -{ - AutoMutex _l(mLock); - ssize_t i = mServices.indexOfKey(name); - LOGV("ServiceManager: getService(%s) -> %d\n", String8(name).string(), i); - if (i >= 0) return mServices.valueAt(i); - return NULL; -} - -status_t BServiceManager::addService(const String16& name, const sp<IBinder>& service) -{ - AutoMutex _l(mLock); - LOGI("ServiceManager: addService(%s, %p)\n", String8(name).string(), service.get()); - const ssize_t res = mServices.add(name, service); - if (res >= NO_ERROR) { - mChanged.broadcast(); - return NO_ERROR; - } - return res; -} - -Vector<String16> BServiceManager::listServices() -{ - Vector<String16> res; - - AutoMutex _l(mLock); - const size_t N = mServices.size(); - for (size_t i=0; i<N; i++) { - res.add(mServices.keyAt(i)); - } - - return res; -} - -}; // namespace android diff --git a/cmds/runtime/ServiceManager.h b/cmds/runtime/ServiceManager.h deleted file mode 100644 index 090ca6de64..0000000000 --- a/cmds/runtime/ServiceManager.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright 2005 The Android Open Source Project -// -#ifndef ANDROID_SERVICE_MANAGER_H -#define ANDROID_SERVICE_MANAGER_H - -#include <binder/IServiceManager.h> -#include <utils/KeyedVector.h> -#include <utils/threads.h> - -namespace android { - -// ---------------------------------------------------------------------- - -class BServiceManager : public BnServiceManager -{ -public: - BServiceManager(); - - virtual sp<IBinder> getService( const String16& name) const; - virtual sp<IBinder> checkService( const String16& name) const; - virtual status_t addService( const String16& name, - const sp<IBinder>& service); - virtual Vector<String16> listServices(); - - -private: - mutable Mutex mLock; - mutable Condition mChanged; - sp<IPermissionController> mPermissionController; - KeyedVector<String16, sp<IBinder> > mServices; -}; - -// ---------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_SERVICE_MANAGER_H diff --git a/cmds/runtime/SignalHandler.cpp b/cmds/runtime/SignalHandler.cpp deleted file mode 100644 index cccaabfc57..0000000000 --- a/cmds/runtime/SignalHandler.cpp +++ /dev/null @@ -1,249 +0,0 @@ -// -// Copyright 2005 The Android Open Source Project -// - -#define LOG_TAG "SignalHandler" - -#include "SignalHandler.h" - -#include <utils/Atomic.h> -#include <utils/Debug.h> -#include <utils/Log.h> - -#include <errno.h> -#include <sys/wait.h> -#include <unistd.h> - -namespace android { - -class SignalHandler::ProcessThread : public Thread -{ -public: - ProcessThread(SignalHandler& sh) - : Thread(false) - , mOwner(sh) - { - } - - virtual bool threadLoop() - { - char buffer[32]; - read(mOwner.mAvailMsg[0], buffer, sizeof(buffer)); - - LOGV("Signal command processing thread woke up!"); - - if (mOwner.mLostCommands) { - LOGE("Lost %d signals!", mOwner.mLostCommands); - mOwner.mLostCommands = 0; - } - - int cur; - while ((cur=mOwner.mCommandBottom) != mOwner.mCommandTop) { - if (mOwner.mCommands[cur].filled == 0) { - LOGV("Command at %d is not yet filled", cur); - break; - } - - LOGV("Processing command at %d, top is %d", - cur, mOwner.mCommandTop); - processCommand(mOwner.mCommands[cur]); - mOwner.mCommands[cur].filled = 0; - - int next = mOwner.mCommandBottom+1; - if (next >= COMMAND_QUEUE_SIZE) { - next = 0; - } - - mOwner.mCommandBottom = next; - } - - return true; - } - - void processCommand(const CommandEntry& entry) - { - switch (entry.signum) { - case SIGCHLD: { - mOwner.mLock.lock(); - ssize_t i = mOwner.mChildHandlers.indexOfKey(entry.info.si_pid); - ChildHandler ch; - if (i >= 0) { - ch = mOwner.mChildHandlers.valueAt(i); - mOwner.mChildHandlers.removeItemsAt(i); - } - mOwner.mLock.unlock(); - - LOGD("SIGCHLD: pid=%d, handle index=%d", entry.info.si_pid, i); - - if (i >= 0) { - int res = waitpid(entry.info.si_pid, NULL, WNOHANG); - LOGW_IF(res == 0, - "Received SIGCHLD, but pid %d is not yet stopped", - entry.info.si_pid); - if (ch.handler) { - ch.handler(entry.info.si_pid, ch.userData); - } - } else { - LOGW("Unhandled SIGCHLD for pid %d", entry.info.si_pid); - } - } break; - } - } - - SignalHandler& mOwner; -}; - - -Mutex SignalHandler::mInstanceLock; -SignalHandler* SignalHandler::mInstance = NULL; - -status_t SignalHandler::setChildHandler(pid_t childPid, - int tag, - child_callback_t handler, - void* userData) -{ - SignalHandler* const self = getInstance(); - - self->mLock.lock(); - - // First make sure this child hasn't already exited. - pid_t res = waitpid(childPid, NULL, WNOHANG); - if (res != 0) { - if (res < 0) { - LOGW("setChildHandler waitpid of %d failed: %d (%s)", - childPid, res, strerror(errno)); - } else { - LOGW("setChildHandler waitpid of %d said %d already dead", - childPid, res); - } - - // Some kind of error... just handle the exit now. - self->mLock.unlock(); - - if (handler) { - handler(childPid, userData); - } - - // Return an error code -- 0 means it already exited. - return (status_t)res; - } - - ChildHandler entry; - entry.childPid = childPid; - entry.tag = tag; - entry.handler = handler; - entry.userData = userData; - - // Note: this replaces an existing entry for this pid, if there already - // is one. This is the required behavior. - LOGD("setChildHandler adding pid %d, tag %d, handler %p, data %p", - childPid, tag, handler, userData); - self->mChildHandlers.add(childPid, entry); - - self->mLock.unlock(); - - return NO_ERROR; -} - -void SignalHandler::killAllChildren(int tag) -{ - SignalHandler* const self = getInstance(); - - AutoMutex _l (self->mLock); - const size_t N = self->mChildHandlers.size(); - for (size_t i=0; i<N; i++) { - const ChildHandler& ch(self->mChildHandlers.valueAt(i)); - if (tag == 0 || ch.tag == tag) { - const pid_t pid = ch.childPid; - LOGI("Killing child %d (tag %d)\n", pid, ch.tag); - kill(pid, SIGKILL); - } - } -} - -SignalHandler::SignalHandler() - : mCommandTop(0) - , mCommandBottom(0) - , mLostCommands(0) -{ - memset(mCommands, 0, sizeof(mCommands)); - - int res = pipe(mAvailMsg); - LOGE_IF(res != 0, "Unable to create signal handler pipe: %s", strerror(errno)); - - mProcessThread = new ProcessThread(*this); - mProcessThread->run("SignalHandler", PRIORITY_HIGHEST); - - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sa.sa_sigaction = sigAction; - sa.sa_flags = SA_NOCLDSTOP|SA_SIGINFO; - sigaction(SIGCHLD, &sa, NULL); -} - -SignalHandler::~SignalHandler() -{ -} - -SignalHandler* SignalHandler::getInstance() -{ - AutoMutex _l(mInstanceLock); - if (mInstance == NULL) { - mInstance = new SignalHandler(); - } - return mInstance; -} - -void SignalHandler::sigAction(int signum, siginfo_t* info, void*) -{ - static const char wakeupMsg[1] = { 0xff }; - - // If our signal handler is being called, then we know we have - // already initialized the SignalHandler class and thus mInstance - // is valid. - SignalHandler* const self = mInstance; - - // XXX This is not safe! - #if 0 - LOGV("Signal %d: signo=%d, errno=%d, code=%d, pid=%d\n", - signum, - info->si_signo, info->si_errno, info->si_code, - info->si_pid); - #endif - - int32_t oldTop, newTop; - - // Find the next command slot... - do { - oldTop = self->mCommandTop; - - newTop = oldTop + 1; - if (newTop >= COMMAND_QUEUE_SIZE) { - newTop = 0; - } - - if (newTop == self->mCommandBottom) { - // The buffer is filled up! Ouch! - // XXX This is not safe! - #if 0 - LOGE("Command buffer overflow! newTop=%d\n", newTop); - #endif - android_atomic_add(1, &self->mLostCommands); - write(self->mAvailMsg[1], wakeupMsg, sizeof(wakeupMsg)); - return; - } - } while(android_atomic_cmpxchg(oldTop, newTop, &(self->mCommandTop))); - - // Fill in the command data... - self->mCommands[oldTop].signum = signum; - self->mCommands[oldTop].info = *info; - - // And now make this command available. - self->mCommands[oldTop].filled = 1; - - // Wake up the processing thread. - write(self->mAvailMsg[1], wakeupMsg, sizeof(wakeupMsg)); -} - -}; // namespace android - diff --git a/cmds/runtime/SignalHandler.h b/cmds/runtime/SignalHandler.h deleted file mode 100644 index 7f4ef8e4e8..0000000000 --- a/cmds/runtime/SignalHandler.h +++ /dev/null @@ -1,137 +0,0 @@ -// -// Copyright 2005 The Android Open Source Project -// -#ifndef ANDROID_SIGNAL_HANDLER_H -#define ANDROID_SIGNAL_HANDLER_H - -#include <utils/KeyedVector.h> -#include <utils/threads.h> - -#include <signal.h> - -namespace android { - -// ---------------------------------------------------------------------- - -enum { - DEFAULT_PROCESS_TAG = 1 -}; - -class SignalHandler -{ -public: - typedef void (*child_callback_t)(pid_t child, void* userData); - - /** - * Set a handler for when a child process exits. By calling - * this, a waitpid() will be done when the child exits to remove - * it from the zombie state. You can also optionally specify a - * handler to be called when the child exits. - * - * If there is already a handler for this child process, it is - * replaced by this new handler. In this case the old handler's - * function is not called. - * - * @param childPid Process ID of child to watch. - * @param childTag User-defined tag for this child. Must be - * greater than zero. - * @param handler If non-NULL, this will be called when the - * child exits. It may be called in either a - * separate signal handling thread, or - * immediately if the child has already exited. - * @param userData Propageted as-is to handler. - * - * @return status_t NO_ERROR if all is well. - */ - static status_t setChildHandler(pid_t childPid, - int childTag = DEFAULT_PROCESS_TAG, - child_callback_t handler = NULL, - void* userData = NULL); - - /** - * Kill all of the child processes for which we have a waiting - * handler, whose tag is the given value. If tag is 0, all - * children are killed. - * - * @param tag - */ - static void killAllChildren(int tag = 0); - -private: - SignalHandler(); - ~SignalHandler(); - - static SignalHandler* getInstance(); - - static void sigAction(int, siginfo_t*, void*); - - // -------------------------------------------------- - // Shared state... all of this is protected by mLock. - // -------------------------------------------------- - - mutable Mutex mLock; - - struct ChildHandler - { - pid_t childPid; - int tag; - child_callback_t handler; - void* userData; - }; - KeyedVector<pid_t, ChildHandler> mChildHandlers; - - // -------------------------------------------------- - // Commmand queue... data is inserted by the signal - // handler using atomic ops, and retrieved by the - // signal processing thread. Because these are touched - // by the signal handler, no lock is used. - // -------------------------------------------------- - - enum { - COMMAND_QUEUE_SIZE = 64 - }; - struct CommandEntry - { - int filled; - int signum; - siginfo_t info; - }; - - // The top of the queue. This is incremented atomically by the - // signal handler before placing a command in the queue. - volatile int32_t mCommandTop; - - // The bottom of the queue. Only modified by the processing - // thread; the signal handler reads it only to determine if the - // queue is full. - int32_t mCommandBottom; - - // Incremented each time we receive a signal and don't have room - // for it on the command queue. - volatile int32_t mLostCommands; - - // The command processing thread. - class ProcessThread; - sp<Thread> mProcessThread; - - // Pipe used to tell command processing thread when new commands. - // are available. The thread blocks on the read end, the signal - // handler writes when it enqueues new commands. - int mAvailMsg[2]; - - // The commands. - CommandEntry mCommands[COMMAND_QUEUE_SIZE]; - - // -------------------------------------------------- - // Singleton. - // -------------------------------------------------- - - static Mutex mInstanceLock; - static SignalHandler* mInstance; -}; - -// ---------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_SIGNAL_HANDLER_H diff --git a/cmds/runtime/main_runtime.cpp b/cmds/runtime/main_runtime.cpp deleted file mode 100644 index dbff095f65..0000000000 --- a/cmds/runtime/main_runtime.cpp +++ /dev/null @@ -1,515 +0,0 @@ -// -// Copyright 2005 The Android Open Source Project -// -// Main entry point for runtime. -// - -#include "ServiceManager.h" -#include "SignalHandler.h" - -#include <utils/threads.h> -#include <utils/Errors.h> - -#include <binder/IPCThreadState.h> -#include <binder/ProcessState.h> -#include <utils/Log.h> -#include <cutils/zygote.h> - -#include <cutils/properties.h> - -#include <private/utils/Static.h> - -#include <surfaceflinger/ISurfaceComposer.h> - -#include <android_runtime/AndroidRuntime.h> - -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <getopt.h> -#include <signal.h> -#include <errno.h> -#include <sys/stat.h> -#include <linux/capability.h> -#include <linux/ioctl.h> -#ifdef HAVE_ANDROID_OS -# include <linux/android_alarm.h> -#endif - -#undef LOG_TAG -#define LOG_TAG "runtime" - -static const char* ZYGOTE_ARGV[] = { - "--setuid=1000", - "--setgid=1000", - "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003", - /* CAP_SYS_TTY_CONFIG & CAP_SYS_RESOURCE & CAP_NET_BROADCAST & - * CAP_NET_ADMIN & CAP_NET_RAW & CAP_NET_BIND_SERVICE & CAP_KILL & - * CAP_SYS_BOOT CAP_SYS_NICE - */ - "--capabilities=96549920,96549920", - "--runtime-init", - "--nice-name=system_server", - "com.android.server.SystemServer" -}; - -using namespace android; - -extern "C" status_t system_init(); - -enum { - SYSTEM_PROCESS_TAG = DEFAULT_PROCESS_TAG+1 -}; - -extern Mutex gEventQMutex; -extern Condition gEventQCondition; - -namespace android { - -extern void set_finish_init_func(void (*func)()); - - -/** - * This class is used to kill this process (runtime) when the system_server dies. - */ -class GrimReaper : public IBinder::DeathRecipient { -public: - GrimReaper() { } - - virtual void binderDied(const wp<IBinder>& who) - { - LOGI("Grim Reaper killing runtime..."); - kill(getpid(), SIGKILL); - } -}; - -extern void QuickTests(); - -/* - * Print usage info. - */ -static void usage(const char* argv0) -{ - fprintf(stderr, - "Usage: runtime [-g gamma] [-l logfile] [-n] [-s]\n" - " [-j app-component] [-v app-verb] [-d app-data]\n" - "\n" - "-l: File to send log messages to\n" - "-n: Don't print to stdout/stderr\n" - "-s: Force single-process mode\n" - "-j: Custom home app component name\n" - "-v: Custom home app intent verb\n" - "-d: Custom home app intent data\n" - ); - exit(1); -} - -// Selected application to run. -static const char* gInitialApplication = NULL; -static const char* gInitialVerb = NULL; -static const char* gInitialData = NULL; - -static void writeStringToParcel(Parcel& parcel, const char* str) -{ - if (str) { - parcel.writeString16(String16(str)); - } else { - parcel.writeString16(NULL, 0); - } -} - -/* - * Starting point for program logic. - * - * Returns with an exit status code (0 on success, nonzero on error). - */ -static int run(sp<ProcessState>& proc) -{ - // Temporary hack to call startRunning() on the activity manager. - sp<IServiceManager> sm = defaultServiceManager(); - sp<IBinder> am; - while ((am = sm->getService(String16("activity"))) == NULL) { - LOGI("Waiting for activity manager..."); - } - Parcel data, reply; - // XXX Need to also supply a package name for this to work again. - // IActivityManager::getInterfaceDescriptor() is the token for invoking on this interface; - // hardcoding it here avoids having to link with the full Activity Manager library - data.writeInterfaceToken(String16("android.app.IActivityManager")); - writeStringToParcel(data, NULL); - writeStringToParcel(data, gInitialApplication); - writeStringToParcel(data, gInitialVerb); - writeStringToParcel(data, gInitialData); -LOGI("run() sending FIRST_CALL_TRANSACTION to activity manager"); - am->transact(IBinder::FIRST_CALL_TRANSACTION, data, &reply); - - if (proc->supportsProcesses()) { - // Now we link to the Activity Manager waiting for it to die. If it does kill ourself. - // initd will restart this process and bring the system back up. - sp<GrimReaper> grim = new GrimReaper(); - am->linkToDeath(grim, grim.get(), 0); - - // Now join the thread pool. Note this is needed so that the message enqueued in the driver - // for the linkToDeath gets processed. - IPCThreadState::self()->joinThreadPool(); - } else { - // Keep this thread running forever... - while (1) { - usleep(100000); - } - } - return 1; -} - - -}; // namespace android - - -/* - * Post-system-process initialization. - * - * This function continues initialization after the system process - * has been initialized. It needs to be separate because the system - * initialization needs to care of starting the Android runtime if it is not - * running in its own process, which doesn't return until the runtime is - * being shut down. So it will call back to here from inside of Dalvik, - * to allow us to continue booting up. - */ -static void finish_system_init(sp<ProcessState>& proc) -{ - // If we are running multiprocess, we now need to have the - // thread pool started here. We don't do this in boot_init() - // because when running single process we need to start the - // thread pool after the Android runtime has been started (so - // the pool uses Dalvik threads). - if (proc->supportsProcesses()) { - proc->startThreadPool(); - } -} - - -// This function can be used to enforce security to different -// root contexts. For now, we just give every access. -static bool contextChecker( - const String16& name, const sp<IBinder>& caller, void* userData) -{ - return true; -} - -/* - * Initialization of boot services. - * - * This is where we perform initialization of all of our low-level - * boot services. Most importantly, here we become the context - * manager and use that to publish the service manager that will provide - * access to all other services. - */ -static void boot_init() -{ - LOGI("Entered boot_init()!\n"); - - sp<ProcessState> proc(ProcessState::self()); - LOGD("ProcessState: %p\n", proc.get()); - proc->becomeContextManager(contextChecker, NULL); - - if (proc->supportsProcesses()) { - LOGI("Binder driver opened. Multiprocess enabled.\n"); - } else { - LOGI("Binder driver not found. Processes not supported.\n"); - } - - sp<BServiceManager> sm = new BServiceManager; - proc->setContextObject(sm); -} - -/* - * Redirect stdin/stdout/stderr to /dev/null. - */ -static void redirectStdFds(void) -{ - int fd = open("/dev/null", O_RDWR, 0); - if (fd < 0) { - LOGW("Unable to open /dev/null: %s\n", strerror(errno)); - } else { - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - close(fd); - } -} - -static int hasDir(const char* dir) -{ - struct stat s; - int res = stat(dir, &s); - if (res == 0) { - return S_ISDIR(s.st_mode); - } - return 0; -} - -static void validateTime() -{ -#if HAVE_ANDROID_OS - int fd; - int res; - time_t min_time = 1167652800; // jan 1 2007, type 'date -ud "1/1 12:00" +%s' to get value for current year - struct timespec ts; - - fd = open("/dev/alarm", O_RDWR); - if(fd < 0) { - LOGW("Unable to open alarm driver: %s\n", strerror(errno)); - return; - } - res = ioctl(fd, ANDROID_ALARM_GET_TIME(ANDROID_ALARM_RTC_WAKEUP), &ts); - if(res < 0) { - LOGW("Unable to read rtc, %s\n", strerror(errno)); - } - else if(ts.tv_sec >= min_time) { - goto done; - } - LOGW("Invalid time detected, %ld set to %ld\n", ts.tv_sec, min_time); - ts.tv_sec = min_time; - ts.tv_nsec = 0; - res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts); - if(res < 0) { - LOGW("Unable to set rtc to %ld: %s\n", ts.tv_sec, strerror(errno)); - } -done: - close(fd); -#endif -} - -#ifndef HAVE_ANDROID_OS -class QuickRuntime : public AndroidRuntime -{ -public: - QuickRuntime() {} - - virtual void onStarted() - { - printf("QuickRuntime: onStarted\n"); - } -}; -#endif - -static status_t start_process(const char* name); - -static void restart_me(pid_t child, void* userData) -{ - start_process((const char*)userData); -} - -static status_t start_process(const char* name) -{ - String8 path(name); - Vector<const char*> args; - String8 leaf(path.getPathLeaf()); - String8 parentDir(path.getPathDir()); - args.insertAt(leaf.string(), 0); - args.add(parentDir.string()); - args.add(NULL); - pid_t child = fork(); - if (child < 0) { - status_t err = errno; - LOGE("*** fork of child %s failed: %s", leaf.string(), strerror(err)); - return -errno; - } else if (child == 0) { - LOGI("Executing: %s", path.string()); - execv(path.string(), const_cast<char**>(args.array())); - int err = errno; - LOGE("Exec failed: %s\n", strerror(err)); - _exit(err); - } else { - SignalHandler::setChildHandler(child, DEFAULT_PROCESS_TAG, - restart_me, (void*)name); - } - return -errno; -} - -/* - * Application entry point. - * - * Parse arguments, set some values, and pass control off to Run(). - * - * This is redefined to "SDL_main" on SDL simulator builds, and - * "runtime_main" on wxWidgets builds. - */ -extern "C" -int main(int argc, char* const argv[]) -{ - bool singleProcess = false; - const char* logFile = NULL; - int ic; - int result = 1; - pid_t systemPid; - - sp<ProcessState> proc; - -#ifndef HAVE_ANDROID_OS - /* Set stdout/stderr to unbuffered for MinGW/MSYS. */ - //setvbuf(stdout, NULL, _IONBF, 0); - //setvbuf(stderr, NULL, _IONBF, 0); - - LOGI("commandline args:\n"); - for (int i = 0; i < argc; i++) - LOGI(" %2d: '%s'\n", i, argv[i]); -#endif - - while (1) { - ic = getopt(argc, argv, "g:j:v:d:l:ns"); - if (ic < 0) - break; - - switch (ic) { - case 'g': - break; - case 'j': - gInitialApplication = optarg; - break; - case 'v': - gInitialVerb = optarg; - break; - case 'd': - gInitialData = optarg; - break; - case 'l': - logFile = optarg; - break; - case 'n': - redirectStdFds(); - break; - case 's': - singleProcess = true; - break; - case '?': - default: - LOGE("runtime: unrecognized flag -%c\n", ic); - usage(argv[0]); - break; - } - } - if (optind < argc) { - LOGE("runtime: extra stuff: %s\n", argv[optind]); - usage(argv[0]); - } - - if (singleProcess) { - ProcessState::setSingleProcess(true); - } - - if (logFile != NULL) { - android_logToFile(NULL, logFile); - } - - /* - * Set up ANDROID_* environment variables. - * - * TODO: the use of $ANDROID_PRODUCT_OUT will go away soon. - */ - static const char* kSystemDir = "/system"; - static const char* kDataDir = "/data"; - static const char* kAppSubdir = "/app"; - const char* out = NULL; -#ifndef HAVE_ANDROID_OS - //out = getenv("ANDROID_PRODUCT_OUT"); -#endif - if (out == NULL) - out = ""; - - char* systemDir = (char*) malloc(strlen(out) + strlen(kSystemDir) +1); - char* dataDir = (char*) malloc(strlen(out) + strlen(kDataDir) +1); - - sprintf(systemDir, "%s%s", out, kSystemDir); - sprintf(dataDir, "%s%s", out, kDataDir); - setenv("ANDROID_ROOT", systemDir, 1); - setenv("ANDROID_DATA", dataDir, 1); - - char* assetDir = (char*) malloc(strlen(systemDir) + strlen(kAppSubdir) +1); - sprintf(assetDir, "%s%s", systemDir, kAppSubdir); - - LOGI("Startup: sys='%s' asset='%s' data='%s'\n", - systemDir, assetDir, dataDir); - free(systemDir); - free(dataDir); - -#ifdef HAVE_ANDROID_OS - /* set up a process group for easier killing on the device */ - setpgid(0, getpid()); -#endif - - // Change to asset dir. This is only necessary if we've changed to - // a different directory, but there's little harm in doing it regardless. - // - // Expecting assets to live in the current dir is not a great idea, - // because some of our code or one of our libraries could change the - // directory out from under us. Preserve the behavior for now. - if (chdir(assetDir) != 0) { - LOGW("WARNING: could not change dir to '%s': %s\n", - assetDir, strerror(errno)); - } - free(assetDir); - -#if 0 - // Hack to keep libc from beating the filesystem to death. It's - // hitting /etc/localtime frequently, - // - // This statement locks us into Pacific time. We could do better, - // but there's not much point until we're sure that the library - // can't be changed to do more along the lines of what we want. -#ifndef XP_WIN - setenv("TZ", "PST+8PDT,M4.1.0/2,M10.5.0/2", true); -#endif -#endif - - /* track our progress through the boot sequence */ - const int LOG_BOOT_PROGRESS_START = 3000; - LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, - ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); - - validateTime(); - - proc = ProcessState::self(); - - boot_init(); - - /* If we are in multiprocess mode, have zygote spawn the system - * server process and call system_init(). If we are running in - * single process mode just call system_init() directly. - */ - if (proc->supportsProcesses()) { - // If stdio logging is on, system_server should not inherit our stdio - // The dalvikvm instance will copy stdio to the log on its own - char propBuf[PROPERTY_VALUE_MAX]; - bool logStdio = false; - property_get("log.redirect-stdio", propBuf, ""); - logStdio = (strcmp(propBuf, "true") == 0); - - zygote_run_oneshot((int)(!logStdio), - sizeof(ZYGOTE_ARGV) / sizeof(ZYGOTE_ARGV[0]), - ZYGOTE_ARGV); - - //start_process("/system/bin/mediaserver"); - - } else { -#ifndef HAVE_ANDROID_OS - QuickRuntime* runt = new QuickRuntime(); - runt->start("com/android/server/SystemServer", - "" /* spontaneously fork system server from zygote */); -#endif - } - - //printf("+++ post-zygote\n"); - - finish_system_init(proc); - run(proc); - -bail: - if (proc != NULL) { - proc->setContextObject(NULL); - } - - return 0; -} diff --git a/include/binder/ProcessState.h b/include/binder/ProcessState.h index feeb3c3891..9725822eaf 100644 --- a/include/binder/ProcessState.h +++ b/include/binder/ProcessState.h @@ -39,8 +39,6 @@ class ProcessState : public virtual RefBase public: static sp<ProcessState> self(); - static void setSingleProcess(bool singleProcess); - void setContextObject(const sp<IBinder>& object); sp<IBinder> getContextObject(const sp<IBinder>& caller); @@ -48,8 +46,6 @@ public: const String16& name); sp<IBinder> getContextObject(const String16& name, const sp<IBinder>& caller); - - bool supportsProcesses() const; void startThreadPool(); diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h index e705c6f58b..5b5b731348 100644 --- a/include/gui/ISurfaceTexture.h +++ b/include/gui/ISurfaceTexture.h @@ -104,6 +104,24 @@ protected: // queued buffers will be retired in order. // The default mode is asynchronous. virtual status_t setSynchronousMode(bool enabled) = 0; + + // connect attempts to connect a client API to the SurfaceTexture. This + // must be called before any other ISurfaceTexture methods are called except + // for getAllocator. + // + // This method will fail if the connect was previously called on the + // SurfaceTexture and no corresponding disconnect call was made. + virtual status_t connect(int api) = 0; + + // disconnect attempts to disconnect a client API from the SurfaceTexture. + // Calling this method will cause any subsequent calls to other + // ISurfaceTexture methods to fail except for getAllocator and connect. + // Successfully calling connect after this will allow the other methods to + // succeed again. + // + // This method will fail if the the SurfaceTexture is not currently + // connected to the specified client API. + virtual status_t disconnect(int api) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index e36360c167..4080f27669 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -44,6 +44,7 @@ public: MIN_SYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS }; enum { NUM_BUFFER_SLOTS = 32 }; + enum { NO_CONNECTED_API = 0 }; struct FrameAvailableListener : public virtual RefBase { // onFrameAvailable() is called from queueBuffer() each time an @@ -97,6 +98,24 @@ public: // The default mode is asynchronous. virtual status_t setSynchronousMode(bool enabled); + // connect attempts to connect a client API to the SurfaceTexture. This + // must be called before any other ISurfaceTexture methods are called except + // for getAllocator. + // + // This method will fail if the connect was previously called on the + // SurfaceTexture and no corresponding disconnect call was made. + virtual status_t connect(int api); + + // disconnect attempts to disconnect a client API from the SurfaceTexture. + // Calling this method will cause any subsequent calls to other + // ISurfaceTexture methods to fail except for getAllocator and connect. + // Successfully calling connect after this will allow the other methods to + // succeed again. + // + // This method will fail if the the SurfaceTexture is not currently + // connected to the specified client API. + virtual status_t disconnect(int api); + // updateTexImage sets the image contents of the target texture to that of // the most recently queued buffer. // @@ -362,6 +381,11 @@ private: // mAllowSynchronousMode whether we allow synchronous mode or not const bool mAllowSynchronousMode; + // mConnectedApi indicates the API that is currently connected to this + // SurfaceTexture. It defaults to NO_CONNECTED_API (= 0), and gets updated + // by the connect and disconnect methods. + int mConnectedApi; + // mDequeueCondition condition used for dequeueBuffer in synchronous mode mutable Condition mDequeueCondition; diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h index 6ce44fcac7..5ec469e9b8 100644 --- a/include/gui/SurfaceTextureClient.h +++ b/include/gui/SurfaceTextureClient.h @@ -65,6 +65,8 @@ private: int dispatchDisconnect(va_list args); int dispatchSetBufferCount(va_list args); int dispatchSetBuffersGeometry(va_list args); + int dispatchSetBuffersDimensions(va_list args); + int dispatchSetBuffersFormat(va_list args); int dispatchSetBuffersTransform(va_list args); int dispatchSetBuffersTimestamp(va_list args); int dispatchSetCrop(va_list args); @@ -73,7 +75,8 @@ private: int connect(int api); int disconnect(int api); int setBufferCount(int bufferCount); - int setBuffersGeometry(int w, int h, int format); + int setBuffersDimensions(int w, int h); + int setBuffersFormat(int format); int setBuffersTransform(int transform); int setBuffersTimestamp(int64_t timestamp); int setCrop(Rect const* rect); @@ -126,9 +129,6 @@ private: // a timestamp is auto-generated when queueBuffer is called. int64_t mTimestamp; - // mConnectedApi holds the currently connected API to this surface - int mConnectedApi; - // mQueryWidth is the width returned by query(). It is set to width // of the last dequeued buffer or to mReqWidth if no buffer was dequeued. uint32_t mQueryWidth; diff --git a/include/private/binder/binder_module.h b/include/private/binder/binder_module.h index fdf327e1c5..a8dd64f235 100644 --- a/include/private/binder/binder_module.h +++ b/include/private/binder/binder_module.h @@ -21,126 +21,11 @@ namespace android { #endif -#if defined(HAVE_ANDROID_OS) - /* obtain structures and constants from the kernel header */ #include <sys/ioctl.h> #include <linux/binder.h> -#else - -/* Some parts of the simulator need fake versions of this - * stuff in order to compile. Really this should go away - * entirely... - */ - -#define BINDER_CURRENT_PROTOCOL_VERSION 7 - -#define BINDER_TYPE_BINDER 1 -#define BINDER_TYPE_WEAK_BINDER 2 -#define BINDER_TYPE_HANDLE 3 -#define BINDER_TYPE_WEAK_HANDLE 4 -#define BINDER_TYPE_FD 5 - -struct flat_binder_object { - unsigned long type; - unsigned long flags; - union { - void *binder; - signed long handle; - }; - void *cookie; -}; - -struct binder_write_read { - signed long write_size; - signed long write_consumed; - unsigned long write_buffer; - signed long read_size; - signed long read_consumed; - unsigned long read_buffer; -}; - -struct binder_transaction_data { - union { - size_t handle; - void *ptr; - } target; - void *cookie; - unsigned int code; - - unsigned int flags; - pid_t sender_pid; - uid_t sender_euid; - size_t data_size; - size_t offsets_size; - - union { - struct { - const void *buffer; - const void *offsets; - } ptr; - uint8_t buf[8]; - } data; -}; - -enum transaction_flags { - TF_ONE_WAY = 0x01, - TF_ROOT_OBJECT = 0x04, - TF_STATUS_CODE = 0x08, - TF_ACCEPT_FDS = 0x10, -}; - - -enum { - FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff, - FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100, -}; - -enum BinderDriverReturnProtocol { - BR_ERROR, - BR_OK, - BR_TRANSACTION, - BR_REPLY, - BR_ACQUIRE_RESULT, - BR_DEAD_REPLY, - BR_TRANSACTION_COMPLETE, - BR_INCREFS, - BR_ACQUIRE, - BR_RELEASE, - BR_DECREFS, - BR_ATTEMPT_ACQUIRE, - BR_NOOP, - BR_SPAWN_LOOPER, - BR_FINISHED, - BR_DEAD_BINDER, - BR_CLEAR_DEATH_NOTIFICATION_DONE, - BR_FAILED_REPLY, -}; - -enum BinderDriverCommandProtocol { - BC_TRANSACTION, - BC_REPLY, - BC_ACQUIRE_RESULT, - BC_FREE_BUFFER, - BC_INCREFS, - BC_ACQUIRE, - BC_RELEASE, - BC_DECREFS, - BC_INCREFS_DONE, - BC_ACQUIRE_DONE, - BC_ATTEMPT_ACQUIRE, - BC_REGISTER_LOOPER, - BC_ENTER_LOOPER, - BC_EXIT_LOOPER, - BC_REQUEST_DEATH_NOTIFICATION, - BC_CLEAR_DEATH_NOTIFICATION, - BC_DEAD_BINDER_DONE, -}; - -#endif - #ifdef __cplusplus } // namespace android #endif diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index 2d4e10ddde..f5288c8c3e 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -43,8 +43,6 @@ #define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2)) -static bool gSingleProcess = false; - // --------------------------------------------------------------------------- @@ -82,12 +80,6 @@ sp<ProcessState> ProcessState::self() return gProcess; } -void ProcessState::setSingleProcess(bool singleProcess) -{ - gSingleProcess = singleProcess; -} - - void ProcessState::setContextObject(const sp<IBinder>& object) { setContextObject(object, String16("default")); @@ -95,11 +87,7 @@ void ProcessState::setContextObject(const sp<IBinder>& object) sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller) { - if (supportsProcesses()) { - return getStrongProxyForHandle(0); - } else { - return getContextObject(String16("default"), caller); - } + return getStrongProxyForHandle(0); } void ProcessState::setContextObject(const sp<IBinder>& object, const String16& name) @@ -144,11 +132,6 @@ sp<IBinder> ProcessState::getContextObject(const String16& name, const sp<IBinde return object; } -bool ProcessState::supportsProcesses() const -{ - return mDriverFD >= 0; -} - void ProcessState::startThreadPool() { AutoMutex _l(mLock); @@ -169,24 +152,15 @@ bool ProcessState::becomeContextManager(context_check_func checkFunc, void* user AutoMutex _l(mLock); mBinderContextCheckFunc = checkFunc; mBinderContextUserData = userData; - if (mDriverFD >= 0) { - int dummy = 0; -#if defined(HAVE_ANDROID_OS) - status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy); -#else - status_t result = INVALID_OPERATION; -#endif - if (result == 0) { - mManagesContexts = true; - } else if (result == -1) { - mBinderContextCheckFunc = NULL; - mBinderContextUserData = NULL; - LOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno)); - } - } else { - // If there is no driver, our only world is the local - // process so we can always become the context manager there. + + int dummy = 0; + status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy); + if (result == 0) { mManagesContexts = true; + } else if (result == -1) { + mBinderContextCheckFunc = NULL; + mBinderContextUserData = NULL; + LOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno)); } } return mManagesContexts; @@ -322,20 +296,11 @@ void ProcessState::spawnPooledThread(bool isMain) static int open_driver() { - if (gSingleProcess) { - return -1; - } - int fd = open("/dev/binder", O_RDWR); if (fd >= 0) { fcntl(fd, F_SETFD, FD_CLOEXEC); int vers; -#if defined(HAVE_ANDROID_OS) status_t result = ioctl(fd, BINDER_VERSION, &vers); -#else - status_t result = -1; - errno = EPERM; -#endif if (result == -1) { LOGE("Binder ioctl to obtain version failed: %s", strerror(errno)); close(fd); @@ -346,14 +311,11 @@ static int open_driver() close(fd); fd = -1; } -#if defined(HAVE_ANDROID_OS) size_t maxThreads = 15; result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads); if (result == -1) { LOGE("Binder ioctl to set max threads failed: %s", strerror(errno)); } -#endif - } else { LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno)); } @@ -386,9 +348,8 @@ ProcessState::ProcessState() mDriverFD = -1; #endif } - if (mDriverFD < 0) { - // Need to run without the driver, starting our own thread pool. - } + + LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating."); } ProcessState::~ProcessState() diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk index 4070eba736..ed319f5e93 100644 --- a/libs/gui/Android.mk +++ b/libs/gui/Android.mk @@ -32,10 +32,6 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_MODULE:= libgui -ifeq ($(TARGET_SIMULATOR),true) - LOCAL_LDLIBS += -lpthread -endif - include $(BUILD_SHARED_LIBRARY) ifeq (,$(ONE_SHOT_MAKEFILE)) diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp index 16e37802b2..41434a4ba9 100644 --- a/libs/gui/ISurfaceTexture.cpp +++ b/libs/gui/ISurfaceTexture.cpp @@ -41,6 +41,8 @@ enum { GET_ALLOCATOR, QUERY, SET_SYNCHRONOUS_MODE, + CONNECT, + DISCONNECT, }; @@ -154,7 +156,23 @@ public: return result; } + virtual status_t connect(int api) { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); + data.writeInt32(api); + remote()->transact(CONNECT, data, &reply); + status_t result = reply.readInt32(); + return result; + } + virtual status_t disconnect(int api) { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); + data.writeInt32(api); + remote()->transact(DISCONNECT, data, &reply); + status_t result = reply.readInt32(); + return result; + } }; IMPLEMENT_META_INTERFACE(SurfaceTexture, "android.gui.SurfaceTexture"); @@ -248,6 +266,20 @@ status_t BnSurfaceTexture::onTransact( reply->writeInt32(res); return NO_ERROR; } break; + case CONNECT: { + CHECK_INTERFACE(ISurfaceTexture, data, reply); + int api = data.readInt32(); + status_t res = connect(api); + reply->writeInt32(res); + return NO_ERROR; + } break; + case DISCONNECT: { + CHECK_INTERFACE(ISurfaceTexture, data, reply); + int api = data.readInt32(); + status_t res = disconnect(api); + reply->writeInt32(res); + return NO_ERROR; + } break; } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 886a3fb222..14104810f8 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -92,7 +92,8 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) : mNextTransform(0), mTexName(tex), mSynchronousMode(false), - mAllowSynchronousMode(allowSynchronousMode) { + mAllowSynchronousMode(allowSynchronousMode), + mConnectedApi(NO_CONNECTED_API) { LOGV("SurfaceTexture::SurfaceTexture"); sp<ISurfaceComposer> composer(ComposerService::getComposerService()); mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); @@ -493,6 +494,50 @@ status_t SurfaceTexture::setTransform(uint32_t transform) { return OK; } +status_t SurfaceTexture::connect(int api) { + LOGV("SurfaceTexture::connect"); + Mutex::Autolock lock(mMutex); + int err = NO_ERROR; + switch (api) { + case NATIVE_WINDOW_API_EGL: + case NATIVE_WINDOW_API_CPU: + case NATIVE_WINDOW_API_MEDIA: + case NATIVE_WINDOW_API_CAMERA: + if (mConnectedApi != NO_CONNECTED_API) { + err = -EINVAL; + } else { + mConnectedApi = api; + } + break; + default: + err = -EINVAL; + break; + } + return err; +} + +status_t SurfaceTexture::disconnect(int api) { + LOGV("SurfaceTexture::disconnect"); + Mutex::Autolock lock(mMutex); + int err = NO_ERROR; + switch (api) { + case NATIVE_WINDOW_API_EGL: + case NATIVE_WINDOW_API_CPU: + case NATIVE_WINDOW_API_MEDIA: + case NATIVE_WINDOW_API_CAMERA: + if (mConnectedApi == api) { + mConnectedApi = NO_CONNECTED_API; + } else { + err = -EINVAL; + } + break; + default: + err = -EINVAL; + break; + } + return err; +} + status_t SurfaceTexture::updateTexImage() { LOGV("SurfaceTexture::updateTexImage"); Mutex::Autolock lock(mMutex); diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index b9b2310c7f..f39cabf09c 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -27,7 +27,7 @@ SurfaceTextureClient::SurfaceTextureClient( const sp<ISurfaceTexture>& surfaceTexture): mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(0), mReqHeight(0), mReqFormat(0), mReqUsage(0), - mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mConnectedApi(0), + mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mQueryWidth(0), mQueryHeight(0), mQueryFormat(0), mMutex() { // Initialize the ANativeWindow function pointers. @@ -254,6 +254,12 @@ int SurfaceTextureClient::perform(int operation, va_list args) case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP: res = dispatchSetBuffersTimestamp(args); break; + case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: + res = dispatchSetBuffersDimensions(args); + break; + case NATIVE_WINDOW_SET_BUFFERS_FORMAT: + res = dispatchSetBuffersFormat(args); + break; default: res = NAME_NOT_FOUND; break; @@ -290,7 +296,22 @@ int SurfaceTextureClient::dispatchSetBuffersGeometry(va_list args) { int w = va_arg(args, int); int h = va_arg(args, int); int f = va_arg(args, int); - return setBuffersGeometry(w, h, f); + int err = setBuffersDimensions(w, h); + if (err != 0) { + return err; + } + return setBuffersFormat(f); +} + +int SurfaceTextureClient::dispatchSetBuffersDimensions(va_list args) { + int w = va_arg(args, int); + int h = va_arg(args, int); + return setBuffersDimensions(w, h); +} + +int SurfaceTextureClient::dispatchSetBuffersFormat(va_list args) { + int f = va_arg(args, int); + return setBuffersFormat(f); } int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) { @@ -306,45 +327,22 @@ int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) { int SurfaceTextureClient::connect(int api) { LOGV("SurfaceTextureClient::connect"); Mutex::Autolock lock(mMutex); - int err = NO_ERROR; - switch (api) { - case NATIVE_WINDOW_API_EGL: - if (mConnectedApi) { - err = -EINVAL; - } else { - mConnectedApi = api; - } - break; - default: - err = -EINVAL; - break; - } - return err; + return mSurfaceTexture->connect(api); } int SurfaceTextureClient::disconnect(int api) { LOGV("SurfaceTextureClient::disconnect"); Mutex::Autolock lock(mMutex); - int err = NO_ERROR; - switch (api) { - case NATIVE_WINDOW_API_EGL: - if (mConnectedApi == api) { - mConnectedApi = 0; - } else { - err = -EINVAL; - } - break; - default: - err = -EINVAL; - break; - } - return err; + return mSurfaceTexture->disconnect(api); } int SurfaceTextureClient::getConnectedApi() const { + // XXX: This method will be going away shortly, and is currently bogus. It + // always returns "nothing is connected". It will go away once Surface gets + // updated to actually connect as the 'CPU' API when locking a buffer. Mutex::Autolock lock(mMutex); - return mConnectedApi; + return 0; } @@ -390,12 +388,12 @@ int SurfaceTextureClient::setBufferCount(int bufferCount) return err; } -int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format) +int SurfaceTextureClient::setBuffersDimensions(int w, int h) { - LOGV("SurfaceTextureClient::setBuffersGeometry"); + LOGV("SurfaceTextureClient::setBuffersDimensions"); Mutex::Autolock lock(mMutex); - if (w<0 || h<0 || format<0) + if (w<0 || h<0) return BAD_VALUE; if ((w && !h) || (!w && h)) @@ -403,7 +401,6 @@ int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format) mReqWidth = w; mReqHeight = h; - mReqFormat = format; status_t err = mSurfaceTexture->setCrop(Rect(0, 0)); LOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s", strerror(-err)); @@ -411,6 +408,19 @@ int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format) return err; } +int SurfaceTextureClient::setBuffersFormat(int format) +{ + LOGV("SurfaceTextureClient::setBuffersFormat"); + Mutex::Autolock lock(mMutex); + + if (format<0) + return BAD_VALUE; + + mReqFormat = format; + + return NO_ERROR; +} + int SurfaceTextureClient::setBuffersTransform(int transform) { LOGV("SurfaceTextureClient::setBuffersTransform"); diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk index 8d3a9b5eba..0308af3abf 100644 --- a/libs/gui/tests/Android.mk +++ b/libs/gui/tests/Android.mk @@ -2,8 +2,6 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -ifneq ($(TARGET_SIMULATOR),true) - LOCAL_MODULE := SurfaceTexture_test LOCAL_MODULE_TAGS := tests @@ -36,8 +34,6 @@ LOCAL_C_INCLUDES := \ include $(BUILD_EXECUTABLE) -endif - # Include subdirectory makefiles # ============================================================ diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp index c06400e521..9abe89d970 100644 --- a/libs/gui/tests/SurfaceTexture_test.cpp +++ b/libs/gui/tests/SurfaceTexture_test.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#define LOG_TAG "SurfaceTexture_test" //#define LOG_NDEBUG 0 #include <gtest/gtest.h> @@ -379,6 +380,13 @@ protected: ASSERT_NE(-1, mTexMatrixHandle); } + virtual void TearDown() { + mANW.clear(); + mSTC.clear(); + mST.clear(); + GLTest::TearDown(); + } + // drawTexture draws the SurfaceTexture over the entire GL viewport. void drawTexture() { const GLfloat triangleVertices[] = { @@ -1089,13 +1097,21 @@ protected: // synchronously from SurfaceTexture::queueBuffer. class FrameCondition : public SurfaceTexture::FrameAvailableListener { public: + FrameCondition(): + mFrameAvailable(false), + mFrameFinished(false) { + } + // waitForFrame waits for the next frame to arrive. This should be // called from the consumer thread once for every frame expected by the // test. void waitForFrame() { - LOGV("+waitForFrame"); Mutex::Autolock lock(mMutex); - status_t result = mFrameAvailableCondition.wait(mMutex); + LOGV("+waitForFrame"); + while (!mFrameAvailable) { + mFrameAvailableCondition.wait(mMutex); + } + mFrameAvailable = false; LOGV("-waitForFrame"); } @@ -1103,22 +1119,30 @@ protected: // on to produce the next frame. This should be called by the consumer // thread once for every frame expected by the test. void finishFrame() { - LOGV("+finishFrame"); Mutex::Autolock lock(mMutex); + LOGV("+finishFrame"); + mFrameFinished = true; mFrameFinishCondition.signal(); LOGV("-finishFrame"); } // This should be called by SurfaceTexture on the producer thread. virtual void onFrameAvailable() { - LOGV("+onFrameAvailable"); Mutex::Autolock lock(mMutex); + LOGV("+onFrameAvailable"); + mFrameAvailable = true; mFrameAvailableCondition.signal(); - mFrameFinishCondition.wait(mMutex); + while (!mFrameFinished) { + mFrameFinishCondition.wait(mMutex); + } + mFrameFinished = false; LOGV("-onFrameAvailable"); } protected: + bool mFrameAvailable; + bool mFrameFinished; + Mutex mMutex; Condition mFrameAvailableCondition; Condition mFrameFinishCondition; @@ -1164,6 +1188,7 @@ protected: } mProducerThread.clear(); mFC.clear(); + SurfaceTextureGLTest::TearDown(); } void runProducerThread(const sp<ProducerThread> producerThread) { @@ -1180,8 +1205,7 @@ protected: sp<FrameCondition> mFC; }; -// XXX: This test is disabled because it causes hangs on some devices. -TEST_F(SurfaceTextureGLToGLTest, DISABLED_UpdateTexImageBeforeFrameFinishedWorks) { +TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedWorks) { class PT : public ProducerThread { virtual void render() { glClearColor(0.0f, 1.0f, 0.0f, 1.0f); @@ -1199,8 +1223,7 @@ TEST_F(SurfaceTextureGLToGLTest, DISABLED_UpdateTexImageBeforeFrameFinishedWorks // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! } -// XXX: This test is disabled because it causes hangs on some devices. -TEST_F(SurfaceTextureGLToGLTest, DISABLED_UpdateTexImageAfterFrameFinishedWorks) { +TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedWorks) { class PT : public ProducerThread { virtual void render() { glClearColor(0.0f, 1.0f, 0.0f, 1.0f); @@ -1218,8 +1241,7 @@ TEST_F(SurfaceTextureGLToGLTest, DISABLED_UpdateTexImageAfterFrameFinishedWorks) // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! } -// XXX: This test is disabled because it causes hangs on some devices. -TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedUpdateTexImageBeforeFrameFinishedWorks) { +TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedWorks) { enum { NUM_ITERATIONS = 1024 }; class PT : public ProducerThread { @@ -1247,8 +1269,7 @@ TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedUpdateTexImageBeforeFrameFinis } } -// XXX: This test is disabled because it causes hangs on some devices. -TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedUpdateTexImageAfterFrameFinishedWorks) { +TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedWorks) { enum { NUM_ITERATIONS = 1024 }; class PT : public ProducerThread { diff --git a/libs/surfaceflinger_client/Android.mk b/libs/surfaceflinger_client/Android.mk index 267e3edf44..5fca1ce5b3 100644 --- a/libs/surfaceflinger_client/Android.mk +++ b/libs/surfaceflinger_client/Android.mk @@ -7,8 +7,4 @@ LOCAL_SHARED_LIBRARIES := LOCAL_MODULE:= libsurfaceflinger_client -ifeq ($(TARGET_SIMULATOR),true) - LOCAL_LDLIBS += -lpthread -endif - include $(BUILD_SHARED_LIBRARY) diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk index 427bbba896..fbabfc420c 100644 --- a/libs/ui/Android.mk +++ b/libs/ui/Android.mk @@ -68,10 +68,6 @@ LOCAL_C_INCLUDES := \ LOCAL_MODULE:= libui -ifeq ($(TARGET_SIMULATOR),true) - LOCAL_LDLIBS += -lpthread -endif - include $(BUILD_SHARED_LIBRARY) diff --git a/libs/ui/EGLUtils.cpp b/libs/ui/EGLUtils.cpp index f24a71d88d..020646b9c4 100644 --- a/libs/ui/EGLUtils.cpp +++ b/libs/ui/EGLUtils.cpp @@ -24,6 +24,8 @@ #include <EGL/egl.h> +#include <system/graphics.h> + #include <private/ui/android_natives_priv.h> // ---------------------------------------------------------------------------- @@ -67,31 +69,49 @@ status_t EGLUtils::selectConfigForPixelFormat( return BAD_VALUE; // Get all the "potential match" configs... - if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE) + if (eglChooseConfig(dpy, attrs, 0, 0, &numConfigs) == EGL_FALSE) return BAD_VALUE; - EGLConfig* const configs = (EGLConfig*)malloc(sizeof(EGLConfig)*numConfigs); - if (eglChooseConfig(dpy, attrs, configs, numConfigs, &n) == EGL_FALSE) { - free(configs); - return BAD_VALUE; - } - - int i; - EGLConfig config = NULL; - for (i=0 ; i<n ; i++) { - EGLint nativeVisualId = 0; - eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId); - if (nativeVisualId>0 && format == nativeVisualId) { + if (numConfigs) { + EGLConfig* const configs = new EGLConfig[numConfigs]; + if (eglChooseConfig(dpy, attrs, configs, numConfigs, &n) == EGL_FALSE) { + delete [] configs; + return BAD_VALUE; + } + + bool hasAlpha = false; + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + hasAlpha = true; + break; + } + + // The first config is guaranteed to over-satisfy the constraints + EGLConfig config = configs[0]; + + // go through the list and skip configs that over-satisfy our needs + int i; + for (i=0 ; i<n ; i++) { + if (!hasAlpha) { + EGLint alphaSize; + eglGetConfigAttrib(dpy, configs[i], EGL_ALPHA_SIZE, &alphaSize); + if (alphaSize > 0) { + continue; + } + } config = configs[i]; break; } - } - free(configs); - - if (i<n) { - *outConfig = config; - return NO_ERROR; + delete [] configs; + + if (i<n) { + *outConfig = config; + return NO_ERROR; + } } return NAME_NOT_FOUND; diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp index 4393504236..9c10c754ba 100644 --- a/libs/ui/FramebufferNativeWindow.cpp +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -299,6 +299,7 @@ int FramebufferNativeWindow::perform(ANativeWindow* window, { switch (operation) { case NATIVE_WINDOW_SET_USAGE: + case NATIVE_WINDOW_SET_BUFFERS_FORMAT: case NATIVE_WINDOW_CONNECT: case NATIVE_WINDOW_DISCONNECT: break; diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp index c46d6f4724..1e602e982d 100644 --- a/libs/ui/InputTransport.cpp +++ b/libs/ui/InputTransport.cpp @@ -83,7 +83,9 @@ status_t InputChannel::openInputChannelPair(const String8& name, sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) { status_t result; - int serverAshmemFd = ashmem_create_region(name.string(), DEFAULT_MESSAGE_BUFFER_SIZE); + String8 ashmemName("InputChannel "); + ashmemName.append(name); + int serverAshmemFd = ashmem_create_region(ashmemName.string(), DEFAULT_MESSAGE_BUFFER_SIZE); if (serverAshmemFd < 0) { result = -errno; LOGE("channel '%s' ~ Could not create shared memory region. errno=%d", diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk index e23197185c..693a32aa02 100644 --- a/libs/ui/tests/Android.mk +++ b/libs/ui/tests/Android.mk @@ -2,8 +2,6 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -ifneq ($(TARGET_SIMULATOR),true) - # Build the unit tests. test_src_files := \ InputChannel_test.cpp \ @@ -48,5 +46,3 @@ $(foreach file,$(test_src_files), \ # Build the manual test programs. include $(call all-subdir-makefiles) - -endif
\ No newline at end of file diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk index 774e8c9745..f6333576a1 100644 --- a/libs/utils/Android.mk +++ b/libs/utils/Android.mk @@ -103,17 +103,14 @@ LOCAL_SHARED_LIBRARIES := \ liblog \ libcutils -ifneq ($(TARGET_SIMULATOR),true) ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86) # This is needed on x86 to bring in dl_iterate_phdr for CallStack.cpp LOCAL_SHARED_LIBRARIES += libdl endif # linux-x86 -endif # sim LOCAL_MODULE:= libutils include $(BUILD_SHARED_LIBRARY) -ifneq ($(TARGET_SIMULATOR),true) ifeq ($(TARGET_OS),linux) include $(CLEAR_VARS) LOCAL_C_INCLUDES += external/zlib external/icu4c/common @@ -122,7 +119,6 @@ LOCAL_MODULE := libutils LOCAL_SRC_FILES := $(commonSources) BackupData.cpp BackupHelpers.cpp include $(BUILD_STATIC_LIBRARY) endif -endif # Include subdirectory makefiles diff --git a/libs/utils/BackupHelpers.cpp b/libs/utils/BackupHelpers.cpp index 87549fe977..7ef30f9990 100644 --- a/libs/utils/BackupHelpers.cpp +++ b/libs/utils/BackupHelpers.cpp @@ -481,6 +481,14 @@ static int write_pax_header_entry(char* buf, const char* key, const char* value) return sprintf(buf, "%d %s=%s\n", len, key, value); } +// Wire format to the backup manager service is chunked: each chunk is prefixed by +// a 4-byte count of its size. A chunk size of zero (four zero bytes) indicates EOD. +void send_tarfile_chunk(BackupDataWriter* writer, const char* buffer, size_t size) { + uint32_t chunk_size_no = htonl(size); + writer->WriteEntityData(&chunk_size_no, 4); + if (size != 0) writer->WriteEntityData(buffer, size); +} + int write_tarfile(const String8& packageName, const String8& domain, const String8& rootpath, const String8& filepath, BackupDataWriter* writer) { @@ -660,16 +668,16 @@ int write_tarfile(const String8& packageName, const String8& domain, // Checksum and write the pax block header calc_tar_checksum(paxHeader); - writer->WriteEntityData(paxHeader, 512); + send_tarfile_chunk(writer, paxHeader, 512); // Now write the pax data itself int paxblocks = (paxLen + 511) / 512; - writer->WriteEntityData(paxData, 512 * paxblocks); + send_tarfile_chunk(writer, paxData, 512 * paxblocks); } // Checksum and write the 512-byte ustar file header block to the output calc_tar_checksum(buf); - writer->WriteEntityData(buf, 512); + send_tarfile_chunk(writer, buf, 512); // Now write the file data itself, for real files. We honor tar's convention that // only full 512-byte blocks are sent to write(). @@ -699,7 +707,7 @@ int write_tarfile(const String8& packageName, const String8& domain, memset(buf + nRead, 0, remainder); nRead += remainder; } - writer->WriteEntityData(buf, nRead); + send_tarfile_chunk(writer, buf, nRead); toWrite -= nRead; } } diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp index 50312e7bb7..d18c0a2f5a 100644 --- a/libs/utils/Threads.cpp +++ b/libs/utils/Threads.cpp @@ -161,6 +161,7 @@ int androidCreateRawThreadEtc(android_thread_func_t entryFunction, pthread_t thread; int result = pthread_create(&thread, &attr, (android_pthread_entry)entryFunction, userData); + pthread_attr_destroy(&attr); if (result != 0) { LOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n" "(android threadPriority=%d)", diff --git a/libs/utils/VectorImpl.cpp b/libs/utils/VectorImpl.cpp index 289c826d3e..bfb37a60d7 100644 --- a/libs/utils/VectorImpl.cpp +++ b/libs/utils/VectorImpl.cpp @@ -252,13 +252,15 @@ ssize_t VectorImpl::replaceAt(const void* prototype, size_t index) "[%p] replace: index=%d, size=%d", this, (int)index, (int)size()); void* item = editItemLocation(index); - if (item == 0) - return NO_MEMORY; - _do_destroy(item, 1); - if (prototype == 0) { - _do_construct(item, 1); - } else { - _do_copy(item, prototype, 1); + if (item != prototype) { + if (item == 0) + return NO_MEMORY; + _do_destroy(item, 1); + if (prototype == 0) { + _do_construct(item, 1); + } else { + _do_copy(item, prototype, 1); + } } return ssize_t(index); } @@ -290,7 +292,7 @@ void VectorImpl::clear() void* VectorImpl::editItemLocation(size_t index) { LOG_ASSERT(index<capacity(), - "[%p] itemLocation: index=%d, capacity=%d, count=%d", + "[%p] editItemLocation: index=%d, capacity=%d, count=%d", this, (int)index, (int)capacity(), (int)mCount); void* buffer = editArrayImpl(); @@ -302,7 +304,7 @@ void* VectorImpl::editItemLocation(size_t index) const void* VectorImpl::itemLocation(size_t index) const { LOG_ASSERT(index<capacity(), - "[%p] editItemLocation: index=%d, capacity=%d, count=%d", + "[%p] itemLocation: index=%d, capacity=%d, count=%d", this, (int)index, (int)capacity(), (int)mCount); const void* buffer = arrayImpl(); @@ -347,9 +349,10 @@ void* VectorImpl::_grow(size_t where, size_t amount) // LOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d", // this, (int)where, (int)amount, (int)mCount, (int)capacity()); - if (where > mCount) - where = mCount; - + LOG_ASSERT(where <= mCount, + "[%p] _grow: where=%d, amount=%d, count=%d", + this, (int)where, (int)amount, (int)mCount); // caller already checked + const size_t new_size = mCount + amount; if (capacity() < new_size) { const size_t new_capacity = max(kMinVectorCapacity, ((new_size*3)+1)/2); @@ -366,10 +369,10 @@ void* VectorImpl::_grow(size_t where, size_t amount) SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize); if (sb) { void* array = sb->data(); - if (where>0) { + if (where != 0) { _do_copy(array, mStorage, where); } - if (mCount>where) { + if (where != mCount) { const void* from = reinterpret_cast<const uint8_t *>(mStorage) + where*mItemSize; void* dest = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize; _do_copy(dest, from, mCount-where); @@ -379,15 +382,14 @@ void* VectorImpl::_grow(size_t where, size_t amount) } } } else { - ssize_t s = mCount-where; - if (s>0) { - void* array = editArrayImpl(); - void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize; + if (where != mCount) { + void* array = editArrayImpl(); const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize; - _do_move_forward(to, from, s); + void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize; + _do_move_forward(to, from, mCount - where); } } - mCount += amount; + mCount = new_size; void* free_space = const_cast<void*>(itemLocation(where)); return free_space; } @@ -400,14 +402,15 @@ void VectorImpl::_shrink(size_t where, size_t amount) // LOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d", // this, (int)where, (int)amount, (int)mCount, (int)capacity()); - if (where >= mCount) - where = mCount - amount; + LOG_ASSERT(where + amount <= mCount, + "[%p] _shrink: where=%d, amount=%d, count=%d", + this, (int)where, (int)amount, (int)mCount); // caller already checked const size_t new_size = mCount - amount; if (new_size*3 < capacity()) { const size_t new_capacity = max(kMinVectorCapacity, new_size*2); // LOGV("shrink vector %p, new_capacity=%d", this, (int)new_capacity); - if ((where == mCount-amount) && + if ((where == new_size) && (mFlags & HAS_TRIVIAL_COPY) && (mFlags & HAS_TRIVIAL_DTOR)) { @@ -418,31 +421,28 @@ void VectorImpl::_shrink(size_t where, size_t amount) SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize); if (sb) { void* array = sb->data(); - if (where>0) { + if (where != 0) { _do_copy(array, mStorage, where); } - if (mCount > where+amount) { + if (where != new_size) { const void* from = reinterpret_cast<const uint8_t *>(mStorage) + (where+amount)*mItemSize; void* dest = reinterpret_cast<uint8_t *>(array) + where*mItemSize; - _do_copy(dest, from, mCount-(where+amount)); + _do_copy(dest, from, new_size - where); } release_storage(); mStorage = const_cast<void*>(array); } } } else { - void* array = editArrayImpl(); + void* array = editArrayImpl(); void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize; _do_destroy(to, amount); - ssize_t s = mCount-(where+amount); - if (s>0) { + if (where != new_size) { const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize; - _do_move_backward(to, from, s); + _do_move_backward(to, from, new_size - where); } } - - // adjust the number of items... - mCount -= amount; + mCount = new_size; } size_t VectorImpl::itemSize() const { diff --git a/libs/utils/tests/Android.mk b/libs/utils/tests/Android.mk index 87ad98eaad..8726a536c4 100644 --- a/libs/utils/tests/Android.mk +++ b/libs/utils/tests/Android.mk @@ -2,8 +2,6 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -ifneq ($(TARGET_SIMULATOR),true) - # Build the unit tests. test_src_files := \ BlobCache_test.cpp \ @@ -43,5 +41,3 @@ $(foreach file,$(test_src_files), \ $(eval LOCAL_MODULE_TAGS := $(module_tags)) \ $(eval include $(BUILD_EXECUTABLE)) \ ) - -endif diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk index b5c018f462..15e58f2f6a 100644 --- a/opengl/libagl/Android.mk +++ b/opengl/libagl/Android.mk @@ -38,15 +38,13 @@ ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true) LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER endif -ifneq ($(TARGET_SIMULATOR),true) - # we need to access the private Bionic header <bionic_tls.h> - # on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER - # behavior from the bionic Android.mk file - ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true) - LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER - endif - LOCAL_C_INCLUDES += bionic/libc/private +# we need to access the private Bionic header <bionic_tls.h> +# on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER +# behavior from the bionic Android.mk file +ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true) + LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER endif +LOCAL_C_INCLUDES += bionic/libc/private LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl LOCAL_MODULE:= libGLES_android diff --git a/opengl/libagl2/Android.mk b/opengl/libagl2/Android.mk index 564932f5cb..b442a2d4a5 100644 --- a/opengl/libagl2/Android.mk +++ b/opengl/libagl2/Android.mk @@ -39,15 +39,13 @@ ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true) LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER endif -ifneq ($(TARGET_SIMULATOR),true) - # we need to access the private Bionic header <bionic_tls.h> - # on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER - # behavior from the bionic Android.mk file - ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true) - LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER - endif - LOCAL_C_INCLUDES += bionic/libc/private +# we need to access the private Bionic header <bionic_tls.h> +# on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER +# behavior from the bionic Android.mk file +ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true) + LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER endif +LOCAL_C_INCLUDES += bionic/libc/private LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl #replace libagl for now diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk index ff45edcc95..3e66a133ab 100644 --- a/opengl/libs/Android.mk +++ b/opengl/libs/Android.mk @@ -21,18 +21,14 @@ LOCAL_SHARED_LIBRARIES += libcutils libutils libGLESv2_dbg LOCAL_LDLIBS := -lpthread -ldl LOCAL_MODULE:= libEGL LOCAL_LDFLAGS += -Wl,--exclude-libs=ALL -# needed on sim build because of weird logging issues -ifeq ($(TARGET_SIMULATOR),true) -else - LOCAL_SHARED_LIBRARIES += libdl - # Bionic's private TLS header relies on the ARCH_ARM_HAVE_TLS_REGISTER to - # select the appropriate TLS codepath - ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true) - LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER - endif - # we need to access the private Bionic header <bionic_tls.h> - LOCAL_C_INCLUDES += bionic/libc/private +LOCAL_SHARED_LIBRARIES += libdl +# Bionic's private TLS header relies on the ARCH_ARM_HAVE_TLS_REGISTER to +# select the appropriate TLS codepath +ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true) + LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER endif +# we need to access the private Bionic header <bionic_tls.h> +LOCAL_C_INCLUDES += bionic/libc/private LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES @@ -81,16 +77,12 @@ LOCAL_SHARED_LIBRARIES += libcutils libEGL LOCAL_LDLIBS := -lpthread -ldl LOCAL_MODULE:= libGLESv1_CM -# needed on sim build because of weird logging issues -ifeq ($(TARGET_SIMULATOR),true) -else - LOCAL_SHARED_LIBRARIES += libdl - # we need to access the private Bionic header <bionic_tls.h> - ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true) - LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER - endif - LOCAL_C_INCLUDES += bionic/libc/private +LOCAL_SHARED_LIBRARIES += libdl +# we need to access the private Bionic header <bionic_tls.h> +ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true) + LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER endif +LOCAL_C_INCLUDES += bionic/libc/private LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv1\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES @@ -117,16 +109,12 @@ LOCAL_SHARED_LIBRARIES += libcutils libEGL LOCAL_LDLIBS := -lpthread -ldl LOCAL_MODULE:= libGLESv2 -# needed on sim build because of weird logging issues -ifeq ($(TARGET_SIMULATOR),true) -else - LOCAL_SHARED_LIBRARIES += libdl - # we need to access the private Bionic header <bionic_tls.h> - ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true) - LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER - endif - LOCAL_C_INCLUDES += bionic/libc/private +LOCAL_SHARED_LIBRARIES += libdl +# we need to access the private Bionic header <bionic_tls.h> +ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true) + LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER endif +LOCAL_C_INCLUDES += bionic/libc/private LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv2\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index b11db324dd..ddad2d323f 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -31,6 +31,7 @@ #include <cutils/properties.h> #include <cutils/memory.h> +#include <utils/CallStack.h> #include <utils/String8.h> #include "egldefs.h" @@ -147,6 +148,10 @@ static int gl_no_context() { if (egl_tls_t::logNoContextCall()) { LOGE("call to OpenGL ES API with no current context " "(logged once per thread)"); + LOGE("call stack before error:"); + CallStack stack; + stack.update(); + stack.dump(); } return 0; } diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index 7d5d01084f..ba5d29a17d 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -367,7 +367,12 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, if (cnx->egl.eglGetConfigAttrib(iDpy, iConfig, EGL_NATIVE_VISUAL_ID, &format)) { if (format != 0) { - native_window_set_buffers_geometry(window, 0, 0, format); + int err = native_window_set_buffers_format(window, format); + if (err != 0) { + LOGE("error setting native window pixel format: %s (%d)", + strerror(-err), err); + return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + } } } diff --git a/opengl/libs/GLES2_dbg/Android.mk b/opengl/libs/GLES2_dbg/Android.mk index 9f6e68c4da..c2b1142bc3 100644 --- a/opengl/libs/GLES2_dbg/Android.mk +++ b/opengl/libs/GLES2_dbg/Android.mk @@ -31,15 +31,13 @@ ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true) LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER endif -ifneq ($(TARGET_SIMULATOR),true) - # we need to access the private Bionic header <bionic_tls.h> - # on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER - # behavior from the bionic Android.mk file - ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true) - LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER - endif - LOCAL_C_INCLUDES += bionic/libc/private +# we need to access the private Bionic header <bionic_tls.h> +# on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER +# behavior from the bionic Android.mk file +ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true) + LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER endif +LOCAL_C_INCLUDES += bionic/libc/private LOCAL_MODULE:= libGLESv2_dbg LOCAL_MODULE_TAGS := optional diff --git a/opengl/libs/GLES2_dbg/test/Android.mk b/opengl/libs/GLES2_dbg/test/Android.mk index 14a84b447f..8708d439df 100644 --- a/opengl/libs/GLES2_dbg/test/Android.mk +++ b/opengl/libs/GLES2_dbg/test/Android.mk @@ -27,9 +27,7 @@ LOCAL_MODULE:= libGLESv2_dbg_test ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true) LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER endif -ifneq ($(TARGET_SIMULATOR),true) - LOCAL_C_INCLUDES += bionic/libc/private -endif +LOCAL_C_INCLUDES += bionic/libc/private LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES diff --git a/opengl/specs/EGL_ANDROID_blob_cache.txt b/opengl/specs/EGL_ANDROID_blob_cache.txt new file mode 100644 index 0000000000..55dc9004a1 --- /dev/null +++ b/opengl/specs/EGL_ANDROID_blob_cache.txt @@ -0,0 +1,208 @@ +Name + + ANDROID_blob_cache + +Name Strings + + EGL_ANDROID_blob_cache + +Contributors + + Jamie Gennis + +Contact + + Jamie Gennis, Google Inc. (jgennis 'at' google.com) + +Status + + Draft. + +Version + + Version 1, April 22, 2011 + +Number + + EGL Extension #XXX + +Dependencies + + Requires EGL 1.0 + + This extension is written against the wording of the EGL 1.4 Specification + +Overview + + Shader compilation and optimization has been a troublesome aspect of OpenGL + programming for a long time. It can consume seconds of CPU cycles during + application start-up. Additionally, state-based re-compiles done + internally by the drivers add an unpredictable element to application + performance tuning, often leading to occasional pauses in otherwise smooth + animations. + + This extension provides a mechanism through which client API + implementations may cache shader binaries after they are compiled. It may + then retrieve those cached shaders during subsequent executions of the same + program. The management of the cache is handled by the application (or + middleware), allowing it to be tuned to a particular platform or + environment. + + While the focus of this extension is on providing a persistent cache for + shader binaries, it may also be useful for caching other data. This is + perfectly acceptable, but the guarantees provided (or lack thereof) were + designed around the shader use case. + + Note that although this extension is written as if the application + implements the caching functionality, on the Android OS it is implemented + as part of the Android EGL module. This extension is not exposed to + applications on Android, but will be used automatically in every + application that uses EGL if it is supported by the underlying + device-specific EGL implementation. + +New Types + + /* + * EGLsizei is a signed integer type for representing the size of a memory + * buffer. + */ + #include <khrplatform.h> + typedef khronos_ssize_t EGLsizei; + + /* + * EGLSetBlobFunc is a pointer to an application-provided function that a + * client API implementation may use to insert a key/value pair into the + * cache. + */ + typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize, + const void* value, EGLsizei valueSize) + + /* + * EGLGetBlobFunc is a pointer to an application-provided function that a + * client API implementation may use to retrieve a cached value from the + * cache. + */ + typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize, + void* value, EGLsizei valueSize) + +New Procedures and Functions + + void eglSetBlobCacheFuncs(EGLDisplay dpy, + EGLSetBlobFunc set, + EGLGetBlobFunc get); + +New Tokens + + None. + +Changes to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) + + Add a new subsection after Section 3.8, page 50 + (Synchronization Primitives) + + "3.9 Persistent Caching + + In order to facilitate persistent caching of internal client API state that + is slow to compute or collect, the application may specify callback + function pointers through which the client APIs can request data be cached + and retrieved. The command + + void eglSetBlobCacheFuncs(EGLDisplay dpy, + EGLSetBlobFunc set, EGLGetBlobFunc get); + + sets the callback function pointers that client APIs associated with + display <dpy> can use to interact with caching functionality provided by + the application. <set> points to a function that inserts a new value into + the cache and associates it with the given key. <get> points to a function + that retrieves from the cache the value associated with a given key. The + semantics of these callback functions are described in Section 3.9.1 (Cache + Operations). + + Cache functions may only be specified once during the lifetime of an + EGLDisplay. The <set> and <get> functions may be called at any time and + from any thread from the time at which eglSetBlobCacheFuncs is called until + the time that the last resource associated with <dpy> is deleted and <dpy> + itself is terminated. Concurrent calls to these functions from different + threads is also allowed. + + If eglSetBlobCacheFuncs generates an error then all client APIs must behave + as though eglSetBlobCacheFuncs was not called for the display <dpy>. If + <set> or <get> is NULL then an EGL_BAD_PARAMETER error is generated. If a + successful eglSetBlobCacheFuncs call was already made for <dpy> and the + display has not since been terminated then an EGL_BAD_PARAMETER error is + generated. + + 3.9.1 Cache Operations + + To insert a new binary value into the cache and associate it with a given + key, a client API implementation can call the application-provided callback + function + + void (*set) (const void* key, EGLsizei keySize, const void* value, + EGLsizei valueSize) + + <key> and <value> are pointers to the beginning of the key and value, + respectively, that are to be inserted. <keySize> and <valueSize> specify + the size in bytes of the data pointed to by <key> and <value>, + respectively. + + No guarantees are made as to whether a given key/value pair is present in + the cache after the set call. If a different value has been associated + with the given key in the past then it is undefined which value, if any, is + associated with the key after the set call. Note that while there are no + guarantees, the cache implementation should attempt to cache the most + recently set value for a given key. + + To retrieve the binary value associated with a given key from the cache, a + client API implementation can call the application-provided callback + function + + EGLsizei (*get) (const void* key, EGLsizei keySize, void* value, + EGLsizei valueSize) + + <key> is a pointer to the beginning of the key. <keySize> specifies the + size in bytes of the binary key pointed to by <key>. If the cache contains + a value associated with the given key then the size of that binary value in + bytes is returned. Otherwise 0 is returned. + + If the cache contains a value for the given key and its size in bytes is + less than or equal to <valueSize> then the value is written to the memory + pointed to by <value>. Otherwise nothing is written to the memory pointed + to by <value>. + +Issues + + 1. How should errors be handled in the callback functions? + + RESOLVED: No guarantees are made about the presence of values in the cache, + so there should not be a need to return error information to the client API + implementation. The cache implementation can simply drop a value if it + encounters an error during the 'set' callback. Similarly, it can simply + return 0 if it encouters an error in a 'get' callback. + + 2. When a client API driver gets updated, that may need to invalidate + previously cached entries. How can the driver handle this situation? + + RESPONSE: There are a number of ways the driver can handle this situation. + The recommended way is to include the driver version in all cache keys. + That way each driver version will use a set of cache keys that are unique + to that version, and conflicts should never occur. Updating the driver + could then leave a number of values in the cache that will never be + requested again. If needed, the cache implementation can handle those + values in some way, but the driver does not need to take any special + action. + + 3. How much data can be stored in the cache? + + RESPONSE: This is entirely dependent upon the cache implementation. + Presumably it will be tuned to store enough data to be useful, but not + enough to become problematic. :) + +Revision History + +#2 (Jamie Gennis, April 25, 2011) + - Swapped the order of the size and pointer arguments to the get and set + functions. + +#1 (Jamie Gennis, April 22, 2011) + - Initial draft. diff --git a/opengl/specs/EGL_ANDROID_recordable.txt b/opengl/specs/EGL_ANDROID_recordable.txt new file mode 100644 index 0000000000..cf44465198 --- /dev/null +++ b/opengl/specs/EGL_ANDROID_recordable.txt @@ -0,0 +1,113 @@ +Name + + ANDROID_recordable + +Name Strings + + EGL_ANDROID_recordable + +Contributors + + Jamie Gennis + +Contact + + Jamie Gennis, Google Inc. (jgennis 'at' google.com) + +Status + + Draft. + +Version + + Version 1, July 8, 2011 + +Number + + EGL Extension #XXX + +Dependencies + + Requires EGL 1.0 + + This extension is written against the wording of the EGL 1.4 Specification + +Overview + + Android supports a number of different ANativeWindow implementations that + can be used to create an EGLSurface. One implementation, which records the + rendered image as a video each time eglSwapBuffers gets called, may have + some device-specific restrictions. Because of this, some EGLConfigs may be + incompatible with these ANativeWindows. This extension introduces a new + boolean EGLConfig attribute that indicates whether the EGLConfig supports + rendering to an ANativeWindow that records images to a video. + +New Types + + None. + +New Procedures and Functions + + None. + +New Tokens + + Accepted by the <attribute> parameter of eglGetConfigAttrib and + the <attrib_list> parameter of eglChooseConfig: + + EGL_RECORDABLE_ANDROID 0xXXXX + +Changes to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) + + Section 3.4, Configuration Management, add a row to Table 3.1. + + Attribute Type Notes + ---------------------- ------- -------------------------- + EGL_RECORDABLE_ANDROID boolean whether video recording is + supported + + Section 3.4, Configuration Management, add a row to Table 3.4. + + Attribute Default Selection Sort Sort + Criteria Order Priority + ---------------------- ------------- --------- ----- -------- + EGL_RECORDABLE_ANDROID EGL_DONT_CARE Exact None + + Section 3.4, Configuration Management, add a paragraph at the end of the + subsection titled Other EGLConfig Attribute Descriptions. + + EGL_RECORDABLE_ANDROID is a boolean indicating whether the config may + be used to create an EGLSurface from an ANativeWindow that is a video + recorder as indicated by the NATIVE_WINDOW_IS_VIDEO_RECORDER query on + the ANativeWindow. + + Section 3.4.1, Querying Configurations, change the last paragraph as follow + + EGLConfigs are not sorted with respect to the parameters + EGL_BIND_TO_TEXTURE_RGB, EGL_BIND_TO_TEXTURE_RGBA, EGL_CONFORMANT, + EGL_LEVEL, EGL_NATIVE_RENDERABLE, EGL_MAX_SWAP_INTERVAL, + EGL_MIN_SWAP_INTERVAL, EGL_RENDERABLE_TYPE, EGL_SURFACE_TYPE, + EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RED_VALUE, + EGL_TRANSPARENT_GREEN_VALUE, EGL_TRANSPARENT_BLUE_VALUE, and + EGL_RECORDABLE_ANDROID. + +Issues + + 1. Should this functionality be exposed as a new attribute or as a bit in + the EGL_SURFACE_TYPE bitfield? + + RESOLVED: It should be a new attribute. It does not make sense to use up a + bit in the limit-size bitfield for a platform-specific extension. + + 2. How should the new attribute affect the sorting of EGLConfigs? + + RESOLVED: It should not affect sorting. Some implementations may not have + any drawback associated with using a recordable EGLConfig. Such + implementations should not have to double-up some of their configs to one sort earlier than . + Implementations that do have drawbacks can use the existing caveat + mechanism to report this drawback to the client. + +Revision History + +#1 (Jamie Gennis, July 8, 2011) + - Initial draft. diff --git a/opengl/specs/README b/opengl/specs/README new file mode 100644 index 0000000000..2fa258777f --- /dev/null +++ b/opengl/specs/README @@ -0,0 +1,12 @@ +This directory contains OpenGL ES and EGL extension specifications that have +been or are being defined for Android. + +The table below tracks usage of EGL enumerant values that have been reserved +for use by Android extensions. + + Value Extension +---------------- ---------------------------------- +0x3140 EGL_ANDROID_image_native_buffer +0x3141 (unused) +0x3142 EGL_ANDROID_recordable +0x3143 - 0x314F (unused) diff --git a/opengl/tests/EGLTest/Android.mk b/opengl/tests/EGLTest/Android.mk new file mode 100644 index 0000000000..92d7eb12ac --- /dev/null +++ b/opengl/tests/EGLTest/Android.mk @@ -0,0 +1,37 @@ +# Build the unit tests. +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := EGL_test + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := \ + EGL_test.cpp \ + +LOCAL_SHARED_LIBRARIES := \ + libEGL \ + libcutils \ + libstlport \ + libutils \ + +LOCAL_STATIC_LIBRARIES := \ + libgtest \ + libgtest_main \ + +LOCAL_C_INCLUDES := \ + bionic \ + bionic/libstdc++/include \ + external/gtest/include \ + external/stlport/stlport \ + +include $(BUILD_EXECUTABLE) + +# Include subdirectory makefiles +# ============================================================ + +# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework +# team really wants is to build the stuff defined by this makefile. +ifeq (,$(ONE_SHOT_MAKEFILE)) +include $(call first-makefiles-under,$(LOCAL_PATH)) +endif diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp new file mode 100644 index 0000000000..337ad33ebe --- /dev/null +++ b/opengl/tests/EGLTest/EGL_test.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include <utils/String8.h> + +#include <EGL/egl.h> + +namespace android { + +class EGLTest : public ::testing::Test { +protected: + EGLDisplay mEglDisplay; + +protected: + EGLTest() : + mEglDisplay(EGL_NO_DISPLAY) { + } + + virtual void SetUp() { + mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + + EGLint majorVersion; + EGLint minorVersion; + EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion)); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + RecordProperty("EglVersionMajor", majorVersion); + RecordProperty("EglVersionMajor", minorVersion); + } + + virtual void TearDown() { + EGLBoolean success = eglTerminate(mEglDisplay); + ASSERT_EQ(EGL_TRUE, success); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + } +}; + +TEST_F(EGLTest, DISABLED_EGLConfigEightBitFirst) { + + EGLint numConfigs; + EGLConfig config; + EGLBoolean success; + EGLint attrs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs); + ASSERT_EQ(EGL_TRUE, success); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + ASSERT_GE(numConfigs, 1); + + EGLint components[3]; + + success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]); + ASSERT_EQ(EGL_TRUE, success); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]); + ASSERT_EQ(EGL_TRUE, success); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]); + ASSERT_EQ(EGL_TRUE, success); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + + EXPECT_GE(components[0], 8); + EXPECT_GE(components[1], 8); + EXPECT_GE(components[2], 8); +} + +TEST_F(EGLTest, EGLConfigRGBA8888First) { + + EGLint numConfigs; + EGLConfig config; + EGLBoolean success; + EGLint attrs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_NONE + }; + + success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs); + ASSERT_EQ(EGL_TRUE, success); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + ASSERT_GE(numConfigs, 1); + + EGLint components[4]; + + success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]); + ASSERT_EQ(EGL_TRUE, success); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]); + ASSERT_EQ(EGL_TRUE, success); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]); + ASSERT_EQ(EGL_TRUE, success); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]); + ASSERT_EQ(EGL_TRUE, success); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + + EXPECT_GE(components[0], 8); + EXPECT_GE(components[1], 8); + EXPECT_GE(components[2], 8); + EXPECT_GE(components[3], 8); +} + + +} diff --git a/opengl/tests/gl2_jni/Android.mk b/opengl/tests/gl2_jni/Android.mk index e8b6c57f47..5d90ff68e0 100644 --- a/opengl/tests/gl2_jni/Android.mk +++ b/opengl/tests/gl2_jni/Android.mk @@ -2,8 +2,6 @@ # OpenGL ES JNI sample # This makefile builds both an activity and a shared library. ######################################################################### -ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean - TOP_LOCAL_PATH:= $(call my-dir) # Build activity @@ -47,5 +45,3 @@ LOCAL_MODULE := libgl2jni include $(BUILD_SHARED_LIBRARY) - -endif # TARGET_SIMULATOR diff --git a/opengl/tests/gl_jni/Android.mk b/opengl/tests/gl_jni/Android.mk index 4acd91f4a9..3d20e7281c 100644 --- a/opengl/tests/gl_jni/Android.mk +++ b/opengl/tests/gl_jni/Android.mk @@ -2,8 +2,6 @@ # OpenGL ES JNI sample # This makefile builds both an activity and a shared library. ######################################################################### -ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean - TOP_LOCAL_PATH:= $(call my-dir) # Build activity @@ -49,5 +47,3 @@ LOCAL_ARM_MODE := arm include $(BUILD_SHARED_LIBRARY) - -endif # TARGET_SIMULATOR diff --git a/opengl/tests/gl_perfapp/Android.mk b/opengl/tests/gl_perfapp/Android.mk index 4b79569dfa..65e50e9b0c 100644 --- a/opengl/tests/gl_perfapp/Android.mk +++ b/opengl/tests/gl_perfapp/Android.mk @@ -2,8 +2,6 @@ # OpenGL ES Perf App # This makefile builds both an activity and a shared library. ######################################################################### -ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean - TOP_LOCAL_PATH:= $(call my-dir) # Build activity @@ -50,5 +48,3 @@ LOCAL_MODULE := libglperf include $(BUILD_SHARED_LIBRARY) - -endif # TARGET_SIMULATOR diff --git a/opengl/tests/gldual/Android.mk b/opengl/tests/gldual/Android.mk index f1a998a01b..b4b378ec46 100644 --- a/opengl/tests/gldual/Android.mk +++ b/opengl/tests/gldual/Android.mk @@ -2,8 +2,6 @@ # OpenGL ES JNI sample # This makefile builds both an activity and a shared library. ######################################################################### -ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean - TOP_LOCAL_PATH:= $(call my-dir) # Build activity @@ -47,5 +45,3 @@ LOCAL_MODULE := libgldualjni include $(BUILD_SHARED_LIBRARY) - -endif # TARGET_SIMULATOR diff --git a/opengl/tests/testPauseResume/Android.mk b/opengl/tests/testPauseResume/Android.mk index 450473a19d..cf8bdc35f0 100644 --- a/opengl/tests/testPauseResume/Android.mk +++ b/opengl/tests/testPauseResume/Android.mk @@ -2,8 +2,6 @@ # OpenGL ES JNI sample # This makefile builds both an activity and a shared library. ######################################################################### -ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean - TOP_LOCAL_PATH:= $(call my-dir) # Build activity @@ -18,5 +16,3 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_PACKAGE_NAME := TestEGL include $(BUILD_PACKAGE) - -endif # TARGET_SIMULATOR diff --git a/opengl/tests/testViewport/Android.mk b/opengl/tests/testViewport/Android.mk index ab3780961a..9980e7dbc7 100644 --- a/opengl/tests/testViewport/Android.mk +++ b/opengl/tests/testViewport/Android.mk @@ -2,8 +2,6 @@ # OpenGL ES JNI sample # This makefile builds both an activity and a shared library. ######################################################################### -ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean - TOP_LOCAL_PATH:= $(call my-dir) # Build activity @@ -22,5 +20,3 @@ LOCAL_PACKAGE_NAME := TestViewport LOCAL_SDK_VERSION := 8 include $(BUILD_PACKAGE) - -endif # TARGET_SIMULATOR diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index c618263717..f67c82efcd 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -26,13 +26,6 @@ ifeq ($(TARGET_BOARD_PLATFORM), s5pc110) endif -# need "-lrt" on Linux simulator to pick up clock_gettime -ifeq ($(TARGET_SIMULATOR),true) - ifeq ($(HOST_OS),linux) - LOCAL_LDLIBS += -lrt -lpthread - endif -endif - LOCAL_SHARED_LIBRARIES := \ libcutils \ libhardware \ diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp index 33125c487e..7bf3e0ae09 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -99,6 +99,31 @@ uint32_t DisplayHardware::getMaxViewportDims() const { mMaxViewportDims[0] : mMaxViewportDims[1]; } +static status_t selectConfigForPixelFormat( + EGLDisplay dpy, + EGLint const* attrs, + PixelFormat format, + EGLConfig* outConfig) +{ + EGLConfig config = NULL; + EGLint numConfigs = -1, n=0; + eglGetConfigs(dpy, NULL, 0, &numConfigs); + EGLConfig* const configs = new EGLConfig[numConfigs]; + eglChooseConfig(dpy, attrs, configs, numConfigs, &n); + for (int i=0 ; i<n ; i++) { + EGLint nativeVisualId = 0; + eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId); + if (nativeVisualId>0 && format == nativeVisualId) { + *outConfig = configs[i]; + delete [] configs; + return NO_ERROR; + } + } + delete [] configs; + return NAME_NOT_FOUND; +} + + void DisplayHardware::init(uint32_t dpy) { mNativeWindow = new FramebufferNativeWindow(); @@ -108,6 +133,9 @@ void DisplayHardware::init(uint32_t dpy) exit(0); } + int format; + ANativeWindow const * const window = mNativeWindow.get(); + window->query(window, NATIVE_WINDOW_FORMAT, &format); mDpiX = mNativeWindow->xdpi; mDpiY = mNativeWindow->ydpi; mRefreshRate = fbDev->fps; @@ -116,11 +144,13 @@ void DisplayHardware::init(uint32_t dpy) EGLint numConfigs=0; EGLSurface surface; EGLContext context; + EGLBoolean result; + status_t err; // initialize EGL EGLint attribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_NONE, 0, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_NONE, 0, EGL_NONE }; @@ -141,9 +171,8 @@ void DisplayHardware::init(uint32_t dpy) eglInitialize(display, NULL, NULL); eglGetConfigs(display, NULL, 0, &numConfigs); - EGLConfig config; - status_t err = EGLUtils::selectConfigForNativeWindow( - display, attribs, mNativeWindow.get(), &config); + EGLConfig config = NULL; + err = selectConfigForPixelFormat(display, attribs, format, &config); LOGE_IF(err, "couldn't find an EGLConfig matching the screen format"); EGLint r,g,b,a; @@ -224,7 +253,11 @@ void DisplayHardware::init(uint32_t dpy) * Gather OpenGL ES extensions */ - eglMakeCurrent(display, surface, surface, context); + result = eglMakeCurrent(display, surface, surface, context); + if (!result) { + LOGE("Couldn't create a working GLES context. check logs. exiting..."); + exit(0); + } GLExtensions& extensions(GLExtensions::getInstance()); extensions.initWithGLStrings( diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 35e29a6315..f3b6c4dd23 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -188,22 +188,37 @@ void Layer::setGeometry(hwc_layer_t* hwcl) return; } + /* + * Transformations are applied in this order: + * 1) buffer orientation/flip/mirror + * 2) state transformation (window manager) + * 3) layer orientation (screen orientation) + * (NOTE: the matrices are multiplied in reverse order) + */ + + const Transform bufferOrientation(mCurrentTransform); + const Transform& stateTransform(s.transform); + const Transform layerOrientation(mOrientation); + + const Transform tr(layerOrientation * stateTransform * bufferOrientation); + + // this gives us only the "orientation" component of the transform + const uint32_t finalTransform = tr.getOrientation(); + // we can only handle simple transformation - if (mOrientation & Transform::ROT_INVALID) { + if (finalTransform & Transform::ROT_INVALID) { hwcl->flags = HWC_SKIP_LAYER; return; } - // FIXME: shouldn't we take the state's transform into account here? - - Transform tr(Transform(mOrientation) * Transform(mCurrentTransform)); - hwcl->transform = tr.getOrientation(); + hwcl->transform = finalTransform; if (!isOpaque()) { hwcl->blending = mPremultipliedAlpha ? HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE; } + // scaling is already applied in mTransformedBounds hwcl->displayFrame.left = mTransformedBounds.left; hwcl->displayFrame.top = mTransformedBounds.top; hwcl->displayFrame.right = mTransformedBounds.right; diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index bcd8c83325..c86c659ad6 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -228,13 +228,18 @@ void LayerBase::validateVisibility(const Transform& planeTransform) const Layer::State& s(drawingState()); const Transform tr(planeTransform * s.transform); const bool transformed = tr.transformed(); - + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + const uint32_t hw_h = hw.getHeight(); + uint32_t w = s.w; uint32_t h = s.h; tr.transform(mVertices[0], 0, 0); tr.transform(mVertices[1], 0, h); tr.transform(mVertices[2], w, h); tr.transform(mVertices[3], w, 0); + for (size_t i=0 ; i<4 ; i++) + mVertices[i][1] = hw_h - mVertices[i][1]; + if (UNLIKELY(transformed)) { // NOTE: here we could also punt if we have too many rectangles // in the transparent region diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cccab4a623..680814cf23 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -276,7 +276,8 @@ status_t SurfaceFlinger::readyToRun() glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrthof(0, w, h, 0, 0, 1); + // put the origin in the left-bottom corner + glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h mReadyToRunBarrier.open(); @@ -1550,8 +1551,18 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) * Dump SurfaceFlinger global state */ - snprintf(buffer, SIZE, "SurfaceFlinger global state\n"); + snprintf(buffer, SIZE, "SurfaceFlinger global state:\n"); result.append(buffer); + + const GLExtensions& extensions(GLExtensions::getInstance()); + snprintf(buffer, SIZE, "GLES: %s, %s, %s\n", + extensions.getVendor(), + extensions.getRenderer(), + extensions.getVersion()); + result.append(buffer); + snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension()); + result.append(buffer); + mWormholeRegion.dump(result, "WormholeRegion"); const DisplayHardware& hw(graphicPlane(0).displayHardware()); snprintf(buffer, SIZE, @@ -1791,7 +1802,7 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked() } GLfloat vtx[8]; - const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} }; + const GLfloat texCoords[4][2] = { {0,1}, {0,1-v}, {u,1-v}, {u,1} }; glBindTexture(GL_TEXTURE_2D, tname); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -1800,6 +1811,22 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked() glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vtx); + /* + * Texture coordinate mapping + * + * u + * 1 +----------+---+ + * | | | | image is inverted + * | V | | w.r.t. the texture + * 1-v +----------+ | coordinates + * | | + * | | + * | | + * 0 +--------------+ + * 0 1 + * + */ + class s_curve_interpolator { const float nbFrames, s, v; public: @@ -1824,10 +1851,10 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked() const GLfloat h = hw_h - (hw_h * v); const GLfloat x = (hw_w - w) * 0.5f; const GLfloat y = (hw_h - h) * 0.5f; - vtx[0] = x; vtx[1] = y + h; - vtx[2] = x; vtx[3] = y; - vtx[4] = x + w; vtx[5] = y; - vtx[6] = x + w; vtx[7] = y + h; + vtx[0] = x; vtx[1] = y; + vtx[2] = x; vtx[3] = y + h; + vtx[4] = x + w; vtx[5] = y + h; + vtx[6] = x + w; vtx[7] = y; } }; @@ -1842,15 +1869,20 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked() const GLfloat h = 1.0f; const GLfloat x = (hw_w - w) * 0.5f; const GLfloat y = (hw_h - h) * 0.5f; - vtx[0] = x; vtx[1] = y + h; - vtx[2] = x; vtx[3] = y; - vtx[4] = x + w; vtx[5] = y; - vtx[6] = x + w; vtx[7] = y + h; + vtx[0] = x; vtx[1] = y; + vtx[2] = x; vtx[3] = y + h; + vtx[4] = x + w; vtx[5] = y + h; + vtx[6] = x + w; vtx[7] = y; } }; // the full animation is 24 frames - const int nbFrames = 12; + char value[PROPERTY_VALUE_MAX]; + property_get("debug.sf.electron_frames", value, "24"); + int nbFrames = (atoi(value) + 1) >> 1; + if (nbFrames <= 0) // just in case + nbFrames = 24; + s_curve_interpolator itr(nbFrames, 7.5f); s_curve_interpolator itg(nbFrames, 8.0f); s_curve_interpolator itb(nbFrames, 8.5f); @@ -2225,10 +2257,11 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, // invert everything, b/c glReadPixel() below will invert the FB glViewport(0, 0, sw, sh); glScissor(0, 0, sw, sh); + glEnable(GL_SCISSOR_TEST); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); - glOrthof(0, hw_w, 0, hw_h, 0, 1); + glOrthof(0, hw_w, hw_h, 0, 0, 1); glMatrixMode(GL_MODELVIEW); // redraw the screen entirely... @@ -2244,6 +2277,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, } // XXX: this is needed on tegra + glEnable(GL_SCISSOR_TEST); glScissor(0, 0, sw, sh); // check for errors and return screen capture diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp index 0467a14604..4cedcbf86c 100644 --- a/services/surfaceflinger/Transform.cpp +++ b/services/surfaceflinger/Transform.cpp @@ -308,6 +308,7 @@ uint32_t Transform::type() const scale = true; } } else { + // there is a skew component and/or a non 90 degrees rotation flags = ROT_INVALID; } |