---
diff --git a/Kconfig b/Kconfig
index e2d4c61..7b8b559 100644
--- a/Kconfig
+++ b/Kconfig
@@ -9,6 +9,11 @@ choice
---help---
Use the FIFO based RPC channel
+ config BBQUE_RPC_BINDER
+ depends on TARGET_ANDROID
+ bool "BINDER based"
+ ---help---
+ Use the BINDER based RPC channel
endchoice
config BBQUE_TEST_PLATFORM_DATA
diff --git a/include/bbque/binder_service.cc b/include/bbque/binder_service.cc
new file mode 100644
index 0000000..b1a9a8c
--- /dev/null
+++ b/include/bbque/binder_service.cc
@@ -0,0 +1,46 @@
+#include <bbque/binder_service.h>
+
+//Common code shared by client and server
+
+ IMPLEMENT_META_INTERFACE(Bbque, BBQUE_SERVICE_NAME);
+
+//Client side -- the sending one
+
+BpBbque::BpBbque(const sp<IBinder>& impl) : BpInterface<IBbque>(impl) {
+ }
+
+void BpBbque::push(void *push_data, size_t size) {
+ Parcel data;
+ data.writeInterfaceToken(IBbque::getInterfaceDescriptor());
+ data.write(push_data, size);
+ remote()->transact(BBQUE_BINDER_TRANSACTION_CODE, data, NULL, IBinder::FLAG_ONEWAY);
+ data.freeData();
+ }
+
+//Server side -- the receiving one
+
+Bbque::Bbque() {
+ //retrive Android's servicemanager
+ sm = defaultServiceManager();
+}
+
+ void Bbque::push(void *push_data, size_t size) {
+ //This should never be called... needed because of the common interface
+ assert(false);
+ }
+
+// Helper function to get a hold of the "Bbque" service.
+sp<IBbque> Bbque::getBbqueServ(char *name) {
+ assert(sm != 0);
+ //get an handle to the desired service...
+ binder = sm->getService(String16(name));
+ assert(binder != 0);
+ //... and cast it
+ Bbquesp = interface_cast<IBbque>(binder);
+ assert(Bbquesp != 0);
+ return Bbquesp;
+}
+
+
+//----------------------------------------------------------------------------------------------------------------------------------------//
+
diff --git a/include/bbque/binder_service.h b/include/bbque/binder_service.h
new file mode 100644
index 0000000..ea1ea3e
--- /dev/null
+++ b/include/bbque/binder_service.h
@@ -0,0 +1,88 @@
+/*
+ * Author: Gabriel Burca <gburca dash binder at ebixio dot com>
+ */
+
+
+#include <stdlib.h>
+
+#include <utils/RefBase.h>
+#include <utils/Log.h>
+#include <utils/TextOutput.h>
+
+
+#include <binder/IInterface.h>
+#include <binder/IBinder.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+
+#include "bbque/plugins/rpc_channel.h"
+
+using namespace android;
+
+
+#define MAXPCKS 2
+#define BBQUE_BINDER_NAME_LENGTH 16
+#define BBQUE_BINDER_TRANSACTION_CODE 21
+#define BBQUE_RPC_BINDER_MAJOR_VERSION 1
+#define BBQUE_RPC_BINDER_MINOR_VERSION 0
+#define BBQUE_SERVICE_NAME "bbque"
+
+// Where to print the parcel contents: aout, alog, aerr. alog doesn't seem to work.
+#define PLOG aout
+
+// Interface - Shared by server and client
+class IBbque : public IInterface {
+ public:
+
+ // Sends a user-provided value to the service
+ virtual void push(void *push_data, size_t size) = 0;
+
+ DECLARE_META_INTERFACE(Bbque);
+};
+
+// Client
+class BpBbque : public BpInterface<IBbque> {
+ public:
+ BpBbque(const sp<IBinder>& impl);
+
+ virtual void push(void *push_data, size_t size);
+
+
+};
+
+// Server
+class BnBbque : public BnInterface<IBbque> {
+ public:
+
+ BnBbque();
+
+ ssize_t getNextMsg(bbque::plugins::RPCChannelIF::rpc_msg_ptr_t & msg);
+
+ private:
+
+ pthread_mutex_t m_in;
+ pthread_cond_t newMsg_in;
+
+ short unread;
+ short i_idx, r_idx;
+ Parcel *incoming;
+ virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+
+};
+
+class Bbque : public BnBbque {
+ public:
+
+ Bbque();
+ virtual void push(void *push_data, size_t size);
+ sp<IBbque> getBbqueServ(char *name);
+
+ private:
+
+ sp<IServiceManager> sm;
+ sp<IBinder> binder;
+ sp<IBbque> Bbquesp;
+};
+
+
diff --git a/include/bbque/binder_service_client.h b/include/bbque/binder_service_client.h
new file mode 100644
index 0000000..55aed08
--- /dev/null
+++ b/include/bbque/binder_service_client.h
@@ -0,0 +1,125 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
+ vi:ai:tabstop=8:shiftwidth=4:softtabstop=4:expandtab
+*/
+
+/*
+ * Author: Gabriel Burca <gburca dash binder at ebixio dot com>
+ *
+ * Sample code for using binders in Android from C++
+ *
+ * The Bbque service provides 3 operations: push(), alert(), add(). See
+ * the IBbque class documentation to see what they do.
+ *
+ * Both the server and client code are included below.
+ *
+ * To view the log output:
+ * adb logcat -v time binder_Bbque:* *:S
+ *
+ * To run, create 2 adb shell sessions. In the first one run "binder" with no
+ * arguments to start the service. In the second one run "binder N" where N is
+ * an integer, to start a client that connects to the service and calls push(N),
+ * alert(), and add(N, 5).
+ */
+
+#define LOG_TAG "binder_service"
+
+/* For relevant code see:
+ frameworks/base/{include,libs}/binder/{IInterface,Parcel}.h
+ frameworks/base/include/utils/{Errors,RefBase}.h
+ */
+
+#include <stdlib.h>
+
+#include <utils/RefBase.h>
+#include <utils/Log.h>
+#include <utils/TextOutput.h>
+
+
+#include <binder/IInterface.h>
+#include <binder/IBinder.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+
+#include "bbque/plugins/rpc_channel.h"
+
+using namespace android;
+
+namespace br = bbque::rtlib;
+
+#define MAXPCKS 10
+#define BBQUE_RPC_BINDER_MAJOR_VERSION 1
+#define BBQUE_RPC_BINDER_MINOR_VERSION 0
+
+#define INFO(...) \
+ do { \
+ printf(__VA_ARGS__); \
+ printf("\n"); \
+ printf(__VA_ARGS__); \
+ } while(0)
+
+void assert_fail(const char *file, int line, const char *func, const char *expr);
+
+#define ASSERT(e) \
+ do { \
+ if (!(e)) \
+ assert_fail(__FILE__, __LINE__, __func__, #e); \
+ } while(0)
+
+
+// Where to print the parcel contents: aout, alog, aerr. alog doesn't seem to work.
+#define PLOG aout
+
+
+
+// Interface (our AIDL) - Shared by server and client
+class IBbque : public IInterface {
+ public:
+ //bbque::rtlib::rpc_msg_type_t type;
+
+ // Sends a user-provided value to the service
+ virtual void push(void *push_data, size_t size) = 0;
+
+ DECLARE_META_INTERFACE(Bbque); // Expands to 5 lines below:
+ //static const android::String16 descriptor;
+ //static android::sp<IBbque> asInterface(const android::sp<android::IBinder>& obj);
+ //virtual const android::String16& getInterfaceDescriptor() const;
+ //IBbque();
+ //virtual ~IBbque();
+};
+
+// Client
+class BpBbque : public BpInterface<IBbque> {
+ public:
+ BpBbque(const sp<IBinder>& impl);
+
+ virtual void push(void *push_data, size_t size);
+
+
+};
+
+// Server
+class BnBbque : public BnInterface<IBbque> {
+ public:
+
+ pthread_mutex_t m_in;
+ pthread_cond_t newMsg_in;
+
+ short unread;
+ short i_idx, r_idx;
+ int result;
+ Parcel *incoming;
+
+ BnBbque();
+
+ ssize_t getNextMsg(bbque::plugins::RPCChannelIF::rpc_msg_ptr_t & msg);
+
+ virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+};
+
+class Bbque : public BnBbque {
+ virtual void push(void *push_data, size_t size);
+};
+
+sp<IBbque> getBbqueServ(std::string name);
+
diff --git a/include/bbque/
config.h.in b/include/bbque/
config.h.in
index 4b87a89..4b50f1e 100644
--- a/include/bbque/
config.h.in
+++ b/include/bbque/
config.h.in
@@ -103,6 +103,9 @@
/** Use FIFO based RPC channel */
#cmakedefine CONFIG_BBQUE_RPC_FIFO
+/** Use BINDER based RPC channel */
+#cmakedefine CONFIG_BBQUE_RPC_BINDER
+
/** Use Test Platform Data */
#cmakedefine CONFIG_BBQUE_TEST_PLATFORM_DATA
diff --git a/include/bbque/rtlib/rpc_binder_client.h b/include/bbque/rtlib/rpc_binder_client.h
new file mode 100644
index 0000000..8af751a
--- /dev/null
+++ b/include/bbque/rtlib/rpc_binder_client.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2012 Politecnico di Milano
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <
http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BBQUE_RPC_BINDER_CLIENT_H_
+#define BBQUE_RPC_BINDER_CLIENT_H_
+
+#include "bbque/rtlib.h"
+
+#include "bbque/rtlib/bbque_rpc.h"
+#include "bbque/rtlib/rpc_messages.h"
+#include "bbque/utils/utility.h"
+#include "bbque/cpp11/thread.h"
+
+#include "bbque/plugins/rpc_channel.h"
+
+#include <sys/epoll.h>
+
+
+#include <bbque/binder_service.h>
+
+namespace bbque { namespace rtlib {
+
+/**
+ * @brief Client side of the RPF BINDER channel
+ *
+ * Definition of the RPC protocol based on UNIX BINDERs to implement the
+ * Barbeque communication channel. This defines the communication protocol in
+ * terms of message format and functionalities.
+ * The communication protocol must be aligend with the RTLib supported
+ * services.
+ *
+ * @see bbque/rtlib.h
+ * @see bbque/rtlib/rpc_messages.h
+ */
+class BbqueRPC_BINDER_Client : public BbqueRPC {
+
+public:
+
+ BbqueRPC_BINDER_Client();
+
+ ~BbqueRPC_BINDER_Client();
+ void RpcBbqResp(rpc_msg_resp_t *r, ssize_t s);
+ /**
+ * @brief Get from BINDER a PreChange RPC message
+ */
+ void RpcBbqSyncpPreChange(rpc_msg_BBQ_SYNCP_PRECHANGE_t *msg, ssize_t bytes);
+
+ /**
+ * @brief Get from BINDER a SyncChange RPC message
+ */
+ void RpcBbqSyncpSyncChange(rpc_msg_BBQ_SYNCP_SYNCCHANGE_t *msg, ssize_t bytes);
+
+ /**
+ * @brief Get from BINDER a DoChange RPC message
+ */
+ void RpcBbqSyncpDoChange(rpc_msg_BBQ_SYNCP_DOCHANGE_t *msg, ssize_t bytes);
+
+ /**
+ * @brief Get from BINDER a PostChange RPC message
+ */
+ void RpcBbqSyncpPostChange(rpc_msg_BBQ_SYNCP_POSTCHANGE_t *msg, ssize_t bytes);
+ void setDone();
+
+protected:
+
+ RTLIB_ExitCode_t _Init(
+ const char *name);
+
+ RTLIB_ExitCode_t _Register(pregExCtx_t prec);
+
+ RTLIB_ExitCode_t _Unregister(pregExCtx_t prec);
+
+ RTLIB_ExitCode_t _Enable(pregExCtx_t prec);
+
+ RTLIB_ExitCode_t _Disable(pregExCtx_t prec);
+
+ RTLIB_ExitCode_t _ScheduleRequest(pregExCtx_t prec);
+
+ RTLIB_ExitCode_t _Set(pregExCtx_t prec,
+ RTLIB_Constraint* constraints, uint8_t count);
+
+ RTLIB_ExitCode_t _Clear(pregExCtx_t prec);
+
+ RTLIB_ExitCode_t _GGap(pregExCtx_t prec, uint8_t gap);
+
+ void _Exit();
+
+ inline uint32_t RpcMsgToken() {
+ return mypid;
+ }
+
+/******************************************************************************
+ * Synchronization Protocol Messages
+ ******************************************************************************/
+
+ RTLIB_ExitCode_t _SyncpPreChangeResp(
+ rpc_msg_token_t token,
+ pregExCtx_t prec,
+ uint32_t syncLatency);
+
+ RTLIB_ExitCode_t _SyncpSyncChangeResp(
+ rpc_msg_token_t token,
+ pregExCtx_t prec,
+ RTLIB_ExitCode_t sync);
+
+ RTLIB_ExitCode_t _SyncpPostChangeResp(
+ rpc_msg_token_t token,
+ pregExCtx_t prec,
+ RTLIB_ExitCode_t result);
+
+private:
+ char mypid_string[BBQUE_BINDER_NAME_LENGTH];
+
+ Bbque *d;
+
+ pid_t mypid;
+
+ char app_binder_servicename[BBQUE_BINDER_NAME_LENGTH];
+
+ std::string app_binder_path;
+
+ std::string bbque_binder_path;
+
+ int client_binder_fd;
+
+ int server_binder_fd;
+
+ bool done;
+
+ bool running;
+
+ std::thread ChTrd;
+
+ std::mutex trdStatus_mtx;
+
+ std::condition_variable trdStatus_cv;
+
+ /**
+ * @brief Serialize sending of command using the library
+ *
+ * The current implementation of the library allows to send a single
+ * command at each time for single library instance. This is required do
+ * properly handle responses from Barbque.
+ * This mutex should be used to protect the chResp responce attribute,
+ * which is always set to the last received response from Barbques.
+ *
+ * @see chResp
+ */
+ std::mutex chCommand_mtx;
+
+ /**
+ * @brief Signal the reception of a response from Barbeque
+ *
+ * Each time a new message has been received from Barbeque by the channel
+ * fetch thread, this variable is notified. Thus, commands could wait for
+ * a response by susepnding on it.
+ */
+ std::condition_variable chResp_cv;
+
+ /**
+ * @brief The last response reveiced by Barbeque
+ *
+ * This attribute should be always protected by the chCommand_mtx
+ */
+ rpc_msg_resp_t chResp;
+
+ RTLIB_ExitCode_t ChannelRelease();
+
+ RTLIB_ExitCode_t ChannelSetup();
+
+ RTLIB_ExitCode_t ChannelPair(const char *name);
+
+};
+
+} // namespace rtlib
+
+} // namespace bbque
+
+#endif // BBQUE_RPC_BINDER_CLIENT_H_
diff --git a/include/binder/Binder.h b/include/binder/Binder.h
new file mode 100644
index 0000000..ba3ac4b
--- /dev/null
+++ b/include/binder/Binder.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 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.
+ * 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.
+ */
+
+#ifndef ANDROID_BINDER_H
+#define ANDROID_BINDER_H
+
+#include <binder/IBinder.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class BBinder : public IBinder
+{
+public:
+ BBinder();
+
+ virtual const String16& getInterfaceDescriptor() const;
+ virtual bool isBinderAlive() const;
+ virtual status_t pingBinder();
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+ virtual status_t transact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+
+ virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0);
+
+ virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0,
+ wp<DeathRecipient>* outRecipient = NULL);
+
+ virtual void attachObject( const void* objectID,
+ void* object,
+ void* cleanupCookie,
+ object_cleanup_func func);
+ virtual void* findObject(const void* objectID) const;
+ virtual void detachObject(const void* objectID);
+
+ virtual BBinder* localBinder();
+
+protected:
+ virtual ~BBinder();
+
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+
+private:
+ BBinder(const BBinder& o);
+ BBinder& operator=(const BBinder& o);
+
+ class Extras;
+
+ Extras* mExtras;
+ void* mReserved0;
+};
+
+// ---------------------------------------------------------------------------
+
+class BpRefBase : public virtual RefBase
+{
+protected:
+ BpRefBase(const sp<IBinder>& o);
+ virtual ~BpRefBase();
+ virtual void onFirstRef();
+ virtual void onLastStrongRef(const void* id);
+ virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
+
+ inline IBinder* remote() { return mRemote; }
+ inline IBinder* remote() const { return mRemote; }
+
+private:
+ BpRefBase(const BpRefBase& o);
+ BpRefBase& operator=(const BpRefBase& o);
+
+ IBinder* const mRemote;
+ RefBase::weakref_type* mRefs;
+ volatile int32_t mState;
+};
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_BINDER_H
diff --git a/include/binder/BinderService.h b/include/binder/BinderService.h
new file mode 100644
index 0000000..6460268
--- /dev/null
+++ b/include/binder/BinderService.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef ANDROID_BINDER_SERVICE_H
+#define ANDROID_BINDER_SERVICE_H
+
+#include <stdint.h>
+
+#include <utils/Errors.h>
+#include <utils/String16.h>
+
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+template<typename SERVICE>
+class BinderService
+{
+public:
+ static status_t publish(bool allowIsolated = false) {
+ sp<IServiceManager> sm(defaultServiceManager());
+ return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
+ }
+
+ static void publishAndJoinThreadPool(bool allowIsolated = false) {
+ sp<IServiceManager> sm(defaultServiceManager());
+ sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
+ }
+
+ static void instantiate() { publish(); }
+
+ static status_t shutdown() {
+ return NO_ERROR;
+ }
+};
+
+
+}; // namespace android
+// ---------------------------------------------------------------------------
+#endif // ANDROID_BINDER_SERVICE_H
diff --git a/include/binder/BpBinder.h b/include/binder/BpBinder.h
new file mode 100644
index 0000000..7ef93aa
--- /dev/null
+++ b/include/binder/BpBinder.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_BPBINDER_H
+#define ANDROID_BPBINDER_H
+
+#include <binder/IBinder.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class BpBinder : public IBinder
+{
+public:
+ BpBinder(int32_t handle);
+
+ inline int32_t handle() const { return mHandle; }
+
+ virtual const String16& getInterfaceDescriptor() const;
+ virtual bool isBinderAlive() const;
+ virtual status_t pingBinder();
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+ virtual status_t transact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+
+ virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0);
+ virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0,
+ wp<DeathRecipient>* outRecipient = NULL);
+
+ virtual void attachObject( const void* objectID,
+ void* object,
+ void* cleanupCookie,
+ object_cleanup_func func);
+ virtual void* findObject(const void* objectID) const;
+ virtual void detachObject(const void* objectID);
+
+ virtual BpBinder* remoteBinder();
+
+ status_t setConstantData(const void* data, size_t size);
+ void sendObituary();
+
+ class ObjectManager
+ {
+ public:
+ ObjectManager();
+ ~ObjectManager();
+
+ void attach( const void* objectID,
+ void* object,
+ void* cleanupCookie,
+ IBinder::object_cleanup_func func);
+ void* find(const void* objectID) const;
+ void detach(const void* objectID);
+
+ void kill();
+
+ private:
+ ObjectManager(const ObjectManager&);
+ ObjectManager& operator=(const ObjectManager&);
+
+ struct entry_t
+ {
+ void* object;
+ void* cleanupCookie;
+ IBinder::object_cleanup_func func;
+ };
+
+ KeyedVector<const void*, entry_t> mObjects;
+ };
+
+protected:
+ virtual ~BpBinder();
+ virtual void onFirstRef();
+ virtual void onLastStrongRef(const void* id);
+ virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
+
+private:
+ const int32_t mHandle;
+
+ struct Obituary {
+ wp<DeathRecipient> recipient;
+ void* cookie;
+ uint32_t flags;
+ };
+
+ void reportOneDeath(const Obituary& obit);
+ bool isDescriptorCached() const;
+
+ mutable Mutex mLock;
+ volatile int32_t mAlive;
+ volatile int32_t mObitsSent;
+ Vector<Obituary>* mObituaries;
+ ObjectManager mObjects;
+ Parcel* mConstantData;
+ mutable String16 mDescriptorCache;
+};
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_BPBINDER_H
diff --git a/include/binder/IBinder.h b/include/binder/IBinder.h
new file mode 100644
index 0000000..8b84951
--- /dev/null
+++ b/include/binder/IBinder.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 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.
+ * 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.
+ */
+
+#ifndef ANDROID_IBINDER_H
+#define ANDROID_IBINDER_H
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+
+#define B_PACK_CHARS(c1, c2, c3, c4) \
+ ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class BBinder;
+class BpBinder;
+class IInterface;
+class Parcel;
+
+/**
+ * Base class and low-level protocol for a remotable object.
+ * You can derive from this class to create an object for which other
+ * processes can hold references to it. Communication between processes
+ * (method calls, property get and set) is down through a low-level
+ * protocol implemented on top of the transact() API.
+ */
+class IBinder : public virtual RefBase
+{
+public:
+ enum {
+ FIRST_CALL_TRANSACTION = 0x00000001,
+ LAST_CALL_TRANSACTION = 0x00ffffff,
+
+ PING_TRANSACTION = B_PACK_CHARS('_','P','N','G'),
+ DUMP_TRANSACTION = B_PACK_CHARS('_','D','M','P'),
+ INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
+ SYSPROPS_TRANSACTION = B_PACK_CHARS('_', 'S', 'P', 'R'),
+
+ // Corresponds to TF_ONE_WAY -- an asynchronous call.
+ FLAG_ONEWAY = 0x00000001
+ };
+
+ IBinder();
+
+ /**
+ * Check if this IBinder implements the interface named by
+ * @a descriptor. If it does, the base pointer to it is returned,
+ * which you can safely static_cast<> to the concrete C++ interface.
+ */
+ virtual sp<IInterface> queryLocalInterface(const String16& descriptor);
+
+ /**
+ * Return the canonical name of the interface provided by this IBinder
+ * object.
+ */
+ virtual const String16& getInterfaceDescriptor() const = 0;
+
+ virtual bool isBinderAlive() const = 0;
+ virtual status_t pingBinder() = 0;
+ virtual status_t dump(int fd, const Vector<String16>& args) = 0;
+
+ virtual status_t transact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0) = 0;
+
+ /**
+ * This method allows you to add data that is transported through
+ * IPC along with your IBinder pointer. When implementing a Binder
+ * object, override it to write your desired data in to @a outData.
+ * You can then call getConstantData() on your IBinder to retrieve
+ * that data, from any process. You MUST return the number of bytes
+ * written in to the parcel (including padding).
+ */
+ class DeathRecipient : public virtual RefBase
+ {
+ public:
+ virtual void binderDied(const wp<IBinder>& who) = 0;
+ };
+
+ /**
+ * Register the @a recipient for a notification if this binder
+ * goes away. If this binder object unexpectedly goes away
+ * (typically because its hosting process has been killed),
+ * then DeathRecipient::binderDied() will be called with a reference
+ * to this.
+ *
+ * The @a cookie is optional -- if non-NULL, it should be a
+ * memory address that you own (that is, you know it is unique).
+ *
+ * @note You will only receive death notifications for remote binders,
+ * as local binders by definition can't die without you dying as well.
+ * Trying to use this function on a local binder will result in an
+ * INVALID_OPERATION code being returned and nothing happening.
+ *
+ * @note This link always holds a weak reference to its recipient.
+ *
+ * @note You will only receive a weak reference to the dead
+ * binder. You should not try to promote this to a strong reference.
+ * (Nor should you need to, as there is nothing useful you can
+ * directly do with it now that it has passed on.)
+ */
+ virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0) = 0;
+
+ /**
+ * Remove a previously registered death notification.
+ * The @a recipient will no longer be called if this object
+ * dies. The @a cookie is optional. If non-NULL, you can
+ * supply a NULL @a recipient, and the recipient previously
+ * added with that cookie will be unlinked.
+ */
+ virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0,
+ wp<DeathRecipient>* outRecipient = NULL) = 0;
+
+ virtual bool checkSubclass(const void* subclassID) const;
+
+ typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie);
+
+ virtual void attachObject( const void* objectID,
+ void* object,
+ void* cleanupCookie,
+ object_cleanup_func func) = 0;
+ virtual void* findObject(const void* objectID) const = 0;
+ virtual void detachObject(const void* objectID) = 0;
+
+ virtual BBinder* localBinder();
+ virtual BpBinder* remoteBinder();
+
+protected:
+ virtual ~IBinder();
+
+private:
+};
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_IBINDER_H
diff --git a/include/binder/IInterface.h b/include/binder/IInterface.h
new file mode 100644
index 0000000..5f9f69c
--- /dev/null
+++ b/include/binder/IInterface.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+#ifndef ANDROID_IINTERFACE_H
+#define ANDROID_IINTERFACE_H
+
+#include <binder/Binder.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IInterface : public virtual RefBase
+{
+public:
+ IInterface();
+ sp<IBinder> asBinder();
+ sp<const IBinder> asBinder() const;
+
+protected:
+ virtual ~IInterface();
+ virtual IBinder* onAsBinder() = 0;
+};
+
+// ----------------------------------------------------------------------
+
+template<typename INTERFACE>
+inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
+{
+ return INTERFACE::asInterface(obj);
+}
+
+// ----------------------------------------------------------------------
+
+template<typename INTERFACE>
+class BnInterface : public INTERFACE, public BBinder
+{
+public:
+ virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
+ virtual const String16& getInterfaceDescriptor() const;
+
+protected:
+ virtual IBinder* onAsBinder();
+};
+
+// ----------------------------------------------------------------------
+
+template<typename INTERFACE>
+class BpInterface : public INTERFACE, public BpRefBase
+{
+public:
+ BpInterface(const sp<IBinder>& remote);
+
+protected:
+ virtual IBinder* onAsBinder();
+};
+
+// ----------------------------------------------------------------------
+
+#define DECLARE_META_INTERFACE(INTERFACE) \
+ static const android::String16 descriptor; \
+ static android::sp<I##INTERFACE> asInterface( \
+ const android::sp<android::IBinder>& obj); \
+ virtual const android::String16& getInterfaceDescriptor() const; \
+ I##INTERFACE(); \
+ virtual ~I##INTERFACE(); \
+
+
+#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
+ const android::String16 I##INTERFACE::descriptor(NAME); \
+ const android::String16& \
+ I##INTERFACE::getInterfaceDescriptor() const { \
+ return I##INTERFACE::descriptor; \
+ } \
+ android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
+ const android::sp<android::IBinder>& obj) \
+ { \
+ android::sp<I##INTERFACE> intr; \
+ if (obj != NULL) { \
+ intr = static_cast<I##INTERFACE*>( \
+ obj->queryLocalInterface( \
+ I##INTERFACE::descriptor).get()); \
+ if (intr == NULL) { \
+ intr = new Bp##INTERFACE(obj); \
+ } \
+ } \
+ return intr; \
+ } \
+ I##INTERFACE::I##INTERFACE() { } \
+ I##INTERFACE::~I##INTERFACE() { } \
+
+
+#define CHECK_INTERFACE(interface, data, reply) \
+ if (!data.checkInterface(this)) { return PERMISSION_DENIED; } \
+
+
+// ----------------------------------------------------------------------
+// No user-serviceable parts after this...
+
+template<typename INTERFACE>
+inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
+ const String16& _descriptor)
+{
+ if (_descriptor == INTERFACE::descriptor) return this;
+ return NULL;
+}
+
+template<typename INTERFACE>
+inline const String16& BnInterface<INTERFACE>::getInterfaceDescriptor() const
+{
+ return INTERFACE::getInterfaceDescriptor();
+}
+
+template<typename INTERFACE>
+IBinder* BnInterface<INTERFACE>::onAsBinder()
+{
+ return this;
+}
+
+template<typename INTERFACE>
+inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
+ : BpRefBase(remote)
+{
+}
+
+template<typename INTERFACE>
+inline IBinder* BpInterface<INTERFACE>::onAsBinder()
+{
+ return remote();
+}
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IINTERFACE_H
diff --git a/include/binder/IMemory.h b/include/binder/IMemory.h
new file mode 100644
index 0000000..2d0db00
--- /dev/null
+++ b/include/binder/IMemory.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef ANDROID_IMEMORY_H
+#define ANDROID_IMEMORY_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IMemoryHeap : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(MemoryHeap);
+
+ // flags returned by getFlags()
+ enum {
+ READ_ONLY = 0x00000001
+ };
+
+ virtual int getHeapID() const = 0;
+ virtual void* getBase() const = 0;
+ virtual size_t getSize() const = 0;
+ virtual uint32_t getFlags() const = 0;
+ virtual uint32_t getOffset() const = 0;
+
+ // these are there just for backward source compatibility
+ int32_t heapID() const { return getHeapID(); }
+ void* base() const { return getBase(); }
+ size_t virtualSize() const { return getSize(); }
+};
+
+class BnMemoryHeap : public BnInterface<IMemoryHeap>
+{
+public:
+ virtual status_t onTransact(
+ uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+
+ BnMemoryHeap();
+protected:
+ virtual ~BnMemoryHeap();
+};
+
+// ----------------------------------------------------------------------------
+
+class IMemory : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(Memory);
+
+ virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const = 0;
+
+ // helpers
+ void* fastPointer(const sp<IBinder>& heap, ssize_t offset) const;
+ void* pointer() const;
+ size_t size() const;
+ ssize_t offset() const;
+};
+
+class BnMemory : public BnInterface<IMemory>
+{
+public:
+ virtual status_t onTransact(
+ uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+
+ BnMemory();
+protected:
+ virtual ~BnMemory();
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IMEMORY_H
diff --git a/include/binder/IPCThreadState.h b/include/binder/IPCThreadState.h
new file mode 100644
index 0000000..691ba2f
--- /dev/null
+++ b/include/binder/IPCThreadState.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_IPC_THREAD_STATE_H
+#define ANDROID_IPC_THREAD_STATE_H
+
+#include <utils/Errors.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <utils/Vector.h>
+
+#ifdef HAVE_WIN32_PROC
+typedef int uid_t;
+#endif
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class IPCThreadState
+{
+public:
+ static IPCThreadState* self();
+ static IPCThreadState* selfOrNull(); // self(), but won't instantiate
+
+ sp<ProcessState> process();
+
+ status_t clearLastError();
+
+ int getCallingPid();
+ int getCallingUid();
+ int getOrigCallingUid();
+
+ void setStrictModePolicy(int32_t policy);
+ int32_t getStrictModePolicy() const;
+
+ void setLastTransactionBinderFlags(int32_t flags);
+ int32_t getLastTransactionBinderFlags() const;
+
+ int64_t clearCallingIdentity();
+ void restoreCallingIdentity(int64_t token);
+
+ void flushCommands();
+
+ void joinThreadPool(bool isMain = true);
+
+ // Stop the local process.
+ void stopProcess(bool immediate = true);
+
+ status_t transact(int32_t handle,
+ uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags);
+
+ void incStrongHandle(int32_t handle);
+ void decStrongHandle(int32_t handle);
+ void incWeakHandle(int32_t handle);
+ void decWeakHandle(int32_t handle);
+ status_t attemptIncStrongHandle(int32_t handle);
+ static void expungeHandle(int32_t handle, IBinder* binder);
+ status_t requestDeathNotification( int32_t handle,
+ BpBinder* proxy);
+ status_t clearDeathNotification( int32_t handle,
+ BpBinder* proxy);
+
+ static void shutdown();
+
+ // Call this to disable switching threads to background scheduling when
+ // receiving incoming IPC calls. This is specifically here for the
+ // Android system process, since it expects to have background apps calling
+ // in to it but doesn't want to acquire locks in its services while in
+ // the background.
+ static void disableBackgroundScheduling(bool disable);
+
+private:
+ IPCThreadState();
+ ~IPCThreadState();
+
+ status_t sendReply(const Parcel& reply, uint32_t flags);
+ status_t waitForResponse(Parcel *reply,
+ status_t *acquireResult=NULL);
+ status_t talkWithDriver(bool doReceive=true);
+ status_t writeTransactionData(int32_t cmd,
+ uint32_t binderFlags,
+ int32_t handle,
+ uint32_t code,
+ const Parcel& data,
+ status_t* statusBuffer);
+ status_t executeCommand(int32_t command);
+
+ void clearCaller();
+
+ static void threadDestructor(void *st);
+ static void freeBuffer(Parcel* parcel,
+ const uint8_t* data, size_t dataSize,
+ const size_t* objects, size_t objectsSize,
+ void* cookie);
+
+ const sp<ProcessState> mProcess;
+ const pid_t mMyThreadId;
+ Vector<BBinder*> mPendingStrongDerefs;
+ Vector<RefBase::weakref_type*> mPendingWeakDerefs;
+
+ Parcel mIn;
+ Parcel mOut;
+ status_t mLastError;
+ pid_t mCallingPid;
+ uid_t mCallingUid;
+ uid_t mOrigCallingUid;
+ int32_t mStrictModePolicy;
+ int32_t mLastTransactionBinderFlags;
+};
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_IPC_THREAD_STATE_H
diff --git a/include/binder/IPermissionController.h b/include/binder/IPermissionController.h
new file mode 100644
index 0000000..f9d371b
--- /dev/null
+++ b/include/binder/IPermissionController.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+#ifndef ANDROID_IPERMISSION_CONTROLLER_H
+#define ANDROID_IPERMISSION_CONTROLLER_H
+
+#include <binder/IInterface.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IPermissionController : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(PermissionController);
+
+ virtual bool checkPermission(const String16& permission,
+ int32_t pid, int32_t uid) = 0;
+
+ enum {
+ CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION
+ };
+};
+
+// ----------------------------------------------------------------------
+
+class BnPermissionController : public BnInterface<IPermissionController>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IPERMISSION_CONTROLLER_H
+
diff --git a/include/binder/IServiceManager.h b/include/binder/IServiceManager.h
new file mode 100644
index 0000000..2c297d6
--- /dev/null
+++ b/include/binder/IServiceManager.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+#ifndef ANDROID_ISERVICE_MANAGER_H
+#define ANDROID_ISERVICE_MANAGER_H
+
+#include <binder/IInterface.h>
+#include <binder/IPermissionController.h>
+#include <utils/Vector.h>
+#include <utils/String16.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IServiceManager : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(ServiceManager);
+
+ /**
+ * Retrieve an existing service, blocking for a few seconds
+ * if it doesn't yet exist.
+ */
+ virtual sp<IBinder> getService( const String16& name) const = 0;
+
+ /**
+ * Retrieve an existing service, non-blocking.
+ */
+ virtual sp<IBinder> checkService( const String16& name) const = 0;
+
+ /**
+ * Register a service.
+ */
+ virtual status_t addService( const String16& name,
+ const sp<IBinder>& service,
+ bool allowIsolated = false) = 0;
+
+ /**
+ * Return list of all existing services.
+ */
+ virtual Vector<String16> listServices() = 0;
+
+ enum {
+ GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+ CHECK_SERVICE_TRANSACTION,
+ ADD_SERVICE_TRANSACTION,
+ LIST_SERVICES_TRANSACTION,
+ };
+};
+
+sp<IServiceManager> defaultServiceManager();
+
+template<typename INTERFACE>
+status_t getService(const String16& name, sp<INTERFACE>* outService)
+{
+ const sp<IServiceManager> sm = defaultServiceManager();
+ if (sm != NULL) {
+ *outService = interface_cast<INTERFACE>(sm->getService(name));
+ if ((*outService) != NULL) return NO_ERROR;
+ }
+ return NAME_NOT_FOUND;
+}
+
+bool checkCallingPermission(const String16& permission);
+bool checkCallingPermission(const String16& permission,
+ int32_t* outPid, int32_t* outUid);
+bool checkPermission(const String16& permission, pid_t pid, uid_t uid);
+
+
+// ----------------------------------------------------------------------
+
+class BnServiceManager : public BnInterface<IServiceManager>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_ISERVICE_MANAGER_H
+
diff --git a/include/binder/MemoryBase.h b/include/binder/MemoryBase.h
new file mode 100644
index 0000000..463e26d
--- /dev/null
+++ b/include/binder/MemoryBase.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 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.
+ * 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.
+ */
+
+#ifndef ANDROID_MEMORY_BASE_H
+#define ANDROID_MEMORY_BASE_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <binder/IMemory.h>
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class MemoryBase : public BnMemory
+{
+public:
+ MemoryBase(const sp<IMemoryHeap>& heap, ssize_t offset, size_t size);
+ virtual ~MemoryBase();
+ virtual sp<IMemoryHeap> getMemory(ssize_t* offset, size_t* size) const;
+
+protected:
+ size_t getSize() const { return mSize; }
+ ssize_t getOffset() const { return mOffset; }
+ const sp<IMemoryHeap>& getHeap() const { return mHeap; }
+
+private:
+ size_t mSize;
+ ssize_t mOffset;
+ sp<IMemoryHeap> mHeap;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_MEMORY_BASE_H
diff --git a/include/binder/MemoryDealer.h b/include/binder/MemoryDealer.h
new file mode 100644
index 0000000..170f20d
--- /dev/null
+++ b/include/binder/MemoryDealer.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef ANDROID_MEMORY_DEALER_H
+#define ANDROID_MEMORY_DEALER_H
+
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/IMemory.h>
+#include <binder/MemoryHeapBase.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class SimpleBestFitAllocator;
+
+// ----------------------------------------------------------------------------
+
+class MemoryDealer : public RefBase
+{
+public:
+ MemoryDealer(size_t size, const char* name = 0);
+
+ virtual sp<IMemory> allocate(size_t size);
+ virtual void deallocate(size_t offset);
+ virtual void dump(const char* what) const;
+
+ sp<IMemoryHeap> getMemoryHeap() const { return heap(); }
+
+protected:
+ virtual ~MemoryDealer();
+
+private:
+ const sp<IMemoryHeap>& heap() const;
+ SimpleBestFitAllocator* allocator() const;
+
+ sp<IMemoryHeap> mHeap;
+ SimpleBestFitAllocator* mAllocator;
+};
+
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_MEMORY_DEALER_H
diff --git a/include/binder/MemoryHeapBase.h b/include/binder/MemoryHeapBase.h
new file mode 100644
index 0000000..bbbda9c
--- /dev/null
+++ b/include/binder/MemoryHeapBase.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 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.
+ * 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.
+ */
+
+#ifndef ANDROID_MEMORY_HEAP_BASE_H
+#define ANDROID_MEMORY_HEAP_BASE_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <binder/IMemory.h>
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class MemoryHeapBase : public virtual BnMemoryHeap
+{
+public:
+ enum {
+ READ_ONLY = IMemoryHeap::READ_ONLY,
+ // memory won't be mapped locally, but will be mapped in the remote
+ // process.
+ DONT_MAP_LOCALLY = 0x00000100,
+ NO_CACHING = 0x00000200
+ };
+
+ /*
+ * maps the memory referenced by fd. but DOESN'T take ownership
+ * of the filedescriptor (it makes a copy with dup()
+ */
+ MemoryHeapBase(int fd, size_t size, uint32_t flags = 0, uint32_t offset = 0);
+
+ /*
+ * maps memory from the given device
+ */
+ MemoryHeapBase(const char* device, size_t size = 0, uint32_t flags = 0);
+
+ /*
+ * maps memory from ashmem, with the given name for debugging
+ */
+ MemoryHeapBase(size_t size, uint32_t flags = 0, char const* name = NULL);
+
+ virtual ~MemoryHeapBase();
+
+ /* implement IMemoryHeap interface */
+ virtual int getHeapID() const;
+ virtual void* getBase() const;
+ virtual size_t getSize() const;
+ virtual uint32_t getFlags() const;
+ virtual uint32_t getOffset() const;
+
+ const char* getDevice() const;
+
+ /* this closes this heap -- use carefully */
+ void dispose();
+
+ /* this is only needed as a workaround, use only if you know
+ * what you are doing */
+ status_t setDevice(const char* device) {
+ if (mDevice == 0)
+ mDevice = device;
+ return mDevice ? NO_ERROR : ALREADY_EXISTS;
+ }
+
+protected:
+ MemoryHeapBase();
+ // init() takes ownership of fd
+ status_t init(int fd, void *base, int size,
+ int flags = 0, const char* device = NULL);
+
+private:
+ status_t mapfd(int fd, size_t size, uint32_t offset = 0);
+
+ int mFD;
+ size_t mSize;
+ void* mBase;
+ uint32_t mFlags;
+ const char* mDevice;
+ bool mNeedUnmap;
+ uint32_t mOffset;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_MEMORY_HEAP_BASE_H
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
new file mode 100644
index 0000000..33b2f00
--- /dev/null
+++ b/include/binder/Parcel.h
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_PARCEL_H
+#define ANDROID_PARCEL_H
+
+#include <cutils/native_handle.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class Flattenable;
+class IBinder;
+class IPCThreadState;
+class ProcessState;
+class String8;
+class TextOutput;
+
+struct flat_binder_object; // defined in support_p/binder_module.h
+
+class Parcel
+{
+public:
+ class ReadableBlob;
+ class WritableBlob;
+
+ Parcel();
+ ~Parcel();
+
+ const uint8_t* data() const;
+ size_t dataSize() const;
+ size_t dataAvail() const;
+ size_t dataPosition() const;
+ size_t dataCapacity() const;
+
+ status_t setDataSize(size_t size);
+ void setDataPosition(size_t pos) const;
+ status_t setDataCapacity(size_t size);
+
+ status_t setData(const uint8_t* buffer, size_t len);
+
+ status_t appendFrom(const Parcel *parcel,
+ size_t start, size_t len);
+
+ bool pushAllowFds(bool allowFds);
+ void restoreAllowFds(bool lastValue);
+
+ bool hasFileDescriptors() const;
+
+ // Writes the RPC header.
+ status_t writeInterfaceToken(const String16& interface);
+
+ // Parses the RPC header, returning true if the interface name
+ // in the header matches the expected interface from the caller.
+ //
+ // Additionally, enforceInterface does part of the work of
+ // propagating the StrictMode policy mask, populating the current
+ // IPCThreadState, which as an optimization may optionally be
+ // passed in.
+ bool enforceInterface(const String16& interface,
+ IPCThreadState* threadState = NULL) const;
+ bool checkInterface(IBinder*) const;
+
+ void freeData();
+
+ const size_t* objects() const;
+ size_t objectsCount() const;
+
+ status_t errorCheck() const;
+ void setError(status_t err);
+
+ status_t write(const void* data, size_t len);
+ void* writeInplace(size_t len);
+ status_t writeUnpadded(const void* data, size_t len);
+ status_t writeInt32(int32_t val);
+ status_t writeInt64(int64_t val);
+ status_t writeFloat(float val);
+ status_t writeDouble(double val);
+ status_t writeIntPtr(intptr_t val);
+ status_t writeCString(const char* str);
+ status_t writeString8(const String8& str);
+ status_t writeString16(const String16& str);
+ status_t writeString16(const char16_t* str, size_t len);
+ status_t writeStrongBinder(const sp<IBinder>& val);
+ status_t writeWeakBinder(const wp<IBinder>& val);
+ status_t write(const Flattenable& val);
+
+ // Place a native_handle into the parcel (the native_handle's file-
+ // descriptors are dup'ed, so it is safe to delete the native_handle
+ // when this function returns).
+ // Doesn't take ownership of the native_handle.
+ status_t writeNativeHandle(const native_handle* handle);
+
+ // Place a file descriptor into the parcel. The given fd must remain
+ // valid for the lifetime of the parcel.
+ // The Parcel does not take ownership of the given fd unless you ask it to.
+ status_t writeFileDescriptor(int fd, bool takeOwnership = false);
+
+ // Place a file descriptor into the parcel. A dup of the fd is made, which
+ // will be closed once the parcel is destroyed.
+ status_t writeDupFileDescriptor(int fd);
+
+ // Writes a blob to the parcel.
+ // If the blob is small, then it is stored in-place, otherwise it is
+ // transferred by way of an anonymous shared memory region.
+ // The caller should call release() on the blob after writing its contents.
+ status_t writeBlob(size_t len, WritableBlob* outBlob);
+
+ status_t writeObject(const flat_binder_object& val, bool nullMetaData);
+
+ // Like Parcel.java's writeNoException(). Just writes a zero int32.
+ // Currently the native implementation doesn't do any of the StrictMode
+ // stack gathering and serialization that the Java implementation does.
+ status_t writeNoException();
+
+ void remove(size_t start, size_t amt);
+
+ status_t read(void* outData, size_t len) const;
+ const void* readInplace(size_t len) const;
+ int32_t readInt32() const;
+ status_t readInt32(int32_t *pArg) const;
+ int64_t readInt64() const;
+ status_t readInt64(int64_t *pArg) const;
+ float readFloat() const;
+ status_t readFloat(float *pArg) const;
+ double readDouble() const;
+ status_t readDouble(double *pArg) const;
+ intptr_t readIntPtr() const;
+ status_t readIntPtr(intptr_t *pArg) const;
+
+ const char* readCString() const;
+ String8 readString8() const;
+ String16 readString16() const;
+ const char16_t* readString16Inplace(size_t* outLen) const;
+ sp<IBinder> readStrongBinder() const;
+ wp<IBinder> readWeakBinder() const;
+ status_t read(Flattenable& val) const;
+
+ // Like Parcel.java's readExceptionCode(). Reads the first int32
+ // off of a Parcel's header, returning 0 or the negative error
+ // code on exceptions, but also deals with skipping over rich
+ // response headers. Callers should use this to read & parse the
+ // response headers rather than doing it by hand.
+ int32_t readExceptionCode() const;
+
+ // Retrieve native_handle from the parcel. This returns a copy of the
+ // parcel's native_handle (the caller takes ownership). The caller
+ // must free the native_handle with native_handle_close() and
+ // native_handle_delete().
+ native_handle* readNativeHandle() const;
+
+
+ // Retrieve a file descriptor from the parcel. This returns the raw fd
+ // in the parcel, which you do not own -- use dup() to get your own copy.
+ int readFileDescriptor() const;
+
+ // Reads a blob from the parcel.
+ // The caller should call release() on the blob after reading its contents.
+ status_t readBlob(size_t len, ReadableBlob* outBlob) const;
+
+ const flat_binder_object* readObject(bool nullMetaData) const;
+
+ // Explicitly close all file descriptors in the parcel.
+ void closeFileDescriptors();
+
+ typedef void (*release_func)(Parcel* parcel,
+ const uint8_t* data, size_t dataSize,
+ const size_t* objects, size_t objectsSize,
+ void* cookie);
+
+ const uint8_t* ipcData() const;
+ size_t ipcDataSize() const;
+ const size_t* ipcObjects() const;
+ size_t ipcObjectsCount() const;
+ void ipcSetDataReference(const uint8_t* data, size_t dataSize,
+ const size_t* objects, size_t objectsCount,
+ release_func relFunc, void* relCookie);
+
+ void print(TextOutput& to, uint32_t flags = 0) const;
+
+private:
+ Parcel(const Parcel& o);
+ Parcel& operator=(const Parcel& o);
+
+ status_t finishWrite(size_t len);
+ void releaseObjects();
+ void acquireObjects();
+ status_t growData(size_t len);
+ status_t restartWrite(size_t desired);
+ status_t continueWrite(size_t desired);
+ void freeDataNoInit();
+ void initState();
+ void scanForFds() const;
+
+ template<class T>
+ status_t readAligned(T *pArg) const;
+
+ template<class T> T readAligned() const;
+
+ template<class T>
+ status_t writeAligned(T val);
+
+ status_t mError;
+ uint8_t* mData;
+ size_t mDataSize;
+ size_t mDataCapacity;
+ mutable size_t mDataPos;
+ size_t* mObjects;
+ size_t mObjectsSize;
+ size_t mObjectsCapacity;
+ mutable size_t mNextObjectHint;
+
+ mutable bool mFdsKnown;
+ mutable bool mHasFds;
+ bool mAllowFds;
+
+ release_func mOwner;
+ void* mOwnerCookie;
+
+ class Blob {
+ public:
+ Blob();
+ ~Blob();
+
+ void release();
+ inline size_t size() const { return mSize; }
+
+ protected:
+ void init(bool mapped, void* data, size_t size);
+ void clear();
+
+ bool mMapped;
+ void* mData;
+ size_t mSize;
+ };
+
+public:
+ class ReadableBlob : public Blob {
+ friend class Parcel;
+ public:
+ inline const void* data() const { return mData; }
+ };
+
+ class WritableBlob : public Blob {
+ friend class Parcel;
+ public:
+ inline void* data() { return mData; }
+ };
+};
+
+// ---------------------------------------------------------------------------
+
+inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
+{
+ parcel.print(to);
+ return to;
+}
+
+// ---------------------------------------------------------------------------
+
+// Generic acquire and release of objects.
+void acquire_object(const sp<ProcessState>& proc,
+ const flat_binder_object& obj, const void* who);
+void release_object(const sp<ProcessState>& proc,
+ const flat_binder_object& obj, const void* who);
+
+void flatten_binder(const sp<ProcessState>& proc,
+ const sp<IBinder>& binder, flat_binder_object* out);
+void flatten_binder(const sp<ProcessState>& proc,
+ const wp<IBinder>& binder, flat_binder_object* out);
+status_t unflatten_binder(const sp<ProcessState>& proc,
+ const flat_binder_object& flat, sp<IBinder>* out);
+status_t unflatten_binder(const sp<ProcessState>& proc,
+ const flat_binder_object& flat, wp<IBinder>* out);
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_PARCEL_H
diff --git a/include/binder/PermissionCache.h b/include/binder/PermissionCache.h
new file mode 100644
index 0000000..1171d48
--- /dev/null
+++ b/include/binder/PermissionCache.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef BINDER_PERMISSION_H
+#define BINDER_PERMISSION_H
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <utils/String16.h>
+#include <utils/Singleton.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+/*
+ * PermissionCache caches permission checks for a given uid.
+ *
+ * Currently the cache is not updated when there is a permission change,
+ * for instance when an application is uninstalled.
+ *
+ * IMPORTANT: for the reason stated above, only system permissions are safe
+ * to cache. This restriction may be lifted at a later time.
+ *
+ */
+
+class PermissionCache : Singleton<PermissionCache> {
+ struct Entry {
+ String16 name;
+ uid_t uid;
+ bool granted;
+ inline bool operator < (const Entry& e) const {
+ return (uid == e.uid) ? (name <
e.name) : (uid < e.uid);
+ }
+ };
+ mutable Mutex mLock;
+ // we pool all the permission names we see, as many permissions checks
+ // will have identical names
+ SortedVector< String16 > mPermissionNamesPool;
+ // this is our cache per say. it stores pooled names.
+ SortedVector< Entry > mCache;
+
+ // free the whole cache, but keep the permission name pool
+ void purge();
+
+ status_t check(bool* granted,
+ const String16& permission, uid_t uid) const;
+
+ void cache(const String16& permission, uid_t uid, bool granted);
+
+public:
+ PermissionCache();
+
+ static bool checkCallingPermission(const String16& permission);
+
+ static bool checkCallingPermission(const String16& permission,
+ int32_t* outPid, int32_t* outUid);
+
+ static bool checkPermission(const String16& permission,
+ pid_t pid, uid_t uid);
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif /* BINDER_PERMISSION_H */
diff --git a/include/binder/ProcessState.h b/include/binder/ProcessState.h
new file mode 100644
index 0000000..8caf1af
--- /dev/null
+++ b/include/binder/ProcessState.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_PROCESS_STATE_H
+#define ANDROID_PROCESS_STATE_H
+
+#include <binder/IBinder.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+#include <utils/threads.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+// Global variables
+extern int mArgC;
+extern const char* const* mArgV;
+extern int mArgLen;
+
+class IPCThreadState;
+
+class ProcessState : public virtual RefBase
+{
+public:
+ static sp<ProcessState> self();
+
+ void setContextObject(const sp<IBinder>& object);
+ sp<IBinder> getContextObject(const sp<IBinder>& caller);
+
+ void setContextObject(const sp<IBinder>& object,
+ const String16& name);
+ sp<IBinder> getContextObject(const String16& name,
+ const sp<IBinder>& caller);
+
+ void startThreadPool();
+
+ typedef bool (*context_check_func)(const String16& name,
+ const sp<IBinder>& caller,
+ void* userData);
+
+ bool isContextManager(void) const;
+ bool becomeContextManager(
+ context_check_func checkFunc,
+ void* userData);
+
+ sp<IBinder> getStrongProxyForHandle(int32_t handle);
+ wp<IBinder> getWeakProxyForHandle(int32_t handle);
+ void expungeHandle(int32_t handle, IBinder* binder);
+
+ void setArgs(int argc, const char* const argv[]);
+ int getArgC() const;
+ const char* const* getArgV() const;
+
+ void setArgV0(const char* txt);
+
+ void spawnPooledThread(bool isMain);
+
+ status_t setThreadPoolMaxThreadCount(size_t maxThreads);
+
+private:
+ friend class IPCThreadState;
+
+ ProcessState();
+ ~ProcessState();
+
+ ProcessState(const ProcessState& o);
+ ProcessState& operator=(const ProcessState& o);
+
+ struct handle_entry {
+ IBinder* binder;
+ RefBase::weakref_type* refs;
+ };
+
+ handle_entry* lookupHandleLocked(int32_t handle);
+
+ int mDriverFD;
+ void* mVMStart;
+
+ mutable Mutex mLock; // protects everything below.
+
+ Vector<handle_entry>mHandleToObject;
+
+ bool mManagesContexts;
+ context_check_func mBinderContextCheckFunc;
+ void* mBinderContextUserData;
+
+ KeyedVector<String16, sp<IBinder> >
+ mContexts;
+
+
+ String8 mRootDir;
+ bool mThreadPoolStarted;
+ volatile int32_t mThreadPoolSeq;
+};
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_PROCESS_STATE_H
diff --git a/include/corkscrew/backtrace.h b/include/corkscrew/backtrace.h
new file mode 100644
index 0000000..556ad04
--- /dev/null
+++ b/include/corkscrew/backtrace.h
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+/* A stack unwinder. */
+
+#ifndef _CORKSCREW_BACKTRACE_H
+#define _CORKSCREW_BACKTRACE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <corkscrew/ptrace.h>
+#include <corkscrew/map_info.h>
+#include <corkscrew/symbol_table.h>
+
+/*
+ * Describes a single frame of a backtrace.
+ */
+typedef struct {
+ uintptr_t absolute_pc; /* absolute PC offset */
+ uintptr_t stack_top; /* top of stack for this frame */
+ size_t stack_size; /* size of this stack frame */
+} backtrace_frame_t;
+
+/*
+ * Describes the symbols associated with a backtrace frame.
+ */
+typedef struct {
+ uintptr_t relative_pc; /* relative frame PC offset from the start of the library,
+ or the absolute PC if the library is unknown */
+ uintptr_t relative_symbol_addr; /* relative offset of the symbol from the start of the
+ library or 0 if the library is unknown */
+ char* map_name; /* executable or library name, or NULL if unknown */
+ char* symbol_name; /* symbol name, or NULL if unknown */
+ char* demangled_name; /* demangled symbol name, or NULL if unknown */
+} backtrace_symbol_t;
+
+/*
+ * Unwinds the call stack for the current thread of execution.
+ * Populates the backtrace array with the program counters from the call stack.
+ * Returns the number of frames collected, or -1 if an error occurred.
+ */
+ssize_t unwind_backtrace(backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth);
+
+/*
+ * Unwinds the call stack for a thread within this process.
+ * Populates the backtrace array with the program counters from the call stack.
+ * Returns the number of frames collected, or -1 if an error occurred.
+ *
+ * The task is briefly suspended while the backtrace is being collected.
+ */
+ssize_t unwind_backtrace_thread(pid_t tid, backtrace_frame_t* backtrace,
+ size_t ignore_depth, size_t max_depth);
+
+/*
+ * Unwinds the call stack of a task within a remote process using ptrace().
+ * Populates the backtrace array with the program counters from the call stack.
+ * Returns the number of frames collected, or -1 if an error occurred.
+ */
+ssize_t unwind_backtrace_ptrace(pid_t tid, const ptrace_context_t* context,
+ backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth);
+
+/*
+ * Gets the symbols for each frame of a backtrace.
+ * The symbols array must be big enough to hold one symbol record per frame.
+ * The symbols must later be freed using free_backtrace_symbols.
+ */
+void get_backtrace_symbols(const backtrace_frame_t* backtrace, size_t frames,
+ backtrace_symbol_t* backtrace_symbols);
+
+/*
+ * Gets the symbols for each frame of a backtrace from a remote process.
+ * The symbols array must be big enough to hold one symbol record per frame.
+ * The symbols must later be freed using free_backtrace_symbols.
+ */
+void get_backtrace_symbols_ptrace(const ptrace_context_t* context,
+ const backtrace_frame_t* backtrace, size_t frames,
+ backtrace_symbol_t* backtrace_symbols);
+
+/*
+ * Frees the storage associated with backtrace symbols.
+ */
+void free_backtrace_symbols(backtrace_symbol_t* backtrace_symbols, size_t frames);
+
+enum {
+ // A hint for how big to make the line buffer for format_backtrace_line
+ MAX_BACKTRACE_LINE_LENGTH = 800,
+};
+
+/**
+ * Formats a line from a backtrace as a zero-terminated string into the specified buffer.
+ */
+void format_backtrace_line(unsigned frameNumber, const backtrace_frame_t* frame,
+ const backtrace_symbol_t* symbol, char* buffer, size_t bufferSize);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _CORKSCREW_BACKTRACE_H
diff --git a/include/corkscrew/demangle.h b/include/corkscrew/demangle.h
new file mode 100644
index 0000000..04b0225
--- /dev/null
+++ b/include/corkscrew/demangle.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/* C++ symbol name demangling. */
+
+#ifndef _CORKSCREW_DEMANGLE_H
+#define _CORKSCREW_DEMANGLE_H
+
+#include <sys/types.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Demangles a C++ symbol name.
+ * If name is NULL or if the name cannot be demangled, returns NULL.
+ * Otherwise, returns a newly allocated string that contains the demangled name.
+ *
+ * The caller must free the returned string using free().
+ */
+char* demangle_symbol_name(const char* name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _CORKSCREW_DEMANGLE_H
diff --git a/include/corkscrew/map_info.h b/include/corkscrew/map_info.h
new file mode 100644
index 0000000..c5cd8f8
--- /dev/null
+++ b/include/corkscrew/map_info.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+/* Process memory map. */
+
+#ifndef _CORKSCREW_MAP_INFO_H
+#define _CORKSCREW_MAP_INFO_H
+
+#include <sys/types.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct map_info {
+ struct map_info* next;
+ uintptr_t start;
+ uintptr_t end;
+ bool is_readable;
+ bool is_executable;
+ void* data; // arbitrary data associated with the map by the user, initially NULL
+ char name[];
+} map_info_t;
+
+/* Loads memory map from /proc/<tid>/maps. */
+map_info_t* load_map_info_list(pid_t tid);
+
+/* Frees memory map. */
+void free_map_info_list(map_info_t* milist);
+
+/* Finds the memory map that contains the specified address. */
+const map_info_t* find_map_info(const map_info_t* milist, uintptr_t addr);
+
+/* Returns true if the addr is in an readable map. */
+bool is_readable_map(const map_info_t* milist, uintptr_t addr);
+
+/* Returns true if the addr is in an executable map. */
+bool is_executable_map(const map_info_t* milist, uintptr_t addr);
+
+/* Acquires a reference to the memory map for this process.
+ * The result is cached and refreshed automatically.
+ * Make sure to release the map info when done. */
+map_info_t* acquire_my_map_info_list();
+
+/* Releases a reference to the map info for this process that was
+ * previous acquired using acquire_my_map_info_list(). */
+void release_my_map_info_list(map_info_t* milist);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _CORKSCREW_MAP_INFO_H
diff --git a/include/corkscrew/ptrace.h b/include/corkscrew/ptrace.h
new file mode 100644
index 0000000..172e348
--- /dev/null
+++ b/include/corkscrew/ptrace.h
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+/* Useful ptrace() utility functions. */
+
+#ifndef _CORKSCREW_PTRACE_H
+#define _CORKSCREW_PTRACE_H
+
+#include <corkscrew/map_info.h>
+#include <corkscrew/symbol_table.h>
+
+#include <sys/types.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Stores information about a process that is used for several different
+ * ptrace() based operations. */
+typedef struct {
+ map_info_t* map_info_list;
+} ptrace_context_t;
+
+/* Describes how to access memory from a process. */
+typedef struct {
+ pid_t tid;
+ const map_info_t* map_info_list;
+} memory_t;
+
+#if __i386__
+/* ptrace() register context. */
+typedef struct pt_regs_x86 {
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t esi;
+ uint32_t edi;
+ uint32_t ebp;
+ uint32_t eax;
+ uint32_t xds;
+ uint32_t xes;
+ uint32_t xfs;
+ uint32_t xgs;
+ uint32_t orig_eax;
+ uint32_t eip;
+ uint32_t xcs;
+ uint32_t eflags;
+ uint32_t esp;
+ uint32_t xss;
+} pt_regs_x86_t;
+#endif
+
+/*
+ * Initializes a memory structure for accessing memory from this process.
+ */
+void init_memory(memory_t* memory, const map_info_t* map_info_list);
+
+/*
+ * Initializes a memory structure for accessing memory from another process
+ * using ptrace().
+ */
+void init_memory_ptrace(memory_t* memory, pid_t tid);
+
+/*
+ * Reads a word of memory safely.
+ * If the memory is local, ensures that the address is readable before dereferencing it.
+ * Returns false and a value of 0xffffffff if the word could not be read.
+ */
+bool try_get_word(const memory_t* memory, uintptr_t ptr, uint32_t* out_value);
+
+/*
+ * Reads a word of memory safely using ptrace().
+ * Returns false and a value of 0xffffffff if the word could not be read.
+ */
+bool try_get_word_ptrace(pid_t tid, uintptr_t ptr, uint32_t* out_value);
+
+/*
+ * Loads information needed for examining a remote process using ptrace().
+ * The caller must already have successfully attached to the process
+ * using ptrace().
+ *
+ * The context can be used for any threads belonging to that process
+ * assuming ptrace() is attached to them before performing the actual
+ * unwinding. The context can continue to be used to decode backtraces
+ * even after ptrace() has been detached from the process.
+ */
+ptrace_context_t* load_ptrace_context(pid_t pid);
+
+/*
+ * Frees a ptrace context.
+ */
+void free_ptrace_context(ptrace_context_t* context);
+
+/*
+ * Finds a symbol using ptrace.
+ * Returns the containing map and information about the symbol, or
+ * NULL if one or the other is not available.
+ */
+void find_symbol_ptrace(const ptrace_context_t* context,
+ uintptr_t addr, const map_info_t** out_map_info, const symbol_t** out_symbol);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _CORKSCREW_PTRACE_H
diff --git a/include/corkscrew/symbol_table.h b/include/corkscrew/symbol_table.h
new file mode 100644
index 0000000..020c8b8
--- /dev/null
+++ b/include/corkscrew/symbol_table.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef _CORKSCREW_SYMBOL_TABLE_H
+#define _CORKSCREW_SYMBOL_TABLE_H
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ uintptr_t start;
+ uintptr_t end;
+ char* name;
+} symbol_t;
+
+typedef struct {
+ symbol_t* symbols;
+ size_t num_symbols;
+} symbol_table_t;
+
+/*
+ * Loads a symbol table from a given file.
+ * Returns NULL on error.
+ */
+symbol_table_t* load_symbol_table(const char* filename);
+
+/*
+ * Frees a symbol table.
+ */
+void free_symbol_table(symbol_table_t* table);
+
+/*
+ * Finds a symbol associated with an address in the symbol table.
+ * Returns NULL if not found.
+ */
+const symbol_t* find_symbol(const symbol_table_t* table, uintptr_t addr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _CORKSCREW_SYMBOL_TABLE_H
diff --git a/include/cutils/abort_socket.h b/include/cutils/abort_socket.h
new file mode 100644
index 0000000..fbb1112
--- /dev/null
+++ b/include/cutils/abort_socket.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2009, 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.
+ */
+
+/* Helper to perform abortable blocking operations on a socket:
+ * asocket_connect()
+ * asocket_accept()
+ * asocket_read()
+ * asocket_write()
+ * These calls are similar to the regular syscalls, but can be aborted with:
+ * asocket_abort()
+ *
+ * Calling close() on a regular POSIX socket does not abort blocked syscalls on
+ * that socket in other threads.
+ *
+ * After calling asocket_abort() the socket cannot be reused.
+ *
+ * Call asocket_destory() *after* all threads have finished with the socket to
+ * finish closing the socket and free the asocket structure.
+ *
+ * The helper is implemented by setting the socket non-blocking to initiate
+ * syscalls connect(), accept(), read(), write(), then using a blocking poll()
+ * on both the primary socket and a local pipe. This makes the poll() abortable
+ * by writing a byte to the local pipe in asocket_abort().
+ *
+ * asocket_create() sets the fd to non-blocking mode. It must not be changed to
+ * blocking mode.
+ *
+ * Using asocket will triple the number of file descriptors required per
+ * socket, due to the local pipe. It may be possible to use a global pipe per
+ * process rather than per socket, but we have not been able to come up with a
+ * race-free implementation yet.
+ *
+ * All functions except asocket_init() and asocket_destroy() are thread safe.
+ */
+
+#include <stdlib.h>
+#include <sys/socket.h>
+
+#ifndef __CUTILS_ABORT_SOCKET_H__
+#define __CUTILS_ABORT_SOCKET_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct asocket {
+ int fd; /* primary socket fd */
+ int abort_fd[2]; /* pipe used to abort */
+};
+
+/* Create an asocket from fd.
+ * Sets the socket to non-blocking mode.
+ * Returns NULL on error with errno set.
+ */
+struct asocket *asocket_init(int fd);
+
+/* Blocking socket I/O with timeout.
+ * Calling asocket_abort() from another thread will cause each of these
+ * functions to immediately return with value -1 and errno ECANCELED.
+ * timeout is in ms, use -1 to indicate no timeout. On timeout -1 is returned
+ * with errno ETIMEDOUT.
+ * EINTR is handled in-call.
+ * Other semantics are identical to the regular syscalls.
+ */
+int asocket_connect(struct asocket *s, const struct sockaddr *addr,
+ socklen_t addrlen, int timeout);
+
+int asocket_accept(struct asocket *s, struct sockaddr *addr,
+ socklen_t *addrlen, int timeout);
+
+int asocket_read(struct asocket *s, void *buf, size_t count, int timeout);
+
+int asocket_write(struct asocket *s, const void *buf, size_t count,
+ int timeout);
+
+/* Abort above calls and shutdown socket.
+ * Further I/O operations on this socket will immediately fail after this call.
+ * asocket_destroy() should be used to release resources once all threads
+ * have returned from blocking calls on the socket.
+ */
+void asocket_abort(struct asocket *s);
+
+/* Close socket and free asocket structure.
+ * Must not be called until all calls on this structure have completed.
+ */
+void asocket_destroy(struct asocket *s);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__CUTILS_ABORT_SOCKET__H__
diff --git a/include/cutils/android_reboot.h b/include/cutils/android_reboot.h
new file mode 100644
index 0000000..0c79be7
--- /dev/null
+++ b/include/cutils/android_reboot.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef __CUTILS_ANDROID_REBOOT_H__
+#define __CUTILS_ANDROID_REBOOT_H__
+
+__BEGIN_DECLS
+
+/* Commands */
+#define ANDROID_RB_RESTART 0xDEAD0001
+#define ANDROID_RB_POWEROFF 0xDEAD0002
+#define ANDROID_RB_RESTART2 0xDEAD0003
+
+/* Flags */
+#define ANDROID_RB_FLAG_NO_SYNC 0x1
+#define ANDROID_RB_FLAG_NO_REMOUNT_RO 0x2
+
+int android_reboot(int cmd, int flags, char *arg);
+
+__END_DECLS
+
+#endif /* __CUTILS_ANDROID_REBOOT_H__ */
diff --git a/include/cutils/array.h b/include/cutils/array.h
new file mode 100644
index 0000000..c97ff34
--- /dev/null
+++ b/include/cutils/array.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+/**
+ * A pointer array which intelligently expands its capacity ad needed.
+ */
+
+#ifndef __ARRAY_H
+#define __ARRAY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+
+/** An array. */
+typedef struct Array Array;
+
+/** Constructs a new array. Returns NULL if we ran out of memory. */
+Array* arrayCreate();
+
+/** Frees an array. Does not free elements themselves. */
+void arrayFree(Array* array);
+
+/** Adds a pointer. Returns 0 is successful, < 0 otherwise. */
+int arrayAdd(Array* array, void* pointer);
+
+/** Gets the pointer at the specified index. */
+void* arrayGet(Array* array, int index);
+
+/** Removes the pointer at the given index and returns it. */
+void* arrayRemove(Array* array, int index);
+
+/** Sets pointer at the given index. Returns old pointer. */
+void* arraySet(Array* array, int index, void* pointer);
+
+/** Sets the array size. Sets new pointers to NULL. Returns 0 if successful, < 0 otherwise . */
+int arraySetSize(Array* array, int size);
+
+/** Returns the size of the given array. */
+int arraySize(Array* array);
+
+/**
+ * Returns a pointer to a C-style array which will be valid until this array
+ * changes.
+ */
+const void** arrayUnwrap(Array* array);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ARRAY_H */
diff --git a/include/cutils/ashmem.h b/include/cutils/ashmem.h
new file mode 100644
index 0000000..25b233e
--- /dev/null
+++ b/include/cutils/ashmem.h
@@ -0,0 +1,45 @@
+/* cutils/ashmem.h
+ **
+ ** Copyright 2008 The Android Open Source Project
+ **
+ ** This file is dual licensed. It may be redistributed and/or modified
+ ** under the terms of the Apache 2.0 License OR version 2 of the GNU
+ ** General Public License.
+ */
+
+#ifndef _CUTILS_ASHMEM_H
+#define _CUTILS_ASHMEM_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ashmem_create_region(const char *name, size_t size);
+int ashmem_set_prot_region(int fd, int prot);
+int ashmem_pin_region(int fd, size_t offset, size_t len);
+int ashmem_unpin_region(int fd, size_t offset, size_t len);
+int ashmem_get_size_region(int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifndef __ASHMEMIOC /* in case someone included <linux/ashmem.h> too */
+
+#define ASHMEM_NAME_LEN 256
+
+#define ASHMEM_NAME_DEF "dev/ashmem"
+
+/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
+#define ASHMEM_NOT_PURGED 0
+#define ASHMEM_WAS_PURGED 1
+
+/* Return values from ASHMEM_UNPIN: Is the mapping now pinned or unpinned? */
+#define ASHMEM_IS_UNPINNED 0
+#define ASHMEM_IS_PINNED 1
+
+#endif /* ! __ASHMEMIOC */
+
+#endif /* _CUTILS_ASHMEM_H */
diff --git a/include/cutils/atomic-arm.h b/include/cutils/atomic-arm.h
new file mode 100644
index 0000000..16fe512
--- /dev/null
+++ b/include/cutils/atomic-arm.h
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef ANDROID_CUTILS_ATOMIC_ARM_H
+#define ANDROID_CUTILS_ATOMIC_ARM_H
+
+#include <stdint.h>
+#include <machine/cpu-features.h>
+
+extern inline void android_compiler_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+#if ANDROID_SMP == 0
+extern inline void android_memory_barrier(void)
+{
+ android_compiler_barrier();
+}
+extern inline void android_memory_store_barrier(void)
+{
+ android_compiler_barrier();
+}
+#elif defined(__ARM_HAVE_DMB)
+extern inline void android_memory_barrier(void)
+{
+ __asm__ __volatile__ ("dmb" : : : "memory");
+}
+extern inline void android_memory_store_barrier(void)
+{
+ __asm__ __volatile__ ("dmb st" : : : "memory");
+}
+#elif defined(__ARM_HAVE_LDREX_STREX)
+extern inline void android_memory_barrier(void)
+{
+ __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory");
+}
+extern inline void android_memory_store_barrier(void)
+{
+ android_memory_barrier();
+}
+#else
+extern inline void android_memory_barrier(void)
+{
+ typedef void (kuser_memory_barrier)(void);
+ (*(kuser_memory_barrier *)0xffff0fa0)();
+}
+extern inline void android_memory_store_barrier(void)
+{
+ android_memory_barrier();
+}
+#endif
+
+extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
+{
+ int32_t value = *ptr;
+ android_memory_barrier();
+ return value;
+}
+
+extern inline int32_t android_atomic_release_load(volatile const int32_t *ptr)
+{
+ android_memory_barrier();
+ return *ptr;
+}
+
+extern inline void android_atomic_acquire_store(int32_t value,
+ volatile int32_t *ptr)
+{
+ *ptr = value;
+ android_memory_barrier();
+}
+
+extern inline void android_atomic_release_store(int32_t value,
+ volatile int32_t *ptr)
+{
+ android_memory_barrier();
+ *ptr = value;
+}
+
+#if defined(__thumb__)
+extern int android_atomic_cas(int32_t old_value, int32_t new_value,
+ volatile int32_t *ptr);
+#elif defined(__ARM_HAVE_LDREX_STREX)
+extern inline int android_atomic_cas(int32_t old_value, int32_t new_value,
+ volatile int32_t *ptr)
+{
+ int32_t prev, status;
+ do {
+ __asm__ __volatile__ ("ldrex %0, [%3]\n"
+ "mov %1, #0\n"
+ "teq %0, %4\n"
+ "strexeq %1, %5, [%3]"
+ : "=&r" (prev), "=&r" (status), "+m"(*ptr)
+ : "r" (ptr), "Ir" (old_value), "r" (new_value)
+ : "cc");
+ } while (__builtin_expect(status != 0, 0));
+ return prev != old_value;
+}
+#else
+extern inline int android_atomic_cas(int32_t old_value, int32_t new_value,
+ volatile int32_t *ptr)
+{
+ typedef int (kuser_cmpxchg)(int32_t, int32_t, volatile int32_t *);
+ int32_t prev, status;
+ prev = *ptr;
+ do {
+ status = (*(kuser_cmpxchg *)0xffff0fc0)(old_value, new_value, ptr);
+ if (__builtin_expect(status == 0, 1))
+ return 0;
+ prev = *ptr;
+ } while (prev == old_value);
+ return 1;
+}
+#endif
+
+extern inline int android_atomic_acquire_cas(int32_t old_value,
+ int32_t new_value,
+ volatile int32_t *ptr)
+{
+ int status = android_atomic_cas(old_value, new_value, ptr);
+ android_memory_barrier();
+ return status;
+}
+
+extern inline int android_atomic_release_cas(int32_t old_value,
+ int32_t new_value,
+ volatile int32_t *ptr)
+{
+ android_memory_barrier();
+ return android_atomic_cas(old_value, new_value, ptr);
+}
+
+
+#if defined(__thumb__)
+extern int32_t android_atomic_add(int32_t increment,
+ volatile int32_t *ptr);
+#elif defined(__ARM_HAVE_LDREX_STREX)
+extern inline int32_t android_atomic_add(int32_t increment,
+ volatile int32_t *ptr)
+{
+ int32_t prev, tmp, status;
+ android_memory_barrier();
+ do {
+ __asm__ __volatile__ ("ldrex %0, [%4]\n"
+ "add %1, %0, %5\n"
+ "strex %2, %1, [%4]"
+ : "=&r" (prev), "=&r" (tmp),
+ "=&r" (status), "+m" (*ptr)
+ : "r" (ptr), "Ir" (increment)
+ : "cc");
+ } while (__builtin_expect(status != 0, 0));
+ return prev;
+}
+#else
+extern inline int32_t android_atomic_add(int32_t increment,
+ volatile int32_t *ptr)
+{
+ int32_t prev, status;
+ android_memory_barrier();
+ do {
+ prev = *ptr;
+ status = android_atomic_cas(prev, prev + increment, ptr);
+ } while (__builtin_expect(status != 0, 0));
+ return prev;
+}
+#endif
+
+extern inline int32_t android_atomic_inc(volatile int32_t *addr)
+{
+ return android_atomic_add(1, addr);
+}
+
+extern inline int32_t android_atomic_dec(volatile int32_t *addr)
+{
+ return android_atomic_add(-1, addr);
+}
+
+#if defined(__thumb__)
+extern int32_t android_atomic_and(int32_t value, volatile int32_t *ptr);
+#elif defined(__ARM_HAVE_LDREX_STREX)
+extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
+{
+ int32_t prev, tmp, status;
+ android_memory_barrier();
+ do {
+ __asm__ __volatile__ ("ldrex %0, [%4]\n"
+ "and %1, %0, %5\n"
+ "strex %2, %1, [%4]"
+ : "=&r" (prev), "=&r" (tmp),
+ "=&r" (status), "+m" (*ptr)
+ : "r" (ptr), "Ir" (value)
+ : "cc");
+ } while (__builtin_expect(status != 0, 0));
+ return prev;
+}
+#else
+extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
+{
+ int32_t prev, status;
+ android_memory_barrier();
+ do {
+ prev = *ptr;
+ status = android_atomic_cas(prev, prev & value, ptr);
+ } while (__builtin_expect(status != 0, 0));
+ return prev;
+}
+#endif
+
+#if defined(__thumb__)
+extern int32_t android_atomic_or(int32_t value, volatile int32_t *ptr);
+#elif defined(__ARM_HAVE_LDREX_STREX)
+extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
+{
+ int32_t prev, tmp, status;
+ android_memory_barrier();
+ do {
+ __asm__ __volatile__ ("ldrex %0, [%4]\n"
+ "orr %1, %0, %5\n"
+ "strex %2, %1, [%4]"
+ : "=&r" (prev), "=&r" (tmp),
+ "=&r" (status), "+m" (*ptr)
+ : "r" (ptr), "Ir" (value)
+ : "cc");
+ } while (__builtin_expect(status != 0, 0));
+ return prev;
+}
+#else
+extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
+{
+ int32_t prev, status;
+ android_memory_barrier();
+ do {
+ prev = *ptr;
+ status = android_atomic_cas(prev, prev | value, ptr);
+ } while (__builtin_expect(status != 0, 0));
+ return prev;
+}
+#endif
+
+#endif /* ANDROID_CUTILS_ATOMIC_ARM_H */
diff --git a/include/cutils/atomic-inline.h b/include/cutils/atomic-inline.h
new file mode 100644
index 0000000..49f3e70
--- /dev/null
+++ b/include/cutils/atomic-inline.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef ANDROID_CUTILS_ATOMIC_INLINE_H
+#define ANDROID_CUTILS_ATOMIC_INLINE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Inline declarations and macros for some special-purpose atomic
+ * operations. These are intended for rare circumstances where a
+ * memory barrier needs to be issued inline rather than as a function
+ * call.
+ *
+ * Most code should not use these.
+ *
+ * Anything that does include this file must set ANDROID_SMP to either
+ * 0 or 1, indicating compilation for UP or SMP, respectively.
+ *
+ * Macros defined in this header:
+ *
+ * void ANDROID_MEMBAR_FULL(void)
+ * Full memory barrier. Provides a compiler reordering barrier, and
+ * on SMP systems emits an appropriate instruction.
+ */
+
+#if !defined(ANDROID_SMP)
+# error "Must define ANDROID_SMP before including atomic-inline.h"
+#endif
+
+#if defined(__arm__)
+#include <cutils/atomic-arm.h>
+#elif defined(__i386__) || defined(__x86_64__)
+#include <cutils/atomic-x86.h>
+#elif defined(__sh__)
+/* implementation is in atomic-android-sh.c */
+#else
+#error atomic operations are unsupported
+#endif
+
+#if ANDROID_SMP == 0
+#define ANDROID_MEMBAR_FULL android_compiler_barrier
+#else
+#define ANDROID_MEMBAR_FULL android_memory_barrier
+#endif
+
+#if ANDROID_SMP == 0
+#define ANDROID_MEMBAR_STORE android_compiler_barrier
+#else
+#define ANDROID_MEMBAR_STORE android_memory_store_barrier
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ANDROID_CUTILS_ATOMIC_INLINE_H */
diff --git a/include/cutils/atomic-x86.h b/include/cutils/atomic-x86.h
new file mode 100644
index 0000000..438012e
--- /dev/null
+++ b/include/cutils/atomic-x86.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef ANDROID_CUTILS_ATOMIC_X86_H
+#define ANDROID_CUTILS_ATOMIC_X86_H
+
+#include <stdint.h>
+
+extern inline void android_compiler_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+#if ANDROID_SMP == 0
+extern inline void android_memory_barrier(void)
+{
+ android_compiler_barrier();
+}
+extern inline void android_memory_store_barrier(void)
+{
+ android_compiler_barrier();
+}
+#else
+extern inline void android_memory_barrier(void)
+{
+ __asm__ __volatile__ ("mfence" : : : "memory");
+}
+extern inline void android_memory_store_barrier(void)
+{
+ android_compiler_barrier();
+}
+#endif
+
+extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
+{
+ int32_t value = *ptr;
+ android_compiler_barrier();
+ return value;
+}
+
+extern inline int32_t android_atomic_release_load(volatile const int32_t *ptr)
+{
+ android_memory_barrier();
+ return *ptr;
+}
+
+extern inline void android_atomic_acquire_store(int32_t value,
+ volatile int32_t *ptr)
+{
+ *ptr = value;
+ android_memory_barrier();
+}
+
+extern inline void android_atomic_release_store(int32_t value,
+ volatile int32_t *ptr)
+{
+ android_compiler_barrier();
+ *ptr = value;
+}
+
+extern inline int android_atomic_cas(int32_t old_value, int32_t new_value,
+ volatile int32_t *ptr)
+{
+ int32_t prev;
+ __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
+ : "=a" (prev)
+ : "q" (new_value), "m" (*ptr), "0" (old_value)
+ : "memory");
+ return prev != old_value;
+}
+
+extern inline int android_atomic_acquire_cas(int32_t old_value,
+ int32_t new_value,
+ volatile int32_t *ptr)
+{
+ /* Loads are not reordered with other loads. */
+ return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern inline int android_atomic_release_cas(int32_t old_value,
+ int32_t new_value,
+ volatile int32_t *ptr)
+{
+ /* Stores are not reordered with other stores. */
+ return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern inline int32_t android_atomic_add(int32_t increment,
+ volatile int32_t *ptr)
+{
+ __asm__ __volatile__ ("lock; xaddl %0, %1"
+ : "+r" (increment), "+m" (*ptr)
+ : : "memory");
+ /* increment now holds the old value of *ptr */
+ return increment;
+}
+
+extern inline int32_t android_atomic_inc(volatile int32_t *addr)
+{
+ return android_atomic_add(1, addr);
+}
+
+extern inline int32_t android_atomic_dec(volatile int32_t *addr)
+{
+ return android_atomic_add(-1, addr);
+}
+
+extern inline int32_t android_atomic_and(int32_t value,
+ volatile int32_t *ptr)
+{
+ int32_t prev, status;
+ do {
+ prev = *ptr;
+ status = android_atomic_cas(prev, prev & value, ptr);
+ } while (__builtin_expect(status != 0, 0));
+ return prev;
+}
+
+extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
+{
+ int32_t prev, status;
+ do {
+ prev = *ptr;
+ status = android_atomic_cas(prev, prev | value, ptr);
+ } while (__builtin_expect(status != 0, 0));
+ return prev;
+}
+
+#endif /* ANDROID_CUTILS_ATOMIC_X86_H */
diff --git a/include/cutils/atomic.h b/include/cutils/atomic.h
new file mode 100644
index 0000000..ae42eb8
--- /dev/null
+++ b/include/cutils/atomic.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef ANDROID_CUTILS_ATOMIC_H
+#define ANDROID_CUTILS_ATOMIC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * A handful of basic atomic operations. The appropriate pthread
+ * functions should be used instead of these whenever possible.
+ *
+ * The "acquire" and "release" terms can be defined intuitively in terms
+ * of the placement of memory barriers in a simple lock implementation:
+ * - wait until compare-and-swap(lock-is-free --> lock-is-held) succeeds
+ * - barrier
+ * - [do work]
+ * - barrier
+ * - store(lock-is-free)
+ * In very crude terms, the initial (acquire) barrier prevents any of the
+ * "work" from happening before the lock is held, and the later (release)
+ * barrier ensures that all of the work happens before the lock is released.
+ * (Think of cached writes, cache read-ahead, and instruction reordering
+ * around the CAS and store instructions.)
+ *
+ * The barriers must apply to both the compiler and the CPU. Note it is
+ * legal for instructions that occur before an "acquire" barrier to be
+ * moved down below it, and for instructions that occur after a "release"
+ * barrier to be moved up above it.
+ *
+ * The ARM-driven implementation we use here is short on subtlety,
+ * and actually requests a full barrier from the compiler and the CPU.
+ * The only difference between acquire and release is in whether they
+ * are issued before or after the atomic operation with which they
+ * are associated. To ease the transition to C/C++ atomic intrinsics,
+ * you should not rely on this, and instead assume that only the minimal
+ * acquire/release protection is provided.
+ *
+ * NOTE: all int32_t* values are expected to be aligned on 32-bit boundaries.
+ * If they are not, atomicity is not guaranteed.
+ */
+
+/*
+ * Basic arithmetic and bitwise operations. These all provide a
+ * barrier with "release" ordering, and return the previous value.
+ *
+ * These have the same characteristics (e.g. what happens on overflow)
+ * as the equivalent non-atomic C operations.
+ */
+int32_t android_atomic_inc(volatile int32_t* addr);
+int32_t android_atomic_dec(volatile int32_t* addr);
+int32_t android_atomic_add(int32_t value, volatile int32_t* addr);
+int32_t android_atomic_and(int32_t value, volatile int32_t* addr);
+int32_t android_atomic_or(int32_t value, volatile int32_t* addr);
+
+/*
+ * Perform an atomic load with "acquire" or "release" ordering.
+ *
+ * This is only necessary if you need the memory barrier. A 32-bit read
+ * from a 32-bit aligned address is atomic on all supported platforms.
+ */
+int32_t android_atomic_acquire_load(volatile const int32_t* addr);
+int32_t android_atomic_release_load(volatile const int32_t* addr);
+
+/*
+ * Perform an atomic store with "acquire" or "release" ordering.
+ *
+ * This is only necessary if you need the memory barrier. A 32-bit write
+ * to a 32-bit aligned address is atomic on all supported platforms.
+ */
+void android_atomic_acquire_store(int32_t value, volatile int32_t* addr);
+void android_atomic_release_store(int32_t value, volatile int32_t* addr);
+
+/*
+ * Compare-and-set operation with "acquire" or "release" ordering.
+ *
+ * This returns zero if the new value was successfully stored, which will
+ * only happen when *addr == oldvalue.
+ *
+ * (The return value is inverted from implementations on other platforms,
+ * but matches the ARM ldrex/strex result.)
+ *
+ * Implementations that use the release CAS in a loop may be less efficient
+ * than possible, because we re-issue the memory barrier on each iteration.
+ */
+int android_atomic_acquire_cas(int32_t oldvalue, int32_t newvalue,
+ volatile int32_t* addr);
+int android_atomic_release_cas(int32_t oldvalue, int32_t newvalue,
+ volatile int32_t* addr);
+
+/*
+ * Aliases for code using an older version of this header. These are now
+ * deprecated and should not be used. The definitions will be removed
+ * in a future release.
+ */
+#define android_atomic_write android_atomic_release_store
+#define android_atomic_cmpxchg android_atomic_release_cas
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // ANDROID_CUTILS_ATOMIC_H
diff --git a/include/cutils/bitops.h b/include/cutils/bitops.h
new file mode 100644
index 0000000..1b3b762
--- /dev/null
+++ b/include/cutils/bitops.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#ifndef __CUTILS_BITOPS_H
+#define __CUTILS_BITOPS_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+static inline int popcount(unsigned int x)
+{
+ return __builtin_popcount(x);
+}
+
+static inline int popcountl(unsigned long x)
+{
+ return __builtin_popcountl(x);
+}
+
+static inline int popcountll(unsigned long long x)
+{
+ return __builtin_popcountll(x);
+}
+
+__END_DECLS
+
+#endif /* __CUTILS_BITOPS_H */
diff --git a/include/cutils/compiler.h b/include/cutils/compiler.h
new file mode 100644
index 0000000..70f884a
--- /dev/null
+++ b/include/cutils/compiler.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef ANDROID_CUTILS_COMPILER_H
+#define ANDROID_CUTILS_COMPILER_H
+
+/*
+ * helps the compiler's optimizer predicting branches
+ */
+
+#ifdef __cplusplus
+# define CC_LIKELY( exp ) (__builtin_expect( !!(exp), true ))
+# define CC_UNLIKELY( exp ) (__builtin_expect( !!(exp), false ))
+#else
+# define CC_LIKELY( exp ) (__builtin_expect( !!(exp), 1 ))
+# define CC_UNLIKELY( exp ) (__builtin_expect( !!(exp), 0 ))
+#endif
+
+/**
+ * exports marked symbols
+ *
+ * if used on a C++ class declaration, this macro must be inserted
+ * after the "class" keyword. For instance:
+ *
+ * template <typename TYPE>
+ * class ANDROID_API Singleton { }
+ */
+
+#define ANDROID_API __attribute__((visibility("default")))
+
+#endif // ANDROID_CUTILS_COMPILER_H
diff --git a/include/cutils/config_utils.h b/include/cutils/config_utils.h
new file mode 100644
index 0000000..2dea6f1
--- /dev/null
+++ b/include/cutils/config_utils.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#ifndef __CUTILS_CONFIG_UTILS_H
+#define __CUTILS_CONFIG_UTILS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct cnode cnode;
+
+
+struct cnode
+{
+ cnode *next;
+ cnode *first_child;
+ cnode *last_child;
+ const char *name;
+ const char *value;
+};
+
+/* parse a text string into a config node tree */
+void config_load(cnode *root, char *data);
+
+/* parse a file into a config node tree */
+void config_load_file(cnode *root, const char *fn);
+
+/* create a single config node */
+cnode* config_node(const char *name, const char *value);
+
+/* locate a named child of a config node */
+cnode* config_find(cnode *root, const char *name);
+
+/* look up a child by name and return the boolean value */
+int config_bool(cnode *root, const char *name, int _default);
+
+/* look up a child by name and return the string value */
+const char* config_str(cnode *root, const char *name, const char *_default);
+
+/* add a named child to a config node (or modify it if it already exists) */
+void config_set(cnode *root, const char *name, const char *value);
+
+/* free a config node tree */
+void config_free(cnode *root);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cutils/cpu_info.h b/include/cutils/cpu_info.h
new file mode 100644
index 0000000..78c1884
--- /dev/null
+++ b/include/cutils/cpu_info.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef __CUTILS_CPU_INFO_H
+#define __CUTILS_CPU_INFO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* returns a string contiaining an ASCII representation of the CPU serial number,
+** or NULL if cpu info not available.
+** The string is a static variable, so don't call free() on it.
+*/
+extern const char* get_cpu_serial_number(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_CPU_INFO_H */
diff --git a/include/cutils/debugger.h b/include/cutils/debugger.h
new file mode 100644
index 0000000..5a8e796
--- /dev/null
+++ b/include/cutils/debugger.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef __CUTILS_DEBUGGER_H
+#define __CUTILS_DEBUGGER_H
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DEBUGGER_SOCKET_NAME "android:debuggerd"
+
+typedef enum {
+ // dump a crash
+ DEBUGGER_ACTION_CRASH,
+ // dump a tombstone file
+ DEBUGGER_ACTION_DUMP_TOMBSTONE,
+ // dump a backtrace only back to the socket
+ DEBUGGER_ACTION_DUMP_BACKTRACE,
+} debugger_action_t;
+
+/* message sent over the socket */
+typedef struct {
+ debugger_action_t action;
+ pid_t tid;
+} debugger_msg_t;
+
+/* Dumps a process backtrace, registers, and stack to a tombstone file (requires root).
+ * Stores the tombstone path in the provided buffer.
+ * Returns 0 on success, -1 on error.
+ */
+int dump_tombstone(pid_t tid, char* pathbuf, size_t pathlen);
+
+/* Dumps a process backtrace only to the specified file (requires root).
+ * Returns 0 on success, -1 on error.
+ */
+int dump_backtrace_to_file(pid_t tid, int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_DEBUGGER_H */
diff --git a/include/cutils/dir_hash.h b/include/cutils/dir_hash.h
new file mode 100644
index 0000000..fbb4d02
--- /dev/null
+++ b/include/cutils/dir_hash.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+typedef enum {
+ SHA_1,
+} HashAlgorithm;
+
+int get_file_hash(HashAlgorithm algorithm, const char *path,
+ char *output_string, size_t max_output_string);
+
+int get_recursive_hash_manifest(HashAlgorithm algorithm,
+ const char *directory_path,
+ char **output_string);
diff --git a/include/cutils/event_tag_map.h b/include/cutils/event_tag_map.h
new file mode 100644
index 0000000..1653c61
--- /dev/null
+++ b/include/cutils/event_tag_map.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef _LIBS_CUTILS_EVENTTAGMAP_H
+#define _LIBS_CUTILS_EVENTTAGMAP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EVENT_TAG_MAP_FILE "/system/etc/event-log-tags"
+
+struct EventTagMap;
+typedef struct EventTagMap EventTagMap;
+
+/*
+ * Open the specified file as an event log tag map.
+ *
+ * Returns NULL on failure.
+ */
+EventTagMap* android_openEventTagMap(const char* fileName);
+
+/*
+ * Close the map.
+ */
+void android_closeEventTagMap(EventTagMap* map);
+
+/*
+ * Look up a tag by index. Returns the tag string, or NULL if not found.
+ */
+const char* android_lookupEventTag(const EventTagMap* map, int tag);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_LIBS_CUTILS_EVENTTAGMAP_H*/
diff --git a/include/cutils/hashmap.h b/include/cutils/hashmap.h
new file mode 100644
index 0000000..5cb344c
--- /dev/null
+++ b/include/cutils/hashmap.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+/**
+ * Hash map.
+ */
+
+#ifndef __HASHMAP_H
+#define __HASHMAP_H
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** A hash map. */
+typedef struct Hashmap Hashmap;
+
+/**
+ * Creates a new hash map. Returns NULL if memory allocation fails.
+ *
+ * @param initialCapacity number of expected entries
+ * @param hash function which hashes keys
+ * @param equals function which compares keys for equality
+ */
+Hashmap* hashmapCreate(size_t initialCapacity,
+ int (*hash)(void* key), bool (*equals)(void* keyA, void* keyB));
+
+/**
+ * Frees the hash map. Does not free the keys or values themselves.
+ */
+void hashmapFree(Hashmap* map);
+
+/**
+ * Hashes the memory pointed to by key with the given size. Useful for
+ * implementing hash functions.
+ */
+int hashmapHash(void* key, size_t keySize);
+
+/**
+ * Puts value for the given key in the map. Returns pre-existing value if
+ * any.
+ *
+ * If memory allocation fails, this function returns NULL, the map's size
+ * does not increase, and errno is set to ENOMEM.
+ */
+void* hashmapPut(Hashmap* map, void* key, void* value);
+
+/**
+ * Gets a value from the map. Returns NULL if no entry for the given key is
+ * found or if the value itself is NULL.
+ */
+void* hashmapGet(Hashmap* map, void* key);
+
+/**
+ * Returns true if the map contains an entry for the given key.
+ */
+bool hashmapContainsKey(Hashmap* map, void* key);
+
+/**
+ * Gets the value for a key. If a value is not found, this function gets a
+ * value and creates an entry using the given callback.
+ *
+ * If memory allocation fails, the callback is not called, this function
+ * returns NULL, and errno is set to ENOMEM.
+ */
+void* hashmapMemoize(Hashmap* map, void* key,
+ void* (*initialValue)(void* key, void* context), void* context);
+
+/**
+ * Removes an entry from the map. Returns the removed value or NULL if no
+ * entry was present.
+ */
+void* hashmapRemove(Hashmap* map, void* key);
+
+/**
+ * Gets the number of entries in this map.
+ */
+size_t hashmapSize(Hashmap* map);
+
+/**
+ * Invokes the given callback on each entry in the map. Stops iterating if
+ * the callback returns false.
+ */
+void hashmapForEach(Hashmap* map,
+ bool (*callback)(void* key, void* value, void* context),
+ void* context);
+
+/**
+ * Concurrency support.
+ */
+
+/**
+ * Locks the hash map so only the current thread can access it.
+ */
+void hashmapLock(Hashmap* map);
+
+/**
+ * Unlocks the hash map so other threads can access it.
+ */
+void hashmapUnlock(Hashmap* map);
+
+/**
+ * Key utilities.
+ */
+
+/**
+ * Hashes int keys. 'key' is a pointer to int.
+ */
+int hashmapIntHash(void* key);
+
+/**
+ * Compares two int keys for equality.
+ */
+bool hashmapIntEquals(void* keyA, void* keyB);
+
+/**
+ * For debugging.
+ */
+
+/**
+ * Gets current capacity.
+ */
+size_t hashmapCurrentCapacity(Hashmap* map);
+
+/**
+ * Counts the number of entry collisions.
+ */
+size_t hashmapCountCollisions(Hashmap* map);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HASHMAP_H */
diff --git a/include/cutils/iosched_policy.h b/include/cutils/iosched_policy.h
new file mode 100644
index 0000000..07c5d1f
--- /dev/null
+++ b/include/cutils/iosched_policy.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef __CUTILS_IOSCHED_POLICY_H
+#define __CUTILS_IOSCHED_POLICY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ IoSchedClass_NONE,
+ IoSchedClass_RT,
+ IoSchedClass_BE,
+ IoSchedClass_IDLE,
+} IoSchedClass;
+
+extern int android_set_ioprio(int pid, IoSchedClass clazz, int ioprio);
+extern int android_get_ioprio(int pid, IoSchedClass *clazz, int *ioprio);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_IOSCHED_POLICY_H */
diff --git a/include/cutils/jstring.h b/include/cutils/jstring.h
new file mode 100644
index 0000000..ee0018f
--- /dev/null
+++ b/include/cutils/jstring.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#ifndef __CUTILS_STRING16_H
+#define __CUTILS_STRING16_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uint16_t char16_t;
+
+extern char * strndup16to8 (const char16_t* s, size_t n);
+extern size_t strnlen16to8 (const char16_t* s, size_t n);
+extern char * strncpy16to8 (char *dest, const char16_t*s, size_t n);
+
+extern char16_t * strdup8to16 (const char* s, size_t *out_len);
+extern size_t strlen8to16 (const char* utf8Str);
+extern char16_t * strcpy8to16 (char16_t *dest, const char*s, size_t *out_len);
+extern char16_t * strcpylen8to16 (char16_t *dest, const char*s, int length,
+ size_t *out_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_STRING16_H */
diff --git a/include/cutils/klog.h b/include/cutils/klog.h
new file mode 100644
index 0000000..1335543
--- /dev/null
+++ b/include/cutils/klog.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef _CUTILS_KLOG_H_
+#define _CUTILS_KLOG_H_
+
+void klog_init(void);
+void klog_set_level(int level);
+void klog_close(void);
+void klog_write(int level, const char *fmt, ...)
+ __attribute__ ((format(printf, 2, 3)));
+
+#define KLOG_ERROR(tag,x...) klog_write(3, "<3>" tag ": " x)
+#define KLOG_WARNING(tag,x...) klog_write(4, "<4>" tag ": " x)
+#define KLOG_NOTICE(tag,x...) klog_write(5, "<5>" tag ": " x)
+#define KLOG_INFO(tag,x...) klog_write(6, "<6>" tag ": " x)
+#define KLOG_DEBUG(tag,x...) klog_write(7, "<7>" tag ": " x)
+
+#define KLOG_DEFAULT_LEVEL 3 /* messages <= this level are logged */
+
+#endif
diff --git a/include/cutils/list.h b/include/cutils/list.h
new file mode 100644
index 0000000..3881fc9
--- /dev/null
+++ b/include/cutils/list.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef _CUTILS_LIST_H_
+#define _CUTILS_LIST_H_
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct listnode
+{
+ struct listnode *next;
+ struct listnode *prev;
+};
+
+#define node_to_item(node, container, member) \
+ (container *) (((char*) (node)) - offsetof(container, member))
+
+#define list_declare(name) \
+ struct listnode name = { \
+ .next = &name, \
+ .prev = &name, \
+ }
+
+#define list_for_each(node, list) \
+ for (node = (list)->next; node != (list); node = node->next)
+
+#define list_for_each_reverse(node, list) \
+ for (node = (list)->prev; node != (list); node = node->prev)
+
+void list_init(struct listnode *list);
+void list_add_tail(struct listnode *list, struct listnode *item);
+void list_remove(struct listnode *item);
+
+#define list_empty(list) ((list) == (list)->next)
+#define list_head(list) ((list)->next)
+#define list_tail(list) ((list)->prev)
+
+#ifdef __cplusplus
+};
+#endif /* __cplusplus */
+
+#endif
diff --git a/include/cutils/log.h b/include/cutils/log.h
new file mode 100644
index 0000000..878952e
--- /dev/null
+++ b/include/cutils/log.h
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// C/C++ logging functions. See the logging documentation for API details.
+//
+// We'd like these to be available from C code (in case we import some from
+// somewhere), so this has a C interface.
+//
+// The output will be correct when the log file is shared between multiple
+// threads and/or multiple processes so long as the operating system
+// supports O_APPEND. These calls have mutex-protected data structures
+// and so are NOT reentrant. Do not use LOG in a signal handler.
+//
+#ifndef _LIBS_CUTILS_LOG_H
+#define _LIBS_CUTILS_LOG_H
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#ifdef HAVE_PTHREADS
+#include <pthread.h>
+#endif
+#include <stdarg.h>
+
+#include <cutils/uio.h>
+#include <cutils/logd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Normally we strip ALOGV (VERBOSE messages) from release builds.
+ * You can modify this (for example with "#define LOG_NDEBUG 0"
+ * at the top of your source file) to change that behavior.
+ */
+#ifndef LOG_NDEBUG
+#ifdef NDEBUG
+#define LOG_NDEBUG 1
+#else
+#define LOG_NDEBUG 0
+#endif
+#endif
+
+/*
+ * This is the local tag used for the following simplified
+ * logging macros. You can change this preprocessor definition
+ * before using the other macros to change the tag.
+ */
+#ifndef LOG_TAG
+#define LOG_TAG NULL
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Simplified macro to send a verbose log message using the current LOG_TAG.
+ */
+#ifndef ALOGV
+#if LOG_NDEBUG
+#define ALOGV(...) ((void)0)
+#else
+#define ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#endif
+#endif
+
+#define CONDITION(cond) (__builtin_expect((cond)!=0, 0))
+
+#ifndef ALOGV_IF
+#if LOG_NDEBUG
+#define ALOGV_IF(cond, ...) ((void)0)
+#else
+#define ALOGV_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+#endif
+
+/*
+ * Simplified macro to send a debug log message using the current LOG_TAG.
+ */
+#ifndef ALOGD
+#define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef ALOGD_IF
+#define ALOGD_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an info log message using the current LOG_TAG.
+ */
+#ifndef ALOGI
+#define ALOGI(...) ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef ALOGI_IF
+#define ALOGI_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send a warning log message using the current LOG_TAG.
+ */
+#ifndef ALOGW
+#define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef ALOGW_IF
+#define ALOGW_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an error log message using the current LOG_TAG.
+ */
+#ifndef ALOGE
+#define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef ALOGE_IF
+#define ALOGE_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * verbose priority.
+ */
+#ifndef IF_ALOGV
+#if LOG_NDEBUG
+#define IF_ALOGV() if (false)
+#else
+#define IF_ALOGV() IF_ALOG(LOG_VERBOSE, LOG_TAG)
+#endif
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * debug priority.
+ */
+#ifndef IF_ALOGD
+#define IF_ALOGD() IF_ALOG(LOG_DEBUG, LOG_TAG)
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * info priority.
+ */
+#ifndef IF_ALOGI
+#define IF_ALOGI() IF_ALOG(LOG_INFO, LOG_TAG)
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * warn priority.
+ */
+#ifndef IF_ALOGW
+#define IF_ALOGW() IF_ALOG(LOG_WARN, LOG_TAG)
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * error priority.
+ */
+#ifndef IF_ALOGE
+#define IF_ALOGE() IF_ALOG(LOG_ERROR, LOG_TAG)
+#endif
+
+
+// ---------------------------------------------------------------------
+
+/*
+ * Simplified macro to send a verbose system log message using the current LOG_TAG.
+ */
+#ifndef SLOGV
+#if LOG_NDEBUG
+#define SLOGV(...) ((void)0)
+#else
+#define SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#endif
+#endif
+
+#define CONDITION(cond) (__builtin_expect((cond)!=0, 0))
+
+#ifndef SLOGV_IF
+#if LOG_NDEBUG
+#define SLOGV_IF(cond, ...) ((void)0)
+#else
+#define SLOGV_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+#endif
+
+/*
+ * Simplified macro to send a debug system log message using the current LOG_TAG.
+ */
+#ifndef SLOGD
+#define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGD_IF
+#define SLOGD_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an info system log message using the current LOG_TAG.
+ */
+#ifndef SLOGI
+#define SLOGI(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGI_IF
+#define SLOGI_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send a warning system log message using the current LOG_TAG.
+ */
+#ifndef SLOGW
+#define SLOGW(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGW_IF
+#define SLOGW_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an error system log message using the current LOG_TAG.
+ */
+#ifndef SLOGE
+#define SLOGE(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGE_IF
+#define SLOGE_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+
+
+
+// ---------------------------------------------------------------------
+
+/*
+ * Log a fatal error. If the given condition fails, this stops program
+ * execution like a normal assertion, but also generating the given message.
+ * It is NOT stripped from release builds. Note that the condition test
+ * is -inverted- from the normal assert() semantics.
+ */
+#ifndef LOG_ALWAYS_FATAL_IF
+#define LOG_ALWAYS_FATAL_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \
+ : (void)0 )
+#endif
+
+#ifndef LOG_ALWAYS_FATAL
+#define LOG_ALWAYS_FATAL(...) \
+ ( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) )
+#endif
+
+/*
+ * Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that
+ * are stripped out of release builds.
+ */
+#if LOG_NDEBUG
+
+#ifndef LOG_FATAL_IF
+#define LOG_FATAL_IF(cond, ...) ((void)0)
+#endif
+#ifndef LOG_FATAL
+#define LOG_FATAL(...) ((void)0)
+#endif
+
+#else
+
+#ifndef LOG_FATAL_IF
+#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__)
+#endif
+#ifndef LOG_FATAL
+#define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__)
+#endif
+
+#endif
+
+/*
+ * Assertion that generates a log message when the assertion fails.
+ * Stripped out of release builds. Uses the current LOG_TAG.
+ */
+#ifndef ALOG_ASSERT
+#define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__)
+//#define ALOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond)
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Basic log message macro.
+ *
+ * Example:
+ * ALOG(LOG_WARN, NULL, "Failed with error %d", errno);
+ *
+ * The second argument may be NULL or "" to indicate the "global" tag.
+ */
+#ifndef ALOG
+#define ALOG(priority, tag, ...) \
+ LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
+#endif
+
+/*
+ * Log macro that allows you to specify a number for the priority.
+ */
+#ifndef LOG_PRI
+#define LOG_PRI(priority, tag, ...) \
+ android_printLog(priority, tag, __VA_ARGS__)
+#endif
+
+/*
+ * Log macro that allows you to pass in a varargs ("args" is a va_list).
+ */
+#ifndef LOG_PRI_VA
+#define LOG_PRI_VA(priority, tag, fmt, args) \
+ android_vprintLog(priority, NULL, tag, fmt, args)
+#endif
+
+/*
+ * Conditional given a desired logging priority and tag.
+ */
+#ifndef IF_ALOG
+#define IF_ALOG(priority, tag) \
+ if (android_testLog(ANDROID_##priority, tag))
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Event logging.
+ */
+
+/*
+ * Event log entry types. These must match up with the declarations in
+ * java/android/android/util/EventLog.java.
+ */
+typedef enum {
+ EVENT_TYPE_INT = 0,
+ EVENT_TYPE_LONG = 1,
+ EVENT_TYPE_STRING = 2,
+ EVENT_TYPE_LIST = 3,
+} AndroidEventLogType;
+
+
+#ifndef LOG_EVENT_INT
+#define LOG_EVENT_INT(_tag, _value) { \
+ int intBuf = _value; \
+ (void) android_btWriteLog(_tag, EVENT_TYPE_INT, &intBuf, \
+ sizeof(intBuf)); \
+ }
+#endif
+#ifndef LOG_EVENT_LONG
+#define LOG_EVENT_LONG(_tag, _value) { \
+ long long longBuf = _value; \
+ (void) android_btWriteLog(_tag, EVENT_TYPE_LONG, &longBuf, \
+ sizeof(longBuf)); \
+ }
+#endif
+#ifndef LOG_EVENT_STRING
+#define LOG_EVENT_STRING(_tag, _value) \
+ ((void) 0) /* not implemented -- must combine len with string */
+#endif
+/* TODO: something for LIST */
+
+/*
+ * ===========================================================================
+ *
+ * The stuff in the rest of this file should not be used directly.
+ */
+
+#define android_printLog(prio, tag, fmt...) \
+ __android_log_print(prio, tag, fmt)
+
+#define android_vprintLog(prio, cond, tag, fmt...) \
+ __android_log_vprint(prio, tag, fmt)
+
+/* XXX Macros to work around syntax errors in places where format string
+ * arg is not passed to ALOG_ASSERT, LOG_ALWAYS_FATAL or LOG_ALWAYS_FATAL_IF
+ * (happens only in debug builds).
+ */
+
+/* Returns 2nd arg. Used to substitute default value if caller's vararg list
+ * is empty.
+ */
+#define __android_second(dummy, second, ...) second
+
+/* If passed multiple args, returns ',' followed by all but 1st arg, otherwise
+ * returns nothing.
+ */
+#define __android_rest(first, ...) , ## __VA_ARGS__
+
+#define android_printAssert(cond, tag, fmt...) \
+ __android_log_assert(cond, tag, \
+ __android_second(0, ## fmt, NULL) __android_rest(fmt))
+
+#define android_writeLog(prio, tag, text) \
+ __android_log_write(prio, tag, text)
+
+#define android_bWriteLog(tag, payload, len) \
+ __android_log_bwrite(tag, payload, len)
+#define android_btWriteLog(tag, type, payload, len) \
+ __android_log_btwrite(tag, type, payload, len)
+
+// TODO: remove these prototypes and their users
+#define android_testLog(prio, tag) (1)
+#define android_writevLog(vec,num) do{}while(0)
+#define android_write1Log(str,len) do{}while (0)
+#define android_setMinPriority(tag, prio) do{}while(0)
+//#define android_logToCallback(func) do{}while(0)
+#define android_logToFile(tag, file) (0)
+#define android_logToFd(tag, fd) (0)
+
+typedef enum {
+ LOG_ID_MAIN = 0,
+ LOG_ID_RADIO = 1,
+ LOG_ID_EVENTS = 2,
+ LOG_ID_SYSTEM = 3,
+
+ LOG_ID_MAX
+} log_id_t;
+
+/*
+ * Send a simple string to the log.
+ */
+int __android_log_buf_write(int bufID, int prio, const char *tag, const char *text);
+int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _LIBS_CUTILS_LOG_H
diff --git a/include/cutils/logd.h b/include/cutils/logd.h
new file mode 100644
index 0000000..8737639
--- /dev/null
+++ b/include/cutils/logd.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef _ANDROID_CUTILS_LOGD_H
+#define _ANDROID_CUTILS_LOGD_H
+
+/* the stable/frozen log-related definitions have been
+ * moved to this header, which is exposed by the NDK
+ */
+#include <android/log.h>
+
+/* the rest is only used internally by the system */
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/types.h>
+#ifdef HAVE_PTHREADS
+#include <pthread.h>
+#endif
+#include <cutils/uio.h>
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int __android_log_bwrite(int32_t tag, const void *payload, size_t len);
+int __android_log_btwrite(int32_t tag, char type, const void *payload,
+ size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LOGD_H */
diff --git a/include/cutils/logger.h b/include/cutils/logger.h
new file mode 100644
index 0000000..04f3fb0
--- /dev/null
+++ b/include/cutils/logger.h
@@ -0,0 +1,81 @@
+/* utils/logger.h
+**
+** Copyright 2007, The Android Open Source Project
+**
+** This file is dual licensed. It may be redistributed and/or modified
+** under the terms of the Apache 2.0 License OR version 2 of the GNU
+** General Public License.
+*/
+
+#ifndef _UTILS_LOGGER_H
+#define _UTILS_LOGGER_H
+
+#include <stdint.h>
+
+/*
+ * The userspace structure for version 1 of the logger_entry ABI.
+ * This structure is returned to userspace by the kernel logger
+ * driver unless an upgrade to a newer ABI version is requested.
+ */
+struct logger_entry {
+ uint16_t len; /* length of the payload */
+ uint16_t __pad; /* no matter what, we get 2 bytes of padding */
+ int32_t pid; /* generating process's pid */
+ int32_t tid; /* generating process's tid */
+ int32_t sec; /* seconds since Epoch */
+ int32_t nsec; /* nanoseconds */
+ char msg[0]; /* the entry's payload */
+};
+
+/*
+ * The userspace structure for version 2 of the logger_entry ABI.
+ * This structure is returned to userspace if ioctl(LOGGER_SET_VERSION)
+ * is called with version==2
+ */
+struct logger_entry_v2 {
+ uint16_t len; /* length of the payload */
+ uint16_t hdr_size; /* sizeof(struct logger_entry_v2) */
+ int32_t pid; /* generating process's pid */
+ int32_t tid; /* generating process's tid */
+ int32_t sec; /* seconds since Epoch */
+ int32_t nsec; /* nanoseconds */
+ uint32_t euid; /* effective UID of logger */
+ char msg[0]; /* the entry's payload */
+};
+
+#define LOGGER_LOG_MAIN "log/main"
+#define LOGGER_LOG_RADIO "log/radio"
+#define LOGGER_LOG_EVENTS "log/events"
+#define LOGGER_LOG_SYSTEM "log/system"
+
+/*
+ * The maximum size of the log entry payload that can be
+ * written to the kernel logger driver. An attempt to write
+ * more than this amount to /dev/log/* will result in a
+ * truncated log entry.
+ */
+#define LOGGER_ENTRY_MAX_PAYLOAD 4076
+
+/*
+ * The maximum size of a log entry which can be read from the
+ * kernel logger driver. An attempt to read less than this amount
+ * may result in read() returning EINVAL.
+ */
+#define LOGGER_ENTRY_MAX_LEN (5*1024)
+
+#ifdef HAVE_IOCTL
+
+#include <sys/ioctl.h>
+
+#define __LOGGERIO 0xAE
+
+#define LOGGER_GET_LOG_BUF_SIZE _IO(__LOGGERIO, 1) /* size of log */
+#define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */
+#define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */
+#define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */
+#define LOGGER_GET_VERSION _IO(__LOGGERIO, 5) /* abi version */
+#define LOGGER_SET_VERSION _IO(__LOGGERIO, 6) /* abi version */
+
+#endif // HAVE_IOCTL
+
+#endif /* _UTILS_LOGGER_H */
diff --git a/include/cutils/logprint.h b/include/cutils/logprint.h
new file mode 100644
index 0000000..2b1e1c5
--- /dev/null
+++ b/include/cutils/logprint.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#ifndef _LOGPRINT_H
+#define _LOGPRINT_H
+
+#include <cutils/log.h>
+#include <cutils/logger.h>
+#include <cutils/event_tag_map.h>
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ FORMAT_OFF = 0,
+ FORMAT_BRIEF,
+ FORMAT_PROCESS,
+ FORMAT_TAG,
+ FORMAT_THREAD,
+ FORMAT_RAW,
+ FORMAT_TIME,
+ FORMAT_THREADTIME,
+ FORMAT_LONG,
+} AndroidLogPrintFormat;
+
+typedef struct AndroidLogFormat_t AndroidLogFormat;
+
+typedef struct AndroidLogEntry_t {
+ time_t tv_sec;
+ long tv_nsec;
+ android_LogPriority priority;
+ int32_t pid;
+ int32_t tid;
+ const char * tag;
+ size_t messageLen;
+ const char * message;
+} AndroidLogEntry;
+
+AndroidLogFormat *android_log_format_new();
+
+void android_log_format_free(AndroidLogFormat *p_format);
+
+void android_log_setPrintFormat(AndroidLogFormat *p_format,
+ AndroidLogPrintFormat format);
+
+/**
+ * Returns FORMAT_OFF on invalid string
+ */
+AndroidLogPrintFormat android_log_formatFromString(const char *s);
+
+/**
+ * filterExpression: a single filter expression
+ * eg "AT:d"
+ *
+ * returns 0 on success and -1 on invalid expression
+ *
+ * Assumes single threaded execution
+ *
+ */
+
+int android_log_addFilterRule(AndroidLogFormat *p_format,
+ const char *filterExpression);
+
+
+/**
+ * filterString: a whitespace-separated set of filter expressions
+ * eg "AT:d *:i"
+ *
+ * returns 0 on success and -1 on invalid expression
+ *
+ * Assumes single threaded execution
+ *
+ */
+
+int android_log_addFilterString(AndroidLogFormat *p_format,
+ const char *filterString);
+
+
+/**
+ * returns 1 if this log line should be printed based on its priority
+ * and tag, and 0 if it should not
+ */
+int android_log_shouldPrintLine (
+ AndroidLogFormat *p_format, const char *tag, android_LogPriority pri);
+
+
+/**
+ * Splits a wire-format buffer into an AndroidLogEntry
+ * entry allocated by caller. Pointers will point directly into buf
+ *
+ * Returns 0 on success and -1 on invalid wire format (entry will be
+ * in unspecified state)
+ */
+int android_log_processLogBuffer(struct logger_entry *buf,
+ AndroidLogEntry *entry);
+
+/**
+ * Like android_log_processLogBuffer, but for binary logs.
+ *
+ * If "map" is non-NULL, it will be used to convert the log tag number
+ * into a string.
+ */
+int android_log_processBinaryLogBuffer(struct logger_entry *buf,
+ AndroidLogEntry *entry, const EventTagMap* map, char* messageBuf,
+ int messageBufLen);
+
+
+/**
+ * Formats a log message into a buffer
+ *
+ * Uses defaultBuffer if it can, otherwise malloc()'s a new buffer
+ * If return value != defaultBuffer, caller must call free()
+ * Returns NULL on malloc error
+ */
+
+char *android_log_formatLogLine (
+ AndroidLogFormat *p_format,
+ char *defaultBuffer,
+ size_t defaultBufferSize,
+ const AndroidLogEntry *p_line,
+ size_t *p_outLength);
+
+
+/**
+ * Either print or do not print log line, based on filter
+ *
+ * Assumes single threaded execution
+ *
+ */
+int android_log_printLogLine(
+ AndroidLogFormat *p_format,
+ int fd,
+ const AndroidLogEntry *entry);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /*_LOGPRINT_H*/
diff --git a/include/cutils/memory.h b/include/cutils/memory.h
new file mode 100644
index 0000000..e725cdd
--- /dev/null
+++ b/include/cutils/memory.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#ifndef ANDROID_CUTILS_MEMORY_H
+#define ANDROID_CUTILS_MEMORY_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* size is given in bytes and must be multiple of 2 */
+void android_memset16(uint16_t* dst, uint16_t value, size_t size);
+
+/* size is given in bytes and must be multiple of 4 */
+void android_memset32(uint32_t* dst, uint32_t value, size_t size);
+
+#if !HAVE_STRLCPY
+/* Declaration of strlcpy() for platforms that don't already have it. */
+size_t strlcpy(char *dst, const char *src, size_t size);
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // ANDROID_CUTILS_MEMORY_H
diff --git a/include/cutils/misc.h b/include/cutils/misc.h
new file mode 100644
index 0000000..2c48dfa
--- /dev/null
+++ b/include/cutils/misc.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#ifndef __CUTILS_MISC_H
+#define __CUTILS_MISC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /* Load an entire file into a malloc'd chunk of memory
+ * that is length_of_file + 1 (null terminator). If
+ * sz is non-zero, return the size of the file via sz.
+ * Returns 0 on failure.
+ */
+extern void *load_file(const char *fn, unsigned *sz);
+
+ /* Connects your process to the system debugger daemon
+ * so that on a crash it may be logged or interactively
+ * debugged (depending on system settings).
+ */
+extern void debuggerd_connect(void);
+
+
+ /* This is the range of UIDs (and GIDs) that are reserved
+ * for assigning to applications.
+ */
+#define FIRST_APPLICATION_UID 10000
+#define LAST_APPLICATION_UID 99999
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_MISC_H */
diff --git a/include/cutils/mq.h b/include/cutils/mq.h
new file mode 100644
index 0000000..b27456d
--- /dev/null
+++ b/include/cutils/mq.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+/**
+ * IPC messaging library.
+ */
+
+#ifndef __MQ_H
+#define __MQ_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** A message. */
+typedef struct MqMessage MqMessage;
+
+/** A destination to which messages can be sent. */
+typedef struct MqDestination MqDestination;
+
+/* Array of bytes. */
+typedef struct MqBytes MqBytes;
+
+/**
+ * Hears messages.
+ *
+ * @param destination to which the message was sent
+ * @param message the message to hear
+ */
+typedef void MqMessageListener(MqDestination* destination, MqMessage* message);
+
+/**
+ * Hears a destination close.
+ *
+ * @param destination that closed
+ */
+typedef void MqCloseListener(MqDestination* destination);
+
+/** Message functions. */
+
+/**
+ * Creates a new Message.
+ *
+ * @param header as defined by user
+ * @param body as defined by user
+ * @param replyTo destination to which replies should be sent, NULL if none
+ */
+MqMessage* mqCreateMessage(MqBytes header, MqBytes body,
+ MqDestination* replyTo);
+
+/** Sends a message to a destination. */
+void mqSendMessage(MqMessage* message, MqDestination* destination);
+
+/** Destination functions. */
+
+/**
+ * Creates a new destination. Acquires a reference implicitly.
+ *
+ * @param messageListener function to call when a message is recieved
+ * @param closeListener function to call when the destination closes
+ * @param userData user-specific data to associate with the destination.
+ * Retrieve using mqGetDestinationUserData().
+ */
+MqDestination* mqCreateDestination(MqMessageListener* messageListener,
+ MqCloseListener* closeListener, void* userData);
+
+/**
+ * Gets user data which was associated with the given destination at
+ * construction time.
+ *
+ * It is only valid to call this function in the same process that the
+ * given destination was created in.
+ * This function returns a null pointer if you call it on a destination
+ * created in a remote process.
+ */
+void* mqGetUserData(MqDestination* destination);
+
+/**
+ * Returns 1 if the destination was created in this process, or 0 if
+ * the destination was created in a different process, in which case you have
+ * a remote stub.
+ */
+int mqIsDestinationLocal(MqDestination* destination);
+
+/**
+ * Increments the destination's reference count.
+ */
+void mqKeepDestination(MqDesintation* destination);
+
+/**
+ * Decrements the destination's reference count.
+ */
+void mqFreeDestination(MqDestination* desintation);
+
+/** Registry API. */
+
+/**
+ * Gets the destination bound to a name.
+ */
+MqDestination* mqGetDestination(char* name);
+
+/**
+ * Binds a destination to a name.
+ */
+void mqPutDestination(char* name, MqDestination* desintation);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MQ_H */
diff --git a/include/cutils/mspace.h b/include/cutils/mspace.h
new file mode 100644
index 0000000..93fe48e
--- /dev/null
+++ b/include/cutils/mspace.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+/* A wrapper file for dlmalloc.h that defines prototypes for the
+ * mspace_*() functions, which provide an interface for creating
+ * multiple heaps.
+ */
+
+#ifndef MSPACE_H_
+#define MSPACE_H_
+
+/* It's a pain getting the mallinfo stuff to work
+ * with Linux, OSX, and klibc, so just turn it off
+ * for now.
+ * TODO: make mallinfo work
+ */
+#define NO_MALLINFO 1
+
+/* Allow setting the maximum heap footprint.
+ */
+#define USE_MAX_ALLOWED_FOOTPRINT 1
+
+#define USE_CONTIGUOUS_MSPACES 1
+#if USE_CONTIGUOUS_MSPACES
+#define HAVE_MMAP 0
+#define HAVE_MORECORE 1
+#define MORECORE_CONTIGUOUS 0
+#endif
+
+#define MSPACES 1
+#define ONLY_MSPACES 1
+#include "../../../../bionic/libc/bionic/dlmalloc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ mspace_usable_size(void* p);
+
+ Returns the number of bytes you can actually use in
+ an allocated chunk, which may be more than you requested (although
+ often not) due to alignment and minimum size constraints.
+ You can use this many bytes without worrying about
+ overwriting other allocated objects. This is not a particularly great
+ programming practice. mspace_usable_size can be more useful in
+ debugging and assertions, for example:
+
+ p = mspace_malloc(msp, n);
+ assert(mspace_usable_size(msp, p) >= 256);
+*/
+size_t mspace_usable_size(mspace, const void*);
+
+#if USE_CONTIGUOUS_MSPACES
+/*
+ Similar to create_mspace(), but the underlying memory is
+ guaranteed to be contiguous. No more than max_capacity
+ bytes is ever allocated to the mspace.
+ */
+mspace create_contiguous_mspace(size_t starting_capacity, size_t max_capacity,
+ int locked);
+
+/*
+ Identical to create_contiguous_mspace, but labels the mapping 'mspace/name'
+ instead of 'mspace'
+*/
+mspace create_contiguous_mspace_with_name(size_t starting_capacity,
+ size_t max_capacity, int locked, const char *name);
+
+/*
+ Identical to create_contiguous_mspace, but uses previously mapped memory.
+*/
+mspace create_contiguous_mspace_with_base(size_t starting_capacity,
+ size_t max_capacity, int locked, void *base);
+
+size_t destroy_contiguous_mspace(mspace msp);
+
+/*
+ Returns the position of the "break" within the given mspace.
+*/
+void *contiguous_mspace_sbrk0(mspace msp);
+#endif
+
+/*
+ Call the handler for each block in the specified mspace.
+ chunkptr and chunklen refer to the heap-level chunk including
+ the chunk overhead, and userptr and userlen refer to the
+ user-usable part of the chunk. If the chunk is free, userptr
+ will be NULL and userlen will be 0. userlen is not guaranteed
+ to be the same value passed into malloc() for a given chunk;
+ it is >= the requested size.
+ */
+void mspace_walk_heap(mspace msp,
+ void(*handler)(const void *chunkptr, size_t chunklen,
+ const void *userptr, size_t userlen, void *arg), void *harg);
+
+/*
+ mspace_walk_free_pages(handler, harg)
+
+ Calls the provided handler on each free region in the specified
+ mspace. The memory between start and end are guaranteed not to
+ contain any important data, so the handler is free to alter the
+ contents in any way. This can be used to advise the OS that large
+ free regions may be swapped out.
+
+ The value in harg will be passed to each call of the handler.
+ */
+void mspace_walk_free_pages(mspace msp,
+ void(*handler)(void *start, void *end, void *arg), void *harg);
+
+#ifdef __cplusplus
+}; /* end of extern "C" */
+#endif
+
+#endif /* MSPACE_H_ */
diff --git a/include/cutils/native_handle.h b/include/cutils/native_handle.h
new file mode 100644
index 0000000..268c5d3
--- /dev/null
+++ b/include/cutils/native_handle.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef NATIVE_HANDLE_H_
+#define NATIVE_HANDLE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct native_handle
+{
+ int version; /* sizeof(native_handle_t) */
+ int numFds; /* number of file-descriptors at &data[0] */
+ int numInts; /* number of ints at &data[numFds] */
+ int data[0]; /* numFds + numInts ints */
+} native_handle_t;
+
+/*
+ * native_handle_close
+ *
+ * closes the file descriptors contained in this native_handle_t
+ *
+ * return 0 on success, or a negative error code on failure
+ *
+ */
+int native_handle_close(const native_handle_t* h);
+
+
+/*
+ * native_handle_create
+ *
+ * creates a native_handle_t and initializes it. must be destroyed with
+ * native_handle_delete().
+ *
+ */
+native_handle_t* native_handle_create(int numFds, int numInts);
+
+/*
+ * native_handle_delete
+ *
+ * frees a native_handle_t allocated with native_handle_create().
+ * This ONLY frees the memory allocated for the native_handle_t, but doesn't
+ * close the file descriptors; which can be achieved with native_handle_close().
+ *
+ * return 0 on success, or a negative error code on failure
+ *
+ */
+int native_handle_delete(native_handle_t* h);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NATIVE_HANDLE_H_ */
diff --git a/include/cutils/open_memstream.h b/include/cutils/open_memstream.h
new file mode 100644
index 0000000..b7998be
--- /dev/null
+++ b/include/cutils/open_memstream.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __CUTILS_OPEN_MEMSTREAM_H__
+#define __CUTILS_OPEN_MEMSTREAM_H__
+
+#include <stdio.h>
+
+#ifndef HAVE_OPEN_MEMSTREAM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+FILE* open_memstream(char** bufp, size_t* sizep);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*!HAVE_OPEN_MEMSTREAM*/
+
+#endif /*__CUTILS_OPEN_MEMSTREAM_H__*/
diff --git a/include/cutils/partition_utils.h b/include/cutils/partition_utils.h
new file mode 100644
index 0000000..597df92
--- /dev/null
+++ b/include/cutils/partition_utils.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef __CUTILS_PARTITION_WIPED_H__
+#define __CUTILS_PARTITION_WIPED_H__
+
+__BEGIN_DECLS
+
+int partition_wiped(char *source);
+void erase_footer(const char *dev_path, long long size);
+
+__END_DECLS
+
+#endif /* __CUTILS_PARTITION_WIPED_H__ */
diff --git a/include/cutils/process_name.h b/include/cutils/process_name.h
new file mode 100644
index 0000000..1e72e5c
--- /dev/null
+++ b/include/cutils/process_name.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 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.
+ * 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.
+ */
+
+/**
+ * Gives the current process a name.
+ */
+
+#ifndef __PROCESS_NAME_H
+#define __PROCESS_NAME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Sets the current process name.
+ *
+ * Warning: This leaks a string every time you call it. Use judiciously!
+ */
+void set_process_name(const char* process_name);
+
+/** Gets the current process name. */
+const char* get_process_name(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PROCESS_NAME_H */
diff --git a/include/cutils/properties.h b/include/cutils/properties.h
new file mode 100644
index 0000000..25fd67a
--- /dev/null
+++ b/include/cutils/properties.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#ifndef __CUTILS_PROPERTIES_H
+#define __CUTILS_PROPERTIES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* System properties are *small* name value pairs managed by the
+** property service. If your data doesn't fit in the provided
+** space it is not appropriate for a system property.
+**
+** WARNING: system/bionic/include/sys/system_properties.h also defines
+** these, but with different names. (TODO: fix that)
+*/
+#define PROPERTY_KEY_MAX 32
+#define PROPERTY_VALUE_MAX 92
+
+/* property_get: returns the length of the value which will never be
+** greater than PROPERTY_VALUE_MAX - 1 and will always be zero terminated.
+** (the length does not include the terminating zero).
+**
+** If the property read fails or returns an empty value, the default
+** value is used (if nonnull).
+*/
+int property_get(const char *key, char *value, const char *default_value);
+
+/* property_set: returns 0 on success, < 0 on failure
+*/
+int property_set(const char *key, const char *value);
+
+int property_list(void (*propfn)(const char *key, const char *value, void *cookie), void *cookie);
+
+
+#ifdef HAVE_SYSTEM_PROPERTY_SERVER
+/*
+ * We have an external property server instead of built-in libc support.
+ * Used by the simulator.
+ */
+#define SYSTEM_PROPERTY_PIPE_NAME "/tmp/android-sysprop"
+
+enum {
+ kSystemPropertyUnknown = 0,
+ kSystemPropertyGet,
+ kSystemPropertySet,
+ kSystemPropertyList
+};
+#endif /*HAVE_SYSTEM_PROPERTY_SERVER*/
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cutils/qsort_r_compat.h b/include/cutils/qsort_r_compat.h
new file mode 100644
index 0000000..479a1ab
--- /dev/null
+++ b/include/cutils/qsort_r_compat.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/*
+ * Provides a portable version of qsort_r, called qsort_r_compat, which is a
+ * reentrant variant of qsort that passes a user data pointer to its comparator.
+ * This implementation follows the BSD parameter convention.
+ */
+
+#ifndef _LIBS_CUTILS_QSORT_R_COMPAT_H
+#define _LIBS_CUTILS_QSORT_R_COMPAT_H
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
+ int (*compar)(void*, const void* , const void* ));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _LIBS_CUTILS_QSORT_R_COMPAT_H
diff --git a/include/cutils/qtaguid.h b/include/cutils/qtaguid.h
new file mode 100644
index 0000000..f8550fd
--- /dev/null
+++ b/include/cutils/qtaguid.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#ifndef __CUTILS_QTAGUID_H
+#define __CUTILS_QTAGUID_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Set tags (and owning UIDs) for network sockets.
+*/
+extern int qtaguid_tagSocket(int sockfd, int tag, uid_t uid);
+
+/*
+ * Untag a network socket before closing.
+*/
+extern int qtaguid_untagSocket(int sockfd);
+
+/*
+ * For the given uid, switch counter sets.
+ * The kernel only keeps a limited number of sets.
+ * 2 for now.
+ */
+extern int qtaguid_setCounterSet(int counterSetNum, uid_t uid);
+
+/*
+ * Delete all tag info that relates to the given tag an uid.
+ * If the tag is 0, then ALL info about the uid is freeded.
+ * The delete data also affects active tagged socketd, which are
+ * then untagged.
+ * The calling process can only operate on its own tags.
+ * Unless it is part of the happy AID_NET_BW_ACCT group.
+ * In which case it can clobber everything.
+ */
+extern int qtaguid_deleteTagData(int tag, uid_t uid);
+
+/*
+ * Enable/disable qtaguid functionnality at a lower level.
+ * When pacified, the kernel will accept commands but do nothing.
+ */
+extern int qtaguid_setPacifier(int on);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_QTAG_UID_H */
diff --git a/include/cutils/record_stream.h b/include/cutils/record_stream.h
new file mode 100644
index 0000000..bfac87a
--- /dev/null
+++ b/include/cutils/record_stream.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+/*
+ * A simple utility for reading fixed records out of a stream fd
+ */
+
+#ifndef _CUTILS_RECORD_STREAM_H
+#define _CUTILS_RECORD_STREAM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct RecordStream RecordStream;
+
+extern RecordStream *record_stream_new(int fd, size_t maxRecordLen);
+extern void record_stream_free(RecordStream *p_rs);
+
+extern int record_stream_get_next (RecordStream *p_rs, void ** p_outRecord,
+ size_t *p_outRecordLen);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /*_CUTILS_RECORD_STREAM_H*/
+
diff --git a/include/cutils/sched_policy.h b/include/cutils/sched_policy.h
new file mode 100644
index 0000000..ba84ce3
--- /dev/null
+++ b/include/cutils/sched_policy.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef __CUTILS_SCHED_POLICY_H
+#define __CUTILS_SCHED_POLICY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Keep in sync with THREAD_GROUP_* in frameworks/base/core/java/android/os/Process.java */
+typedef enum {
+ SP_DEFAULT = -1,
+ SP_BACKGROUND = 0,
+ SP_FOREGROUND = 1,
+ SP_SYSTEM = 2, // can't be used with set_sched_policy()
+ SP_AUDIO_APP = 3,
+ SP_AUDIO_SYS = 4,
+ SP_CNT,
+ SP_MAX = SP_CNT - 1,
+ SP_SYSTEM_DEFAULT = SP_FOREGROUND,
+} SchedPolicy;
+
+/* Assign thread tid to the cgroup associated with the specified policy.
+ * If the thread is a thread group leader, that is it's gettid() == getpid(),
+ * then the other threads in the same thread group are _not_ affected.
+ * On platforms which support gettid(), zero tid means current thread.
+ * Return value: 0 for success, or -errno for error.
+ */
+extern int set_sched_policy(int tid, SchedPolicy policy);
+
+/* Return the policy associated with the cgroup of thread tid via policy pointer.
+ * On platforms which support gettid(), zero tid means current thread.
+ * Return value: 0 for success, or -1 for error and set errno.
+ */
+extern int get_sched_policy(int tid, SchedPolicy *policy);
+
+/* Return a displayable string corresponding to policy.
+ * Return value: non-NULL NUL-terminated name of unspecified length;
+ * the caller is responsible for displaying the useful part of the string.
+ */
+extern const char *get_sched_policy_name(SchedPolicy policy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_SCHED_POLICY_H */
diff --git a/include/cutils/selector.h b/include/cutils/selector.h
new file mode 100644
index 0000000..dfc2a9d
--- /dev/null
+++ b/include/cutils/selector.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+/**
+ * Framework for multiplexing I/O. A selector manages a set of file
+ * descriptors and calls out to user-provided callback functions to read and
+ * write data and handle errors.
+ */
+
+#ifndef __SELECTOR_H
+#define __SELECTOR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+
+/**
+ * Manages SelectableFds and invokes their callbacks at appropriate times.
+ */
+typedef struct Selector Selector;
+
+/**
+ * A selectable descriptor. Contains callbacks which the selector can invoke
+ * before calling select(), when the descriptor is readable or writable, and
+ * when the descriptor contains out-of-band data. Simply set a callback to
+ * NULL if you're not interested in that particular event.
+ *
+ * A selectable descriptor can indicate that it needs to be removed from the
+ * selector by setting the 'remove' flag. The selector will remove the
+ * descriptor at a later time and invoke the onRemove() callback.
+ *
+ * SelectableFd fields should only be modified from the selector loop.
+ */
+typedef struct SelectableFd SelectableFd;
+struct SelectableFd {
+
+ /** The file descriptor itself. */
+ int fd;
+
+ /** Pointer to user-specific data. Can be NULL. */
+ void* data;
+
+ /**
+ * Set this flag when you no longer wish to be selected. The selector
+ * will invoke onRemove() when the descriptor is actually removed.
+ */
+ bool remove;
+
+ /**
+ * Invoked by the selector before calling select. You can set up other
+ * callbacks from here as necessary.
+ */
+ void (*beforeSelect)(SelectableFd* self);
+
+ /**
+ * Invoked by the selector when the descriptor has data available. Set to
+ * NULL to indicate that you're not interested in reading.
+ */
+ void (*onReadable)(SelectableFd* self);
+
+ /**
+ * Invoked by the selector when the descriptor can accept data. Set to
+ * NULL to indicate that you're not interested in writing.
+ */
+ void (*onWritable)(SelectableFd* self);
+
+ /**
+ * Invoked by the selector when out-of-band (OOB) data is available. Set to
+ * NULL to indicate that you're not interested in OOB data.
+ */
+ void (*onExcept)(SelectableFd* self);
+
+ /**
+ * Invoked by the selector after the descriptor is removed from the
+ * selector but before the selector frees the SelectableFd memory.
+ */
+ void (*onRemove)(SelectableFd* self);
+
+ /**
+ * The selector which selected this fd. Set by the selector itself.
+ */
+ Selector* selector;
+};
+
+/**
+ * Creates a new selector.
+ */
+Selector* selectorCreate(void);
+
+/**
+ * Creates a new selectable fd, adds it to the given selector and returns a
+ * pointer. Outside of 'selector' and 'fd', all fields are set to 0 or NULL
+ * by default.
+ *
+ * The selectable fd should only be modified from the selector loop thread.
+ */
+SelectableFd* selectorAdd(Selector* selector, int fd);
+
+/**
+ * Wakes up the selector even though no I/O events occurred. Use this
+ * to indicate that you're ready to write to a descriptor.
+ */
+void selectorWakeUp(Selector* selector);
+
+/**
+ * Loops continuously selecting file descriptors and firing events.
+ * Does not return.
+ */
+void selectorLoop(Selector* selector);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SELECTOR_H */
diff --git a/include/cutils/sockets.h b/include/cutils/sockets.h
new file mode 100644
index 0000000..19cae0c
--- /dev/null
+++ b/include/cutils/sockets.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#ifndef __CUTILS_SOCKETS_H
+#define __CUTILS_SOCKETS_H
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#ifdef HAVE_WINSOCK
+#include <winsock2.h>
+typedef int socklen_t;
+#elif HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#define ANDROID_SOCKET_ENV_PREFIX "ANDROID_SOCKET_"
+#define ANDROID_SOCKET_DIR "/dev/socket"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * android_get_control_socket - simple helper function to get the file
+ * descriptor of our init-managed Unix domain socket. `name' is the name of the
+ * socket, as given in init.rc. Returns -1 on error.
+ *
+ * This is inline and not in libcutils proper because we want to use this in
+ * third-party daemons with minimal modification.
+ */
+static inline int android_get_control_socket(const char *name)
+{
+ char key[64] = ANDROID_SOCKET_ENV_PREFIX;
+ const char *val;
+ int fd;
+
+ /* build our environment variable, counting cycles like a wolf ... */
+#if HAVE_STRLCPY
+ strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
+ name,
+ sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
+#else /* for the host, which may lack the almightly strncpy ... */
+ strncpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
+ name,
+ sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
+ key[sizeof(key)-1] = '\0';
+#endif
+
+ val = getenv(key);
+ if (!val)
+ return -1;
+
+ errno = 0;
+ fd = strtol(val, NULL, 10);
+ if (errno)
+ return -1;
+
+ return fd;
+}
+
+/*
+ * See also android.os.LocalSocketAddress.Namespace
+ */
+// Linux "abstract" (non-filesystem) namespace
+#define ANDROID_SOCKET_NAMESPACE_ABSTRACT 0
+// Android "reserved" (/dev/socket) namespace
+#define ANDROID_SOCKET_NAMESPACE_RESERVED 1
+// Normal filesystem namespace
+#define ANDROID_SOCKET_NAMESPACE_FILESYSTEM 2
+
+extern int socket_loopback_client(int port, int type);
+extern int socket_network_client(const char *host, int port, int type);
+extern int socket_loopback_server(int port, int type);
+extern int socket_local_server(const char *name, int namespaceId, int type);
+extern int socket_local_server_bind(int s, const char *name, int namespaceId);
+extern int socket_local_client_connect(int fd,
+ const char *name, int namespaceId, int type);
+extern int socket_local_client(const char *name, int namespaceId, int type);
+extern int socket_inaddr_any_server(int port, int type);
+
+/*
+ * socket_peer_is_trusted - Takes a socket which is presumed to be a
+ * connected local socket (e.g. AF_LOCAL) and returns whether the peer
+ * (the userid that owns the process on the other end of that socket)
+ * is one of the two trusted userids, root or shell.
+ *
+ * Note: This only works as advertised on the Android OS and always
+ * just returns true when called on other operating systems.
+ */
+extern bool socket_peer_is_trusted(int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_SOCKETS_H */
diff --git a/include/cutils/str_parms.h b/include/cutils/str_parms.h
new file mode 100644
index 0000000..247c996
--- /dev/null
+++ b/include/cutils/str_parms.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#ifndef __CUTILS_STR_PARMS_H
+#define __CUTILS_STR_PARMS_H
+
+#include <stdint.h>
+
+struct str_parms;
+
+struct str_parms *str_parms_create(void);
+struct str_parms *str_parms_create_str(const char *_string);
+void str_parms_destroy(struct str_parms *str_parms);
+
+void str_parms_del(struct str_parms *str_parms, const char *key);
+
+int str_parms_add_str(struct str_parms *str_parms, const char *key,
+ const char *value);
+int str_parms_add_int(struct str_parms *str_parms, const char *key, int value);
+
+int str_parms_add_float(struct str_parms *str_parms, const char *key,
+ float value);
+
+int str_parms_get_str(struct str_parms *str_parms, const char *key,
+ char *out_val, int len);
+int str_parms_get_int(struct str_parms *str_parms, const char *key,
+ int *out_val);
+int str_parms_get_float(struct str_parms *str_parms, const char *key,
+ float *out_val);
+
+char *str_parms_to_str(struct str_parms *str_parms);
+
+/* debug */
+void str_parms_dump(struct str_parms *str_parms);
+
+#endif /* __CUTILS_STR_PARMS_H */
diff --git a/include/cutils/threads.h b/include/cutils/threads.h
new file mode 100644
index 0000000..acf8f48
--- /dev/null
+++ b/include/cutils/threads.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef _LIBS_CUTILS_THREADS_H
+#define _LIBS_CUTILS_THREADS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***********************************************************************/
+/***********************************************************************/
+/***** *****/
+/***** local thread storage *****/
+/***** *****/
+/***********************************************************************/
+/***********************************************************************/
+
+#ifdef HAVE_PTHREADS
+
+#include <pthread.h>
+
+typedef struct {
+ pthread_mutex_t lock;
+ int has_tls;
+ pthread_key_t tls;
+
+} thread_store_t;
+
+#define THREAD_STORE_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0 }
+
+#elif defined HAVE_WIN32_THREADS
+
+#include <windows.h>
+
+typedef struct {
+ int lock_init;
+ int has_tls;
+ DWORD tls;
+ CRITICAL_SECTION lock;
+
+} thread_store_t;
+
+#define THREAD_STORE_INITIALIZER { 0, 0, 0, {0, 0, 0, 0, 0, 0} }
+
+#else
+# error "no thread_store_t implementation for your platform !!"
+#endif
+
+typedef void (*thread_store_destruct_t)(void* value);
+
+extern void* thread_store_get(thread_store_t* store);
+
+extern void thread_store_set(thread_store_t* store,
+ void* value,
+ thread_store_destruct_t destroy);
+
+/***********************************************************************/
+/***********************************************************************/
+/***** *****/
+/***** mutexes *****/
+/***** *****/
+/***********************************************************************/
+/***********************************************************************/
+
+#ifdef HAVE_PTHREADS
+
+typedef pthread_mutex_t mutex_t;
+
+#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+static __inline__ void mutex_lock(mutex_t* lock)
+{
+ pthread_mutex_lock(lock);
+}
+static __inline__ void mutex_unlock(mutex_t* lock)
+{
+ pthread_mutex_unlock(lock);
+}
+static __inline__ int mutex_init(mutex_t* lock)
+{
+ return pthread_mutex_init(lock, NULL);
+}
+static __inline__ void mutex_destroy(mutex_t* lock)
+{
+ pthread_mutex_destroy(lock);
+}
+#endif
+
+#ifdef HAVE_WIN32_THREADS
+typedef struct {
+ int init;
+ CRITICAL_SECTION lock[1];
+} mutex_t;
+
+#define MUTEX_INITIALIZER { 0, {{ NULL, 0, 0, NULL, NULL, 0 }} }
+
+static __inline__ void mutex_lock(mutex_t* lock)
+{
+ if (!lock->init) {
+ lock->init = 1;
+ InitializeCriticalSection( lock->lock );
+ lock->init = 2;
+ } else while (lock->init != 2)
+ Sleep(10);
+
+ EnterCriticalSection(lock->lock);
+}
+
+static __inline__ void mutex_unlock(mutex_t* lock)
+{
+ LeaveCriticalSection(lock->lock);
+}
+static __inline__ int mutex_init(mutex_t* lock)
+{
+ InitializeCriticalSection(lock->lock);
+ lock->init = 2;
+ return 0;
+}
+static __inline__ void mutex_destroy(mutex_t* lock)
+{
+ if (lock->init) {
+ lock->init = 0;
+ DeleteCriticalSection(lock->lock);
+ }
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBS_CUTILS_THREADS_H */
diff --git a/include/cutils/tztime.h b/include/cutils/tztime.h
new file mode 100644
index 0000000..36ac25d
--- /dev/null
+++ b/include/cutils/tztime.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#ifndef _CUTILS_TZTIME_H
+#define _CUTILS_TZTIME_H
+
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+time_t mktime_tz(struct tm * const tmp, char const * tz);
+void localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz);
+
+#ifdef HAVE_ANDROID_OS
+
+/* the following is defined in the Bionic C library on Android, but the
+ * declarations are only available through a platform-private header
+ */
+#include <bionic_time.h>
+
+#else /* !HAVE_ANDROID_OS */
+
+struct strftime_locale {
+ const char *mon[12]; /* short names */
+ const char *month[12]; /* long names */
+ const char *standalone_month[12]; /* long standalone names */
+ const char *wday[7]; /* short names */
+ const char *weekday[7]; /* long names */
+ const char *X_fmt;
+ const char *x_fmt;
+ const char *c_fmt;
+ const char *am;
+ const char *pm;
+ const char *date_fmt;
+};
+
+size_t strftime_tz(char *s, size_t max, const char *format, const struct tm *tm, const struct strftime_locale *locale);
+
+#endif /* !HAVE_ANDROID_OS */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_TZTIME_H */
+
diff --git a/include/cutils/uevent.h b/include/cutils/uevent.h
new file mode 100644
index 0000000..4cca7e5
--- /dev/null
+++ b/include/cutils/uevent.h
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#ifndef __CUTILS_UEVENT_H
+#define __CUTILS_UEVENT_H
+
+#include <stdbool.h>
+#include <sys/socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int uevent_open_socket(int buf_sz, bool passcred);
+ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length);
+ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, size_t length, uid_t *uid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_UEVENT_H */
diff --git a/include/cutils/uio.h b/include/cutils/uio.h
new file mode 100644
index 0000000..01a74d2
--- /dev/null
+++ b/include/cutils/uio.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+//
+// implementation of sys/uio.h for platforms that don't have it (Win32)
+//
+#ifndef _LIBS_CUTILS_UIO_H
+#define _LIBS_CUTILS_UIO_H
+
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#else
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+
+struct iovec {
+ const void* iov_base;
+ size_t iov_len;
+};
+
+extern int readv( int fd, struct iovec* vecs, int count );
+extern int writev( int fd, const struct iovec* vecs, int count );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !HAVE_SYS_UIO_H */
+
+#endif /* _LIBS_UTILS_UIO_H */
+
diff --git a/include/cutils/zygote.h b/include/cutils/zygote.h
new file mode 100644
index 0000000..22721a6
--- /dev/null
+++ b/include/cutils/zygote.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef __CUTILS_ZYGOTE_H
+#define __CUTILS_ZYGOTE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int zygote_run_oneshot(int sendStdio, int argc, const char **argv);
+int zygote_run(int argc, const char **argv);
+int zygote_run_wait(int argc, const char **argv, void (*post_run_func)(int));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_ZYGOTE_H */
diff --git a/include/system/audio.h b/include/system/audio.h
new file mode 100644
index 0000000..3807317
--- /dev/null
+++ b/include/system/audio.h
@@ -0,0 +1,518 @@
+/*
+ * 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.
+ */
+
+
+#ifndef ANDROID_AUDIO_CORE_H
+#define ANDROID_AUDIO_CORE_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <cutils/bitops.h>
+
+__BEGIN_DECLS
+
+/* The enums were moved here mostly from
+ * frameworks/base/include/media/AudioSystem.h
+ */
+
+typedef int audio_io_handle_t;
+
+/* Audio stream types */
+typedef enum {
+ AUDIO_STREAM_DEFAULT = -1,
+ AUDIO_STREAM_VOICE_CALL = 0,
+ AUDIO_STREAM_SYSTEM = 1,
+ AUDIO_STREAM_RING = 2,
+ AUDIO_STREAM_MUSIC = 3,
+ AUDIO_STREAM_ALARM = 4,
+ AUDIO_STREAM_NOTIFICATION = 5,
+ AUDIO_STREAM_BLUETOOTH_SCO = 6,
+ AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user and must be routed to speaker */
+ AUDIO_STREAM_DTMF = 8,
+ AUDIO_STREAM_TTS = 9,
+
+ AUDIO_STREAM_CNT,
+ AUDIO_STREAM_MAX = AUDIO_STREAM_CNT - 1,
+} audio_stream_type_t;
+
+/* Do not change these values without updating their counterparts
+ * in media/java/android/media/MediaRecorder.java!
+ */
+typedef enum {
+ AUDIO_SOURCE_DEFAULT = 0,
+ AUDIO_SOURCE_MIC = 1,
+ AUDIO_SOURCE_VOICE_UPLINK = 2,
+ AUDIO_SOURCE_VOICE_DOWNLINK = 3,
+ AUDIO_SOURCE_VOICE_CALL = 4,
+ AUDIO_SOURCE_CAMCORDER = 5,
+ AUDIO_SOURCE_VOICE_RECOGNITION = 6,
+ AUDIO_SOURCE_VOICE_COMMUNICATION = 7,
+
+ AUDIO_SOURCE_CNT,
+ AUDIO_SOURCE_MAX = AUDIO_SOURCE_CNT - 1,
+} audio_source_t;
+
+/* special audio session values
+ * (XXX: should this be living in the audio effects land?)
+ */
+typedef enum {
+ /* session for effects attached to a particular output stream
+ * (value must be less than 0)
+ */
+ AUDIO_SESSION_OUTPUT_STAGE = -1,
+
+ /* session for effects applied to output mix. These effects can
+ * be moved by audio policy manager to another output stream
+ * (value must be 0)
+ */
+ AUDIO_SESSION_OUTPUT_MIX = 0,
+} audio_session_t;
+
+/* Audio sub formats (see enum audio_format). */
+
+/* PCM sub formats */
+typedef enum {
+ AUDIO_FORMAT_PCM_SUB_16_BIT = 0x1, /* DO NOT CHANGE - PCM signed 16 bits */
+ AUDIO_FORMAT_PCM_SUB_8_BIT = 0x2, /* DO NOT CHANGE - PCM unsigned 8 bits */
+ AUDIO_FORMAT_PCM_SUB_32_BIT = 0x3, /* PCM signed .31 fixed point */
+ AUDIO_FORMAT_PCM_SUB_8_24_BIT = 0x4, /* PCM signed 7.24 fixed point */
+} audio_format_pcm_sub_fmt_t;
+
+/* MP3 sub format field definition : can use 11 LSBs in the same way as MP3
+ * frame header to specify bit rate, stereo mode, version...
+ */
+typedef enum {
+ AUDIO_FORMAT_MP3_SUB_NONE = 0x0,
+} audio_format_mp3_sub_fmt_t;
+
+/* AMR NB/WB sub format field definition: specify frame block interleaving,
+ * bandwidth efficient or octet aligned, encoding mode for recording...
+ */
+typedef enum {
+ AUDIO_FORMAT_AMR_SUB_NONE = 0x0,
+} audio_format_amr_sub_fmt_t;
+
+/* AAC sub format field definition: specify profile or bitrate for recording... */
+typedef enum {
+ AUDIO_FORMAT_AAC_SUB_NONE = 0x0,
+} audio_format_aac_sub_fmt_t;
+
+/* VORBIS sub format field definition: specify quality for recording... */
+typedef enum {
+ AUDIO_FORMAT_VORBIS_SUB_NONE = 0x0,
+} audio_format_vorbis_sub_fmt_t;
+
+/* Audio format consists in a main format field (upper 8 bits) and a sub format
+ * field (lower 24 bits).
+ *
+ * The main format indicates the main codec type. The sub format field
+ * indicates options and parameters for each format. The sub format is mainly
+ * used for record to indicate for instance the requested bitrate or profile.
+ * It can also be used for certain formats to give informations not present in
+ * the encoded audio stream (e.g. octet alignement for AMR).
+ */
+typedef enum {
+ AUDIO_FORMAT_INVALID = 0xFFFFFFFFUL,
+ AUDIO_FORMAT_DEFAULT = 0,
+ AUDIO_FORMAT_PCM = 0x00000000UL, /* DO NOT CHANGE */
+ AUDIO_FORMAT_MP3 = 0x01000000UL,
+ AUDIO_FORMAT_AMR_NB = 0x02000000UL,
+ AUDIO_FORMAT_AMR_WB = 0x03000000UL,
+ AUDIO_FORMAT_AAC = 0x04000000UL,
+ AUDIO_FORMAT_HE_AAC_V1 = 0x05000000UL,
+ AUDIO_FORMAT_HE_AAC_V2 = 0x06000000UL,
+ AUDIO_FORMAT_VORBIS = 0x07000000UL,
+ AUDIO_FORMAT_MAIN_MASK = 0xFF000000UL,
+ AUDIO_FORMAT_SUB_MASK = 0x00FFFFFFUL,
+
+ /* Aliases */
+ AUDIO_FORMAT_PCM_16_BIT = (AUDIO_FORMAT_PCM |
+ AUDIO_FORMAT_PCM_SUB_16_BIT),
+ AUDIO_FORMAT_PCM_8_BIT = (AUDIO_FORMAT_PCM |
+ AUDIO_FORMAT_PCM_SUB_8_BIT),
+ AUDIO_FORMAT_PCM_32_BIT = (AUDIO_FORMAT_PCM |
+ AUDIO_FORMAT_PCM_SUB_32_BIT),
+ AUDIO_FORMAT_PCM_8_24_BIT = (AUDIO_FORMAT_PCM |
+ AUDIO_FORMAT_PCM_SUB_8_24_BIT),
+} audio_format_t;
+
+typedef enum {
+ /* output channels */
+ AUDIO_CHANNEL_OUT_FRONT_LEFT = 0x1,
+ AUDIO_CHANNEL_OUT_FRONT_RIGHT = 0x2,
+ AUDIO_CHANNEL_OUT_FRONT_CENTER = 0x4,
+ AUDIO_CHANNEL_OUT_LOW_FREQUENCY = 0x8,
+ AUDIO_CHANNEL_OUT_BACK_LEFT = 0x10,
+ AUDIO_CHANNEL_OUT_BACK_RIGHT = 0x20,
+ AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x40,
+ AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80,
+ AUDIO_CHANNEL_OUT_BACK_CENTER = 0x100,
+ AUDIO_CHANNEL_OUT_SIDE_LEFT = 0x200,
+ AUDIO_CHANNEL_OUT_SIDE_RIGHT = 0x400,
+ AUDIO_CHANNEL_OUT_TOP_CENTER = 0x800,
+ AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT = 0x1000,
+ AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER = 0x2000,
+ AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT = 0x4000,
+ AUDIO_CHANNEL_OUT_TOP_BACK_LEFT = 0x8000,
+ AUDIO_CHANNEL_OUT_TOP_BACK_CENTER = 0x10000,
+ AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT = 0x20000,
+
+ AUDIO_CHANNEL_OUT_MONO = AUDIO_CHANNEL_OUT_FRONT_LEFT,
+ AUDIO_CHANNEL_OUT_STEREO = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
+ AUDIO_CHANNEL_OUT_FRONT_RIGHT),
+ AUDIO_CHANNEL_OUT_QUAD = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
+ AUDIO_CHANNEL_OUT_FRONT_RIGHT |
+ AUDIO_CHANNEL_OUT_BACK_LEFT |
+ AUDIO_CHANNEL_OUT_BACK_RIGHT),
+ AUDIO_CHANNEL_OUT_SURROUND = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
+ AUDIO_CHANNEL_OUT_FRONT_RIGHT |
+ AUDIO_CHANNEL_OUT_FRONT_CENTER |
+ AUDIO_CHANNEL_OUT_BACK_CENTER),
+ AUDIO_CHANNEL_OUT_5POINT1 = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
+ AUDIO_CHANNEL_OUT_FRONT_RIGHT |
+ AUDIO_CHANNEL_OUT_FRONT_CENTER |
+ AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
+ AUDIO_CHANNEL_OUT_BACK_LEFT |
+ AUDIO_CHANNEL_OUT_BACK_RIGHT),
+ // matches the correct AudioFormat.CHANNEL_OUT_7POINT1_SURROUND definition for 7.1
+ AUDIO_CHANNEL_OUT_7POINT1 = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
+ AUDIO_CHANNEL_OUT_FRONT_RIGHT |
+ AUDIO_CHANNEL_OUT_FRONT_CENTER |
+ AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
+ AUDIO_CHANNEL_OUT_BACK_LEFT |
+ AUDIO_CHANNEL_OUT_BACK_RIGHT |
+ AUDIO_CHANNEL_OUT_SIDE_LEFT |
+ AUDIO_CHANNEL_OUT_SIDE_RIGHT),
+ AUDIO_CHANNEL_OUT_ALL = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
+ AUDIO_CHANNEL_OUT_FRONT_RIGHT |
+ AUDIO_CHANNEL_OUT_FRONT_CENTER |
+ AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
+ AUDIO_CHANNEL_OUT_BACK_LEFT |
+ AUDIO_CHANNEL_OUT_BACK_RIGHT |
+ AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER |
+ AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER |
+ AUDIO_CHANNEL_OUT_BACK_CENTER|
+ AUDIO_CHANNEL_OUT_SIDE_LEFT|
+ AUDIO_CHANNEL_OUT_SIDE_RIGHT|
+ AUDIO_CHANNEL_OUT_TOP_CENTER|
+ AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT|
+ AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER|
+ AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT|
+ AUDIO_CHANNEL_OUT_TOP_BACK_LEFT|
+ AUDIO_CHANNEL_OUT_TOP_BACK_CENTER|
+ AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT),
+
+ /* input channels */
+ AUDIO_CHANNEL_IN_LEFT = 0x4,
+ AUDIO_CHANNEL_IN_RIGHT = 0x8,
+ AUDIO_CHANNEL_IN_FRONT = 0x10,
+ AUDIO_CHANNEL_IN_BACK = 0x20,
+ AUDIO_CHANNEL_IN_LEFT_PROCESSED = 0x40,
+ AUDIO_CHANNEL_IN_RIGHT_PROCESSED = 0x80,
+ AUDIO_CHANNEL_IN_FRONT_PROCESSED = 0x100,
+ AUDIO_CHANNEL_IN_BACK_PROCESSED = 0x200,
+ AUDIO_CHANNEL_IN_PRESSURE = 0x400,
+ AUDIO_CHANNEL_IN_X_AXIS = 0x800,
+ AUDIO_CHANNEL_IN_Y_AXIS = 0x1000,
+ AUDIO_CHANNEL_IN_Z_AXIS = 0x2000,
+ AUDIO_CHANNEL_IN_VOICE_UPLINK = 0x4000,
+ AUDIO_CHANNEL_IN_VOICE_DNLINK = 0x8000,
+
+ AUDIO_CHANNEL_IN_MONO = AUDIO_CHANNEL_IN_FRONT,
+ AUDIO_CHANNEL_IN_STEREO = (AUDIO_CHANNEL_IN_LEFT | AUDIO_CHANNEL_IN_RIGHT),
+ AUDIO_CHANNEL_IN_ALL = (AUDIO_CHANNEL_IN_LEFT |
+ AUDIO_CHANNEL_IN_RIGHT |
+ AUDIO_CHANNEL_IN_FRONT |
+ AUDIO_CHANNEL_IN_BACK|
+ AUDIO_CHANNEL_IN_LEFT_PROCESSED |
+ AUDIO_CHANNEL_IN_RIGHT_PROCESSED |
+ AUDIO_CHANNEL_IN_FRONT_PROCESSED |
+ AUDIO_CHANNEL_IN_BACK_PROCESSED|
+ AUDIO_CHANNEL_IN_PRESSURE |
+ AUDIO_CHANNEL_IN_X_AXIS |
+ AUDIO_CHANNEL_IN_Y_AXIS |
+ AUDIO_CHANNEL_IN_Z_AXIS |
+ AUDIO_CHANNEL_IN_VOICE_UPLINK |
+ AUDIO_CHANNEL_IN_VOICE_DNLINK),
+};
+
+typedef uint32_t audio_channel_mask_t;
+
+typedef enum {
+ AUDIO_MODE_INVALID = -2,
+ AUDIO_MODE_CURRENT = -1,
+ AUDIO_MODE_NORMAL = 0,
+ AUDIO_MODE_RINGTONE = 1,
+ AUDIO_MODE_IN_CALL = 2,
+ AUDIO_MODE_IN_COMMUNICATION = 3,
+
+ AUDIO_MODE_CNT,
+ AUDIO_MODE_MAX = AUDIO_MODE_CNT - 1,
+} audio_mode_t;
+
+typedef enum {
+ AUDIO_IN_ACOUSTICS_AGC_ENABLE = 0x0001,
+ AUDIO_IN_ACOUSTICS_AGC_DISABLE = 0,
+ AUDIO_IN_ACOUSTICS_NS_ENABLE = 0x0002,
+ AUDIO_IN_ACOUSTICS_NS_DISABLE = 0,
+ AUDIO_IN_ACOUSTICS_TX_IIR_ENABLE = 0x0004,
+ AUDIO_IN_ACOUSTICS_TX_DISABLE = 0,
+} audio_in_acoustics_t;
+
+typedef enum {
+ /* output devices */
+ AUDIO_DEVICE_OUT_EARPIECE = 0x1,
+ AUDIO_DEVICE_OUT_SPEAKER = 0x2,
+ AUDIO_DEVICE_OUT_WIRED_HEADSET = 0x4,
+ AUDIO_DEVICE_OUT_WIRED_HEADPHONE = 0x8,
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO = 0x10,
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
+ AUDIO_DEVICE_OUT_AUX_DIGITAL = 0x400,
+ AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800,
+ AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000,
+ AUDIO_DEVICE_OUT_USB_ACCESSORY = 0x2000,
+ AUDIO_DEVICE_OUT_USB_DEVICE = 0x4000,
+ AUDIO_DEVICE_OUT_DEFAULT = 0x8000,
+ AUDIO_DEVICE_OUT_ALL = (AUDIO_DEVICE_OUT_EARPIECE |
+ AUDIO_DEVICE_OUT_SPEAKER |
+ AUDIO_DEVICE_OUT_WIRED_HEADSET |
+ AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
+ AUDIO_DEVICE_OUT_AUX_DIGITAL |
+ AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
+ AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
+ AUDIO_DEVICE_OUT_USB_ACCESSORY |
+ AUDIO_DEVICE_OUT_USB_DEVICE |
+ AUDIO_DEVICE_OUT_DEFAULT),
+ AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
+ AUDIO_DEVICE_OUT_ALL_SCO = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
+ AUDIO_DEVICE_OUT_ALL_USB = (AUDIO_DEVICE_OUT_USB_ACCESSORY |
+ AUDIO_DEVICE_OUT_USB_DEVICE),
+
+ /* input devices */
+ AUDIO_DEVICE_IN_COMMUNICATION = 0x10000,
+ AUDIO_DEVICE_IN_AMBIENT = 0x20000,
+ AUDIO_DEVICE_IN_BUILTIN_MIC = 0x40000,
+ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x80000,
+ AUDIO_DEVICE_IN_WIRED_HEADSET = 0x100000,
+ AUDIO_DEVICE_IN_AUX_DIGITAL = 0x200000,
+ AUDIO_DEVICE_IN_VOICE_CALL = 0x400000,
+ AUDIO_DEVICE_IN_BACK_MIC = 0x800000,
+ AUDIO_DEVICE_IN_DEFAULT = 0x80000000,
+
+ AUDIO_DEVICE_IN_ALL = (AUDIO_DEVICE_IN_COMMUNICATION |
+ AUDIO_DEVICE_IN_AMBIENT |
+ AUDIO_DEVICE_IN_BUILTIN_MIC |
+ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET |
+ AUDIO_DEVICE_IN_WIRED_HEADSET |
+ AUDIO_DEVICE_IN_AUX_DIGITAL |
+ AUDIO_DEVICE_IN_VOICE_CALL |
+ AUDIO_DEVICE_IN_BACK_MIC |
+ AUDIO_DEVICE_IN_DEFAULT),
+ AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
+} audio_devices_t;
+
+/* the audio output flags serve two purposes:
+ * - when an AudioTrack is created they indicate a "wish" to be connected to an
+ * output stream with attributes corresponding to the specified flags
+ * - when present in an output profile descriptor listed for a particular audio
+ * hardware module, they indicate that an output stream can be opened that
+ * supports the attributes indicated by the flags.
+ * the audio policy manager will try to match the flags in the request
+ * (when getOuput() is called) to an available output stream.
+ */
+typedef enum {
+ AUDIO_OUTPUT_FLAG_NONE = 0x0, // no attributes
+ AUDIO_OUTPUT_FLAG_DIRECT = 0x1, // this output directly connects a track
+ // to one output stream: no software mixer
+ AUDIO_OUTPUT_FLAG_PRIMARY = 0x2, // this output is the primary output of
+ // the device. It is unique and must be
+ // present. It is opened by default and
+ // receives routing, audio mode and volume
+ // controls related to voice calls.
+ AUDIO_OUTPUT_FLAG_FAST = 0x4, // output supports "fast tracks",
+ // defined elsewhere
+ AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8 // use deep audio buffers
+} audio_output_flags_t;
+
+static inline bool audio_is_output_device(audio_devices_t device)
+{
+ if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL) == 0))
+ return true;
+ else
+ return false;
+}
+
+static inline bool audio_is_input_device(audio_devices_t device)
+{
+ if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_IN_ALL) == 0))
+ return true;
+ else
+ return false;
+}
+
+static inline bool audio_is_a2dp_device(audio_devices_t device)
+{
+ if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_ALL_A2DP))
+ return true;
+ else
+ return false;
+}
+
+static inline bool audio_is_bluetooth_sco_device(audio_devices_t device)
+{
+ if ((popcount(device) == 1) && (device & (AUDIO_DEVICE_OUT_ALL_SCO |
+ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)))
+ return true;
+ else
+ return false;
+}
+
+static inline bool audio_is_usb_device(audio_devices_t device)
+{
+ if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_ALL_USB))
+ return true;
+ else
+ return false;
+}
+
+static inline bool audio_is_input_channel(uint32_t channel)
+{
+ if ((channel & ~AUDIO_CHANNEL_IN_ALL) == 0)
+ return true;
+ else
+ return false;
+}
+
+static inline bool audio_is_output_channel(uint32_t channel)
+{
+ if ((channel & ~AUDIO_CHANNEL_OUT_ALL) == 0)
+ return true;
+ else
+ return false;
+}
+
+/* Derive an output channel mask from a channel count.
+ * This is to be used when the content channel mask is unknown. The 1, 2, 4, 5, 6, 7 and 8 channel
+ * cases are mapped to the standard game/home-theater layouts, but note that 4 is mapped to quad,
+ * and not stereo + FC + mono surround. A channel count of 3 is arbitrarily mapped to stereo + FC
+ * for continuity with stereo.
+ * Returns the matching channel mask, or 0 if the number of channels exceeds that of the
+ * configurations for which a default channel mask is defined.
+ */
+static inline audio_channel_mask_t audio_channel_out_mask_from_count(uint32_t channel_count)
+{
+ switch(channel_count) {
+ case 1:
+ return AUDIO_CHANNEL_OUT_MONO;
+ case 2:
+ return AUDIO_CHANNEL_OUT_STEREO;
+ case 3:
+ return (AUDIO_CHANNEL_OUT_STEREO | AUDIO_CHANNEL_OUT_FRONT_CENTER);
+ case 4: // 4.0
+ return AUDIO_CHANNEL_OUT_QUAD;
+ case 5: // 5.0
+ return (AUDIO_CHANNEL_OUT_QUAD | AUDIO_CHANNEL_OUT_FRONT_CENTER);
+ case 6: // 5.1
+ return AUDIO_CHANNEL_OUT_5POINT1;
+ case 7: // 6.1
+ return (AUDIO_CHANNEL_OUT_5POINT1 | AUDIO_CHANNEL_OUT_BACK_CENTER);
+ case 8:
+ return AUDIO_CHANNEL_OUT_7POINT1;
+ default:
+ return 0;
+ }
+}
+
+/* Similar to above, but for input. Currently handles only mono and stereo. */
+static inline audio_channel_mask_t audio_channel_in_mask_from_count(uint32_t channel_count)
+{
+ switch (channel_count) {
+ case 1:
+ return AUDIO_CHANNEL_IN_MONO;
+ case 2:
+ return AUDIO_CHANNEL_IN_STEREO;
+ default:
+ return 0;
+ }
+}
+
+static inline bool audio_is_valid_format(audio_format_t format)
+{
+ switch (format & AUDIO_FORMAT_MAIN_MASK) {
+ case AUDIO_FORMAT_PCM:
+ if (format != AUDIO_FORMAT_PCM_16_BIT &&
+ format != AUDIO_FORMAT_PCM_8_BIT) {
+ return false;
+ }
+ case AUDIO_FORMAT_MP3:
+ case AUDIO_FORMAT_AMR_NB:
+ case AUDIO_FORMAT_AMR_WB:
+ case AUDIO_FORMAT_AAC:
+ case AUDIO_FORMAT_HE_AAC_V1:
+ case AUDIO_FORMAT_HE_AAC_V2:
+ case AUDIO_FORMAT_VORBIS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline bool audio_is_linear_pcm(audio_format_t format)
+{
+ return ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM);
+}
+
+static inline size_t audio_bytes_per_sample(audio_format_t format)
+{
+ size_t size = 0;
+
+ switch (format) {
+ case AUDIO_FORMAT_PCM_32_BIT:
+ case AUDIO_FORMAT_PCM_8_24_BIT:
+ size = sizeof(int32_t);
+ break;
+ case AUDIO_FORMAT_PCM_16_BIT:
+ size = sizeof(int16_t);
+ break;
+ case AUDIO_FORMAT_PCM_8_BIT:
+ size = sizeof(uint8_t);
+ break;
+ default:
+ break;
+ }
+ return size;
+}
+
+__END_DECLS
+
+#endif // ANDROID_AUDIO_CORE_H
diff --git a/include/system/audio_policy.h b/include/system/audio_policy.h
new file mode 100644
index 0000000..91b8e9c
--- /dev/null
+++ b/include/system/audio_policy.h
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+
+#ifndef ANDROID_AUDIO_POLICY_CORE_H
+#define ANDROID_AUDIO_POLICY_CORE_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <cutils/bitops.h>
+
+__BEGIN_DECLS
+
+/* The enums were moved here mostly from
+ * frameworks/base/include/media/AudioSystem.h
+ */
+
+/* device categories used for audio_policy->set_force_use() */
+typedef enum {
+ AUDIO_POLICY_FORCE_NONE,
+ AUDIO_POLICY_FORCE_SPEAKER,
+ AUDIO_POLICY_FORCE_HEADPHONES,
+ AUDIO_POLICY_FORCE_BT_SCO,
+ AUDIO_POLICY_FORCE_BT_A2DP,
+ AUDIO_POLICY_FORCE_WIRED_ACCESSORY,
+ AUDIO_POLICY_FORCE_BT_CAR_DOCK,
+ AUDIO_POLICY_FORCE_BT_DESK_DOCK,
+ AUDIO_POLICY_FORCE_ANALOG_DOCK,
+ AUDIO_POLICY_FORCE_DIGITAL_DOCK,
+ AUDIO_POLICY_FORCE_NO_BT_A2DP, /* A2DP sink is not preferred to speaker or wired HS */
+
+ AUDIO_POLICY_FORCE_CFG_CNT,
+ AUDIO_POLICY_FORCE_CFG_MAX = AUDIO_POLICY_FORCE_CFG_CNT - 1,
+
+ AUDIO_POLICY_FORCE_DEFAULT = AUDIO_POLICY_FORCE_NONE,
+} audio_policy_forced_cfg_t;
+
+/* usages used for audio_policy->set_force_use() */
+typedef enum {
+ AUDIO_POLICY_FORCE_FOR_COMMUNICATION,
+ AUDIO_POLICY_FORCE_FOR_MEDIA,
+ AUDIO_POLICY_FORCE_FOR_RECORD,
+ AUDIO_POLICY_FORCE_FOR_DOCK,
+
+ AUDIO_POLICY_FORCE_USE_CNT,
+ AUDIO_POLICY_FORCE_USE_MAX = AUDIO_POLICY_FORCE_USE_CNT - 1,
+} audio_policy_force_use_t;
+
+/* device connection states used for audio_policy->set_device_connection_state()
+ */
+typedef enum {
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+
+ AUDIO_POLICY_DEVICE_STATE_CNT,
+ AUDIO_POLICY_DEVICE_STATE_MAX = AUDIO_POLICY_DEVICE_STATE_CNT - 1,
+} audio_policy_dev_state_t;
+
+typedef enum {
+ /* Used to generate a tone to notify the user of a
+ * notification/alarm/ringtone while they are in a call. */
+ AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION = 0,
+
+ AUDIO_POLICY_TONE_CNT,
+ AUDIO_POLICY_TONE_MAX = AUDIO_POLICY_TONE_CNT - 1,
+} audio_policy_tone_t;
+
+
+static inline bool audio_is_low_visibility(audio_stream_type_t stream)
+{
+ switch (stream) {
+ case AUDIO_STREAM_SYSTEM:
+ case AUDIO_STREAM_NOTIFICATION:
+ case AUDIO_STREAM_RING:
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+__END_DECLS
+
+#endif // ANDROID_AUDIO_POLICY_CORE_H
diff --git a/include/system/camera.h b/include/system/camera.h
new file mode 100644
index 0000000..e4cacc5
--- /dev/null
+++ b/include/system/camera.h
@@ -0,0 +1,266 @@
+/*
+ * 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.
+ */
+
+#ifndef SYSTEM_CORE_INCLUDE_ANDROID_CAMERA_H
+#define SYSTEM_CORE_INCLUDE_ANDROID_CAMERA_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <cutils/native_handle.h>
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+__BEGIN_DECLS
+
+/**
+ * A set of bit masks for specifying how the received preview frames are
+ * handled before the previewCallback() call.
+ *
+ * The least significant 3 bits of an "int" value are used for this purpose:
+ *
+ * ..... 0 0 0
+ * ^ ^ ^
+ * | | |---------> determine whether the callback is enabled or not
+ * | |-----------> determine whether the callback is one-shot or not
+ * |-------------> determine whether the frame is copied out or not
+ *
+ * WARNING: When a frame is sent directly without copying, it is the frame
+ * receiver's responsiblity to make sure that the frame data won't get
+ * corrupted by subsequent preview frames filled by the camera. This flag is
+ * recommended only when copying out data brings significant performance price
+ * and the handling/processing of the received frame data is always faster than
+ * the preview frame rate so that data corruption won't occur.
+ *
+ * For instance,
+ * 1. 0x00 disables the callback. In this case, copy out and one shot bits
+ * are ignored.
+ * 2. 0x01 enables a callback without copying out the received frames. A
+ * typical use case is the Camcorder application to avoid making costly
+ * frame copies.
+ * 3. 0x05 is enabling a callback with frame copied out repeatedly. A typical
+ * use case is the Camera application.
+ * 4. 0x07 is enabling a callback with frame copied out only once. A typical
+ * use case is the Barcode scanner application.
+ */
+
+enum {
+ CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK = 0x01,
+ CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK = 0x02,
+ CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK = 0x04,
+ /** Typical use cases */
+ CAMERA_FRAME_CALLBACK_FLAG_NOOP = 0x00,
+ CAMERA_FRAME_CALLBACK_FLAG_CAMCORDER = 0x01,
+ CAMERA_FRAME_CALLBACK_FLAG_CAMERA = 0x05,
+ CAMERA_FRAME_CALLBACK_FLAG_BARCODE_SCANNER = 0x07
+};
+
+/** msgType in notifyCallback and dataCallback functions */
+enum {
+ CAMERA_MSG_ERROR = 0x0001, // notifyCallback
+ CAMERA_MSG_SHUTTER = 0x0002, // notifyCallback
+ CAMERA_MSG_FOCUS = 0x0004, // notifyCallback
+ CAMERA_MSG_ZOOM = 0x0008, // notifyCallback
+ CAMERA_MSG_PREVIEW_FRAME = 0x0010, // dataCallback
+ CAMERA_MSG_VIDEO_FRAME = 0x0020, // data_timestamp_callback
+ CAMERA_MSG_POSTVIEW_FRAME = 0x0040, // dataCallback
+ CAMERA_MSG_RAW_IMAGE = 0x0080, // dataCallback
+ CAMERA_MSG_COMPRESSED_IMAGE = 0x0100, // dataCallback
+ CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x0200, // dataCallback
+ // Preview frame metadata. This can be combined with
+ // CAMERA_MSG_PREVIEW_FRAME in dataCallback. For example, the apps can
+ // request FRAME and METADATA. Or the apps can request only FRAME or only
+ // METADATA.
+ CAMERA_MSG_PREVIEW_METADATA = 0x0400, // dataCallback
+ // Notify on autofocus start and stop. This is useful in continuous
+ // autofocus - FOCUS_MODE_CONTINUOUS_VIDEO and FOCUS_MODE_CONTINUOUS_PICTURE.
+ CAMERA_MSG_FOCUS_MOVE = 0x0800, // notifyCallback
+ CAMERA_MSG_ALL_MSGS = 0xFFFF
+};
+
+/** cmdType in sendCommand functions */
+enum {
+ CAMERA_CMD_START_SMOOTH_ZOOM = 1,
+ CAMERA_CMD_STOP_SMOOTH_ZOOM = 2,
+
+ /**
+ * Set the clockwise rotation of preview display (setPreviewDisplay) in
+ * degrees. This affects the preview frames and the picture displayed after
+ * snapshot. This method is useful for portrait mode applications. Note
+ * that preview display of front-facing cameras is flipped horizontally
+ * before the rotation, that is, the image is reflected along the central
+ * vertical axis of the camera sensor. So the users can see themselves as
+ * looking into a mirror.
+ *
+ * This does not affect the order of byte array of
+ * CAMERA_MSG_PREVIEW_FRAME, CAMERA_MSG_VIDEO_FRAME,
+ * CAMERA_MSG_POSTVIEW_FRAME, CAMERA_MSG_RAW_IMAGE, or
+ * CAMERA_MSG_COMPRESSED_IMAGE. This is allowed to be set during preview
+ * since API level 14.
+ */
+ CAMERA_CMD_SET_DISPLAY_ORIENTATION = 3,
+
+ /**
+ * cmdType to disable/enable shutter sound. In sendCommand passing arg1 =
+ * 0 will disable, while passing arg1 = 1 will enable the shutter sound.
+ */
+ CAMERA_CMD_ENABLE_SHUTTER_SOUND = 4,
+
+ /* cmdType to play recording sound */
+ CAMERA_CMD_PLAY_RECORDING_SOUND = 5,
+
+ /**
+ * Start the face detection. This should be called after preview is started.
+ * The camera will notify the listener of CAMERA_MSG_FACE and the detected
+ * faces in the preview frame. The detected faces may be the same as the
+ * previous ones. Apps should call CAMERA_CMD_STOP_FACE_DETECTION to stop
+ * the face detection. This method is supported if CameraParameters
+ * KEY_MAX_NUM_HW_DETECTED_FACES or KEY_MAX_NUM_SW_DETECTED_FACES is
+ * bigger than 0. Hardware and software face detection should not be running
+ * at the same time. If the face detection has started, apps should not send
+ * this again.
+ *
+ * In hardware face detection mode, CameraParameters KEY_WHITE_BALANCE,
+ * KEY_FOCUS_AREAS and KEY_METERING_AREAS have no effect.
+ *
+ * arg1 is the face detection type. It can be CAMERA_FACE_DETECTION_HW or
+ * CAMERA_FACE_DETECTION_SW. If the type of face detection requested is not
+ * supported, the HAL must return BAD_VALUE.
+ */
+ CAMERA_CMD_START_FACE_DETECTION = 6,
+
+ /**
+ * Stop the face detection.
+ */
+ CAMERA_CMD_STOP_FACE_DETECTION = 7,
+
+ /**
+ * Enable/disable focus move callback (CAMERA_MSG_FOCUS_MOVE). Passing
+ * arg1 = 0 will disable, while passing arg1 = 1 will enable the callback.
+ */
+ CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG = 8,
+
+ /**
+ * Ping camera service to see if camera hardware is released.
+ *
+ * When any camera method returns error, the client can use ping command
+ * to see if the camera has been taken away by other clients. If the result
+ * is NO_ERROR, it means the camera hardware is not released. If the result
+ * is not NO_ERROR, the camera has been released and the existing client
+ * can silently finish itself or show a dialog.
+ */
+ CAMERA_CMD_PING = 9,
+};
+
+/** camera fatal errors */
+enum {
+ CAMERA_ERROR_UNKNOWN = 1,
+ /**
+ * Camera was released because another client has connected to the camera.
+ * The original client should call Camera::disconnect immediately after
+ * getting this notification. Otherwise, the camera will be released by
+ * camera service in a short time. The client should not call any method
+ * (except disconnect and sending CAMERA_CMD_PING) after getting this.
+ */
+ CAMERA_ERROR_RELEASED = 2,
+ CAMERA_ERROR_SERVER_DIED = 100
+};
+
+enum {
+ /** The facing of the camera is opposite to that of the screen. */
+ CAMERA_FACING_BACK = 0,
+ /** The facing of the camera is the same as that of the screen. */
+ CAMERA_FACING_FRONT = 1
+};
+
+enum {
+ /** Hardware face detection. It does not use much CPU. */
+ CAMERA_FACE_DETECTION_HW = 0,
+ /**
+ * Software face detection. It uses some CPU. Applications must use
+ * Camera.setPreviewTexture for preview in this mode.
+ */
+ CAMERA_FACE_DETECTION_SW = 1
+};
+
+/**
+ * The information of a face from camera face detection.
+ */
+typedef struct camera_face {
+ /**
+ * Bounds of the face [left, top, right, bottom]. (-1000, -1000) represents
+ * the top-left of the camera field of view, and (1000, 1000) represents the
+ * bottom-right of the field of view. The width and height cannot be 0 or
+ * negative. This is supported by both hardware and software face detection.
+ *
+ * The direction is relative to the sensor orientation, that is, what the
+ * sensor sees. The direction is not affected by the rotation or mirroring
+ * of CAMERA_CMD_SET_DISPLAY_ORIENTATION.
+ */
+ int32_t rect[4];
+
+ /**
+ * The confidence level of the face. The range is 1 to 100. 100 is the
+ * highest confidence. This is supported by both hardware and software
+ * face detection.
+ */
+ int32_t score;
+
+ /**
+ * An unique id per face while the face is visible to the tracker. If
+ * the face leaves the field-of-view and comes back, it will get a new
+ * id. If the value is 0, id is not supported.
+ */
+ int32_t id;
+
+ /**
+ * The coordinates of the center of the left eye. The range is -1000 to
+ * 1000. -2000, -2000 if this is not supported.
+ */
+ int32_t left_eye[2];
+
+ /**
+ * The coordinates of the center of the right eye. The range is -1000 to
+ * 1000. -2000, -2000 if this is not supported.
+ */
+ int32_t right_eye[2];
+
+ /**
+ * The coordinates of the center of the mouth. The range is -1000 to 1000.
+ * -2000, -2000 if this is not supported.
+ */
+ int32_t mouth[2];
+
+} camera_face_t;
+
+/**
+ * The metadata of the frame data.
+ */
+typedef struct camera_frame_metadata {
+ /**
+ * The number of detected faces in the frame.
+ */
+ int32_t number_of_faces;
+
+ /**
+ * An array of the detected faces. The length is number_of_faces.
+ */
+ camera_face_t *faces;
+} camera_frame_metadata_t;
+
+__END_DECLS
+
+#endif /* SYSTEM_CORE_INCLUDE_ANDROID_CAMERA_H */
diff --git a/include/system/graphics.h b/include/system/graphics.h
new file mode 100644
index 0000000..24e2bfb
--- /dev/null
+++ b/include/system/graphics.h
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+#ifndef SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H
+#define SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * If the HAL needs to create service threads to handle graphics related
+ * tasks, these threads need to run at HAL_PRIORITY_URGENT_DISPLAY priority
+ * if they can block the main rendering thread in any way.
+ *
+ * the priority of the current thread can be set with:
+ *
+ * #include <sys/resource.h>
+ * setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+ *
+ */
+
+#define HAL_PRIORITY_URGENT_DISPLAY (-8)
+
+/**
+ * pixel format definitions
+ */
+
+enum {
+ HAL_PIXEL_FORMAT_RGBA_8888 = 1,
+ HAL_PIXEL_FORMAT_RGBX_8888 = 2,
+ HAL_PIXEL_FORMAT_RGB_888 = 3,
+ HAL_PIXEL_FORMAT_RGB_565 = 4,
+ HAL_PIXEL_FORMAT_BGRA_8888 = 5,
+ HAL_PIXEL_FORMAT_RGBA_5551 = 6,
+ HAL_PIXEL_FORMAT_RGBA_4444 = 7,
+
+ /* 0x8 - 0xFF range unavailable */
+
+ /*
+ * 0x100 - 0x1FF
+ *
+ * This range is reserved for pixel formats that are specific to the HAL
+ * implementation. Implementations can use any value in this range to
+ * communicate video pixel formats between their HAL modules. These formats
+ * must not have an alpha channel. Additionally, an EGLimage created from a
+ * gralloc buffer of one of these formats must be supported for use with the
+ * GL_OES_EGL_image_external OpenGL ES extension.
+ */
+
+ /*
+ * Android YUV format:
+ *
+ * This format is exposed outside of the HAL to software decoders and
+ * applications. EGLImageKHR must support it in conjunction with the
+ * OES_EGL_image_external extension.
+ *
+ * YV12 is a 4:2:0 YCrCb planar format comprised of a WxH Y plane followed
+ * by (W/2) x (H/2) Cr and Cb planes.
+ *
+ * This format assumes
+ * - an even width
+ * - an even height
+ * - a horizontal stride multiple of 16 pixels
+ * - a vertical stride equal to the height
+ *
+ * y_size = stride * height
+ * c_stride = ALIGN(stride/2, 16)
+ * c_size = c_stride * height/2
+ * size = y_size + c_size * 2
+ * cr_offset = y_size
+ * cb_offset = y_size + c_size
+ *
+ */
+ HAL_PIXEL_FORMAT_YV12 = 0x32315659, // YCrCb 4:2:0 Planar
+
+ /*
+ * Android RAW sensor format:
+ *
+ * This format is exposed outside of the HAL to applications.
+ *
+ * RAW_SENSOR is a single-channel 16-bit format, typically representing raw
+ * Bayer-pattern images from an image sensor, with minimal processing.
+ *
+ * The exact pixel layout of the data in the buffer is sensor-dependent, and
+ * needs to be queried from the camera device.
+ *
+ * Generally, not all 16 bits are used; more common values are 10 or 12
+ * bits. All parameters to interpret the raw data (black and white points,
+ * color space, etc) must be queried from the camera device.
+ *
+ * This format assumes
+ * - an even width
+ * - an even height
+ * - a horizontal stride multiple of 16 pixels (32 bytes).
+ */
+ HAL_PIXEL_FORMAT_RAW_SENSOR = 0x20,
+
+ /* Legacy formats (deprecated), used by ImageFormat.java */
+ HAL_PIXEL_FORMAT_YCbCr_422_SP = 0x10, // NV16
+ HAL_PIXEL_FORMAT_YCrCb_420_SP = 0x11, // NV21
+ HAL_PIXEL_FORMAT_YCbCr_422_I = 0x14, // YUY2
+};
+
+
+/**
+ * Transformation definitions
+ *
+ * IMPORTANT NOTE:
+ * HAL_TRANSFORM_ROT_90 is applied CLOCKWISE and AFTER HAL_TRANSFORM_FLIP_{H|V}.
+ *
+ */
+
+enum {
+ /* flip source image horizontally (around the vertical axis) */
+ HAL_TRANSFORM_FLIP_H = 0x01,
+ /* flip source image vertically (around the horizontal axis)*/
+ HAL_TRANSFORM_FLIP_V = 0x02,
+ /* rotate source image 90 degrees clockwise */
+ HAL_TRANSFORM_ROT_90 = 0x04,
+ /* rotate source image 180 degrees */
+ HAL_TRANSFORM_ROT_180 = 0x03,
+ /* rotate source image 270 degrees clockwise */
+ HAL_TRANSFORM_ROT_270 = 0x07,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H */
diff --git a/include/system/window.h b/include/system/window.h
new file mode 100644
index 0000000..8e00bcd
--- /dev/null
+++ b/include/system/window.h
@@ -0,0 +1,723 @@
+/*
+ * 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.
+ */
+
+#ifndef SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H
+#define SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H
+
+#include <stdint.h>
+#include <string.h>
+#include <sys/cdefs.h>
+#include <system/graphics.h>
+#include <cutils/native_handle.h>
+
+__BEGIN_DECLS
+
+/*****************************************************************************/
+
+#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \
+ (((unsigned)(a)<<24)|((unsigned)(b)<<16)|((unsigned)(c)<<8)|(unsigned)(d))
+
+#define ANDROID_NATIVE_WINDOW_MAGIC \
+ ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d')
+
+#define ANDROID_NATIVE_BUFFER_MAGIC \
+ ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r')
+
+// ---------------------------------------------------------------------------
+
+typedef const native_handle_t* buffer_handle_t;
+
+// ---------------------------------------------------------------------------
+
+typedef struct android_native_rect_t
+{
+ int32_t left;
+ int32_t top;
+ int32_t right;
+ int32_t bottom;
+} android_native_rect_t;
+
+// ---------------------------------------------------------------------------
+
+typedef struct android_native_base_t
+{
+ /* a magic value defined by the actual EGL native type */
+ int magic;
+
+ /* the sizeof() of the actual EGL native type */
+ int version;
+
+ void* reserved[4];
+
+ /* reference-counting interface */
+ void (*incRef)(struct android_native_base_t* base);
+ void (*decRef)(struct android_native_base_t* base);
+} android_native_base_t;
+
+typedef struct ANativeWindowBuffer
+{
+#ifdef __cplusplus
+ ANativeWindowBuffer() {
+ common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
+ common.version = sizeof(ANativeWindowBuffer);
+ memset(common.reserved, 0, sizeof(common.reserved));
+ }
+
+ // Implement the methods that sp<ANativeWindowBuffer> expects so that it
+ // can be used to automatically refcount ANativeWindowBuffer's.
+ void incStrong(const void* id) const {
+ common.incRef(const_cast<android_native_base_t*>(&common));
+ }
+ void decStrong(const void* id) const {
+ common.decRef(const_cast<android_native_base_t*>(&common));
+ }
+#endif
+
+ struct android_native_base_t common;
+
+ int width;
+ int height;
+ int stride;
+ int format;
+ int usage;
+
+ void* reserved[2];
+
+ buffer_handle_t handle;
+
+ void* reserved_proc[8];
+} ANativeWindowBuffer_t;
+
+// Old typedef for backwards compatibility.
+typedef ANativeWindowBuffer_t android_native_buffer_t;
+
+// ---------------------------------------------------------------------------
+
+/* attributes queriable with query() */
+enum {
+ NATIVE_WINDOW_WIDTH = 0,
+ NATIVE_WINDOW_HEIGHT = 1,
+ NATIVE_WINDOW_FORMAT = 2,
+
+ /* The minimum number of buffers that must remain un-dequeued after a buffer
+ * has been queued. This value applies only if set_buffer_count was used to
+ * override the number of buffers and if a buffer has since been queued.
+ * Users of the set_buffer_count ANativeWindow method should query this
+ * value before calling set_buffer_count. If it is necessary to have N
+ * buffers simultaneously dequeued as part of the steady-state operation,
+ * and this query returns M then N+M buffers should be requested via
+ * native_window_set_buffer_count.
+ *
+ * Note that this value does NOT apply until a single buffer has been
+ * queued. In particular this means that it is possible to:
+ *
+ * 1. Query M = min undequeued buffers
+ * 2. Set the buffer count to N + M
+ * 3. Dequeue all N + M buffers
+ * 4. Cancel M buffers
+ * 5. Queue, dequeue, queue, dequeue, ad infinitum
+ */
+ NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS = 3,
+
+ /* Check whether queueBuffer operations on the ANativeWindow send the buffer
+ * to the window compositor. The query sets the returned 'value' argument
+ * to 1 if the ANativeWindow DOES send queued buffers directly to the window
+ * compositor and 0 if the buffers do not go directly to the window
+ * compositor.
+ *
+ * This can be used to determine whether protected buffer content should be
+ * sent to the ANativeWindow. Note, however, that a result of 1 does NOT
+ * indicate that queued buffers will be protected from applications or users
+ * capturing their contents. If that behavior is desired then some other
+ * mechanism (e.g. the GRALLOC_USAGE_PROTECTED flag) should be used in
+ * conjunction with this query.
+ */
+ NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER = 4,
+
+ /* Get the concrete type of a ANativeWindow. See below for the list of
+ * possible return values.
+ *
+ * This query should not be used outside the Android framework and will
+ * likely be removed in the near future.
+ */
+ NATIVE_WINDOW_CONCRETE_TYPE = 5,
+
+
+ /*
+ * Default width and height of ANativeWindow buffers, these are the
+ * dimensions of the window buffers irrespective of the
+ * NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS call and match the native window
+ * size unless overridden by NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS.
+ */
+ NATIVE_WINDOW_DEFAULT_WIDTH = 6,
+ NATIVE_WINDOW_DEFAULT_HEIGHT = 7,
+
+ /*
+ * transformation that will most-likely be applied to buffers. This is only
+ * a hint, the actual transformation applied might be different.
+ *
+ * INTENDED USE:
+ *
+ * The transform hint can be used by a producer, for instance the GLES
+ * driver, to pre-rotate the rendering such that the final transformation
+ * in the composer is identity. This can be very useful when used in
+ * conjunction with the h/w composer HAL, in situations where it
+ * cannot handle arbitrary rotations.
+ *
+ * 1. Before dequeuing a buffer, the GL driver (or any other ANW client)
+ * queries the ANW for NATIVE_WINDOW_TRANSFORM_HINT.
+ *
+ * 2. The GL driver overrides the width and height of the ANW to
+ * account for NATIVE_WINDOW_TRANSFORM_HINT. This is done by querying
+ * NATIVE_WINDOW_DEFAULT_{WIDTH | HEIGHT}, swapping the dimensions
+ * according to NATIVE_WINDOW_TRANSFORM_HINT and calling
+ * native_window_set_buffers_dimensions().
+ *
+ * 3. The GL driver dequeues a buffer of the new pre-rotated size.
+ *
+ * 4. The GL driver renders to the buffer such that the image is
+ * already transformed, that is applying NATIVE_WINDOW_TRANSFORM_HINT
+ * to the rendering.
+ *
+ * 5. The GL driver calls native_window_set_transform to apply
+ * inverse transformation to the buffer it just rendered.
+ * In order to do this, the GL driver needs
+ * to calculate the inverse of NATIVE_WINDOW_TRANSFORM_HINT, this is
+ * done easily:
+ *
+ * int hintTransform, inverseTransform;
+ * query(..., NATIVE_WINDOW_TRANSFORM_HINT, &hintTransform);
+ * inverseTransform = hintTransform;
+ * if (hintTransform & HAL_TRANSFORM_ROT_90)
+ * inverseTransform ^= HAL_TRANSFORM_ROT_180;
+ *
+ *
+ * 6. The GL driver queues the pre-transformed buffer.
+ *
+ * 7. The composer combines the buffer transform with the display
+ * transform. If the buffer transform happens to cancel out the
+ * display transform then no rotation is needed.
+ *
+ */
+ NATIVE_WINDOW_TRANSFORM_HINT = 8,
+
+ /*
+ * Boolean that indicates whether the consumer is running more than
+ * one buffer behind the producer.
+ */
+ NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND = 9
+};
+
+/* Valid operations for the (*perform)() hook.
+ *
+ * Values marked as 'deprecated' are supported, but have been superceded by
+ * other functionality.
+ *
+ * Values marked as 'private' should be considered private to the framework.
+ * HAL implementation code with access to an ANativeWindow should not use these,
+ * as it may not interact properly with the framework's use of the
+ * ANativeWindow.
+ */
+enum {
+ NATIVE_WINDOW_SET_USAGE = 0,
+ NATIVE_WINDOW_CONNECT = 1, /* deprecated */
+ NATIVE_WINDOW_DISCONNECT = 2, /* deprecated */
+ NATIVE_WINDOW_SET_CROP = 3, /* private */
+ NATIVE_WINDOW_SET_BUFFER_COUNT = 4,
+ NATIVE_WINDOW_SET_BUFFERS_GEOMETRY = 5, /* deprecated */
+ NATIVE_WINDOW_SET_BUFFERS_TRANSFORM = 6,
+ NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP = 7,
+ NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS = 8,
+ NATIVE_WINDOW_SET_BUFFERS_FORMAT = 9,
+ NATIVE_WINDOW_SET_SCALING_MODE = 10, /* private */
+ NATIVE_WINDOW_LOCK = 11, /* private */
+ NATIVE_WINDOW_UNLOCK_AND_POST = 12, /* private */
+ NATIVE_WINDOW_API_CONNECT = 13, /* private */
+ NATIVE_WINDOW_API_DISCONNECT = 14, /* private */
+ NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS = 15, /* private */
+ NATIVE_WINDOW_SET_POST_TRANSFORM_CROP = 16, /* private */
+};
+
+/* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */
+enum {
+ /* Buffers will be queued by EGL via eglSwapBuffers after being filled using
+ * OpenGL ES.
+ */
+ NATIVE_WINDOW_API_EGL = 1,
+
+ /* Buffers will be queued after being filled using the CPU
+ */
+ NATIVE_WINDOW_API_CPU = 2,
+
+ /* Buffers will be queued by Stagefright after being filled by a video
+ * decoder. The video decoder can either be a software or hardware decoder.
+ */
+ NATIVE_WINDOW_API_MEDIA = 3,
+
+ /* Buffers will be queued by the the camera HAL.
+ */
+ NATIVE_WINDOW_API_CAMERA = 4,
+};
+
+/* parameter for NATIVE_WINDOW_SET_BUFFERS_TRANSFORM */
+enum {
+ /* flip source image horizontally */
+ NATIVE_WINDOW_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H ,
+ /* flip source image vertically */
+ NATIVE_WINDOW_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V,
+ /* rotate source image 90 degrees clock-wise */
+ NATIVE_WINDOW_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
+ /* rotate source image 180 degrees */
+ NATIVE_WINDOW_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
+ /* rotate source image 270 degrees clock-wise */
+ NATIVE_WINDOW_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
+};
+
+/* parameter for NATIVE_WINDOW_SET_SCALING_MODE */
+enum {
+ /* the window content is not updated (frozen) until a buffer of
+ * the window size is received (enqueued)
+ */
+ NATIVE_WINDOW_SCALING_MODE_FREEZE = 0,
+ /* the buffer is scaled in both dimensions to match the window size */
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW = 1,
+ /* the buffer is scaled uniformly such that the smaller dimension
+ * of the buffer matches the window size (cropping in the process)
+ */
+ NATIVE_WINDOW_SCALING_MODE_SCALE_CROP = 2,
+ /* the window is clipped to the size of the buffer's crop rectangle; pixels
+ * outside the crop rectangle are treated as if they are completely
+ * transparent.
+ */
+ NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP = 3,
+};
+
+/* values returned by the NATIVE_WINDOW_CONCRETE_TYPE query */
+enum {
+ NATIVE_WINDOW_FRAMEBUFFER = 0, /* FramebufferNativeWindow */
+ NATIVE_WINDOW_SURFACE = 1, /* Surface */
+ NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT = 2, /* SurfaceTextureClient */
+};
+
+/* parameter for NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
+ *
+ * Special timestamp value to indicate that timestamps should be auto-generated
+ * by the native window when queueBuffer is called. This is equal to INT64_MIN,
+ * defined directly to avoid problems with C99/C++ inclusion of stdint.h.
+ */
+static const int64_t NATIVE_WINDOW_TIMESTAMP_AUTO = (-9223372036854775807LL-1);
+
+struct ANativeWindow
+{
+#ifdef __cplusplus
+ ANativeWindow()
+ : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
+ {
+ common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
+ common.version = sizeof(ANativeWindow);
+ memset(common.reserved, 0, sizeof(common.reserved));
+ }
+
+ /* Implement the methods that sp<ANativeWindow> expects so that it
+ can be used to automatically refcount ANativeWindow's. */
+ void incStrong(const void* id) const {
+ common.incRef(const_cast<android_native_base_t*>(&common));
+ }
+ void decStrong(const void* id) const {
+ common.decRef(const_cast<android_native_base_t*>(&common));
+ }
+#endif
+
+ struct android_native_base_t common;
+
+ /* flags describing some attributes of this surface or its updater */
+ const uint32_t flags;
+
+ /* min swap interval supported by this updated */
+ const int minSwapInterval;
+
+ /* max swap interval supported by this updated */
+ const int maxSwapInterval;
+
+ /* horizontal and vertical resolution in DPI */
+ const float xdpi;
+ const float ydpi;
+
+ /* Some storage reserved for the OEM's driver. */
+ intptr_t oem[4];
+
+ /*
+ * Set the swap interval for this surface.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+ int (*setSwapInterval)(struct ANativeWindow* window,
+ int interval);
+
+ /*
+ * Hook called by EGL to acquire a buffer. After this call, the buffer
+ * is not locked, so its content cannot be modified. This call may block if
+ * no buffers are available.
+ *
+ * The window holds a reference to the buffer between dequeueBuffer and
+ * either queueBuffer or cancelBuffer, so clients only need their own
+ * reference if they might use the buffer after queueing or canceling it.
+ * Holding a reference to a buffer after queueing or canceling it is only
+ * allowed if a specific buffer count has been set.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+ int (*dequeueBuffer)(struct ANativeWindow* window,
+ struct ANativeWindowBuffer** buffer);
+
+ /*
+ * hook called by EGL to lock a buffer. This MUST be called before modifying
+ * the content of a buffer. The buffer must have been acquired with
+ * dequeueBuffer first.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+ int (*lockBuffer)(struct ANativeWindow* window,
+ struct ANativeWindowBuffer* buffer);
+ /*
+ * Hook called by EGL when modifications to the render buffer are done.
+ * This unlocks and post the buffer.
+ *
+ * The window holds a reference to the buffer between dequeueBuffer and
+ * either queueBuffer or cancelBuffer, so clients only need their own
+ * reference if they might use the buffer after queueing or canceling it.
+ * Holding a reference to a buffer after queueing or canceling it is only
+ * allowed if a specific buffer count has been set.
+ *
+ * Buffers MUST be queued in the same order than they were dequeued.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+ int (*queueBuffer)(struct ANativeWindow* window,
+ struct ANativeWindowBuffer* buffer);
+
+ /*
+ * hook used to retrieve information about the native window.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+ int (*query)(const struct ANativeWindow* window,
+ int what, int* value);
+
+ /*
+ * hook used to perform various operations on the surface.
+ * (*perform)() is a generic mechanism to add functionality to
+ * ANativeWindow while keeping backward binary compatibility.
+ *
+ * DO NOT CALL THIS HOOK DIRECTLY. Instead, use the helper functions
+ * defined below.
+ *
+ * (*perform)() returns -ENOENT if the 'what' parameter is not supported
+ * by the surface's implementation.
+ *
+ * The valid operations are:
+ * NATIVE_WINDOW_SET_USAGE
+ * NATIVE_WINDOW_CONNECT (deprecated)
+ * NATIVE_WINDOW_DISCONNECT (deprecated)
+ * NATIVE_WINDOW_SET_CROP (private)
+ * NATIVE_WINDOW_SET_BUFFER_COUNT
+ * NATIVE_WINDOW_SET_BUFFERS_GEOMETRY (deprecated)
+ * NATIVE_WINDOW_SET_BUFFERS_TRANSFORM
+ * NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
+ * NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS
+ * NATIVE_WINDOW_SET_BUFFERS_FORMAT
+ * NATIVE_WINDOW_SET_SCALING_MODE (private)
+ * NATIVE_WINDOW_LOCK (private)
+ * NATIVE_WINDOW_UNLOCK_AND_POST (private)
+ * NATIVE_WINDOW_API_CONNECT (private)
+ * NATIVE_WINDOW_API_DISCONNECT (private)
+ * NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS (private)
+ * NATIVE_WINDOW_SET_POST_TRANSFORM_CROP (private)
+ *
+ */
+
+ int (*perform)(struct ANativeWindow* window,
+ int operation, ... );
+
+ /*
+ * Hook used to cancel a buffer that has been dequeued.
+ * No synchronization is performed between dequeue() and cancel(), so
+ * either external synchronization is needed, or these functions must be
+ * called from the same thread.
+ *
+ * The window holds a reference to the buffer between dequeueBuffer and
+ * either queueBuffer or cancelBuffer, so clients only need their own
+ * reference if they might use the buffer after queueing or canceling it.
+ * Holding a reference to a buffer after queueing or canceling it is only
+ * allowed if a specific buffer count has been set.
+ */
+ int (*cancelBuffer)(struct ANativeWindow* window,
+ struct ANativeWindowBuffer* buffer);
+
+
+ void* reserved_proc[2];
+};
+
+ /* Backwards compatibility: use ANativeWindow (struct ANativeWindow in C).
+ * android_native_window_t is deprecated.
+ */
+typedef struct ANativeWindow ANativeWindow;
+typedef struct ANativeWindow android_native_window_t;
+
+/*
+ * native_window_set_usage(..., usage)
+ * Sets the intended usage flags for the next buffers
+ * acquired with (*lockBuffer)() and on.
+ * By default (if this function is never called), a usage of
+ * GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
+ * is assumed.
+ * Calling this function will usually cause following buffers to be
+ * reallocated.
+ */
+
+static inline int native_window_set_usage(
+ struct ANativeWindow* window, int usage)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
+}
+
+/* deprecated. Always returns 0. Don't call. */
+static inline int native_window_connect(
+ struct ANativeWindow* window, int api) {
+ return 0;
+}
+
+/* deprecated. Always returns 0. Don't call. */
+static inline int native_window_disconnect(
+ struct ANativeWindow* window, int api) {
+ return 0;
+}
+
+/*
+ * native_window_set_crop(..., crop)
+ * Sets which region of the next queued buffers needs to be considered.
+ * Depending on the scaling mode, a buffer's crop region is scaled and/or
+ * cropped to match the surface's size. This function sets the crop in
+ * pre-transformed buffer pixel coordinates.
+ *
+ * The specified crop region applies to all buffers queued after it is called.
+ *
+ * If 'crop' is NULL, subsequently queued buffers won't be cropped.
+ *
+ * An error is returned if for instance the crop region is invalid, out of the
+ * buffer's bound or if the window is invalid.
+ */
+static inline int native_window_set_crop(
+ struct ANativeWindow* window,
+ android_native_rect_t const * crop)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_CROP, crop);
+}
+
+/*
+ * native_window_set_post_transform_crop(..., crop)
+ * Sets which region of the next queued buffers needs to be considered.
+ * Depending on the scaling mode, a buffer's crop region is scaled and/or
+ * cropped to match the surface's size. This function sets the crop in
+ * post-transformed pixel coordinates.
+ *
+ * The specified crop region applies to all buffers queued after it is called.
+ *
+ * If 'crop' is NULL, subsequently queued buffers won't be cropped.
+ *
+ * An error is returned if for instance the crop region is invalid, out of the
+ * buffer's bound or if the window is invalid.
+ */
+static inline int native_window_set_post_transform_crop(
+ struct ANativeWindow* window,
+ android_native_rect_t const * crop)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_POST_TRANSFORM_CROP, crop);
+}
+
+/*
+ * native_window_set_active_rect(..., active_rect)
+ *
+ * This function is deprectated and will be removed soon. For now it simply
+ * sets the post-transform crop for compatibility while multi-project commits
+ * get checked.
+ */
+static inline int native_window_set_active_rect(
+ struct ANativeWindow* window,
+ android_native_rect_t const * active_rect)
+{
+ return native_window_set_post_transform_crop(window, active_rect);
+}
+
+/*
+ * native_window_set_buffer_count(..., count)
+ * Sets the number of buffers associated with this native window.
+ */
+static inline int native_window_set_buffer_count(
+ struct ANativeWindow* window,
+ size_t bufferCount)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_BUFFER_COUNT, bufferCount);
+}
+
+/*
+ * native_window_set_buffers_geometry(..., int w, int h, int format)
+ * All buffers dequeued after this call will have the dimensions and format
+ * specified. A successful call to this function has the same effect as calling
+ * native_window_set_buffers_size and native_window_set_buffers_format.
+ *
+ * XXX: This function is deprecated. The native_window_set_buffers_dimensions
+ * and native_window_set_buffers_format functions should be used instead.
+ */
+static inline int native_window_set_buffers_geometry(
+ struct ANativeWindow* window,
+ int w, int h, int format)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
+ w, h, format);
+}
+
+/*
+ * native_window_set_buffers_dimensions(..., int w, int h)
+ * All buffers dequeued after this call will have the dimensions specified.
+ * In particular, all buffers will have a fixed-size, independent from the
+ * native-window size. They will be scaled according to the scaling mode
+ * (see native_window_set_scaling_mode) upon window composition.
+ *
+ * If w and h are 0, the normal behavior is restored. That is, dequeued buffers
+ * following this call will be sized to match the window's size.
+ *
+ * Calling this function will reset the window crop to a NULL value, which
+ * disables cropping of the buffers.
+ */
+static inline int native_window_set_buffers_dimensions(
+ struct ANativeWindow* window,
+ int w, int h)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS,
+ w, h);
+}
+
+/*
+ * native_window_set_buffers_user_dimensions(..., int w, int h)
+ *
+ * Sets the user buffer size for the window, which overrides the
+ * window's size. All buffers dequeued after this call will have the
+ * dimensions specified unless overridden by
+ * native_window_set_buffers_dimensions. All buffers will have a
+ * fixed-size, independent from the native-window size. They will be
+ * scaled according to the scaling mode (see
+ * native_window_set_scaling_mode) upon window composition.
+ *
+ * If w and h are 0, the normal behavior is restored. That is, the
+ * default buffer size will match the windows's size.
+ *
+ * Calling this function will reset the window crop to a NULL value, which
+ * disables cropping of the buffers.
+ */
+static inline int native_window_set_buffers_user_dimensions(
+ struct ANativeWindow* window,
+ int w, int h)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS,
+ w, h);
+}
+
+/*
+ * native_window_set_buffers_format(..., int format)
+ * All buffers dequeued after this call will have the format specified.
+ *
+ * If the specified format is 0, the default buffer format will be used.
+ */
+static inline int native_window_set_buffers_format(
+ struct ANativeWindow* window,
+ int format)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_FORMAT, format);
+}
+
+/*
+ * native_window_set_buffers_transform(..., int transform)
+ * All buffers queued after this call will be displayed transformed according
+ * to the transform parameter specified.
+ */
+static inline int native_window_set_buffers_transform(
+ struct ANativeWindow* window,
+ int transform)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TRANSFORM,
+ transform);
+}
+
+/*
+ * native_window_set_buffers_timestamp(..., int64_t timestamp)
+ * All buffers queued after this call will be associated with the timestamp
+ * parameter specified. If the timestamp is set to NATIVE_WINDOW_TIMESTAMP_AUTO
+ * (the default), timestamps will be generated automatically when queueBuffer is
+ * called. The timestamp is measured in nanoseconds, and is normally monotonically
+ * increasing. The timestamp should be unaffected by time-of-day adjustments,
+ * and for a camera should be strictly monotonic but for a media player may be
+ * reset when the position is set.
+ */
+static inline int native_window_set_buffers_timestamp(
+ struct ANativeWindow* window,
+ int64_t timestamp)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP,
+ timestamp);
+}
+
+/*
+ * native_window_set_scaling_mode(..., int mode)
+ * All buffers queued after this call will be associated with the scaling mode
+ * specified.
+ */
+static inline int native_window_set_scaling_mode(
+ struct ANativeWindow* window,
+ int mode)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_SCALING_MODE,
+ mode);
+}
+
+/*
+ * native_window_api_connect(..., int api)
+ * connects an API to this window. only one API can be connected at a time.
+ * Returns -EINVAL if for some reason the window cannot be connected, which
+ * can happen if it's connected to some other API.
+ */
+static inline int native_window_api_connect(
+ struct ANativeWindow* window, int api)
+{
+ return window->perform(window, NATIVE_WINDOW_API_CONNECT, api);
+}
+
+/*
+ * native_window_api_disconnect(..., int api)
+ * disconnect the API from this window.
+ * An error is returned if for instance the window wasn't connected in the
+ * first place.
+ */
+static inline int native_window_api_disconnect(
+ struct ANativeWindow* window, int api)
+{
+ return window->perform(window, NATIVE_WINDOW_API_DISCONNECT, api);
+}
+
+
+__END_DECLS
+
+#endif /* SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H */
diff --git a/include/thread/pthread.h b/include/thread/pthread.h
new file mode 100644
index 0000000..4baf82f
--- /dev/null
+++ b/include/thread/pthread.h
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _PTHREAD_H_
+#define _PTHREAD_H_
+
+#include <time.h>
+#include <signal.h>
+#include <sched.h>
+#include <limits.h>
+#include <sys/types.h>
+
+/*
+ * Types
+ */
+typedef struct
+{
+ int volatile value;
+} pthread_mutex_t;
+
+#define PTHREAD_MUTEX_INITIALIZER {0}
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER {0x4000}
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER {0x8000}
+
+enum {
+ PTHREAD_MUTEX_NORMAL = 0,
+ PTHREAD_MUTEX_RECURSIVE = 1,
+ PTHREAD_MUTEX_ERRORCHECK = 2,
+
+ PTHREAD_MUTEX_ERRORCHECK_NP = PTHREAD_MUTEX_ERRORCHECK,
+ PTHREAD_MUTEX_RECURSIVE_NP = PTHREAD_MUTEX_RECURSIVE,
+
+ PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
+};
+
+
+
+typedef struct
+{
+ int volatile value;
+} pthread_cond_t;
+
+typedef struct
+{
+ uint32_t flags;
+ void * stack_base;
+ size_t stack_size;
+ size_t guard_size;
+ int32_t sched_policy;
+ int32_t sched_priority;
+} pthread_attr_t;
+
+typedef long pthread_mutexattr_t;
+typedef long pthread_condattr_t;
+
+typedef int pthread_key_t;
+typedef long pthread_t;
+
+typedef volatile int pthread_once_t;
+
+/*
+ * Defines
+ */
+#define PTHREAD_COND_INITIALIZER {0}
+
+#define PTHREAD_STACK_MIN (2 * PAGE_SIZE)
+
+#define PTHREAD_CREATE_DETACHED 0x00000001
+#define PTHREAD_CREATE_JOINABLE 0x00000000
+
+#define PTHREAD_ONCE_INIT 0
+
+#define PTHREAD_PROCESS_PRIVATE 0
+#define PTHREAD_PROCESS_SHARED 1
+
+#define PTHREAD_SCOPE_SYSTEM 0
+#define PTHREAD_SCOPE_PROCESS 1
+
+/*
+ * Prototypes
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int pthread_attr_init(pthread_attr_t * attr);
+int pthread_attr_destroy(pthread_attr_t * attr);
+
+int pthread_attr_setdetachstate(pthread_attr_t * attr, int state);
+int pthread_attr_getdetachstate(pthread_attr_t const * attr, int * state);
+
+int pthread_attr_setschedpolicy(pthread_attr_t * attr, int policy);
+int pthread_attr_getschedpolicy(pthread_attr_t const * attr, int * policy);
+
+int pthread_attr_setschedparam(pthread_attr_t * attr, struct sched_param const * param);
+int pthread_attr_getschedparam(pthread_attr_t const * attr, struct sched_param * param);
+
+int pthread_attr_setstacksize(pthread_attr_t * attr, size_t stack_size);
+int pthread_attr_getstacksize(pthread_attr_t const * attr, size_t * stack_size);
+
+int pthread_attr_setstackaddr(pthread_attr_t * attr, void * stackaddr);
+int pthread_attr_getstackaddr(pthread_attr_t const * attr, void ** stackaddr);
+
+int pthread_attr_setstack(pthread_attr_t * attr, void * stackaddr, size_t stack_size);
+int pthread_attr_getstack(pthread_attr_t const * attr, void ** stackaddr, size_t * stack_size);
+
+int pthread_attr_setguardsize(pthread_attr_t * attr, size_t guard_size);
+int pthread_attr_getguardsize(pthread_attr_t const * attr, size_t * guard_size);
+
+int pthread_attr_setscope(pthread_attr_t *attr, int scope);
+int pthread_attr_getscope(pthread_attr_t const *attr);
+
+int pthread_getattr_np(pthread_t thid, pthread_attr_t * attr);
+
+int pthread_create(pthread_t *thread, pthread_attr_t const * attr,
+ void *(*start_routine)(void *), void * arg);
+void pthread_exit(void * retval);
+int pthread_join(pthread_t thid, void ** ret_val);
+int pthread_detach(pthread_t thid);
+
+pthread_t pthread_self(void);
+int pthread_equal(pthread_t one, pthread_t two);
+
+int pthread_getschedparam(pthread_t thid, int * policy,
+ struct sched_param * param);
+int pthread_setschedparam(pthread_t thid, int poilcy,
+ struct sched_param const * param);
+
+int pthread_mutexattr_init(pthread_mutexattr_t *attr);
+int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
+int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type);
+int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);
+int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);
+int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared);
+
+int pthread_mutex_init(pthread_mutex_t *mutex,
+ const pthread_mutexattr_t *attr);
+int pthread_mutex_destroy(pthread_mutex_t *mutex);
+int pthread_mutex_lock(pthread_mutex_t *mutex);
+int pthread_mutex_unlock(pthread_mutex_t *mutex);
+int pthread_mutex_trylock(pthread_mutex_t *mutex);
+#if 0 /* MISSING FROM BIONIC */
+int pthread_mutex_timedlock(pthread_mutex_t *mutex, struct timespec* ts);
+#endif /* MISSING */
+
+int pthread_condattr_init(pthread_condattr_t *attr);
+int pthread_condattr_getpshared(pthread_condattr_t *attr, int *pshared);
+int pthread_condattr_setpshared(pthread_condattr_t* attr, int pshared);
+int pthread_condattr_destroy(pthread_condattr_t *attr);
+
+int pthread_cond_init(pthread_cond_t *cond,
+ const pthread_condattr_t *attr);
+int pthread_cond_destroy(pthread_cond_t *cond);
+int pthread_cond_broadcast(pthread_cond_t *cond);
+int pthread_cond_signal(pthread_cond_t *cond);
+int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
+int pthread_cond_timedwait(pthread_cond_t *cond,
+ pthread_mutex_t * mutex,
+ const struct timespec *abstime);
+
+/* BIONIC: same as pthread_cond_timedwait, except the 'abstime' given refers
+ * to the CLOCK_MONOTONIC clock instead, to avoid any problems when
+ * the wall-clock time is changed brutally
+ */
+int pthread_cond_timedwait_monotonic_np(pthread_cond_t *cond,
+ pthread_mutex_t *mutex,
+ const struct timespec *abstime);
+
+/* BIONIC: DEPRECATED. same as pthread_cond_timedwait_monotonic_np()
+ * unfortunately pthread_cond_timedwait_monotonic has shipped already
+ */
+int pthread_cond_timedwait_monotonic(pthread_cond_t *cond,
+ pthread_mutex_t *mutex,
+ const struct timespec *abstime);
+
+#define HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC 1
+
+/* BIONIC: same as pthread_cond_timedwait, except the 'reltime' given refers
+ * is relative to the current time.
+ */
+int pthread_cond_timedwait_relative_np(pthread_cond_t *cond,
+ pthread_mutex_t *mutex,
+ const struct timespec *reltime);
+
+#define HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE 1
+
+
+
+int pthread_cond_timeout_np(pthread_cond_t *cond,
+ pthread_mutex_t * mutex,
+ unsigned msecs);
+
+/* same as pthread_mutex_lock(), but will wait up to 'msecs' milli-seconds
+ * before returning. same return values than pthread_mutex_trylock though, i.e.
+ * returns EBUSY if the lock could not be acquired after the timeout
+ * expired.
+ */
+int pthread_mutex_lock_timeout_np(pthread_mutex_t *mutex, unsigned msecs);
+
+/* read-write lock support */
+
+typedef int pthread_rwlockattr_t;
+
+typedef struct {
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+ int numLocks;
+ int writerThreadId;
+ int pendingReaders;
+ int pendingWriters;
+ void* reserved[4]; /* for future extensibility */
+} pthread_rwlock_t;
+
+#define PTHREAD_RWLOCK_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0, 0, 0, { NULL, NULL, NULL, NULL } }
+
+int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);
+int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr);
+int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared);
+int pthread_rwlockattr_getpshared(pthread_rwlockattr_t *attr, int *pshared);
+
+int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
+int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
+
+int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
+int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
+int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, const struct timespec *abs_timeout);
+
+int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
+int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
+int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, const struct timespec *abs_timeout);
+
+int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
+
+
+int pthread_key_create(pthread_key_t *key, void (*destructor_function)(void *));
+int pthread_key_delete (pthread_key_t);
+int pthread_setspecific(pthread_key_t key, const void *value);
+void *pthread_getspecific(pthread_key_t key);
+
+int pthread_kill(pthread_t tid, int sig);
+int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset);
+
+int pthread_getcpuclockid(pthread_t tid, clockid_t *clockid);
+
+int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
+
+int pthread_setname_np(pthread_t thid, const char *thname);
+
+typedef void (*__pthread_cleanup_func_t)(void*);
+
+typedef struct __pthread_cleanup_t {
+ struct __pthread_cleanup_t* __cleanup_prev;
+ __pthread_cleanup_func_t __cleanup_routine;
+ void* __cleanup_arg;
+} __pthread_cleanup_t;
+
+extern void __pthread_cleanup_push(__pthread_cleanup_t* c,
+ __pthread_cleanup_func_t routine,
+ void* arg);
+
+extern void __pthread_cleanup_pop(__pthread_cleanup_t* c,
+ int execute);
+
+/* Believe or not, the definitions of pthread_cleanup_push and
+ * pthread_cleanup_pop below are correct. Posix states that these
+ * can be implemented as macros that might introduce opening and
+ * closing braces, and that using setjmp/longjmp/return/break/continue
+ * between them results in undefined behaviour.
+ *
+ * And indeed, GLibc and other C libraries use a similar definition
+ */
+#define pthread_cleanup_push(routine, arg) \
+ do { \
+ __pthread_cleanup_t __cleanup; \
+ __pthread_cleanup_push( &__cleanup, (routine), (arg) ); \
+
+#define pthread_cleanup_pop(execute) \
+ __pthread_cleanup_pop( &__cleanup, (execute)); \
+ } while (0);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+/************ TO FIX ************/
+
+#define LONG_LONG_MAX __LONG_LONG_MAX__
+#define LONG_LONG_MIN (-__LONG_LONG_MAX__ - 1)
+
+#endif /* _PTHREAD_H_ */
diff --git a/include/utils/AndroidThreads.h b/include/utils/AndroidThreads.h
new file mode 100644
index 0000000..f67648f
--- /dev/null
+++ b/include/utils/AndroidThreads.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef _LIBS_UTILS_ANDROID_THREADS_H
+#define _LIBS_UTILS_ANDROID_THREADS_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/ThreadDefs.h>
+
+// ---------------------------------------------------------------------------
+// C API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Create and run a new thread.
+extern int androidCreateThread(android_thread_func_t, void *);
+
+// Create thread with lots of parameters
+extern int androidCreateThreadEtc(android_thread_func_t entryFunction,
+ void *userData,
+ const char* threadName,
+ int32_t threadPriority,
+ size_t threadStackSize,
+ android_thread_id_t *threadId);
+
+// Get some sort of unique identifier for the current thread.
+extern android_thread_id_t androidGetThreadId();
+
+// Low-level thread creation -- never creates threads that can
+// interact with the Java VM.
+extern int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
+ void *userData,
+ const char* threadName,
+ int32_t threadPriority,
+ size_t threadStackSize,
+ android_thread_id_t *threadId);
+
+// Used by the Java Runtime to control how threads are created, so that
+// they can be proper and lovely Java threads.
+typedef int (*android_create_thread_fn)(android_thread_func_t entryFunction,
+ void *userData,
+ const char* threadName,
+ int32_t threadPriority,
+ size_t threadStackSize,
+ android_thread_id_t *threadId);
+
+extern void androidSetCreateThreadFunc(android_create_thread_fn func);
+
+// ------------------------------------------------------------------
+// Extra functions working with raw pids.
+
+// Get pid for the current thread.
+extern pid_t androidGetTid();
+
+#ifdef HAVE_ANDROID_OS
+// Change the priority AND scheduling group of a particular thread. The priority
+// should be one of the ANDROID_PRIORITY constants. Returns INVALID_OPERATION
+// if the priority set failed, else another value if just the group set failed;
+// in either case errno is set. Thread ID zero means current thread.
+extern int androidSetThreadPriority(pid_t tid, int prio);
+
+// Get the current priority of a particular thread. Returns one of the
+// ANDROID_PRIORITY constants or a negative result in case of error.
+extern int androidGetThreadPriority(pid_t tid);
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+// ----------------------------------------------------------------------------
+// C++ API
+#ifdef __cplusplus
+namespace android {
+// ----------------------------------------------------------------------------
+
+// Create and run a new thread.
+inline bool createThread(thread_func_t f, void *a) {
+ return androidCreateThread(f, a) ? true : false;
+}
+
+// Create thread with lots of parameters
+inline bool createThreadEtc(thread_func_t entryFunction,
+ void *userData,
+ const char* threadName = "android:unnamed_thread",
+ int32_t threadPriority = PRIORITY_DEFAULT,
+ size_t threadStackSize = 0,
+ thread_id_t *threadId = 0)
+{
+ return androidCreateThreadEtc(entryFunction, userData, threadName,
+ threadPriority, threadStackSize, threadId) ? true : false;
+}
+
+// Get some sort of unique identifier for the current thread.
+inline thread_id_t getThreadId() {
+ return androidGetThreadId();
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+#endif // __cplusplus
+// ----------------------------------------------------------------------------
+
+#endif // _LIBS_UTILS_ANDROID_THREADS_H
diff --git a/include/utils/Atomic.h b/include/utils/Atomic.h
new file mode 100644
index 0000000..7eb476c
--- /dev/null
+++ b/include/utils/Atomic.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_UTILS_ATOMIC_H
+#define ANDROID_UTILS_ATOMIC_H
+
+#include <cutils/atomic.h>
+
+#endif // ANDROID_UTILS_ATOMIC_H
diff --git a/include/utils/BasicHashtable.h b/include/utils/BasicHashtable.h
new file mode 100644
index 0000000..fdf9738
--- /dev/null
+++ b/include/utils/BasicHashtable.h
@@ -0,0 +1,393 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_BASIC_HASHTABLE_H
+#define ANDROID_BASIC_HASHTABLE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/SharedBuffer.h>
+#include <utils/TypeHelpers.h>
+
+namespace android {
+
+/* Implementation type. Nothing to see here. */
+class BasicHashtableImpl {
+protected:
+ struct Bucket {
+ // The collision flag indicates that the bucket is part of a collision chain
+ // such that at least two entries both hash to this bucket. When true, we
+ // may need to seek further along the chain to find the entry.
+ static const uint32_t COLLISION = 0x80000000UL;
+
+ // The present flag indicates that the bucket contains an initialized entry value.
+ static const uint32_t PRESENT = 0x40000000UL;
+
+ // Mask for 30 bits worth of the hash code that are stored within the bucket to
+ // speed up lookups and rehashing by eliminating the need to recalculate the
+ // hash code of the entry's key.
+ static const uint32_t HASH_MASK = 0x3fffffffUL;
+
+ // Combined value that stores the collision and present flags as well as
+ // a 30 bit hash code.
+ uint32_t cookie;
+
+ // Storage for the entry begins here.
+ char entry[0];
+ };
+
+ BasicHashtableImpl(size_t entrySize, bool hasTrivialDestructor,
+ size_t minimumInitialCapacity, float loadFactor);
+ BasicHashtableImpl(const BasicHashtableImpl& other);
+
+ void dispose();
+
+ inline void edit() {
+ if (mBuckets && !SharedBuffer::bufferFromData(mBuckets)->onlyOwner()) {
+ clone();
+ }
+ }
+
+ void setTo(const BasicHashtableImpl& other);
+ void clear();
+
+ ssize_t next(ssize_t index) const;
+ ssize_t find(ssize_t index, hash_t hash, const void* __restrict__ key) const;
+ size_t add(hash_t hash, const void* __restrict__ entry);
+ void removeAt(size_t index);
+ void rehash(size_t minimumCapacity, float loadFactor);
+
+ const size_t mBucketSize; // number of bytes per bucket including the entry
+ const bool mHasTrivialDestructor; // true if the entry type does not require destruction
+ size_t mCapacity; // number of buckets that can be filled before exceeding load factor
+ float mLoadFactor; // load factor
+ size_t mSize; // number of elements actually in the table
+ size_t mFilledBuckets; // number of buckets for which collision or present is true
+ size_t mBucketCount; // number of slots in the mBuckets array
+ void* mBuckets; // array of buckets, as a SharedBuffer
+
+ inline const Bucket& bucketAt(const void* __restrict__ buckets, size_t index) const {
+ return *reinterpret_cast<const Bucket*>(
+ static_cast<const uint8_t*>(buckets) + index * mBucketSize);
+ }
+
+ inline Bucket& bucketAt(void* __restrict__ buckets, size_t index) const {
+ return *reinterpret_cast<Bucket*>(static_cast<uint8_t*>(buckets) + index * mBucketSize);
+ }
+
+ virtual bool compareBucketKey(const Bucket& bucket, const void* __restrict__ key) const = 0;
+ virtual void initializeBucketEntry(Bucket& bucket, const void* __restrict__ entry) const = 0;
+ virtual void destroyBucketEntry(Bucket& bucket) const = 0;
+
+private:
+ void clone();
+
+ // Allocates a bucket array as a SharedBuffer.
+ void* allocateBuckets(size_t count) const;
+
+ // Releases a bucket array's associated SharedBuffer.
+ void releaseBuckets(void* __restrict__ buckets, size_t count) const;
+
+ // Destroys the contents of buckets (invokes destroyBucketEntry for each
+ // populated bucket if needed).
+ void destroyBuckets(void* __restrict__ buckets, size_t count) const;
+
+ // Copies the content of buckets (copies the cookie and invokes copyBucketEntry
+ // for each populated bucket if needed).
+ void copyBuckets(const void* __restrict__ fromBuckets,
+ void* __restrict__ toBuckets, size_t count) const;
+
+ // Determines the appropriate size of a bucket array to store a certain minimum
+ // number of entries and returns its effective capacity.
+ static void determineCapacity(size_t minimumCapacity, float loadFactor,
+ size_t* __restrict__ outBucketCount, size_t* __restrict__ outCapacity);
+
+ // Trim a hash code to 30 bits to match what we store in the bucket's cookie.
+ inline static hash_t trimHash(hash_t hash) {
+ return (hash & Bucket::HASH_MASK) ^ (hash >> 30);
+ }
+
+ // Returns the index of the first bucket that is in the collision chain
+ // for the specified hash code, given the total number of buckets.
+ // (Primary hash)
+ inline static size_t chainStart(hash_t hash, size_t count) {
+ return hash % count;
+ }
+
+ // Returns the increment to add to a bucket index to seek to the next bucket
+ // in the collision chain for the specified hash code, given the total number of buckets.
+ // (Secondary hash)
+ inline static size_t chainIncrement(hash_t hash, size_t count) {
+ return ((hash >> 7) | (hash << 25)) % (count - 1) + 1;
+ }
+
+ // Returns the index of the next bucket that is in the collision chain
+ // that is defined by the specified increment, given the total number of buckets.
+ inline static size_t chainSeek(size_t index, size_t increment, size_t count) {
+ return (index + increment) % count;
+ }
+};
+
+/*
+ * A BasicHashtable stores entries that are indexed by hash code in place
+ * within an array. The basic operations are finding entries by key,
+ * adding new entries and removing existing entries.
+ *
+ * This class provides a very limited set of operations with simple semantics.
+ * It is intended to be used as a building block to construct more complex
+ * and interesting data structures such as HashMap. Think very hard before
+ * adding anything extra to BasicHashtable, it probably belongs at a
+ * higher level of abstraction.
+ *
+ * TKey: The key type.
+ * TEntry: The entry type which is what is actually stored in the array.
+ *
+ * TKey must support the following contract:
+ * bool operator==(const TKey& other) const; // return true if equal
+ * bool operator!=(const TKey& other) const; // return true if unequal
+ *
+ * TEntry must support the following contract:
+ * const TKey& getKey() const; // get the key from the entry
+ *
+ * This class supports storing entries with duplicate keys. Of course, it can't
+ * tell them apart during removal so only the first entry will be removed.
+ * We do this because it means that operations like add() can't fail.
+ */
+template <typename TKey, typename TEntry>
+class BasicHashtable : private BasicHashtableImpl {
+public:
+ /* Creates a hashtable with the specified minimum initial capacity.
+ * The underlying array will be created when the first entry is added.
+ *
+ * minimumInitialCapacity: The minimum initial capacity for the hashtable.
+ * Default is 0.
+ * loadFactor: The desired load factor for the hashtable, between 0 and 1.
+ * Default is 0.75.
+ */
+ BasicHashtable(size_t minimumInitialCapacity = 0, float loadFactor = 0.75f);
+
+ /* Copies a hashtable.
+ * The underlying storage is shared copy-on-write.
+ */
+ BasicHashtable(const BasicHashtable& other);
+
+ /* Clears and destroys the hashtable.
+ */
+ virtual ~BasicHashtable();
+
+ /* Making this hashtable a copy of the other hashtable.
+ * The underlying storage is shared copy-on-write.
+ *
+ * other: The hashtable to copy.
+ */
+ inline BasicHashtable<TKey, TEntry>& operator =(const BasicHashtable<TKey, TEntry> & other) {
+ setTo(other);
+ return *this;
+ }
+
+ /* Returns the number of entries in the hashtable.
+ */
+ inline size_t size() const {
+ return mSize;
+ }
+
+ /* Returns the capacity of the hashtable, which is the number of elements that can
+ * added to the hashtable without requiring it to be grown.
+ */
+ inline size_t capacity() const {
+ return mCapacity;
+ }
+
+ /* Returns the number of buckets that the hashtable has, which is the size of its
+ * underlying array.
+ */
+ inline size_t bucketCount() const {
+ return mBucketCount;
+ }
+
+ /* Returns the load factor of the hashtable. */
+ inline float loadFactor() const {
+ return mLoadFactor;
+ };
+
+ /* Returns a const reference to the entry at the specified index.
+ *
+ * index: The index of the entry to retrieve. Must be a valid index within
+ * the bounds of the hashtable.
+ */
+ inline const TEntry& entryAt(size_t index) const {
+ return entryFor(bucketAt(mBuckets, index));
+ }
+
+ /* Returns a non-const reference to the entry at the specified index.
+ *
+ * index: The index of the entry to edit. Must be a valid index within
+ * the bounds of the hashtable.
+ */
+ inline TEntry& editEntryAt(size_t index) {
+ edit();
+ return entryFor(bucketAt(mBuckets, index));
+ }
+
+ /* Clears the hashtable.
+ * All entries in the hashtable are destroyed immediately.
+ * If you need to do something special with the entries in the hashtable then iterate
+ * over them and do what you need before clearing the hashtable.
+ */
+ inline void clear() {
+ BasicHashtableImpl::clear();
+ }
+
+ /* Returns the index of the next entry in the hashtable given the index of a previous entry.
+ * If the given index is -1, then returns the index of the first entry in the hashtable,
+ * if there is one, or -1 otherwise.
+ * If the given index is not -1, then returns the index of the next entry in the hashtable,
+ * in strictly increasing order, or -1 if there are none left.
+ *
+ * index: The index of the previous entry that was iterated, or -1 to begin
+ * iteration at the beginning of the hashtable.
+ */
+ inline ssize_t next(ssize_t index) const {
+ return BasicHashtableImpl::next(index);
+ }
+
+ /* Finds the index of an entry with the specified key.
+ * If the given index is -1, then returns the index of the first matching entry,
+ * otherwise returns the index of the next matching entry.
+ * If the hashtable contains multiple entries with keys that match the requested
+ * key, then the sequence of entries returned is arbitrary.
+ * Returns -1 if no entry was found.
+ *
+ * index: The index of the previous entry with the specified key, or -1 to
+ * find the first matching entry.
+ * hash: The hashcode of the key.
+ * key: The key.
+ */
+ inline ssize_t find(ssize_t index, hash_t hash, const TKey& key) const {
+ return BasicHashtableImpl::find(index, hash, &key);
+ }
+
+ /* Adds the entry to the hashtable.
+ * Returns the index of the newly added entry.
+ * If an entry with the same key already exists, then a duplicate entry is added.
+ * If the entry will not fit, then the hashtable's capacity is increased and
+ * its contents are rehashed. See rehash().
+ *
+ * hash: The hashcode of the key.
+ * entry: The entry to add.
+ */
+ inline size_t add(hash_t hash, const TEntry& entry) {
+ return BasicHashtableImpl::add(hash, &entry);
+ }
+
+ /* Removes the entry with the specified index from the hashtable.
+ * The entry is destroyed immediately.
+ * The index must be valid.
+ *
+ * The hashtable is not compacted after an item is removed, so it is legal
+ * to continue iterating over the hashtable using next() or find().
+ *
+ * index: The index of the entry to remove. Must be a valid index within the
+ * bounds of the hashtable, and it must refer to an existing entry.
+ */
+ inline void removeAt(size_t index) {
+ BasicHashtableImpl::removeAt(index);
+ }
+
+ /* Rehashes the contents of the hashtable.
+ * Grows the hashtable to at least the specified minimum capacity or the
+ * current number of elements, whichever is larger.
+ *
+ * Rehashing causes all entries to be copied and the entry indices may change.
+ * Although the hash codes are cached by the hashtable, rehashing can be an
+ * expensive operation and should be avoided unless the hashtable's size
+ * needs to be changed.
+ *
+ * Rehashing is the only way to change the capacity or load factor of the
+ * hashtable once it has been created. It can be used to compact the
+ * hashtable by choosing a minimum capacity that is smaller than the current
+ * capacity (such as 0).
+ *
+ * minimumCapacity: The desired minimum capacity after rehashing.
+ * loadFactor: The desired load factor after rehashing.
+ */
+ inline void rehash(size_t minimumCapacity, float loadFactor) {
+ BasicHashtableImpl::rehash(minimumCapacity, loadFactor);
+ }
+
+protected:
+ static inline const TEntry& entryFor(const Bucket& bucket) {
+ return reinterpret_cast<const TEntry&>(bucket.entry);
+ }
+
+ static inline TEntry& entryFor(Bucket& bucket) {
+ return reinterpret_cast<TEntry&>(bucket.entry);
+ }
+
+ virtual bool compareBucketKey(const Bucket& bucket, const void* __restrict__ key) const;
+ virtual void initializeBucketEntry(Bucket& bucket, const void* __restrict__ entry) const;
+ virtual void destroyBucketEntry(Bucket& bucket) const;
+
+private:
+ // For dumping the raw contents of a hashtable during testing.
+ friend class BasicHashtableTest;
+ inline uint32_t cookieAt(size_t index) const {
+ return bucketAt(mBuckets, index).cookie;
+ }
+};
+
+template <typename TKey, typename TEntry>
+BasicHashtable<TKey, TEntry>::BasicHashtable(size_t minimumInitialCapacity, float loadFactor) :
+ BasicHashtableImpl(sizeof(TEntry), traits<TEntry>::has_trivial_dtor,
+ minimumInitialCapacity, loadFactor) {
+}
+
+template <typename TKey, typename TEntry>
+BasicHashtable<TKey, TEntry>::BasicHashtable(const BasicHashtable<TKey, TEntry>& other) :
+ BasicHashtableImpl(other) {
+}
+
+template <typename TKey, typename TEntry>
+BasicHashtable<TKey, TEntry>::~BasicHashtable() {
+ dispose();
+}
+
+template <typename TKey, typename TEntry>
+bool BasicHashtable<TKey, TEntry>::compareBucketKey(const Bucket& bucket,
+ const void* __restrict__ key) const {
+ return entryFor(bucket).getKey() == *static_cast<const TKey*>(key);
+}
+
+template <typename TKey, typename TEntry>
+void BasicHashtable<TKey, TEntry>::initializeBucketEntry(Bucket& bucket,
+ const void* __restrict__ entry) const {
+ if (!traits<TEntry>::has_trivial_copy) {
+ new (&entryFor(bucket)) TEntry(*(static_cast<const TEntry*>(entry)));
+ } else {
+ memcpy(&entryFor(bucket), entry, sizeof(TEntry));
+ }
+}
+
+template <typename TKey, typename TEntry>
+void BasicHashtable<TKey, TEntry>::destroyBucketEntry(Bucket& bucket) const {
+ if (!traits<TEntry>::has_trivial_dtor) {
+ entryFor(bucket).~TEntry();
+ }
+}
+
+}; // namespace android
+
+#endif // ANDROID_BASIC_HASHTABLE_H
diff --git a/include/utils/BitSet.h b/include/utils/BitSet.h
new file mode 100644
index 0000000..e189d0c
--- /dev/null
+++ b/include/utils/BitSet.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef UTILS_BITSET_H
+#define UTILS_BITSET_H
+
+#include <stdint.h>
+#include <utils/TypeHelpers.h>
+
+/*
+ * Contains some bit manipulation helpers.
+ */
+
+namespace android {
+
+// A simple set of 32 bits that can be individually marked or cleared.
+struct BitSet32 {
+ uint32_t value;
+
+ inline BitSet32() : value(0) { }
+ explicit inline BitSet32(uint32_t value) : value(value) { }
+
+ // Gets the value associated with a particular bit index.
+ static inline uint32_t valueForBit(uint32_t n) { return 0x80000000 >> n; }
+
+ // Clears the bit set.
+ inline void clear() { value = 0; }
+
+ // Returns the number of marked bits in the set.
+ inline uint32_t count() const { return __builtin_popcount(value); }
+
+ // Returns true if the bit set does not contain any marked bits.
+ inline bool isEmpty() const { return ! value; }
+
+ // Returns true if the bit set does not contain any unmarked bits.
+ inline bool isFull() const { return value == 0xffffffff; }
+
+ // Returns true if the specified bit is marked.
+ inline bool hasBit(uint32_t n) const { return value & valueForBit(n); }
+
+ // Marks the specified bit.
+ inline void markBit(uint32_t n) { value |= valueForBit(n); }
+
+ // Clears the specified bit.
+ inline void clearBit(uint32_t n) { value &= ~ valueForBit(n); }
+
+ // Finds the first marked bit in the set.
+ // Result is undefined if all bits are unmarked.
+ inline uint32_t firstMarkedBit() const { return __builtin_clz(value); }
+
+ // Finds the first unmarked bit in the set.
+ // Result is undefined if all bits are marked.
+ inline uint32_t firstUnmarkedBit() const { return __builtin_clz(~ value); }
+
+ // Finds the last marked bit in the set.
+ // Result is undefined if all bits are unmarked.
+ inline uint32_t lastMarkedBit() const { return 31 - __builtin_ctz(value); }
+
+ // Finds the first marked bit in the set and clears it. Returns the bit index.
+ // Result is undefined if all bits are unmarked.
+ inline uint32_t clearFirstMarkedBit() {
+ uint32_t n = firstMarkedBit();
+ clearBit(n);
+ return n;
+ }
+
+ // Finds the first unmarked bit in the set and marks it. Returns the bit index.
+ // Result is undefined if all bits are marked.
+ inline uint32_t markFirstUnmarkedBit() {
+ uint32_t n = firstUnmarkedBit();
+ markBit(n);
+ return n;
+ }
+
+ // Finds the last marked bit in the set and clears it. Returns the bit index.
+ // Result is undefined if all bits are unmarked.
+ inline uint32_t clearLastMarkedBit() {
+ uint32_t n = lastMarkedBit();
+ clearBit(n);
+ return n;
+ }
+
+ // Gets the index of the specified bit in the set, which is the number of
+ // marked bits that appear before the specified bit.
+ inline uint32_t getIndexOfBit(uint32_t n) const {
+ return __builtin_popcount(value & ~(0xffffffffUL >> n));
+ }
+
+ inline bool operator== (const BitSet32& other) const { return value == other.value; }
+ inline bool operator!= (const BitSet32& other) const { return value != other.value; }
+};
+
+ANDROID_BASIC_TYPES_TRAITS(BitSet32)
+
+} // namespace android
+
+#endif // UTILS_BITSET_H
diff --git a/include/utils/BlobCache.h b/include/utils/BlobCache.h
new file mode 100644
index 0000000..4f342a2
--- /dev/null
+++ b/include/utils/BlobCache.h
@@ -0,0 +1,251 @@
+/*
+ ** Copyright 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.
+ */
+
+#ifndef ANDROID_BLOB_CACHE_H
+#define ANDROID_BLOB_CACHE_H
+
+#include <stddef.h>
+
+#include <utils/Flattenable.h>
+#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+#include <utils/threads.h>
+
+namespace android {
+
+// A BlobCache is an in-memory cache for binary key/value pairs. A BlobCache
+// does NOT provide any thread-safety guarantees.
+//
+// The cache contents can be serialized to an in-memory buffer or mmap'd file
+// and then reloaded in a subsequent execution of the program. This
+// serialization is non-portable and the data should only be used by the device
+// that generated it.
+class BlobCache : public RefBase, public Flattenable {
+public:
+
+ // Create an empty blob cache. The blob cache will cache key/value pairs
+ // with key and value sizes less than or equal to maxKeySize and
+ // maxValueSize, respectively. The total combined size of ALL cache entries
+ // (key sizes plus value sizes) will not exceed maxTotalSize.
+ BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize);
+
+ // set inserts a new binary value into the cache and associates it with the
+ // given binary key. If the key or value are too large for the cache then
+ // the cache remains unchanged. This includes the case where a different
+ // value was previously associated with the given key - the old value will
+ // remain in the cache. If the given key and value are small enough to be
+ // put in the cache (based on the maxKeySize, maxValueSize, and maxTotalSize
+ // values specified to the BlobCache constructor), then the key/value pair
+ // will be in the cache after set returns. Note, however, that a subsequent
+ // call to set may evict old key/value pairs from the cache.
+ //
+ // Preconditions:
+ // key != NULL
+ // 0 < keySize
+ // value != NULL
+ // 0 < valueSize
+ void set(const void* key, size_t keySize, const void* value,
+ size_t valueSize);
+
+ // get retrieves from the cache the binary value associated with a given
+ // binary key. If the key is present in the cache then the length of the
+ // binary value associated with that key is returned. If the value argument
+ // is non-NULL and the size of the cached value is less than valueSize bytes
+ // then the cached value is copied into the buffer pointed to by the value
+ // argument. If the key is not present in the cache then 0 is returned and
+ // the buffer pointed to by the value argument is not modified.
+ //
+ // Note that when calling get multiple times with the same key, the later
+ // calls may fail, returning 0, even if earlier calls succeeded. The return
+ // value must be checked for each call.
+ //
+ // Preconditions:
+ // key != NULL
+ // 0 < keySize
+ // 0 <= valueSize
+ size_t get(const void* key, size_t keySize, void* value, size_t valueSize);
+
+ // getFlattenedSize returns the number of bytes needed to store the entire
+ // serialized cache.
+ virtual size_t getFlattenedSize() const;
+
+ // getFdCount returns the number of file descriptors that will result from
+ // flattening the cache. This will always return 0 so as to allow the
+ // flattened cache to be saved to disk and then later restored.
+ virtual size_t getFdCount() const;
+
+ // flatten serializes the current contents of the cache into the memory
+ // pointed to by 'buffer'. The serialized cache contents can later be
+ // loaded into a BlobCache object using the unflatten method. The contents
+ // of the BlobCache object will not be modified.
+ //
+ // Preconditions:
+ // size >= this.getFlattenedSize()
+ // count == 0
+ virtual status_t flatten(void* buffer, size_t size, int fds[],
+ size_t count) const;
+
+ // unflatten replaces the contents of the cache with the serialized cache
+ // contents in the memory pointed to by 'buffer'. The previous contents of
+ // the BlobCache will be evicted from the cache. If an error occurs while
+ // unflattening the serialized cache contents then the BlobCache will be
+ // left in an empty state.
+ //
+ // Preconditions:
+ // count == 0
+ virtual status_t unflatten(void const* buffer, size_t size, int fds[],
+ size_t count);
+
+private:
+ // Copying is disallowed.
+ BlobCache(const BlobCache&);
+ void operator=(const BlobCache&);
+
+ // A random function helper to get around MinGW not having nrand48()
+ long int blob_random();
+
+ // clean evicts a randomly chosen set of entries from the cache such that
+ // the total size of all remaining entries is less than mMaxTotalSize/2.
+ void clean();
+
+ // isCleanable returns true if the cache is full enough for the clean method
+ // to have some effect, and false otherwise.
+ bool isCleanable() const;
+
+ // A Blob is an immutable sized unstructured data blob.
+ class Blob : public RefBase {
+ public:
+ Blob(const void* data, size_t size, bool copyData);
+ ~Blob();
+
+ bool operator<(const Blob& rhs) const;
+
+ const void* getData() const;
+ size_t getSize() const;
+
+ private:
+ // Copying is not allowed.
+ Blob(const Blob&);
+ void operator=(const Blob&);
+
+ // mData points to the buffer containing the blob data.
+ const void* mData;
+
+ // mSize is the size of the blob data in bytes.
+ size_t mSize;
+
+ // mOwnsData indicates whether or not this Blob object should free the
+ // memory pointed to by mData when the Blob gets destructed.
+ bool mOwnsData;
+ };
+
+ // A CacheEntry is a single key/value pair in the cache.
+ class CacheEntry {
+ public:
+ CacheEntry();
+ CacheEntry(const sp<Blob>& key, const sp<Blob>& value);
+ CacheEntry(const CacheEntry& ce);
+
+ bool operator<(const CacheEntry& rhs) const;
+ const CacheEntry& operator=(const CacheEntry&);
+
+ sp<Blob> getKey() const;
+ sp<Blob> getValue() const;
+
+ void setValue(const sp<Blob>& value);
+
+ private:
+
+ // mKey is the key that identifies the cache entry.
+ sp<Blob> mKey;
+
+ // mValue is the cached data associated with the key.
+ sp<Blob> mValue;
+ };
+
+ // A Header is the header for the entire BlobCache serialization format. No
+ // need to make this portable, so we simply write the struct out.
+ struct Header {
+ // mMagicNumber is the magic number that identifies the data as
+ // serialized BlobCache contents. It must always contain 'Blb$'.
+ uint32_t mMagicNumber;
+
+ // mBlobCacheVersion is the serialization format version.
+ uint32_t mBlobCacheVersion;
+
+ // mDeviceVersion is the device-specific version of the cache. This can
+ // be used to invalidate the cache.
+ uint32_t mDeviceVersion;
+
+ // mNumEntries is number of cache entries following the header in the
+ // data.
+ size_t mNumEntries;
+ };
+
+ // An EntryHeader is the header for a serialized cache entry. No need to
+ // make this portable, so we simply write the struct out. Each EntryHeader
+ // is followed imediately by the key data and then the value data.
+ //
+ // The beginning of each serialized EntryHeader is 4-byte aligned, so the
+ // number of bytes that a serialized cache entry will occupy is:
+ //
+ // ((sizeof(EntryHeader) + keySize + valueSize) + 3) & ~3
+ //
+ struct EntryHeader {
+ // mKeySize is the size of the entry key in bytes.
+ size_t mKeySize;
+
+ // mValueSize is the size of the entry value in bytes.
+ size_t mValueSize;
+
+ // mData contains both the key and value data for the cache entry. The
+ // key comes first followed immediately by the value.
+ uint8_t mData[];
+ };
+
+ // mMaxKeySize is the maximum key size that will be cached. Calls to
+ // BlobCache::set with a keySize parameter larger than mMaxKeySize will
+ // simply not add the key/value pair to the cache.
+ const size_t mMaxKeySize;
+
+ // mMaxValueSize is the maximum value size that will be cached. Calls to
+ // BlobCache::set with a valueSize parameter larger than mMaxValueSize will
+ // simply not add the key/value pair to the cache.
+ const size_t mMaxValueSize;
+
+ // mMaxTotalSize is the maximum size that all cache entries can occupy. This
+ // includes space for both keys and values. When a call to BlobCache::set
+ // would otherwise cause this limit to be exceeded, either the key/value
+ // pair passed to BlobCache::set will not be cached or other cache entries
+ // will be evicted from the cache to make room for the new entry.
+ const size_t mMaxTotalSize;
+
+ // mTotalSize is the total combined size of all keys and values currently in
+ // the cache.
+ size_t mTotalSize;
+
+ // mRandState is the pseudo-random number generator state. It is passed to
+ // nrand48 to generate random numbers when needed.
+ unsigned short mRandState[3];
+
+ // mCacheEntries stores all the cache entries that are resident in memory.
+ // Cache entries are added to it by the 'set' method.
+ SortedVector<CacheEntry> mCacheEntries;
+};
+
+}
+
+#endif // ANDROID_BLOB_CACHE_H
diff --git a/include/utils/BufferedTextOutput.h b/include/utils/BufferedTextOutput.h
new file mode 100644
index 0000000..69c6240
--- /dev/null
+++ b/include/utils/BufferedTextOutput.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#ifndef ANDROID_BUFFEREDTEXTOUTPUT_H
+#define ANDROID_BUFFEREDTEXTOUTPUT_H
+
+#include <utils/TextOutput.h>
+#include <utils/threads.h>
+#include <cutils/uio.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class BufferedTextOutput : public TextOutput
+{
+public:
+ //** Flags for constructor */
+ enum {
+ MULTITHREADED = 0x0001
+ };
+
+ BufferedTextOutput(uint32_t flags = 0);
+ virtual ~BufferedTextOutput();
+
+ virtual status_t print(const char* txt, size_t len);
+ virtual void moveIndent(int delta);
+
+ virtual void pushBundle();
+ virtual void popBundle();
+
+protected:
+ virtual status_t writeLines(const struct iovec& vec, size_t N) = 0;
+
+private:
+ struct BufferState;
+ struct ThreadState;
+
+ static ThreadState*getThreadState();
+ static void threadDestructor(void *st);
+
+ BufferState*getBuffer() const;
+
+ uint32_t mFlags;
+ const int32_t mSeq;
+ const int32_t mIndex;
+
+ Mutex mLock;
+ BufferState* mGlobalState;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_BUFFEREDTEXTOUTPUT_H
diff --git a/include/utils/ByteOrder.h b/include/utils/ByteOrder.h
new file mode 100644
index 0000000..baa3a83
--- /dev/null
+++ b/include/utils/ByteOrder.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+//
+
+#ifndef _LIBS_UTILS_BYTE_ORDER_H
+#define _LIBS_UTILS_BYTE_ORDER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#ifdef HAVE_WINSOCK
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#endif
+
+/*
+ * These macros are like the hton/ntoh byte swapping macros,
+ * except they allow you to swap to and from the "device" byte
+ * order. The device byte order is the endianness of the target
+ * device -- for the ARM CPUs we use today, this is little endian.
+ *
+ * Note that the byte swapping functions have not been optimized
+ * much; performance is currently not an issue for them since the
+ * intent is to allow us to avoid byte swapping on the device.
+ */
+
+static inline uint32_t android_swap_long(uint32_t v)
+{
+ return (v<<24) | ((v<<8)&0x00FF0000) | ((v>>8)&0x0000FF00) | (v>>24);
+}
+
+static inline uint16_t android_swap_short(uint16_t v)
+{
+ return (v<<8) | (v>>8);
+}
+
+#define DEVICE_BYTE_ORDER LITTLE_ENDIAN
+
+#if BYTE_ORDER == DEVICE_BYTE_ORDER
+
+#define dtohl(x) (x)
+#define dtohs(x) (x)
+#define htodl(x) (x)
+#define htods(x) (x)
+
+#else
+
+#define dtohl(x) (android_swap_long(x))
+#define dtohs(x) (android_swap_short(x))
+#define htodl(x) (android_swap_long(x))
+#define htods(x) (android_swap_short(x))
+
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define fromlel(x) (x)
+#define fromles(x) (x)
+#define tolel(x) (x)
+#define toles(x) (x)
+#else
+#define fromlel(x) (android_swap_long(x))
+#define fromles(x) (android_swap_short(x))
+#define tolel(x) (android_swap_long(x))
+#define toles(x) (android_swap_short(x))
+#endif
+
+#endif // _LIBS_UTILS_BYTE_ORDER_H
diff --git a/include/utils/CallStack.h b/include/utils/CallStack.h
new file mode 100644
index 0000000..079e20c
--- /dev/null
+++ b/include/utils/CallStack.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef ANDROID_CALLSTACK_H
+#define ANDROID_CALLSTACK_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/String8.h>
+#include <corkscrew/backtrace.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class CallStack
+{
+public:
+ enum {
+ MAX_DEPTH = 31
+ };
+
+ CallStack();
+ CallStack(const CallStack& rhs);
+ ~CallStack();
+
+ CallStack& operator = (const CallStack& rhs);
+
+ bool operator == (const CallStack& rhs) const;
+ bool operator != (const CallStack& rhs) const;
+ bool operator < (const CallStack& rhs) const;
+ bool operator >= (const CallStack& rhs) const;
+ bool operator > (const CallStack& rhs) const;
+ bool operator <= (const CallStack& rhs) const;
+
+ const void* operator [] (int index) const;
+
+ void clear();
+
+ void update(int32_t ignoreDepth=1, int32_t maxDepth=MAX_DEPTH);
+
+ // Dump a stack trace to the log
+ void dump(const char* prefix = 0) const;
+
+ // Return a string (possibly very long) containing the complete stack trace
+ String8 toString(const char* prefix = 0) const;
+
+ size_t size() const { return mCount; }
+
+private:
+ size_t mCount;
+ backtrace_frame_t mStack[MAX_DEPTH];
+};
+
+}; // namespace android
+
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_CALLSTACK_H
diff --git a/include/utils/Compat.h b/include/utils/Compat.h
new file mode 100644
index 0000000..1819266
--- /dev/null
+++ b/include/utils/Compat.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __LIB_UTILS_COMPAT_H
+#define __LIB_UTILS_COMPAT_H
+
+#include <unistd.h>
+
+/* Compatibility definitions for non-Linux (i.e., BSD-based) hosts. */
+#ifndef HAVE_OFF64_T
+#if _FILE_OFFSET_BITS < 64
+#error "_FILE_OFFSET_BITS < 64; large files are not supported on this platform"
+#endif /* _FILE_OFFSET_BITS < 64 */
+
+typedef off_t off64_t;
+
+static inline off64_t lseek64(int fd, off64_t offset, int whence) {
+ return lseek(fd, offset, whence);
+}
+
+#ifdef HAVE_PREAD
+static inline ssize_t pread64(int fd, void* buf, size_t nbytes, off64_t offset) {
+ return pread(fd, buf, nbytes, offset);
+}
+#endif
+
+#endif /* !HAVE_OFF64_T */
+
+#endif /* __LIB_UTILS_COMPAT_H */
diff --git a/include/utils/Condition.h b/include/utils/Condition.h
new file mode 100644
index 0000000..8852d53
--- /dev/null
+++ b/include/utils/Condition.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef _LIBS_UTILS_CONDITION_H
+#define _LIBS_UTILS_CONDITION_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/Timers.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+/*
+ * Condition variable class. The implementation is system-dependent.
+ *
+ * Condition variables are paired up with mutexes. Lock the mutex,
+ * call wait(), then either re-wait() if things aren't quite what you want,
+ * or unlock the mutex and continue. All threads calling wait() must
+ * use the same mutex for a given Condition.
+ */
+class Condition {
+public:
+ enum {
+ PRIVATE = 0,
+ SHARED = 1
+ };
+
+ Condition();
+ Condition(int type);
+ ~Condition();
+ // Wait on the condition variable. Lock the mutex before calling.
+ status_t wait(Mutex& mutex);
+ // same with relative timeout
+ status_t waitRelative(Mutex& mutex, nsecs_t reltime);
+ // Signal the condition variable, allowing one thread to continue.
+ void signal();
+ // Signal the condition variable, allowing all threads to continue.
+ void broadcast();
+
+private:
+#if defined(HAVE_PTHREADS)
+ pthread_cond_t mCond;
+#else
+ void* mState;
+#endif
+};
+
+// ---------------------------------------------------------------------------
+
+#if defined(HAVE_PTHREADS)
+
+inline Condition::Condition() {
+ pthread_cond_init(&mCond, NULL);
+}
+inline Condition::Condition(int type) {
+ if (type == SHARED) {
+ pthread_condattr_t attr;
+ pthread_condattr_init(&attr);
+ pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+ pthread_cond_init(&mCond, &attr);
+ pthread_condattr_destroy(&attr);
+ } else {
+ pthread_cond_init(&mCond, NULL);
+ }
+}
+inline Condition::~Condition() {
+ pthread_cond_destroy(&mCond);
+}
+inline status_t Condition::wait(Mutex& mutex) {
+ return -pthread_cond_wait(&mCond, &mutex.mMutex);
+}
+inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
+#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
+ struct timespec ts;
+ ts.tv_sec = reltime/1000000000;
+ ts.tv_nsec = reltime%1000000000;
+ return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
+#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
+ struct timespec ts;
+#if defined(HAVE_POSIX_CLOCKS)
+ clock_gettime(CLOCK_REALTIME, &ts);
+#else // HAVE_POSIX_CLOCKS
+ // we don't support the clocks here.
+ struct timeval t;
+ gettimeofday(&t, NULL);
+ ts.tv_sec = t.tv_sec;
+ ts.tv_nsec= t.tv_usec*1000;
+#endif // HAVE_POSIX_CLOCKS
+ ts.tv_sec += reltime/1000000000;
+ ts.tv_nsec+= reltime%1000000000;
+ if (ts.tv_nsec >= 1000000000) {
+ ts.tv_nsec -= 1000000000;
+ ts.tv_sec += 1;
+ }
+ return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
+#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
+}
+inline void Condition::signal() {
+ pthread_cond_signal(&mCond);
+}
+inline void Condition::broadcast() {
+ pthread_cond_broadcast(&mCond);
+}
+
+#endif // HAVE_PTHREADS
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // _LIBS_UTILS_CONDITON_H
diff --git a/include/utils/Debug.h b/include/utils/Debug.h
new file mode 100644
index 0000000..d9ed32d
--- /dev/null
+++ b/include/utils/Debug.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_DEBUG_H
+#define ANDROID_DEBUG_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+template<bool> struct CompileTimeAssert;
+template<> struct CompileTimeAssert<true> {};
+#define COMPILE_TIME_ASSERT(_exp) \
+ template class CompileTimeAssert< (_exp) >;
+#endif
+#define COMPILE_TIME_ASSERT_FUNCTION_SCOPE(_exp) \
+ CompileTimeAssert<( _exp )>();
+
+// ---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+template<bool C, typename LSH, typename RHS> struct CompileTimeIfElse;
+template<typename LHS, typename RHS>
+struct CompileTimeIfElse<true, LHS, RHS> { typedef LHS TYPE; };
+template<typename LHS, typename RHS>
+struct CompileTimeIfElse<false, LHS, RHS> { typedef RHS TYPE; };
+#endif
+
+// ---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const char* stringForIndent(int32_t indentLevel);
+
+typedef void (*debugPrintFunc)(void* cookie, const char* txt);
+
+void printTypeCode(uint32_t typeCode,
+ debugPrintFunc func = 0, void* cookie = 0);
+
+void printHexData(int32_t indent, const void *buf, size_t length,
+ size_t bytesPerLine=16, int32_t singleLineBytesCutoff=16,
+ size_t alignment=0, bool cArrayStyle=false,
+ debugPrintFunc func = 0, void* cookie = 0);
+
+#ifdef __cplusplus
+}
+#endif
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_DEBUG_H
diff --git a/include/utils/Endian.h b/include/utils/Endian.h
new file mode 100644
index 0000000..19f2504
--- /dev/null
+++ b/include/utils/Endian.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Android endian-ness defines.
+//
+#ifndef _LIBS_UTILS_ENDIAN_H
+#define _LIBS_UTILS_ENDIAN_H
+
+#if defined(HAVE_ENDIAN_H)
+
+#include <endian.h>
+
+#else /*not HAVE_ENDIAN_H*/
+
+#define __BIG_ENDIAN 0x1000
+#define __LITTLE_ENDIAN 0x0001
+
+#if defined(HAVE_LITTLE_ENDIAN)
+# define __BYTE_ORDER __LITTLE_ENDIAN
+#else
+# define __BYTE_ORDER __BIG_ENDIAN
+#endif
+
+#endif /*not HAVE_ENDIAN_H*/
+
+#endif /*_LIBS_UTILS_ENDIAN_H*/
diff --git a/include/utils/Errors.h b/include/utils/Errors.h
new file mode 100644
index 0000000..0b75b19
--- /dev/null
+++ b/include/utils/Errors.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef ANDROID_ERRORS_H
+#define ANDROID_ERRORS_H
+
+#include <sys/types.h>
+#include <errno.h>
+
+namespace android {
+
+// use this type to return error codes
+#ifdef HAVE_MS_C_RUNTIME
+typedef int status_t;
+#else
+typedef int32_t status_t;
+#endif
+
+/* the MS C runtime lacks a few error codes */
+
+/*
+ * Error codes.
+ * All error codes are negative values.
+ */
+
+// Win32 #defines NO_ERROR as well. It has the same value, so there's no
+// real conflict, though it's a bit awkward.
+#ifdef _WIN32
+# undef NO_ERROR
+#endif
+
+enum {
+ OK = 0, // Everything's swell.
+ NO_ERROR = 0, // No errors.
+
+ UNKNOWN_ERROR = 0x80000000,
+
+ NO_MEMORY = -ENOMEM,
+ INVALID_OPERATION = -ENOSYS,
+ BAD_VALUE = -EINVAL,
+ BAD_TYPE = 0x80000001,
+ NAME_NOT_FOUND = -ENOENT,
+ PERMISSION_DENIED = -EPERM,
+ NO_INIT = -ENODEV,
+ ALREADY_EXISTS = -EEXIST,
+ DEAD_OBJECT = -EPIPE,
+ FAILED_TRANSACTION = 0x80000002,
+ JPARKS_BROKE_IT = -EPIPE,
+#if !defined(HAVE_MS_C_RUNTIME)
+ BAD_INDEX = -EOVERFLOW,
+ NOT_ENOUGH_DATA = -ENODATA,
+ WOULD_BLOCK = -EWOULDBLOCK,
+ TIMED_OUT = -ETIMEDOUT,
+ UNKNOWN_TRANSACTION = -EBADMSG,
+#else
+ BAD_INDEX = -E2BIG,
+ NOT_ENOUGH_DATA = 0x80000003,
+ WOULD_BLOCK = 0x80000004,
+ TIMED_OUT = 0x80000005,
+ UNKNOWN_TRANSACTION = 0x80000006,
+#endif
+ FDS_NOT_ALLOWED = 0x80000007,
+};
+
+// Restore define; enumeration is in "android" namespace, so the value defined
+// there won't work for Win32 code in a different namespace.
+#ifdef _WIN32
+# define NO_ERROR 0L
+#endif
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_ERRORS_H
diff --git a/include/utils/FileMap.h b/include/utils/FileMap.h
new file mode 100644
index 0000000..dfe6d51
--- /dev/null
+++ b/include/utils/FileMap.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+//
+// Encapsulate a shared file mapping.
+//
+#ifndef __LIBS_FILE_MAP_H
+#define __LIBS_FILE_MAP_H
+
+#include <sys/types.h>
+
+#include <utils/Compat.h>
+
+#ifdef HAVE_WIN32_FILEMAP
+#include <windows.h>
+#endif
+
+namespace android {
+
+/*
+ * This represents a memory-mapped file. It might be the entire file or
+ * only part of it. This requires a little bookkeeping because the mapping
+ * needs to be aligned on page boundaries, and in some cases we'd like to
+ * have multiple references to the mapped area without creating additional
+ * maps.
+ *
+ * This always uses MAP_SHARED.
+ *
+ * TODO: we should be able to create a new FileMap that is a subset of
+ * an existing FileMap and shares the underlying mapped pages. Requires
+ * completing the refcounting stuff and possibly introducing the notion
+ * of a FileMap hierarchy.
+ */
+class FileMap {
+public:
+ FileMap(void);
+
+ /*
+ * Create a new mapping on an open file.
+ *
+ * Closing the file descriptor does not unmap the pages, so we don't
+ * claim ownership of the fd.
+ *
+ * Returns "false" on failure.
+ */
+ bool create(const char* origFileName, int fd,
+ off64_t offset, size_t length, bool readOnly);
+
+ /*
+ * Return the name of the file this map came from, if known.
+ */
+ const char* getFileName(void) const { return mFileName; }
+
+ /*
+ * Get a pointer to the piece of the file we requested.
+ */
+ void* getDataPtr(void) const { return mDataPtr; }
+
+ /*
+ * Get the length we requested.
+ */
+ size_t getDataLength(void) const { return mDataLength; }
+
+ /*
+ * Get the data offset used to create this map.
+ */
+ off64_t getDataOffset(void) const { return mDataOffset; }
+
+ /*
+ * Get a "copy" of the object.
+ */
+ FileMap* acquire(void) { mRefCount++; return this; }
+
+ /*
+ * Call this when mapping is no longer needed.
+ */
+ void release(void) {
+ if (--mRefCount <= 0)
+ delete this;
+ }
+
+ /*
+ * This maps directly to madvise() values, but allows us to avoid
+ * including <sys/mman.h> everywhere.
+ */
+ enum MapAdvice {
+ NORMAL, RANDOM, SEQUENTIAL, WILLNEED, DONTNEED
+ };
+
+ /*
+ * Apply an madvise() call to the entire file.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+ int advise(MapAdvice advice);
+
+protected:
+ // don't delete objects; call release()
+ ~FileMap(void);
+
+private:
+ // these are not implemented
+ FileMap(const FileMap& src);
+ const FileMap& operator=(const FileMap& src);
+
+ int mRefCount; // reference count
+ char* mFileName; // original file name, if known
+ void* mBasePtr; // base of mmap area; page aligned
+ size_t mBaseLength; // length, measured from "mBasePtr"
+ off64_t mDataOffset; // offset used when map was created
+ void* mDataPtr; // start of requested data, offset from base
+ size_t mDataLength; // length, measured from "mDataPtr"
+#ifdef HAVE_WIN32_FILEMAP
+ HANDLE mFileHandle; // Win32 file handle
+ HANDLE mFileMapping; // Win32 file mapping handle
+#endif
+
+ static long mPageSize;
+};
+
+}; // namespace android
+
+#endif // __LIBS_FILE_MAP_H
diff --git a/include/utils/Flattenable.h b/include/utils/Flattenable.h
new file mode 100644
index 0000000..852be3b
--- /dev/null
+++ b/include/utils/Flattenable.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef ANDROID_UTILS_FLATTENABLE_H
+#define ANDROID_UTILS_FLATTENABLE_H
+
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+class Flattenable
+{
+public:
+ // size in bytes of the flattened object
+ virtual size_t getFlattenedSize() const = 0;
+
+ // number of file descriptors to flatten
+ virtual size_t getFdCount() const = 0;
+
+ // flattens the object into buffer.
+ // size should be at least of getFlattenedSize()
+ // file descriptors are written in the fds[] array but ownership is
+ // not transfered (ie: they must be dupped by the caller of
+ // flatten() if needed).
+ virtual status_t flatten(void* buffer, size_t size,
+ int fds[], size_t count) const = 0;
+
+ // unflattens the object from buffer.
+ // size should be equal to the value of getFlattenedSize() when the
+ // object was flattened.
+ // unflattened file descriptors are found in the fds[] array and
+ // don't need to be dupped(). ie: the caller of unflatten doesn't
+ // keep ownership. If a fd is not retained by unflatten() it must be
+ // explicitly closed.
+ virtual status_t unflatten(void const* buffer, size_t size,
+ int fds[], size_t count) = 0;
+
+protected:
+ virtual ~Flattenable() = 0;
+
+};
+
+}; // namespace android
+
+
+#endif /* ANDROID_UTILS_FLATTENABLE_H */
diff --git a/include/utils/Functor.h b/include/utils/Functor.h
new file mode 100644
index 0000000..e24ded4
--- /dev/null
+++ b/include/utils/Functor.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_FUNCTOR_H
+#define ANDROID_FUNCTOR_H
+
+#include <utils/Errors.h>
+
+namespace android {
+
+class Functor {
+public:
+ Functor() {}
+ virtual ~Functor() {}
+ virtual status_t operator ()(int what, void* data) { return NO_ERROR; }
+};
+
+}; // namespace android
+
+#endif // ANDROID_FUNCTOR_H
diff --git a/include/utils/GenerationCache.h b/include/utils/GenerationCache.h
new file mode 100644
index 0000000..40722d1
--- /dev/null
+++ b/include/utils/GenerationCache.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef ANDROID_UTILS_GENERATION_CACHE_H
+#define ANDROID_UTILS_GENERATION_CACHE_H
+
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+/**
+ * GenerationCache callback used when an item is removed
+ */
+template<typename EntryKey, typename EntryValue>
+class OnEntryRemoved {
+public:
+ virtual ~OnEntryRemoved() { };
+ virtual void operator()(EntryKey& key, EntryValue& value) = 0;
+}; // class OnEntryRemoved
+
+template<typename EntryKey, typename EntryValue>
+struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > {
+ Entry(const Entry<EntryKey, EntryValue>& e) :
+ key(e.key), value(e.value),
+ parent(e.parent), child(e.child) { }
+ Entry(const EntryKey& key, const EntryValue& value) :
+ key(key), value(value) { }
+
+ EntryKey key;
+ EntryValue value;
+
+ sp<Entry<EntryKey, EntryValue> > parent; // next older entry
+ sp<Entry<EntryKey, EntryValue> > child; // next younger entry
+}; // struct Entry
+
+/**
+ * A LRU type cache
+ */
+template<typename K, typename V>
+class GenerationCache {
+public:
+ GenerationCache(uint32_t maxCapacity);
+ virtual ~GenerationCache();
+
+ enum Capacity {
+ kUnlimitedCapacity,
+ };
+
+ void setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener);
+
+ size_t size() const;
+
+ void clear();
+
+ bool contains(const K& key) const;
+ const K& getKeyAt(size_t index) const;
+ const V& getValueAt(size_t index) const;
+
+ const V& get(const K& key);
+ bool put(const K& key, const V& value);
+
+ void removeAt(ssize_t index);
+ bool remove(const K& key);
+ bool removeOldest();
+
+private:
+ KeyedVector<K, sp<Entry<K, V> > > mCache;
+ uint32_t mMaxCapacity;
+
+ OnEntryRemoved<K, V>* mListener;
+
+ sp<Entry<K, V> > mOldest;
+ sp<Entry<K, V> > mYoungest;
+
+ void attachToCache(const sp<Entry<K, V> >& entry);
+ void detachFromCache(const sp<Entry<K, V> >& entry);
+
+ const V mNullValue;
+}; // class GenerationCache
+
+template<typename K, typename V>
+GenerationCache<K, V>::GenerationCache(uint32_t maxCapacity): mMaxCapacity(maxCapacity),
+ mListener(NULL), mNullValue(NULL) {
+};
+
+template<typename K, typename V>
+GenerationCache<K, V>::~GenerationCache() {
+ clear();
+};
+
+template<typename K, typename V>
+uint32_t GenerationCache<K, V>::size() const {
+ return mCache.size();
+}
+
+/**
+ * Should be set by the user of the Cache so that the callback is called whenever an item is
+ * removed from the cache
+ */
+template<typename K, typename V>
+void GenerationCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener) {
+ mListener = listener;
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::clear() {
+ if (mListener) {
+ for (uint32_t i = 0; i < mCache.size(); i++) {
+ sp<Entry<K, V> > entry = mCache.valueAt(i);
+ if (mListener) {
+ (*mListener)(entry->key, entry->value);
+ }
+ }
+ }
+ mCache.clear();
+ mYoungest.clear();
+ mOldest.clear();
+}
+
+template<typename K, typename V>
+bool GenerationCache<K, V>::contains(const K& key) const {
+ return mCache.indexOfKey(key) >= 0;
+}
+
+template<typename K, typename V>
+const K& GenerationCache<K, V>::getKeyAt(size_t index) const {
+ return mCache.keyAt(index);
+}
+
+template<typename K, typename V>
+const V& GenerationCache<K, V>::getValueAt(size_t index) const {
+ return mCache.valueAt(index)->value;
+}
+
+template<typename K, typename V>
+const V& GenerationCache<K, V>::get(const K& key) {
+ ssize_t index = mCache.indexOfKey(key);
+ if (index >= 0) {
+ const sp<Entry<K, V> >& entry = mCache.valueAt(index);
+ detachFromCache(entry);
+ attachToCache(entry);
+ return entry->value;
+ }
+
+ return mNullValue;
+}
+
+template<typename K, typename V>
+bool GenerationCache<K, V>::put(const K& key, const V& value) {
+ if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) {
+ removeOldest();
+ }
+
+ ssize_t index = mCache.indexOfKey(key);
+ if (index < 0) {
+ sp<Entry<K, V> > entry = new Entry<K, V>(key, value);
+ mCache.add(key, entry);
+ attachToCache(entry);
+ return true;
+ }
+
+ return false;
+}
+
+template<typename K, typename V>
+bool GenerationCache<K, V>::remove(const K& key) {
+ ssize_t index = mCache.indexOfKey(key);
+ if (index >= 0) {
+ removeAt(index);
+ return true;
+ }
+
+ return false;
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::removeAt(ssize_t index) {
+ sp<Entry<K, V> > entry = mCache.valueAt(index);
+ if (mListener) {
+ (*mListener)(entry->key, entry->value);
+ }
+ mCache.removeItemsAt(index, 1);
+ detachFromCache(entry);
+}
+
+template<typename K, typename V>
+bool GenerationCache<K, V>::removeOldest() {
+ if (mOldest.get()) {
+ ssize_t index = mCache.indexOfKey(mOldest->key);
+ if (index >= 0) {
+ removeAt(index);
+ return true;
+ }
+ ALOGE("GenerationCache: removeOldest failed to find the item in the cache "
+ "with the given key, but we know it must be in there. "
+ "Is the key comparator kaput?");
+ }
+
+ return false;
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::attachToCache(const sp<Entry<K, V> >& entry) {
+ if (!mYoungest.get()) {
+ mYoungest = mOldest = entry;
+ } else {
+ entry->parent = mYoungest;
+ mYoungest->child = entry;
+ mYoungest = entry;
+ }
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::detachFromCache(const sp<Entry<K, V> >& entry) {
+ if (entry->parent.get()) {
+ entry->parent->child = entry->child;
+ } else {
+ mOldest = entry->child;
+ }
+
+ if (entry->child.get()) {
+ entry->child->parent = entry->parent;
+ } else {
+ mYoungest = entry->parent;
+ }
+
+ entry->parent.clear();
+ entry->child.clear();
+}
+
+}; // namespace android
+
+#endif // ANDROID_UTILS_GENERATION_CACHE_H
diff --git a/include/utils/KeyedVector.h b/include/utils/KeyedVector.h
new file mode 100644
index 0000000..20575ee
--- /dev/null
+++ b/include/utils/KeyedVector.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_KEYED_VECTOR_H
+#define ANDROID_KEYED_VECTOR_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/SortedVector.h>
+#include <utils/TypeHelpers.h>
+#include <utils/Errors.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+template <typename KEY, typename VALUE>
+class KeyedVector
+{
+public:
+ typedef KEY key_type;
+ typedef VALUE value_type;
+
+ inline KeyedVector();
+
+ /*
+ * empty the vector
+ */
+
+ inline void clear() { mVector.clear(); }
+
+ /*!
+ * vector stats
+ */
+
+ //! returns number of items in the vector
+ inline size_t size() const { return mVector.size(); }
+ //! returns wether or not the vector is empty
+ inline bool isEmpty() const { return mVector.isEmpty(); }
+ //! returns how many items can be stored without reallocating the backing store
+ inline size_t capacity() const { return mVector.capacity(); }
+ //! setst the capacity. capacity can never be reduced less than size()
+ inline ssize_t setCapacity(size_t size) { return mVector.setCapacity(size); }
+
+ /*!
+ * accessors
+ */
+ const VALUE& valueFor(const KEY& key) const;
+ const VALUE& valueAt(size_t index) const;
+ const KEY& keyAt(size_t index) const;
+ ssize_t indexOfKey(const KEY& key) const;
+
+ /*!
+ * modifying the array
+ */
+
+ VALUE& editValueFor(const KEY& key);
+ VALUE& editValueAt(size_t index);
+
+ /*!
+ * add/insert/replace items
+ */
+
+ ssize_t add(const KEY& key, const VALUE& item);
+ ssize_t replaceValueFor(const KEY& key, const VALUE& item);
+ ssize_t replaceValueAt(size_t index, const VALUE& item);
+
+ /*!
+ * remove items
+ */
+
+ ssize_t removeItem(const KEY& key);
+ ssize_t removeItemsAt(size_t index, size_t count = 1);
+
+private:
+ SortedVector< key_value_pair_t<KEY, VALUE> > mVector;
+};
+
+// KeyedVector<KEY, VALUE> can be trivially moved using memcpy() because its
+// underlying SortedVector can be trivially moved.
+template<typename KEY, typename VALUE> struct trait_trivial_move<KeyedVector<KEY, VALUE> > {
+ enum { value = trait_trivial_move<SortedVector< key_value_pair_t<KEY, VALUE> > >::value };
+};
+
+
+// ---------------------------------------------------------------------------
+
+/**
+ * Variation of KeyedVector that holds a default value to return when
+ * valueFor() is called with a key that doesn't exist.
+ */
+template <typename KEY, typename VALUE>
+class DefaultKeyedVector : public KeyedVector<KEY, VALUE>
+{
+public:
+ inline DefaultKeyedVector(const VALUE& defValue = VALUE());
+ const VALUE& valueFor(const KEY& key) const;
+
+private:
+ VALUE mDefault;
+};
+
+// ---------------------------------------------------------------------------
+
+template<typename KEY, typename VALUE> inline
+KeyedVector<KEY,VALUE>::KeyedVector()
+{
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::indexOfKey(const KEY& key) const {
+ return mVector.indexOf( key_value_pair_t<KEY,VALUE>(key) );
+}
+
+template<typename KEY, typename VALUE> inline
+const VALUE& KeyedVector<KEY,VALUE>::valueFor(const KEY& key) const {
+ ssize_t i = this->indexOfKey(key);
+ assert(i>=0);
+ return mVector.itemAt(i).value;
+}
+
+template<typename KEY, typename VALUE> inline
+const VALUE& KeyedVector<KEY,VALUE>::valueAt(size_t index) const {
+ return mVector.itemAt(index).value;
+}
+
+template<typename KEY, typename VALUE> inline
+const KEY& KeyedVector<KEY,VALUE>::keyAt(size_t index) const {
+ return mVector.itemAt(index).key;
+}
+
+template<typename KEY, typename VALUE> inline
+VALUE& KeyedVector<KEY,VALUE>::editValueFor(const KEY& key) {
+ ssize_t i = this->indexOfKey(key);
+ assert(i>=0);
+ return mVector.editItemAt(i).value;
+}
+
+template<typename KEY, typename VALUE> inline
+VALUE& KeyedVector<KEY,VALUE>::editValueAt(size_t index) {
+ return mVector.editItemAt(index).value;
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::add(const KEY& key, const VALUE& value) {
+ return mVector.add( key_value_pair_t<KEY,VALUE>(key, value) );
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::replaceValueFor(const KEY& key, const VALUE& value) {
+ key_value_pair_t<KEY,VALUE> pair(key, value);
+ mVector.remove(pair);
+ return mVector.add(pair);
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::replaceValueAt(size_t index, const VALUE& item) {
+ if (index<size()) {
+ mVector.editItemAt(index).value = item;
+ return index;
+ }
+ return BAD_INDEX;
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::removeItem(const KEY& key) {
+ return mVector.remove(key_value_pair_t<KEY,VALUE>(key));
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY, VALUE>::removeItemsAt(size_t index, size_t count) {
+ return mVector.removeItemsAt(index, count);
+}
+
+// ---------------------------------------------------------------------------
+
+template<typename KEY, typename VALUE> inline
+DefaultKeyedVector<KEY,VALUE>::DefaultKeyedVector(const VALUE& defValue)
+ : mDefault(defValue)
+{
+}
+
+template<typename KEY, typename VALUE> inline
+const VALUE& DefaultKeyedVector<KEY,VALUE>::valueFor(const KEY& key) const {
+ ssize_t i = this->indexOfKey(key);
+ return i >= 0 ? KeyedVector<KEY,VALUE>::valueAt(i) : mDefault;
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_KEYED_VECTOR_H
diff --git a/include/utils/LinearTransform.h b/include/utils/LinearTransform.h
new file mode 100644
index 0000000..04cb355
--- /dev/null
+++ b/include/utils/LinearTransform.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBS_UTILS_LINEAR_TRANSFORM_H
+#define _LIBS_UTILS_LINEAR_TRANSFORM_H
+
+#include <stdint.h>
+
+namespace android {
+
+// LinearTransform defines a structure which hold the definition of a
+// transformation from single dimensional coordinate system A into coordinate
+// system B (and back again). Values in A and in B are 64 bit, the linear
+// scale factor is expressed as a rational number using two 32 bit values.
+//
+// Specifically, let
+// f(a) = b
+// F(b) = f^-1(b) = a
+// then
+//
+// f(a) = (((a - a_zero) * a_to_b_numer) / a_to_b_denom) + b_zero;
+//
+// and
+//
+// F(b) = (((b - b_zero) * a_to_b_denom) / a_to_b_numer) + a_zero;
+//
+struct LinearTransform {
+ int64_t a_zero;
+ int64_t b_zero;
+ int32_t a_to_b_numer;
+ uint32_t a_to_b_denom;
+
+ // Transform from A->B
+ // Returns true on success, or false in the case of a singularity or an
+ // overflow.
+ bool doForwardTransform(int64_t a_in, int64_t* b_out) const;
+
+ // Transform from B->A
+ // Returns true on success, or false in the case of a singularity or an
+ // overflow.
+ bool doReverseTransform(int64_t b_in, int64_t* a_out) const;
+
+ // Helpers which will reduce the fraction N/D using Euclid's method.
+ template <class T> static void reduce(T* N, T* D);
+ static void reduce(int32_t* N, uint32_t* D);
+};
+
+
+}
+
+#endif // _LIBS_UTILS_LINEAR_TRANSFORM_H
diff --git a/include/utils/List.h b/include/utils/List.h
new file mode 100644
index 0000000..403cd7f
--- /dev/null
+++ b/include/utils/List.h
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Templated list class. Normally we'd use STL, but we don't have that.
+// This class mimics STL's interfaces.
+//
+// Objects are copied into the list with the '=' operator or with copy-
+// construction, so if the compiler's auto-generated versions won't work for
+// you, define your own.
+//
+// The only class you want to use from here is "List".
+//
+#ifndef _LIBS_UTILS_LIST_H
+#define _LIBS_UTILS_LIST_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace android {
+
+/*
+ * Doubly-linked list. Instantiate with "List<MyClass> myList".
+ *
+ * Objects added to the list are copied using the assignment operator,
+ * so this must be defined.
+ */
+template<typename T>
+class List
+{
+protected:
+ /*
+ * One element in the list.
+ */
+ class _Node {
+ public:
+ explicit _Node(const T& val) : mVal(val) {}
+ ~_Node() {}
+ inline T& getRef() { return mVal; }
+ inline const T& getRef() const { return mVal; }
+ inline _Node* getPrev() const { return mpPrev; }
+ inline _Node* getNext() const { return mpNext; }
+ inline void setVal(const T& val) { mVal = val; }
+ inline void setPrev(_Node* ptr) { mpPrev = ptr; }
+ inline void setNext(_Node* ptr) { mpNext = ptr; }
+ private:
+ friend class List;
+ friend class _ListIterator;
+ T mVal;
+ _Node* mpPrev;
+ _Node* mpNext;
+ };
+
+ /*
+ * Iterator for walking through the list.
+ */
+
+ template <typename TYPE>
+ struct CONST_ITERATOR {
+ typedef _Node const * NodePtr;
+ typedef const TYPE Type;
+ };
+
+ template <typename TYPE>
+ struct NON_CONST_ITERATOR {
+ typedef _Node* NodePtr;
+ typedef TYPE Type;
+ };
+
+ template<
+ typename U,
+ template <class> class Constness
+ >
+ class _ListIterator {
+ typedef _ListIterator<U, Constness> _Iter;
+ typedef typename Constness<U>::NodePtr _NodePtr;
+ typedef typename Constness<U>::Type _Type;
+
+ explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {}
+
+ public:
+ _ListIterator() {}
+ _ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {}
+ ~_ListIterator() {}
+
+ // this will handle conversions from iterator to const_iterator
+ // (and also all convertible iterators)
+ // Here, in this implementation, the iterators can be converted
+ // if the nodes can be converted
+ template<typename V> explicit
+ _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {}
+
+
+ /*
+ * Dereference operator. Used to get at the juicy insides.
+ */
+ _Type& operator*() const { return mpNode->getRef(); }
+ _Type* operator->() const { return &(mpNode->getRef()); }
+
+ /*
+ * Iterator comparison.
+ */
+ inline bool operator==(const _Iter& right) const {
+ return mpNode == right.mpNode; }
+
+ inline bool operator!=(const _Iter& right) const {
+ return mpNode != right.mpNode; }
+
+ /*
+ * handle comparisons between iterator and const_iterator
+ */
+ template<typename OTHER>
+ inline bool operator==(const OTHER& right) const {
+ return mpNode == right.mpNode; }
+
+ template<typename OTHER>
+ inline bool operator!=(const OTHER& right) const {
+ return mpNode != right.mpNode; }
+
+ /*
+ * Incr/decr, used to move through the list.
+ */
+ inline _Iter& operator++() { // pre-increment
+ mpNode = mpNode->getNext();
+ return *this;
+ }
+ const _Iter operator++(int) { // post-increment
+ _Iter tmp(*this);
+ mpNode = mpNode->getNext();
+ return tmp;
+ }
+ inline _Iter& operator--() { // pre-increment
+ mpNode = mpNode->getPrev();
+ return *this;
+ }
+ const _Iter operator--(int) { // post-increment
+ _Iter tmp(*this);
+ mpNode = mpNode->getPrev();
+ return tmp;
+ }
+
+ inline _NodePtr getNode() const { return mpNode; }
+
+ _NodePtr mpNode; /* should be private, but older gcc fails */
+ private:
+ friend class List;
+ };
+
+public:
+ List() {
+ prep();
+ }
+ List(const List<T>& src) { // copy-constructor
+ prep();
+ insert(begin(), src.begin(), src.end());
+ }
+ virtual ~List() {
+ clear();
+ delete[] (unsigned char*) mpMiddle;
+ }
+
+ typedef _ListIterator<T, NON_CONST_ITERATOR> iterator;
+ typedef _ListIterator<T, CONST_ITERATOR> const_iterator;
+
+ List<T>& operator=(const List<T>& right);
+
+ /* returns true if the list is empty */
+ inline bool empty() const { return mpMiddle->getNext() == mpMiddle; }
+
+ /* return #of elements in list */
+ size_t size() const {
+ return size_t(distance(begin(), end()));
+ }
+
+ /*
+ * Return the first element or one past the last element. The
+ * _Node* we're returning is converted to an "iterator" by a
+ * constructor in _ListIterator.
+ */
+ inline iterator begin() {
+ return iterator(mpMiddle->getNext());
+ }
+ inline const_iterator begin() const {
+ return const_iterator(const_cast<_Node const*>(mpMiddle->getNext()));
+ }
+ inline iterator end() {
+ return iterator(mpMiddle);
+ }
+ inline const_iterator end() const {
+ return const_iterator(const_cast<_Node const*>(mpMiddle));
+ }
+
+ /* add the object to the head or tail of the list */
+ void push_front(const T& val) { insert(begin(), val); }
+ void push_back(const T& val) { insert(end(), val); }
+
+ /* insert before the current node; returns iterator at new node */
+ iterator insert(iterator posn, const T& val)
+ {
+ _Node* newNode = new _Node(val); // alloc & copy-construct
+ newNode->setNext(posn.getNode());
+ newNode->setPrev(posn.getNode()->getPrev());
+ posn.getNode()->getPrev()->setNext(newNode);
+ posn.getNode()->setPrev(newNode);
+ return iterator(newNode);
+ }
+
+ /* insert a range of elements before the current node */
+ void insert(iterator posn, const_iterator first, const_iterator last) {
+ for ( ; first != last; ++first)
+ insert(posn, *first);
+ }
+
+ /* remove one entry; returns iterator at next node */
+ iterator erase(iterator posn) {
+ _Node* pNext = posn.getNode()->getNext();
+ _Node* pPrev = posn.getNode()->getPrev();
+ pPrev->setNext(pNext);
+ pNext->setPrev(pPrev);
+ delete posn.getNode();
+ return iterator(pNext);
+ }
+
+ /* remove a range of elements */
+ iterator erase(iterator first, iterator last) {
+ while (first != last)
+ erase(first++); // don't erase than incr later!
+ return iterator(last);
+ }
+
+ /* remove all contents of the list */
+ void clear() {
+ _Node* pCurrent = mpMiddle->getNext();
+ _Node* pNext;
+
+ while (pCurrent != mpMiddle) {
+ pNext = pCurrent->getNext();
+ delete pCurrent;
+ pCurrent = pNext;
+ }
+ mpMiddle->setPrev(mpMiddle);
+ mpMiddle->setNext(mpMiddle);
+ }
+
+ /*
+ * Measure the distance between two iterators. On exist, "first"
+ * will be equal to "last". The iterators must refer to the same
+ * list.
+ *
+ * FIXME: This is actually a generic iterator function. It should be a
+ * template function at the top-level with specializations for things like
+ * vector<>, which can just do pointer math). Here we limit it to
+ * _ListIterator of the same type but different constness.
+ */
+ template<
+ typename U,
+ template <class> class CL,
+ template <class> class CR
+ >
+ ptrdiff_t distance(
+ _ListIterator<U, CL> first, _ListIterator<U, CR> last) const
+ {
+ ptrdiff_t count = 0;
+ while (first != last) {
+ ++first;
+ ++count;
+ }
+ return count;
+ }
+
+private:
+ /*
+ * I want a _Node but don't need it to hold valid data. More
+ * to the point, I don't want T's constructor to fire, since it
+ * might have side-effects or require arguments. So, we do this
+ * slightly uncouth storage alloc.
+ */
+ void prep() {
+ mpMiddle = (_Node*) new unsigned char[sizeof(_Node)];
+ mpMiddle->setPrev(mpMiddle);
+ mpMiddle->setNext(mpMiddle);
+ }
+
+ /*
+ * This node plays the role of "pointer to head" and "pointer to tail".
+ * It sits in the middle of a circular list of nodes. The iterator
+ * runs around the circle until it encounters this one.
+ */
+ _Node* mpMiddle;
+};
+
+/*
+ * Assignment operator.
+ *
+ * The simplest way to do this would be to clear out the target list and
+ * fill it with the source. However, we can speed things along by
+ * re-using existing elements.
+ */
+template<class T>
+List<T>& List<T>::operator=(const List<T>& right)
+{
+ if (this == &right)
+ return *this; // self-assignment
+ iterator firstDst = begin();
+ iterator lastDst = end();
+ const_iterator firstSrc = right.begin();
+ const_iterator lastSrc = right.end();
+ while (firstSrc != lastSrc && firstDst != lastDst)
+ *firstDst++ = *firstSrc++;
+ if (firstSrc == lastSrc) // ran out of elements in source?
+ erase(firstDst, lastDst); // yes, erase any extras
+ else
+ insert(lastDst, firstSrc, lastSrc); // copy remaining over
+ return *this;
+}
+
+}; // namespace android
+
+#endif // _LIBS_UTILS_LIST_H
diff --git a/include/utils/Log.h b/include/utils/Log.h
new file mode 100644
index 0000000..3c6cc8b
--- /dev/null
+++ b/include/utils/Log.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// C/C++ logging functions. See the logging documentation for API details.
+//
+// We'd like these to be available from C code (in case we import some from
+// somewhere), so this has a C interface.
+//
+// The output will be correct when the log file is shared between multiple
+// threads and/or multiple processes so long as the operating system
+// supports O_APPEND. These calls have mutex-protected data structures
+// and so are NOT reentrant. Do not use LOG in a signal handler.
+//
+#ifndef _LIBS_UTILS_LOG_H
+#define _LIBS_UTILS_LOG_H
+
+#include <cutils/log.h>
+
+#endif // _LIBS_UTILS_LOG_H
diff --git a/include/utils/Looper.h b/include/utils/Looper.h
new file mode 100644
index 0000000..d4a0067
--- /dev/null
+++ b/include/utils/Looper.h
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef UTILS_LOOPER_H
+#define UTILS_LOOPER_H
+
+#include <utils/threads.h>
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include <utils/Timers.h>
+
+#include <android/looper.h>
+
+#include <sys/epoll.h>
+
+/*
+ * Declare a concrete type for the NDK's looper forward declaration.
+ */
+struct ALooper {
+};
+
+namespace android {
+
+/**
+ * A message that can be posted to a Looper.
+ */
+struct Message {
+ Message() : what(0) { }
+ Message(int what) : what(what) { }
+
+ /* The message type. (interpretation is left up to the handler) */
+ int what;
+};
+
+
+/**
+ * Interface for a Looper message handler.
+ *
+ * The Looper holds a strong reference to the message handler whenever it has
+ * a message to deliver to it. Make sure to call Looper::removeMessages
+ * to remove any pending messages destined for the handler so that the handler
+ * can be destroyed.
+ */
+class MessageHandler : public virtual RefBase {
+protected:
+ virtual ~MessageHandler() { }
+
+public:
+ /**
+ * Handles a message.
+ */
+ virtual void handleMessage(const Message& message) = 0;
+};
+
+
+/**
+ * A simple proxy that holds a weak reference to a message handler.
+ */
+class WeakMessageHandler : public MessageHandler {
+protected:
+ virtual ~WeakMessageHandler();
+
+public:
+ WeakMessageHandler(const wp<MessageHandler>& handler);
+ virtual void handleMessage(const Message& message);
+
+private:
+ wp<MessageHandler> mHandler;
+};
+
+
+/**
+ * A looper callback.
+ */
+class LooperCallback : public virtual RefBase {
+protected:
+ virtual ~LooperCallback() { }
+
+public:
+ /**
+ * Handles a poll event for the given file descriptor.
+ * It is given the file descriptor it is associated with,
+ * a bitmask of the poll events that were triggered (typically ALOOPER_EVENT_INPUT),
+ * and the data pointer that was originally supplied.
+ *
+ * Implementations should return 1 to continue receiving callbacks, or 0
+ * to have this file descriptor and callback unregistered from the looper.
+ */
+ virtual int handleEvent(int fd, int events, void* data) = 0;
+};
+
+
+/**
+ * Wraps a ALooper_callbackFunc function pointer.
+ */
+class SimpleLooperCallback : public LooperCallback {
+protected:
+ virtual ~SimpleLooperCallback();
+
+public:
+ SimpleLooperCallback(ALooper_callbackFunc callback);
+ virtual int handleEvent(int fd, int events, void* data);
+
+private:
+ ALooper_callbackFunc mCallback;
+};
+
+
+/**
+ * A polling loop that supports monitoring file descriptor events, optionally
+ * using callbacks. The implementation uses epoll() internally.
+ *
+ * A looper can be associated with a thread although there is no requirement that it must be.
+ */
+class Looper : public ALooper, public RefBase {
+protected:
+ virtual ~Looper();
+
+public:
+ /**
+ * Creates a looper.
+ *
+ * If allowNonCallbaks is true, the looper will allow file descriptors to be
+ * registered without associated callbacks. This assumes that the caller of
+ * pollOnce() is prepared to handle callback-less events itself.
+ */
+ Looper(bool allowNonCallbacks);
+
+ /**
+ * Returns whether this looper instance allows the registration of file descriptors
+ * using identifiers instead of callbacks.
+ */
+ bool getAllowNonCallbacks() const;
+
+ /**
+ * Waits for events to be available, with optional timeout in milliseconds.
+ * Invokes callbacks for all file descriptors on which an event occurred.
+ *
+ * If the timeout is zero, returns immediately without blocking.
+ * If the timeout is negative, waits indefinitely until an event appears.
+ *
+ * Returns ALOOPER_POLL_WAKE if the poll was awoken using wake() before
+ * the timeout expired and no callbacks were invoked and no other file
+ * descriptors were ready.
+ *
+ * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked.
+ *
+ * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given
+ * timeout expired.
+ *
+ * Returns ALOOPER_POLL_ERROR if an error occurred.
+ *
+ * Returns a value >= 0 containing an identifier if its file descriptor has data
+ * and it has no callback function (requiring the caller here to handle it).
+ * In this (and only this) case outFd, outEvents and outData will contain the poll
+ * events and data associated with the fd, otherwise they will be set to NULL.
+ *
+ * This method does not return until it has finished invoking the appropriate callbacks
+ * for all file descriptors that were signalled.
+ */
+ int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
+ inline int pollOnce(int timeoutMillis) {
+ return pollOnce(timeoutMillis, NULL, NULL, NULL);
+ }
+
+ /**
+ * Like pollOnce(), but performs all pending callbacks until all
+ * data has been consumed or a file descriptor is available with no callback.
+ * This function will never return ALOOPER_POLL_CALLBACK.
+ */
+ int pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData);
+ inline int pollAll(int timeoutMillis) {
+ return pollAll(timeoutMillis, NULL, NULL, NULL);
+ }
+
+ /**
+ * Wakes the poll asynchronously.
+ *
+ * This method can be called on any thread.
+ * This method returns immediately.
+ */
+ void wake();
+
+ /**
+ * Adds a new file descriptor to be polled by the looper.
+ * If the same file descriptor was previously added, it is replaced.
+ *
+ * "fd" is the file descriptor to be added.
+ * "ident" is an identifier for this event, which is returned from pollOnce().
+ * The identifier must be >= 0, or ALOOPER_POLL_CALLBACK if providing a non-NULL callback.
+ * "events" are the poll events to wake up on. Typically this is ALOOPER_EVENT_INPUT.
+ * "callback" is the function to call when there is an event on the file descriptor.
+ * "data" is a private data pointer to supply to the callback.
+ *
+ * There are two main uses of this function:
+ *
+ * (1) If "callback" is non-NULL, then this function will be called when there is
+ * data on the file descriptor. It should execute any events it has pending,
+ * appropriately reading from the file descriptor. The 'ident' is ignored in this case.
+ *
+ * (2) If "callback" is NULL, the 'ident' will be returned by ALooper_pollOnce
+ * when its file descriptor has data available, requiring the caller to take
+ * care of processing it.
+ *
+ * Returns 1 if the file descriptor was added, 0 if the arguments were invalid.
+ *
+ * This method can be called on any thread.
+ * This method may block briefly if it needs to wake the poll.
+ *
+ * The callback may either be specified as a bare function pointer or as a smart
+ * pointer callback object. The smart pointer should be preferred because it is
+ * easier to avoid races when the callback is removed from a different thread.
+ * See removeFd() for details.
+ */
+ int addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data);
+ int addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data);
+
+ /**
+ * Removes a previously added file descriptor from the looper.
+ *
+ * When this method returns, it is safe to close the file descriptor since the looper
+ * will no longer have a reference to it. However, it is possible for the callback to
+ * already be running or for it to run one last time if the file descriptor was already
+ * signalled. Calling code is responsible for ensuring that this case is safely handled.
+ * For example, if the callback takes care of removing itself during its own execution either
+ * by returning 0 or by calling this method, then it can be guaranteed to not be invoked
+ * again at any later time unless registered anew.
+ *
+ * A simple way to avoid this problem is to use the version of addFd() that takes
+ * a sp<LooperCallback> instead of a bare function pointer. The LooperCallback will
+ * be released at the appropriate time by the Looper.
+ *
+ * Returns 1 if the file descriptor was removed, 0 if none was previously registered.
+ *
+ * This method can be called on any thread.
+ * This method may block briefly if it needs to wake the poll.
+ */
+ int removeFd(int fd);
+
+ /**
+ * Enqueues a message to be processed by the specified handler.
+ *
+ * The handler must not be null.
+ * This method can be called on any thread.
+ */
+ void sendMessage(const sp<MessageHandler>& handler, const Message& message);
+
+ /**
+ * Enqueues a message to be processed by the specified handler after all pending messages
+ * after the specified delay.
+ *
+ * The time delay is specified in uptime nanoseconds.
+ * The handler must not be null.
+ * This method can be called on any thread.
+ */
+ void sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,
+ const Message& message);
+
+ /**
+ * Enqueues a message to be processed by the specified handler after all pending messages
+ * at the specified time.
+ *
+ * The time is specified in uptime nanoseconds.
+ * The handler must not be null.
+ * This method can be called on any thread.
+ */
+ void sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
+ const Message& message);
+
+ /**
+ * Removes all messages for the specified handler from the queue.
+ *
+ * The handler must not be null.
+ * This method can be called on any thread.
+ */
+ void removeMessages(const sp<MessageHandler>& handler);
+
+ /**
+ * Removes all messages of a particular type for the specified handler from the queue.
+ *
+ * The handler must not be null.
+ * This method can be called on any thread.
+ */
+ void removeMessages(const sp<MessageHandler>& handler, int what);
+
+ /**
+ * Prepares a looper associated with the calling thread, and returns it.
+ * If the thread already has a looper, it is returned. Otherwise, a new
+ * one is created, associated with the thread, and returned.
+ *
+ * The opts may be ALOOPER_PREPARE_ALLOW_NON_CALLBACKS or 0.
+ */
+ static sp<Looper> prepare(int opts);
+
+ /**
+ * Sets the given looper to be associated with the calling thread.
+ * If another looper is already associated with the thread, it is replaced.
+ *
+ * If "looper" is NULL, removes the currently associated looper.
+ */
+ static void setForThread(const sp<Looper>& looper);
+
+ /**
+ * Returns the looper associated with the calling thread, or NULL if
+ * there is not one.
+ */
+ static sp<Looper> getForThread();
+
+private:
+ struct Request {
+ int fd;
+ int ident;
+ sp<LooperCallback> callback;
+ void* data;
+ };
+
+ struct Response {
+ int events;
+ Request request;
+ };
+
+ struct MessageEnvelope {
+ MessageEnvelope() : uptime(0) { }
+
+ MessageEnvelope(nsecs_t uptime, const sp<MessageHandler> handler,
+ const Message& message) : uptime(uptime), handler(handler), message(message) {
+ }
+
+ nsecs_t uptime;
+ sp<MessageHandler> handler;
+ Message message;
+ };
+
+ const bool mAllowNonCallbacks; // immutable
+
+ int mWakeReadPipeFd; // immutable
+ int mWakeWritePipeFd; // immutable
+ Mutex mLock;
+
+ Vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock
+ bool mSendingMessage; // guarded by mLock
+
+ int mEpollFd; // immutable
+
+ // Locked list of file descriptor monitoring requests.
+ KeyedVector<int, Request> mRequests; // guarded by mLock
+
+ // This state is only used privately by pollOnce and does not require a lock since
+ // it runs on a single thread.
+ Vector<Response> mResponses;
+ size_t mResponseIndex;
+ nsecs_t mNextMessageUptime; // set to LLONG_MAX when none
+
+ int pollInner(int timeoutMillis);
+ void awoken();
+ void pushResponse(int events, const Request& request);
+
+ static void initTLSKey();
+ static void threadDestructor(void *st);
+};
+
+} // namespace android
+
+#endif // UTILS_LOOPER_H
diff --git a/include/utils/Mutex.h b/include/utils/Mutex.h
new file mode 100644
index 0000000..dfa6988
--- /dev/null
+++ b/include/utils/Mutex.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#define HAVE_PTHREADS
+
+#ifndef _LIBS_UTILS_MUTEX_H
+#define _LIBS_UTILS_MUTEX_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/Errors.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class Condition;
+
+/*
+ * Simple mutex class. The implementation is system-dependent.
+ *
+ * The mutex must be unlocked by the thread that locked it. They are not
+ * recursive, i.e. the same thread can't lock it multiple times.
+ */
+class Mutex {
+public:
+ enum {
+ PRIVATE = 0,
+ SHARED = 1
+ };
+
+ Mutex();
+ Mutex(const char* name);
+ Mutex(int type, const char* name = NULL);
+ ~Mutex();
+
+ // lock or unlock the mutex
+ status_t lock();
+ void unlock();
+
+ // lock if possible; returns 0 on success, error otherwise
+ status_t tryLock();
+
+ // Manages the mutex automatically. It'll be locked when Autolock is
+ // constructed and released when Autolock goes out of scope.
+ class Autolock {
+ public:
+ inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
+ inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
+ inline ~Autolock() { mLock.unlock(); }
+ private:
+ Mutex& mLock;
+ };
+
+private:
+ friend class Condition;
+
+ // A mutex cannot be copied
+ Mutex(const Mutex&);
+ Mutex& operator = (const Mutex&);
+
+#if defined(HAVE_PTHREADS)
+ pthread_mutex_t mMutex;
+#else
+ void _init();
+ void* mState;
+#endif
+};
+
+// ---------------------------------------------------------------------------
+
+#if defined(HAVE_PTHREADS)
+
+inline Mutex::Mutex() {
+ pthread_mutex_init(&mMutex, NULL);
+}
+inline Mutex::Mutex(const char* name) {
+ pthread_mutex_init(&mMutex, NULL);
+}
+inline Mutex::Mutex(int type, const char* name) {
+ if (type == SHARED) {
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+ pthread_mutex_init(&mMutex, &attr);
+ pthread_mutexattr_destroy(&attr);
+ } else {
+ pthread_mutex_init(&mMutex, NULL);
+ }
+}
+inline Mutex::~Mutex() {
+ pthread_mutex_destroy(&mMutex);
+}
+inline status_t Mutex::lock() {
+ return -pthread_mutex_lock(&mMutex);
+}
+inline void Mutex::unlock() {
+ pthread_mutex_unlock(&mMutex);
+}
+inline status_t Mutex::tryLock() {
+ return -pthread_mutex_trylock(&mMutex);
+}
+
+#endif // HAVE_PTHREADS
+
+// ---------------------------------------------------------------------------
+
+/*
+ * Automatic mutex. Declare one of these at the top of a function.
+ * When the function returns, it will go out of scope, and release the
+ * mutex.
+ */
+
+typedef Mutex::Autolock AutoMutex;
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // _LIBS_UTILS_MUTEX_H
diff --git a/include/utils/PropertyMap.h b/include/utils/PropertyMap.h
new file mode 100644
index 0000000..a9e674f
--- /dev/null
+++ b/include/utils/PropertyMap.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef _UTILS_PROPERTY_MAP_H
+#define _UTILS_PROPERTY_MAP_H
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+#include <utils/Errors.h>
+#include <utils/Tokenizer.h>
+
+namespace android {
+
+/*
+ * Provides a mechanism for passing around string-based property key / value pairs
+ * and loading them from property files.
+ *
+ * The property files have the following simple structure:
+ *
+ * # Comment
+ * key = value
+ *
+ * Keys and values are any sequence of printable ASCII characters.
+ * The '=' separates the key from the value.
+ * The key and value may not contain whitespace.
+ *
+ * The '\' character is reserved for escape sequences and is not currently supported.
+ * The '"" character is reserved for quoting and is not currently supported.
+ * Files that contain the '\' or '"' character will fail to parse.
+ *
+ * The file must not contain duplicate keys.
+ *
+ * TODO Support escape sequences and quoted values when needed.
+ */
+class PropertyMap {
+public:
+ /* Creates an empty property map. */
+ PropertyMap();
+ ~PropertyMap();
+
+ /* Clears the property map. */
+ void clear();
+
+ /* Adds a property.
+ * Replaces the property with the same key if it is already present.
+ */
+ void addProperty(const String8& key, const String8& value);
+
+ /* Returns true if the property map contains the specified key. */
+ bool hasProperty(const String8& key) const;
+
+ /* Gets the value of a property and parses it.
+ * Returns true and sets outValue if the key was found and its value was parsed successfully.
+ * Otherwise returns false and does not modify outValue. (Also logs a warning.)
+ */
+ bool tryGetProperty(const String8& key, String8& outValue) const;
+ bool tryGetProperty(const String8& key, bool& outValue) const;
+ bool tryGetProperty(const String8& key, int32_t& outValue) const;
+ bool tryGetProperty(const String8& key, float& outValue) const;
+
+ /* Adds all values from the specified property map. */
+ void addAll(const PropertyMap* map);
+
+ /* Gets the underlying property map. */
+ inline const KeyedVector<String8, String8>& getProperties() const { return mProperties; }
+
+ /* Loads a property map from a file. */
+ static status_t load(const String8& filename, PropertyMap** outMap);
+
+private:
+ class Parser {
+ PropertyMap* mMap;
+ Tokenizer* mTokenizer;
+
+ public:
+ Parser(PropertyMap* map, Tokenizer* tokenizer);
+ ~Parser();
+ status_t parse();
+
+ private:
+ status_t parseType();
+ status_t parseKey();
+ status_t parseKeyProperty();
+ status_t parseModifier(const String8& token, int32_t* outMetaState);
+ status_t parseCharacterLiteral(char16_t* outCharacter);
+ };
+
+ KeyedVector<String8, String8> mProperties;
+};
+
+} // namespace android
+
+#endif // _UTILS_PROPERTY_MAP_H
diff --git a/include/utils/RWLock.h b/include/utils/RWLock.h
new file mode 100644
index 0000000..a5abea2
--- /dev/null
+++ b/include/utils/RWLock.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef _LIBS_UTILS_RWLOCK_H
+#define _LIBS_UTILS_RWLOCK_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/Errors.h>
+#include <utils/ThreadDefs.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+#if defined(HAVE_PTHREADS)
+
+/*
+ * Simple mutex class. The implementation is system-dependent.
+ *
+ * The mutex must be unlocked by the thread that locked it. They are not
+ * recursive, i.e. the same thread can't lock it multiple times.
+ */
+class RWLock {
+public:
+ enum {
+ PRIVATE = 0,
+ SHARED = 1
+ };
+
+ RWLock();
+ RWLock(const char* name);
+ RWLock(int type, const char* name = NULL);
+ ~RWLock();
+
+ status_t readLock();
+ status_t tryReadLock();
+ status_t writeLock();
+ status_t tryWriteLock();
+ void unlock();
+
+ class AutoRLock {
+ public:
+ inline AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); }
+ inline ~AutoRLock() { mLock.unlock(); }
+ private:
+ RWLock& mLock;
+ };
+
+ class AutoWLock {
+ public:
+ inline AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); }
+ inline ~AutoWLock() { mLock.unlock(); }
+ private:
+ RWLock& mLock;
+ };
+
+private:
+ // A RWLock cannot be copied
+ RWLock(const RWLock&);
+ RWLock& operator = (const RWLock&);
+
+ pthread_rwlock_t mRWLock;
+};
+
+inline RWLock::RWLock() {
+ pthread_rwlock_init(&mRWLock, NULL);
+}
+inline RWLock::RWLock(const char* name) {
+ pthread_rwlock_init(&mRWLock, NULL);
+}
+inline RWLock::RWLock(int type, const char* name) {
+ if (type == SHARED) {
+ pthread_rwlockattr_t attr;
+ pthread_rwlockattr_init(&attr);
+ pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+ pthread_rwlock_init(&mRWLock, &attr);
+ pthread_rwlockattr_destroy(&attr);
+ } else {
+ pthread_rwlock_init(&mRWLock, NULL);
+ }
+}
+inline RWLock::~RWLock() {
+ pthread_rwlock_destroy(&mRWLock);
+}
+inline status_t RWLock::readLock() {
+ return -pthread_rwlock_rdlock(&mRWLock);
+}
+inline status_t RWLock::tryReadLock() {
+ return -pthread_rwlock_tryrdlock(&mRWLock);
+}
+inline status_t RWLock::writeLock() {
+ return -pthread_rwlock_wrlock(&mRWLock);
+}
+inline status_t RWLock::tryWriteLock() {
+ return -pthread_rwlock_trywrlock(&mRWLock);
+}
+inline void RWLock::unlock() {
+ pthread_rwlock_unlock(&mRWLock);
+}
+
+#endif // HAVE_PTHREADS
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // _LIBS_UTILS_RWLOCK_H
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
new file mode 100644
index 0000000..99f5182
--- /dev/null
+++ b/include/utils/RefBase.h
@@ -0,0 +1,529 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_REF_BASE_H
+#define ANDROID_REF_BASE_H
+
+#include <cutils/atomic.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <utils/StrongPointer.h>
+#include <utils/TypeHelpers.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class TextOutput;
+TextOutput& printWeakPointer(TextOutput& to, const void* val);
+
+// ---------------------------------------------------------------------------
+
+#define COMPARE_WEAK(_op_) \
+inline bool operator _op_ (const sp<T>& o) const { \
+ return m_ptr _op_ o.m_ptr; \
+} \
+inline bool operator _op_ (const T* o) const { \
+ return m_ptr _op_ o; \
+} \
+template<typename U> \
+inline bool operator _op_ (const sp<U>& o) const { \
+ return m_ptr _op_ o.m_ptr; \
+} \
+template<typename U> \
+inline bool operator _op_ (const U* o) const { \
+ return m_ptr _op_ o; \
+}
+
+// ---------------------------------------------------------------------------
+class ReferenceMover;
+class ReferenceConverterBase {
+public:
+ virtual size_t getReferenceTypeSize() const = 0;
+ virtual void* getReferenceBase(void const*) const = 0;
+ inline virtual ~ReferenceConverterBase() { }
+};
+
+// ---------------------------------------------------------------------------
+
+class RefBase
+{
+public:
+ void incStrong(const void* id) const;
+ void decStrong(const void* id) const;
+
+ void forceIncStrong(const void* id) const;
+
+ //! DEBUGGING ONLY: Get current strong ref count.
+ int32_t getStrongCount() const;
+
+ class weakref_type
+ {
+ public:
+ RefBase* refBase() const;
+
+ void incWeak(const void* id);
+ void decWeak(const void* id);
+
+ // acquires a strong reference if there is already one.
+ bool attemptIncStrong(const void* id);
+
+ // acquires a weak reference if there is already one.
+ // This is not always safe. see ProcessState.cpp and BpBinder.cpp
+ // for proper use.
+ bool attemptIncWeak(const void* id);
+
+ //! DEBUGGING ONLY: Get current weak ref count.
+ int32_t getWeakCount() const;
+
+ //! DEBUGGING ONLY: Print references held on object.
+ void printRefs() const;
+
+ //! DEBUGGING ONLY: Enable tracking for this object.
+ // enable -- enable/disable tracking
+ // retain -- when tracking is enable, if true, then we save a stack trace
+ // for each reference and dereference; when retain == false, we
+ // match up references and dereferences and keep only the
+ // outstanding ones.
+
+ void trackMe(bool enable, bool retain);
+ };
+
+ weakref_type* createWeak(const void* id) const;
+
+ weakref_type* getWeakRefs() const;
+
+ //! DEBUGGING ONLY: Print references held on object.
+ inline void printRefs() const { getWeakRefs()->printRefs(); }
+
+ //! DEBUGGING ONLY: Enable tracking of object.
+ inline void trackMe(bool enable, bool retain)
+ {
+ getWeakRefs()->trackMe(enable, retain);
+ }
+
+ typedef RefBase basetype;
+
+protected:
+ RefBase();
+ virtual ~RefBase();
+
+ //! Flags for extendObjectLifetime()
+ enum {
+ OBJECT_LIFETIME_STRONG = 0x0000,
+ OBJECT_LIFETIME_WEAK = 0x0001,
+ OBJECT_LIFETIME_MASK = 0x0001
+ };
+
+ void extendObjectLifetime(int32_t mode);
+
+ //! Flags for onIncStrongAttempted()
+ enum {
+ FIRST_INC_STRONG = 0x0001
+ };
+
+ virtual void onFirstRef();
+ virtual void onLastStrongRef(const void* id);
+ virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
+ virtual void onLastWeakRef(const void* id);
+
+private:
+ friend class ReferenceMover;
+ static void moveReferences(void* d, void const* s, size_t n,
+ const ReferenceConverterBase& caster);
+
+private:
+ friend class weakref_type;
+ class weakref_impl;
+
+ RefBase(const RefBase& o);
+ RefBase& operator=(const RefBase& o);
+
+ weakref_impl* const mRefs;
+};
+
+// ---------------------------------------------------------------------------
+
+template <class T>
+class LightRefBase
+{
+public:
+ inline LightRefBase() : mCount(0) { }
+ inline void incStrong(const void* id) const {
+ android_atomic_inc(&mCount);
+ }
+ inline void decStrong(const void* id) const {
+ if (android_atomic_dec(&mCount) == 1) {
+ delete static_cast<const T*>(this);
+ }
+ }
+ //! DEBUGGING ONLY: Get current strong ref count.
+ inline int32_t getStrongCount() const {
+ return mCount;
+ }
+
+ typedef LightRefBase<T> basetype;
+
+protected:
+ inline ~LightRefBase() { }
+
+private:
+ friend class ReferenceMover;
+ inline static void moveReferences(void* d, void const* s, size_t n,
+ const ReferenceConverterBase& caster) { }
+
+private:
+ mutable volatile int32_t mCount;
+};
+
+// ---------------------------------------------------------------------------
+
+template <typename T>
+class wp
+{
+public:
+ typedef typename RefBase::weakref_type weakref_type;
+
+ inline wp() : m_ptr(0) { }
+
+ wp(T* other);
+ wp(const wp<T>& other);
+ wp(const sp<T>& other);
+ template<typename U> wp(U* other);
+ template<typename U> wp(const sp<U>& other);
+ template<typename U> wp(const wp<U>& other);
+
+ ~wp();
+
+ // Assignment
+
+ wp& operator = (T* other);
+ wp& operator = (const wp<T>& other);
+ wp& operator = (const sp<T>& other);
+
+ template<typename U> wp& operator = (U* other);
+ template<typename U> wp& operator = (const wp<U>& other);
+ template<typename U> wp& operator = (const sp<U>& other);
+
+ void set_object_and_refs(T* other, weakref_type* refs);
+
+ // promotion to sp
+
+ sp<T> promote() const;
+
+ // Reset
+
+ void clear();
+
+ // Accessors
+
+ inline weakref_type* get_refs() const { return m_refs; }
+
+ inline T* unsafe_get() const { return m_ptr; }
+
+ // Operators
+
+ COMPARE_WEAK(==)
+ COMPARE_WEAK(!=)
+ COMPARE_WEAK(>)
+ COMPARE_WEAK(<)
+ COMPARE_WEAK(<=)
+ COMPARE_WEAK(>=)
+
+ inline bool operator == (const wp<T>& o) const {
+ return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
+ }
+ template<typename U>
+ inline bool operator == (const wp<U>& o) const {
+ return m_ptr == o.m_ptr;
+ }
+
+ inline bool operator > (const wp<T>& o) const {
+ return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
+ }
+ template<typename U>
+ inline bool operator > (const wp<U>& o) const {
+ return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
+ }
+
+ inline bool operator < (const wp<T>& o) const {
+ return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
+ }
+ template<typename U>
+ inline bool operator < (const wp<U>& o) const {
+ return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
+ }
+ inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
+ template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
+ inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
+ template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
+ inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
+ template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
+
+private:
+ template<typename Y> friend class sp;
+ template<typename Y> friend class wp;
+
+ T* m_ptr;
+ weakref_type* m_refs;
+};
+
+template <typename T>
+TextOutput& operator<<(TextOutput& to, const wp<T>& val);
+
+#undef COMPARE_WEAK
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts below here.
+
+template<typename T>
+wp<T>::wp(T* other)
+ : m_ptr(other)
+{
+ if (other) m_refs = other->createWeak(this);
+}
+
+template<typename T>
+wp<T>::wp(const wp<T>& other)
+ : m_ptr(other.m_ptr), m_refs(other.m_refs)
+{
+ if (m_ptr) m_refs->incWeak(this);
+}
+
+template<typename T>
+wp<T>::wp(const sp<T>& other)
+ : m_ptr(other.m_ptr)
+{
+ if (m_ptr) {
+ m_refs = m_ptr->createWeak(this);
+ }
+}
+
+template<typename T> template<typename U>
+wp<T>::wp(U* other)
+ : m_ptr(other)
+{
+ if (other) m_refs = other->createWeak(this);
+}
+
+template<typename T> template<typename U>
+wp<T>::wp(const wp<U>& other)
+ : m_ptr(other.m_ptr)
+{
+ if (m_ptr) {
+ m_refs = other.m_refs;
+ m_refs->incWeak(this);
+ }
+}
+
+template<typename T> template<typename U>
+wp<T>::wp(const sp<U>& other)
+ : m_ptr(other.m_ptr)
+{
+ if (m_ptr) {
+ m_refs = m_ptr->createWeak(this);
+ }
+}
+
+template<typename T>
+wp<T>::~wp()
+{
+ if (m_ptr) m_refs->decWeak(this);
+}
+
+template<typename T>
+wp<T>& wp<T>::operator = (T* other)
+{
+ weakref_type* newRefs =
+ other ? other->createWeak(this) : 0;
+ if (m_ptr) m_refs->decWeak(this);
+ m_ptr = other;
+ m_refs = newRefs;
+ return *this;
+}
+
+template<typename T>
+wp<T>& wp<T>::operator = (const wp<T>& other)
+{
+ weakref_type* otherRefs(other.m_refs);
+ T* otherPtr(other.m_ptr);
+ if (otherPtr) otherRefs->incWeak(this);
+ if (m_ptr) m_refs->decWeak(this);
+ m_ptr = otherPtr;
+ m_refs = otherRefs;
+ return *this;
+}
+
+template<typename T>
+wp<T>& wp<T>::operator = (const sp<T>& other)
+{
+ weakref_type* newRefs =
+ other != NULL ? other->createWeak(this) : 0;
+ T* otherPtr(other.m_ptr);
+ if (m_ptr) m_refs->decWeak(this);
+ m_ptr = otherPtr;
+ m_refs = newRefs;
+ return *this;
+}
+
+template<typename T> template<typename U>
+wp<T>& wp<T>::operator = (U* other)
+{
+ weakref_type* newRefs =
+ other ? other->createWeak(this) : 0;
+ if (m_ptr) m_refs->decWeak(this);
+ m_ptr = other;
+ m_refs = newRefs;
+ return *this;
+}
+
+template<typename T> template<typename U>
+wp<T>& wp<T>::operator = (const wp<U>& other)
+{
+ weakref_type* otherRefs(other.m_refs);
+ U* otherPtr(other.m_ptr);
+ if (otherPtr) otherRefs->incWeak(this);
+ if (m_ptr) m_refs->decWeak(this);
+ m_ptr = otherPtr;
+ m_refs = otherRefs;
+ return *this;
+}
+
+template<typename T> template<typename U>
+wp<T>& wp<T>::operator = (const sp<U>& other)
+{
+ weakref_type* newRefs =
+ other != NULL ? other->createWeak(this) : 0;
+ U* otherPtr(other.m_ptr);
+ if (m_ptr) m_refs->decWeak(this);
+ m_ptr = otherPtr;
+ m_refs = newRefs;
+ return *this;
+}
+
+template<typename T>
+void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
+{
+ if (other) refs->incWeak(this);
+ if (m_ptr) m_refs->decWeak(this);
+ m_ptr = other;
+ m_refs = refs;
+}
+
+template<typename T>
+sp<T> wp<T>::promote() const
+{
+ sp<T> result;
+ if (m_ptr && m_refs->attemptIncStrong(&result)) {
+ result.set_pointer(m_ptr);
+ }
+ return result;
+}
+
+template<typename T>
+void wp<T>::clear()
+{
+ if (m_ptr) {
+ m_refs->decWeak(this);
+ m_ptr = 0;
+ }
+}
+
+template <typename T>
+inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
+{
+ return printWeakPointer(to, val.unsafe_get());
+}
+
+// ---------------------------------------------------------------------------
+
+// this class just serves as a namespace so TYPE::moveReferences can stay
+// private.
+
+class ReferenceMover {
+ // StrongReferenceCast and WeakReferenceCast do the impedance matching
+ // between the generic (void*) implementation in Refbase and the strongly typed
+ // template specializations below.
+
+ template <typename TYPE>
+ struct StrongReferenceCast : public ReferenceConverterBase {
+ virtual size_t getReferenceTypeSize() const { return sizeof( sp<TYPE> ); }
+ virtual void* getReferenceBase(void const* p) const {
+ sp<TYPE> const* sptr(reinterpret_cast<sp<TYPE> const*>(p));
+ return static_cast<typename TYPE::basetype *>(sptr->get());
+ }
+ };
+
+ template <typename TYPE>
+ struct WeakReferenceCast : public ReferenceConverterBase {
+ virtual size_t getReferenceTypeSize() const { return sizeof( wp<TYPE> ); }
+ virtual void* getReferenceBase(void const* p) const {
+ wp<TYPE> const* sptr(reinterpret_cast<wp<TYPE> const*>(p));
+ return static_cast<typename TYPE::basetype *>(sptr->unsafe_get());
+ }
+ };
+
+public:
+ template<typename TYPE> static inline
+ void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
+ memmove(d, s, n*sizeof(sp<TYPE>));
+ StrongReferenceCast<TYPE> caster;
+ TYPE::moveReferences(d, s, n, caster);
+ }
+ template<typename TYPE> static inline
+ void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
+ memmove(d, s, n*sizeof(wp<TYPE>));
+ WeakReferenceCast<TYPE> caster;
+ TYPE::moveReferences(d, s, n, caster);
+ }
+};
+
+// specialization for moving sp<> and wp<> types.
+// these are used by the [Sorted|Keyed]Vector<> implementations
+// sp<> and wp<> need to be handled specially, because they do not
+// have trivial copy operation in the general case (see RefBase.cpp
+// when DEBUG ops are enabled), but can be implemented very
+// efficiently in most cases.
+
+template<typename TYPE> inline
+void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
+ ReferenceMover::move_references(d, s, n);
+}
+
+template<typename TYPE> inline
+void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
+ ReferenceMover::move_references(d, s, n);
+}
+
+template<typename TYPE> inline
+void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
+ ReferenceMover::move_references(d, s, n);
+}
+
+template<typename TYPE> inline
+void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
+ ReferenceMover::move_references(d, s, n);
+}
+
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_REF_BASE_H
diff --git a/include/utils/SharedBuffer.h b/include/utils/SharedBuffer.h
new file mode 100644
index 0000000..24508b0
--- /dev/null
+++ b/include/utils/SharedBuffer.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_SHARED_BUFFER_H
+#define ANDROID_SHARED_BUFFER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class SharedBuffer
+{
+public:
+
+ /* flags to use with release() */
+ enum {
+ eKeepStorage = 0x00000001
+ };
+
+ /*! allocate a buffer of size 'size' and acquire() it.
+ * call release() to free it.
+ */
+ static SharedBuffer* alloc(size_t size);
+
+ /*! free the memory associated with the SharedBuffer.
+ * Fails if there are any users associated with this SharedBuffer.
+ * In other words, the buffer must have been release by all its
+ * users.
+ */
+ static ssize_t dealloc(const SharedBuffer* released);
+
+ //! get the SharedBuffer from the data pointer
+ static inline const SharedBuffer* sharedBuffer(const void* data);
+
+ //! access the data for read
+ inline const void* data() const;
+
+ //! access the data for read/write
+ inline void* data();
+
+ //! get size of the buffer
+ inline size_t size() const;
+
+ //! get back a SharedBuffer object from its data
+ static inline SharedBuffer* bufferFromData(void* data);
+
+ //! get back a SharedBuffer object from its data
+ static inline const SharedBuffer* bufferFromData(const void* data);
+
+ //! get the size of a SharedBuffer object from its data
+ static inline size_t sizeFromData(const void* data);
+
+ //! edit the buffer (get a writtable, or non-const, version of it)
+ SharedBuffer* edit() const;
+
+ //! edit the buffer, resizing if needed
+ SharedBuffer* editResize(size_t size) const;
+
+ //! like edit() but fails if a copy is required
+ SharedBuffer* attemptEdit() const;
+
+ //! resize and edit the buffer, loose it's content.
+ SharedBuffer* reset(size_t size) const;
+
+ //! acquire/release a reference on this buffer
+ void acquire() const;
+
+ /*! release a reference on this buffer, with the option of not
+ * freeing the memory associated with it if it was the last reference
+ * returns the previous reference count
+ */
+ int32_t release(uint32_t flags = 0) const;
+
+ //! returns wether or not we're the only owner
+ inline bool onlyOwner() const;
+
+
+private:
+ inline SharedBuffer() { }
+ inline ~SharedBuffer() { }
+ inline SharedBuffer(const SharedBuffer&);
+
+ // 16 bytes. must be sized to preserve correct alingment.
+ mutable int32_t mRefs;
+ size_t mSize;
+ uint32_t mReserved[2];
+};
+
+// ---------------------------------------------------------------------------
+
+const SharedBuffer* SharedBuffer::sharedBuffer(const void* data) {
+ return data ? reinterpret_cast<const SharedBuffer *>(data)-1 : 0;
+}
+
+const void* SharedBuffer::data() const {
+ return this + 1;
+}
+
+void* SharedBuffer::data() {
+ return this + 1;
+}
+
+size_t SharedBuffer::size() const {
+ return mSize;
+}
+
+SharedBuffer* SharedBuffer::bufferFromData(void* data)
+{
+ return ((SharedBuffer*)data)-1;
+}
+
+const SharedBuffer* SharedBuffer::bufferFromData(const void* data)
+{
+ return ((const SharedBuffer*)data)-1;
+}
+
+size_t SharedBuffer::sizeFromData(const void* data)
+{
+ return (((const SharedBuffer*)data)-1)->mSize;
+}
+
+bool SharedBuffer::onlyOwner() const {
+ return (mRefs == 1);
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_VECTOR_H
diff --git a/include/utils/Singleton.h b/include/utils/Singleton.h
new file mode 100644
index 0000000..a42ce21
--- /dev/null
+++ b/include/utils/Singleton.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef ANDROID_UTILS_SINGLETON_H
+#define ANDROID_UTILS_SINGLETON_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/threads.h>
+#include <cutils/compiler.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+template <typename TYPE>
+class ANDROID_API Singleton
+{
+public:
+ static TYPE& getInstance() {
+ Mutex::Autolock _l(sLock);
+ TYPE* instance = sInstance;
+ if (instance == 0) {
+ instance = new TYPE();
+ sInstance = instance;
+ }
+ return *instance;
+ }
+
+ static bool hasInstance() {
+ Mutex::Autolock _l(sLock);
+ return sInstance != 0;
+ }
+
+protected:
+ ~Singleton() { };
+ Singleton() { };
+
+private:
+ Singleton(const Singleton&);
+ Singleton& operator = (const Singleton&);
+ static Mutex sLock;
+ static TYPE* sInstance;
+};
+
+/*
+ * use ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) in your implementation file
+ * (eg: <TYPE>.cpp) to create the static instance of Singleton<>'s attributes,
+ * and avoid to have a copy of them in each compilation units Singleton<TYPE>
+ * is used.
+ * NOTE: we use a version of Mutex ctor that takes a parameter, because
+ * for some unknown reason using the default ctor doesn't emit the variable!
+ */
+
+#define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) \
+ template class Singleton< TYPE >; \
+ template<> Mutex Singleton< TYPE >::sLock(Mutex::PRIVATE); \
+ template<> TYPE* Singleton< TYPE >::sInstance(0);
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_UTILS_SINGLETON_H
+
diff --git a/include/utils/SortedVector.h b/include/utils/SortedVector.h
new file mode 100644
index 0000000..2445525
--- /dev/null
+++ b/include/utils/SortedVector.h
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_SORTED_VECTOR_H
+#define ANDROID_SORTED_VECTOR_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Vector.h>
+#include <utils/VectorImpl.h>
+#include <utils/TypeHelpers.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+template <class TYPE>
+class SortedVector : private SortedVectorImpl
+{
+ friend class Vector<TYPE>;
+
+public:
+ typedef TYPE value_type;
+
+ /*!
+ * Constructors and destructors
+ */
+
+ SortedVector();
+ SortedVector(const SortedVector<TYPE>& rhs);
+ virtual ~SortedVector();
+
+ /*! copy operator */
+ const SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
+ SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
+
+ /*
+ * empty the vector
+ */
+
+ inline void clear() { VectorImpl::clear(); }
+
+ /*!
+ * vector stats
+ */
+
+ //! returns number of items in the vector
+ inline size_t size() const { return VectorImpl::size(); }
+ //! returns wether or not the vector is empty
+ inline bool isEmpty() const { return VectorImpl::isEmpty(); }
+ //! returns how many items can be stored without reallocating the backing store
+ inline size_t capacity() const { return VectorImpl::capacity(); }
+ //! setst the capacity. capacity can never be reduced less than size()
+ inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); }
+
+ /*!
+ * C-style array access
+ */
+
+ //! read-only C-style access
+ inline const TYPE* array() const;
+
+ //! read-write C-style access. BE VERY CAREFUL when modifying the array
+ //! you ust keep it sorted! You usually don't use this function.
+ TYPE* editArray();
+
+ //! finds the index of an item
+ ssize_t indexOf(const TYPE& item) const;
+
+ //! finds where this item should be inserted
+ size_t orderOf(const TYPE& item) const;
+
+
+ /*!
+ * accessors
+ */
+
+ //! read-only access to an item at a given index
+ inline const TYPE& operator [] (size_t index) const;
+ //! alternate name for operator []
+ inline const TYPE& itemAt(size_t index) const;
+ //! stack-usage of the vector. returns the top of the stack (last element)
+ const TYPE& top() const;
+ //! same as operator [], but allows to access the vector backward (from the end) with a negative index
+ const TYPE& mirrorItemAt(ssize_t index) const;
+
+ /*!
+ * modifing the array
+ */
+
+ //! add an item in the right place (and replace the one that is there)
+ ssize_t add(const TYPE& item);
+
+ //! editItemAt() MUST NOT change the order of this item
+ TYPE& editItemAt(size_t index) {
+ return *( static_cast<TYPE *>(VectorImpl::editItemLocation(index)) );
+ }
+
+ //! merges a vector into this one
+ ssize_t merge(const Vector<TYPE>& vector);
+ ssize_t merge(const SortedVector<TYPE>& vector);
+
+ //! removes an item
+ ssize_t remove(const TYPE&);
+
+ //! remove several items
+ inline ssize_t removeItemsAt(size_t index, size_t count = 1);
+ //! remove one item
+ inline ssize_t removeAt(size_t index) { return removeItemsAt(index); }
+
+protected:
+ virtual void do_construct(void* storage, size_t num) const;
+ virtual void do_destroy(void* storage, size_t num) const;
+ virtual void do_copy(void* dest, const void* from, size_t num) const;
+ virtual void do_splat(void* dest, const void* item, size_t num) const;
+ virtual void do_move_forward(void* dest, const void* from, size_t num) const;
+ virtual void do_move_backward(void* dest, const void* from, size_t num) const;
+ virtual int do_compare(const void* lhs, const void* rhs) const;
+};
+
+// SortedVector<T> can be trivially moved using memcpy() because moving does not
+// require any change to the underlying SharedBuffer contents or reference count.
+template<typename T> struct trait_trivial_move<SortedVector<T> > { enum { value = true }; };
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts from here...
+// ---------------------------------------------------------------------------
+
+template<class TYPE> inline
+SortedVector<TYPE>::SortedVector()
+ : SortedVectorImpl(sizeof(TYPE),
+ ((traits<TYPE>::has_trivial_ctor ? HAS_TRIVIAL_CTOR : 0)
+ |(traits<TYPE>::has_trivial_dtor ? HAS_TRIVIAL_DTOR : 0)
+ |(traits<TYPE>::has_trivial_copy ? HAS_TRIVIAL_COPY : 0))
+ )
+{
+}
+
+template<class TYPE> inline
+SortedVector<TYPE>::SortedVector(const SortedVector<TYPE>& rhs)
+ : SortedVectorImpl(rhs) {
+}
+
+template<class TYPE> inline
+SortedVector<TYPE>::~SortedVector() {
+ finish_vector();
+}
+
+template<class TYPE> inline
+SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
+ SortedVectorImpl::operator = (rhs);
+ return *this;
+}
+
+template<class TYPE> inline
+const SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
+ SortedVectorImpl::operator = (rhs);
+ return *this;
+}
+
+template<class TYPE> inline
+const TYPE* SortedVector<TYPE>::array() const {
+ return static_cast<const TYPE *>(arrayImpl());
+}
+
+template<class TYPE> inline
+TYPE* SortedVector<TYPE>::editArray() {
+ return static_cast<TYPE *>(editArrayImpl());
+}
+
+
+template<class TYPE> inline
+const TYPE& SortedVector<TYPE>::operator[](size_t index) const {
+ assert( index<size() );
+ return *(array() + index);
+}
+
+template<class TYPE> inline
+const TYPE& SortedVector<TYPE>::itemAt(size_t index) const {
+ return operator[](index);
+}
+
+template<class TYPE> inline
+const TYPE& SortedVector<TYPE>::mirrorItemAt(ssize_t index) const {
+ assert( (index>0 ? index : -index)<size() );
+ return *(array() + ((index<0) ? (size()-index) : index));
+}
+
+template<class TYPE> inline
+const TYPE& SortedVector<TYPE>::top() const {
+ return *(array() + size() - 1);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::add(const TYPE& item) {
+ return SortedVectorImpl::add(&item);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::indexOf(const TYPE& item) const {
+ return SortedVectorImpl::indexOf(&item);
+}
+
+template<class TYPE> inline
+size_t SortedVector<TYPE>::orderOf(const TYPE& item) const {
+ return SortedVectorImpl::orderOf(&item);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::merge(const Vector<TYPE>& vector) {
+ return SortedVectorImpl::merge(reinterpret_cast<const VectorImpl&>(vector));
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::merge(const SortedVector<TYPE>& vector) {
+ return SortedVectorImpl::merge(reinterpret_cast<const SortedVectorImpl&>(vector));
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::remove(const TYPE& item) {
+ return SortedVectorImpl::remove(&item);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::removeItemsAt(size_t index, size_t count) {
+ return VectorImpl::removeItemsAt(index, count);
+}
+
+// ---------------------------------------------------------------------------
+
+template<class TYPE>
+void SortedVector<TYPE>::do_construct(void* storage, size_t num) const {
+ construct_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_destroy(void* storage, size_t num) const {
+ destroy_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
+ copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
+ splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
+ move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
+ move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+int SortedVector<TYPE>::do_compare(const void* lhs, const void* rhs) const {
+ return compare_type( *reinterpret_cast<const TYPE*>(lhs), *reinterpret_cast<const TYPE*>(rhs) );
+}
+
+}; // namespace android
+
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_SORTED_VECTOR_H
diff --git a/include/utils/StopWatch.h b/include/utils/StopWatch.h
new file mode 100644
index 0000000..693dd3c
--- /dev/null
+++ b/include/utils/StopWatch.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_STOPWATCH_H
+#define ANDROID_STOPWATCH_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Timers.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class StopWatch
+{
+public:
+ StopWatch( const char *name,
+ int clock = SYSTEM_TIME_MONOTONIC,
+ uint32_t flags = 0);
+ ~StopWatch();
+
+ const char* name() const;
+ nsecs_t lap();
+ nsecs_t elapsedTime() const;
+
+ void reset();
+
+private:
+ const char* mName;
+ int mClock;
+ uint32_t mFlags;
+
+ struct lap_t {
+ nsecs_t soFar;
+ nsecs_t thisLap;
+ };
+
+ nsecs_t mStartTime;
+ lap_t mLaps[8];
+ int mNumLaps;
+};
+
+
+}; // namespace android
+
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_STOPWATCH_H
diff --git a/include/utils/String16.h b/include/utils/String16.h
new file mode 100644
index 0000000..fe06c57
--- /dev/null
+++ b/include/utils/String16.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_STRING16_H
+#define ANDROID_STRING16_H
+
+#include <utils/Errors.h>
+#include <utils/SharedBuffer.h>
+#include <utils/Unicode.h>
+#include <utils/TypeHelpers.h>
+
+// ---------------------------------------------------------------------------
+
+extern "C" {
+
+}
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class String8;
+class TextOutput;
+
+//! This is a string holding UTF-16 characters.
+class String16
+{
+public:
+ String16();
+ String16(const String16& o);
+ String16(const String16& o,
+ size_t len,
+ size_t begin=0);
+ explicit String16(const char16_t* o);
+ explicit String16(const char16_t* o, size_t len);
+ explicit String16(const String8& o);
+ explicit String16(const char* o);
+ explicit String16(const char* o, size_t len);
+
+ ~String16();
+
+ inline const char16_t* string() const;
+ inline size_t size() const;
+
+ inline const SharedBuffer* sharedBuffer() const;
+
+ void setTo(const String16& other);
+ status_t setTo(const char16_t* other);
+ status_t setTo(const char16_t* other, size_t len);
+ status_t setTo(const String16& other,
+ size_t len,
+ size_t begin=0);
+
+ status_t append(const String16& other);
+ status_t append(const char16_t* other, size_t len);
+
+ inline String16& operator=(const String16& other);
+
+ inline String16& operator+=(const String16& other);
+ inline String16 operator+(const String16& other) const;
+
+ status_t insert(size_t pos, const char16_t* chrs);
+ status_t insert(size_t pos,
+ const char16_t* chrs, size_t len);
+
+ ssize_t findFirst(char16_t c) const;
+ ssize_t findLast(char16_t c) const;
+
+ bool startsWith(const String16& prefix) const;
+ bool startsWith(const char16_t* prefix) const;
+
+ status_t makeLower();
+
+ status_t replaceAll(char16_t replaceThis,
+ char16_t withThis);
+
+ status_t remove(size_t len, size_t begin=0);
+
+ inline int compare(const String16& other) const;
+
+ inline bool operator<(const String16& other) const;
+ inline bool operator<=(const String16& other) const;
+ inline bool operator==(const String16& other) const;
+ inline bool operator!=(const String16& other) const;
+ inline bool operator>=(const String16& other) const;
+ inline bool operator>(const String16& other) const;
+
+ inline bool operator<(const char16_t* other) const;
+ inline bool operator<=(const char16_t* other) const;
+ inline bool operator==(const char16_t* other) const;
+ inline bool operator!=(const char16_t* other) const;
+ inline bool operator>=(const char16_t* other) const;
+ inline bool operator>(const char16_t* other) const;
+
+ inline operator const char16_t*() const;
+
+private:
+ const char16_t* mString;
+};
+
+// String16 can be trivially moved using memcpy() because moving does not
+// require any change to the underlying SharedBuffer contents or reference count.
+ANDROID_TRIVIAL_MOVE_TRAIT(String16)
+
+TextOutput& operator<<(TextOutput& to, const String16& val);
+
+// ---------------------------------------------------------------------------
+// No user servicable parts below.
+
+inline int compare_type(const String16& lhs, const String16& rhs)
+{
+ return lhs.compare(rhs);
+}
+
+inline int strictly_order_type(const String16& lhs, const String16& rhs)
+{
+ return compare_type(lhs, rhs) < 0;
+}
+
+inline const char16_t* String16::string() const
+{
+ return mString;
+}
+
+inline size_t String16::size() const
+{
+ return SharedBuffer::sizeFromData(mString)/sizeof(char16_t)-1;
+}
+
+inline const SharedBuffer* String16::sharedBuffer() const
+{
+ return SharedBuffer::bufferFromData(mString);
+}
+
+inline String16& String16::operator=(const String16& other)
+{
+ setTo(other);
+ return *this;
+}
+
+inline String16& String16::operator+=(const String16& other)
+{
+ append(other);
+ return *this;
+}
+
+inline String16 String16::operator+(const String16& other) const
+{
+ String16 tmp(*this);
+ tmp += other;
+ return tmp;
+}
+
+inline int String16::compare(const String16& other) const
+{
+ return strzcmp16(mString, size(), other.mString, other.size());
+}
+
+inline bool String16::operator<(const String16& other) const
+{
+ return strzcmp16(mString, size(), other.mString, other.size()) < 0;
+}
+
+inline bool String16::operator<=(const String16& other) const
+{
+ return strzcmp16(mString, size(), other.mString, other.size()) <= 0;
+}
+
+inline bool String16::operator==(const String16& other) const
+{
+ return strzcmp16(mString, size(), other.mString, other.size()) == 0;
+}
+
+inline bool String16::operator!=(const String16& other) const
+{
+ return strzcmp16(mString, size(), other.mString, other.size()) != 0;
+}
+
+inline bool String16::operator>=(const String16& other) const
+{
+ return strzcmp16(mString, size(), other.mString, other.size()) >= 0;
+}
+
+inline bool String16::operator>(const String16& other) const
+{
+ return strzcmp16(mString, size(), other.mString, other.size()) > 0;
+}
+
+inline bool String16::operator<(const char16_t* other) const
+{
+ return strcmp16(mString, other) < 0;
+}
+
+inline bool String16::operator<=(const char16_t* other) const
+{
+ return strcmp16(mString, other) <= 0;
+}
+
+inline bool String16::operator==(const char16_t* other) const
+{
+ return strcmp16(mString, other) == 0;
+}
+
+inline bool String16::operator!=(const char16_t* other) const
+{
+ return strcmp16(mString, other) != 0;
+}
+
+inline bool String16::operator>=(const char16_t* other) const
+{
+ return strcmp16(mString, other) >= 0;
+}
+
+inline bool String16::operator>(const char16_t* other) const
+{
+ return strcmp16(mString, other) > 0;
+}
+
+inline String16::operator const char16_t*() const
+{
+ return mString;
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_STRING16_H
diff --git a/include/utils/String8.h b/include/utils/String8.h
new file mode 100644
index 0000000..335e7f1
--- /dev/null
+++ b/include/utils/String8.h
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_STRING8_H
+#define ANDROID_STRING8_H
+
+#include <utils/Errors.h>
+#include <utils/SharedBuffer.h>
+#include <utils/Unicode.h>
+#include <utils/TypeHelpers.h>
+
+#include <string.h> // for strcmp
+#include <stdarg.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class String16;
+class TextOutput;
+
+//! This is a string holding UTF-8 characters. Does not allow the value more
+// than 0x10FFFF, which is not valid unicode codepoint.
+class String8
+{
+public:
+ String8();
+ String8(const String8& o);
+ explicit String8(const char* o);
+ explicit String8(const char* o, size_t numChars);
+
+ explicit String8(const String16& o);
+ explicit String8(const char16_t* o);
+ explicit String8(const char16_t* o, size_t numChars);
+ explicit String8(const char32_t* o);
+ explicit String8(const char32_t* o, size_t numChars);
+ ~String8();
+
+ static inline const String8 empty();
+
+ static String8 format(const char* fmt, ...) __attribute__((format (printf, 1, 2)));
+ static String8 formatV(const char* fmt, va_list args);
+
+ inline const char* string() const;
+ inline size_t size() const;
+ inline size_t length() const;
+ inline size_t bytes() const;
+ inline bool isEmpty() const;
+
+ inline const SharedBuffer* sharedBuffer() const;
+
+ void clear();
+
+ void setTo(const String8& other);
+ status_t setTo(const char* other);
+ status_t setTo(const char* other, size_t numChars);
+ status_t setTo(const char16_t* other, size_t numChars);
+ status_t setTo(const char32_t* other,
+ size_t length);
+
+ status_t append(const String8& other);
+ status_t append(const char* other);
+ status_t append(const char* other, size_t numChars);
+
+ status_t appendFormat(const char* fmt, ...)
+ __attribute__((format (printf, 2, 3)));
+ status_t appendFormatV(const char* fmt, va_list args);
+
+ // Note that this function takes O(N) time to calculate the value.
+ // No cache value is stored.
+ size_t getUtf32Length() const;
+ int32_t getUtf32At(size_t index,
+ size_t *next_index) const;
+ void getUtf32(char32_t* dst) const;
+
+ inline String8& operator=(const String8& other);
+ inline String8& operator=(const char* other);
+
+ inline String8& operator+=(const String8& other);
+ inline String8 operator+(const String8& other) const;
+
+ inline String8& operator+=(const char* other);
+ inline String8 operator+(const char* other) const;
+
+ inline int compare(const String8& other) const;
+
+ inline bool operator<(const String8& other) const;
+ inline bool operator<=(const String8& other) const;
+ inline bool operator==(const String8& other) const;
+ inline bool operator!=(const String8& other) const;
+ inline bool operator>=(const String8& other) const;
+ inline bool operator>(const String8& other) const;
+
+ inline bool operator<(const char* other) const;
+ inline bool operator<=(const char* other) const;
+ inline bool operator==(const char* other) const;
+ inline bool operator!=(const char* other) const;
+ inline bool operator>=(const char* other) const;
+ inline bool operator>(const char* other) const;
+
+ inline operator const char*() const;
+
+ char* lockBuffer(size_t size);
+ void unlockBuffer();
+ status_t unlockBuffer(size_t size);
+
+ // return the index of the first byte of other in this at or after
+ // start, or -1 if not found
+ ssize_t find(const char* other, size_t start = 0) const;
+
+ void toLower();
+ void toLower(size_t start, size_t numChars);
+ void toUpper();
+ void toUpper(size_t start, size_t numChars);
+
+ /*
+ * These methods operate on the string as if it were a path name.
+ */
+
+ /*
+ * Set the filename field to a specific value.
+ *
+ * Normalizes the filename, removing a trailing '/' if present.
+ */
+ void setPathName(const char* name);
+ void setPathName(const char* name, size_t numChars);
+
+ /*
+ * Get just the filename component.
+ *
+ * "/tmp/foo/bar.c" --> "bar.c"
+ */
+ String8 getPathLeaf(void) const;
+
+ /*
+ * Remove the last (file name) component, leaving just the directory
+ * name.
+ *
+ * "/tmp/foo/bar.c" --> "/tmp/foo"
+ * "/tmp" --> "" // ????? shouldn't this be "/" ???? XXX
+ * "bar.c" --> ""
+ */
+ String8 getPathDir(void) const;
+
+ /*
+ * Retrieve the front (root dir) component. Optionally also return the
+ * remaining components.
+ *
+ * "/tmp/foo/bar.c" --> "tmp" (remain = "foo/bar.c")
+ * "/tmp" --> "tmp" (remain = "")
+ * "bar.c" --> "bar.c" (remain = "")
+ */
+ String8 walkPath(String8* outRemains = NULL) const;
+
+ /*
+ * Return the filename extension. This is the last '.' and any number
+ * of characters that follow it. The '.' is included in case we
+ * decide to expand our definition of what constitutes an extension.
+ *
+ * "/tmp/foo/bar.c" --> ".c"
+ * "/tmp" --> ""
+ * "/tmp/foo.bar/baz" --> ""
+ * "foo.jpeg" --> ".jpeg"
+ * "foo." --> ""
+ */
+ String8 getPathExtension(void) const;
+
+ /*
+ * Return the path without the extension. Rules for what constitutes
+ * an extension are described in the comment for getPathExtension().
+ *
+ * "/tmp/foo/bar.c" --> "/tmp/foo/bar"
+ */
+ String8 getBasePath(void) const;
+
+ /*
+ * Add a component to the pathname. We guarantee that there is
+ * exactly one path separator between the old path and the new.
+ * If there is no existing name, we just copy the new name in.
+ *
+ * If leaf is a fully qualified path (i.e. starts with '/', it
+ * replaces whatever was there before.
+ */
+ String8& appendPath(const char* leaf);
+ String8& appendPath(const String8& leaf) { return appendPath(leaf.string()); }
+
+ /*
+ * Like appendPath(), but does not affect this string. Returns a new one instead.
+ */
+ String8 appendPathCopy(const char* leaf) const
+ { String8 p(*this); p.appendPath(leaf); return p; }
+ String8 appendPathCopy(const String8& leaf) const { return appendPathCopy(leaf.string()); }
+
+ /*
+ * Converts all separators in this string to /, the default path separator.
+ *
+ * If the default OS separator is backslash, this converts all
+ * backslashes to slashes, in-place. Otherwise it does nothing.
+ * Returns self.
+ */
+ String8& convertToResPath();
+
+private:
+ status_t real_append(const char* other, size_t numChars);
+ char* find_extension(void) const;
+
+ const char* mString;
+};
+
+// String8 can be trivially moved using memcpy() because moving does not
+// require any change to the underlying SharedBuffer contents or reference count.
+ANDROID_TRIVIAL_MOVE_TRAIT(String8)
+
+TextOutput& operator<<(TextOutput& to, const String16& val);
+
+// ---------------------------------------------------------------------------
+// No user servicable parts below.
+
+inline int compare_type(const String8& lhs, const String8& rhs)
+{
+ return lhs.compare(rhs);
+}
+
+inline int strictly_order_type(const String8& lhs, const String8& rhs)
+{
+ return compare_type(lhs, rhs) < 0;
+}
+
+inline const String8 String8::empty() {
+ return String8();
+}
+
+inline const char* String8::string() const
+{
+ return mString;
+}
+
+inline size_t String8::length() const
+{
+ return SharedBuffer::sizeFromData(mString)-1;
+}
+
+inline size_t String8::size() const
+{
+ return length();
+}
+
+inline bool String8::isEmpty() const
+{
+ return length() == 0;
+}
+
+inline size_t String8::bytes() const
+{
+ return SharedBuffer::sizeFromData(mString)-1;
+}
+
+inline const SharedBuffer* String8::sharedBuffer() const
+{
+ return SharedBuffer::bufferFromData(mString);
+}
+
+inline String8& String8::operator=(const String8& other)
+{
+ setTo(other);
+ return *this;
+}
+
+inline String8& String8::operator=(const char* other)
+{
+ setTo(other);
+ return *this;
+}
+
+inline String8& String8::operator+=(const String8& other)
+{
+ append(other);
+ return *this;
+}
+
+inline String8 String8::operator+(const String8& other) const
+{
+ String8 tmp(*this);
+ tmp += other;
+ return tmp;
+}
+
+inline String8& String8::operator+=(const char* other)
+{
+ append(other);
+ return *this;
+}
+
+inline String8 String8::operator+(const char* other) const
+{
+ String8 tmp(*this);
+ tmp += other;
+ return tmp;
+}
+
+inline int String8::compare(const String8& other) const
+{
+ return strcmp(mString, other.mString);
+}
+
+inline bool String8::operator<(const String8& other) const
+{
+ return strcmp(mString, other.mString) < 0;
+}
+
+inline bool String8::operator<=(const String8& other) const
+{
+ return strcmp(mString, other.mString) <= 0;
+}
+
+inline bool String8::operator==(const String8& other) const
+{
+ return strcmp(mString, other.mString) == 0;
+}
+
+inline bool String8::operator!=(const String8& other) const
+{
+ return strcmp(mString, other.mString) != 0;
+}
+
+inline bool String8::operator>=(const String8& other) const
+{
+ return strcmp(mString, other.mString) >= 0;
+}
+
+inline bool String8::operator>(const String8& other) const
+{
+ return strcmp(mString, other.mString) > 0;
+}
+
+inline bool String8::operator<(const char* other) const
+{
+ return strcmp(mString, other) < 0;
+}
+
+inline bool String8::operator<=(const char* other) const
+{
+ return strcmp(mString, other) <= 0;
+}
+
+inline bool String8::operator==(const char* other) const
+{
+ return strcmp(mString, other) == 0;
+}
+
+inline bool String8::operator!=(const char* other) const
+{
+ return strcmp(mString, other) != 0;
+}
+
+inline bool String8::operator>=(const char* other) const
+{
+ return strcmp(mString, other) >= 0;
+}
+
+inline bool String8::operator>(const char* other) const
+{
+ return strcmp(mString, other) > 0;
+}
+
+inline String8::operator const char*() const
+{
+ return mString;
+}
+
+} // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_STRING8_H
diff --git a/include/utils/StringArray.h b/include/utils/StringArray.h
new file mode 100644
index 0000000..c244587
--- /dev/null
+++ b/include/utils/StringArray.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+//
+// Sortable array of strings. STL-ish, but STL-free.
+//
+#ifndef _LIBS_UTILS_STRING_ARRAY_H
+#define _LIBS_UTILS_STRING_ARRAY_H
+
+#include <stdlib.h>
+#include <string.h>
+
+namespace android {
+
+//
+// An expanding array of strings. Add, get, sort, delete.
+//
+class StringArray {
+public:
+ StringArray();
+ virtual ~StringArray();
+
+ //
+ // Add a string. A copy of the string is made.
+ //
+ bool push_back(const char* str);
+
+ //
+ // Delete an entry.
+ //
+ void erase(int idx);
+
+ //
+ // Sort the array.
+ //
+ void sort(int (*compare)(const void*, const void*));
+
+ //
+ // Pass this to the sort routine to do an ascending alphabetical sort.
+ //
+ static int cmpAscendingAlpha(const void* pstr1, const void* pstr2);
+
+ //
+ // Get the #of items in the array.
+ //
+ inline int size(void) const { return mCurrent; }
+
+ //
+ // Return entry N.
+ // [should use operator[] here]
+ //
+ const char* getEntry(int idx) const {
+ return (unsigned(idx) >= unsigned(mCurrent)) ? NULL : mArray[idx];
+ }
+
+ //
+ // Set entry N to specified string.
+ // [should use operator[] here]
+ //
+ void setEntry(int idx, const char* str);
+
+private:
+ int mMax;
+ int mCurrent;
+ char** mArray;
+};
+
+}; // namespace android
+
+#endif // _LIBS_UTILS_STRING_ARRAY_H
diff --git a/include/utils/StrongPointer.h b/include/utils/StrongPointer.h
new file mode 100644
index 0000000..49fa3a8
--- /dev/null
+++ b/include/utils/StrongPointer.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_STRONG_POINTER_H
+#define ANDROID_STRONG_POINTER_H
+
+#include <cutils/atomic.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class TextOutput;
+TextOutput& printStrongPointer(TextOutput& to, const void* val);
+
+template<typename T> class wp;
+
+// ---------------------------------------------------------------------------
+
+#define COMPARE(_op_) \
+inline bool operator _op_ (const sp<T>& o) const { \
+ return m_ptr _op_ o.m_ptr; \
+} \
+inline bool operator _op_ (const T* o) const { \
+ return m_ptr _op_ o; \
+} \
+template<typename U> \
+inline bool operator _op_ (const sp<U>& o) const { \
+ return m_ptr _op_ o.m_ptr; \
+} \
+template<typename U> \
+inline bool operator _op_ (const U* o) const { \
+ return m_ptr _op_ o; \
+} \
+inline bool operator _op_ (const wp<T>& o) const { \
+ return m_ptr _op_ o.m_ptr; \
+} \
+template<typename U> \
+inline bool operator _op_ (const wp<U>& o) const { \
+ return m_ptr _op_ o.m_ptr; \
+}
+
+// ---------------------------------------------------------------------------
+
+template <typename T>
+class sp
+{
+public:
+ inline sp() : m_ptr(0) { }
+
+ sp(T* other);
+ sp(const sp<T>& other);
+ template<typename U> sp(U* other);
+ template<typename U> sp(const sp<U>& other);
+
+ ~sp();
+
+ // Assignment
+
+ sp& operator = (T* other);
+ sp& operator = (const sp<T>& other);
+
+ template<typename U> sp& operator = (const sp<U>& other);
+ template<typename U> sp& operator = (U* other);
+
+ //! Special optimization for use by ProcessState (and nobody else).
+ void force_set(T* other);
+
+ // Reset
+
+ void clear();
+
+ // Accessors
+
+ inline T& operator* () const { return *m_ptr; }
+ inline T* operator-> () const { return m_ptr; }
+ inline T* get() const { return m_ptr; }
+
+ // Operators
+
+ COMPARE(==)
+ COMPARE(!=)
+ COMPARE(>)
+ COMPARE(<)
+ COMPARE(<=)
+ COMPARE(>=)
+
+private:
+ template<typename Y> friend class sp;
+ template<typename Y> friend class wp;
+ void set_pointer(T* ptr);
+ T* m_ptr;
+};
+
+#undef COMPARE
+
+template <typename T>
+TextOutput& operator<<(TextOutput& to, const sp<T>& val);
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts below here.
+
+template<typename T>
+sp<T>::sp(T* other)
+: m_ptr(other)
+ {
+ if (other) other->incStrong(this);
+ }
+
+template<typename T>
+sp<T>::sp(const sp<T>& other)
+: m_ptr(other.m_ptr)
+ {
+ if (m_ptr) m_ptr->incStrong(this);
+ }
+
+template<typename T> template<typename U>
+sp<T>::sp(U* other) : m_ptr(other)
+{
+ if (other) ((T*)other)->incStrong(this);
+}
+
+template<typename T> template<typename U>
+sp<T>::sp(const sp<U>& other)
+: m_ptr(other.m_ptr)
+ {
+ if (m_ptr) m_ptr->incStrong(this);
+ }
+
+template<typename T>
+sp<T>::~sp()
+{
+ if (m_ptr) m_ptr->decStrong(this);
+}
+
+template<typename T>
+sp<T>& sp<T>::operator = (const sp<T>& other) {
+ T* otherPtr(other.m_ptr);
+ if (otherPtr) otherPtr->incStrong(this);
+ if (m_ptr) m_ptr->decStrong(this);
+ m_ptr = otherPtr;
+ return *this;
+}
+
+template<typename T>
+sp<T>& sp<T>::operator = (T* other)
+{
+ if (other) other->incStrong(this);
+ if (m_ptr) m_ptr->decStrong(this);
+ m_ptr = other;
+ return *this;
+}
+
+template<typename T> template<typename U>
+sp<T>& sp<T>::operator = (const sp<U>& other)
+{
+ T* otherPtr(other.m_ptr);
+ if (otherPtr) otherPtr->incStrong(this);
+ if (m_ptr) m_ptr->decStrong(this);
+ m_ptr = otherPtr;
+ return *this;
+}
+
+template<typename T> template<typename U>
+sp<T>& sp<T>::operator = (U* other)
+{
+ if (other) ((T*)other)->incStrong(this);
+ if (m_ptr) m_ptr->decStrong(this);
+ m_ptr = other;
+ return *this;
+}
+
+template<typename T>
+void sp<T>::force_set(T* other)
+{
+ other->forceIncStrong(this);
+ m_ptr = other;
+}
+
+template<typename T>
+void sp<T>::clear()
+{
+ if (m_ptr) {
+ m_ptr->decStrong(this);
+ m_ptr = 0;
+ }
+}
+
+template<typename T>
+void sp<T>::set_pointer(T* ptr) {
+ m_ptr = ptr;
+}
+
+template <typename T>
+inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
+{
+ return printStrongPointer(to, val.get());
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_STRONG_POINTER_H
diff --git a/include/utils/SystemClock.h b/include/utils/SystemClock.h
new file mode 100644
index 0000000..7c319be
--- /dev/null
+++ b/include/utils/SystemClock.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 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.
+ * 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.
+ */
+
+#ifndef ANDROID_UTILS_SYSTEMCLOCK_H
+#define ANDROID_UTILS_SYSTEMCLOCK_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace android {
+
+int setCurrentTimeMillis(int64_t millis);
+int64_t uptimeMillis();
+int64_t elapsedRealtime();
+
+}; // namespace android
+
+#endif // ANDROID_UTILS_SYSTEMCLOCK_H
+
diff --git a/include/utils/TextOutput.h b/include/utils/TextOutput.h
new file mode 100644
index 0000000..de2fbbe
--- /dev/null
+++ b/include/utils/TextOutput.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#ifndef ANDROID_TEXTOUTPUT_H
+#define ANDROID_TEXTOUTPUT_H
+
+#include <utils/Errors.h>
+
+#include <stdint.h>
+#include <string.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class TextOutput
+{
+public:
+ TextOutput();
+ virtual ~TextOutput();
+
+ virtual status_t print(const char* txt, size_t len) = 0;
+ virtual void moveIndent(int delta) = 0;
+
+ class Bundle {
+ public:
+ inline Bundle(TextOutput& to) : mTO(to) { to.pushBundle(); }
+ inline ~Bundle() { mTO.popBundle(); }
+ private:
+ TextOutput& mTO;
+ };
+
+ virtual void pushBundle() = 0;
+ virtual void popBundle() = 0;
+};
+
+// ---------------------------------------------------------------------------
+
+// Text output stream for printing to the log (via utils/Log.h).
+extern TextOutput& alog;
+
+// Text output stream for printing to stdout.
+extern TextOutput& aout;
+
+// Text output stream for printing to stderr.
+extern TextOutput& aerr;
+
+typedef TextOutput& (*TextOutputManipFunc)(TextOutput&);
+
+TextOutput& endl(TextOutput& to);
+TextOutput& indent(TextOutput& to);
+TextOutput& dedent(TextOutput& to);
+
+TextOutput& operator<<(TextOutput& to, const char* str);
+TextOutput& operator<<(TextOutput& to, char); // writes raw character
+TextOutput& operator<<(TextOutput& to, bool);
+TextOutput& operator<<(TextOutput& to, int);
+TextOutput& operator<<(TextOutput& to, long);
+TextOutput& operator<<(TextOutput& to, unsigned int);
+TextOutput& operator<<(TextOutput& to, unsigned long);
+TextOutput& operator<<(TextOutput& to, long long);
+TextOutput& operator<<(TextOutput& to, unsigned long long);
+TextOutput& operator<<(TextOutput& to, float);
+TextOutput& operator<<(TextOutput& to, double);
+TextOutput& operator<<(TextOutput& to, TextOutputManipFunc func);
+TextOutput& operator<<(TextOutput& to, const void*);
+
+class TypeCode
+{
+public:
+ inline TypeCode(uint32_t code);
+ inline ~TypeCode();
+
+ inline uint32_t typeCode() const;
+
+private:
+ uint32_t mCode;
+};
+
+TextOutput& operator<<(TextOutput& to, const TypeCode& val);
+
+class HexDump
+{
+public:
+ HexDump(const void *buf, size_t size, size_t bytesPerLine=16);
+ inline ~HexDump();
+
+ inline HexDump& setBytesPerLine(size_t bytesPerLine);
+ inline HexDump& setSingleLineCutoff(int32_t bytes);
+ inline HexDump& setAlignment(size_t alignment);
+ inline HexDump& setCArrayStyle(bool enabled);
+
+ inline const void* buffer() const;
+ inline size_t size() const;
+ inline size_t bytesPerLine() const;
+ inline int32_t singleLineCutoff() const;
+ inline size_t alignment() const;
+ inline bool carrayStyle() const;
+
+private:
+ const void* mBuffer;
+ size_t mSize;
+ size_t mBytesPerLine;
+ int32_t mSingleLineCutoff;
+ size_t mAlignment;
+ bool mCArrayStyle;
+};
+
+TextOutput& operator<<(TextOutput& to, const HexDump& val);
+
+// ---------------------------------------------------------------------------
+// No user servicable parts below.
+
+inline TextOutput& endl(TextOutput& to)
+{
+ to.print("\n", 1);
+ return to;
+}
+
+inline TextOutput& indent(TextOutput& to)
+{
+ to.moveIndent(1);
+ return to;
+}
+
+inline TextOutput& dedent(TextOutput& to)
+{
+ to.moveIndent(-1);
+ return to;
+}
+
+inline TextOutput& operator<<(TextOutput& to, const char* str)
+{
+ to.print(str, strlen(str));
+ return to;
+}
+
+inline TextOutput& operator<<(TextOutput& to, char c)
+{
+ to.print(&c, 1);
+ return to;
+}
+
+inline TextOutput& operator<<(TextOutput& to, TextOutputManipFunc func)
+{
+ return (*func)(to);
+}
+
+inline TypeCode::TypeCode(uint32_t code) : mCode(code) { }
+inline TypeCode::~TypeCode() { }
+inline uint32_t TypeCode::typeCode() const { return mCode; }
+
+inline HexDump::~HexDump() { }
+
+inline HexDump& HexDump::setBytesPerLine(size_t bytesPerLine) {
+ mBytesPerLine = bytesPerLine; return *this;
+}
+inline HexDump& HexDump::setSingleLineCutoff(int32_t bytes) {
+ mSingleLineCutoff = bytes; return *this;
+}
+inline HexDump& HexDump::setAlignment(size_t alignment) {
+ mAlignment = alignment; return *this;
+}
+inline HexDump& HexDump::setCArrayStyle(bool enabled) {
+ mCArrayStyle = enabled; return *this;
+}
+
+inline const void* HexDump::buffer() const { return mBuffer; }
+inline size_t HexDump::size() const { return mSize; }
+inline size_t HexDump::bytesPerLine() const { return mBytesPerLine; }
+inline int32_t HexDump::singleLineCutoff() const { return mSingleLineCutoff; }
+inline size_t HexDump::alignment() const { return mAlignment; }
+inline bool HexDump::carrayStyle() const { return mCArrayStyle; }
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_TEXTOUTPUT_H
diff --git a/include/utils/Thread.h b/include/utils/Thread.h
new file mode 100644
index 0000000..4a34abd
--- /dev/null
+++ b/include/utils/Thread.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef _LIBS_UTILS_THREAD_H
+#define _LIBS_UTILS_THREAD_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/Condition.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/ThreadDefs.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class Thread : virtual public RefBase
+{
+public:
+ // Create a Thread object, but doesn't create or start the associated
+ // thread. See the run() method.
+ Thread(bool canCallJava = true);
+ virtual ~Thread();
+
+ // Start the thread in threadLoop() which needs to be implemented.
+ virtual status_t run( const char* name = 0,
+ int32_t priority = PRIORITY_DEFAULT,
+ size_t stack = 0);
+
+ // Ask this object's thread to exit. This function is asynchronous, when the
+ // function returns the thread might still be running. Of course, this
+ // function can be called from a different thread.
+ virtual void requestExit();
+
+ // Good place to do one-time initializations
+ virtual status_t readyToRun();
+
+ // Call requestExit() and wait until this object's thread exits.
+ // BE VERY CAREFUL of deadlocks. In particular, it would be silly to call
+ // this function from this object's thread. Will return WOULD_BLOCK in
+ // that case.
+ status_t requestExitAndWait();
+
+ // Wait until this object's thread exits. Returns immediately if not yet running.
+ // Do not call from this object's thread; will return WOULD_BLOCK in that case.
+ status_t join();
+
+#ifdef HAVE_ANDROID_OS
+ // Return the thread's kernel ID, same as the thread itself calling gettid() or
+ // androidGetTid(), or -1 if the thread is not running.
+ pid_t getTid() const;
+#endif
+
+protected:
+ // exitPending() returns true if requestExit() has been called.
+ bool exitPending() const;
+
+private:
+ // Derived class must implement threadLoop(). The thread starts its life
+ // here. There are two ways of using the Thread object:
+ // 1) loop: if threadLoop() returns true, it will be called again if
+ // requestExit() wasn't called.
+ // 2) once: if threadLoop() returns false, the thread will exit upon return.
+ virtual bool threadLoop() = 0;
+
+private:
+ Thread& operator=(const Thread&);
+ static int _threadLoop(void* user);
+ const bool mCanCallJava;
+ // always hold mLock when reading or writing
+ thread_id_t mThread;
+ mutable Mutex mLock;
+ Condition mThreadExitedCondition;
+ status_t mStatus;
+ // note that all accesses of mExitPending and mRunning need to hold mLock
+ volatile bool mExitPending;
+ volatile bool mRunning;
+ sp<Thread> mHoldSelf;
+#ifdef HAVE_ANDROID_OS
+ // legacy for debugging, not used by getTid() as it is set by the child thread
+ // and so is not initialized until the child reaches that point
+ pid_t mTid;
+#endif
+};
+
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+#endif // _LIBS_UTILS_THREAD_H
+// ---------------------------------------------------------------------------
diff --git a/include/utils/ThreadDefs.h b/include/utils/ThreadDefs.h
new file mode 100644
index 0000000..a8f8eb3
--- /dev/null
+++ b/include/utils/ThreadDefs.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef _LIBS_UTILS_THREAD_DEFS_H
+#define _LIBS_UTILS_THREAD_DEFS_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <system/graphics.h>
+
+// ---------------------------------------------------------------------------
+// C API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* android_thread_id_t;
+
+typedef int (*android_thread_func_t)(void*);
+
+enum {
+ /*
+ * ***********************************************
+ * ** Keep in sync with android.os.Process.java **
+ * ***********************************************
+ *
+ * This maps directly to the "nice" priorities we use in Android.
+ * A thread priority should be chosen inverse-proportionally to
+ * the amount of work the thread is expected to do. The more work
+ * a thread will do, the less favorable priority it should get so that
+ * it doesn't starve the system. Threads not behaving properly might
+ * be "punished" by the kernel.
+ * Use the levels below when appropriate. Intermediate values are
+ * acceptable, preferably use the {MORE|LESS}_FAVORABLE constants below.
+ */
+ ANDROID_PRIORITY_LOWEST = 19,
+
+ /* use for background tasks */
+ ANDROID_PRIORITY_BACKGROUND = 10,
+
+ /* most threads run at normal priority */
+ ANDROID_PRIORITY_NORMAL = 0,
+
+ /* threads currently running a UI that the user is interacting with */
+ ANDROID_PRIORITY_FOREGROUND = -2,
+
+ /* the main UI thread has a slightly more favorable priority */
+ ANDROID_PRIORITY_DISPLAY = -4,
+
+ /* ui service treads might want to run at a urgent display (uncommon) */
+ ANDROID_PRIORITY_URGENT_DISPLAY = HAL_PRIORITY_URGENT_DISPLAY,
+
+ /* all normal audio threads */
+ ANDROID_PRIORITY_AUDIO = -16,
+
+ /* service audio threads (uncommon) */
+ ANDROID_PRIORITY_URGENT_AUDIO = -19,
+
+ /* should never be used in practice. regular process might not
+ * be allowed to use this level */
+ ANDROID_PRIORITY_HIGHEST = -20,
+
+ ANDROID_PRIORITY_DEFAULT = ANDROID_PRIORITY_NORMAL,
+ ANDROID_PRIORITY_MORE_FAVORABLE = -1,
+ ANDROID_PRIORITY_LESS_FAVORABLE = +1,
+};
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+// ---------------------------------------------------------------------------
+// C++ API
+#ifdef __cplusplus
+namespace android {
+// ---------------------------------------------------------------------------
+
+typedef android_thread_id_t thread_id_t;
+typedef android_thread_func_t thread_func_t;
+
+enum {
+ PRIORITY_LOWEST = ANDROID_PRIORITY_LOWEST,
+ PRIORITY_BACKGROUND = ANDROID_PRIORITY_BACKGROUND,
+ PRIORITY_NORMAL = ANDROID_PRIORITY_NORMAL,
+ PRIORITY_FOREGROUND = ANDROID_PRIORITY_FOREGROUND,
+ PRIORITY_DISPLAY = ANDROID_PRIORITY_DISPLAY,
+ PRIORITY_URGENT_DISPLAY = ANDROID_PRIORITY_URGENT_DISPLAY,
+ PRIORITY_AUDIO = ANDROID_PRIORITY_AUDIO,
+ PRIORITY_URGENT_AUDIO = ANDROID_PRIORITY_URGENT_AUDIO,
+ PRIORITY_HIGHEST = ANDROID_PRIORITY_HIGHEST,
+ PRIORITY_DEFAULT = ANDROID_PRIORITY_DEFAULT,
+ PRIORITY_MORE_FAVORABLE = ANDROID_PRIORITY_MORE_FAVORABLE,
+ PRIORITY_LESS_FAVORABLE = ANDROID_PRIORITY_LESS_FAVORABLE,
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+#endif // __cplusplus
+// ---------------------------------------------------------------------------
+
+
+#endif // _LIBS_UTILS_THREAD_DEFS_H
diff --git a/include/utils/Timers.h b/include/utils/Timers.h
new file mode 100644
index 0000000..d260c08
--- /dev/null
+++ b/include/utils/Timers.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Timer functions.
+//
+#ifndef _LIBS_UTILS_TIMERS_H
+#define _LIBS_UTILS_TIMERS_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+// ------------------------------------------------------------------
+// C API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int64_t nsecs_t; // nano-seconds
+
+static inline nsecs_t seconds_to_nanoseconds(nsecs_t secs)
+{
+ return secs*1000000000;
+}
+
+static inline nsecs_t milliseconds_to_nanoseconds(nsecs_t secs)
+{
+ return secs*1000000;
+}
+
+static inline nsecs_t microseconds_to_nanoseconds(nsecs_t secs)
+{
+ return secs*1000;
+}
+
+static inline nsecs_t nanoseconds_to_seconds(nsecs_t secs)
+{
+ return secs/1000000000;
+}
+
+static inline nsecs_t nanoseconds_to_milliseconds(nsecs_t secs)
+{
+ return secs/1000000;
+}
+
+static inline nsecs_t nanoseconds_to_microseconds(nsecs_t secs)
+{
+ return secs/1000;
+}
+
+static inline nsecs_t s2ns(nsecs_t v) {return seconds_to_nanoseconds(v);}
+static inline nsecs_t ms2ns(nsecs_t v) {return milliseconds_to_nanoseconds(v);}
+static inline nsecs_t us2ns(nsecs_t v) {return microseconds_to_nanoseconds(v);}
+static inline nsecs_t ns2s(nsecs_t v) {return nanoseconds_to_seconds(v);}
+static inline nsecs_t ns2ms(nsecs_t v) {return nanoseconds_to_milliseconds(v);}
+static inline nsecs_t ns2us(nsecs_t v) {return nanoseconds_to_microseconds(v);}
+
+static inline nsecs_t seconds(nsecs_t v) { return s2ns(v); }
+//static inline nsecs_t milliseconds(nsecs_t v) { return ms2ns(v); }
+static inline nsecs_t microseconds(nsecs_t v) { return us2ns(v); }
+
+enum {
+ SYSTEM_TIME_REALTIME = 0, // system-wide realtime clock
+ SYSTEM_TIME_MONOTONIC = 1, // monotonic time since unspecified starting point
+ SYSTEM_TIME_PROCESS = 2, // high-resolution per-process clock
+ SYSTEM_TIME_THREAD = 3 // high-resolution per-thread clock
+};
+
+// return the system-time according to the specified clock
+#ifdef __cplusplus
+nsecs_t systemTime(int clock = SYSTEM_TIME_MONOTONIC);
+#else
+nsecs_t systemTime(int clock);
+#endif // def __cplusplus
+
+/**
+ * Returns the number of milliseconds to wait between the reference time and the timeout time.
+ * If the timeout is in the past relative to the reference time, returns 0.
+ * If the timeout is more than INT_MAX milliseconds in the future relative to the reference time,
+ * such as when timeoutTime == LLONG_MAX, returns -1 to indicate an infinite timeout delay.
+ * Otherwise, returns the difference between the reference time and timeout time
+ * rounded up to the next millisecond.
+ */
+int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+// ------------------------------------------------------------------
+// C++ API
+
+#ifdef __cplusplus
+
+namespace android {
+/*
+ * Time the duration of something.
+ *
+ * Includes some timeval manipulation functions.
+ */
+class DurationTimer {
+public:
+ DurationTimer() {}
+ ~DurationTimer() {}
+
+ // Start the timer.
+ void start();
+ // Stop the timer.
+ void stop();
+ // Get the duration in microseconds.
+ long long durationUsecs() const;
+
+ // Subtract two timevals. Returns the difference (ptv1-ptv2) in
+ // microseconds.
+ static long long subtractTimevals(const struct timeval* ptv1,
+ const struct timeval* ptv2);
+
+ // Add the specified amount of time to the timeval.
+ static void addToTimeval(struct timeval* ptv, long usec);
+
+private:
+ struct timeval mStartWhen;
+ struct timeval mStopWhen;
+};
+
+}; // android
+#endif // def __cplusplus
+
+#endif // _LIBS_UTILS_TIMERS_H
diff --git a/include/utils/Tokenizer.h b/include/utils/Tokenizer.h
new file mode 100644
index 0000000..bb25f37
--- /dev/null
+++ b/include/utils/Tokenizer.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef _UTILS_TOKENIZER_H
+#define _UTILS_TOKENIZER_H
+
+#include <assert.h>
+#include <utils/Errors.h>
+#include <utils/FileMap.h>
+#include <utils/String8.h>
+
+namespace android {
+
+/**
+ * A simple tokenizer for loading and parsing ASCII text files line by line.
+ */
+class Tokenizer {
+ Tokenizer(const String8& filename, FileMap* fileMap, char* buffer,
+ bool ownBuffer, size_t length);
+
+public:
+ ~Tokenizer();
+
+ /**
+ * Opens a file and maps it into memory.
+ *
+ * Returns NO_ERROR and a tokenizer for the file, if successful.
+ * Otherwise returns an error and sets outTokenizer to NULL.
+ */
+ static status_t open(const String8& filename, Tokenizer** outTokenizer);
+
+ /**
+ * Prepares to tokenize the contents of a string.
+ *
+ * Returns NO_ERROR and a tokenizer for the string, if successful.
+ * Otherwise returns an error and sets outTokenizer to NULL.
+ */
+ static status_t fromContents(const String8& filename,
+ const char* contents, Tokenizer** outTokenizer);
+
+ /**
+ * Returns true if at the end of the file.
+ */
+ inline bool isEof() const { return mCurrent == getEnd(); }
+
+ /**
+ * Returns true if at the end of the line or end of the file.
+ */
+ inline bool isEol() const { return isEof() || *mCurrent == '\n'; }
+
+ /**
+ * Gets the name of the file.
+ */
+ inline String8 getFilename() const { return mFilename; }
+
+ /**
+ * Gets a 1-based line number index for the current position.
+ */
+ inline int32_t getLineNumber() const { return mLineNumber; }
+
+ /**
+ * Formats a location string consisting of the filename and current line number.
+ * Returns a string like "MyFile.txt:33".
+ */
+ String8 getLocation() const;
+
+ /**
+ * Gets the character at the current position.
+ * Returns null at end of file.
+ */
+ inline char peekChar() const { return isEof() ? '\0' : *mCurrent; }
+
+ /**
+ * Gets the remainder of the current line as a string, excluding the newline character.
+ */
+ String8 peekRemainderOfLine() const;
+
+ /**
+ * Gets the character at the current position and advances past it.
+ * Returns null at end of file.
+ */
+ inline char nextChar() { return isEof() ? '\0' : *(mCurrent++); }
+
+ /**
+ * Gets the next token on this line stopping at the specified delimiters
+ * or the end of the line whichever comes first and advances past it.
+ * Also stops at embedded nulls.
+ * Returns the token or an empty string if the current character is a delimiter
+ * or is at the end of the line.
+ */
+ String8 nextToken(const char* delimiters);
+
+ /**
+ * Advances to the next line.
+ * Does nothing if already at the end of the file.
+ */
+ void nextLine();
+
+ /**
+ * Skips over the specified delimiters in the line.
+ * Also skips embedded nulls.
+ */
+ void skipDelimiters(const char* delimiters);
+
+private:
+ Tokenizer(const Tokenizer& other); // not copyable
+
+ String8 mFilename;
+ FileMap* mFileMap;
+ char* mBuffer;
+ bool mOwnBuffer;
+ size_t mLength;
+
+ const char* mCurrent;
+ int32_t mLineNumber;
+
+ inline const char* getEnd() const { return mBuffer + mLength; }
+
+};
+
+} // namespace android
+
+#endif // _UTILS_TOKENIZER_H
diff --git a/include/utils/Trace.h b/include/utils/Trace.h
new file mode 100644
index 0000000..4219206
--- /dev/null
+++ b/include/utils/Trace.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef ANDROID_TRACE_H
+#define ANDROID_TRACE_H
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/compiler.h>
+#include <utils/threads.h>
+
+// The ATRACE_TAG macro can be defined before including this header to trace
+// using one of the tags defined below. It must be defined to one of the
+// following ATRACE_TAG_* macros. The trace tag is used to filter tracing in
+// userland to avoid some of the runtime cost of tracing when it is not desired.
+//
+// Defining ATRACE_TAG to be ATRACE_TAG_ALWAYS will result in the tracing always
+// being enabled - this should ONLY be done for debug code, as userland tracing
+// has a performance cost even when the trace is not being recorded. Defining
+// ATRACE_TAG to be ATRACE_TAG_NEVER or leaving ATRACE_TAG undefined will result
+// in the tracing always being disabled.
+//
+// These tags must be kept in sync with frameworks/base/core/java/android/os/Trace.java.
+#define ATRACE_TAG_NEVER 0 // The "never" tag is never enabled.
+#define ATRACE_TAG_ALWAYS (1<<0) // The "always" tag is always enabled.
+#define ATRACE_TAG_GRAPHICS (1<<1)
+#define ATRACE_TAG_INPUT (1<<2)
+#define ATRACE_TAG_VIEW (1<<3)
+#define ATRACE_TAG_WEBVIEW (1<<4)
+#define ATRACE_TAG_WINDOW_MANAGER (1<<5)
+#define ATRACE_TAG_ACTIVITY_MANAGER (1<<6)
+#define ATRACE_TAG_SYNC_MANAGER (1<<7)
+#define ATRACE_TAG_AUDIO (1<<8)
+#define ATRACE_TAG_VIDEO (1<<9)
+#define ATRACE_TAG_LAST ATRACE_TAG_VIDEO
+
+#define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST)
+
+#ifndef ATRACE_TAG
+#define ATRACE_TAG ATRACE_TAG_NEVER
+#elif ATRACE_TAG > ATRACE_TAG_LAST
+#error ATRACE_TAG must be defined to be one of the tags defined in utils/Trace.h
+#endif
+
+// ATRACE_CALL traces the beginning and end of the current function. To trace
+// the correct start and end times this macro should be the first line of the
+// function body.
+#define ATRACE_CALL() android::ScopedTrace ___tracer(ATRACE_TAG, __FUNCTION__)
+
+// ATRACE_INT traces a named integer value. This can be used to track how the
+// value changes over time in a trace.
+#define ATRACE_INT(name, value) android::Tracer::traceCounter(ATRACE_TAG, name, value)
+
+// ATRACE_ENABLED returns true if the trace tag is enabled. It can be used as a
+// guard condition around more expensive trace calculations.
+#define ATRACE_ENABLED() android::Tracer::isTagEnabled(ATRACE_TAG)
+
+namespace android {
+
+class Tracer {
+
+public:
+
+ static uint64_t getEnabledTags() {
+ initIfNeeded();
+ return sEnabledTags;
+ }
+
+ static inline bool isTagEnabled(uint64_t tag) {
+ initIfNeeded();
+ return sEnabledTags & tag;
+ }
+
+ static inline void traceCounter(uint64_t tag, const char* name,
+ int32_t value) {
+ if (CC_UNLIKELY(isTagEnabled(tag))) {
+ char buf[1024];
+ snprintf(buf, 1024, "C|%d|%s|%d", getpid(), name, value);
+ write(sTraceFD, buf, strlen(buf));
+ }
+ }
+
+ static inline void traceBegin(uint64_t tag, const char* name) {
+ if (CC_UNLIKELY(isTagEnabled(tag))) {
+ char buf[1024];
+ size_t len = snprintf(buf, 1024, "B|%d|%s", getpid(), name);
+ write(sTraceFD, buf, len);
+ }
+ }
+
+ static inline void traceEnd(uint64_t tag) {
+ if (CC_UNLIKELY(isTagEnabled(tag))) {
+ char buf = 'E';
+ write(sTraceFD, &buf, 1);
+ }
+ }
+
+private:
+
+ static inline void initIfNeeded() {
+ if (!android_atomic_acquire_load(&sIsReady)) {
+ init();
+ }
+ }
+
+ static void changeCallback();
+
+ // init opens the trace marker file for writing and reads the
+ // atrace.tags.enableflags system property. It does this only the first
+ // time it is run, using sMutex for synchronization.
+ static void init();
+
+ // retrieve the current value of the system property.
+ static void loadSystemProperty();
+
+ // sIsReady is a boolean value indicating whether a call to init() has
+ // completed in this process. It is initialized to 0 and set to 1 when the
+ // first init() call completes. It is set to 1 even if a failure occurred
+ // in init (e.g. the trace marker file couldn't be opened).
+ //
+ // This should be checked by all tracing functions using an atomic acquire
+ // load operation before calling init(). This check avoids the need to lock
+ // a mutex each time a trace function gets called.
+ static volatile int32_t sIsReady;
+
+ // sTraceFD is the file descriptor used to write to the kernel's trace
+ // buffer. It is initialized to -1 and set to an open file descriptor in
+ // init() while a lock on sMutex is held.
+ //
+ // This should only be used by a trace function after init() has
+ // successfully completed.
+ static int sTraceFD;
+
+ // sEnabledTags is the set of tag bits for which tracing is currently
+ // enabled. It is initialized to 0 and set based on the
+ // atrace.tags.enableflags system property in init() while a lock on sMutex
+ // is held.
+ //
+ // This should only be used by a trace function after init() has
+ // successfully completed.
+ //
+ // This value is only ever non-zero when tracing is initialized and sTraceFD is not -1.
+ static uint64_t sEnabledTags;
+
+ // sMutex is used to protect the execution of init().
+ static Mutex sMutex;
+};
+
+class ScopedTrace {
+
+public:
+ inline ScopedTrace(uint64_t tag, const char* name) :
+ mTag(tag) {
+ Tracer::traceBegin(mTag, name);
+ }
+
+ inline ~ScopedTrace() {
+ Tracer::traceEnd(mTag);
+ }
+
+private:
+
+ uint64_t mTag;
+};
+
+}; // namespace android
+
+#endif // ANDROID_TRACE_H
diff --git a/include/utils/TypeHelpers.h b/include/utils/TypeHelpers.h
new file mode 100644
index 0000000..2bf33c3
--- /dev/null
+++ b/include/utils/TypeHelpers.h
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_TYPE_HELPERS_H
+#define ANDROID_TYPE_HELPERS_H
+
+#include <new>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+/*
+ * Types traits
+ */
+
+template <typename T> struct trait_trivial_ctor { enum { value = false }; };
+template <typename T> struct trait_trivial_dtor { enum { value = false }; };
+template <typename T> struct trait_trivial_copy { enum { value = false }; };
+template <typename T> struct trait_trivial_move { enum { value = false }; };
+template <typename T> struct trait_pointer { enum { value = false }; };
+template <typename T> struct trait_pointer<T*> { enum { value = true }; };
+
+template <typename TYPE>
+struct traits {
+ enum {
+ // whether this type is a pointer
+ is_pointer = trait_pointer<TYPE>::value,
+ // whether this type's constructor is a no-op
+ has_trivial_ctor = is_pointer || trait_trivial_ctor<TYPE>::value,
+ // whether this type's destructor is a no-op
+ has_trivial_dtor = is_pointer || trait_trivial_dtor<TYPE>::value,
+ // whether this type type can be copy-constructed with memcpy
+ has_trivial_copy = is_pointer || trait_trivial_copy<TYPE>::value,
+ // whether this type can be moved with memmove
+ has_trivial_move = is_pointer || trait_trivial_move<TYPE>::value
+ };
+};
+
+template <typename T, typename U>
+struct aggregate_traits {
+ enum {
+ is_pointer = false,
+ has_trivial_ctor =
+ traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
+ has_trivial_dtor =
+ traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
+ has_trivial_copy =
+ traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
+ has_trivial_move =
+ traits<T>::has_trivial_move && traits<U>::has_trivial_move
+ };
+};
+
+#define ANDROID_TRIVIAL_CTOR_TRAIT( T ) \
+ template<> struct trait_trivial_ctor< T > { enum { value = true }; };
+
+#define ANDROID_TRIVIAL_DTOR_TRAIT( T ) \
+ template<> struct trait_trivial_dtor< T > { enum { value = true }; };
+
+#define ANDROID_TRIVIAL_COPY_TRAIT( T ) \
+ template<> struct trait_trivial_copy< T > { enum { value = true }; };
+
+#define ANDROID_TRIVIAL_MOVE_TRAIT( T ) \
+ template<> struct trait_trivial_move< T > { enum { value = true }; };
+
+#define ANDROID_BASIC_TYPES_TRAITS( T ) \
+ ANDROID_TRIVIAL_CTOR_TRAIT( T ) \
+ ANDROID_TRIVIAL_DTOR_TRAIT( T ) \
+ ANDROID_TRIVIAL_COPY_TRAIT( T ) \
+ ANDROID_TRIVIAL_MOVE_TRAIT( T )
+
+// ---------------------------------------------------------------------------
+
+/*
+ * basic types traits
+ */
+
+ANDROID_BASIC_TYPES_TRAITS( void )
+ANDROID_BASIC_TYPES_TRAITS( bool )
+ANDROID_BASIC_TYPES_TRAITS( char )
+ANDROID_BASIC_TYPES_TRAITS( unsigned char )
+ANDROID_BASIC_TYPES_TRAITS( short )
+ANDROID_BASIC_TYPES_TRAITS( unsigned short )
+ANDROID_BASIC_TYPES_TRAITS( int )
+ANDROID_BASIC_TYPES_TRAITS( unsigned int )
+ANDROID_BASIC_TYPES_TRAITS( long )
+ANDROID_BASIC_TYPES_TRAITS( unsigned long )
+ANDROID_BASIC_TYPES_TRAITS( long long )
+ANDROID_BASIC_TYPES_TRAITS( unsigned long long )
+ANDROID_BASIC_TYPES_TRAITS( float )
+ANDROID_BASIC_TYPES_TRAITS( double )
+
+// ---------------------------------------------------------------------------
+
+
+/*
+ * compare and order types
+ */
+
+template<typename TYPE> inline
+int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
+ return (lhs < rhs) ? 1 : 0;
+}
+
+template<typename TYPE> inline
+int compare_type(const TYPE& lhs, const TYPE& rhs) {
+ return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs);
+}
+
+/*
+ * create, destroy, copy and move types...
+ */
+
+template<typename TYPE> inline
+void construct_type(TYPE* p, size_t n) {
+ if (!traits<TYPE>::has_trivial_ctor) {
+ while (n--) {
+ new(p++) TYPE;
+ }
+ }
+}
+
+template<typename TYPE> inline
+void destroy_type(TYPE* p, size_t n) {
+ if (!traits<TYPE>::has_trivial_dtor) {
+ while (n--) {
+ p->~TYPE();
+ p++;
+ }
+ }
+}
+
+template<typename TYPE> inline
+void copy_type(TYPE* d, const TYPE* s, size_t n) {
+ if (!traits<TYPE>::has_trivial_copy) {
+ while (n--) {
+ new(d) TYPE(*s);
+ d++, s++;
+ }
+ } else {
+ memcpy(d,s,n*sizeof(TYPE));
+ }
+}
+
+template<typename TYPE> inline
+void splat_type(TYPE* where, const TYPE* what, size_t n) {
+ if (!traits<TYPE>::has_trivial_copy) {
+ while (n--) {
+ new(where) TYPE(*what);
+ where++;
+ }
+ } else {
+ while (n--) {
+ *where++ = *what;
+ }
+ }
+}
+
+template<typename TYPE> inline
+void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
+ if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
+ || traits<TYPE>::has_trivial_move)
+ {
+ memmove(d,s,n*sizeof(TYPE));
+ } else {
+ d += n;
+ s += n;
+ while (n--) {
+ --d, --s;
+ if (!traits<TYPE>::has_trivial_copy) {
+ new(d) TYPE(*s);
+ } else {
+ *d = *s;
+ }
+ if (!traits<TYPE>::has_trivial_dtor) {
+ s->~TYPE();
+ }
+ }
+ }
+}
+
+template<typename TYPE> inline
+void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
+ if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
+ || traits<TYPE>::has_trivial_move)
+ {
+ memmove(d,s,n*sizeof(TYPE));
+ } else {
+ while (n--) {
+ if (!traits<TYPE>::has_trivial_copy) {
+ new(d) TYPE(*s);
+ } else {
+ *d = *s;
+ }
+ if (!traits<TYPE>::has_trivial_dtor) {
+ s->~TYPE();
+ }
+ d++, s++;
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+/*
+ * a key/value pair
+ */
+
+template <typename KEY, typename VALUE>
+struct key_value_pair_t {
+ typedef KEY key_t;
+ typedef VALUE value_t;
+
+ KEY key;
+ VALUE value;
+ key_value_pair_t() { }
+ key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
+ key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { }
+ key_value_pair_t(const KEY& k) : key(k) { }
+ inline bool operator < (const key_value_pair_t& o) const {
+ return strictly_order_type(key, o.key);
+ }
+ inline const KEY& getKey() const {
+ return key;
+ }
+ inline const VALUE& getValue() const {
+ return value;
+ }
+};
+
+template <typename K, typename V>
+struct trait_trivial_ctor< key_value_pair_t<K, V> >
+{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
+template <typename K, typename V>
+struct trait_trivial_dtor< key_value_pair_t<K, V> >
+{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
+template <typename K, typename V>
+struct trait_trivial_copy< key_value_pair_t<K, V> >
+{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
+template <typename K, typename V>
+struct trait_trivial_move< key_value_pair_t<K, V> >
+{ enum { value = aggregate_traits<K,V>::has_trivial_move }; };
+
+// ---------------------------------------------------------------------------
+
+/*
+ * Hash codes.
+ */
+typedef uint32_t hash_t;
+
+template <typename TKey>
+hash_t hash_type(const TKey& key);
+
+/* Built-in hash code specializations.
+ * Assumes pointers are 32bit. */
+#define ANDROID_INT32_HASH(T) \
+ template <> inline hash_t hash_type(const T& value) { return hash_t(value); }
+#define ANDROID_INT64_HASH(T) \
+ template <> inline hash_t hash_type(const T& value) { \
+ return hash_t((value >> 32) ^ value); }
+#define ANDROID_REINTERPRET_HASH(T, R) \
+ template <> inline hash_t hash_type(const T& value) { \
+ return hash_type(*reinterpret_cast<const R*>(&value)); }
+
+ANDROID_INT32_HASH(bool)
+ANDROID_INT32_HASH(int8_t)
+ANDROID_INT32_HASH(uint8_t)
+ANDROID_INT32_HASH(int16_t)
+ANDROID_INT32_HASH(uint16_t)
+ANDROID_INT32_HASH(int32_t)
+ANDROID_INT32_HASH(uint32_t)
+ANDROID_INT64_HASH(int64_t)
+ANDROID_INT64_HASH(uint64_t)
+ANDROID_REINTERPRET_HASH(float, uint32_t)
+ANDROID_REINTERPRET_HASH(double, uint64_t)
+
+template <typename T> inline hash_t hash_type(const T*& value) {
+ return hash_type(uintptr_t(value));
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_TYPE_HELPERS_H
diff --git a/include/utils/Unicode.h b/include/utils/Unicode.h
new file mode 100644
index 0000000..9273533
--- /dev/null
+++ b/include/utils/Unicode.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_UNICODE_H
+#define ANDROID_UNICODE_H
+
+#include <sys/types.h>
+#include <stdint.h>
+
+extern "C" {
+
+typedef uint32_t char32_t;
+typedef uint16_t char16_t;
+
+// Standard string functions on char16_t strings.
+int strcmp16(const char16_t *, const char16_t *);
+int strncmp16(const char16_t *s1, const char16_t *s2, size_t n);
+size_t strlen16(const char16_t *);
+size_t strnlen16(const char16_t *, size_t);
+char16_t *strcpy16(char16_t *, const char16_t *);
+char16_t *strncpy16(char16_t *, const char16_t *, size_t);
+
+// Version of comparison that supports embedded nulls.
+// This is different than strncmp() because we don't stop
+// at a nul character and consider the strings to be different
+// if the lengths are different (thus we need to supply the
+// lengths of both strings). This can also be used when
+// your string is not nul-terminated as it will have the
+// equivalent result as strcmp16 (unlike strncmp16).
+int strzcmp16(const char16_t *s1, size_t n1, const char16_t *s2, size_t n2);
+
+// Version of strzcmp16 for comparing strings in different endianness.
+int strzcmp16_h_n(const char16_t *s1H, size_t n1, const char16_t *s2N, size_t n2);
+
+// Standard string functions on char32_t strings.
+size_t strlen32(const char32_t *);
+size_t strnlen32(const char32_t *, size_t);
+
+/**
+ * Measure the length of a UTF-32 string in UTF-8. If the string is invalid
+ * such as containing a surrogate character, -1 will be returned.
+ */
+ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len);
+
+/**
+ * Stores a UTF-8 string converted from "src" in "dst", if "dst_length" is not
+ * large enough to store the string, the part of the "src" string is stored
+ * into "dst" as much as possible. See the examples for more detail.
+ * Returns the size actually used for storing the string.
+ * dst" is not null-terminated when dst_len is fully used (like strncpy).
+ *
+ * Example 1
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" >= 7
+ * ->
+ * Returned value == 6
+ * "dst" becomes \xE3\x81\x82\xE3\x81\x84\0
+ * (note that "dst" is null-terminated)
+ *
+ * Example 2
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" == 5
+ * ->
+ * Returned value == 3
+ * "dst" becomes \xE3\x81\x82\0
+ * (note that "dst" is null-terminated, but \u3044 is not stored in "dst"
+ * since "dst" does not have enough size to store the character)
+ *
+ * Example 3
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" == 6
+ * ->
+ * Returned value == 6
+ * "dst" becomes \xE3\x81\x82\xE3\x81\x84
+ * (note that "dst" is NOT null-terminated, like strncpy)
+ */
+void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst);
+
+/**
+ * Returns the unicode value at "index".
+ * Returns -1 when the index is invalid (equals to or more than "src_len").
+ * If returned value is positive, it is able to be converted to char32_t, which
+ * is unsigned. Then, if "next_index" is not NULL, the next index to be used is
+ * stored in "next_index". "next_index" can be NULL.
+ */
+int32_t utf32_from_utf8_at(const char *src, size_t src_len, size_t index, size_t *next_index);
+
+
+/**
+ * Returns the UTF-8 length of UTF-16 string "src".
+ */
+ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len);
+
+/**
+ * Converts a UTF-16 string to UTF-8. The destination buffer must be large
+ * enough to fit the UTF-16 as measured by utf16_to_utf8_length with an added
+ * NULL terminator.
+ */
+void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst);
+
+/**
+ * Returns the length of "src" when "src" is valid UTF-8 string.
+ * Returns 0 if src is NULL or 0-length string. Returns -1 when the source
+ * is an invalid string.
+ *
+ * This function should be used to determine whether "src" is valid UTF-8
+ * characters with valid unicode codepoints. "src" must be null-terminated.
+ *
+ * If you are going to use other utf8_to_... functions defined in this header
+ * with string which may not be valid UTF-8 with valid codepoint (form 0 to
+ * 0x10FFFF), you should use this function before calling others, since the
+ * other functions do not check whether the string is valid UTF-8 or not.
+ *
+ * If you do not care whether "src" is valid UTF-8 or not, you should use
+ * strlen() as usual, which should be much faster.
+ */
+ssize_t utf8_length(const char *src);
+
+/**
+ * Measure the length of a UTF-32 string.
+ */
+size_t utf8_to_utf32_length(const char *src, size_t src_len);
+
+/**
+ * Stores a UTF-32 string converted from "src" in "dst". "dst" must be large
+ * enough to store the entire converted string as measured by
+ * utf8_to_utf32_length plus space for a NULL terminator.
+ */
+void utf8_to_utf32(const char* src, size_t src_len, char32_t* dst);
+
+/**
+ * Returns the UTF-16 length of UTF-8 string "src".
+ */
+ssize_t utf8_to_utf16_length(const uint8_t* src, size_t srcLen);
+
+/**
+ * Convert UTF-8 to UTF-16 including surrogate pairs.
+ * Returns a pointer to the end of the string (where a null terminator might go
+ * if you wanted to add one).
+ */
+char16_t* utf8_to_utf16_no_null_terminator(const uint8_t* src, size_t srcLen, char16_t* dst);
+
+/**
+ * Convert UTF-8 to UTF-16 including surrogate pairs. The destination buffer
+ * must be large enough to hold the result as measured by utf8_to_utf16_length
+ * plus an added NULL terminator.
+ */
+void utf8_to_utf16(const uint8_t* src, size_t srcLen, char16_t* dst);
+
+}
+
+#endif
diff --git a/include/utils/UniquePtr.h b/include/utils/UniquePtr.h
new file mode 100644
index 0000000..bc62fe6
--- /dev/null
+++ b/include/utils/UniquePtr.h
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+/* === NOTE === NOTE === NOTE === NOTE === NOTE === NOTE === NOTE === NOTE ===
+ *
+ * THIS IS A COPY OF libcore/include/UniquePtr.h AND AS SUCH THAT IS THE
+ * CANONICAL SOURCE OF THIS FILE. PLEASE KEEP THEM IN SYNC.
+ *
+ * === NOTE === NOTE === NOTE === NOTE === NOTE === NOTE === NOTE === NOTE ===
+ */
+
+#ifndef UNIQUE_PTR_H_included
+#define UNIQUE_PTR_H_included
+
+#include <cstdlib> // For NULL.
+
+// Default deleter for pointer types.
+template <typename T>
+struct DefaultDelete {
+ enum { type_must_be_complete = sizeof(T) };
+ DefaultDelete() {}
+ void operator()(T* p) const {
+ delete p;
+ }
+};
+
+// Default deleter for array types.
+template <typename T>
+struct DefaultDelete<T[]> {
+ enum { type_must_be_complete = sizeof(T) };
+ void operator()(T* p) const {
+ delete[] p;
+ }
+};
+
+// A smart pointer that deletes the given pointer on destruction.
+// Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr
+// and boost::scoped_array).
+// Named to be in keeping with Android style but also to avoid
+// collision with any other implementation, until we can switch over
+// to unique_ptr.
+// Use thus:
+// UniquePtr<C> c(new C);
+template <typename T, typename D = DefaultDelete<T> >
+class UniquePtr {
+public:
+ // Construct a new UniquePtr, taking ownership of the given raw pointer.
+ explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
+ }
+
+ ~UniquePtr() {
+ reset();
+ }
+
+ // Accessors.
+ T& operator*() const { return *mPtr; }
+ T* operator->() const { return mPtr; }
+ T* get() const { return mPtr; }
+
+ // Returns the raw pointer and hands over ownership to the caller.
+ // The pointer will not be deleted by UniquePtr.
+ T* release() __attribute__((warn_unused_result)) {
+ T* result = mPtr;
+ mPtr = NULL;
+ return result;
+ }
+
+ // Takes ownership of the given raw pointer.
+ // If this smart pointer previously owned a different raw pointer, that
+ // raw pointer will be freed.
+ void reset(T* ptr = NULL) {
+ if (ptr != mPtr) {
+ D()(mPtr);
+ mPtr = ptr;
+ }
+ }
+
+private:
+ // The raw pointer.
+ T* mPtr;
+
+ // Comparing unique pointers is probably a mistake, since they're unique.
+ template <typename T2> bool operator==(const UniquePtr<T2>& p) const;
+ template <typename T2> bool operator!=(const UniquePtr<T2>& p) const;
+
+ // Disallow copy and assignment.
+ UniquePtr(const UniquePtr&);
+ void operator=(const UniquePtr&);
+};
+
+// Partial specialization for array types. Like std::unique_ptr, this removes
+// operator* and operator-> but adds operator[].
+template <typename T, typename D>
+class UniquePtr<T[], D> {
+public:
+ explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
+ }
+
+ ~UniquePtr() {
+ reset();
+ }
+
+ T& operator[](size_t i) const {
+ return mPtr[i];
+ }
+ T* get() const { return mPtr; }
+
+ T* release() __attribute__((warn_unused_result)) {
+ T* result = mPtr;
+ mPtr = NULL;
+ return result;
+ }
+
+ void reset(T* ptr = NULL) {
+ if (ptr != mPtr) {
+ D()(mPtr);
+ mPtr = ptr;
+ }
+ }
+
+private:
+ T* mPtr;
+
+ // Disallow copy and assignment.
+ UniquePtr(const UniquePtr&);
+ void operator=(const UniquePtr&);
+};
+
+#if UNIQUE_PTR_TESTS
+
+// Run these tests with:
+// g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out
+
+#include <stdio.h>
+
+static void assert(bool b) {
+ if (!b) {
+ fprintf(stderr, "FAIL\n");
+ abort();
+ }
+ fprintf(stderr, "OK\n");
+}
+static int cCount = 0;
+struct C {
+ C() { ++cCount; }
+ ~C() { --cCount; }
+};
+static bool freed = false;
+struct Freer {
+ void operator()(int* p) {
+ assert(*p == 123);
+ free(p);
+ freed = true;
+ }
+};
+
+int main(int argc, char* argv[]) {
+ //
+ // UniquePtr<T> tests...
+ //
+
+ // Can we free a single object?
+ {
+ UniquePtr<C> c(new C);
+ assert(cCount == 1);
+ }
+ assert(cCount == 0);
+ // Does release work?
+ C* rawC;
+ {
+ UniquePtr<C> c(new C);
+ assert(cCount == 1);
+ rawC = c.release();
+ }
+ assert(cCount == 1);
+ delete rawC;
+ // Does reset work?
+ {
+ UniquePtr<C> c(new C);
+ assert(cCount == 1);
+ c.reset(new C);
+ assert(cCount == 1);
+ }
+ assert(cCount == 0);
+
+ //
+ // UniquePtr<T[]> tests...
+ //
+
+ // Can we free an array?
+ {
+ UniquePtr<C[]> cs(new C[4]);
+ assert(cCount == 4);
+ }
+ assert(cCount == 0);
+ // Does release work?
+ {
+ UniquePtr<C[]> c(new C[4]);
+ assert(cCount == 4);
+ rawC = c.release();
+ }
+ assert(cCount == 4);
+ delete[] rawC;
+ // Does reset work?
+ {
+ UniquePtr<C[]> c(new C[4]);
+ assert(cCount == 4);
+ c.reset(new C[2]);
+ assert(cCount == 2);
+ }
+ assert(cCount == 0);
+
+ //
+ // Custom deleter tests...
+ //
+ assert(!freed);
+ {
+ UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int))));
+ *i = 123;
+ }
+ assert(freed);
+ return 0;
+}
+#endif
+
+#endif // UNIQUE_PTR_H_included
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
new file mode 100644
index 0000000..e39a5b7
--- /dev/null
+++ b/include/utils/Vector.h
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_VECTOR_H
+#define ANDROID_VECTOR_H
+
+#include <new>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Log.h>
+#include <utils/VectorImpl.h>
+#include <utils/TypeHelpers.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+template <typename TYPE>
+class SortedVector;
+
+/*!
+ * The main templated vector class ensuring type safety
+ * while making use of VectorImpl.
+ * This is the class users want to use.
+ */
+
+template <class TYPE>
+class Vector : private VectorImpl
+{
+public:
+ typedef TYPE value_type;
+
+ /*!
+ * Constructors and destructors
+ */
+
+ Vector();
+ Vector(const Vector<TYPE>& rhs);
+ explicit Vector(const SortedVector<TYPE>& rhs);
+ virtual ~Vector();
+
+ /*! copy operator */
+ const Vector<TYPE>& operator = (const Vector<TYPE>& rhs) const;
+ Vector<TYPE>& operator = (const Vector<TYPE>& rhs);
+
+ const Vector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
+ Vector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
+
+ /*
+ * empty the vector
+ */
+
+ inline void clear() { VectorImpl::clear(); }
+
+ /*!
+ * vector stats
+ */
+
+ //! returns number of items in the vector
+ inline size_t size() const { return VectorImpl::size(); }
+ //! returns wether or not the vector is empty
+ inline bool isEmpty() const { return VectorImpl::isEmpty(); }
+ //! returns how many items can be stored without reallocating the backing store
+ inline size_t capacity() const { return VectorImpl::capacity(); }
+ //! setst the capacity. capacity can never be reduced less than size()
+ inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); }
+
+ /*!
+ * C-style array access
+ */
+
+ //! read-only C-style access
+ inline const TYPE* array() const;
+ //! read-write C-style access
+ TYPE* editArray();
+
+ /*!
+ * accessors
+ */
+
+ //! read-only access to an item at a given index
+ inline const TYPE& operator [] (size_t index) const;
+ //! alternate name for operator []
+ inline const TYPE& itemAt(size_t index) const;
+ //! stack-usage of the vector. returns the top of the stack (last element)
+ const TYPE& top() const;
+ //! same as operator [], but allows to access the vector backward (from the end) with a negative index
+ const TYPE& mirrorItemAt(ssize_t index) const;
+
+ /*!
+ * modifing the array
+ */
+
+ //! copy-on write support, grants write access to an item
+ TYPE& editItemAt(size_t index);
+ //! grants right acces to the top of the stack (last element)
+ TYPE& editTop();
+
+ /*!
+ * append/insert another vector
+ */
+
+ //! insert another vector at a given index
+ ssize_t insertVectorAt(const Vector<TYPE>& vector, size_t index);
+
+ //! append another vector at the end of this one
+ ssize_t appendVector(const Vector<TYPE>& vector);
+
+
+ //! insert an array at a given index
+ ssize_t insertArrayAt(const TYPE* array, size_t index, size_t length);
+
+ //! append an array at the end of this vector
+ ssize_t appendArray(const TYPE* array, size_t length);
+
+ /*!
+ * add/insert/replace items
+ */
+
+ //! insert one or several items initialized with their default constructor
+ inline ssize_t insertAt(size_t index, size_t numItems = 1);
+ //! insert one or several items initialized from a prototype item
+ ssize_t insertAt(const TYPE& prototype_item, size_t index, size_t numItems = 1);
+ //! pop the top of the stack (removes the last element). No-op if the stack's empty
+ inline void pop();
+ //! pushes an item initialized with its default constructor
+ inline void push();
+ //! pushes an item on the top of the stack
+ void push(const TYPE& item);
+ //! same as push() but returns the index the item was added at (or an error)
+ inline ssize_t add();
+ //! same as push() but returns the index the item was added at (or an error)
+ ssize_t add(const TYPE& item);
+ //! replace an item with a new one initialized with its default constructor
+ inline ssize_t replaceAt(size_t index);
+ //! replace an item with a new one
+ ssize_t replaceAt(const TYPE& item, size_t index);
+
+ /*!
+ * remove items
+ */
+
+ //! remove several items
+ inline ssize_t removeItemsAt(size_t index, size_t count = 1);
+ //! remove one item
+ inline ssize_t removeAt(size_t index) { return removeItemsAt(index); }
+
+ /*!
+ * sort (stable) the array
+ */
+
+ typedef int (*compar_t)(const TYPE* lhs, const TYPE* rhs);
+ typedef int (*compar_r_t)(const TYPE* lhs, const TYPE* rhs, void* state);
+
+ inline status_t sort(compar_t cmp);
+ inline status_t sort(compar_r_t cmp, void* state);
+
+ // for debugging only
+ inline size_t getItemSize() const { return itemSize(); }
+
+
+ /*
+ * these inlines add some level of compatibility with STL. eventually
+ * we should probably turn things around.
+ */
+ typedef TYPE* iterator;
+ typedef TYPE const* const_iterator;
+
+ inline iterator begin() { return editArray(); }
+ inline iterator end() { return editArray() + size(); }
+ inline const_iterator begin() const { return array(); }
+ inline const_iterator end() const { return array() + size(); }
+ inline void reserve(size_t n) { setCapacity(n); }
+ inline bool empty() const{ return isEmpty(); }
+ inline void push_back(const TYPE& item) { insertAt(item, size(), 1); }
+ inline void push_front(const TYPE& item) { insertAt(item, 0, 1); }
+ inline iterator erase(iterator pos) {
+ return begin() + removeItemsAt(pos-array());
+ }
+
+protected:
+ virtual void do_construct(void* storage, size_t num) const;
+ virtual void do_destroy(void* storage, size_t num) const;
+ virtual void do_copy(void* dest, const void* from, size_t num) const;
+ virtual void do_splat(void* dest, const void* item, size_t num) const;
+ virtual void do_move_forward(void* dest, const void* from, size_t num) const;
+ virtual void do_move_backward(void* dest, const void* from, size_t num) const;
+};
+
+// Vector<T> can be trivially moved using memcpy() because moving does not
+// require any change to the underlying SharedBuffer contents or reference count.
+template<typename T> struct trait_trivial_move<Vector<T> > { enum { value = true }; };
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts from here...
+// ---------------------------------------------------------------------------
+
+template<class TYPE> inline
+Vector<TYPE>::Vector()
+ : VectorImpl(sizeof(TYPE),
+ ((traits<TYPE>::has_trivial_ctor ? HAS_TRIVIAL_CTOR : 0)
+ |(traits<TYPE>::has_trivial_dtor ? HAS_TRIVIAL_DTOR : 0)
+ |(traits<TYPE>::has_trivial_copy ? HAS_TRIVIAL_COPY : 0))
+ )
+{
+}
+
+template<class TYPE> inline
+Vector<TYPE>::Vector(const Vector<TYPE>& rhs)
+ : VectorImpl(rhs) {
+}
+
+template<class TYPE> inline
+Vector<TYPE>::Vector(const SortedVector<TYPE>& rhs)
+ : VectorImpl(static_cast<const VectorImpl&>(rhs)) {
+}
+
+template<class TYPE> inline
+Vector<TYPE>::~Vector() {
+ finish_vector();
+}
+
+template<class TYPE> inline
+Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) {
+ VectorImpl::operator = (rhs);
+ return *this;
+}
+
+template<class TYPE> inline
+const Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) const {
+ VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+ return *this;
+}
+
+template<class TYPE> inline
+Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
+ VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+ return *this;
+}
+
+template<class TYPE> inline
+const Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
+ VectorImpl::operator = (rhs);
+ return *this;
+}
+
+template<class TYPE> inline
+const TYPE* Vector<TYPE>::array() const {
+ return static_cast<const TYPE *>(arrayImpl());
+}
+
+template<class TYPE> inline
+TYPE* Vector<TYPE>::editArray() {
+ return static_cast<TYPE *>(editArrayImpl());
+}
+
+
+template<class TYPE> inline
+const TYPE& Vector<TYPE>::operator[](size_t index) const {
+ LOG_FATAL_IF( index>=size(),
+ "itemAt: index %d is past size %d", (int)index, (int)size() );
+ return *(array() + index);
+}
+
+template<class TYPE> inline
+const TYPE& Vector<TYPE>::itemAt(size_t index) const {
+ return operator[](index);
+}
+
+template<class TYPE> inline
+const TYPE& Vector<TYPE>::mirrorItemAt(ssize_t index) const {
+ LOG_FATAL_IF( (index>0 ? index : -index)>=size(),
+ "mirrorItemAt: index %d is past size %d",
+ (int)index, (int)size() );
+ return *(array() + ((index<0) ? (size()-index) : index));
+}
+
+template<class TYPE> inline
+const TYPE& Vector<TYPE>::top() const {
+ return *(array() + size() - 1);
+}
+
+template<class TYPE> inline
+TYPE& Vector<TYPE>::editItemAt(size_t index) {
+ return *( static_cast<TYPE *>(editItemLocation(index)) );
+}
+
+template<class TYPE> inline
+TYPE& Vector<TYPE>::editTop() {
+ return *( static_cast<TYPE *>(editItemLocation(size()-1)) );
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertVectorAt(const Vector<TYPE>& vector, size_t index) {
+ return VectorImpl::insertVectorAt(reinterpret_cast<const VectorImpl&>(vector), index);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::appendVector(const Vector<TYPE>& vector) {
+ return VectorImpl::appendVector(reinterpret_cast<const VectorImpl&>(vector));
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertArrayAt(const TYPE* array, size_t index, size_t length) {
+ return VectorImpl::insertArrayAt(array, index, length);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::appendArray(const TYPE* array, size_t length) {
+ return VectorImpl::appendArray(array, length);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertAt(const TYPE& item, size_t index, size_t numItems) {
+ return VectorImpl::insertAt(&item, index, numItems);
+}
+
+template<class TYPE> inline
+void Vector<TYPE>::push(const TYPE& item) {
+ return VectorImpl::push(&item);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::add(const TYPE& item) {
+ return VectorImpl::add(&item);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::replaceAt(const TYPE& item, size_t index) {
+ return VectorImpl::replaceAt(&item, index);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertAt(size_t index, size_t numItems) {
+ return VectorImpl::insertAt(index, numItems);
+}
+
+template<class TYPE> inline
+void Vector<TYPE>::pop() {
+ VectorImpl::pop();
+}
+
+template<class TYPE> inline
+void Vector<TYPE>::push() {
+ VectorImpl::push();
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::add() {
+ return VectorImpl::add();
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::replaceAt(size_t index) {
+ return VectorImpl::replaceAt(index);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::removeItemsAt(size_t index, size_t count) {
+ return VectorImpl::removeItemsAt(index, count);
+}
+
+template<class TYPE> inline
+status_t Vector<TYPE>::sort(Vector<TYPE>::compar_t cmp) {
+ return VectorImpl::sort((VectorImpl::compar_t)cmp);
+}
+
+template<class TYPE> inline
+status_t Vector<TYPE>::sort(Vector<TYPE>::compar_r_t cmp, void* state) {
+ return VectorImpl::sort((VectorImpl::compar_r_t)cmp, state);
+}
+
+// ---------------------------------------------------------------------------
+
+template<class TYPE>
+void Vector<TYPE>::do_construct(void* storage, size_t num) const {
+ construct_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_destroy(void* storage, size_t num) const {
+ destroy_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
+ copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
+ splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
+ move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
+ move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+}; // namespace android
+
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_VECTOR_H
diff --git a/include/utils/VectorImpl.h b/include/utils/VectorImpl.h
new file mode 100644
index 0000000..c4ec2ff
--- /dev/null
+++ b/include/utils/VectorImpl.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_VECTOR_IMPL_H
+#define ANDROID_VECTOR_IMPL_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts in here...
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+/*!
+ * Implementation of the guts of the vector<> class
+ * this ensures backward binary compatibility and
+ * reduces code size.
+ * For performance reasons, we expose mStorage and mCount
+ * so these fields are set in stone.
+ *
+ */
+
+class VectorImpl
+{
+public:
+ enum { // flags passed to the ctor
+ HAS_TRIVIAL_CTOR = 0x00000001,
+ HAS_TRIVIAL_DTOR = 0x00000002,
+ HAS_TRIVIAL_COPY = 0x00000004,
+ };
+
+ VectorImpl(size_t itemSize, uint32_t flags);
+ VectorImpl(const VectorImpl& rhs);
+ virtual ~VectorImpl();
+
+ /*! must be called from subclasses destructor */
+ void finish_vector();
+
+ VectorImpl& operator = (const VectorImpl& rhs);
+
+ /*! C-style array access */
+ inline const void* arrayImpl() const { return mStorage; }
+ void* editArrayImpl();
+
+ /*! vector stats */
+ inline size_t size() const { return mCount; }
+ inline bool isEmpty() const { return mCount == 0; }
+ size_t capacity() const;
+ ssize_t setCapacity(size_t size);
+
+ /*! append/insert another vector or array */
+ ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
+ ssize_t appendVector(const VectorImpl& vector);
+ ssize_t insertArrayAt(const void* array, size_t index, size_t length);
+ ssize_t appendArray(const void* array, size_t length);
+
+ /*! add/insert/replace items */
+ ssize_t insertAt(size_t where, size_t numItems = 1);
+ ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
+ void pop();
+ void push();
+ void push(const void* item);
+ ssize_t add();
+ ssize_t add(const void* item);
+ ssize_t replaceAt(size_t index);
+ ssize_t replaceAt(const void* item, size_t index);
+
+ /*! remove items */
+ ssize_t removeItemsAt(size_t index, size_t count = 1);
+ void clear();
+
+ const void* itemLocation(size_t index) const;
+ void* editItemLocation(size_t index);
+
+ typedef int (*compar_t)(const void* lhs, const void* rhs);
+ typedef int (*compar_r_t)(const void* lhs, const void* rhs, void* state);
+ status_t sort(compar_t cmp);
+ status_t sort(compar_r_t cmp, void* state);
+
+protected:
+ size_t itemSize() const;
+ void release_storage();
+
+ virtual void do_construct(void* storage, size_t num) const = 0;
+ virtual void do_destroy(void* storage, size_t num) const = 0;
+ virtual void do_copy(void* dest, const void* from, size_t num) const = 0;
+ virtual void do_splat(void* dest, const void* item, size_t num) const = 0;
+ virtual void do_move_forward(void* dest, const void* from, size_t num) const = 0;
+ virtual void do_move_backward(void* dest, const void* from, size_t num) const = 0;
+
+ // take care of FBC...
+ virtual void reservedVectorImpl1();
+ virtual void reservedVectorImpl2();
+ virtual void reservedVectorImpl3();
+ virtual void reservedVectorImpl4();
+ virtual void reservedVectorImpl5();
+ virtual void reservedVectorImpl6();
+ virtual void reservedVectorImpl7();
+ virtual void reservedVectorImpl8();
+
+private:
+ void* _grow(size_t where, size_t amount);
+ void _shrink(size_t where, size_t amount);
+
+ inline void _do_construct(void* storage, size_t num) const;
+ inline void _do_destroy(void* storage, size_t num) const;
+ inline void _do_copy(void* dest, const void* from, size_t num) const;
+ inline void _do_splat(void* dest, const void* item, size_t num) const;
+ inline void _do_move_forward(void* dest, const void* from, size_t num) const;
+ inline void _do_move_backward(void* dest, const void* from, size_t num) const;
+
+ // These 2 fields are exposed in the inlines below,
+ // so they're set in stone.
+ void * mStorage; // base address of the vector
+ size_t mCount; // number of items
+
+ const uint32_t mFlags;
+ const size_t mItemSize;
+};
+
+
+
+class SortedVectorImpl : public VectorImpl
+{
+public:
+ SortedVectorImpl(size_t itemSize, uint32_t flags);
+ SortedVectorImpl(const VectorImpl& rhs);
+ virtual ~SortedVectorImpl();
+
+ SortedVectorImpl& operator = (const SortedVectorImpl& rhs);
+
+ //! finds the index of an item
+ ssize_t indexOf(const void* item) const;
+
+ //! finds where this item should be inserted
+ size_t orderOf(const void* item) const;
+
+ //! add an item in the right place (or replaces it if there is one)
+ ssize_t add(const void* item);
+
+ //! merges a vector into this one
+ ssize_t merge(const VectorImpl& vector);
+ ssize_t merge(const SortedVectorImpl& vector);
+
+ //! removes an item
+ ssize_t remove(const void* item);
+
+protected:
+ virtual int do_compare(const void* lhs, const void* rhs) const = 0;
+
+ // take care of FBC...
+ virtual void reservedSortedVectorImpl1();
+ virtual void reservedSortedVectorImpl2();
+ virtual void reservedSortedVectorImpl3();
+ virtual void reservedSortedVectorImpl4();
+ virtual void reservedSortedVectorImpl5();
+ virtual void reservedSortedVectorImpl6();
+ virtual void reservedSortedVectorImpl7();
+ virtual void reservedSortedVectorImpl8();
+
+private:
+ ssize_t _indexOrderOf(const void* item, size_t* order = 0) const;
+
+ // these are made private, because they can't be used on a SortedVector
+ // (they don't have an implementation either)
+ ssize_t add();
+ void pop();
+ void push();
+ void push(const void* item);
+ ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
+ ssize_t appendVector(const VectorImpl& vector);
+ ssize_t insertArrayAt(const void* array, size_t index, size_t length);
+ ssize_t appendArray(const void* array, size_t length);
+ ssize_t insertAt(size_t where, size_t numItems = 1);
+ ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
+ ssize_t replaceAt(size_t index);
+ ssize_t replaceAt(const void* item, size_t index);
+};
+
+}; // namespace android
+
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_VECTOR_IMPL_H
diff --git a/include/utils/WorkQueue.h b/include/utils/WorkQueue.h
new file mode 100644
index 0000000..e3c75b2
--- /dev/null
+++ b/include/utils/WorkQueue.h
@@ -0,0 +1,119 @@
+/*]
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef _LIBS_UTILS_WORK_QUEUE_H
+#define _LIBS_UTILS_WORK_QUEUE_H
+
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+namespace android {
+
+/*
+ * A threaded work queue.
+ *
+ * This class is designed to make it easy to run a bunch of isolated work
+ * units in parallel, using up to the specified number of threads.
+ * To use it, write a loop to post work units to the work queue, then synchronize
+ * on the queue at the end.
+ */
+class WorkQueue {
+public:
+ class WorkUnit {
+ public:
+ WorkUnit() { }
+ virtual ~WorkUnit() { }
+
+ /*
+ * Runs the work unit.
+ * If the result is 'true' then the work queue continues scheduling work as usual.
+ * If the result is 'false' then the work queue is canceled.
+ */
+ virtual bool run() = 0;
+ };
+
+ /* Creates a work queue with the specified maximum number of work threads. */
+ WorkQueue(size_t maxThreads, bool canCallJava = true);
+
+ /* Destroys the work queue.
+ * Cancels pending work and waits for all remaining threads to complete.
+ */
+ ~WorkQueue();
+
+ /* Posts a work unit to run later.
+ * If the work queue has been canceled or is already finished, returns INVALID_OPERATION
+ * and does not take ownership of the work unit (caller must destroy it itself).
+ * Otherwise, returns OK and takes ownership of the work unit (the work queue will
+ * destroy it automatically).
+ *
+ * For flow control, this method blocks when the size of the pending work queue is more
+ * 'backlog' times the number of threads. This condition reduces the rate of entry into
+ * the pending work queue and prevents it from growing much more rapidly than the
+ * work threads can actually handle.
+ *
+ * If 'backlog' is 0, then no throttle is applied.
+ */
+ status_t schedule(WorkUnit* workUnit, size_t backlog = 2);
+
+ /* Cancels all pending work.
+ * If the work queue is already finished, returns INVALID_OPERATION.
+ * If the work queue is already canceled, returns OK and does nothing else.
+ * Otherwise, returns OK, discards all pending work units and prevents additional
+ * work units from being scheduled.
+ *
+ * Call finish() after cancel() to wait for all remaining work to complete.
+ */
+ status_t cancel();
+
+ /* Waits for all work to complete.
+ * If the work queue is already finished, returns INVALID_OPERATION.
+ * Otherwise, waits for all work to complete and returns OK.
+ */
+ status_t finish();
+
+private:
+ class WorkThread : public Thread {
+ public:
+ WorkThread(WorkQueue* workQueue, bool canCallJava);
+ virtual ~WorkThread();
+
+ private:
+ virtual bool threadLoop();
+
+ WorkQueue* const mWorkQueue;
+ };
+
+ status_t cancelLocked();
+ bool threadLoop(); // called from each work thread
+
+ const size_t mMaxThreads;
+ const bool mCanCallJava;
+
+ Mutex mLock;
+ Condition mWorkChangedCondition;
+ Condition mWorkDequeuedCondition;
+
+ bool mCanceled;
+ bool mFinished;
+ size_t mIdleThreads;
+ Vector<sp<WorkThread> > mWorkThreads;
+ Vector<WorkUnit*> mWorkUnits;
+};
+
+}; // namespace android
+
+#endif // _LIBS_UTILS_WORK_QUEUE_H
diff --git a/include/utils/ZipFileCRO.h b/include/utils/ZipFileCRO.h
new file mode 100644
index 0000000..3e42a95
--- /dev/null
+++ b/include/utils/ZipFileCRO.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 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.
+ * 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.
+ */
+
+//
+// C API for ead-only access to Zip archives, with minimal heap allocation.
+//
+#ifndef __LIBS_ZIPFILECRO_H
+#define __LIBS_ZIPFILECRO_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <utils/Compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Trivial typedef to ensure that ZipFileCRO is not treated as a simple integer.
+ */
+typedef void* ZipFileCRO;
+
+/*
+ * Trivial typedef to ensure that ZipEntryCRO is not treated as a simple
+ * integer. We use NULL to indicate an invalid value.
+ */
+typedef void* ZipEntryCRO;
+
+extern ZipFileCRO ZipFileXRO_open(const char* path);
+
+extern void ZipFileCRO_destroy(ZipFileCRO zip);
+
+extern ZipEntryCRO ZipFileCRO_findEntryByName(ZipFileCRO zip,
+ const char* fileName);
+
+extern bool ZipFileCRO_getEntryInfo(ZipFileCRO zip, ZipEntryCRO entry,
+ int* pMethod, size_t* pUncompLen,
+ size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32);
+
+extern bool ZipFileCRO_uncompressEntry(ZipFileCRO zip, ZipEntryCRO entry, int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__LIBS_ZIPFILECRO_H*/
diff --git a/include/utils/ZipFileRO.h b/include/utils/ZipFileRO.h
new file mode 100644
index 0000000..547e36a
--- /dev/null
+++ b/include/utils/ZipFileRO.h
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+/*
+ * Read-only access to Zip archives, with minimal heap allocation.
+ *
+ * This is similar to the more-complete ZipFile class, but no attempt
+ * has been made to make them interchangeable. This class operates under
+ * a very different set of assumptions and constraints.
+ *
+ * One such assumption is that if you're getting file descriptors for
+ * use with this class as a child of a fork() operation, you must be on
+ * a pread() to guarantee correct operation. This is because pread() can
+ * atomically read at a file offset without worrying about a lock around an
+ * lseek() + read() pair.
+ */
+#ifndef __LIBS_ZIPFILERO_H
+#define __LIBS_ZIPFILERO_H
+
+#include <utils/Compat.h>
+#include <utils/Errors.h>
+#include <utils/FileMap.h>
+#include <utils/threads.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+
+namespace android {
+
+/*
+ * Trivial typedef to ensure that ZipEntryRO is not treated as a simple
+ * integer. We use NULL to indicate an invalid value.
+ */
+typedef void* ZipEntryRO;
+
+/*
+ * Open a Zip archive for reading.
+ *
+ * We want "open" and "find entry by name" to be fast operations, and we
+ * want to use as little memory as possible. We memory-map the file,
+ * and load a hash table with pointers to the filenames (which aren't
+ * null-terminated). The other fields are at a fixed offset from the
+ * filename, so we don't need to extract those (but we do need to byte-read
+ * and endian-swap them every time we want them).
+ *
+ * To speed comparisons when doing a lookup by name, we could make the mapping
+ * "private" (copy-on-write) and null-terminate the filenames after verifying
+ * the record structure. However, this requires a private mapping of
+ * every page that the Central Directory touches. Easier to tuck a copy
+ * of the string length into the hash table entry.
+ *
+ * NOTE: If this is used on file descriptors inherited from a fork() operation,
+ * you must be on a platform that implements pread() to guarantee correctness
+ * on the shared file descriptors.
+ */
+class ZipFileRO {
+public:
+ ZipFileRO()
+ : mFd(-1), mFileName(NULL), mFileLength(-1),
+ mDirectoryMap(NULL),
+ mNumEntries(-1), mDirectoryOffset(-1),
+ mHashTableSize(-1), mHashTable(NULL)
+ {}
+
+ ~ZipFileRO();
+
+ /*
+ * Open an archive.
+ */
+ status_t open(const char* zipFileName);
+
+ /*
+ * Find an entry, by name. Returns the entry identifier, or NULL if
+ * not found.
+ *
+ * If two entries have the same name, one will be chosen at semi-random.
+ */
+ ZipEntryRO findEntryByName(const char* fileName) const;
+
+ /*
+ * Return the #of entries in the Zip archive.
+ */
+ int getNumEntries(void) const {
+ return mNumEntries;
+ }
+
+ /*
+ * Return the Nth entry. Zip file entries are not stored in sorted
+ * order, and updated entries may appear at the end, so anyone walking
+ * the archive needs to avoid making ordering assumptions. We take
+ * that further by returning the Nth non-empty entry in the hash table
+ * rather than the Nth entry in the archive.
+ *
+ * Valid values are [0..numEntries).
+ *
+ * [This is currently O(n). If it needs to be fast we can allocate an
+ * additional data structure or provide an iterator interface.]
+ */
+ ZipEntryRO findEntryByIndex(int idx) const;
+
+ /*
+ * Copy the filename into the supplied buffer. Returns 0 on success,
+ * -1 if "entry" is invalid, or the filename length if it didn't fit. The
+ * length, and the returned string, include the null-termination.
+ */
+ int getEntryFileName(ZipEntryRO entry, char* buffer, int bufLen) const;
+
+ /*
+ * Get the vital stats for an entry. Pass in NULL pointers for anything
+ * you don't need.
+ *
+ * "*pOffset" holds the Zip file offset of the entry's data.
+ *
+ * Returns "false" if "entry" is bogus or if the data in the Zip file
+ * appears to be bad.
+ */
+ bool getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen,
+ size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) const;
+
+ /*
+ * Create a new FileMap object that maps a subset of the archive. For
+ * an uncompressed entry this effectively provides a pointer to the
+ * actual data, for a compressed entry this provides the input buffer
+ * for inflate().
+ */
+ FileMap* createEntryFileMap(ZipEntryRO entry) const;
+
+ /*
+ * Uncompress the data into a buffer. Depending on the compression
+ * format, this is either an "inflate" operation or a memcpy.
+ *
+ * Use "uncompLen" from getEntryInfo() to determine the required
+ * buffer size.
+ *
+ * Returns "true" on success.
+ */
+ bool uncompressEntry(ZipEntryRO entry, void* buffer) const;
+
+ /*
+ * Uncompress the data to an open file descriptor.
+ */
+ bool uncompressEntry(ZipEntryRO entry, int fd) const;
+
+ /* Zip compression methods we support */
+ enum {
+ kCompressStored = 0, // no compression
+ kCompressDeflated = 8, // standard deflate
+ };
+
+ /*
+ * Utility function: uncompress deflated data, buffer to buffer.
+ */
+ static bool inflateBuffer(void* outBuf, const void* inBuf,
+ size_t uncompLen, size_t compLen);
+
+ /*
+ * Utility function: uncompress deflated data, buffer to fd.
+ */
+ static bool inflateBuffer(int fd, const void* inBuf,
+ size_t uncompLen, size_t compLen);
+
+ /*
+ * Utility function to convert ZIP's time format to a timespec struct.
+ */
+ static inline void zipTimeToTimespec(long when, struct tm* timespec) {
+ const long date = when >> 16;
+ timespec->tm_year = ((date >> 9) & 0x7F) + 80; // Zip is years since 1980
+ timespec->tm_mon = (date >> 5) & 0x0F;
+ timespec->tm_mday = date & 0x1F;
+
+ timespec->tm_hour = (when >> 11) & 0x1F;
+ timespec->tm_min = (when >> 5) & 0x3F;
+ timespec->tm_sec = (when & 0x1F) << 1;
+ }
+
+ /*
+ * Some basic functions for raw data manipulation. "LE" means
+ * Little Endian.
+ */
+ static inline unsigned short get2LE(const unsigned char* buf) {
+ return buf[0] | (buf[1] << 8);
+ }
+ static inline unsigned long get4LE(const unsigned char* buf) {
+ return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
+ }
+
+private:
+ /* these are private and not defined */
+ ZipFileRO(const ZipFileRO& src);
+ ZipFileRO& operator=(const ZipFileRO& src);
+
+ /* locate and parse the central directory */
+ bool mapCentralDirectory(void);
+
+ /* parse the archive, prepping internal structures */
+ bool parseZipArchive(void);
+
+ /* add a new entry to the hash table */
+ void addToHash(const char* str, int strLen, unsigned int hash);
+
+ /* compute string hash code */
+ static unsigned int computeHash(const char* str, int len);
+
+ /* convert a ZipEntryRO back to a hash table index */
+ int entryToIndex(const ZipEntryRO entry) const;
+
+ /*
+ * One entry in the hash table.
+ */
+ typedef struct HashEntry {
+ const char* name;
+ unsigned short nameLen;
+ //unsigned int hash;
+ } HashEntry;
+
+ /* open Zip archive */
+ int mFd;
+
+ /* Lock for handling the file descriptor (seeks, etc) */
+ mutable Mutex mFdLock;
+
+ /* zip file name */
+ char* mFileName;
+
+ /* length of file */
+ size_t mFileLength;
+
+ /* mapped file */
+ FileMap* mDirectoryMap;
+
+ /* number of entries in the Zip archive */
+ int mNumEntries;
+
+ /* CD directory offset in the Zip archive */
+ off64_t mDirectoryOffset;
+
+ /*
+ * We know how many entries are in the Zip archive, so we have a
+ * fixed-size hash table. We probe for an empty slot.
+ */
+ int mHashTableSize;
+ HashEntry* mHashTable;
+};
+
+}; // namespace android
+
+#endif /*__LIBS_ZIPFILERO_H*/
diff --git a/include/utils/ZipUtils.h b/include/utils/ZipUtils.h
new file mode 100644
index 0000000..42c42b6
--- /dev/null
+++ b/include/utils/ZipUtils.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+//
+// Miscellaneous zip/gzip utility functions.
+//
+#ifndef __LIBS_ZIPUTILS_H
+#define __LIBS_ZIPUTILS_H
+
+#include <stdio.h>
+
+namespace android {
+
+/*
+ * Container class for utility functions, primarily for namespace reasons.
+ */
+class ZipUtils {
+public:
+ /*
+ * General utility function for uncompressing "deflate" data from a file
+ * to a buffer.
+ */
+ static bool inflateToBuffer(int fd, void* buf, long uncompressedLen,
+ long compressedLen);
+ static bool inflateToBuffer(FILE* fp, void* buf, long uncompressedLen,
+ long compressedLen);
+
+ /*
+ * Someday we might want to make this generic and handle bzip2 ".bz2"
+ * files too.
+ *
+ * We could declare gzip to be a sub-class of zip that has exactly
+ * one always-compressed entry, but we currently want to treat Zip
+ * and gzip as distinct, so there's no value.
+ *
+ * The zlib library has some gzip utilities, but it has no interface
+ * for extracting the uncompressed length of the file (you do *not*
+ * want to gzseek to the end).
+ *
+ * Pass in a seeked file pointer for the gzip file. If this is a gzip
+ * file, we set our return values appropriately and return "true" with
+ * the file seeked to the start of the compressed data.
+ */
+ static bool examineGzip(FILE* fp, int* pCompressionMethod,
+ long* pUncompressedLen, long* pCompressedLen, unsigned long* pCRC32);
+
+private:
+ ZipUtils() {}
+ ~ZipUtils() {}
+};
+
+}; // namespace android
+
+#endif /*__LIBS_ZIPUTILS_H*/
diff --git a/include/utils/ashmem.h b/include/utils/ashmem.h
new file mode 100644
index 0000000..0854775
--- /dev/null
+++ b/include/utils/ashmem.h
@@ -0,0 +1,41 @@
+/* utils/ashmem.h
+ **
+ ** Copyright 2008 The Android Open Source Project
+ **
+ ** This file is dual licensed. It may be redistributed and/or modified
+ ** under the terms of the Apache 2.0 License OR version 2 of the GNU
+ ** General Public License.
+ */
+
+#ifndef _UTILS_ASHMEM_H
+#define _UTILS_ASHMEM_H
+
+#include <linux/limits.h>
+#include <linux/ioctl.h>
+
+#define ASHMEM_NAME_LEN 256
+
+#define ASHMEM_NAME_DEF "dev/ashmem"
+
+/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
+#define ASHMEM_NOT_REAPED 0
+#define ASHMEM_WAS_REAPED 1
+
+/* Return values from ASHMEM_UNPIN: Is the mapping now pinned or unpinned? */
+#define ASHMEM_NOW_UNPINNED 0
+#define ASHMEM_NOW_PINNED 1
+
+#define __ASHMEMIOC 0x77
+
+#define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN])
+#define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN])
+#define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t)
+#define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4)
+#define ASHMEM_SET_PROT_MASK _IOW(__ASHMEMIOC, 5, unsigned long)
+#define ASHMEM_GET_PROT_MASK _IO(__ASHMEMIOC, 6)
+#define ASHMEM_PIN _IO(__ASHMEMIOC, 7)
+#define ASHMEM_UNPIN _IO(__ASHMEMIOC, 8)
+#define ASHMEM_ISPINNED _IO(__ASHMEMIOC, 9)
+#define ASHMEM_PURGE_ALL_CACHES _IO(__ASHMEMIOC, 10)
+
+#endif /* _UTILS_ASHMEM_H */
diff --git a/include/utils/misc.h b/include/utils/misc.h
new file mode 100644
index 0000000..d7d5bc1
--- /dev/null
+++ b/include/utils/misc.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Handy utility functions and portability code.
+//
+#ifndef _LIBS_UTILS_MISC_H
+#define _LIBS_UTILS_MISC_H
+
+#include <sys/time.h>
+#include <utils/Endian.h>
+
+namespace android {
+
+/* get #of elements in a static array */
+#ifndef NELEM
+# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
+#endif
+
+/*
+ * Make a copy of the string, using "new[]" instead of "malloc". Free the
+ * string with delete[].
+ *
+ * Returns NULL if "str" is NULL.
+ */
+char* strdupNew(const char* str);
+
+/*
+ * Concatenate an argument vector into a single string. If argc is >= 0
+ * it will be used; if it's < 0 then the last element in the arg vector
+ * must be NULL.
+ *
+ * This inserts a space between each argument.
+ *
+ * This does not automatically add double quotes around arguments with
+ * spaces in them. This practice is necessary for Win32, because Win32's
+ * CreateProcess call is stupid.
+ *
+ * The caller should delete[] the returned string.
+ */
+char* concatArgv(int argc, const char* const argv[]);
+
+/*
+ * Count up the number of arguments in "argv". The count does not include
+ * the final NULL entry.
+ */
+int countArgv(const char* const argv[]);
+
+/*
+ * Some utility functions for working with files. These could be made
+ * part of a "File" class.
+ */
+typedef enum FileType {
+ kFileTypeUnknown = 0,
+ kFileTypeNonexistent, // i.e. ENOENT
+ kFileTypeRegular,
+ kFileTypeDirectory,
+ kFileTypeCharDev,
+ kFileTypeBlockDev,
+ kFileTypeFifo,
+ kFileTypeSymlink,
+ kFileTypeSocket,
+} FileType;
+/* get the file's type; follows symlinks */
+FileType getFileType(const char* fileName);
+/* get the file's modification date; returns -1 w/errno set on failure */
+time_t getFileModDate(const char* fileName);
+
+/*
+ * Round up to the nearest power of 2. Handy for hash tables.
+ */
+unsigned int roundUpPower2(unsigned int val);
+
+void strreverse(char* begin, char* end);
+void k_itoa(int value, char* str, int base);
+char* itoa(int val, int base);
+
+typedef void (*sysprop_change_callback)(void);
+void add_sysprop_change_callback(sysprop_change_callback cb, int priority);
+void report_sysprop_change();
+
+}; // namespace android
+
+#endif // _LIBS_UTILS_MISC_H
diff --git a/include/utils/threads.h b/include/utils/threads.h
new file mode 100644
index 0000000..9de3382
--- /dev/null
+++ b/include/utils/threads.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef _LIBS_UTILS_THREADS_H
+#define _LIBS_UTILS_THREADS_H
+
+/*
+ * Please, DO NOT USE!
+ *
+ * This file is here only for legacy reasons. Instead, include directly
+ * the headers you need below.
+ *
+ */
+
+#include <utils/AndroidThreads.h>
+
+#ifdef __cplusplus
+#include <utils/Condition.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/RWLock.h>
+#include <utils/Thread.h>
+#endif
+
+#endif // _LIBS_UTILS_THREADS_H
diff --git a/plugins/rpc/Binder.cpp b/plugins/rpc/Binder.cpp
new file mode 100644
index 0000000..1f21f9c
--- /dev/null
+++ b/plugins/rpc/Binder.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2005 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 <binder/Binder.h>
+
+#include <utils/Atomic.h>
+#include <utils/misc.h>
+#include <binder/BpBinder.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+#include <stdio.h>
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+IBinder::IBinder()
+ : RefBase()
+{
+}
+
+IBinder::~IBinder()
+{
+}
+
+// ---------------------------------------------------------------------------
+
+sp<IInterface> IBinder::queryLocalInterface(const String16& descriptor)
+{
+ return NULL;
+}
+
+BBinder* IBinder::localBinder()
+{
+ return NULL;
+}
+
+BpBinder* IBinder::remoteBinder()
+{
+ return NULL;
+}
+
+bool IBinder::checkSubclass(const void* /*subclassID*/) const
+{
+ return false;
+}
+
+// ---------------------------------------------------------------------------
+
+class BBinder::Extras
+{
+public:
+ Mutex mLock;
+ BpBinder::ObjectManager mObjects;
+};
+
+// ---------------------------------------------------------------------------
+
+BBinder::BBinder()
+ : mExtras(NULL)
+{
+}
+
+bool BBinder::isBinderAlive() const
+{
+ return true;
+}
+
+status_t BBinder::pingBinder()
+{
+ return NO_ERROR;
+}
+
+const String16& BBinder::getInterfaceDescriptor() const
+{
+ // This is a local static rather than a global static,
+ // to avoid static initializer ordering issues.
+ static String16 sEmptyDescriptor;
+ ALOGW("reached BBinder::getInterfaceDescriptor (this=%p)", this);
+ return sEmptyDescriptor;
+}
+
+status_t BBinder::transact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ data.setDataPosition(0);
+
+ status_t err = NO_ERROR;
+ switch (code) {
+ case PING_TRANSACTION:
+ reply->writeInt32(pingBinder());
+ break;
+ default:
+ err = onTransact(code, data, reply, flags);
+ break;
+ }
+
+ if (reply != NULL) {
+ reply->setDataPosition(0);
+ }
+
+ return err;
+}
+
+status_t BBinder::linkToDeath(
+ const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
+{
+ return INVALID_OPERATION;
+}
+
+status_t BBinder::unlinkToDeath(
+ const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
+ wp<DeathRecipient>* outRecipient)
+{
+ return INVALID_OPERATION;
+}
+
+status_t BBinder::dump(int fd, const Vector<String16>& args)
+{
+ return NO_ERROR;
+}
+
+void BBinder::attachObject(
+ const void* objectID, void* object, void* cleanupCookie,
+ object_cleanup_func func)
+{
+ Extras* e = mExtras;
+
+ if (!e) {
+ e = new Extras;
+ if (android_atomic_cmpxchg(0, reinterpret_cast<int32_t>(e),
+ reinterpret_cast<volatile int32_t*>(&mExtras)) != 0) {
+ delete e;
+ e = mExtras;
+ }
+ if (e == 0) return; // out of memory
+ }
+
+ AutoMutex _l(e->mLock);
+ e->mObjects.attach(objectID, object, cleanupCookie, func);
+}
+
+void* BBinder::findObject(const void* objectID) const
+{
+ Extras* e = mExtras;
+ if (!e) return NULL;
+
+ AutoMutex _l(e->mLock);
+ return e->mObjects.find(objectID);
+}
+
+void BBinder::detachObject(const void* objectID)
+{
+ Extras* e = mExtras;
+ if (!e) return;
+
+ AutoMutex _l(e->mLock);
+ e->mObjects.detach(objectID);
+}
+
+BBinder* BBinder::localBinder()
+{
+ return this;
+}
+
+BBinder::~BBinder()
+{
+ if (mExtras) delete mExtras;
+}
+
+
+status_t BBinder::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case INTERFACE_TRANSACTION:
+ reply->writeString16(getInterfaceDescriptor());
+ return NO_ERROR;
+
+ case DUMP_TRANSACTION: {
+ int fd = data.readFileDescriptor();
+ int argc = data.readInt32();
+ Vector<String16> args;
+ for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
+ args.add(data.readString16());
+ }
+ return dump(fd, args);
+ }
+
+ case SYSPROPS_TRANSACTION: {
+ report_sysprop_change();
+ return NO_ERROR;
+ }
+
+ default:
+ return UNKNOWN_TRANSACTION;
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+enum {
+ // This is used to transfer ownership of the remote binder from
+ // the BpRefBase object holding it (when it is constructed), to the
+ // owner of the BpRefBase object when it first acquires that BpRefBase.
+ kRemoteAcquired = 0x00000001
+};
+
+BpRefBase::BpRefBase(const sp<IBinder>& o)
+ : mRemote(o.get()), mRefs(NULL), mState(0)
+{
+ extendObjectLifetime(OBJECT_LIFETIME_WEAK);
+
+ if (mRemote) {
+ mRemote->incStrong(this); // Removed on first IncStrong().
+ mRefs = mRemote->createWeak(this); // Held for our entire lifetime.
+ }
+}
+
+BpRefBase::~BpRefBase()
+{
+ if (mRemote) {
+ if (!(mState&kRemoteAcquired)) {
+ mRemote->decStrong(this);
+ }
+ mRefs->decWeak(this);
+ }
+}
+
+void BpRefBase::onFirstRef()
+{
+ android_atomic_or(kRemoteAcquired, &mState);
+}
+
+void BpRefBase::onLastStrongRef(const void* id)
+{
+ if (mRemote) {
+ mRemote->decStrong(this);
+ }
+}
+
+bool BpRefBase::onIncStrongAttempted(uint32_t flags, const void* id)
+{
+ return mRemote ? mRefs->attemptIncStrong(this) : false;
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/plugins/rpc/BpBinder.cpp b/plugins/rpc/BpBinder.cpp
new file mode 100644
index 0000000..47a62db
--- /dev/null
+++ b/plugins/rpc/BpBinder.cpp
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#define LOG_TAG "BpBinder"
+//#define LOG_NDEBUG 0
+
+#include <binder/BpBinder.h>
+
+#include <binder/IPCThreadState.h>
+#include <utils/Log.h>
+
+#include <stdio.h>
+
+//#undef ALOGV
+//#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+BpBinder::ObjectManager::ObjectManager()
+{
+}
+
+BpBinder::ObjectManager::~ObjectManager()
+{
+ kill();
+}
+
+void BpBinder::ObjectManager::attach(
+ const void* objectID, void* object, void* cleanupCookie,
+ IBinder::object_cleanup_func func)
+{
+ entry_t e;
+ e.object = object;
+ e.cleanupCookie = cleanupCookie;
+ e.func = func;
+
+ if (mObjects.indexOfKey(objectID) >= 0) {
+ ALOGE("Trying to attach object ID %p to binder ObjectManager %p with object %p, but object ID already in use",
+ objectID, this, object);
+ return;
+ }
+
+ mObjects.add(objectID, e);
+}
+
+void* BpBinder::ObjectManager::find(const void* objectID) const
+{
+ const ssize_t i = mObjects.indexOfKey(objectID);
+ if (i < 0) return NULL;
+ return mObjects.valueAt(i).object;
+}
+
+void BpBinder::ObjectManager::detach(const void* objectID)
+{
+ mObjects.removeItem(objectID);
+}
+
+void BpBinder::ObjectManager::kill()
+{
+ const size_t N = mObjects.size();
+ ALOGV("Killing %d objects in manager %p", N, this);
+ for (size_t i=0; i<N; i++) {
+ const entry_t& e = mObjects.valueAt(i);
+ if (e.func != NULL) {
+ e.func(mObjects.keyAt(i), e.object, e.cleanupCookie);
+ }
+ }
+
+ mObjects.clear();
+}
+
+// ---------------------------------------------------------------------------
+
+BpBinder::BpBinder(int32_t handle)
+ : mHandle(handle)
+ , mAlive(1)
+ , mObitsSent(0)
+ , mObituaries(NULL)
+{
+ ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
+
+ extendObjectLifetime(OBJECT_LIFETIME_WEAK);
+ IPCThreadState::self()->incWeakHandle(handle);
+}
+
+bool BpBinder::isDescriptorCached() const {
+ Mutex::Autolock _l(mLock);
+ return mDescriptorCache.size() ? true : false;
+}
+
+const String16& BpBinder::getInterfaceDescriptor() const
+{
+ if (isDescriptorCached() == false) {
+ Parcel send, reply;
+ // do the IPC without a lock held.
+ status_t err = const_cast<BpBinder*>(this)->transact(
+ INTERFACE_TRANSACTION, send, &reply);
+ if (err == NO_ERROR) {
+ String16 res(reply.readString16());
+ Mutex::Autolock _l(mLock);
+ // mDescriptorCache could have been assigned while the lock was
+ // released.
+ if (mDescriptorCache.size() == 0)
+ mDescriptorCache = res;
+ }
+ }
+
+ // we're returning a reference to a non-static object here. Usually this
+ // is not something smart to do, however, with binder objects it is
+ // (usually) safe because they are reference-counted.
+
+ return mDescriptorCache;
+}
+
+bool BpBinder::isBinderAlive() const
+{
+ return mAlive != 0;
+}
+
+status_t BpBinder::pingBinder()
+{
+ Parcel send;
+ Parcel reply;
+ status_t err = transact(PING_TRANSACTION, send, &reply);
+ if (err != NO_ERROR) return err;
+ if (reply.dataSize() < sizeof(status_t)) return NOT_ENOUGH_DATA;
+ return (status_t)reply.readInt32();
+}
+
+status_t BpBinder::dump(int fd, const Vector<String16>& args)
+{
+ Parcel send;
+ Parcel reply;
+ send.writeFileDescriptor(fd);
+ const size_t numArgs = args.size();
+ send.writeInt32(numArgs);
+ for (size_t i = 0; i < numArgs; i++) {
+ send.writeString16(args[i]);
+ }
+ status_t err = transact(DUMP_TRANSACTION, send, &reply);
+ return err;
+}
+
+status_t BpBinder::transact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ // Once a binder has died, it will never come back to life.
+ if (mAlive) {
+ status_t status = IPCThreadState::self()->transact(
+ mHandle, code, data, reply, flags);
+ if (status == DEAD_OBJECT) mAlive = 0;
+ return status;
+ }
+
+ return DEAD_OBJECT;
+}
+
+status_t BpBinder::linkToDeath(
+ const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
+{
+ Obituary ob;
+ ob.recipient = recipient;
+ ob.cookie = cookie;
+ ob.flags = flags;
+
+ LOG_ALWAYS_FATAL_IF(recipient == NULL,
+ "linkToDeath(): recipient must be non-NULL");
+
+ {
+ AutoMutex _l(mLock);
+
+ if (!mObitsSent) {
+ if (!mObituaries) {
+ mObituaries = new Vector<Obituary>;
+ if (!mObituaries) {
+ return NO_MEMORY;
+ }
+ ALOGV("Requesting death notification: %p handle %d\n", this, mHandle);
+ getWeakRefs()->incWeak(this);
+ IPCThreadState* self = IPCThreadState::self();
+ self->requestDeathNotification(mHandle, this);
+ self->flushCommands();
+ }
+ ssize_t res = mObituaries->add(ob);
+ return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
+ }
+ }
+
+ return DEAD_OBJECT;
+}
+
+status_t BpBinder::unlinkToDeath(
+ const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
+ wp<DeathRecipient>* outRecipient)
+{
+ AutoMutex _l(mLock);
+
+ if (mObitsSent) {
+ return DEAD_OBJECT;
+ }
+
+ const size_t N = mObituaries ? mObituaries->size() : 0;
+ for (size_t i=0; i<N; i++) {
+ const Obituary& obit = mObituaries->itemAt(i);
+ if ((obit.recipient == recipient
+ || (recipient == NULL && obit.cookie == cookie))
+ && obit.flags == flags) {
+ const uint32_t allFlags = obit.flags|flags;
+ if (outRecipient != NULL) {
+ *outRecipient = mObituaries->itemAt(i).recipient;
+ }
+ mObituaries->removeAt(i);
+ if (mObituaries->size() == 0) {
+ ALOGV("Clearing death notification: %p handle %d\n", this, mHandle);
+ IPCThreadState* self = IPCThreadState::self();
+ self->clearDeathNotification(mHandle, this);
+ self->flushCommands();
+ delete mObituaries;
+ mObituaries = NULL;
+ }
+ return NO_ERROR;
+ }
+ }
+
+ return NAME_NOT_FOUND;
+}
+
+void BpBinder::sendObituary()
+{
+ ALOGV("Sending obituary for proxy %p handle %d, mObitsSent=%s\n",
+ this, mHandle, mObitsSent ? "true" : "false");
+
+ mAlive = 0;
+ if (mObitsSent) return;
+
+ mLock.lock();
+ Vector<Obituary>* obits = mObituaries;
+ if(obits != NULL) {
+ ALOGV("Clearing sent death notification: %p handle %d\n", this, mHandle);
+ IPCThreadState* self = IPCThreadState::self();
+ self->clearDeathNotification(mHandle, this);
+ self->flushCommands();
+ mObituaries = NULL;
+ }
+ mObitsSent = 1;
+ mLock.unlock();
+
+ ALOGV("Reporting death of proxy %p for %d recipients\n",
+ this, obits ? obits->size() : 0);
+
+ if (obits != NULL) {
+ const size_t N = obits->size();
+ for (size_t i=0; i<N; i++) {
+ reportOneDeath(obits->itemAt(i));
+ }
+
+ delete obits;
+ }
+}
+
+void BpBinder::reportOneDeath(const Obituary& obit)
+{
+ sp<DeathRecipient> recipient = obit.recipient.promote();
+ ALOGV("Reporting death to recipient: %p\n", recipient.get());
+ if (recipient == NULL) return;
+
+ recipient->binderDied(this);
+}
+
+
+void BpBinder::attachObject(
+ const void* objectID, void* object, void* cleanupCookie,
+ object_cleanup_func func)
+{
+ AutoMutex _l(mLock);
+ ALOGV("Attaching object %p to binder %p (manager=%p)", object, this, &mObjects);
+ mObjects.attach(objectID, object, cleanupCookie, func);
+}
+
+void* BpBinder::findObject(const void* objectID) const
+{
+ AutoMutex _l(mLock);
+ return mObjects.find(objectID);
+}
+
+void BpBinder::detachObject(const void* objectID)
+{
+ AutoMutex _l(mLock);
+ mObjects.detach(objectID);
+}
+
+BpBinder* BpBinder::remoteBinder()
+{
+ return this;
+}
+
+BpBinder::~BpBinder()
+{
+ ALOGV("Destroying BpBinder %p handle %d\n", this, mHandle);
+
+ IPCThreadState* ipc = IPCThreadState::self();
+
+ mLock.lock();
+ Vector<Obituary>* obits = mObituaries;
+ if(obits != NULL) {
+ if (ipc) ipc->clearDeathNotification(mHandle, this);
+ mObituaries = NULL;
+ }
+ mLock.unlock();
+
+ if (obits != NULL) {
+ // XXX Should we tell any remaining DeathRecipient
+ // objects that the last strong ref has gone away, so they
+ // are no longer linked?
+ delete obits;
+ }
+
+ if (ipc) {
+ ipc->expungeHandle(mHandle, this);
+ ipc->decWeakHandle(mHandle);
+ }
+}
+
+void BpBinder::onFirstRef()
+{
+ ALOGV("onFirstRef BpBinder %p handle %d\n", this, mHandle);
+ IPCThreadState* ipc = IPCThreadState::self();
+ if (ipc) ipc->incStrongHandle(mHandle);
+}
+
+void BpBinder::onLastStrongRef(const void* id)
+{
+ ALOGV("onLastStrongRef BpBinder %p handle %d\n", this, mHandle);
+ IF_ALOGV() {
+ printRefs();
+ }
+ IPCThreadState* ipc = IPCThreadState::self();
+ if (ipc) ipc->decStrongHandle(mHandle);
+}
+
+bool BpBinder::onIncStrongAttempted(uint32_t flags, const void* id)
+{
+ ALOGV("onIncStrongAttempted BpBinder %p handle %d\n", this, mHandle);
+ IPCThreadState* ipc = IPCThreadState::self();
+ return ipc ? ipc->attemptIncStrongHandle(mHandle) == NO_ERROR : false;
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/plugins/rpc/CMakeLists.txt b/plugins/rpc/CMakeLists.txt
index 003dbc8..91edeb1 100644
--- a/plugins/rpc/CMakeLists.txt
+++ b/plugins/rpc/CMakeLists.txt
@@ -1,16 +1,36 @@
+if (CONFIG_BBQUE_RPC_FIFO)
+ #----- Add "RPC FIFO" target dynamic library
+ set(PLUGIN_RPC_FIFO_SRC fifo_rpc fifo_plugin)
+ add_library(bbque_rpc_fifo MODULE ${PLUGIN_RPC_FIFO_SRC})
+ target_link_libraries(
+ bbque_rpc_fifo
+ ${Boost_LIBRARIES}
+ )
+ install(TARGETS bbque_rpc_fifo LIBRARY
+ DESTINATION ${BBQUE_PATH_PLUGINS}
+ COMPONENT BarbequeRTRM)
+
+ #----- Add "RPC FIFO" specific flags
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--gc-sections")
+endif (CONFIG_BBQUE_RPC_FIFO)
-#----- Add "RPC FIFO" target dynamic library
-set(PLUGIN_RPC_FIFO_SRC fifo_rpc fifo_plugin)
-add_library(bbque_rpc_fifo MODULE ${PLUGIN_RPC_FIFO_SRC})
-target_link_libraries(
- bbque_rpc_fifo
- ${Boost_LIBRARIES}
-)
-install(TARGETS bbque_rpc_fifo LIBRARY
+if (CONFIG_BBQUE_RPC_BINDER)
+ set(PLUGIN_RPC_BINDER_SRC binder_rpc binder_plugin ${PROJECT_SOURCE_DIR}/include/bbque/binder_service IInterface Binder RefBase VectorImpl)
+ add_library(bbque_rpc_binder MODULE ${PLUGIN_RPC_BINDER_SRC})
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections -fpermissive /system/lib/libcutils.so /system/lib/libutils.so")
+ target_link_libraries(
+ bbque_rpc_binder
+ ${Boost_LIBRARIES}
+ /system/lib/libbinder.so # senza questo ---> cannot locate '_ZNK7android6Parcel14checkInterfaceEPNS_7IBinderE
+#se non compilo Binder ---> _ZTIN7android7BBinderE
+ )
+ install(TARGETS bbque_rpc_binder LIBRARY
DESTINATION ${BBQUE_PATH_PLUGINS}
COMPONENT BarbequeRTRM)
-#----- Add "RPC FIFO" specific flags
-set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
-set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--gc-sections")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--gc-sections")
+endif (CONFIG_BBQUE_RPC_BINDER)
+
+
diff --git a/plugins/rpc/IInterface.cpp b/plugins/rpc/IInterface.cpp
new file mode 100644
index 0000000..29acf5d
--- /dev/null
+++ b/plugins/rpc/IInterface.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2005 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 <binder/IInterface.h>
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+IInterface::IInterface()
+ : RefBase() {
+}
+
+IInterface::~IInterface() {
+}
+
+sp<IBinder> IInterface::asBinder()
+{
+ return this ? onAsBinder() : NULL;
+}
+
+sp<const IBinder> IInterface::asBinder() const
+{
+ return this ? const_cast<IInterface*>(this)->onAsBinder() : NULL;
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/plugins/rpc/RefBase.cpp b/plugins/rpc/RefBase.cpp
new file mode 100644
index 0000000..e80a795
--- /dev/null
+++ b/plugins/rpc/RefBase.cpp
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#define LOG_TAG "RefBase"
+
+#include <utils/RefBase.h>
+
+#include <utils/Atomic.h>
+#include <utils/CallStack.h>
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <utils/TextOutput.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <typeinfo>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+// compile with refcounting debugging enabled
+#define DEBUG_REFS 0
+#define DEBUG_REFS_FATAL_SANITY_CHECKS 0
+#define DEBUG_REFS_ENABLED_BY_DEFAULT 1
+#define DEBUG_REFS_CALLSTACK_ENABLED 1
+
+// log all reference counting operations
+#define PRINT_REFS 0
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+#define INITIAL_STRONG_VALUE (1<<28)
+
+// ---------------------------------------------------------------------------
+
+class RefBase::weakref_impl : public RefBase::weakref_type
+{
+public:
+ volatile int32_t mStrong;
+ volatile int32_t mWeak;
+ RefBase* const mBase;
+ volatile int32_t mFlags;
+
+#if !DEBUG_REFS
+
+ weakref_impl(RefBase* base)
+ : mStrong(INITIAL_STRONG_VALUE)
+ , mWeak(0)
+ , mBase(base)
+ , mFlags(0)
+ {
+ }
+
+ void addStrongRef(const void* /*id*/) { }
+ void removeStrongRef(const void* /*id*/) { }
+ void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
+ void addWeakRef(const void* /*id*/) { }
+ void removeWeakRef(const void* /*id*/) { }
+ void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
+ void printRefs() const { }
+ void trackMe(bool, bool) { }
+
+#else
+
+ weakref_impl(RefBase* base)
+ : mStrong(INITIAL_STRONG_VALUE)
+ , mWeak(0)
+ , mBase(base)
+ , mFlags(0)
+ , mStrongRefs(NULL)
+ , mWeakRefs(NULL)
+ , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
+ , mRetain(false)
+ {
+ }
+
+ ~weakref_impl()
+ {
+ bool dumpStack = false;
+ if (!mRetain && mStrongRefs != NULL) {
+ dumpStack = true;
+#if DEBUG_REFS_FATAL_SANITY_CHECKS
+ LOG_ALWAYS_FATAL("Strong references remain!");
+#else
+ ALOGE("Strong references remain:");
+#endif
+ ref_entry* refs = mStrongRefs;
+ while (refs) {
+ char inc = refs->ref >= 0 ? '+' : '-';
+ ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
+#if DEBUG_REFS_CALLSTACK_ENABLED
+ refs->stack.dump();
+#endif
+ refs = refs->next;
+ }
+ }
+
+ if (!mRetain && mWeakRefs != NULL) {
+ dumpStack = true;
+#if DEBUG_REFS_FATAL_SANITY_CHECKS
+ LOG_ALWAYS_FATAL("Weak references remain:");
+#else
+ ALOGE("Weak references remain!");
+#endif
+ ref_entry* refs = mWeakRefs;
+ while (refs) {
+ char inc = refs->ref >= 0 ? '+' : '-';
+ ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
+#if DEBUG_REFS_CALLSTACK_ENABLED
+ refs->stack.dump();
+#endif
+ refs = refs->next;
+ }
+ }
+ if (dumpStack) {
+ ALOGE("above errors at:");
+ CallStack stack;
+ stack.update();
+ stack.dump();
+ }
+ }
+
+ void addStrongRef(const void* id) {
+ //ALOGD_IF(mTrackEnabled,
+ // "addStrongRef: RefBase=%p, id=%p", mBase, id);
+ addRef(&mStrongRefs, id, mStrong);
+ }
+
+ void removeStrongRef(const void* id) {
+ //ALOGD_IF(mTrackEnabled,
+ // "removeStrongRef: RefBase=%p, id=%p", mBase, id);
+ if (!mRetain) {
+ removeRef(&mStrongRefs, id);
+ } else {
+ addRef(&mStrongRefs, id, -mStrong);
+ }
+ }
+
+ void renameStrongRefId(const void* old_id, const void* new_id) {
+ //ALOGD_IF(mTrackEnabled,
+ // "renameStrongRefId: RefBase=%p, oid=%p, nid=%p",
+ // mBase, old_id, new_id);
+ renameRefsId(mStrongRefs, old_id, new_id);
+ }
+
+ void addWeakRef(const void* id) {
+ addRef(&mWeakRefs, id, mWeak);
+ }
+
+ void removeWeakRef(const void* id) {
+ if (!mRetain) {
+ removeRef(&mWeakRefs, id);
+ } else {
+ addRef(&mWeakRefs, id, -mWeak);
+ }
+ }
+
+ void renameWeakRefId(const void* old_id, const void* new_id) {
+ renameRefsId(mWeakRefs, old_id, new_id);
+ }
+
+ void trackMe(bool track, bool retain)
+ {
+ mTrackEnabled = track;
+ mRetain = retain;
+ }
+
+ void printRefs() const
+ {
+ String8 text;
+
+ {
+ Mutex::Autolock _l(mMutex);
+ char buf[128];
+ sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this);
+ text.append(buf);
+ printRefsLocked(&text, mStrongRefs);
+ sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this);
+ text.append(buf);
+ printRefsLocked(&text, mWeakRefs);
+ }
+
+ {
+ char name[100];
+ snprintf(name, 100, "/data/%p.stack", this);
+ int rc = open(name, O_RDWR | O_CREAT | O_APPEND);
+ if (rc >= 0) {
+ write(rc, text.string(), text.length());
+ close(rc);
+ ALOGD("STACK TRACE for %p saved in %s", this, name);
+ }
+ else ALOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this,
+ name, strerror(errno));
+ }
+ }
+
+private:
+ struct ref_entry
+ {
+ ref_entry* next;
+ const void* id;
+#if DEBUG_REFS_CALLSTACK_ENABLED
+ CallStack stack;
+#endif
+ int32_t ref;
+ };
+
+ void addRef(ref_entry** refs, const void* id, int32_t mRef)
+ {
+ if (mTrackEnabled) {
+ AutoMutex _l(mMutex);
+
+ ref_entry* ref = new ref_entry;
+ // Reference count at the time of the snapshot, but before the
+ // update. Positive value means we increment, negative--we
+ // decrement the reference count.
+ ref->ref = mRef;
+ ref->id = id;
+#if DEBUG_REFS_CALLSTACK_ENABLED
+ ref->stack.update(2);
+#endif
+ ref->next = *refs;
+ *refs = ref;
+ }
+ }
+
+ void removeRef(ref_entry** refs, const void* id)
+ {
+ if (mTrackEnabled) {
+ AutoMutex _l(mMutex);
+
+ ref_entry* const head = *refs;
+ ref_entry* ref = head;
+ while (ref != NULL) {
+ if (ref->id == id) {
+ *refs = ref->next;
+ delete ref;
+ return;
+ }
+ refs = &ref->next;
+ ref = *refs;
+ }
+
+#if DEBUG_REFS_FATAL_SANITY_CHECKS
+ LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p"
+ "(weakref_type %p) that doesn't exist!",
+ id, mBase, this);
+#endif
+
+ ALOGE("RefBase: removing id %p on RefBase %p"
+ "(weakref_type %p) that doesn't exist!",
+ id, mBase, this);
+
+ ref = head;
+ while (ref) {
+ char inc = ref->ref >= 0 ? '+' : '-';
+ ALOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref);
+ ref = ref->next;
+ }
+
+ CallStack stack;
+ stack.update();
+ stack.dump();
+ }
+ }
+
+ void renameRefsId(ref_entry* r, const void* old_id, const void* new_id)
+ {
+ if (mTrackEnabled) {
+ AutoMutex _l(mMutex);
+ ref_entry* ref = r;
+ while (ref != NULL) {
+ if (ref->id == old_id) {
+ ref->id = new_id;
+ }
+ ref = ref->next;
+ }
+ }
+ }
+
+ void printRefsLocked(String8* out, const ref_entry* refs) const
+ {
+ char buf[128];
+ while (refs) {
+ char inc = refs->ref >= 0 ? '+' : '-';
+ sprintf(buf, "\t%c ID %p (ref %d):\n",
+ inc, refs->id, refs->ref);
+ out->append(buf);
+#if DEBUG_REFS_CALLSTACK_ENABLED
+ out->append(refs->stack.toString("\t\t"));
+#else
+ out->append("\t\t(call stacks disabled)");
+#endif
+ refs = refs->next;
+ }
+ }
+
+ mutable Mutex mMutex;
+ ref_entry* mStrongRefs;
+ ref_entry* mWeakRefs;
+
+ bool mTrackEnabled;
+ // Collect stack traces on addref and removeref, instead of deleting the stack references
+ // on removeref that match the address ones.
+ bool mRetain;
+
+#endif
+};
+
+// ---------------------------------------------------------------------------
+
+void RefBase::incStrong(const void* id) const
+{
+ weakref_impl* const refs = mRefs;
+ refs->incWeak(id);
+
+ refs->addStrongRef(id);
+ const int32_t c = android_atomic_inc(&refs->mStrong);
+ ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
+#if PRINT_REFS
+ ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
+#endif
+ if (c != INITIAL_STRONG_VALUE) {
+ return;
+ }
+
+ android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
+ refs->mBase->onFirstRef();
+}
+
+void RefBase::decStrong(const void* id) const
+{
+ weakref_impl* const refs = mRefs;
+ refs->removeStrongRef(id);
+ const int32_t c = android_atomic_dec(&refs->mStrong);
+#if PRINT_REFS
+ ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
+#endif
+ ALOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
+ if (c == 1) {
+ refs->mBase->onLastStrongRef(id);
+ if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
+ delete this;
+ }
+ }
+ refs->decWeak(id);
+}
+
+void RefBase::forceIncStrong(const void* id) const
+{
+ weakref_impl* const refs = mRefs;
+ refs->incWeak(id);
+
+ refs->addStrongRef(id);
+ const int32_t c = android_atomic_inc(&refs->mStrong);
+ ALOG_ASSERT(c >= 0, "forceIncStrong called on %p after ref count underflow",
+ refs);
+#if PRINT_REFS
+ ALOGD("forceIncStrong of %p from %p: cnt=%d\n", this, id, c);
+#endif
+
+ switch (c) {
+ case INITIAL_STRONG_VALUE:
+ android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
+ // fall through...
+ case 0:
+ refs->mBase->onFirstRef();
+ }
+}
+
+int32_t RefBase::getStrongCount() const
+{
+ return mRefs->mStrong;
+}
+
+RefBase* RefBase::weakref_type::refBase() const
+{
+ return static_cast<const weakref_impl*>(this)->mBase;
+}
+
+void RefBase::weakref_type::incWeak(const void* id)
+{
+ weakref_impl* const impl = static_cast<weakref_impl*>(this);
+ impl->addWeakRef(id);
+ const int32_t c = android_atomic_inc(&impl->mWeak);
+ ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
+}
+
+
+void RefBase::weakref_type::decWeak(const void* id)
+{
+ weakref_impl* const impl = static_cast<weakref_impl*>(this);
+ impl->removeWeakRef(id);
+ const int32_t c = android_atomic_dec(&impl->mWeak);
+ ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
+ if (c != 1) return;
+
+ if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
+ // This is the regular lifetime case. The object is destroyed
+ // when the last strong reference goes away. Since weakref_impl
+ // outlive the object, it is not destroyed in the dtor, and
+ // we'll have to do it here.
+ if (impl->mStrong == INITIAL_STRONG_VALUE) {
+ // Special case: we never had a strong reference, so we need to
+ // destroy the object now.
+ delete impl->mBase;
+ } else {
+ // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
+ delete impl;
+ }
+ } else {
+ // less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
+ impl->mBase->onLastWeakRef(id);
+ if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
+ // this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
+ // is gone, we can destroy the object.
+ delete impl->mBase;
+ }
+ }
+}
+
+bool RefBase::weakref_type::attemptIncStrong(const void* id)
+{
+ incWeak(id);
+
+ weakref_impl* const impl = static_cast<weakref_impl*>(this);
+
+ int32_t curCount = impl->mStrong;
+ ALOG_ASSERT(curCount >= 0, "attemptIncStrong called on %p after underflow",
+ this);
+ while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
+ if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {
+ break;
+ }
+ curCount = impl->mStrong;
+ }
+
+ if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
+ bool allow;
+ if (curCount == INITIAL_STRONG_VALUE) {
+ // Attempting to acquire first strong reference... this is allowed
+ // if the object does NOT have a longer lifetime (meaning the
+ // implementation doesn't need to see this), or if the implementation
+ // allows it to happen.
+ allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK
+ || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
+ } else {
+ // Attempting to revive the object... this is allowed
+ // if the object DOES have a longer lifetime (so we can safely
+ // call the object with only a weak ref) and the implementation
+ // allows it to happen.
+ allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK
+ && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
+ }
+ if (!allow) {
+ decWeak(id);
+ return false;
+ }
+ curCount = android_atomic_inc(&impl->mStrong);
+
+ // If the strong reference count has already been incremented by
+ // someone else, the implementor of onIncStrongAttempted() is holding
+ // an unneeded reference. So call onLastStrongRef() here to remove it.
+ // (No, this is not pretty.) Note that we MUST NOT do this if we
+ // are in fact acquiring the first reference.
+ if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) {
+ impl->mBase->onLastStrongRef(id);
+ }
+ }
+
+ impl->addStrongRef(id);
+
+#if PRINT_REFS
+ ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
+#endif
+
+ if (curCount == INITIAL_STRONG_VALUE) {
+ android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong);
+ impl->mBase->onFirstRef();
+ }
+
+ return true;
+}
+
+bool RefBase::weakref_type::attemptIncWeak(const void* id)
+{
+ weakref_impl* const impl = static_cast<weakref_impl*>(this);
+
+ int32_t curCount = impl->mWeak;
+ ALOG_ASSERT(curCount >= 0, "attemptIncWeak called on %p after underflow",
+ this);
+ while (curCount > 0) {
+ if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mWeak) == 0) {
+ break;
+ }
+ curCount = impl->mWeak;
+ }
+
+ if (curCount > 0) {
+ impl->addWeakRef(id);
+ }
+
+ return curCount > 0;
+}
+
+int32_t RefBase::weakref_type::getWeakCount() const
+{
+ return static_cast<const weakref_impl*>(this)->mWeak;
+}
+
+void RefBase::weakref_type::printRefs() const
+{
+ static_cast<const weakref_impl*>(this)->printRefs();
+}
+
+void RefBase::weakref_type::trackMe(bool enable, bool retain)
+{
+ static_cast<weakref_impl*>(this)->trackMe(enable, retain);
+}
+
+RefBase::weakref_type* RefBase::createWeak(const void* id) const
+{
+ mRefs->incWeak(id);
+ return mRefs;
+}
+
+RefBase::weakref_type* RefBase::getWeakRefs() const
+{
+ return mRefs;
+}
+
+RefBase::RefBase()
+ : mRefs(new weakref_impl(this))
+{
+}
+
+RefBase::~RefBase()
+{
+ if (mRefs->mStrong == INITIAL_STRONG_VALUE) {
+ // we never acquired a strong (and/or weak) reference on this object.
+ delete mRefs;
+ } else {
+ // life-time of this object is extended to WEAK or FOREVER, in
+ // which case weakref_impl doesn't out-live the object and we
+ // can free it now.
+ if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
+ // It's possible that the weak count is not 0 if the object
+ // re-acquired a weak reference in its destructor
+ if (mRefs->mWeak == 0) {
+ delete mRefs;
+ }
+ }
+ }
+ // for debugging purposes, clear this.
+ const_cast<weakref_impl*&>(mRefs) = NULL;
+}
+
+void RefBase::extendObjectLifetime(int32_t mode)
+{
+ android_atomic_or(mode, &mRefs->mFlags);
+}
+
+void RefBase::onFirstRef()
+{
+}
+
+void RefBase::onLastStrongRef(const void* /*id*/)
+{
+}
+
+bool RefBase::onIncStrongAttempted(uint32_t flags, const void* id)
+{
+ return (flags&FIRST_INC_STRONG) ? true : false;
+}
+
+void RefBase::onLastWeakRef(const void* /*id*/)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+void RefBase::moveReferences(void* dst, void const* src, size_t n,
+ const ReferenceConverterBase& caster)
+{
+#if DEBUG_REFS
+ const size_t itemSize = caster.getReferenceTypeSize();
+ for (size_t i=0 ; i<n ; i++) {
+ void* d = reinterpret_cast<void *>(intptr_t(dst) + i*itemSize);
+ void const* s = reinterpret_cast<void const*>(intptr_t(src) + i*itemSize);
+ RefBase* ref(reinterpret_cast<RefBase*>(caster.getReferenceBase(d)));
+ ref->mRefs->renameStrongRefId(s, d);
+ ref->mRefs->renameWeakRefId(s, d);
+ }
+#endif
+}
+
+// ---------------------------------------------------------------------------
+
+TextOutput& printStrongPointer(TextOutput& to, const void* val)
+{
+ to << "sp<>(" << val << ")";
+ return to;
+}
+
+TextOutput& printWeakPointer(TextOutput& to, const void* val)
+{
+ to << "wp<>(" << val << ")";
+ return to;
+}
+
+
+}; // namespace android
diff --git a/plugins/rpc/VectorImpl.cpp b/plugins/rpc/VectorImpl.cpp
new file mode 100644
index 0000000..e78faa8
--- /dev/null
+++ b/plugins/rpc/VectorImpl.cpp
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#define LOG_TAG "Vector"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include <utils/SharedBuffer.h>
+#include <utils/VectorImpl.h>
+
+/*****************************************************************************/
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+const size_t kMinVectorCapacity = 4;
+
+static inline size_t max(size_t a, size_t b) {
+ return a>b ? a : b;
+}
+
+// ----------------------------------------------------------------------------
+
+VectorImpl::VectorImpl(size_t itemSize, uint32_t flags)
+ : mStorage(0), mCount(0), mFlags(flags), mItemSize(itemSize)
+{
+}
+
+VectorImpl::VectorImpl(const VectorImpl& rhs)
+ : mStorage(rhs.mStorage), mCount(rhs.mCount),
+ mFlags(rhs.mFlags), mItemSize(rhs.mItemSize)
+{
+ if (mStorage) {
+ SharedBuffer::sharedBuffer(mStorage)->acquire();
+ }
+}
+
+VectorImpl::~VectorImpl()
+{
+ ALOG_ASSERT(!mCount,
+ "[%p] "
+ "subclasses of VectorImpl must call finish_vector()"
+ " in their destructor. Leaking %d bytes.",
+ this, (int)(mCount*mItemSize));
+ // We can't call _do_destroy() here because the vtable is already gone.
+}
+
+VectorImpl& VectorImpl::operator = (const VectorImpl& rhs)
+{
+ ALOG_ASSERT(mItemSize == rhs.mItemSize,
+ "Vector<> have different types (this=%p, rhs=%p)", this, &rhs);
+ if (this != &rhs) {
+ release_storage();
+ if (rhs.mCount) {
+ mStorage = rhs.mStorage;
+ mCount = rhs.mCount;
+ SharedBuffer::sharedBuffer(mStorage)->acquire();
+ } else {
+ mStorage = 0;
+ mCount = 0;
+ }
+ }
+ return *this;
+}
+
+void* VectorImpl::editArrayImpl()
+{
+ if (mStorage) {
+ SharedBuffer* sb = SharedBuffer::sharedBuffer(mStorage)->attemptEdit();
+ if (sb == 0) {
+ sb = SharedBuffer::alloc(capacity() * mItemSize);
+ if (sb) {
+ _do_copy(sb->data(), mStorage, mCount);
+ release_storage();
+ mStorage = sb->data();
+ }
+ }
+ }
+ return mStorage;
+}
+
+size_t VectorImpl::capacity() const
+{
+ if (mStorage) {
+ return SharedBuffer::sharedBuffer(mStorage)->size() / mItemSize;
+ }
+ return 0;
+}
+
+ssize_t VectorImpl::insertVectorAt(const VectorImpl& vector, size_t index)
+{
+ return insertArrayAt(vector.arrayImpl(), index, vector.size());
+}
+
+ssize_t VectorImpl::appendVector(const VectorImpl& vector)
+{
+ return insertVectorAt(vector, size());
+}
+
+ssize_t VectorImpl::insertArrayAt(const void* array, size_t index, size_t length)
+{
+ if (index > size())
+ return BAD_INDEX;
+ void* where = _grow(index, length);
+ if (where) {
+ _do_copy(where, array, length);
+ }
+ return where ? index : (ssize_t)NO_MEMORY;
+}
+
+ssize_t VectorImpl::appendArray(const void* array, size_t length)
+{
+ return insertArrayAt(array, size(), length);
+}
+
+ssize_t VectorImpl::insertAt(size_t index, size_t numItems)
+{
+ return insertAt(0, index, numItems);
+}
+
+ssize_t VectorImpl::insertAt(const void* item, size_t index, size_t numItems)
+{
+ if (index > size())
+ return BAD_INDEX;
+ void* where = _grow(index, numItems);
+ if (where) {
+ if (item) {
+ _do_splat(where, item, numItems);
+ } else {
+ _do_construct(where, numItems);
+ }
+ }
+ return where ? index : (ssize_t)NO_MEMORY;
+}
+
+static int sortProxy(const void* lhs, const void* rhs, void* func)
+{
+ return (*(VectorImpl::compar_t)func)(lhs, rhs);
+}
+
+status_t VectorImpl::sort(VectorImpl::compar_t cmp)
+{
+ return sort(sortProxy, (void*)cmp);
+}
+
+status_t VectorImpl::sort(VectorImpl::compar_r_t cmp, void* state)
+{
+ // the sort must be stable. we're using insertion sort which
+ // is well suited for small and already sorted arrays
+ // for big arrays, it could be better to use mergesort
+ const ssize_t count = size();
+ if (count > 1) {
+ void* array = const_cast<void*>(arrayImpl());
+ void* temp = 0;
+ ssize_t i = 1;
+ while (i < count) {
+ void* item = reinterpret_cast<char*>(array) + mItemSize*(i);
+ void* curr = reinterpret_cast<char*>(array) + mItemSize*(i-1);
+ if (cmp(curr, item, state) > 0) {
+
+ if (!temp) {
+ // we're going to have to modify the array...
+ array = editArrayImpl();
+ if (!array) return NO_MEMORY;
+ temp = malloc(mItemSize);
+ if (!temp) return NO_MEMORY;
+ item = reinterpret_cast<char*>(array) + mItemSize*(i);
+ curr = reinterpret_cast<char*>(array) + mItemSize*(i-1);
+ } else {
+ _do_destroy(temp, 1);
+ }
+
+ _do_copy(temp, item, 1);
+
+ ssize_t j = i-1;
+ void* next = reinterpret_cast<char*>(array) + mItemSize*(i);
+ do {
+ _do_destroy(next, 1);
+ _do_copy(next, curr, 1);
+ next = curr;
+ --j;
+ curr = reinterpret_cast<char*>(array) + mItemSize*(j);
+ } while (j>=0 && (cmp(curr, temp, state) > 0));
+
+ _do_destroy(next, 1);
+ _do_copy(next, temp, 1);
+ }
+ i++;
+ }
+
+ if (temp) {
+ _do_destroy(temp, 1);
+ free(temp);
+ }
+ }
+ return NO_ERROR;
+}
+
+void VectorImpl::pop()
+{
+ if (size())
+ removeItemsAt(size()-1, 1);
+}
+
+void VectorImpl::push()
+{
+ push(0);
+}
+
+void VectorImpl::push(const void* item)
+{
+ insertAt(item, size());
+}
+
+ssize_t VectorImpl::add()
+{
+ return add(0);
+}
+
+ssize_t VectorImpl::add(const void* item)
+{
+ return insertAt(item, size());
+}
+
+ssize_t VectorImpl::replaceAt(size_t index)
+{
+ return replaceAt(0, index);
+}
+
+ssize_t VectorImpl::replaceAt(const void* prototype, size_t index)
+{
+ ALOG_ASSERT(index<size(),
+ "[%p] replace: index=%d, size=%d", this, (int)index, (int)size());
+
+ void* item = editItemLocation(index);
+ 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);
+}
+
+ssize_t VectorImpl::removeItemsAt(size_t index, size_t count)
+{
+ ALOG_ASSERT((index+count)<=size(),
+ "[%p] remove: index=%d, count=%d, size=%d",
+ this, (int)index, (int)count, (int)size());
+
+ if ((index+count) > size())
+ return BAD_VALUE;
+ _shrink(index, count);
+ return index;
+}
+
+void VectorImpl::finish_vector()
+{
+ release_storage();
+ mStorage = 0;
+ mCount = 0;
+}
+
+void VectorImpl::clear()
+{
+ _shrink(0, mCount);
+}
+
+void* VectorImpl::editItemLocation(size_t index)
+{
+ ALOG_ASSERT(index<capacity(),
+ "[%p] editItemLocation: index=%d, capacity=%d, count=%d",
+ this, (int)index, (int)capacity(), (int)mCount);
+
+ void* buffer = editArrayImpl();
+ if (buffer)
+ return reinterpret_cast<char*>(buffer) + index*mItemSize;
+ return 0;
+}
+
+const void* VectorImpl::itemLocation(size_t index) const
+{
+ ALOG_ASSERT(index<capacity(),
+ "[%p] itemLocation: index=%d, capacity=%d, count=%d",
+ this, (int)index, (int)capacity(), (int)mCount);
+
+ const void* buffer = arrayImpl();
+ if (buffer)
+ return reinterpret_cast<const char*>(buffer) + index*mItemSize;
+ return 0;
+}
+
+ssize_t VectorImpl::setCapacity(size_t new_capacity)
+{
+ size_t current_capacity = capacity();
+ ssize_t amount = new_capacity - size();
+ if (amount <= 0) {
+ // we can't reduce the capacity
+ return current_capacity;
+ }
+ SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
+ if (sb) {
+ void* array = sb->data();
+ _do_copy(array, mStorage, size());
+ release_storage();
+ mStorage = const_cast<void*>(array);
+ } else {
+ return NO_MEMORY;
+ }
+ return new_capacity;
+}
+
+void VectorImpl::release_storage()
+{
+ if (mStorage) {
+ const SharedBuffer* sb = SharedBuffer::sharedBuffer(mStorage);
+ if (sb->release(SharedBuffer::eKeepStorage) == 1) {
+ _do_destroy(mStorage, mCount);
+ SharedBuffer::dealloc(sb);
+ }
+ }
+}
+
+void* VectorImpl::_grow(size_t where, size_t amount)
+{
+// ALOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
+// this, (int)where, (int)amount, (int)mCount, (int)capacity());
+
+ ALOG_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);
+// ALOGV("grow vector %p, new_capacity=%d", this, (int)new_capacity);
+ if ((mStorage) &&
+ (mCount==where) &&
+ (mFlags & HAS_TRIVIAL_COPY) &&
+ (mFlags & HAS_TRIVIAL_DTOR))
+ {
+ const SharedBuffer* cur_sb = SharedBuffer::sharedBuffer(mStorage);
+ SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
+ mStorage = sb->data();
+ } else {
+ SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
+ if (sb) {
+ void* array = sb->data();
+ if (where != 0) {
+ _do_copy(array, mStorage, 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);
+ }
+ release_storage();
+ mStorage = const_cast<void*>(array);
+ }
+ }
+ } else {
+ void* array = editArrayImpl();
+ if (where != mCount) {
+ const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize;
+ void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
+ _do_move_forward(to, from, mCount - where);
+ }
+ }
+ mCount = new_size;
+ void* free_space = const_cast<void*>(itemLocation(where));
+ return free_space;
+}
+
+void VectorImpl::_shrink(size_t where, size_t amount)
+{
+ if (!mStorage)
+ return;
+
+// ALOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
+// this, (int)where, (int)amount, (int)mCount, (int)capacity());
+
+ ALOG_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);
+// ALOGV("shrink vector %p, new_capacity=%d", this, (int)new_capacity);
+ if ((where == new_size) &&
+ (mFlags & HAS_TRIVIAL_COPY) &&
+ (mFlags & HAS_TRIVIAL_DTOR))
+ {
+ const SharedBuffer* cur_sb = SharedBuffer::sharedBuffer(mStorage);
+ SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
+ mStorage = sb->data();
+ } else {
+ SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
+ if (sb) {
+ void* array = sb->data();
+ if (where != 0) {
+ _do_copy(array, mStorage, where);
+ }
+ 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, new_size - where);
+ }
+ release_storage();
+ mStorage = const_cast<void*>(array);
+ }
+ }
+ } else {
+ void* array = editArrayImpl();
+ void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
+ _do_destroy(to, amount);
+ if (where != new_size) {
+ const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
+ _do_move_backward(to, from, new_size - where);
+ }
+ }
+ mCount = new_size;
+}
+
+size_t VectorImpl::itemSize() const {
+ return mItemSize;
+}
+
+void VectorImpl::_do_construct(void* storage, size_t num) const
+{
+ if (!(mFlags & HAS_TRIVIAL_CTOR)) {
+ do_construct(storage, num);
+ }
+}
+
+void VectorImpl::_do_destroy(void* storage, size_t num) const
+{
+ if (!(mFlags & HAS_TRIVIAL_DTOR)) {
+ do_destroy(storage, num);
+ }
+}
+
+void VectorImpl::_do_copy(void* dest, const void* from, size_t num) const
+{
+ if (!(mFlags & HAS_TRIVIAL_COPY)) {
+ do_copy(dest, from, num);
+ } else {
+ memcpy(dest, from, num*itemSize());
+ }
+}
+
+void VectorImpl::_do_splat(void* dest, const void* item, size_t num) const {
+ do_splat(dest, item, num);
+}
+
+void VectorImpl::_do_move_forward(void* dest, const void* from, size_t num) const {
+ do_move_forward(dest, from, num);
+}
+
+void VectorImpl::_do_move_backward(void* dest, const void* from, size_t num) const {
+ do_move_backward(dest, from, num);
+}
+
+void VectorImpl::reservedVectorImpl1() { }
+void VectorImpl::reservedVectorImpl2() { }
+void VectorImpl::reservedVectorImpl3() { }
+void VectorImpl::reservedVectorImpl4() { }
+void VectorImpl::reservedVectorImpl5() { }
+void VectorImpl::reservedVectorImpl6() { }
+void VectorImpl::reservedVectorImpl7() { }
+void VectorImpl::reservedVectorImpl8() { }
+
+/*****************************************************************************/
+
+SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags)
+ : VectorImpl(itemSize, flags)
+{
+}
+
+SortedVectorImpl::SortedVectorImpl(const VectorImpl& rhs)
+: VectorImpl(rhs)
+{
+}
+
+SortedVectorImpl::~SortedVectorImpl()
+{
+}
+
+SortedVectorImpl& SortedVectorImpl::operator = (const SortedVectorImpl& rhs)
+{
+ return static_cast<SortedVectorImpl&>( VectorImpl::operator = (static_cast<const VectorImpl&>(rhs)) );
+}
+
+ssize_t SortedVectorImpl::indexOf(const void* item) const
+{
+ return _indexOrderOf(item);
+}
+
+size_t SortedVectorImpl::orderOf(const void* item) const
+{
+ size_t o;
+ _indexOrderOf(item, &o);
+ return o;
+}
+
+ssize_t SortedVectorImpl::_indexOrderOf(const void* item, size_t* order) const
+{
+ // binary search
+ ssize_t err = NAME_NOT_FOUND;
+ ssize_t l = 0;
+ ssize_t h = size()-1;
+ ssize_t mid;
+ const void* a = arrayImpl();
+ const size_t s = itemSize();
+ while (l <= h) {
+ mid = l + (h - l)/2;
+ const void* const curr = reinterpret_cast<const char *>(a) + (mid*s);
+ const int c = do_compare(curr, item);
+ if (c == 0) {
+ err = l = mid;
+ break;
+ } else if (c < 0) {
+ l = mid + 1;
+ } else {
+ h = mid - 1;
+ }
+ }
+ if (order) *order = l;
+ return err;
+}
+
+ssize_t SortedVectorImpl::add(const void* item)
+{
+ size_t order;
+ ssize_t index = _indexOrderOf(item, &order);
+ if (index < 0) {
+ index = VectorImpl::insertAt(item, order, 1);
+ } else {
+ index = VectorImpl::replaceAt(item, index);
+ }
+ return index;
+}
+
+ssize_t SortedVectorImpl::merge(const VectorImpl& vector)
+{
+ // naive merge...
+ if (!vector.isEmpty()) {
+ const void* buffer = vector.arrayImpl();
+ const size_t is = itemSize();
+ size_t s = vector.size();
+ for (size_t i=0 ; i<s ; i++) {
+ ssize_t err = add( reinterpret_cast<const char*>(buffer) + i*is );
+ if (err<0) {
+ return err;
+ }
+ }
+ }
+ return NO_ERROR;
+}
+
+ssize_t SortedVectorImpl::merge(const SortedVectorImpl& vector)
+{
+ // we've merging a sorted vector... nice!
+ ssize_t err = NO_ERROR;
+ if (!vector.isEmpty()) {
+ // first take care of the case where the vectors are sorted together
+ if (do_compare(vector.itemLocation(vector.size()-1), arrayImpl()) <= 0) {
+ err = VectorImpl::insertVectorAt(static_cast<const VectorImpl&>(vector), 0);
+ } else if (do_compare(vector.arrayImpl(), itemLocation(size()-1)) >= 0) {
+ err = VectorImpl::appendVector(static_cast<const VectorImpl&>(vector));
+ } else {
+ // this could be made a little better
+ err = merge(static_cast<const VectorImpl&>(vector));
+ }
+ }
+ return err;
+}
+
+ssize_t SortedVectorImpl::remove(const void* item)
+{
+ ssize_t i = indexOf(item);
+ if (i>=0) {
+ VectorImpl::removeItemsAt(i, 1);
+ }
+ return i;
+}
+
+void SortedVectorImpl::reservedSortedVectorImpl1() { };
+void SortedVectorImpl::reservedSortedVectorImpl2() { };
+void SortedVectorImpl::reservedSortedVectorImpl3() { };
+void SortedVectorImpl::reservedSortedVectorImpl4() { };
+void SortedVectorImpl::reservedSortedVectorImpl5() { };
+void SortedVectorImpl::reservedSortedVectorImpl6() { };
+void SortedVectorImpl::reservedSortedVectorImpl7() { };
+void SortedVectorImpl::reservedSortedVectorImpl8() { };
+
+
+/*****************************************************************************/
+
+}; // namespace android
+
diff --git a/plugins/rpc/binder_plugin.cc b/plugins/rpc/binder_plugin.cc
new file mode 100644
index 0000000..fa9358e
--- /dev/null
+++ b/plugins/rpc/binder_plugin.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Politecnico di Milano
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <
http://www.gnu.org/licenses/>.
+ */
+
+#include "binder_plugin.h"
+#include "binder_rpc.h"
+#include "bbque/plugins/static_plugin.h"
+
+namespace bp = bbque::plugins;
+
+extern "C"
+int32_t PF_exitFunc() {
+ return 0;
+}
+
+extern "C"
+PF_ExitFunc PF_initPlugin(const PF_PlatformServices * params) {
+ int res = 0;
+
+
+ PF_RegisterParams rp;
+ rp.version.major = 1;
+ rp.version.minor = 0;
+ rp.programming_language = PF_LANG_CPP;
+
+ // Registering Binder RPC Module
+ rp.CreateFunc = bp::BinderRPC::Create;
+ rp.DestroyFunc = bp::BinderRPC::Destroy;
+ res = params->RegisterObject((const char *)MODULE_NAMESPACE, &rp);
+ if (res < 0)
+ return NULL;
+
+ return PF_exitFunc;
+
+}
+PLUGIN_INIT(PF_initPlugin);
+
diff --git a/plugins/rpc/binder_plugin.h b/plugins/rpc/binder_plugin.h
new file mode 100644
index 0000000..40a0878
--- /dev/null
+++ b/plugins/rpc/binder_plugin.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 Politecnico di Milano
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <
http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BBQUE_RPC_BINDER_PLUGIN_H_
+#define BBQUE_RPC_BINDER_PLUGIN_H_
+
+#include <cstdint>
+
+#include "bbque/plugins/plugin.h"
+
+extern "C" int32_t PF_exitFunc();
+extern "C" PF_ExitFunc PF_initPlugin(const PF_PlatformServices * params);
+
+#endif // BBQUE_RPC_BINDER_PLUGIN_H_
diff --git a/plugins/rpc/binder_rpc.cc b/plugins/rpc/binder_rpc.cc
new file mode 100644
index 0000000..0532354
--- /dev/null
+++ b/plugins/rpc/binder_rpc.cc
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2012 Politecnico di Milano
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <
http://www.gnu.org/licenses/>.
+ */
+
+#include "bbque/modules_factory.h"
+
+#include "bbque/config.h"
+#include <boost/filesystem.hpp>
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <csignal>
+
+#include "binder_rpc.h"
+
+namespace br = bbque::rtlib;
+namespace fs = boost::filesystem;
+namespace po = boost::program_options;
+
+BnBbque::BnBbque() {
+ pthread_mutex_init(&m_in, NULL);
+ pthread_cond_init(&newMsg_in, NULL);
+ unread = i_idx = r_idx = 0;
+ incoming = ::malloc(sizeof(Parcel)*MAXPCKS);
+}
+
+//This method is called by Android when a new msg has been sent to us. It runs on a separate (system?) thread.
+status_t BnBbque::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+ //just a check...
+ assert(code == BBQUE_BINDER_TRANSACTION_CODE);
+ data.checkInterface(this);
+ pthread_mutex_lock(&m_in);
+ //copy the arrived parcel entirely to our queue... don't do anything else with the parcel at this time...
+ ::memcpy(&incoming[i_idx], &data, sizeof(Parcel));
+ unread++;
+ //signal that a new msg is available
+ pthread_cond_signal(&newMsg_in);
+ pthread_mutex_unlock(&m_in);
+ if (++i_idx >= MAXPCKS) i_idx = 0; //avoid modulos
+}
+
+
+
+ssize_t BnBbque::getNextMsg(bbque::plugins::RPCChannelIF::rpc_msg_ptr_t & msg) {
+ //this mutex protects the shared incoming array
+ pthread_mutex_lock(&m_in);
+ //if there are no unread messages just wait for a new one...
+ if (unread == 0) pthread_cond_wait(&newMsg_in, &m_in);
+ ssize_t bytes = incoming[r_idx].dataAvail();
+ assert(bytes > 0);
+ //create space for the message and copy there the content of the parcel...
+ //may be optimized accessing directly the data of the parcel (but what can we assume about a parcel lifecycle...)?
+ msg = ::malloc(bytes);
+ incoming[r_idx].read(msg, bytes);
+ incoming[r_idx].freeData();
+ pthread_mutex_unlock(&m_in);
+ //Only 1 thread should access this method... no need for mutex
+ if (++r_idx >= MAXPCKS) r_idx = 0; //avoid unnecessary modulo operations, slow
+ unread--;
+ return bytes;
+}
+
+
+
+namespace bbque { namespace plugins {
+
+typedef struct binder_data {
+ /** The application BINDER filename... not sure it's necessary... */
+ char app_binder_servicename[BBQUE_BINDER_NAME_LENGTH];
+ android::sp<IBbque> binder_srv;
+} binder_data_t;
+
+
+BinderRPC::BinderRPC() :
+
+ initialized(false),
+ rpc_binder_fd(0) {
+
+ // Get a logger
+ plugins::LoggerIF::Configuration conf(MODULE_NAMESPACE);
+ logger = ModulesFactory::GetLoggerModule(std::cref(conf));
+ if (!logger) {
+ if (daemonized)
+ syslog(LOG_INFO, "Build BINDER rpc plugin [%p] FAILED "
+ "(Error: missing logger module)", (void*)this);
+ else
+ fprintf(stdout, FI("Build BINDER rpc plugin [%p] FAILED "
+ "(Error: missing logger module)\n"), (void*)this);
+
+ }
+
+ // Ignore SIGPIPE, which will otherwise result into a BBQ termination.
+ // Indeed, in case of write errors the timeouts allows BBQ to react to
+ // the application not responding or disappearing.
+ signal(SIGPIPE, SIG_IGN);
+
+ assert(logger);
+ logger->Debug("Built BINDER rpc object @%p", (void*)this);
+
+}
+
+BinderRPC::~BinderRPC() {
+
+}
+
+//----- RPCChannelIF module interface
+
+int BinderRPC::Init() {
+ d = new Bbque();
+ //add a new service with a known name
+ android::defaultServiceManager()->addService(String16(BBQUE_SERVICE_NAME), d);
+ //start the pool of threads that will manage incoming transaction for the service
+ android::ProcessState::self()->startThreadPool();
+ return 0;
+}
+
+ssize_t BinderRPC::RecvMessage(rpc_msg_ptr_t & msg) {
+ //getNextMsg blocks the execution until a new msg is available
+ return d->getNextMsg(msg);
+}
+
+RPCChannelIF::plugin_data_t BinderRPC::GetPluginData(
+ rpc_msg_ptr_t & msg) {
+ binder_data_t *pd;
+ br::rpc_msg_APP_PAIR_t hdr;
+
+ // We should also have a valid RPC message
+ assert(msg->typ == br::RPC_APP_PAIR);
+
+ // Build a new set of plugins data
+ pd = (binder_data_t *)::malloc(sizeof(binder_data_t));
+ if (!pd) {
+ printf("Malloc error\n");
+ logger->Error("BINDER RPC: get plugin data (malloc) FAILED");
+ return;
+ }
+
+ bzero(pd, sizeof(binder_data_t));
+ //save the service pid. Maybe unuseful
+ snprintf(pd->app_binder_servicename, BBQUE_BINDER_NAME_LENGTH, "%d",(int)msg->app_pid);
+
+ //save the handle to the desired interface.
+
+ //FIXME: Writing directly a sp in the struct brings to a segfault after the first run of the testapp...
+ //so a dummy location is written first, than it is copied to the location saved in the struct
+ //I should check if this degrades performance...
+
+ pd->binder_srv = d->getBbqueServ(pd->app_binder_servicename);
+ //dummy = d->getBbqueServ(pd->app_binder_servicename);
+ //::memcpy(pd->binder_srv, &dummy, sizeof(android::sp<IBbque>));
+
+
+ logger->Info("BINDER RPC: [%s] channel initialization DONE", pd->app_binder_servicename);
+ return plugin_data_t(pd);
+
+}
+
+void BinderRPC::ReleasePluginData(plugin_data_t & pd) {
+ //::free(pd->binder_srv);
+
+}
+
+ssize_t BinderRPC::SendMessage(plugin_data_t & pd, rpc_msg_ptr_t msg,
+ size_t count) {
+ binder_data_t * ppd = (binder_data_t*)pd.get();
+ android::sp<IBbque> mybinder = ppd->binder_srv;
+
+ //FIXME: i have to fetch the pointer to the service each time because I can't safely store a smartpointer for
+ // multiple cycles of the demo app and for multiple demo apps at the same time...
+ //d->getBbqueServ(ppd->app_binder_servicename)->push((void*)msg, count);
+ mybinder->push((void*)msg, count);
+ return count; //is there a way to retrieve the really sent data size?
+}
+
+void BinderRPC::FreeMessage(rpc_msg_ptr_t & msg) {
+ ::free(msg);
+}
+
+//----- static plugin interface
+
+void * BinderRPC::Create(PF_ObjectParams *params) {
+ // Declare the supported options
+ po::options_description binder_rpc_opts_desc("Binder RPC Options");
+ binder_rpc_opts_desc.add_options()
+ (MODULE_NAMESPACE".exa", NULL,
+ "example config option. NOT USED!")
+ ;
+/* FIXME: fix this... also probably causes segfault on line 88 of this file, when checking for daemonized
+ static po::variables_map binder_rpc_opts_value;
+
+ // Get configuration params
+
+ PF_Service_ConfDataIn data_in;
+ data_in.opts_desc = &binder_rpc_opts_desc;
+ PF_Service_ConfDataOut data_out;
+ data_out.opts_value = &binder_rpc_opts_value;
+ PF_ServiceData sd;
+
sd.id = MODULE_NAMESPACE;
+ sd.request = &data_in;
+ sd.response = &data_out;
+
+ int32_t response = params->
+ platform_services->InvokeService(PF_SERVICE_CONF_DATA, sd);
+ if (response!=PF_SERVICE_DONE)
+ return NULL;
+
+ if (daemonized)
+ syslog(LOG_INFO, "Using Binder RPC Plugin");
+ else
+ fprintf(LOG_INFO, "Using Binder RPC Plugin");
+*/
+ return new BinderRPC();
+
+}
+
+int32_t BinderRPC::Destroy(void *plugin) {
+ if (!plugin)
+ return -1;
+ delete (BinderRPC *)plugin;
+ return 0;
+}
+
+
+} // namesapce plugins
+
+} // namespace bque
+
diff --git a/plugins/rpc/binder_rpc.h b/plugins/rpc/binder_rpc.h
new file mode 100644
index 0000000..7152597
--- /dev/null
+++ b/plugins/rpc/binder_rpc.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2012 Politecnico di Milano
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <
http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BBQUE_PLUGINS_BINDER_RPC_H_
+#define BBQUE_PLUGINS_BINDER_RPC_H_
+
+#include "bbque/rtlib/rpc_messages.h"
+
+#include "bbque/plugins/rpc_channel.h"
+#include "bbque/plugins/plugin.h"
+#include "bbque/plugins/logger.h"
+
+#include "bbque/plugins/rpc_channel.h"
+
+#include <cstdint>
+
+#include <bbque/binder_service.h>
+
+#define MODULE_NAMESPACE RPC_CHANNEL_NAMESPACE".bin"
+
+// These are the parameters received by the PluginManager on create calls
+struct PF_ObjectParams;
+
+namespace bbque { namespace plugins {
+
+/**
+ * @brief A BINDER based implementation of the RPCChannelIF interface.
+ *
+ * This class provide a BINDER based communication channel between the Barbque
+ * RTRM and the applications.
+ */
+class BinderRPC : public RPCChannelIF {
+
+public:
+
+//----- static plugin interface
+
+ /**
+ *
+ */
+ static void * Create(PF_ObjectParams *);
+
+ /**
+ *
+ */
+ static int32_t Destroy(void *);
+
+ ~BinderRPC();
+
+//----- RPCChannelIF module interface
+
+
+ virtual ssize_t RecvMessage(rpc_msg_ptr_t & msg);
+
+ virtual plugin_data_t GetPluginData(rpc_msg_ptr_t & msg);
+
+ virtual void ReleasePluginData(plugin_data_t & pd);
+
+ virtual ssize_t SendMessage(plugin_data_t & pd, rpc_msg_ptr_t msg,
+ size_t count);
+
+ virtual void FreeMessage(rpc_msg_ptr_t & msg);
+
+private:
+ Bbque *d;
+
+ /**
+ * @brief System logger instance
+ */
+ plugins::LoggerIF *logger;
+
+ /**
+ * @brief Thrue if the channel has been correctly initalized
+ */
+ bool initialized;
+
+ /**
+ * @brief The path of the directory for BINDERs creation
+ */
+ std::string conf_binder_dir;
+
+ /**
+ * @brief The RPC server BINDER descriptor
+ */
+ int rpc_binder_fd;
+
+ /**
+ * @brief The plugins constructor
+ * Plugins objects could be build only by using the "create" method.
+ * Usually the PluginManager acts as object
+ * @param
+ * @return
+ */
+ BinderRPC();
+
+ int Init();
+
+};
+
+} // namespace plugins
+
+} // namespace bbque
+
+#endif // BBQUE_PLUGINS_TESTING_H_
diff --git a/plugins/rpc/fifo_rpc.cc b/plugins/rpc/fifo_rpc.cc
index b24e5d0..072bdfe 100644
--- a/plugins/rpc/fifo_rpc.cc
+++ b/plugins/rpc/fifo_rpc.cc
@@ -46,7 +46,7 @@ FifoRPC::FifoRPC(std::string const & fifo_dir) :
syslog(LOG_INFO, "Build FIFO rpc plugin [%p] FAILED "
"(Error: missing logger module)", (void*)this);
else
- fprintf(stdout, FI("Build FIFO rpc plugin [%p] FAILED "
+ fprintf(stdout, FMT_INFO("Build FIFO rpc plugin [%p] FAILED "
"(Error: missing logger module)\n"), (void*)this);
}
@@ -174,6 +174,7 @@ ssize_t FifoRPC::RecvMessage(rpc_msg_ptr_t & msg) {
return bytes;
}
+ logger->Debug("AGGIUNTA: FIFO RPC: messaggio ricevuto...");
// Allocate a new message buffer
fifo_buff_ptr = ::malloc(hdr.fifo_msg_size);
if (!fifo_buff_ptr) {
@@ -441,7 +442,7 @@ void * FifoRPC::Create(PF_ObjectParams *params) {
syslog(LOG_INFO, "Using RPC FIFOs dir [%s]",
conf_fifo_dir.c_str());
else
- fprintf(stderr, FI("FIFO RPC: using dir [%s]\n"),
+ fprintf(stderr, FMT_INFO("FIFO RPC: using dir [%s]\n"),
conf_fifo_dir.c_str());
return new FifoRPC(conf_fifo_dir);
diff --git a/rtlib/Binder.cpp b/rtlib/Binder.cpp
new file mode 100644
index 0000000..1f21f9c
--- /dev/null
+++ b/rtlib/Binder.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2005 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 <binder/Binder.h>
+
+#include <utils/Atomic.h>
+#include <utils/misc.h>
+#include <binder/BpBinder.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+#include <stdio.h>
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+IBinder::IBinder()
+ : RefBase()
+{
+}
+
+IBinder::~IBinder()
+{
+}
+
+// ---------------------------------------------------------------------------
+
+sp<IInterface> IBinder::queryLocalInterface(const String16& descriptor)
+{
+ return NULL;
+}
+
+BBinder* IBinder::localBinder()
+{
+ return NULL;
+}
+
+BpBinder* IBinder::remoteBinder()
+{
+ return NULL;
+}
+
+bool IBinder::checkSubclass(const void* /*subclassID*/) const
+{
+ return false;
+}
+
+// ---------------------------------------------------------------------------
+
+class BBinder::Extras
+{
+public:
+ Mutex mLock;
+ BpBinder::ObjectManager mObjects;
+};
+
+// ---------------------------------------------------------------------------
+
+BBinder::BBinder()
+ : mExtras(NULL)
+{
+}
+
+bool BBinder::isBinderAlive() const
+{
+ return true;
+}
+
+status_t BBinder::pingBinder()
+{
+ return NO_ERROR;
+}
+
+const String16& BBinder::getInterfaceDescriptor() const
+{
+ // This is a local static rather than a global static,
+ // to avoid static initializer ordering issues.
+ static String16 sEmptyDescriptor;
+ ALOGW("reached BBinder::getInterfaceDescriptor (this=%p)", this);
+ return sEmptyDescriptor;
+}
+
+status_t BBinder::transact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ data.setDataPosition(0);
+
+ status_t err = NO_ERROR;
+ switch (code) {
+ case PING_TRANSACTION:
+ reply->writeInt32(pingBinder());
+ break;
+ default:
+ err = onTransact(code, data, reply, flags);
+ break;
+ }
+
+ if (reply != NULL) {
+ reply->setDataPosition(0);
+ }
+
+ return err;
+}
+
+status_t BBinder::linkToDeath(
+ const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
+{
+ return INVALID_OPERATION;
+}
+
+status_t BBinder::unlinkToDeath(
+ const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
+ wp<DeathRecipient>* outRecipient)
+{
+ return INVALID_OPERATION;
+}
+
+status_t BBinder::dump(int fd, const Vector<String16>& args)
+{
+ return NO_ERROR;
+}
+
+void BBinder::attachObject(
+ const void* objectID, void* object, void* cleanupCookie,
+ object_cleanup_func func)
+{
+ Extras* e = mExtras;
+
+ if (!e) {
+ e = new Extras;
+ if (android_atomic_cmpxchg(0, reinterpret_cast<int32_t>(e),
+ reinterpret_cast<volatile int32_t*>(&mExtras)) != 0) {
+ delete e;
+ e = mExtras;
+ }
+ if (e == 0) return; // out of memory
+ }
+
+ AutoMutex _l(e->mLock);
+ e->mObjects.attach(objectID, object, cleanupCookie, func);
+}
+
+void* BBinder::findObject(const void* objectID) const
+{
+ Extras* e = mExtras;
+ if (!e) return NULL;
+
+ AutoMutex _l(e->mLock);
+ return e->mObjects.find(objectID);
+}
+
+void BBinder::detachObject(const void* objectID)
+{
+ Extras* e = mExtras;
+ if (!e) return;
+
+ AutoMutex _l(e->mLock);
+ e->mObjects.detach(objectID);
+}
+
+BBinder* BBinder::localBinder()
+{
+ return this;
+}
+
+BBinder::~BBinder()
+{
+ if (mExtras) delete mExtras;
+}
+
+
+status_t BBinder::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case INTERFACE_TRANSACTION:
+ reply->writeString16(getInterfaceDescriptor());
+ return NO_ERROR;
+
+ case DUMP_TRANSACTION: {
+ int fd = data.readFileDescriptor();
+ int argc = data.readInt32();
+ Vector<String16> args;
+ for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
+ args.add(data.readString16());
+ }
+ return dump(fd, args);
+ }
+
+ case SYSPROPS_TRANSACTION: {
+ report_sysprop_change();
+ return NO_ERROR;
+ }
+
+ default:
+ return UNKNOWN_TRANSACTION;
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+enum {
+ // This is used to transfer ownership of the remote binder from
+ // the BpRefBase object holding it (when it is constructed), to the
+ // owner of the BpRefBase object when it first acquires that BpRefBase.
+ kRemoteAcquired = 0x00000001
+};
+
+BpRefBase::BpRefBase(const sp<IBinder>& o)
+ : mRemote(o.get()), mRefs(NULL), mState(0)
+{
+ extendObjectLifetime(OBJECT_LIFETIME_WEAK);
+
+ if (mRemote) {
+ mRemote->incStrong(this); // Removed on first IncStrong().
+ mRefs = mRemote->createWeak(this); // Held for our entire lifetime.
+ }
+}
+
+BpRefBase::~BpRefBase()
+{
+ if (mRemote) {
+ if (!(mState&kRemoteAcquired)) {
+ mRemote->decStrong(this);
+ }
+ mRefs->decWeak(this);
+ }
+}
+
+void BpRefBase::onFirstRef()
+{
+ android_atomic_or(kRemoteAcquired, &mState);
+}
+
+void BpRefBase::onLastStrongRef(const void* id)
+{
+ if (mRemote) {
+ mRemote->decStrong(this);
+ }
+}
+
+bool BpRefBase::onIncStrongAttempted(uint32_t flags, const void* id)
+{
+ return mRemote ? mRefs->attemptIncStrong(this) : false;
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/rtlib/BpBinder.cpp b/rtlib/BpBinder.cpp
new file mode 100644
index 0000000..47a62db
--- /dev/null
+++ b/rtlib/BpBinder.cpp
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#define LOG_TAG "BpBinder"
+//#define LOG_NDEBUG 0
+
+#include <binder/BpBinder.h>
+
+#include <binder/IPCThreadState.h>
+#include <utils/Log.h>
+
+#include <stdio.h>
+
+//#undef ALOGV
+//#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+BpBinder::ObjectManager::ObjectManager()
+{
+}
+
+BpBinder::ObjectManager::~ObjectManager()
+{
+ kill();
+}
+
+void BpBinder::ObjectManager::attach(
+ const void* objectID, void* object, void* cleanupCookie,
+ IBinder::object_cleanup_func func)
+{
+ entry_t e;
+ e.object = object;
+ e.cleanupCookie = cleanupCookie;
+ e.func = func;
+
+ if (mObjects.indexOfKey(objectID) >= 0) {
+ ALOGE("Trying to attach object ID %p to binder ObjectManager %p with object %p, but object ID already in use",
+ objectID, this, object);
+ return;
+ }
+
+ mObjects.add(objectID, e);
+}
+
+void* BpBinder::ObjectManager::find(const void* objectID) const
+{
+ const ssize_t i = mObjects.indexOfKey(objectID);
+ if (i < 0) return NULL;
+ return mObjects.valueAt(i).object;
+}
+
+void BpBinder::ObjectManager::detach(const void* objectID)
+{
+ mObjects.removeItem(objectID);
+}
+
+void BpBinder::ObjectManager::kill()
+{
+ const size_t N = mObjects.size();
+ ALOGV("Killing %d objects in manager %p", N, this);
+ for (size_t i=0; i<N; i++) {
+ const entry_t& e = mObjects.valueAt(i);
+ if (e.func != NULL) {
+ e.func(mObjects.keyAt(i), e.object, e.cleanupCookie);
+ }
+ }
+
+ mObjects.clear();
+}
+
+// ---------------------------------------------------------------------------
+
+BpBinder::BpBinder(int32_t handle)
+ : mHandle(handle)
+ , mAlive(1)
+ , mObitsSent(0)
+ , mObituaries(NULL)
+{
+ ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
+
+ extendObjectLifetime(OBJECT_LIFETIME_WEAK);
+ IPCThreadState::self()->incWeakHandle(handle);
+}
+
+bool BpBinder::isDescriptorCached() const {
+ Mutex::Autolock _l(mLock);
+ return mDescriptorCache.size() ? true : false;
+}
+
+const String16& BpBinder::getInterfaceDescriptor() const
+{
+ if (isDescriptorCached() == false) {
+ Parcel send, reply;
+ // do the IPC without a lock held.
+ status_t err = const_cast<BpBinder*>(this)->transact(
+ INTERFACE_TRANSACTION, send, &reply);
+ if (err == NO_ERROR) {
+ String16 res(reply.readString16());
+ Mutex::Autolock _l(mLock);
+ // mDescriptorCache could have been assigned while the lock was
+ // released.
+ if (mDescriptorCache.size() == 0)
+ mDescriptorCache = res;
+ }
+ }
+
+ // we're returning a reference to a non-static object here. Usually this
+ // is not something smart to do, however, with binder objects it is
+ // (usually) safe because they are reference-counted.
+
+ return mDescriptorCache;
+}
+
+bool BpBinder::isBinderAlive() const
+{
+ return mAlive != 0;
+}
+
+status_t BpBinder::pingBinder()
+{
+ Parcel send;
+ Parcel reply;
+ status_t err = transact(PING_TRANSACTION, send, &reply);
+ if (err != NO_ERROR) return err;
+ if (reply.dataSize() < sizeof(status_t)) return NOT_ENOUGH_DATA;
+ return (status_t)reply.readInt32();
+}
+
+status_t BpBinder::dump(int fd, const Vector<String16>& args)
+{
+ Parcel send;
+ Parcel reply;
+ send.writeFileDescriptor(fd);
+ const size_t numArgs = args.size();
+ send.writeInt32(numArgs);
+ for (size_t i = 0; i < numArgs; i++) {
+ send.writeString16(args[i]);
+ }
+ status_t err = transact(DUMP_TRANSACTION, send, &reply);
+ return err;
+}
+
+status_t BpBinder::transact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ // Once a binder has died, it will never come back to life.
+ if (mAlive) {
+ status_t status = IPCThreadState::self()->transact(
+ mHandle, code, data, reply, flags);
+ if (status == DEAD_OBJECT) mAlive = 0;
+ return status;
+ }
+
+ return DEAD_OBJECT;
+}
+
+status_t BpBinder::linkToDeath(
+ const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
+{
+ Obituary ob;
+ ob.recipient = recipient;
+ ob.cookie = cookie;
+ ob.flags = flags;
+
+ LOG_ALWAYS_FATAL_IF(recipient == NULL,
+ "linkToDeath(): recipient must be non-NULL");
+
+ {
+ AutoMutex _l(mLock);
+
+ if (!mObitsSent) {
+ if (!mObituaries) {
+ mObituaries = new Vector<Obituary>;
+ if (!mObituaries) {
+ return NO_MEMORY;
+ }
+ ALOGV("Requesting death notification: %p handle %d\n", this, mHandle);
+ getWeakRefs()->incWeak(this);
+ IPCThreadState* self = IPCThreadState::self();
+ self->requestDeathNotification(mHandle, this);
+ self->flushCommands();
+ }
+ ssize_t res = mObituaries->add(ob);
+ return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
+ }
+ }
+
+ return DEAD_OBJECT;
+}
+
+status_t BpBinder::unlinkToDeath(
+ const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
+ wp<DeathRecipient>* outRecipient)
+{
+ AutoMutex _l(mLock);
+
+ if (mObitsSent) {
+ return DEAD_OBJECT;
+ }
+
+ const size_t N = mObituaries ? mObituaries->size() : 0;
+ for (size_t i=0; i<N; i++) {
+ const Obituary& obit = mObituaries->itemAt(i);
+ if ((obit.recipient == recipient
+ || (recipient == NULL && obit.cookie == cookie))
+ && obit.flags == flags) {
+ const uint32_t allFlags = obit.flags|flags;
+ if (outRecipient != NULL) {
+ *outRecipient = mObituaries->itemAt(i).recipient;
+ }
+ mObituaries->removeAt(i);
+ if (mObituaries->size() == 0) {
+ ALOGV("Clearing death notification: %p handle %d\n", this, mHandle);
+ IPCThreadState* self = IPCThreadState::self();
+ self->clearDeathNotification(mHandle, this);
+ self->flushCommands();
+ delete mObituaries;
+ mObituaries = NULL;
+ }
+ return NO_ERROR;
+ }
+ }
+
+ return NAME_NOT_FOUND;
+}
+
+void BpBinder::sendObituary()
+{
+ ALOGV("Sending obituary for proxy %p handle %d, mObitsSent=%s\n",
+ this, mHandle, mObitsSent ? "true" : "false");
+
+ mAlive = 0;
+ if (mObitsSent) return;
+
+ mLock.lock();
+ Vector<Obituary>* obits = mObituaries;
+ if(obits != NULL) {
+ ALOGV("Clearing sent death notification: %p handle %d\n", this, mHandle);
+ IPCThreadState* self = IPCThreadState::self();
+ self->clearDeathNotification(mHandle, this);
+ self->flushCommands();
+ mObituaries = NULL;
+ }
+ mObitsSent = 1;
+ mLock.unlock();
+
+ ALOGV("Reporting death of proxy %p for %d recipients\n",
+ this, obits ? obits->size() : 0);
+
+ if (obits != NULL) {
+ const size_t N = obits->size();
+ for (size_t i=0; i<N; i++) {
+ reportOneDeath(obits->itemAt(i));
+ }
+
+ delete obits;
+ }
+}
+
+void BpBinder::reportOneDeath(const Obituary& obit)
+{
+ sp<DeathRecipient> recipient = obit.recipient.promote();
+ ALOGV("Reporting death to recipient: %p\n", recipient.get());
+ if (recipient == NULL) return;
+
+ recipient->binderDied(this);
+}
+
+
+void BpBinder::attachObject(
+ const void* objectID, void* object, void* cleanupCookie,
+ object_cleanup_func func)
+{
+ AutoMutex _l(mLock);
+ ALOGV("Attaching object %p to binder %p (manager=%p)", object, this, &mObjects);
+ mObjects.attach(objectID, object, cleanupCookie, func);
+}
+
+void* BpBinder::findObject(const void* objectID) const
+{
+ AutoMutex _l(mLock);
+ return mObjects.find(objectID);
+}
+
+void BpBinder::detachObject(const void* objectID)
+{
+ AutoMutex _l(mLock);
+ mObjects.detach(objectID);
+}
+
+BpBinder* BpBinder::remoteBinder()
+{
+ return this;
+}
+
+BpBinder::~BpBinder()
+{
+ ALOGV("Destroying BpBinder %p handle %d\n", this, mHandle);
+
+ IPCThreadState* ipc = IPCThreadState::self();
+
+ mLock.lock();
+ Vector<Obituary>* obits = mObituaries;
+ if(obits != NULL) {
+ if (ipc) ipc->clearDeathNotification(mHandle, this);
+ mObituaries = NULL;
+ }
+ mLock.unlock();
+
+ if (obits != NULL) {
+ // XXX Should we tell any remaining DeathRecipient
+ // objects that the last strong ref has gone away, so they
+ // are no longer linked?
+ delete obits;
+ }
+
+ if (ipc) {
+ ipc->expungeHandle(mHandle, this);
+ ipc->decWeakHandle(mHandle);
+ }
+}
+
+void BpBinder::onFirstRef()
+{
+ ALOGV("onFirstRef BpBinder %p handle %d\n", this, mHandle);
+ IPCThreadState* ipc = IPCThreadState::self();
+ if (ipc) ipc->incStrongHandle(mHandle);
+}
+
+void BpBinder::onLastStrongRef(const void* id)
+{
+ ALOGV("onLastStrongRef BpBinder %p handle %d\n", this, mHandle);
+ IF_ALOGV() {
+ printRefs();
+ }
+ IPCThreadState* ipc = IPCThreadState::self();
+ if (ipc) ipc->decStrongHandle(mHandle);
+}
+
+bool BpBinder::onIncStrongAttempted(uint32_t flags, const void* id)
+{
+ ALOGV("onIncStrongAttempted BpBinder %p handle %d\n", this, mHandle);
+ IPCThreadState* ipc = IPCThreadState::self();
+ return ipc ? ipc->attemptIncStrongHandle(mHandle) == NO_ERROR : false;
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/rtlib/CMakeLists.txt b/rtlib/CMakeLists.txt
index 7748b22..2e6e64c 100644
--- a/rtlib/CMakeLists.txt
+++ b/rtlib/CMakeLists.txt
@@ -12,7 +12,6 @@ configure_file (
)
# Add "barbeque" specific flags
-set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBBQUE_RTLIB")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--gc-sections")
@@ -22,6 +21,13 @@ set (RTLIB_SRC bbque_exc ${RTLIB_SRC})
if (CONFIG_BBQUE_RPC_FIFO)
set (RTLIB_SRC rpc_fifo_client ${RTLIB_SRC})
endif (CONFIG_BBQUE_RPC_FIFO)
+if (CONFIG_BBQUE_RPC_BINDER)
+target_link_libraries(
+ /system/lib/libbinder.so
+ )
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -fpermissive /system/lib/libc.so /system/lib/libdl.so /system/lib/libstdc++.so /system/lib/libui.so /system/lib/libm.so /system/lib/libcutils.so /system/lib/libutils.so /system/lib/libbinder.so /system/lib/libz.so /system/lib/liblog.so /system/lib/libcorkscrew.so /system/lib/libgccdemangle.so")
+ set (RTLIB_SRC rpc_binder_client ${PROJECT_SOURCE_DIR}/include/bbque/binder_service IInterface Binder BpBinder RefBase VectorImpl ${RTLIB_SRC})
+endif (CONFIG_BBQUE_RPC_BINDER)
# Build subdirs
add_subdirectory(monitors)
diff --git a/rtlib/IInterface.cpp b/rtlib/IInterface.cpp
new file mode 100644
index 0000000..29acf5d
--- /dev/null
+++ b/rtlib/IInterface.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2005 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 <binder/IInterface.h>
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+IInterface::IInterface()
+ : RefBase() {
+}
+
+IInterface::~IInterface() {
+}
+
+sp<IBinder> IInterface::asBinder()
+{
+ return this ? onAsBinder() : NULL;
+}
+
+sp<const IBinder> IInterface::asBinder() const
+{
+ return this ? const_cast<IInterface*>(this)->onAsBinder() : NULL;
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/rtlib/RefBase.cpp b/rtlib/RefBase.cpp
new file mode 100644
index 0000000..e80a795
--- /dev/null
+++ b/rtlib/RefBase.cpp
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#define LOG_TAG "RefBase"
+
+#include <utils/RefBase.h>
+
+#include <utils/Atomic.h>
+#include <utils/CallStack.h>
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <utils/TextOutput.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <typeinfo>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+// compile with refcounting debugging enabled
+#define DEBUG_REFS 0
+#define DEBUG_REFS_FATAL_SANITY_CHECKS 0
+#define DEBUG_REFS_ENABLED_BY_DEFAULT 1
+#define DEBUG_REFS_CALLSTACK_ENABLED 1
+
+// log all reference counting operations
+#define PRINT_REFS 0
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+#define INITIAL_STRONG_VALUE (1<<28)
+
+// ---------------------------------------------------------------------------
+
+class RefBase::weakref_impl : public RefBase::weakref_type
+{
+public:
+ volatile int32_t mStrong;
+ volatile int32_t mWeak;
+ RefBase* const mBase;
+ volatile int32_t mFlags;
+
+#if !DEBUG_REFS
+
+ weakref_impl(RefBase* base)
+ : mStrong(INITIAL_STRONG_VALUE)
+ , mWeak(0)
+ , mBase(base)
+ , mFlags(0)
+ {
+ }
+
+ void addStrongRef(const void* /*id*/) { }
+ void removeStrongRef(const void* /*id*/) { }
+ void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
+ void addWeakRef(const void* /*id*/) { }
+ void removeWeakRef(const void* /*id*/) { }
+ void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
+ void printRefs() const { }
+ void trackMe(bool, bool) { }
+
+#else
+
+ weakref_impl(RefBase* base)
+ : mStrong(INITIAL_STRONG_VALUE)
+ , mWeak(0)
+ , mBase(base)
+ , mFlags(0)
+ , mStrongRefs(NULL)
+ , mWeakRefs(NULL)
+ , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
+ , mRetain(false)
+ {
+ }
+
+ ~weakref_impl()
+ {
+ bool dumpStack = false;
+ if (!mRetain && mStrongRefs != NULL) {
+ dumpStack = true;
+#if DEBUG_REFS_FATAL_SANITY_CHECKS
+ LOG_ALWAYS_FATAL("Strong references remain!");
+#else
+ ALOGE("Strong references remain:");
+#endif
+ ref_entry* refs = mStrongRefs;
+ while (refs) {
+ char inc = refs->ref >= 0 ? '+' : '-';
+ ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
+#if DEBUG_REFS_CALLSTACK_ENABLED
+ refs->stack.dump();
+#endif
+ refs = refs->next;
+ }
+ }
+
+ if (!mRetain && mWeakRefs != NULL) {
+ dumpStack = true;
+#if DEBUG_REFS_FATAL_SANITY_CHECKS
+ LOG_ALWAYS_FATAL("Weak references remain:");
+#else
+ ALOGE("Weak references remain!");
+#endif
+ ref_entry* refs = mWeakRefs;
+ while (refs) {
+ char inc = refs->ref >= 0 ? '+' : '-';
+ ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
+#if DEBUG_REFS_CALLSTACK_ENABLED
+ refs->stack.dump();
+#endif
+ refs = refs->next;
+ }
+ }
+ if (dumpStack) {
+ ALOGE("above errors at:");
+ CallStack stack;
+ stack.update();
+ stack.dump();
+ }
+ }
+
+ void addStrongRef(const void* id) {
+ //ALOGD_IF(mTrackEnabled,
+ // "addStrongRef: RefBase=%p, id=%p", mBase, id);
+ addRef(&mStrongRefs, id, mStrong);
+ }
+
+ void removeStrongRef(const void* id) {
+ //ALOGD_IF(mTrackEnabled,
+ // "removeStrongRef: RefBase=%p, id=%p", mBase, id);
+ if (!mRetain) {
+ removeRef(&mStrongRefs, id);
+ } else {
+ addRef(&mStrongRefs, id, -mStrong);
+ }
+ }
+
+ void renameStrongRefId(const void* old_id, const void* new_id) {
+ //ALOGD_IF(mTrackEnabled,
+ // "renameStrongRefId: RefBase=%p, oid=%p, nid=%p",
+ // mBase, old_id, new_id);
+ renameRefsId(mStrongRefs, old_id, new_id);
+ }
+
+ void addWeakRef(const void* id) {
+ addRef(&mWeakRefs, id, mWeak);
+ }
+
+ void removeWeakRef(const void* id) {
+ if (!mRetain) {
+ removeRef(&mWeakRefs, id);
+ } else {
+ addRef(&mWeakRefs, id, -mWeak);
+ }
+ }
+
+ void renameWeakRefId(const void* old_id, const void* new_id) {
+ renameRefsId(mWeakRefs, old_id, new_id);
+ }
+
+ void trackMe(bool track, bool retain)
+ {
+ mTrackEnabled = track;
+ mRetain = retain;
+ }
+
+ void printRefs() const
+ {
+ String8 text;
+
+ {
+ Mutex::Autolock _l(mMutex);
+ char buf[128];
+ sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this);
+ text.append(buf);
+ printRefsLocked(&text, mStrongRefs);
+ sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this);
+ text.append(buf);
+ printRefsLocked(&text, mWeakRefs);
+ }
+
+ {
+ char name[100];
+ snprintf(name, 100, "/data/%p.stack", this);
+ int rc = open(name, O_RDWR | O_CREAT | O_APPEND);
+ if (rc >= 0) {
+ write(rc, text.string(), text.length());
+ close(rc);
+ ALOGD("STACK TRACE for %p saved in %s", this, name);
+ }
+ else ALOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this,
+ name, strerror(errno));
+ }
+ }
+
+private:
+ struct ref_entry
+ {
+ ref_entry* next;
+ const void* id;
+#if DEBUG_REFS_CALLSTACK_ENABLED
+ CallStack stack;
+#endif
+ int32_t ref;
+ };
+
+ void addRef(ref_entry** refs, const void* id, int32_t mRef)
+ {
+ if (mTrackEnabled) {
+ AutoMutex _l(mMutex);
+
+ ref_entry* ref = new ref_entry;
+ // Reference count at the time of the snapshot, but before the
+ // update. Positive value means we increment, negative--we
+ // decrement the reference count.
+ ref->ref = mRef;
+ ref->id = id;
+#if DEBUG_REFS_CALLSTACK_ENABLED
+ ref->stack.update(2);
+#endif
+ ref->next = *refs;
+ *refs = ref;
+ }
+ }
+
+ void removeRef(ref_entry** refs, const void* id)
+ {
+ if (mTrackEnabled) {
+ AutoMutex _l(mMutex);
+
+ ref_entry* const head = *refs;
+ ref_entry* ref = head;
+ while (ref != NULL) {
+ if (ref->id == id) {
+ *refs = ref->next;
+ delete ref;
+ return;
+ }
+ refs = &ref->next;
+ ref = *refs;
+ }
+
+#if DEBUG_REFS_FATAL_SANITY_CHECKS
+ LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p"
+ "(weakref_type %p) that doesn't exist!",
+ id, mBase, this);
+#endif
+
+ ALOGE("RefBase: removing id %p on RefBase %p"
+ "(weakref_type %p) that doesn't exist!",
+ id, mBase, this);
+
+ ref = head;
+ while (ref) {
+ char inc = ref->ref >= 0 ? '+' : '-';
+ ALOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref);
+ ref = ref->next;
+ }
+
+ CallStack stack;
+ stack.update();
+ stack.dump();
+ }
+ }
+
+ void renameRefsId(ref_entry* r, const void* old_id, const void* new_id)
+ {
+ if (mTrackEnabled) {
+ AutoMutex _l(mMutex);
+ ref_entry* ref = r;
+ while (ref != NULL) {
+ if (ref->id == old_id) {
+ ref->id = new_id;
+ }
+ ref = ref->next;
+ }
+ }
+ }
+
+ void printRefsLocked(String8* out, const ref_entry* refs) const
+ {
+ char buf[128];
+ while (refs) {
+ char inc = refs->ref >= 0 ? '+' : '-';
+ sprintf(buf, "\t%c ID %p (ref %d):\n",
+ inc, refs->id, refs->ref);
+ out->append(buf);
+#if DEBUG_REFS_CALLSTACK_ENABLED
+ out->append(refs->stack.toString("\t\t"));
+#else
+ out->append("\t\t(call stacks disabled)");
+#endif
+ refs = refs->next;
+ }
+ }
+
+ mutable Mutex mMutex;
+ ref_entry* mStrongRefs;
+ ref_entry* mWeakRefs;
+
+ bool mTrackEnabled;
+ // Collect stack traces on addref and removeref, instead of deleting the stack references
+ // on removeref that match the address ones.
+ bool mRetain;
+
+#endif
+};
+
+// ---------------------------------------------------------------------------
+
+void RefBase::incStrong(const void* id) const
+{
+ weakref_impl* const refs = mRefs;
+ refs->incWeak(id);
+
+ refs->addStrongRef(id);
+ const int32_t c = android_atomic_inc(&refs->mStrong);
+ ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
+#if PRINT_REFS
+ ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
+#endif
+ if (c != INITIAL_STRONG_VALUE) {
+ return;
+ }
+
+ android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
+ refs->mBase->onFirstRef();
+}
+
+void RefBase::decStrong(const void* id) const
+{
+ weakref_impl* const refs = mRefs;
+ refs->removeStrongRef(id);
+ const int32_t c = android_atomic_dec(&refs->mStrong);
+#if PRINT_REFS
+ ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
+#endif
+ ALOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
+ if (c == 1) {
+ refs->mBase->onLastStrongRef(id);
+ if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
+ delete this;
+ }
+ }
+ refs->decWeak(id);
+}
+
+void RefBase::forceIncStrong(const void* id) const
+{
+ weakref_impl* const refs = mRefs;
+ refs->incWeak(id);
+
+ refs->addStrongRef(id);
+ const int32_t c = android_atomic_inc(&refs->mStrong);
+ ALOG_ASSERT(c >= 0, "forceIncStrong called on %p after ref count underflow",
+ refs);
+#if PRINT_REFS
+ ALOGD("forceIncStrong of %p from %p: cnt=%d\n", this, id, c);
+#endif
+
+ switch (c) {
+ case INITIAL_STRONG_VALUE:
+ android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
+ // fall through...
+ case 0:
+ refs->mBase->onFirstRef();
+ }
+}
+
+int32_t RefBase::getStrongCount() const
+{
+ return mRefs->mStrong;
+}
+
+RefBase* RefBase::weakref_type::refBase() const
+{
+ return static_cast<const weakref_impl*>(this)->mBase;
+}
+
+void RefBase::weakref_type::incWeak(const void* id)
+{
+ weakref_impl* const impl = static_cast<weakref_impl*>(this);
+ impl->addWeakRef(id);
+ const int32_t c = android_atomic_inc(&impl->mWeak);
+ ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
+}
+
+
+void RefBase::weakref_type::decWeak(const void* id)
+{
+ weakref_impl* const impl = static_cast<weakref_impl*>(this);
+ impl->removeWeakRef(id);
+ const int32_t c = android_atomic_dec(&impl->mWeak);
+ ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
+ if (c != 1) return;
+
+ if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
+ // This is the regular lifetime case. The object is destroyed
+ // when the last strong reference goes away. Since weakref_impl
+ // outlive the object, it is not destroyed in the dtor, and
+ // we'll have to do it here.
+ if (impl->mStrong == INITIAL_STRONG_VALUE) {
+ // Special case: we never had a strong reference, so we need to
+ // destroy the object now.
+ delete impl->mBase;
+ } else {
+ // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
+ delete impl;
+ }
+ } else {
+ // less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
+ impl->mBase->onLastWeakRef(id);
+ if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
+ // this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
+ // is gone, we can destroy the object.
+ delete impl->mBase;
+ }
+ }
+}
+
+bool RefBase::weakref_type::attemptIncStrong(const void* id)
+{
+ incWeak(id);
+
+ weakref_impl* const impl = static_cast<weakref_impl*>(this);
+
+ int32_t curCount = impl->mStrong;
+ ALOG_ASSERT(curCount >= 0, "attemptIncStrong called on %p after underflow",
+ this);
+ while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
+ if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {
+ break;
+ }
+ curCount = impl->mStrong;
+ }
+
+ if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
+ bool allow;
+ if (curCount == INITIAL_STRONG_VALUE) {
+ // Attempting to acquire first strong reference... this is allowed
+ // if the object does NOT have a longer lifetime (meaning the
+ // implementation doesn't need to see this), or if the implementation
+ // allows it to happen.
+ allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK
+ || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
+ } else {
+ // Attempting to revive the object... this is allowed
+ // if the object DOES have a longer lifetime (so we can safely
+ // call the object with only a weak ref) and the implementation
+ // allows it to happen.
+ allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK
+ && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
+ }
+ if (!allow) {
+ decWeak(id);
+ return false;
+ }
+ curCount = android_atomic_inc(&impl->mStrong);
+
+ // If the strong reference count has already been incremented by
+ // someone else, the implementor of onIncStrongAttempted() is holding
+ // an unneeded reference. So call onLastStrongRef() here to remove it.
+ // (No, this is not pretty.) Note that we MUST NOT do this if we
+ // are in fact acquiring the first reference.
+ if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) {
+ impl->mBase->onLastStrongRef(id);
+ }
+ }
+
+ impl->addStrongRef(id);
+
+#if PRINT_REFS
+ ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
+#endif
+
+ if (curCount == INITIAL_STRONG_VALUE) {
+ android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong);
+ impl->mBase->onFirstRef();
+ }
+
+ return true;
+}
+
+bool RefBase::weakref_type::attemptIncWeak(const void* id)
+{
+ weakref_impl* const impl = static_cast<weakref_impl*>(this);
+
+ int32_t curCount = impl->mWeak;
+ ALOG_ASSERT(curCount >= 0, "attemptIncWeak called on %p after underflow",
+ this);
+ while (curCount > 0) {
+ if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mWeak) == 0) {
+ break;
+ }
+ curCount = impl->mWeak;
+ }
+
+ if (curCount > 0) {
+ impl->addWeakRef(id);
+ }
+
+ return curCount > 0;
+}
+
+int32_t RefBase::weakref_type::getWeakCount() const
+{
+ return static_cast<const weakref_impl*>(this)->mWeak;
+}
+
+void RefBase::weakref_type::printRefs() const
+{
+ static_cast<const weakref_impl*>(this)->printRefs();
+}
+
+void RefBase::weakref_type::trackMe(bool enable, bool retain)
+{
+ static_cast<weakref_impl*>(this)->trackMe(enable, retain);
+}
+
+RefBase::weakref_type* RefBase::createWeak(const void* id) const
+{
+ mRefs->incWeak(id);
+ return mRefs;
+}
+
+RefBase::weakref_type* RefBase::getWeakRefs() const
+{
+ return mRefs;
+}
+
+RefBase::RefBase()
+ : mRefs(new weakref_impl(this))
+{
+}
+
+RefBase::~RefBase()
+{
+ if (mRefs->mStrong == INITIAL_STRONG_VALUE) {
+ // we never acquired a strong (and/or weak) reference on this object.
+ delete mRefs;
+ } else {
+ // life-time of this object is extended to WEAK or FOREVER, in
+ // which case weakref_impl doesn't out-live the object and we
+ // can free it now.
+ if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
+ // It's possible that the weak count is not 0 if the object
+ // re-acquired a weak reference in its destructor
+ if (mRefs->mWeak == 0) {
+ delete mRefs;
+ }
+ }
+ }
+ // for debugging purposes, clear this.
+ const_cast<weakref_impl*&>(mRefs) = NULL;
+}
+
+void RefBase::extendObjectLifetime(int32_t mode)
+{
+ android_atomic_or(mode, &mRefs->mFlags);
+}
+
+void RefBase::onFirstRef()
+{
+}
+
+void RefBase::onLastStrongRef(const void* /*id*/)
+{
+}
+
+bool RefBase::onIncStrongAttempted(uint32_t flags, const void* id)
+{
+ return (flags&FIRST_INC_STRONG) ? true : false;
+}
+
+void RefBase::onLastWeakRef(const void* /*id*/)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+void RefBase::moveReferences(void* dst, void const* src, size_t n,
+ const ReferenceConverterBase& caster)
+{
+#if DEBUG_REFS
+ const size_t itemSize = caster.getReferenceTypeSize();
+ for (size_t i=0 ; i<n ; i++) {
+ void* d = reinterpret_cast<void *>(intptr_t(dst) + i*itemSize);
+ void const* s = reinterpret_cast<void const*>(intptr_t(src) + i*itemSize);
+ RefBase* ref(reinterpret_cast<RefBase*>(caster.getReferenceBase(d)));
+ ref->mRefs->renameStrongRefId(s, d);
+ ref->mRefs->renameWeakRefId(s, d);
+ }
+#endif
+}
+
+// ---------------------------------------------------------------------------
+
+TextOutput& printStrongPointer(TextOutput& to, const void* val)
+{
+ to << "sp<>(" << val << ")";
+ return to;
+}
+
+TextOutput& printWeakPointer(TextOutput& to, const void* val)
+{
+ to << "wp<>(" << val << ")";
+ return to;
+}
+
+
+}; // namespace android
diff --git a/rtlib/VectorImpl.cpp b/rtlib/VectorImpl.cpp
new file mode 100644
index 0000000..e78faa8
--- /dev/null
+++ b/rtlib/VectorImpl.cpp
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#define LOG_TAG "Vector"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include <utils/SharedBuffer.h>
+#include <utils/VectorImpl.h>
+
+/*****************************************************************************/
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+const size_t kMinVectorCapacity = 4;
+
+static inline size_t max(size_t a, size_t b) {
+ return a>b ? a : b;
+}
+
+// ----------------------------------------------------------------------------
+
+VectorImpl::VectorImpl(size_t itemSize, uint32_t flags)
+ : mStorage(0), mCount(0), mFlags(flags), mItemSize(itemSize)
+{
+}
+
+VectorImpl::VectorImpl(const VectorImpl& rhs)
+ : mStorage(rhs.mStorage), mCount(rhs.mCount),
+ mFlags(rhs.mFlags), mItemSize(rhs.mItemSize)
+{
+ if (mStorage) {
+ SharedBuffer::sharedBuffer(mStorage)->acquire();
+ }
+}
+
+VectorImpl::~VectorImpl()
+{
+ ALOG_ASSERT(!mCount,
+ "[%p] "
+ "subclasses of VectorImpl must call finish_vector()"
+ " in their destructor. Leaking %d bytes.",
+ this, (int)(mCount*mItemSize));
+ // We can't call _do_destroy() here because the vtable is already gone.
+}
+
+VectorImpl& VectorImpl::operator = (const VectorImpl& rhs)
+{
+ ALOG_ASSERT(mItemSize == rhs.mItemSize,
+ "Vector<> have different types (this=%p, rhs=%p)", this, &rhs);
+ if (this != &rhs) {
+ release_storage();
+ if (rhs.mCount) {
+ mStorage = rhs.mStorage;
+ mCount = rhs.mCount;
+ SharedBuffer::sharedBuffer(mStorage)->acquire();
+ } else {
+ mStorage = 0;
+ mCount = 0;
+ }
+ }
+ return *this;
+}
+
+void* VectorImpl::editArrayImpl()
+{
+ if (mStorage) {
+ SharedBuffer* sb = SharedBuffer::sharedBuffer(mStorage)->attemptEdit();
+ if (sb == 0) {
+ sb = SharedBuffer::alloc(capacity() * mItemSize);
+ if (sb) {
+ _do_copy(sb->data(), mStorage, mCount);
+ release_storage();
+ mStorage = sb->data();
+ }
+ }
+ }
+ return mStorage;
+}
+
+size_t VectorImpl::capacity() const
+{
+ if (mStorage) {
+ return SharedBuffer::sharedBuffer(mStorage)->size() / mItemSize;
+ }
+ return 0;
+}
+
+ssize_t VectorImpl::insertVectorAt(const VectorImpl& vector, size_t index)
+{
+ return insertArrayAt(vector.arrayImpl(), index, vector.size());
+}
+
+ssize_t VectorImpl::appendVector(const VectorImpl& vector)
+{
+ return insertVectorAt(vector, size());
+}
+
+ssize_t VectorImpl::insertArrayAt(const void* array, size_t index, size_t length)
+{
+ if (index > size())
+ return BAD_INDEX;
+ void* where = _grow(index, length);
+ if (where) {
+ _do_copy(where, array, length);
+ }
+ return where ? index : (ssize_t)NO_MEMORY;
+}
+
+ssize_t VectorImpl::appendArray(const void* array, size_t length)
+{
+ return insertArrayAt(array, size(), length);
+}
+
+ssize_t VectorImpl::insertAt(size_t index, size_t numItems)
+{
+ return insertAt(0, index, numItems);
+}
+
+ssize_t VectorImpl::insertAt(const void* item, size_t index, size_t numItems)
+{
+ if (index > size())
+ return BAD_INDEX;
+ void* where = _grow(index, numItems);
+ if (where) {
+ if (item) {
+ _do_splat(where, item, numItems);
+ } else {
+ _do_construct(where, numItems);
+ }
+ }
+ return where ? index : (ssize_t)NO_MEMORY;
+}
+
+static int sortProxy(const void* lhs, const void* rhs, void* func)
+{
+ return (*(VectorImpl::compar_t)func)(lhs, rhs);
+}
+
+status_t VectorImpl::sort(VectorImpl::compar_t cmp)
+{
+ return sort(sortProxy, (void*)cmp);
+}
+
+status_t VectorImpl::sort(VectorImpl::compar_r_t cmp, void* state)
+{
+ // the sort must be stable. we're using insertion sort which
+ // is well suited for small and already sorted arrays
+ // for big arrays, it could be better to use mergesort
+ const ssize_t count = size();
+ if (count > 1) {
+ void* array = const_cast<void*>(arrayImpl());
+ void* temp = 0;
+ ssize_t i = 1;
+ while (i < count) {
+ void* item = reinterpret_cast<char*>(array) + mItemSize*(i);
+ void* curr = reinterpret_cast<char*>(array) + mItemSize*(i-1);
+ if (cmp(curr, item, state) > 0) {
+
+ if (!temp) {
+ // we're going to have to modify the array...
+ array = editArrayImpl();
+ if (!array) return NO_MEMORY;
+ temp = malloc(mItemSize);
+ if (!temp) return NO_MEMORY;
+ item = reinterpret_cast<char*>(array) + mItemSize*(i);
+ curr = reinterpret_cast<char*>(array) + mItemSize*(i-1);
+ } else {
+ _do_destroy(temp, 1);
+ }
+
+ _do_copy(temp, item, 1);
+
+ ssize_t j = i-1;
+ void* next = reinterpret_cast<char*>(array) + mItemSize*(i);
+ do {
+ _do_destroy(next, 1);
+ _do_copy(next, curr, 1);
+ next = curr;
+ --j;
+ curr = reinterpret_cast<char*>(array) + mItemSize*(j);
+ } while (j>=0 && (cmp(curr, temp, state) > 0));
+
+ _do_destroy(next, 1);
+ _do_copy(next, temp, 1);
+ }
+ i++;
+ }
+
+ if (temp) {
+ _do_destroy(temp, 1);
+ free(temp);
+ }
+ }
+ return NO_ERROR;
+}
+
+void VectorImpl::pop()
+{
+ if (size())
+ removeItemsAt(size()-1, 1);
+}
+
+void VectorImpl::push()
+{
+ push(0);
+}
+
+void VectorImpl::push(const void* item)
+{
+ insertAt(item, size());
+}
+
+ssize_t VectorImpl::add()
+{
+ return add(0);
+}
+
+ssize_t VectorImpl::add(const void* item)
+{
+ return insertAt(item, size());
+}
+
+ssize_t VectorImpl::replaceAt(size_t index)
+{
+ return replaceAt(0, index);
+}
+
+ssize_t VectorImpl::replaceAt(const void* prototype, size_t index)
+{
+ ALOG_ASSERT(index<size(),
+ "[%p] replace: index=%d, size=%d", this, (int)index, (int)size());
+
+ void* item = editItemLocation(index);
+ 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);
+}
+
+ssize_t VectorImpl::removeItemsAt(size_t index, size_t count)
+{
+ ALOG_ASSERT((index+count)<=size(),
+ "[%p] remove: index=%d, count=%d, size=%d",
+ this, (int)index, (int)count, (int)size());
+
+ if ((index+count) > size())
+ return BAD_VALUE;
+ _shrink(index, count);
+ return index;
+}
+
+void VectorImpl::finish_vector()
+{
+ release_storage();
+ mStorage = 0;
+ mCount = 0;
+}
+
+void VectorImpl::clear()
+{
+ _shrink(0, mCount);
+}
+
+void* VectorImpl::editItemLocation(size_t index)
+{
+ ALOG_ASSERT(index<capacity(),
+ "[%p] editItemLocation: index=%d, capacity=%d, count=%d",
+ this, (int)index, (int)capacity(), (int)mCount);
+
+ void* buffer = editArrayImpl();
+ if (buffer)
+ return reinterpret_cast<char*>(buffer) + index*mItemSize;
+ return 0;
+}
+
+const void* VectorImpl::itemLocation(size_t index) const
+{
+ ALOG_ASSERT(index<capacity(),
+ "[%p] itemLocation: index=%d, capacity=%d, count=%d",
+ this, (int)index, (int)capacity(), (int)mCount);
+
+ const void* buffer = arrayImpl();
+ if (buffer)
+ return reinterpret_cast<const char*>(buffer) + index*mItemSize;
+ return 0;
+}
+
+ssize_t VectorImpl::setCapacity(size_t new_capacity)
+{
+ size_t current_capacity = capacity();
+ ssize_t amount = new_capacity - size();
+ if (amount <= 0) {
+ // we can't reduce the capacity
+ return current_capacity;
+ }
+ SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
+ if (sb) {
+ void* array = sb->data();
+ _do_copy(array, mStorage, size());
+ release_storage();
+ mStorage = const_cast<void*>(array);
+ } else {
+ return NO_MEMORY;
+ }
+ return new_capacity;
+}
+
+void VectorImpl::release_storage()
+{
+ if (mStorage) {
+ const SharedBuffer* sb = SharedBuffer::sharedBuffer(mStorage);
+ if (sb->release(SharedBuffer::eKeepStorage) == 1) {
+ _do_destroy(mStorage, mCount);
+ SharedBuffer::dealloc(sb);
+ }
+ }
+}
+
+void* VectorImpl::_grow(size_t where, size_t amount)
+{
+// ALOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
+// this, (int)where, (int)amount, (int)mCount, (int)capacity());
+
+ ALOG_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);
+// ALOGV("grow vector %p, new_capacity=%d", this, (int)new_capacity);
+ if ((mStorage) &&
+ (mCount==where) &&
+ (mFlags & HAS_TRIVIAL_COPY) &&
+ (mFlags & HAS_TRIVIAL_DTOR))
+ {
+ const SharedBuffer* cur_sb = SharedBuffer::sharedBuffer(mStorage);
+ SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
+ mStorage = sb->data();
+ } else {
+ SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
+ if (sb) {
+ void* array = sb->data();
+ if (where != 0) {
+ _do_copy(array, mStorage, 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);
+ }
+ release_storage();
+ mStorage = const_cast<void*>(array);
+ }
+ }
+ } else {
+ void* array = editArrayImpl();
+ if (where != mCount) {
+ const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize;
+ void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
+ _do_move_forward(to, from, mCount - where);
+ }
+ }
+ mCount = new_size;
+ void* free_space = const_cast<void*>(itemLocation(where));
+ return free_space;
+}
+
+void VectorImpl::_shrink(size_t where, size_t amount)
+{
+ if (!mStorage)
+ return;
+
+// ALOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
+// this, (int)where, (int)amount, (int)mCount, (int)capacity());
+
+ ALOG_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);
+// ALOGV("shrink vector %p, new_capacity=%d", this, (int)new_capacity);
+ if ((where == new_size) &&
+ (mFlags & HAS_TRIVIAL_COPY) &&
+ (mFlags & HAS_TRIVIAL_DTOR))
+ {
+ const SharedBuffer* cur_sb = SharedBuffer::sharedBuffer(mStorage);
+ SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
+ mStorage = sb->data();
+ } else {
+ SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
+ if (sb) {
+ void* array = sb->data();
+ if (where != 0) {
+ _do_copy(array, mStorage, where);
+ }
+ 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, new_size - where);
+ }
+ release_storage();
+ mStorage = const_cast<void*>(array);
+ }
+ }
+ } else {
+ void* array = editArrayImpl();
+ void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
+ _do_destroy(to, amount);
+ if (where != new_size) {
+ const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
+ _do_move_backward(to, from, new_size - where);
+ }
+ }
+ mCount = new_size;
+}
+
+size_t VectorImpl::itemSize() const {
+ return mItemSize;
+}
+
+void VectorImpl::_do_construct(void* storage, size_t num) const
+{
+ if (!(mFlags & HAS_TRIVIAL_CTOR)) {
+ do_construct(storage, num);
+ }
+}
+
+void VectorImpl::_do_destroy(void* storage, size_t num) const
+{
+ if (!(mFlags & HAS_TRIVIAL_DTOR)) {
+ do_destroy(storage, num);
+ }
+}
+
+void VectorImpl::_do_copy(void* dest, const void* from, size_t num) const
+{
+ if (!(mFlags & HAS_TRIVIAL_COPY)) {
+ do_copy(dest, from, num);
+ } else {
+ memcpy(dest, from, num*itemSize());
+ }
+}
+
+void VectorImpl::_do_splat(void* dest, const void* item, size_t num) const {
+ do_splat(dest, item, num);
+}
+
+void VectorImpl::_do_move_forward(void* dest, const void* from, size_t num) const {
+ do_move_forward(dest, from, num);
+}
+
+void VectorImpl::_do_move_backward(void* dest, const void* from, size_t num) const {
+ do_move_backward(dest, from, num);
+}
+
+void VectorImpl::reservedVectorImpl1() { }
+void VectorImpl::reservedVectorImpl2() { }
+void VectorImpl::reservedVectorImpl3() { }
+void VectorImpl::reservedVectorImpl4() { }
+void VectorImpl::reservedVectorImpl5() { }
+void VectorImpl::reservedVectorImpl6() { }
+void VectorImpl::reservedVectorImpl7() { }
+void VectorImpl::reservedVectorImpl8() { }
+
+/*****************************************************************************/
+
+SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags)
+ : VectorImpl(itemSize, flags)
+{
+}
+
+SortedVectorImpl::SortedVectorImpl(const VectorImpl& rhs)
+: VectorImpl(rhs)
+{
+}
+
+SortedVectorImpl::~SortedVectorImpl()
+{
+}
+
+SortedVectorImpl& SortedVectorImpl::operator = (const SortedVectorImpl& rhs)
+{
+ return static_cast<SortedVectorImpl&>( VectorImpl::operator = (static_cast<const VectorImpl&>(rhs)) );
+}
+
+ssize_t SortedVectorImpl::indexOf(const void* item) const
+{
+ return _indexOrderOf(item);
+}
+
+size_t SortedVectorImpl::orderOf(const void* item) const
+{
+ size_t o;
+ _indexOrderOf(item, &o);
+ return o;
+}
+
+ssize_t SortedVectorImpl::_indexOrderOf(const void* item, size_t* order) const
+{
+ // binary search
+ ssize_t err = NAME_NOT_FOUND;
+ ssize_t l = 0;
+ ssize_t h = size()-1;
+ ssize_t mid;
+ const void* a = arrayImpl();
+ const size_t s = itemSize();
+ while (l <= h) {
+ mid = l + (h - l)/2;
+ const void* const curr = reinterpret_cast<const char *>(a) + (mid*s);
+ const int c = do_compare(curr, item);
+ if (c == 0) {
+ err = l = mid;
+ break;
+ } else if (c < 0) {
+ l = mid + 1;
+ } else {
+ h = mid - 1;
+ }
+ }
+ if (order) *order = l;
+ return err;
+}
+
+ssize_t SortedVectorImpl::add(const void* item)
+{
+ size_t order;
+ ssize_t index = _indexOrderOf(item, &order);
+ if (index < 0) {
+ index = VectorImpl::insertAt(item, order, 1);
+ } else {
+ index = VectorImpl::replaceAt(item, index);
+ }
+ return index;
+}
+
+ssize_t SortedVectorImpl::merge(const VectorImpl& vector)
+{
+ // naive merge...
+ if (!vector.isEmpty()) {
+ const void* buffer = vector.arrayImpl();
+ const size_t is = itemSize();
+ size_t s = vector.size();
+ for (size_t i=0 ; i<s ; i++) {
+ ssize_t err = add( reinterpret_cast<const char*>(buffer) + i*is );
+ if (err<0) {
+ return err;
+ }
+ }
+ }
+ return NO_ERROR;
+}
+
+ssize_t SortedVectorImpl::merge(const SortedVectorImpl& vector)
+{
+ // we've merging a sorted vector... nice!
+ ssize_t err = NO_ERROR;
+ if (!vector.isEmpty()) {
+ // first take care of the case where the vectors are sorted together
+ if (do_compare(vector.itemLocation(vector.size()-1), arrayImpl()) <= 0) {
+ err = VectorImpl::insertVectorAt(static_cast<const VectorImpl&>(vector), 0);
+ } else if (do_compare(vector.arrayImpl(), itemLocation(size()-1)) >= 0) {
+ err = VectorImpl::appendVector(static_cast<const VectorImpl&>(vector));
+ } else {
+ // this could be made a little better
+ err = merge(static_cast<const VectorImpl&>(vector));
+ }
+ }
+ return err;
+}
+
+ssize_t SortedVectorImpl::remove(const void* item)
+{
+ ssize_t i = indexOf(item);
+ if (i>=0) {
+ VectorImpl::removeItemsAt(i, 1);
+ }
+ return i;
+}
+
+void SortedVectorImpl::reservedSortedVectorImpl1() { };
+void SortedVectorImpl::reservedSortedVectorImpl2() { };
+void SortedVectorImpl::reservedSortedVectorImpl3() { };
+void SortedVectorImpl::reservedSortedVectorImpl4() { };
+void SortedVectorImpl::reservedSortedVectorImpl5() { };
+void SortedVectorImpl::reservedSortedVectorImpl6() { };
+void SortedVectorImpl::reservedSortedVectorImpl7() { };
+void SortedVectorImpl::reservedSortedVectorImpl8() { };
+
+
+/*****************************************************************************/
+
+}; // namespace android
+
diff --git a/rtlib/bbque_rpc.cc b/rtlib/bbque_rpc.cc
index 4e26d31..f66c616 100644
--- a/rtlib/bbque_rpc.cc
+++ b/rtlib/bbque_rpc.cc
@@ -18,6 +18,7 @@
#include "bbque/config.h"
#include "bbque/rtlib/bbque_rpc.h"
#include "bbque/rtlib/rpc_fifo_client.h"
+#include "bbque/rtlib/rpc_binder_client.h"
#include "bbque/app/application.h"
#include <cstdio>
@@ -40,14 +41,15 @@ BbqueRPC * BbqueRPC::GetInstance() {
// Parse environment configuration
ParseOptions();
-
#ifdef CONFIG_BBQUE_RPC_FIFO
DB(fprintf(stderr, FD("Using FIFO RPC channel\n")));
instance = new BbqueRPC_FIFO_Client();
-#else
+#elif defined CONFIG_BBQUE_RPC_BINDER
+ DB(fprintf(stderr, FD("Using BINDER RPC channel\n")));
+ instance = new BbqueRPC_BINDER_Client();
+#else
#error RPC Channel NOT defined
-#endif // CONFIG_BBQUE_RPC_FIFO
-
+#endif
return instance;
}
diff --git a/rtlib/rpc_binder_client.cc b/rtlib/rpc_binder_client.cc
new file mode 100644
index 0000000..e015522
--- /dev/null
+++ b/rtlib/rpc_binder_client.cc
@@ -0,0 +1,606 @@
+/*
+ * Copyright (C) 2012 Politecnico di Milano
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <
http://www.gnu.org/licenses/>.
+ */
+
+#include "bbque/rtlib/rpc_binder_client.h"
+
+#include "bbque/rtlib/rpc_messages.h"
+#include "bbque/utils/utility.h"
+#include "bbque/config.h"
+
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+// Setup logging
+#undef BBQUE_LOG_MODULE
+#define BBQUE_LOG_MODULE "rpc.bin"
+#undef BBQUE_LOG_UID
+#define BBQUE_LOG_UID GetUid()
+
+android::sp<IBbque> binder_srv;
+bbque::rtlib::BbqueRPC_BINDER_Client *caller;
+
+
+#define RPC_BINDER_SEND_SIZE(RPC_MSG, SIZE)\
+chResp.result = RTLIB_BBQUE_CHANNEL_TIMEOUT; \
+DB(fprintf(stderr, FD("Tx [" #RPC_MSG "] Request "\
+ "RPC_HDR [typ: %d, pid: %d, eid: %"PRIu8"], Bytes: %u...\n"),\
+ rf_ ## RPC_MSG.hdr.typ,\
+ rf_ ## RPC_MSG.hdr.app_pid,\
+ rf_ ## RPC_MSG.hdr.exc_id,\
+ SIZE\
+));\
+binder_srv->push((void*)&rf_ ## RPC_MSG, SIZE);
+
+
+#define RPC_BINDER_SEND(RPC_MSG)\
+ RPC_BINDER_SEND_SIZE(RPC_MSG, RPC_PKT_SIZE(RPC_MSG))
+
+
+namespace bbque { namespace rtlib {
+
+BbqueRPC_BINDER_Client::BbqueRPC_BINDER_Client() :
+ BbqueRPC() {
+ DB(fprintf(stderr, FD("Building BINDER RPC channel\n")));
+ mypid = getpid();
+ snprintf(mypid_string, BBQUE_BINDER_NAME_LENGTH, "%d",(int)mypid);
+ d = new Bbque();
+}
+
+BbqueRPC_BINDER_Client::~BbqueRPC_BINDER_Client() {
+ DB(fprintf(stderr, FD("BbqueRPC_BINDER_Client dtor\n")));
+ ChannelRelease();
+}
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::ChannelRelease() {
+
+}
+
+void BbqueRPC_BINDER_Client::RpcBbqResp(rpc_msg_resp_t *r, ssize_t s) {
+ ::memcpy((void *)&chResp, (void *)r, s);
+ // Notify about reception of a new response
+ DB(fprintf(stderr, FI("Notify response [%d]\n"), chResp.result));
+ chResp_cv.notify_one();
+}
+
+#define WAIT_RPC_RESP \
+ chResp_cv.wait_for(chCommand_ul, \
+ std::chrono::milliseconds(BBQUE_RPC_TIMEOUT)); \
+ if (chResp.result == RTLIB_BBQUE_CHANNEL_TIMEOUT) {\
+ fprintf(stderr, FW("RTLIB response TIMEOUT\n")); \
+ }
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::ChannelPair(const char *name) {
+ std::unique_lock<std::mutex> chCommand_ul(chCommand_mtx);
+ rpc_msg_APP_PAIR_t rf_APP_PAIR =
+ {
+ {
+ RPC_APP_PAIR,
+ RpcMsgToken(),
+ mypid,
+ 0
+ },
+ BBQUE_RPC_BINDER_MAJOR_VERSION,
+ BBQUE_RPC_BINDER_MINOR_VERSION,
+ "\0"
+ };
+ ::strncpy(rf_APP_PAIR.app_name, name, RTLIB_APP_NAME_LENGTH);
+
+ DB(fprintf(stderr, FD("Pairing Binder channels [app: %s, pid: %d]\n"),
+ name, mypid));
+ printf("%s\n",name);
+ // Sending RPC Request
+ RPC_BINDER_SEND(APP_PAIR);
+
+ DB(fprintf(stderr, FD("Waiting BBQUE response...\n")));
+
+ WAIT_RPC_RESP;
+ return (RTLIB_ExitCode_t)chResp.result;
+
+}
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::ChannelSetup() {
+ binder_srv = d->getBbqueServ(BBQUE_SERVICE_NAME);
+ android::defaultServiceManager()->addService(String16(mypid_string), d);
+ android::ProcessState::self()->startThreadPool();
+ RTLIB_ExitCode_t result = RTLIB_OK;
+}
+
+
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::_Init(
+ const char *name) {
+ caller = this;
+ ChannelSetup();
+ ChannelPair(name);
+ return RTLIB_OK;
+}
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::_Register(pregExCtx_t prec) {
+ std::unique_lock<std::mutex> chCommand_ul(chCommand_mtx);
+ rpc_msg_EXC_REGISTER_t rf_EXC_REGISTER =
+ {
+ {
+ RPC_EXC_REGISTER,
+ RpcMsgToken(),
+ mypid,
+ prec->exc_id
+ },
+ "\0",
+ "\0"
+ };
+
+ ::strncpy(rf_EXC_REGISTER.exc_name, prec->name.c_str(),
+ RTLIB_EXC_NAME_LENGTH);
+ ::strncpy(rf_EXC_REGISTER.recipe, prec->exc_params.recipe,
+ RTLIB_EXC_NAME_LENGTH);
+
+ DB(fprintf(stderr, FD("Registering EXC [%d:%d:%s]...\n"),
+ rf_EXC_REGISTER.hdr.app_pid,
+ rf_EXC_REGISTER.hdr.exc_id,
+ rf_EXC_REGISTER.exc_name));
+
+ // Sending RPC Request
+ RPC_BINDER_SEND(EXC_REGISTER);
+
+ DB(fprintf(stderr, FD("Waiting BBQUE response...\n")));
+ WAIT_RPC_RESP;
+ return (RTLIB_ExitCode_t)chResp.result;
+
+}
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::_Unregister(pregExCtx_t prec) {
+std::unique_lock<std::mutex> chCommand_ul(chCommand_mtx);
+ rpc_msg_EXC_UNREGISTER_t rf_EXC_UNREGISTER = {
+ {
+ RPC_EXC_UNREGISTER,
+ RpcMsgToken(),
+ mypid,
+ prec->exc_id
+ },
+ "\0"
+
+ };
+ ::strncpy(rf_EXC_UNREGISTER.exc_name, prec->name.c_str(),
+ RTLIB_EXC_NAME_LENGTH);
+
+ DB(fprintf(stderr, FD("Unregistering EXC [%d:%d:%s]...\n"),
+ rf_EXC_UNREGISTER.hdr.app_pid,
+ rf_EXC_UNREGISTER.hdr.exc_id,
+ rf_EXC_UNREGISTER.exc_name));
+
+ // Sending RPC Request
+ RPC_BINDER_SEND(EXC_UNREGISTER);
+
+ DB(fprintf(stderr, FD("Waiting BBQUE response...\n")));
+
+ WAIT_RPC_RESP;
+ return (RTLIB_ExitCode_t)chResp.result;
+
+}
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::_Enable(pregExCtx_t prec) {
+ std::unique_lock<std::mutex> chCommand_ul(chCommand_mtx);
+
+
+ rpc_msg_EXC_START_t rf_EXC_START = {
+
+ {
+ RPC_EXC_START,
+ RpcMsgToken(),
+ mypid,
+ prec->exc_id
+ },
+
+ };
+
+ DB(fprintf(stderr, FD("Enabling EXC [%d:%d]...\n"),
+ rf_EXC_START.hdr.app_pid,
+ rf_EXC_START.hdr.exc_id));
+
+ // Sending RPC Request
+ RPC_BINDER_SEND(EXC_START);
+
+ DB(fprintf(stderr, FD("Waiting BBQUE response...\n")));
+ WAIT_RPC_RESP;
+ return (RTLIB_ExitCode_t)chResp.result;
+}
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::_Disable(pregExCtx_t prec) {
+ std::unique_lock<std::mutex> chCommand_ul(chCommand_mtx);
+ rpc_msg_EXC_STOP_t rf_EXC_STOP = {
+
+ {
+ RPC_EXC_STOP,
+ RpcMsgToken(),
+ mypid,
+ prec->exc_id
+ },
+
+ };
+
+ DB(fprintf(stderr, FD("Disabling EXC [%d:%d]...\n"),
+ rf_EXC_STOP.hdr.app_pid,
+ rf_EXC_STOP.hdr.exc_id));
+
+ // Sending RPC Request
+ RPC_BINDER_SEND(EXC_STOP);
+
+ DB(fprintf(stderr, FD("Waiting BBQUE response...\n")));
+
+ WAIT_RPC_RESP;
+ return (RTLIB_ExitCode_t)chResp.result;
+ }
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::_Set(pregExCtx_t prec,
+ RTLIB_Constraint_t* constraints, uint8_t count) {
+std::unique_lock<std::mutex> chCommand_ul(chCommand_mtx);
+ // Here the message is dynamically allocate to make room for a variable
+ // number of constraints...
+ rpc_msg_EXC_SET_t *prf_EXC_SET;
+ size_t msg_size;
+
+ // At least 1 constraint it is expected
+ assert(count);
+
+ // Allocate the buffer to hold all the contraints
+ msg_size = RPC_PKT_SIZE(EXC_SET) + ((count-1)*sizeof(RTLIB_Constraint_t));
+ prf_EXC_SET = (rpc_msg_EXC_SET_t*)::malloc(msg_size);
+
+
+ // Init RPC header
+ prf_EXC_SET->hdr.typ = RPC_EXC_SET;
+ prf_EXC_SET->hdr.token = RpcMsgToken();
+ prf_EXC_SET->hdr.app_pid = mypid;
+ prf_EXC_SET->hdr.exc_id = prec->exc_id;
+
+ DB(fprintf(stderr, FD("Copying [%d] constraints using buffer @%p "
+ "of [%"PRIu64"] Bytes...\n"),
+ count, (void*)&(prf_EXC_SET->constraints),
+ (count)*sizeof(RTLIB_Constraint_t)));
+
+ // Init RPC header
+ prf_EXC_SET->count = count;
+ ::memcpy(&(prf_EXC_SET->constraints), constraints,
+ (count)*sizeof(RTLIB_Constraint_t));
+
+ // Sending RPC Request
+ volatile rpc_msg_EXC_SET_t & rf_EXC_SET = (*prf_EXC_SET);
+ DB(fprintf(stderr, FD("Set [%d] constraints on EXC [%d:%d]...\n"),
+ count, rf_EXC_SET.hdr.app_pid,
+ rf_EXC_SET.hdr.exc_id));
+ RPC_BINDER_SEND_SIZE(EXC_SET, msg_size);
+
+ // Clean-up the BINDER message
+ ::free(prf_EXC_SET);
+
+ DB(fprintf(stderr, FD("Waiting BBQUE response...\n")));
+
+ WAIT_RPC_RESP;
+ return (RTLIB_ExitCode_t)chResp.result;
+
+}
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::_Clear(pregExCtx_t prec) {
+ std::unique_lock<std::mutex> chCommand_ul(chCommand_mtx);
+ rpc_msg_EXC_CLEAR_t rf_EXC_CLEAR = {
+
+ {
+ RPC_EXC_CLEAR,
+ RpcMsgToken(),
+ mypid,
+ prec->exc_id
+ },
+ };
+
+ DB(fprintf(stderr, FD("Clear constraints for EXC [%d:%d]...\n"),
+ rf_EXC_CLEAR.hdr.app_pid,
+ rf_EXC_CLEAR.hdr.exc_id));
+
+ // Sending RPC Request
+ RPC_BINDER_SEND(EXC_CLEAR);
+
+ DB(fprintf(stderr, FD("Waiting BBQUE response...\n")));
+
+ WAIT_RPC_RESP;
+ return (RTLIB_ExitCode_t)chResp.result;
+}
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::_GGap(pregExCtx_t prec, uint8_t gap) {
+ std::unique_lock<std::mutex> chCommand_ul(chCommand_mtx);
+ rpc_msg_EXC_GGAP_t rf_EXC_GGAP = {
+
+ {
+ RPC_EXC_GGAP,
+ RpcMsgToken(),
+ mypid,
+ prec->exc_id
+ },
+ gap,
+
+ };
+
+ DB(fprintf(stderr, FD("Set Goal-Gap for EXC [%d:%d]...\n"),
+ rf_EXC_GGAP.hdr.app_pid,
+ rf_EXC_GGAP.hdr.exc_id));
+
+ // Sending RPC Request
+ RPC_BINDER_SEND(EXC_GGAP);
+
+ DB(fprintf(stderr, FD("Waiting BBQUE response...\n")));
+
+ WAIT_RPC_RESP;
+ return (RTLIB_ExitCode_t)chResp.result;
+
+}
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::_ScheduleRequest(pregExCtx_t prec) {
+ std::unique_lock<std::mutex> chCommand_ul(chCommand_mtx);
+ rpc_msg_EXC_SCHEDULE_t rf_EXC_SCHEDULE = {
+
+ {
+ RPC_EXC_SCHEDULE,
+ RpcMsgToken(),
+ mypid,
+ prec->exc_id
+ },
+ };
+
+ DB(fprintf(stderr, FD("Schedule request for EXC [%d:%d]...\n"),
+ rf_EXC_SCHEDULE.hdr.app_pid,
+ rf_EXC_SCHEDULE.hdr.exc_id));
+
+ // Sending RPC Request
+ RPC_BINDER_SEND(EXC_SCHEDULE);
+
+ DB(fprintf(stderr, FD("Waiting BBQUE response...\n")));
+
+ WAIT_RPC_RESP;
+ return (RTLIB_ExitCode_t)chResp.result;
+}
+
+void BbqueRPC_BINDER_Client::_Exit() {
+ ChannelRelease();
+}
+
+
+/******************************************************************************
+ * Synchronization Protocol Messages - PreChange
+ ******************************************************************************/
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::_SyncpPreChangeResp(
+ rpc_msg_token_t token, pregExCtx_t prec, uint32_t syncLatency) {
+ rpc_msg_BBQ_SYNCP_PRECHANGE_RESP_t rf_BBQ_SYNCP_PRECHANGE_RESP = {
+
+ {
+ RPC_BBQ_RESP,
+ token,
+ mypid,
+ prec->exc_id
+ },
+ syncLatency,
+ RTLIB_OK
+
+ };
+
+ DB(fprintf(stderr, FD("PreChange response EXC [%d:%d] "
+ "latency [%d]...\n"),
+ rf_BBQ_SYNCP_PRECHANGE_RESP.hdr.app_pid,
+ rf_BBQ_SYNCP_PRECHANGE_RESP.hdr.exc_id,
+ rf_BBQ_SYNCP_PRECHANGE_RESP.syncLatency));
+
+ // Sending RPC Request
+ RPC_BINDER_SEND(BBQ_SYNCP_PRECHANGE_RESP);
+
+ return RTLIB_OK;
+
+}
+
+void BbqueRPC_BINDER_Client::RpcBbqSyncpPreChange(rpc_msg_BBQ_SYNCP_PRECHANGE_t *msg, ssize_t bytes) {
+
+ if (bytes <= 0) {
+ fprintf(stderr, FE("FAILED read from app binder "
+ "(Error %d: %s)\n"),
+ errno, strerror(errno));
+ chResp.result = RTLIB_BBQUE_CHANNEL_READ_FAILED;
+ }
+
+ // Notify the Pre-Change
+ SyncP_PreChangeNotify(*msg);
+}
+
+
+/******************************************************************************
+ * Synchronization Protocol Messages - SyncChange
+ ******************************************************************************/
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::_SyncpSyncChangeResp(
+ rpc_msg_token_t token, pregExCtx_t prec, RTLIB_ExitCode_t sync) {
+
+ rpc_msg_BBQ_SYNCP_SYNCCHANGE_RESP_t rf_BBQ_SYNCP_SYNCCHANGE_RESP = {
+ {
+ RPC_BBQ_RESP,
+ token,
+ mypid,
+ prec->exc_id
+ },
+ (uint8_t)sync
+
+ };
+
+ // Check that the ExitCode can be represented by the response message
+ assert(sync < 256);
+
+ DB(fprintf(stderr, FD("SyncChange response EXC [%d:%d]...\n"),
+ rf_BBQ_SYNCP_SYNCCHANGE_RESP.hdr.app_pid,
+ rf_BBQ_SYNCP_SYNCCHANGE_RESP.hdr.exc_id));
+
+ // Sending RPC Request
+ RPC_BINDER_SEND(BBQ_SYNCP_SYNCCHANGE_RESP);
+
+ return RTLIB_OK;
+}
+
+void BbqueRPC_BINDER_Client::RpcBbqSyncpSyncChange(rpc_msg_BBQ_SYNCP_SYNCCHANGE_t *msg, ssize_t bytes) {
+
+ if (bytes <= 0) {
+ fprintf(stderr, FE("FAILED read from app binder"
+ "(Error %d: %s)\n"),
+ errno, strerror(errno));
+ chResp.result = RTLIB_BBQUE_CHANNEL_READ_FAILED;
+ }
+
+ // Notify the Sync-Change
+ SyncP_SyncChangeNotify(*msg);
+}
+
+
+/******************************************************************************
+ * Synchronization Protocol Messages - SyncChange
+ ******************************************************************************/
+
+void BbqueRPC_BINDER_Client::RpcBbqSyncpDoChange(rpc_msg_BBQ_SYNCP_DOCHANGE_t *msg, ssize_t bytes) {
+
+ if (bytes <= 0) {
+ fprintf(stderr, FE("FAILED read from app "
+ "(Error %d: %s)\n"),
+ errno, strerror(errno));
+ chResp.result = RTLIB_BBQUE_CHANNEL_READ_FAILED;
+ }
+
+ // Notify the Sync-Change
+ SyncP_DoChangeNotify(*msg);
+
+}
+
+
+/******************************************************************************
+ * Synchronization Protocol Messages - PostChange
+ ******************************************************************************/
+
+RTLIB_ExitCode_t BbqueRPC_BINDER_Client::_SyncpPostChangeResp(
+ rpc_msg_token_t token, pregExCtx_t prec, RTLIB_ExitCode_t result) {
+
+rpc_msg_BBQ_SYNCP_POSTCHANGE_RESP_t rf_BBQ_SYNCP_POSTCHANGE_RESP = {
+
+ {
+ RPC_BBQ_RESP,
+ token,
+ mypid,
+ prec->exc_id
+ },
+ (uint8_t)result
+
+ };
+
+ // Check that the ExitCode can be represented by the response message
+ assert(result < 256);
+
+ DB(fprintf(stderr, FD("PostChange response EXC [%d:%d]...\n"),
+ rf_BBQ_SYNCP_POSTCHANGE_RESP.hdr.app_pid,
+ rf_BBQ_SYNCP_POSTCHANGE_RESP.hdr.exc_id));
+
+ // Sending RPC Request
+ RPC_BINDER_SEND(BBQ_SYNCP_POSTCHANGE_RESP);
+
+ return RTLIB_OK;
+}
+
+void BbqueRPC_BINDER_Client::RpcBbqSyncpPostChange(rpc_msg_BBQ_SYNCP_POSTCHANGE_t *msg, ssize_t bytes) {
+
+if (bytes <= 0) {
+ fprintf(stderr, FE("FAILED read from app "
+ "(Error %d: %s)\n"),
+ errno, strerror(errno));
+ chResp.result = RTLIB_BBQUE_CHANNEL_READ_FAILED;
+ }
+
+ // Notify the Sync-Change
+ SyncP_PostChangeNotify(*msg);
+}
+
+void BbqueRPC_BINDER_Client::setDone() {
+ done = true;
+}
+
+} // namespace rtlib
+
+} // namespace bbque
+
+
+
+
+status_t BnBbque::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+ assert (code == BBQUE_BINDER_TRANSACTION_CODE);
+ data.checkInterface(this);
+ ssize_t size = data.dataAvail();
+ bbque::plugins::RPCChannelIF::rpc_msg_ptr_t msg;
+ msg = ::malloc(data.dataAvail());
+ data.read(msg, data.dataAvail());
+
+switch (msg->typ) {
+
+ case bbque::rtlib::RPC_APP_EXIT:
+ caller->setDone();
+ break;
+
+ //--- Application Originated Messages
+ case bbque::rtlib::RPC_APP_RESP:
+ DB(fprintf(stderr, FI("APP_RESP\n")));
+ caller->RpcBbqResp((bbque::rtlib::rpc_msg_resp_t *)msg, size);
+ break;
+
+ //--- Execution Context Originated Messages
+ case bbque::rtlib::RPC_EXC_RESP:
+ DB(fprintf(stderr, FI("EXC_RESP\n")));
+ caller->RpcBbqResp((bbque::rtlib::rpc_msg_resp_t *)msg, size);
+ break;
+
+ //--- Barbeque Originated Messages
+ case bbque::rtlib::RPC_BBQ_STOP_EXECUTION:
+ DB(fprintf(stderr, FI("BBQ_STOP_EXECUTION\n")));
+ break;
+ case bbque::rtlib::RPC_BBQ_SYNCP_PRECHANGE:
+ DB(fprintf(stderr, FI("BBQ_SYNCP_PRECHANGE\n")));
+ caller->RpcBbqSyncpPreChange((bbque::rtlib::rpc_msg_BBQ_SYNCP_PRECHANGE_t *)msg, size);
+ break;
+ case bbque::rtlib::RPC_BBQ_SYNCP_SYNCCHANGE:
+ DB(fprintf(stderr, FI("BBQ_SYNCP_SYNCCHANGE\n")));
+ caller->RpcBbqSyncpSyncChange((bbque::rtlib::rpc_msg_BBQ_SYNCP_SYNCCHANGE_t *)msg, size);
+ break;
+ case bbque::rtlib::RPC_BBQ_SYNCP_DOCHANGE:
+ DB(fprintf(stderr, FI("BBQ_SYNCP_DOCHANGE\n")));
+ caller->RpcBbqSyncpDoChange((bbque::rtlib::rpc_msg_BBQ_SYNCP_DOCHANGE_t *)msg, size);
+ break;
+ case bbque::rtlib::RPC_BBQ_SYNCP_POSTCHANGE:
+ DB(fprintf(stderr, FI("BBQ_SYNCP_POSTCHANGE\n")));
+ caller->RpcBbqSyncpPostChange((bbque::rtlib::rpc_msg_BBQ_SYNCP_POSTCHANGE_t *)msg, size);
+ break;
+
+ default:
+ fprintf(stderr, FE("Unknown BBQ response/command [%d]\n"), msg->typ);
+ assert(false);
+ break;
+ }
+
+ ::free(msg);
+}
+
+BnBbque::BnBbque() {
+}
--
1.7.8.6