diff options
Diffstat (limited to 'include')
110 files changed, 8195 insertions, 883 deletions
diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h index 99ab2f0..09f0de1 100644 --- a/include/android_runtime/AndroidRuntime.h +++ b/include/android_runtime/AndroidRuntime.h @@ -87,7 +87,7 @@ public: virtual void onExit(int code); /** create a new thread that is visible from Java */ - static void createJavaThread(const char* name, void (*start)(void *), + static android_thread_id_t createJavaThread(const char* name, void (*start)(void *), void* arg); /** return a pointer to the VM running in this process */ @@ -98,6 +98,7 @@ public: private: static int startReg(JNIEnv* env); + void parseExtraOpts(char* extraOptsBuf); int startVm(JavaVM** pJavaVM, JNIEnv** pEnv); Vector<JavaVMOption> mOptions; diff --git a/include/android_runtime/android_app_NativeActivity.h b/include/android_runtime/android_app_NativeActivity.h new file mode 100644 index 0000000..c388ba8 --- /dev/null +++ b/include/android_runtime/android_app_NativeActivity.h @@ -0,0 +1,149 @@ +/* + * 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_APP_NATIVEACTIVITY_H +#define _ANDROID_APP_NATIVEACTIVITY_H + +#include <ui/InputTransport.h> + +#include <android/native_activity.h> + +#include "jni.h" + +namespace android { + +extern void android_NativeActivity_setWindowFormat( + ANativeActivity* activity, int32_t format); + +extern void android_NativeActivity_setWindowFlags( + ANativeActivity* activity, int32_t values, int32_t mask); + +extern void android_NativeActivity_showSoftInput( + ANativeActivity* activity, int32_t flags); + +extern void android_NativeActivity_hideSoftInput( + ANativeActivity* activity, int32_t flags); + +} // namespace android + + +/* + * NDK input queue API. + * + * Here is the event flow: + * 1. Event arrives in input consumer, and is returned by getEvent(). + * 2. Application calls preDispatchEvent(): + * a. Event is assigned a sequence ID and enqueued in mPreDispatchingKeys. + * b. Main thread picks up event, hands to input method. + * c. Input method eventually returns sequence # and whether it was handled. + * d. finishPreDispatch() is called to enqueue the information. + * e. next getEvent() call will: + * - finish any pre-dispatch events that the input method handled + * - return the next pre-dispatched event that the input method didn't handle. + * f. (A preDispatchEvent() call on this event will now return false). + * 3. Application calls finishEvent() with whether it was handled. + * - If handled is true, the event is finished. + * - If handled is false, the event is put on mUnhandledKeys, and: + * a. Main thread receives event from consumeUnhandledEvent(). + * b. Java sends event through default key handler. + * c. event is finished. + */ +struct AInputQueue : public android::InputEventFactoryInterface { +public: + /* Creates a consumer associated with an input channel. */ + explicit AInputQueue(const android::sp<android::InputChannel>& channel, int workWrite); + + /* Destroys the consumer and releases its input channel. */ + ~AInputQueue(); + + void attachLooper(ALooper* looper, ALooper_callbackFunc* callback, void* data); + + void detachLooper(); + + int32_t hasEvents(); + + int32_t getEvent(AInputEvent** outEvent); + + bool preDispatchEvent(AInputEvent* event); + + void finishEvent(AInputEvent* event, bool handled); + + // ---------------------------------------------------------- + + inline android::InputConsumer& getConsumer() { return mConsumer; } + + void dispatchEvent(android::KeyEvent* event); + + void finishPreDispatch(int seq, bool handled); + + android::KeyEvent* consumeUnhandledEvent(); + android::KeyEvent* consumePreDispatchingEvent(int* outSeq); + + virtual android::KeyEvent* createKeyEvent(); + virtual android::MotionEvent* createMotionEvent(); + + int mWorkWrite; + +private: + void doUnhandledKey(android::KeyEvent* keyEvent); + bool preDispatchKey(android::KeyEvent* keyEvent); + void wakeupDispatch(); + + android::InputConsumer mConsumer; + android::sp<android::PollLoop> mPollLoop; + + int mDispatchKeyRead; + int mDispatchKeyWrite; + + struct in_flight_event { + android::InputEvent* event; + int seq; + bool doFinish; + }; + + struct finish_pre_dispatch { + int seq; + bool handled; + }; + + android::Mutex mLock; + + int mSeq; + + // Cache of previously allocated key events. + android::Vector<android::KeyEvent*> mAvailKeyEvents; + // Cache of previously allocated motion events. + android::Vector<android::MotionEvent*> mAvailMotionEvents; + + // All input events that are actively being processed. + android::Vector<in_flight_event> mInFlightEvents; + + // Key events that the app didn't handle, and are pending for + // delivery to the activity's default key handling. + android::Vector<android::KeyEvent*> mUnhandledKeys; + + // Keys that arrived in the Java framework and need to be + // dispatched to the app. + android::Vector<android::KeyEvent*> mDispatchingKeys; + + // Key events that are pending to be pre-dispatched to the IME. + android::Vector<in_flight_event> mPreDispatchingKeys; + + // Event sequence numbers that we have finished pre-dispatching. + android::Vector<finish_pre_dispatch> mFinishPreDispatches; +}; + +#endif // _ANDROID_APP_NATIVEACTIVITY_H diff --git a/include/android_runtime/android_content_res_Configuration.h b/include/android_runtime/android_content_res_Configuration.h new file mode 100644 index 0000000..2f5a982 --- /dev/null +++ b/include/android_runtime/android_content_res_Configuration.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 _ANDROID_CONTENT_RES_CONFIGURATION_H +#define _ANDROID_CONTENT_RES_CONFIGURATION_H + +#include <utils/ResourceTypes.h> +#include <android/configuration.h> + +#include "jni.h" + +struct AConfiguration : android::ResTable_config { +}; + +namespace android { + +extern void android_Configuration_getFromJava( + JNIEnv* env, jobject clazz, struct AConfiguration* out); + +} // namespace android + + +#endif // _ANDROID_CONTENT_RES_CONFIGURATION_H diff --git a/include/android_runtime/android_view_Surface.h b/include/android_runtime/android_view_Surface.h new file mode 100644 index 0000000..c37932e --- /dev/null +++ b/include/android_runtime/android_view_Surface.h @@ -0,0 +1,31 @@ +/* + * 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_VIEW_SURFACE_H +#define _ANDROID_VIEW_SURFACE_H + +#include <android/native_window.h> + +#include "jni.h" + +namespace android { + +extern sp<ANativeWindow> android_Surface_getNativeWindow( + JNIEnv* env, jobject clazz); + +} // namespace android + +#endif // _ANDROID_VIEW_SURFACE_H diff --git a/include/binder/BinderService.h b/include/binder/BinderService.h new file mode 100644 index 0000000..2316fef --- /dev/null +++ b/include/binder/BinderService.h @@ -0,0 +1,60 @@ +/* + * 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() { + sp<IServiceManager> sm(defaultServiceManager()); + return sm->addService(String16(SERVICE::getServiceName()), new SERVICE()); + } + + static void publishAndJoinThreadPool() { + sp<ProcessState> proc(ProcessState::self()); + sp<IServiceManager> sm(defaultServiceManager()); + sm->addService(String16(SERVICE::getServiceName()), new SERVICE()); + 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/IInterface.h b/include/binder/IInterface.h index 273d922..5f9f69c 100644 --- a/include/binder/IInterface.h +++ b/include/binder/IInterface.h @@ -72,21 +72,24 @@ protected: // ---------------------------------------------------------------------- #define DECLARE_META_INTERFACE(INTERFACE) \ - static const String16 descriptor; \ - static sp<I##INTERFACE> asInterface(const sp<IBinder>& obj); \ - virtual const String16& getInterfaceDescriptor() const; \ + 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 String16 I##INTERFACE::descriptor(NAME); \ - const String16& I##INTERFACE::getInterfaceDescriptor() const { \ + const android::String16 I##INTERFACE::descriptor(NAME); \ + const android::String16& \ + I##INTERFACE::getInterfaceDescriptor() const { \ return I##INTERFACE::descriptor; \ } \ - sp<I##INTERFACE> I##INTERFACE::asInterface(const sp<IBinder>& obj) \ + android::sp<I##INTERFACE> I##INTERFACE::asInterface( \ + const android::sp<android::IBinder>& obj) \ { \ - sp<I##INTERFACE> intr; \ + android::sp<I##INTERFACE> intr; \ if (obj != NULL) { \ intr = static_cast<I##INTERFACE*>( \ obj->queryLocalInterface( \ diff --git a/include/binder/IPCThreadState.h b/include/binder/IPCThreadState.h index 3ab985d..04e24d2 100644 --- a/include/binder/IPCThreadState.h +++ b/include/binder/IPCThreadState.h @@ -40,6 +40,9 @@ public: int getCallingPid(); int getCallingUid(); + + void setStrictModePolicy(int32_t policy); + int32_t getStrictModePolicy() const; int64_t clearCallingIdentity(); void restoreCallingIdentity(int64_t token); @@ -109,8 +112,9 @@ private: status_t mLastError; pid_t mCallingPid; uid_t mCallingUid; + int32_t mStrictModePolicy; }; - + }; // namespace android // --------------------------------------------------------------------------- diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h index 66c34b2..32c9a1d5 100644 --- a/include/binder/Parcel.h +++ b/include/binder/Parcel.h @@ -26,11 +26,12 @@ // --------------------------------------------------------------------------- namespace android { +class Flattenable; class IBinder; +class IPCThreadState; class ProcessState; class String8; class TextOutput; -class Flattenable; struct flat_binder_object; // defined in support_p/binder_module.h @@ -56,9 +57,19 @@ public: bool hasFileDescriptors() const; + // Writes the RPC header. status_t writeInterfaceToken(const String16& interface); - bool enforceInterface(const String16& interface) const; - bool checkInterface(IBinder*) const; + + // 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(); @@ -100,6 +111,11 @@ public: 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; @@ -122,7 +138,14 @@ public: 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 diff --git a/include/camera/Camera.h b/include/camera/Camera.h index 57968e3..964700b 100644 --- a/include/camera/Camera.h +++ b/include/camera/Camera.h @@ -92,6 +92,32 @@ enum { CAMERA_ERROR_SERVER_DIED = 100 }; +enum { + CAMERA_FACING_BACK = 0, + CAMERA_FACING_FRONT = 1 /* The camera faces to the user */ +}; + +struct CameraInfo { + + /** + * The direction that the camera faces to. It should be + * CAMERA_FACING_BACK or CAMERA_FACING_FRONT. + */ + int facing; + + /** + * The orientation of the camera image. The value is the angle that the + * camera image needs to be rotated clockwise so it shows correctly on + * the display in its natural orientation. It should be 0, 90, 180, or 270. + * + * For example, suppose a device has a naturally tall screen, but the camera + * sensor is mounted in landscape. If the top side of the camera sensor is + * aligned with the right edge of the display in natural orientation, the + * value should be 90. + */ + int orientation; +}; + class ICameraService; class ICamera; class Surface; @@ -112,7 +138,10 @@ class Camera : public BnCameraClient, public IBinder::DeathRecipient public: // construct a camera client from an existing remote static sp<Camera> create(const sp<ICamera>& camera); - static sp<Camera> connect(); + static int32_t getNumberOfCameras(); + static status_t getCameraInfo(int cameraId, + struct CameraInfo* cameraInfo); + static sp<Camera> connect(int cameraId); ~Camera(); void init(); diff --git a/include/camera/CameraHardwareInterface.h b/include/camera/CameraHardwareInterface.h index d877c74..1529db7 100644 --- a/include/camera/CameraHardwareInterface.h +++ b/include/camera/CameraHardwareInterface.h @@ -213,8 +213,15 @@ public: virtual status_t dump(int fd, const Vector<String16>& args) const = 0; }; -/** factory function to instantiate a camera hardware object */ -extern "C" sp<CameraHardwareInterface> openCameraHardware(); +/** + * The functions need to be provided by the camera HAL. + * + * If getNumberOfCameras() returns N, the valid cameraId for getCameraInfo() + * and openCameraHardware() is 0 to N-1. + */ +extern "C" int HAL_getNumberOfCameras(); +extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo); +extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId); }; // namespace android diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h index 5ea83a5..6a5d254 100644 --- a/include/camera/CameraParameters.h +++ b/include/camera/CameraParameters.h @@ -65,13 +65,15 @@ public: // Supported preview frame sizes in pixels. // Example value: "800x600,480x320". Read only. static const char KEY_SUPPORTED_PREVIEW_SIZES[]; - // The image format for preview frames. + // The image format for preview frames. See CAMERA_MSG_PREVIEW_FRAME in + // frameworks/base/include/camera/Camera.h. // Example value: "yuv420sp" or PIXEL_FORMAT_XXX constants. Read/write. static const char KEY_PREVIEW_FORMAT[]; // Supported image formats for preview frames. // Example value: "yuv420sp,yuv422i-yuyv". Read only. static const char KEY_SUPPORTED_PREVIEW_FORMATS[]; - // Number of preview frames per second. + // Number of preview frames per second. This is the target frame rate. The + // actual frame rate depends on the driver. // Example value: "15". Read/write. static const char KEY_PREVIEW_FRAME_RATE[]; // Supported number of preview frames per second. @@ -83,7 +85,8 @@ public: // Supported dimensions for captured pictures in pixels. // Example value: "2048x1536,1024x768". Read only. static const char KEY_SUPPORTED_PICTURE_SIZES[]; - // The image format for captured pictures. + // The image format for captured pictures. See CAMERA_MSG_COMPRESSED_IMAGE + // in frameworks/base/include/camera/Camera.h. // Example value: "jpeg" or PIXEL_FORMAT_XXX constants. Read/write. static const char KEY_PICTURE_FORMAT[]; // Supported image formats for captured pictures. @@ -119,14 +122,17 @@ public: // should not set default value for this parameter. // Example value: "0" or "90" or "180" or "270". Write only. static const char KEY_ROTATION[]; - // GPS latitude coordinate. This will be stored in JPEG EXIF header. - // Example value: "25.032146". Write only. + // GPS latitude coordinate. GPSLatitude and GPSLatitudeRef will be stored in + // JPEG EXIF header. + // Example value: "25.032146" or "-33.462809". Write only. static const char KEY_GPS_LATITUDE[]; - // GPS longitude coordinate. This will be stored in JPEG EXIF header. - // Example value: "121.564448". Write only. + // GPS longitude coordinate. GPSLongitude and GPSLongitudeRef will be stored + // in JPEG EXIF header. + // Example value: "121.564448" or "-70.660286". Write only. static const char KEY_GPS_LONGITUDE[]; - // GPS altitude. This will be stored in JPEG EXIF header. - // Example value: "21.0". Write only. + // GPS altitude. GPSAltitude and GPSAltitudeRef will be stored in JPEG EXIF + // header. + // Example value: "21.0" or "-5". Write only. static const char KEY_GPS_ALTITUDE[]; // GPS timestamp (UTC in seconds since January 1, 1970). This should be // stored in JPEG EXIF header. @@ -165,10 +171,9 @@ public: // Supported flash modes. // Example value: "auto,on,off". Read only. static const char KEY_SUPPORTED_FLASH_MODES[]; - // Current focus mode. If the camera does not support auto-focus, the value - // should be FOCUS_MODE_FIXED. If the focus mode is not FOCUS_MODE_FIXED or - // or FOCUS_MODE_INFINITY, applications should call - // CameraHardwareInterface.autoFocus to start the focus. + // Current focus mode. This will not be empty. Applications should call + // CameraHardwareInterface.autoFocus to start the focus if focus mode is + // FOCUS_MODE_AUTO or FOCUS_MODE_MACRO. // Example value: "auto" or FOCUS_MODE_XXX constants. Read/write. static const char KEY_FOCUS_MODE[]; // Supported focus modes. @@ -221,9 +226,47 @@ public: // Example value: "true". Read only. static const char KEY_SMOOTH_ZOOM_SUPPORTED[]; + // The distances (in meters) from the camera to where an object appears to + // be in focus. The object is sharpest at the optimal focus distance. The + // depth of field is the far focus distance minus near focus distance. + // + // Focus distances may change after starting auto focus, canceling auto + // focus, or starting the preview. Applications can read this anytime to get + // the latest focus distances. If the focus mode is FOCUS_MODE_CONTINUOUS, + // focus distances may change from time to time. + // + // This is intended to estimate the distance between the camera and the + // subject. After autofocus, the subject distance may be within near and far + // focus distance. However, the precision depends on the camera hardware, + // autofocus algorithm, the focus area, and the scene. The error can be + // large and it should be only used as a reference. + // + // Far focus distance > optimal focus distance > near focus distance. If + // the far focus distance is infinity, the value should be "Infinity" (case + // sensitive). The format is three float values separated by commas. The + // first is near focus distance. The second is optimal focus distance. The + // third is far focus distance. + // Example value: "0.95,1.9,Infinity" or "0.049,0.05,0.051". Read only. + static const char KEY_FOCUS_DISTANCES[]; + + // The image format for video frames. See CAMERA_MSG_VIDEO_FRAME in + // frameworks/base/include/camera/Camera.h. + // Example value: "yuv420sp" or PIXEL_FORMAT_XXX constants. Read only. + static const char KEY_VIDEO_FRAME_FORMAT[]; + + // Metering mode. This affects how camera determines exposure. + // Example value: "spot" or METERING_MODE_XXX constants. Read/write. + static const char KEY_METERING_MODE[]; + // Supported metering modes. + // Example value: "center-weighted,frame-average,spot". Read only. + static const char KEY_SUPPORTED_METERING_MODES[]; + // Value for KEY_ZOOM_SUPPORTED or KEY_SMOOTH_ZOOM_SUPPORTED. static const char TRUE[]; + // Value for KEY_FOCUS_DISTANCES. + static const char FOCUS_DISTANCE_INFINITY[]; + // Values for white balance settings. static const char WHITE_BALANCE_AUTO[]; static const char WHITE_BALANCE_INCANDESCENT[]; @@ -309,6 +352,21 @@ public: // continuously. Applications should not call // CameraHardwareInterface.autoFocus in this mode. static const char FOCUS_MODE_EDOF[]; + // Continuous auto focus mode. The camera continuously tries to focus. This + // is ideal for shooting video or shooting photo of moving object. Auto + // focus starts when the parameter is set. Applications should not call + // CameraHardwareInterface.autoFocus in this mode. + static const char FOCUS_MODE_CONTINUOUS[]; + + // The camera determines the exposure by giving more weight to the + // central part of the scene. + static const char METERING_MODE_CENTER_WEIGHTED[]; + // The camera determines the exposure by averaging the entire scene, + // giving no weighting to any particular area. + static const char METERING_MODE_FRAME_AVERAGE[]; + // The camera determines the exposure by a very small area of the scene, + // typically the center. + static const char METERING_MODE_SPOT[]; private: DefaultKeyedVector<String8,String8> mMap; diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h index 82b1283..7d70c1e 100644 --- a/include/camera/ICameraService.h +++ b/include/camera/ICameraService.h @@ -30,13 +30,19 @@ class ICameraService : public IInterface { public: enum { - CONNECT = IBinder::FIRST_CALL_TRANSACTION, + GET_NUMBER_OF_CAMERAS = IBinder::FIRST_CALL_TRANSACTION, + GET_CAMERA_INFO, + CONNECT }; public: DECLARE_META_INTERFACE(CameraService); - virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient) = 0; + virtual int32_t getNumberOfCameras() = 0; + virtual status_t getCameraInfo(int cameraId, + struct CameraInfo* cameraInfo) = 0; + virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, + int cameraId) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/gui/ISensorEventConnection.h b/include/gui/ISensorEventConnection.h new file mode 100644 index 0000000..ed4e4cc --- /dev/null +++ b/include/gui/ISensorEventConnection.h @@ -0,0 +1,57 @@ +/* + * 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_GUI_ISENSOR_EVENT_CONNECTION_H +#define ANDROID_GUI_ISENSOR_EVENT_CONNECTION_H + +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <utils/RefBase.h> + +#include <binder/IInterface.h> + +namespace android { +// ---------------------------------------------------------------------------- + +class SensorChannel; + +class ISensorEventConnection : public IInterface +{ +public: + DECLARE_META_INTERFACE(SensorEventConnection); + + virtual sp<SensorChannel> getSensorChannel() const = 0; + virtual status_t enableDisable(int handle, bool enabled) = 0; + virtual status_t setEventRate(int handle, nsecs_t ns) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnSensorEventConnection : public BnInterface<ISensorEventConnection> +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_GUI_ISENSOR_EVENT_CONNECTION_H diff --git a/include/gui/ISensorServer.h b/include/gui/ISensorServer.h new file mode 100644 index 0000000..9c8afc5 --- /dev/null +++ b/include/gui/ISensorServer.h @@ -0,0 +1,57 @@ +/* + * 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_GUI_ISENSORSERVER_H +#define ANDROID_GUI_ISENSORSERVER_H + +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <utils/RefBase.h> + +#include <binder/IInterface.h> + +namespace android { +// ---------------------------------------------------------------------------- + +class Sensor; +class ISensorEventConnection; + +class ISensorServer : public IInterface +{ +public: + DECLARE_META_INTERFACE(SensorServer); + + virtual Vector<Sensor> getSensorList() = 0; + virtual sp<ISensorEventConnection> createSensorEventConnection() = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnSensorServer : public BnInterface<ISensorServer> +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_GUI_ISENSORSERVER_H diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h new file mode 100644 index 0000000..2de07b1 --- /dev/null +++ b/include/gui/Sensor.h @@ -0,0 +1,91 @@ +/* + * 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_GUI_SENSOR_H +#define ANDROID_GUI_SENSOR_H + +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <utils/String8.h> +#include <utils/Flattenable.h> + +#include <hardware/sensors.h> + +#include <android/sensor.h> + +// ---------------------------------------------------------------------------- +// Concrete types for the NDK +struct ASensor { }; + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +class Parcel; + +// ---------------------------------------------------------------------------- + +class Sensor : public ASensor, public Flattenable +{ +public: + enum { + TYPE_ACCELEROMETER = ASENSOR_TYPE_ACCELEROMETER, + TYPE_MAGNETIC_FIELD = ASENSOR_TYPE_MAGNETIC_FIELD, + TYPE_GYROSCOPE = ASENSOR_TYPE_GYROSCOPE, + TYPE_LIGHT = ASENSOR_TYPE_LIGHT, + TYPE_PROXIMITY = ASENSOR_TYPE_PROXIMITY + }; + + Sensor(); + Sensor(struct sensor_t const* hwSensor); + virtual ~Sensor(); + + const String8& getName() const; + const String8& getVendor() const; + int32_t getHandle() const; + int32_t getType() const; + float getMinValue() const; + float getMaxValue() const; + float getResolution() const; + float getPowerUsage() const; + int32_t getMinDelay() const; + + // Flattenable interface + virtual size_t getFlattenedSize() const; + virtual size_t getFdCount() const; + virtual status_t flatten(void* buffer, size_t size, + int fds[], size_t count) const; + virtual status_t unflatten(void const* buffer, size_t size, + int fds[], size_t count); + +private: + String8 mName; + String8 mVendor; + int32_t mHandle; + int32_t mType; + float mMinValue; + float mMaxValue; + float mResolution; + float mPower; + int32_t mMinDelay; +}; + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_GUI_SENSOR_H diff --git a/include/gui/SensorChannel.h b/include/gui/SensorChannel.h new file mode 100644 index 0000000..bb54618 --- /dev/null +++ b/include/gui/SensorChannel.h @@ -0,0 +1,53 @@ +/* + * 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_GUI_SENSOR_CHANNEL_H +#define ANDROID_GUI_SENSOR_CHANNEL_H + +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <utils/RefBase.h> + + +namespace android { +// ---------------------------------------------------------------------------- +class Parcel; + +class SensorChannel : public RefBase +{ +public: + + SensorChannel(); + SensorChannel(const Parcel& data); + virtual ~SensorChannel(); + + int getFd() const; + ssize_t write(void const* vaddr, size_t size); + ssize_t read(void* vaddr, size_t size); + + status_t writeToParcel(Parcel* reply) const; + +private: + int mSendFd; + mutable int mReceiveFd; +}; + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_GUI_SENSOR_CHANNEL_H diff --git a/include/gui/SensorEventQueue.h b/include/gui/SensorEventQueue.h new file mode 100644 index 0000000..6581ae3 --- /dev/null +++ b/include/gui/SensorEventQueue.h @@ -0,0 +1,82 @@ +/* + * 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_SENSOR_EVENT_QUEUE_H +#define ANDROID_SENSOR_EVENT_QUEUE_H + +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <utils/RefBase.h> +#include <utils/Timers.h> + +#include <gui/SensorChannel.h> + +// ---------------------------------------------------------------------------- + +struct ALooper; +struct ASensorEvent; + +// Concrete types for the NDK +struct ASensorEventQueue { + ALooper* looper; +}; + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +class ISensorEventConnection; +class Sensor; +class PollLoop; + +// ---------------------------------------------------------------------------- + +class SensorEventQueue : public ASensorEventQueue, public RefBase +{ +public: + SensorEventQueue(const sp<ISensorEventConnection>& connection); + virtual ~SensorEventQueue(); + virtual void onFirstRef(); + + int getFd() const; + ssize_t write(ASensorEvent const* events, size_t numEvents); + ssize_t read(ASensorEvent* events, size_t numEvents); + + status_t waitForEvent() const; + status_t wake() const; + + status_t enableSensor(Sensor const* sensor) const; + status_t disableSensor(Sensor const* sensor) const; + status_t setEventRate(Sensor const* sensor, nsecs_t ns) const; + + // these are here only to support SensorManager.java + status_t enableSensor(int32_t handle, int32_t us) const; + status_t disableSensor(int32_t handle) const; + +private: + sp<PollLoop> getPollLoop() const; + sp<ISensorEventConnection> mSensorEventConnection; + sp<SensorChannel> mSensorChannel; + mutable Mutex mLock; + mutable sp<PollLoop> mPollLoop; +}; + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_SENSOR_EVENT_QUEUE_H diff --git a/include/gui/SensorManager.h b/include/gui/SensorManager.h new file mode 100644 index 0000000..e1b1a7b --- /dev/null +++ b/include/gui/SensorManager.h @@ -0,0 +1,63 @@ +/* + * 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_GUI_SENSOR_MANAGER_H +#define ANDROID_GUI_SENSOR_MANAGER_H + +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <utils/RefBase.h> +#include <utils/Singleton.h> +#include <utils/Vector.h> + +#include <gui/SensorEventQueue.h> + +// ---------------------------------------------------------------------------- +// Concrete types for the NDK +struct ASensorManager { }; + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +class ISensorServer; +class Sensor; +class SensorEventQueue; + +// ---------------------------------------------------------------------------- + +class SensorManager : public ASensorManager, public Singleton<SensorManager> +{ +public: + SensorManager(); + ~SensorManager(); + + ssize_t getSensorList(Sensor const* const** list) const; + Sensor const* getDefaultSensor(int type); + sp<SensorEventQueue> createEventQueue(); + +private: + sp<ISensorServer> mSensorServer; + Sensor const** mSensorList; + Vector<Sensor> mSensors; +}; + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_GUI_SENSOR_MANAGER_H diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h new file mode 100644 index 0000000..c967efb --- /dev/null +++ b/include/media/AudioEffect.h @@ -0,0 +1,470 @@ +/* + * 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_AUDIOEFFECT_H +#define ANDROID_AUDIOEFFECT_H + +#include <stdint.h> +#include <sys/types.h> + +#include <media/IAudioFlinger.h> +#include <media/IEffect.h> +#include <media/IEffectClient.h> +#include <media/EffectApi.h> +#include <media/AudioSystem.h> + +#include <utils/RefBase.h> +#include <utils/Errors.h> +#include <binder/IInterface.h> + + +namespace android { + +// ---------------------------------------------------------------------------- + +class effect_param_cblk_t; + +// ---------------------------------------------------------------------------- + +class AudioEffect : public RefBase +{ +public: + + /* + * Static methods for effect libraries management. + */ + + /* + * Loads the effect library which path is given as first argument. + * This must be the full path of a dynamic library (.so) implementing one or + * more effect engines and exposing the effect library interface described in + * EffectApi.h. The function returns a handle on the library for use by + * further call to unloadEffectLibrary() to unload the library. + * + * Parameters: + * libPath: full path of the dynamic library file in the file system. + * handle: address where to return the library handle + * + * Returned status (from utils/Errors.h) can be: + * NO_ERROR successful operation. + * PERMISSION_DENIED could not get AudioFlinger interface or + * application does not have permission to configure audio + * NO_INIT effect factory not initialized or + * library could not be loaded or + * library does not implement required functions + * BAD_VALUE invalid libPath string or handle + * + * Returned value: + * *handle updated with library handle + */ + static status_t loadEffectLibrary(const char *libPath, int *handle); + + /* + * Unloads the effect library which handle is given as argument. + * + * Parameters: + * handle: library handle + * + * Returned status (from utils/Errors.h) can be: + * NO_ERROR successful operation. + * PERMISSION_DENIED could not get AudioFlinger interface or + * application does not have permission to configure audio + * NO_INIT effect factory not initialized + * BAD_VALUE invalid handle + */ + static status_t unloadEffectLibrary(int handle); + + /* + * Static methods for effects enumeration. + */ + + /* + * Returns the number of effects available. This method together + * with queryEffect() is used to enumerate all effects: + * The enumeration sequence is: + * queryNumberEffects(&num_effects); + * for (i = 0; i < num_effects; i++) + * queryEffect(i,...); + * + * Parameters: + * numEffects: address where the number of effects should be returned. + * + * Returned status (from utils/Errors.h) can be: + * NO_ERROR successful operation. + * PERMISSION_DENIED could not get AudioFlinger interface + * NO_INIT effect library failed to initialize + * BAD_VALUE invalid numEffects pointer + * + * Returned value + * *numEffects: updated with number of effects available + */ + static status_t queryNumberEffects(uint32_t *numEffects); + + /* + * Returns an effect descriptor during effect + * enumeration. + * + * Parameters: + * index: index of the queried effect. + * descriptor: address where the effect descriptor should be returned. + * + * Returned status (from utils/Errors.h) can be: + * NO_ERROR successful operation. + * PERMISSION_DENIED could not get AudioFlinger interface + * NO_INIT effect library failed to initialize + * BAD_VALUE invalid descriptor pointer or index + * INVALID_OPERATION effect list has changed since last execution of queryNumberEffects() + * + * Returned value + * *descriptor: updated with effect descriptor + */ + static status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor); + + + /* + * Returns the descriptor for the specified effect uuid. + * + * Parameters: + * uuid: pointer to effect uuid. + * descriptor: address where the effect descriptor should be returned. + * + * Returned status (from utils/Errors.h) can be: + * NO_ERROR successful operation. + * PERMISSION_DENIED could not get AudioFlinger interface + * NO_INIT effect library failed to initialize + * BAD_VALUE invalid uuid or descriptor pointers + * NAME_NOT_FOUND no effect with this uuid found + * + * Returned value + * *descriptor updated with effect descriptor + */ + static status_t getEffectDescriptor(effect_uuid_t *uuid, effect_descriptor_t *descriptor); + + + /* + * Events used by callback function (effect_callback_t). + */ + enum event_type { + EVENT_CONTROL_STATUS_CHANGED = 0, + EVENT_ENABLE_STATUS_CHANGED = 1, + EVENT_PARAMETER_CHANGED = 2, + EVENT_ERROR = 3 + }; + + /* Callback function notifying client application of a change in effect engine state or + * configuration. + * An effect engine can be shared by several applications but only one has the control + * of the engine activity and configuration at a time. + * The EVENT_CONTROL_STATUS_CHANGED event is received when an application loses or + * retrieves the control of the effect engine. Loss of control happens + * if another application requests the use of the engine by creating an AudioEffect for + * the same effect type but with a higher priority. Control is returned when the + * application having the control deletes its AudioEffect object. + * The EVENT_ENABLE_STATUS_CHANGED event is received by all applications not having the + * control of the effect engine when the effect is enabled or disabled. + * The EVENT_PARAMETER_CHANGED event is received by all applications not having the + * control of the effect engine when an effect parameter is changed. + * The EVENT_ERROR event is received when the media server process dies. + * + * Parameters: + * + * event: type of event notified (see enum AudioEffect::event_type). + * user: Pointer to context for use by the callback receiver. + * info: Pointer to optional parameter according to event type: + * - EVENT_CONTROL_STATUS_CHANGED: boolean indicating if control is granted (true) + * or stolen (false). + * - EVENT_ENABLE_STATUS_CHANGED: boolean indicating if effect is now enabled (true) + * or disabled (false). + * - EVENT_PARAMETER_CHANGED: pointer to a effect_param_t structure. + * - EVENT_ERROR: status_t indicating the error (DEAD_OBJECT when media server dies). + */ + + typedef void (*effect_callback_t)(int32_t event, void* user, void *info); + + + /* Constructor. + * AudioEffect is the base class for creating and controlling an effect engine from + * the application process. Creating an AudioEffect object will create the effect engine + * in the AudioFlinger if no engine of the specified type exists. If one exists, this engine + * will be used. The application creating the AudioEffect object (or a derived class like + * Reverb for instance) will either receive control of the effect engine or not, depending + * on the priority parameter. If priority is higher than the priority used by the current + * effect engine owner, the control will be transfered to the new application. Otherwise + * control will remain to the previous application. In this case, the new application will be + * notified of changes in effect engine state or control ownership by the effect callback. + * After creating the AudioEffect, the application must call the initCheck() method and + * check the creation status before trying to control the effect engine (see initCheck()). + * If the effect is to be applied to an AudioTrack or MediaPlayer only the application + * must specify the audio session ID corresponding to this player. + */ + + /* Simple Constructor. + */ + AudioEffect(); + + + /* Constructor. + * + * Parameters: + * + * type: type of effect created: can be null if uuid is specified. This corresponds to + * the OpenSL ES interface implemented by this effect. + * uuid: Uuid of effect created: can be null if type is specified. This uuid corresponds to + * a particular implementation of an effect type. + * priority: requested priority for effect control: the priority level corresponds to the + * value of priority parameter: negative values indicate lower priorities, positive values + * higher priorities, 0 being the normal priority. + * cbf: optional callback function (see effect_callback_t) + * user: pointer to context for use by the callback receiver. + * sessionID: audio session this effect is associated to. If 0, the effect will be global to + * the output mix. If not 0, the effect will be applied to all players + * (AudioTrack or MediaPLayer) within the same audio session. + * output: HAL audio output stream to which this effect must be attached. Leave at 0 for + * automatic output selection by AudioFlinger. + */ + + AudioEffect(const effect_uuid_t *type, + const effect_uuid_t *uuid = NULL, + int32_t priority = 0, + effect_callback_t cbf = 0, + void* user = 0, + int sessionId = 0, + audio_io_handle_t output = 0 + ); + + /* Constructor. + * Same as above but with type and uuid specified by character strings + */ + AudioEffect(const char *typeStr, + const char *uuidStr = NULL, + int32_t priority = 0, + effect_callback_t cbf = 0, + void* user = 0, + int sessionId = 0, + audio_io_handle_t output = 0 + ); + + /* Terminates the AudioEffect and unregisters it from AudioFlinger. + * The effect engine is also destroyed if this AudioEffect was the last controlling + * the engine. + */ + ~AudioEffect(); + + /* Initialize an uninitialized AudioEffect. + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR or ALREADY_EXISTS: successful initialization + * - INVALID_OPERATION: AudioEffect is already initialized + * - BAD_VALUE: invalid parameter + * - NO_INIT: audio flinger or audio hardware not initialized + * */ + status_t set(const effect_uuid_t *type, + const effect_uuid_t *uuid = NULL, + int32_t priority = 0, + effect_callback_t cbf = 0, + void* user = 0, + int sessionId = 0, + audio_io_handle_t output = 0 + ); + + /* Result of constructing the AudioEffect. This must be checked + * before using any AudioEffect API. + * initCheck() can return: + * - NO_ERROR: the effect engine is successfully created and the application has control. + * - ALREADY_EXISTS: the effect engine is successfully created but the application does not + * have control. + * - NO_INIT: the effect creation failed. + * + */ + status_t initCheck() const; + + + /* Returns the unique effect Id for the controlled effect engine. This ID is unique + * system wide and is used for instance in the case of auxiliary effects to attach + * the effect to an AudioTrack or MediaPlayer. + * + */ + int32_t id() const { return mId; } + + /* Returns a descriptor for the effect (see effect_descriptor_t in EffectApi.h). + */ + effect_descriptor_t descriptor() const; + + /* Returns effect control priority of this AudioEffect object. + */ + int32_t priority() const { return mPriority; } + + + /* Enables or disables the effect engine. + * + * Parameters: + * enabled: requested enable state. + * + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation + * - INVALID_OPERATION: the application does not have control of the effect engine or the + * effect is already in the requested state. + */ + virtual status_t setEnabled(bool enabled); + bool getEnabled() const; + + /* Sets a parameter value. + * + * Parameters: + * param: pointer to effect_param_t structure containing the parameter + * and its value (See EffectApi.h). + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation. + * - INVALID_OPERATION: the application does not have control of the effect engine. + * - BAD_VALUE: invalid parameter identifier or value. + * - DEAD_OBJECT: the effect engine has been deleted. + */ + virtual status_t setParameter(effect_param_t *param); + + /* Prepare a new parameter value that will be set by next call to + * setParameterCommit(). This method can be used to set multiple parameters + * in a synchronous manner or to avoid multiple binder calls for each + * parameter. + * + * Parameters: + * param: pointer to effect_param_t structure containing the parameter + * and its value (See EffectApi.h). + * + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation. + * - INVALID_OPERATION: the application does not have control of the effect engine. + * - NO_MEMORY: no more space available in shared memory used for deferred parameter + * setting. + */ + virtual status_t setParameterDeferred(effect_param_t *param); + + /* Commit all parameter values previously prepared by setParameterDeferred(). + * + * Parameters: + * none + * + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation. + * - INVALID_OPERATION: No new parameter values ready for commit. + * - BAD_VALUE: invalid parameter identifier or value: there is no indication + * as to which of the parameters caused this error. + * - DEAD_OBJECT: the effect engine has been deleted. + */ + virtual status_t setParameterCommit(); + + /* Gets a parameter value. + * + * Parameters: + * param: pointer to effect_param_t structure containing the parameter + * and the returned value (See EffectApi.h). + * + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation. + * - INVALID_OPERATION: the AudioEffect was not successfully initialized. + * - BAD_VALUE: invalid parameter identifier. + * - DEAD_OBJECT: the effect engine has been deleted. + */ + virtual status_t getParameter(effect_param_t *param); + + /* Sends a command and receives a response to/from effect engine. + * See EffectApi.h for details on effect command() function, valid command codes + * and formats. + */ + virtual status_t command(uint32_t cmdCode, + uint32_t cmdSize, + void *cmdData, + uint32_t *replySize, + void *replyData); + + + /* + * Utility functions. + */ + + /* Converts the string passed as first argument to the effect_uuid_t + * pointed to by second argument + */ + static status_t stringToGuid(const char *str, effect_uuid_t *guid); + /* Converts the effect_uuid_t pointed to by first argument to the + * string passed as second argument + */ + static status_t guidToString(const effect_uuid_t *guid, char *str, size_t maxLen); + +protected: + volatile int32_t mEnabled; // enable state + int32_t mSessionId; // audio session ID + int32_t mPriority; // priority for effect control + status_t mStatus; // effect status + effect_callback_t mCbf; // callback function for status, control and + // parameter changes notifications + void* mUserData; // client context for callback function + effect_descriptor_t mDescriptor; // effect descriptor + int32_t mId; // system wide unique effect engine instance ID + +private: + + // Implements the IEffectClient interface + class EffectClient : public android::BnEffectClient, public android::IBinder::DeathRecipient + { + public: + + EffectClient(AudioEffect *effect) : mEffect(effect){} + + // IEffectClient + virtual void controlStatusChanged(bool controlGranted) { + mEffect->controlStatusChanged(controlGranted); + } + virtual void enableStatusChanged(bool enabled) { + mEffect->enableStatusChanged(enabled); + } + virtual void commandExecuted(uint32_t cmdCode, + uint32_t cmdSize, + void *pCmdData, + uint32_t replySize, + void *pReplyData) { + mEffect->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData); + } + + // IBinder::DeathRecipient + virtual void binderDied(const wp<IBinder>& who) {mEffect->binderDied();} + + private: + AudioEffect *mEffect; + }; + + + friend class EffectClient; + + // IEffectClient + void controlStatusChanged(bool controlGranted); + void enableStatusChanged(bool enabled); + void commandExecuted(uint32_t cmdCode, + uint32_t cmdSize, + void *pCmdData, + uint32_t replySize, + void *pReplyData); + void binderDied(); + + + sp<IEffect> mIEffect; // IEffect binder interface + sp<EffectClient> mIEffectClient; // IEffectClient implementation + sp<IMemory> mCblkMemory; // shared memory for deferred parameter setting + effect_param_cblk_t* mCblk; // control block for deferred parameter setting +}; + + +}; // namespace android + +#endif // ANDROID_AUDIOEFFECT_H diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h index 92bc126..38e3d44 100644 --- a/include/media/AudioRecord.h +++ b/include/media/AudioRecord.h @@ -100,6 +100,19 @@ public: typedef void (*callback_t)(int event, void* user, void *info); + /* Returns the minimum frame count required for the successful creation of + * an AudioRecord object. + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation + * - NO_INIT: audio server or audio hardware not initialized + * - BAD_VALUE: unsupported configuration + */ + + static status_t getMinFrameCount(int* frameCount, + uint32_t sampleRate, + int format, + int channelCount); + /* Constructs an uninitialized AudioRecord. No connection with * AudioFlinger takes place. */ @@ -142,7 +155,8 @@ public: uint32_t flags = 0, callback_t cbf = 0, void* user = 0, - int notificationFrames = 0); + int notificationFrames = 0, + int sessionId = 0); /* Terminates the AudioRecord and unregisters it from AudioFlinger. @@ -168,7 +182,8 @@ public: callback_t cbf = 0, void* user = 0, int notificationFrames = 0, - bool threadCanCallJava = false); + bool threadCanCallJava = false, + int sessionId = 0); /* Result of constructing the AudioRecord. This must be checked @@ -270,6 +285,16 @@ public: */ audio_io_handle_t getInput(); + /* returns the audio session ID associated to this AudioRecord. + * + * Parameters: + * none. + * + * Returned value: + * AudioRecord session ID. + */ + int getSessionId(); + /* obtains a buffer of "frameCount" frames. The buffer must be * filled entirely. If the track is stopped, obtainBuffer() returns * STOPPED instead of NO_ERROR as long as there are buffers availlable, @@ -356,6 +381,7 @@ private: uint32_t mFlags; uint32_t mChannels; audio_io_handle_t mInput; + int mSessionId; }; }; // namespace android diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index d0ccc50..9fd905f 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -168,6 +168,15 @@ public: TX_DISABLE = 0 }; + // special audio session values + enum audio_sessions { + SESSION_OUTPUT_STAGE = -1, // session for effects attached to a particular output stream + // (value must be less than 0) + SESSION_OUTPUT_MIX = 0, // session for effects applied to output mix. These effects can + // be moved by audio policy manager to another output stream + // (value must be 0) + }; + /* These are static methods to control the system-wide AudioFlinger * only privileged processes can have access to them */ @@ -234,6 +243,8 @@ public: static status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int stream = DEFAULT); static unsigned int getInputFramesLost(audio_io_handle_t ioHandle); + + static int newAudioSessionId(); // // AudioPolicyService interface // @@ -351,8 +362,12 @@ public: uint32_t format = FORMAT_DEFAULT, uint32_t channels = CHANNEL_OUT_STEREO, output_flags flags = OUTPUT_FLAG_INDIRECT); - static status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream); - static status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream); + static status_t startOutput(audio_io_handle_t output, + AudioSystem::stream_type stream, + int session = 0); + static status_t stopOutput(audio_io_handle_t output, + AudioSystem::stream_type stream, + int session = 0); static void releaseOutput(audio_io_handle_t output); static audio_io_handle_t getInput(int inputSource, uint32_t samplingRate = 0, @@ -368,6 +383,16 @@ public: static status_t setStreamVolumeIndex(stream_type stream, int index); static status_t getStreamVolumeIndex(stream_type stream, int *index); + static uint32_t getStrategyForStream(stream_type stream); + + static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc); + static status_t registerEffect(effect_descriptor_t *desc, + audio_io_handle_t output, + uint32_t strategy, + int session, + int id); + static status_t unregisterEffect(int id); + static const sp<IAudioPolicyService>& get_audio_policy_service(); // ---------------------------------------------------------------------------- diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index 14b30ae..4475d4a 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -102,6 +102,17 @@ public: typedef void (*callback_t)(int event, void* user, void *info); + /* Returns the minimum frame count required for the successful creation of + * an AudioTrack object. + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation + * - NO_INIT: audio server or audio hardware not initialized + */ + + static status_t getMinFrameCount(int* frameCount, + int streamType =-1, + uint32_t sampleRate = 0); + /* Constructs an uninitialized AudioTrack. No connection with * AudioFlinger takes place. */ @@ -138,7 +149,8 @@ public: uint32_t flags = 0, callback_t cbf = 0, void* user = 0, - int notificationFrames = 0); + int notificationFrames = 0, + int sessionId = 0); /* Creates an audio track and registers it with AudioFlinger. With this constructor, * The PCM data to be rendered by AudioTrack is passed in a shared memory buffer @@ -157,7 +169,8 @@ public: uint32_t flags = 0, callback_t cbf = 0, void* user = 0, - int notificationFrames = 0); + int notificationFrames = 0, + int sessionId = 0); /* Terminates the AudioTrack and unregisters it from AudioFlinger. * Also destroys all resources assotiated with the AudioTrack. @@ -182,7 +195,8 @@ public: void* user = 0, int notificationFrames = 0, const sp<IMemory>& sharedBuffer = 0, - bool threadCanCallJava = false); + bool threadCanCallJava = false, + int sessionId = 0); /* Result of constructing the AudioTrack. This must be checked @@ -239,10 +253,17 @@ public: /* set volume for this track, mostly used for games' sound effects + * left and right volumes. Levels must be <= 1.0. */ - void setVolume(float left, float right); + status_t setVolume(float left, float right); void getVolume(float* left, float* right); + /* set the send level for this track. An auxiliary effect should be attached + * to the track with attachEffect(). Level must be <= 1.0. + */ + status_t setAuxEffectSendLevel(float level); + void getAuxEffectSendLevel(float* level); + /* set sample rate for this track, mostly used for games' sound effects */ status_t setSampleRate(int sampleRate); @@ -340,6 +361,31 @@ public: */ audio_io_handle_t getOutput(); + /* returns the unique ID associated to this track. + * + * Parameters: + * none. + * + * Returned value: + * AudioTrack ID. + */ + int getSessionId(); + + + /* Attach track auxiliary output to specified effect. Used effectId = 0 + * to detach track from effect. + * + * Parameters: + * + * effectId: effectId obtained from AudioEffect::id(). + * + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation + * - INVALID_OPERATION: the effect is not an auxiliary effect. + * - BAD_VALUE: The specified effect ID is invalid + */ + status_t attachAuxEffect(int effectId); + /* obtains a buffer of "frameCount" frames. The buffer must be * filled entirely. If the track is stopped, obtainBuffer() returns * STOPPED instead of NO_ERROR as long as there are buffers availlable, @@ -398,13 +444,15 @@ private: int frameCount, uint32_t flags, const sp<IMemory>& sharedBuffer, - audio_io_handle_t output); + audio_io_handle_t output, + bool enforceFrameCount); sp<IAudioTrack> mAudioTrack; sp<IMemory> mCblkMemory; sp<AudioTrackThread> mAudioTrackThread; float mVolume[2]; + float mSendLevel; uint32_t mFrameCount; audio_track_cblk_t* mCblk; @@ -420,7 +468,8 @@ private: callback_t mCbf; void* mUserData; - uint32_t mNotificationFrames; + uint32_t mNotificationFramesReq; // requested number of frames between each notification callback + uint32_t mNotificationFramesAct; // actual number of frames between each notification callback sp<IMemory> mSharedBuffer; int mLoopCount; uint32_t mRemainingFrames; @@ -429,6 +478,8 @@ private: uint32_t mNewPosition; uint32_t mUpdatePeriod; uint32_t mFlags; + int mSessionId; + int mAuxEffectId; }; diff --git a/include/media/EffectApi.h b/include/media/EffectApi.h new file mode 100644 index 0000000..16fb43c --- /dev/null +++ b/include/media/EffectApi.h @@ -0,0 +1,796 @@ +/* + * 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_EFFECTAPI_H_ +#define ANDROID_EFFECTAPI_H_ + +#include <errno.h> +#include <stdint.h> +#include <sys/types.h> + +#if __cplusplus +extern "C" { +#endif + +///////////////////////////////////////////////// +// Effect control interface +///////////////////////////////////////////////// + +// The effect control interface is exposed by each effect engine implementation. It consists of +// a set of functions controlling the configuration, activation and process of the engine. +// The functions are grouped in a structure of type effect_interface_s: +// struct effect_interface_s { +// effect_process_t process; +// effect_command_t command; +// }; + + +// effect_interface_t: Effect control interface handle. +// The effect_interface_t serves two purposes regarding the implementation of the effect engine: +// - 1 it is the address of a pointer to an effect_interface_s structure where the functions +// of the effect control API for a particular effect are located. +// - 2 it is the address of the context of a particular effect instance. +// A typical implementation in the effect library would define a structure as follows: +// struct effect_module_s { +// const struct effect_interface_s *itfe; +// effect_config_t config; +// effect_context_t context; +// } +// The implementation of EffectCreate() function would then allocate a structure of this +// type and return its address as effect_interface_t +typedef struct effect_interface_s **effect_interface_t; + + +// Effect API version 1.0 +#define EFFECT_API_VERSION 0x0100 // Format 0xMMmm MM: Major version, mm: minor version + +// Maximum length of character strings in structures defines by this API. +#define EFFECT_STRING_LEN_MAX 64 + +// +//--- Effect descriptor structure effect_descriptor_t +// + +// Unique effect ID (can be generated from the following site: +// http://www.itu.int/ITU-T/asn1/uuid.html) +// This format is used for both "type" and "uuid" fields of the effect descriptor structure. +// - When used for effect type and the engine is implementing and effect corresponding to a standard +// OpenSL ES interface, this ID must be the one defined in OpenSLES_IID.h for that interface. +// - When used as uuid, it should be a unique UUID for this particular implementation. +typedef struct effect_uuid_s { + uint32_t timeLow; + uint16_t timeMid; + uint16_t timeHiAndVersion; + uint16_t clockSeq; + uint8_t node[6]; +} effect_uuid_t; + +// NULL UUID definition (matches SL_IID_NULL_) +#define EFFECT_UUID_INITIALIZER { 0xec7178ec, 0xe5e1, 0x4432, 0xa3f4, \ + { 0x46, 0x57, 0xe6, 0x79, 0x52, 0x10 } } +static const effect_uuid_t EFFECT_UUID_NULL_ = EFFECT_UUID_INITIALIZER; +const effect_uuid_t * const EFFECT_UUID_NULL = &EFFECT_UUID_NULL_; +const char * const EFFECT_UUID_NULL_STR = "ec7178ec-e5e1-4432-a3f4-4657e6795210"; + +// The effect descriptor contains necessary information to facilitate the enumeration of the effect +// engines present in a library. +typedef struct effect_descriptor_s { + effect_uuid_t type; // UUID of to the OpenSL ES interface implemented by this effect + effect_uuid_t uuid; // UUID for this particular implementation + uint16_t apiVersion; // Version of the effect API implemented: matches EFFECT_API_VERSION + uint32_t flags; // effect engine capabilities/requirements flags (see below) + uint16_t cpuLoad; // CPU load indication (see below) + uint16_t memoryUsage; // Data Memory usage (see below) + char name[EFFECT_STRING_LEN_MAX]; // human readable effect name + char implementor[EFFECT_STRING_LEN_MAX]; // human readable effect implementor name +} effect_descriptor_t; + +// CPU load and memory usage indication: each effect implementation must provide an indication of +// its CPU and memory usage for the audio effect framework to limit the number of effects +// instantiated at a given time on a given platform. +// The CPU load is expressed in 0.1 MIPS units as estimated on an ARM9E core (ARMv5TE) with 0 WS. +// The memory usage is expressed in KB and includes only dynamically allocated memory + +// Definitions for flags field of effect descriptor. +// +---------------------------+-----------+----------------------------------- +// | description | bits | values +// +---------------------------+-----------+----------------------------------- +// | connection mode | 0..1 | 0 insert: after track process +// | | | 1 auxiliary: connect to track auxiliary +// | | | output and use send level +// | | | 2 replace: replaces track process function; +// | | | must implement SRC, volume and mono to stereo. +// | | | 3 reserved +// +---------------------------+-----------+----------------------------------- +// | insertion preference | 2..4 | 0 none +// | | | 1 first of the chain +// | | | 2 last of the chain +// | | | 3 exclusive (only effect in the insert chain) +// | | | 4..7 reserved +// +---------------------------+-----------+----------------------------------- +// | Volume management | 5..6 | 0 none +// | | | 1 implements volume control +// | | | 2 requires volume indication +// | | | 3 reserved +// +---------------------------+-----------+----------------------------------- +// | Device indication | 7..8 | 0 none +// | | | 1 requires device updates +// | | | 2..3 reserved +// +---------------------------+-----------+----------------------------------- +// | Sample input mode | 9..10 | 0 direct: process() function or EFFECT_CMD_CONFIGURE +// | | | command must specify a buffer descriptor +// | | | 1 provider: process() function uses the +// | | | bufferProvider indicated by the +// | | | EFFECT_CMD_CONFIGURE command to request input. +// | | | buffers. +// | | | 2 both: both input modes are supported +// | | | 3 reserved +// +---------------------------+-----------+----------------------------------- +// | Sample output mode | 11..12 | 0 direct: process() function or EFFECT_CMD_CONFIGURE +// | | | command must specify a buffer descriptor +// | | | 1 provider: process() function uses the +// | | | bufferProvider indicated by the +// | | | EFFECT_CMD_CONFIGURE command to request output +// | | | buffers. +// | | | 2 both: both output modes are supported +// | | | 3 reserved +// +---------------------------+-----------+----------------------------------- +// | Hardware acceleration | 13..15 | 0 No hardware acceleration +// | | | 1 non tunneled hw acceleration: the process() function +// | | | reads the samples, send them to HW accelerated +// | | | effect processor, reads back the processed samples +// | | | and returns them to the output buffer. +// | | | 2 tunneled hw acceleration: the process() function is +// | | | transparent. The effect interface is only used to +// | | | control the effect engine. This mode is relevant for +// | | | global effects actually applied by the audio +// | | | hardware on the output stream. +// +---------------------------+-----------+----------------------------------- +// | Audio Mode indication | 16..17 | 0 none +// | | | 1 requires audio mode updates +// | | | 2..3 reserved +// +---------------------------+-----------+----------------------------------- + +// Insert mode +#define EFFECT_FLAG_TYPE_MASK 0x00000003 +#define EFFECT_FLAG_TYPE_INSERT 0x00000000 +#define EFFECT_FLAG_TYPE_AUXILIARY 0x00000001 +#define EFFECT_FLAG_TYPE_REPLACE 0x00000002 + +// Insert preference +#define EFFECT_FLAG_INSERT_MASK 0x0000001C +#define EFFECT_FLAG_INSERT_ANY 0x00000000 +#define EFFECT_FLAG_INSERT_FIRST 0x00000004 +#define EFFECT_FLAG_INSERT_LAST 0x00000008 +#define EFFECT_FLAG_INSERT_EXCLUSIVE 0x0000000C + + +// Volume control +#define EFFECT_FLAG_VOLUME_MASK 0x00000060 +#define EFFECT_FLAG_VOLUME_CTRL 0x00000020 +#define EFFECT_FLAG_VOLUME_IND 0x00000040 +#define EFFECT_FLAG_VOLUME_NONE 0x00000000 + +// Device indication +#define EFFECT_FLAG_DEVICE_MASK 0x00000180 +#define EFFECT_FLAG_DEVICE_IND 0x00000080 +#define EFFECT_FLAG_DEVICE_NONE 0x00000000 + +// Sample input modes +#define EFFECT_FLAG_INPUT_MASK 0x00000600 +#define EFFECT_FLAG_INPUT_DIRECT 0x00000000 +#define EFFECT_FLAG_INPUT_PROVIDER 0x00000200 +#define EFFECT_FLAG_INPUT_BOTH 0x00000400 + +// Sample output modes +#define EFFECT_FLAG_OUTPUT_MASK 0x00001800 +#define EFFECT_FLAG_OUTPUT_DIRECT 0x00000000 +#define EFFECT_FLAG_OUTPUT_PROVIDER 0x00000800 +#define EFFECT_FLAG_OUTPUT_BOTH 0x00001000 + +// Hardware acceleration mode +#define EFFECT_FLAG_HW_ACC_MASK 0x00006000 +#define EFFECT_FLAG_HW_ACC_SIMPLE 0x00002000 +#define EFFECT_FLAG_HW_ACC_TUNNEL 0x00004000 + +// Audio mode indication +#define EFFECT_FLAG_AUDIO_MODE_MASK 0x00018000 +#define EFFECT_FLAG_AUDIO_MODE_IND 0x00008000 +#define EFFECT_FLAG_AUDIO_MODE_NONE 0x00000000 + +// Forward definition of type audio_buffer_t +typedef struct audio_buffer_s audio_buffer_t; + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: process +// +// Description: Effect process function. Takes input samples as specified +// (count and location) in input buffer descriptor and output processed +// samples as specified in output buffer descriptor. If the buffer descriptor +// is not specified the function must use either the buffer or the +// buffer provider function installed by the EFFECT_CMD_CONFIGURE command. +// The effect framework will call the process() function after the EFFECT_CMD_ENABLE +// command is received and until the EFFECT_CMD_DISABLE is received. When the engine +// receives the EFFECT_CMD_DISABLE command it should turn off the effect gracefully +// and when done indicate that it is OK to stop calling the process() function by +// returning the -ENODATA status. +// +// NOTE: the process() function implementation should be "real-time safe" that is +// it should not perform blocking calls: malloc/free, sleep, read/write/open/close, +// pthread_cond_wait/pthread_mutex_lock... +// +// Input: +// effect_interface_t: handle to the effect interface this function +// is called on. +// inBuffer: buffer descriptor indicating where to read samples to process. +// If NULL, use the configuration passed by EFFECT_CMD_CONFIGURE command. +// +// inBuffer: buffer descriptor indicating where to write processed samples. +// If NULL, use the configuration passed by EFFECT_CMD_CONFIGURE command. +// +// Output: +// returned value: 0 successful operation +// -ENODATA the engine has finished the disable phase and the framework +// can stop calling process() +// -EINVAL invalid interface handle or +// invalid input/output buffer description +//////////////////////////////////////////////////////////////////////////////// +typedef int32_t (*effect_process_t)(effect_interface_t self, + audio_buffer_t *inBuffer, + audio_buffer_t *outBuffer); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: command +// +// Description: Send a command and receive a response to/from effect engine. +// +// Input: +// effect_interface_t: handle to the effect interface this function +// is called on. +// cmdCode: command code: the command can be a standardized command defined in +// effect_command_e (see below) or a proprietary command. +// cmdSize: size of command in bytes +// pCmdData: pointer to command data +// pReplyData: pointer to reply data +// +// Input/Output: +// replySize: maximum size of reply data as input +// actual size of reply data as output +// +// Output: +// returned value: 0 successful operation +// -EINVAL invalid interface handle or +// invalid command/reply size or format according to command code +// The return code should be restricted to indicate problems related to the this +// API specification. Status related to the execution of a particular command should be +// indicated as part of the reply field. +// +// *pReplyData updated with command response +// +//////////////////////////////////////////////////////////////////////////////// +typedef int32_t (*effect_command_t)(effect_interface_t self, + uint32_t cmdCode, + uint32_t cmdSize, + void *pCmdData, + uint32_t *replySize, + void *pReplyData); + + +// Effect control interface definition +struct effect_interface_s { + effect_process_t process; + effect_command_t command; +}; + + +// +//--- Standardized command codes for command() function +// +enum effect_command_e { + EFFECT_CMD_INIT, // initialize effect engine + EFFECT_CMD_CONFIGURE, // configure effect engine (see effect_config_t) + EFFECT_CMD_RESET, // reset effect engine + EFFECT_CMD_ENABLE, // enable effect process + EFFECT_CMD_DISABLE, // disable effect process + EFFECT_CMD_SET_PARAM, // set parameter immediately (see effect_param_t) + EFFECT_CMD_SET_PARAM_DEFERRED, // set parameter deferred + EFFECT_CMD_SET_PARAM_COMMIT, // commit previous set parameter deferred + EFFECT_CMD_GET_PARAM, // get parameter + EFFECT_CMD_SET_DEVICE, // set audio device (see audio_device_e) + EFFECT_CMD_SET_VOLUME, // set volume + EFFECT_CMD_SET_AUDIO_MODE, // set the audio mode (normal, ring, ...) + EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code +}; + +//================================================================================================== +// command: EFFECT_CMD_INIT +//-------------------------------------------------------------------------------------------------- +// description: +// Initialize effect engine: All configurations return to default +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_CONFIGURE +//-------------------------------------------------------------------------------------------------- +// description: +// Apply new audio parameters configurations for input and output buffers +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_RESET +//-------------------------------------------------------------------------------------------------- +// description: +// Reset the effect engine. Keep configuration but resets state and buffer content +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_ENABLE +//-------------------------------------------------------------------------------------------------- +// description: +// Enable the process. Called by the framework before the first call to process() +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_DISABLE +//-------------------------------------------------------------------------------------------------- +// description: +// Disable the process. Called by the framework after the last call to process() +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_PARAM +//-------------------------------------------------------------------------------------------------- +// description: +// Set a parameter and apply it immediately +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_PARAM_DEFERRED +//-------------------------------------------------------------------------------------------------- +// description: +// Set a parameter but apply it only when receiving EFFECT_CMD_SET_PARAM_COMMIT command +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_SET_PARAM_COMMIT +//-------------------------------------------------------------------------------------------------- +// description: +// Apply all previously received EFFECT_CMD_SET_PARAM_DEFERRED commands +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_GET_PARAM +//-------------------------------------------------------------------------------------------------- +// description: +// Get a parameter value +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param +// data: effect_param_t + param +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//================================================================================================== +// command: EFFECT_CMD_SET_DEVICE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the rendering device the audio output path is connected to. See audio_device_e for device +// values. +// The effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to receive this +// command when the device changes +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: audio_device_e +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_SET_VOLUME +//-------------------------------------------------------------------------------------------------- +// description: +// Set and get volume. Used by audio framework to delegate volume control to effect engine. +// The effect implementation must set EFFECT_FLAG_VOLUME_IND or EFFECT_FLAG_VOLUME_CTRL flag in +// its descriptor to receive this command before every call to process() function +// If EFFECT_FLAG_VOLUME_CTRL flag is set in the effect descriptor, the effect engine must return +// the volume that should be applied before the effect is processed. The overall volume (the volume +// actually applied by the effect engine multiplied by the returned value) should match the value +// indicated in the command. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: n * sizeof(uint32_t) +// data: volume for each channel defined in effect_config_t for output buffer expressed in +// 8.24 fixed point format +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: n * sizeof(uint32_t) / 0 +// data: - if EFFECT_FLAG_VOLUME_CTRL is set in effect descriptor: +// volume for each channel defined in effect_config_t for output buffer expressed in +// 8.24 fixed point format +// - if EFFECT_FLAG_VOLUME_CTRL is not set in effect descriptor: +// N/A +// It is legal to receive a null pointer as pReplyData in which case the effect framework has +// delegated volume control to another effect +//================================================================================================== +// command: EFFECT_CMD_SET_AUDIO_MODE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the audio mode. The effect implementation must set EFFECT_FLAG_AUDIO_MODE_IND flag in its +// descriptor to receive this command when the audio mode changes. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: audio_mode_e +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_FIRST_PROPRIETARY +//-------------------------------------------------------------------------------------------------- +// description: +// All proprietary effect commands must use command codes above this value. The size and format of +// command and response fields is free in this case +//================================================================================================== + + +// Audio buffer descriptor used by process(), bufferProvider() functions and buffer_config_t +// structure. Multi-channel audio is always interleaved. The channel order is from LSB to MSB with +// regard to the channel mask definition in audio_channels_e e.g : +// Stereo: left, right +// 5 point 1: front left, front right, front center, low frequency, back left, back right +// The buffer size is expressed in frame count, a frame being composed of samples for all +// channels at a given time. Frame size for unspecified format (AUDIO_FORMAT_OTHER) is 8 bit by +// definition +struct audio_buffer_s { + size_t frameCount; // number of frames in buffer + union { + void* raw; // raw pointer to start of buffer + int32_t* s32; // pointer to signed 32 bit data at start of buffer + int16_t* s16; // pointer to signed 16 bit data at start of buffer + uint8_t* u8; // pointer to unsigned 8 bit data at start of buffer + }; +}; + +// The buffer_provider_s structure contains functions that can be used +// by the effect engine process() function to query and release input +// or output audio buffer. +// The getBuffer() function is called to retrieve a buffer where data +// should read from or written to by process() function. +// The releaseBuffer() function MUST be called when the buffer retrieved +// with getBuffer() is not needed anymore. +// The process function should use the buffer provider mechanism to retrieve +// input or output buffer if the inBuffer or outBuffer passed as argument is NULL +// and the buffer configuration (buffer_config_t) given by the EFFECT_CMD_CONFIGURE +// command did not specify an audio buffer. + +typedef int32_t (* buffer_function_t)(void *cookie, audio_buffer_t *buffer); + +typedef struct buffer_provider_s { + buffer_function_t getBuffer; // retrieve next buffer + buffer_function_t releaseBuffer; // release used buffer + void *cookie; // for use by client of buffer provider functions +} buffer_provider_t; + + +// The buffer_config_s structure specifies the input or output audio format +// to be used by the effect engine. It is part of the effect_config_t +// structure that defines both input and output buffer configurations and is +// passed by the EFFECT_CMD_CONFIGURE command. +typedef struct buffer_config_s { + audio_buffer_t buffer; // buffer for use by process() function if not passed explicitly + uint32_t samplingRate; // sampling rate + uint32_t channels; // channel mask (see audio_channels_e) + buffer_provider_t bufferProvider; // buffer provider + uint8_t format; // Audio format (see audio_format_e) + uint8_t accessMode; // read/write or accumulate in buffer (effect_buffer_access_e) + uint16_t mask; // indicates which of the above fields is valid +} buffer_config_t; + +// Sample format +enum audio_format_e { + SAMPLE_FORMAT_PCM_S15, // PCM signed 16 bits + SAMPLE_FORMAT_PCM_U8, // PCM unsigned 8 bits + SAMPLE_FORMAT_PCM_S7_24, // PCM signed 7.24 fixed point representation + SAMPLE_FORMAT_OTHER // other format (e.g. compressed) +}; + +// Channel mask +enum audio_channels_e { + CHANNEL_FRONT_LEFT = 0x1, // front left channel + CHANNEL_FRONT_RIGHT = 0x2, // front right channel + CHANNEL_FRONT_CENTER = 0x4, // front center channel + CHANNEL_LOW_FREQUENCY = 0x8, // low frequency channel + CHANNEL_BACK_LEFT = 0x10, // back left channel + CHANNEL_BACK_RIGHT = 0x20, // back right channel + CHANNEL_FRONT_LEFT_OF_CENTER = 0x40, // front left of center channel + CHANNEL_FRONT_RIGHT_OF_CENTER = 0x80, // front right of center channel + CHANNEL_BACK_CENTER = 0x100, // back center channel + CHANNEL_MONO = CHANNEL_FRONT_LEFT, + CHANNEL_STEREO = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT), + CHANNEL_QUAD = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT), + CHANNEL_SURROUND = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER), + CHANNEL_5POINT1 = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT), + CHANNEL_7POINT1 = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT | + CHANNEL_FRONT_LEFT_OF_CENTER | CHANNEL_FRONT_RIGHT_OF_CENTER), +}; + +// Render device +enum audio_device_e { + DEVICE_EARPIECE = 0x1, // earpiece + DEVICE_SPEAKER = 0x2, // speaker + DEVICE_WIRED_HEADSET = 0x4, // wired headset, with microphone + DEVICE_WIRED_HEADPHONE = 0x8, // wired headphone, without microphone + DEVICE_BLUETOOTH_SCO = 0x10, // generic bluetooth SCO + DEVICE_BLUETOOTH_SCO_HEADSET = 0x20, // bluetooth SCO headset + DEVICE_BLUETOOTH_SCO_CARKIT = 0x40, // bluetooth SCO car kit + DEVICE_BLUETOOTH_A2DP = 0x80, // generic bluetooth A2DP + DEVICE_BLUETOOTH_A2DP_HEADPHONES = 0x100, // bluetooth A2DP headphones + DEVICE_BLUETOOTH_A2DP_SPEAKER = 0x200, // bluetooth A2DP speakers + DEVICE_AUX_DIGITAL = 0x400, // digital output + DEVICE_EXTERNAL_SPEAKER = 0x800 // external speaker (stereo and High quality) +}; + +// Audio mode +enum audio_mode_e { + AUDIO_MODE_NORMAL, // phone idle + AUDIO_MODE_RINGTONE, // phone ringing + AUDIO_MODE_IN_CALL // phone call connected +}; + +// Values for "accessMode" field of buffer_config_t: +// overwrite, read only, accumulate (read/modify/write) +enum effect_buffer_access_e { + EFFECT_BUFFER_ACCESS_WRITE, + EFFECT_BUFFER_ACCESS_READ, + EFFECT_BUFFER_ACCESS_ACCUMULATE + +}; + +// Values for bit field "mask" in buffer_config_t. If a bit is set, the corresponding field +// in buffer_config_t must be taken into account when executing the EFFECT_CMD_CONFIGURE command +#define EFFECT_CONFIG_BUFFER 0x0001 // buffer field must be taken into account +#define EFFECT_CONFIG_SMP_RATE 0x0002 // samplingRate field must be taken into account +#define EFFECT_CONFIG_CHANNELS 0x0004 // channels field must be taken into account +#define EFFECT_CONFIG_FORMAT 0x0008 // format field must be taken into account +#define EFFECT_CONFIG_ACC_MODE 0x0010 // accessMode field must be taken into account +#define EFFECT_CONFIG_PROVIDER 0x0020 // bufferProvider field must be taken into account +#define EFFECT_CONFIG_ALL (EFFECT_CONFIG_BUFFER | EFFECT_CONFIG_SMP_RATE | \ + EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT | \ + EFFECT_CONFIG_ACC_MODE | EFFECT_CONFIG_PROVIDER) + + +// effect_config_s structure describes the format of the pCmdData argument of EFFECT_CMD_CONFIGURE +// command to configure audio parameters and buffers for effect engine input and output. +typedef struct effect_config_s { + buffer_config_t inputCfg; + buffer_config_t outputCfg;; +} effect_config_t; + + +// effect_param_s structure describes the format of the pCmdData argument of EFFECT_CMD_SET_PARAM +// command and pCmdData and pReplyData of EFFECT_CMD_GET_PARAM command. +// psize and vsize represent the actual size of parameter and value. +// +// NOTE: the start of value field inside the data field is always on a 32 bit boundary: +// +// +-----------+ +// | status | sizeof(int) +// +-----------+ +// | psize | sizeof(int) +// +-----------+ +// | vsize | sizeof(int) +// +-----------+ +// | | | | +// ~ parameter ~ > psize | +// | | | > ((psize - 1)/sizeof(int) + 1) * sizeof(int) +// +-----------+ | +// | padding | | +// +-----------+ +// | | | +// ~ value ~ > vsize +// | | | +// +-----------+ + +typedef struct effect_param_s { + int32_t status; // Transaction status (unused for command, used for reply) + uint32_t psize; // Parameter size + uint32_t vsize; // Value size + char data[]; // Start of Parameter + Value data +} effect_param_t; + + +///////////////////////////////////////////////// +// Effect library interface +///////////////////////////////////////////////// + +// An effect library is required to implement and expose the following functions +// to enable effect enumeration and instantiation. The name of these functions must be as +// specified here as the effect framework will get the function address with dlsym(): +// +// - effect_QueryNumberEffects_t EffectQueryNumberEffects; +// - effect_QueryEffect_t EffectQueryEffect; +// - effect_CreateEffect_t EffectCreate; +// - effect_ReleaseEffect_t EffectRelease; + + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectQueryNumberEffects +// +// Description: Returns the number of different effects exposed by the +// library. Each effect must have a unique effect uuid (see +// effect_descriptor_t). This function together with EffectQueryEffect() +// is used to enumerate all effects present in the library. +// +// Input/Output: +// pNumEffects: address where the number of effects should be returned. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV library failed to initialize +// -EINVAL invalid pNumEffects +// *pNumEffects: updated with number of effects in library +// +//////////////////////////////////////////////////////////////////////////////// +typedef int32_t (*effect_QueryNumberEffects_t)(uint32_t *pNumEffects); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectQueryEffect +// +// Description: Returns the descriptor of the effect engine which index is +// given as first argument. +// See effect_descriptor_t for details on effect descriptors. +// This function together with EffectQueryNumberEffects() is used to enumerate all +// effects present in the library. The enumeration sequence is: +// EffectQueryNumberEffects(&num_effects); +// for (i = 0; i < num_effects; i++) +// EffectQueryEffect(i,...); +// +// Input/Output: +// index: index of the effect +// pDescriptor: address where to return the effect descriptor. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV library failed to initialize +// -EINVAL invalid pDescriptor or index +// -ENOSYS effect list has changed since last execution of +// EffectQueryNumberEffects() +// -ENOENT no more effect available +// *pDescriptor: updated with the effect descriptor. +// +//////////////////////////////////////////////////////////////////////////////// +typedef int32_t (*effect_QueryEffect_t)(uint32_t index, + effect_descriptor_t *pDescriptor); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectCreate +// +// Description: Creates an effect engine of the specified type and returns an +// effect control interface on this engine. The function will allocate the +// resources for an instance of the requested effect engine and return +// a handle on the effect control interface. +// +// Input: +// uuid: pointer to the effect uuid. +// sessionId: audio session to which this effect instance will be attached. All effects +// created with the same session ID are connected in series and process the same signal +// stream. Knowing that two effects are part of the same effect chain can help the +// library implement some kind of optimizations. +// ioId: identifies the output or input stream this effect is directed to at audio HAL. +// For future use especially with tunneled HW accelerated effects +// +// Input/Output: +// pInterface: address where to return the effect interface. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV library failed to initialize +// -EINVAL invalid pEffectUuid or pInterface +// -ENOENT no effect with this uuid found +// *pInterface: updated with the effect interface handle. +// +//////////////////////////////////////////////////////////////////////////////// +typedef int32_t (*effect_CreateEffect_t)(effect_uuid_t *uuid, + int32_t sessionId, + int32_t ioId, + effect_interface_t *pInterface); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectRelease +// +// Description: Releases the effect engine whose handle is given as argument. +// All resources allocated to this particular instance of the effect are +// released. +// +// Input: +// interface: handle on the effect interface to be released. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV library failed to initialize +// -EINVAL invalid interface handle +// +//////////////////////////////////////////////////////////////////////////////// +typedef int32_t (*effect_ReleaseEffect_t)(effect_interface_t interface); + + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*ANDROID_EFFECTAPI_H_*/ diff --git a/include/media/EffectBassBoostApi.h b/include/media/EffectBassBoostApi.h new file mode 100644 index 0000000..75f8d78 --- /dev/null +++ b/include/media/EffectBassBoostApi.h @@ -0,0 +1,43 @@ +/* + * 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_EFFECTBASSBOOSTAPI_H_ +#define ANDROID_EFFECTBASSBOOSTAPI_H_ + +#include <media/EffectApi.h> + +#if __cplusplus +extern "C" { +#endif + +#ifndef OPENSL_ES_H_ +static const effect_uuid_t SL_IID_BASSBOOST_ = { 0x0634f220, 0xddd4, 0x11db, 0xa0fc, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const effect_uuid_t * const SL_IID_BASSBOOST = &SL_IID_BASSBOOST_; +#endif //OPENSL_ES_H_ + +/* enumerated parameter settings for BassBoost effect */ +typedef enum +{ + BASSBOOST_PARAM_STRENGTH_SUPPORTED, + BASSBOOST_PARAM_STRENGTH +} t_bassboost_params; + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*ANDROID_EFFECTBASSBOOSTAPI_H_*/ diff --git a/include/media/EffectEnvironmentalReverbApi.h b/include/media/EffectEnvironmentalReverbApi.h new file mode 100644 index 0000000..2233e3f --- /dev/null +++ b/include/media/EffectEnvironmentalReverbApi.h @@ -0,0 +1,69 @@ +/* + * 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_EFFECTENVIRONMENTALREVERBAPI_H_ +#define ANDROID_EFFECTENVIRONMENTALREVERBAPI_H_ + +#include <media/EffectApi.h> + +#if __cplusplus +extern "C" { +#endif + +#ifndef OPENSL_ES_H_ +static const effect_uuid_t SL_IID_ENVIRONMENTALREVERB_ = { 0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, { 0x4e, 0x23, 0x4d, 0x6, 0x83, 0x9e } }; +const effect_uuid_t * const SL_IID_ENVIRONMENTALREVERB = &SL_IID_ENVIRONMENTALREVERB_; +#endif //OPENSL_ES_H_ + +/* enumerated parameter settings for environmental reverb effect */ +typedef enum +{ + // Parameters below are as defined in OpenSL ES specification for environmental reverb interface + REVERB_PARAM_ROOM_LEVEL, // in millibels, range -6000 to 0 + REVERB_PARAM_ROOM_HF_LEVEL, // in millibels, range -4000 to 0 + REVERB_PARAM_DECAY_TIME, // in milliseconds, range 100 to 20000 + REVERB_PARAM_DECAY_HF_RATIO, // in permilles, range 100 to 1000 + REVERB_PARAM_REFLECTIONS_LEVEL, // in millibels, range -6000 to 0 + REVERB_PARAM_REFLECTIONS_DELAY, // in milliseconds, range 0 to 65 + REVERB_PARAM_REVERB_LEVEL, // in millibels, range -6000 to 0 + REVERB_PARAM_REVERB_DELAY, // in milliseconds, range 0 to 65 + REVERB_PARAM_DIFFUSION, // in permilles, range 0 to 1000 + REVERB_PARAM_DENSITY, // in permilles, range 0 to 1000 + REVERB_PARAM_PROPERTIES, + REVERB_PARAM_BYPASS +} t_env_reverb_params; + +//t_reverb_settings is equal to SLEnvironmentalReverbSettings defined in OpenSL ES specification. +typedef struct s_reverb_settings { + int16_t roomLevel; + int16_t roomHFLevel; + int32_t decayTime; + int16_t decayHFRatio; + int16_t reflectionsLevel; + int32_t reflectionsDelay; + int16_t reverbLevel; + int32_t reverbDelay; + int16_t diffusion; + int16_t density; +} __attribute__((packed)) t_reverb_settings; + + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*ANDROID_EFFECTENVIRONMENTALREVERBAPI_H_*/ diff --git a/include/media/EffectEqualizerApi.h b/include/media/EffectEqualizerApi.h new file mode 100644 index 0000000..0492ea0 --- /dev/null +++ b/include/media/EffectEqualizerApi.h @@ -0,0 +1,58 @@ +/* + * 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_EFFECTEQUALIZERAPI_H_ +#define ANDROID_EFFECTEQUALIZERAPI_H_ + +#include <media/EffectApi.h> + +#ifndef OPENSL_ES_H_ +static const effect_uuid_t SL_IID_EQUALIZER_ = { 0x0bed4300, 0xddd6, 0x11db, 0x8f34, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const effect_uuid_t * const SL_IID_EQUALIZER = &SL_IID_EQUALIZER_; +#endif //OPENSL_ES_H_ + +#if __cplusplus +extern "C" { +#endif + +/* enumerated parameters for Equalizer effect */ +typedef enum +{ + EQ_PARAM_NUM_BANDS, // Gets the number of frequency bands that the equalizer supports. + EQ_PARAM_LEVEL_RANGE, // Returns the minimum and maximum band levels supported. + EQ_PARAM_BAND_LEVEL, // Gets/Sets the gain set for the given equalizer band. + EQ_PARAM_CENTER_FREQ, // Gets the center frequency of the given band. + EQ_PARAM_BAND_FREQ_RANGE, // Gets the frequency range of the given frequency band. + EQ_PARAM_GET_BAND, // Gets the band that has the most effect on the given frequency. + EQ_PARAM_CUR_PRESET, // Gets/Sets the current preset. + EQ_PARAM_GET_NUM_OF_PRESETS, // Gets the total number of presets the equalizer supports. + EQ_PARAM_GET_PRESET_NAME, // Gets the preset name based on the index. + EQ_PARAM_PROPERTIES // Gets/Sets all parameters at a time. +} t_equalizer_params; + +//t_equalizer_settings groups all current equalizer setting for backup and restore. +typedef struct s_equalizer_settings { + uint16_t curPreset; + uint16_t numBands; + uint16_t bandLevels[]; +} t_equalizer_settings; + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*ANDROID_EFFECTEQUALIZERAPI_H_*/ diff --git a/include/media/EffectPresetReverbApi.h b/include/media/EffectPresetReverbApi.h new file mode 100644 index 0000000..53205bb --- /dev/null +++ b/include/media/EffectPresetReverbApi.h @@ -0,0 +1,54 @@ +/* + * 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_EFFECTPRESETREVERBAPI_H_ +#define ANDROID_EFFECTPRESETREVERBAPI_H_ + +#include <media/EffectApi.h> + +#if __cplusplus +extern "C" { +#endif + +#ifndef OPENSL_ES_H_ +static const effect_uuid_t SL_IID_PRESETREVERB_ = { 0x47382d60, 0xddd8, 0x11db, 0xbf3a, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const effect_uuid_t * const SL_IID_PRESETREVERB = &SL_IID_PRESETREVERB_; +#endif //OPENSL_ES_H_ + +/* enumerated parameter settings for preset reverb effect */ +typedef enum +{ + REVERB_PARAM_PRESET +} t_preset_reverb_params; + + +typedef enum +{ + REVERB_PRESET_NONE, + REVERB_PRESET_SMALLROOM, + REVERB_PRESET_MEDIUMROOM, + REVERB_PRESET_LARGEROOM, + REVERB_PRESET_MEDIUMHALL, + REVERB_PRESET_LARGEHALL, + REVERB_PRESET_PLATE +} t_reverb_presets; + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*ANDROID_EFFECTPRESETREVERBAPI_H_*/ diff --git a/include/media/EffectVirtualizerApi.h b/include/media/EffectVirtualizerApi.h new file mode 100644 index 0000000..c3d5131 --- /dev/null +++ b/include/media/EffectVirtualizerApi.h @@ -0,0 +1,43 @@ +/* + * 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_EFFECTVIRTUALIZERAPI_H_ +#define ANDROID_EFFECTVIRTUALIZERAPI_H_ + +#include <media/EffectApi.h> + +#if __cplusplus +extern "C" { +#endif + +#ifndef OPENSL_ES_H_ +static const effect_uuid_t SL_IID_VIRTUALIZER_ = { 0x37cc2c00, 0xdddd, 0x11db, 0x8577, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const effect_uuid_t * const SL_IID_VIRTUALIZER = &SL_IID_VIRTUALIZER_; +#endif //OPENSL_ES_H_ + +/* enumerated parameter settings for virtualizer effect */ +typedef enum +{ + VIRTUALIZER_PARAM_STRENGTH_SUPPORTED, + VIRTUALIZER_PARAM_STRENGTH +} t_virtualizer_params; + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*ANDROID_EFFECTVIRTUALIZERAPI_H_*/ diff --git a/include/media/EffectVisualizerApi.h b/include/media/EffectVisualizerApi.h new file mode 100644 index 0000000..bef1a4f --- /dev/null +++ b/include/media/EffectVisualizerApi.h @@ -0,0 +1,56 @@ +/* + * 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_EFFECTVISUALIZERAPI_H_ +#define ANDROID_EFFECTVISUALIZERAPI_H_ + +#include <media/EffectApi.h> + +#if __cplusplus +extern "C" { +#endif + +#ifndef OPENSL_ES_H_ +static const effect_uuid_t SL_IID_VISUALIZATION_ = + { 0xe46b26a0, 0xdddd, 0x11db, 0x8afd, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const effect_uuid_t * const SL_IID_VISUALIZATION = &SL_IID_VISUALIZATION_; +#endif //OPENSL_ES_H_ + +#define VISUALIZER_CAPTURE_SIZE_MAX 1024 // maximum capture size in samples +#define VISUALIZER_CAPTURE_SIZE_MIN 128 // minimum capture size in samples + +/* enumerated parameters for Visualizer effect */ +typedef enum +{ + VISU_PARAM_CAPTURE_SIZE, // Sets the number PCM samples in the capture. +} t_visualizer_params; + +/* commands */ +typedef enum +{ + VISU_CMD_CAPTURE = EFFECT_CMD_FIRST_PROPRIETARY, // Gets the latest PCM capture. +}t_visualizer_cmds; + +// VISU_CMD_CAPTURE retrieves the latest PCM snapshot captured by the visualizer engine. +// It returns the number of samples specified by VISU_PARAM_CAPTURE_SIZE +// in 8 bit unsigned format (0 = 0x80) + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*ANDROID_EFFECTVISUALIZERAPI_H_*/ diff --git a/include/media/EffectsFactoryApi.h b/include/media/EffectsFactoryApi.h new file mode 100644 index 0000000..0ed1a14 --- /dev/null +++ b/include/media/EffectsFactoryApi.h @@ -0,0 +1,221 @@ +/* + * 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_EFFECTSFACTORYAPI_H_ +#define ANDROID_EFFECTSFACTORYAPI_H_ + +#include <errno.h> +#include <stdint.h> +#include <sys/types.h> +#include <media/EffectApi.h> + +#if __cplusplus +extern "C" { +#endif + +///////////////////////////////////////////////// +// Effect factory interface +///////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectQueryNumberEffects +// +// Description: Returns the number of different effects in all loaded libraries. +// Each effect must have a different effect uuid (see +// effect_descriptor_t). This function together with EffectQueryEffect() +// is used to enumerate all effects present in all loaded libraries. +// Each time EffectQueryNumberEffects() is called, the factory must +// reset the index of the effect descriptor returned by next call to +// EffectQueryEffect() to restart enumeration from the beginning. +// +// Input/Output: +// pNumEffects: address where the number of effects should be returned. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV factory failed to initialize +// -EINVAL invalid pNumEffects +// *pNumEffects: updated with number of effects in factory +// +//////////////////////////////////////////////////////////////////////////////// +int EffectQueryNumberEffects(uint32_t *pNumEffects); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectQueryEffect +// +// Description: Returns a descriptor of the next available effect. +// See effect_descriptor_t for a details on effect descriptor. +// This function together with EffectQueryNumberEffects() is used to enumerate all +// effects present in all loaded libraries. The enumeration sequence is: +// EffectQueryNumberEffects(&num_effects); +// for (i = 0; i < num_effects; i++) +// EffectQueryEffect(i,...); +// +// Input/Output: +// pDescriptor: address where to return the effect descriptor. +// +// Output: +// returned value: 0 successful operation. +// -ENOENT no more effect available +// -ENODEV factory failed to initialize +// -EINVAL invalid pDescriptor +// -ENOSYS effect list has changed since last execution of EffectQueryNumberEffects() +// *pDescriptor: updated with the effect descriptor. +// +//////////////////////////////////////////////////////////////////////////////// +int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectCreate +// +// Description: Creates an effect engine of the specified type and returns an +// effect control interface on this engine. The function will allocate the +// resources for an instance of the requested effect engine and return +// a handler on the effect control interface. +// +// Input: +// pEffectUuid: pointer to the effect uuid. +// sessionId: audio session to which this effect instance will be attached. All effects created +// with the same session ID are connected in series and process the same signal stream. +// Knowing that two effects are part of the same effect chain can help the library implement +// some kind of optimizations. +// ioId: identifies the output or input stream this effect is directed to at audio HAL. For future +// use especially with tunneled HW accelerated effects +// +// Input/Output: +// pInterface: address where to return the effect interface. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV factory failed to initialize +// -EINVAL invalid pEffectUuid or pInterface +// -ENOENT no effect with this uuid found +// *pInterface: updated with the effect interface. +// +//////////////////////////////////////////////////////////////////////////////// +int EffectCreate(effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t ioId, effect_interface_t *pInterface); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectRelease +// +// Description: Releases the effect engine whose handler is given as argument. +// All resources allocated to this particular instance of the effect are +// released. +// +// Input: +// interface: handler on the effect interface to be released. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV factory failed to initialize +// -EINVAL invalid interface handler +// +//////////////////////////////////////////////////////////////////////////////// +int EffectRelease(effect_interface_t interface); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectLoadLibrary +// +// Description: Loads the effect library which path is given as first argument. +// This must be the full path of a dynamic library (.so) implementing one or +// more effect engines and exposing the effect library interface described in +// EffectApi.h. The function returns a handle on the library for used by +// further call to EffectUnloadLibrary() to unload the library. +// +// Input: +// libPath: full path of the dynamic library file in the file system. +// +// handle: address where to return the library handle +// +// Output: +// returned value: 0 successful operation. +// -ENODEV effect factory not initialized or +// library could not be loaded or +// library does not implement required functions +// -EINVAL invalid libPath string or handle +// +//////////////////////////////////////////////////////////////////////////////// +int EffectLoadLibrary(const char *libPath, int *handle); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectUnloadLibrary +// +// Description: Unloads the effect library which handle is given as argument. +// +// Input: +// handle: library handle +// +// Output: +// returned value: 0 successful operation. +// -ENODEV effect factory not initialized +// -ENOENT invalid handle +// +//////////////////////////////////////////////////////////////////////////////// +int EffectUnloadLibrary(int handle); + + + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectGetDescriptor +// +// Description: Returns the descriptor of the effect which uuid is pointed +// to by first argument. +// +// Input: +// pEffectUuid: pointer to the effect uuid. +// +// Input/Output: +// pDescriptor: address where to return the effect descriptor. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV factory failed to initialize +// -EINVAL invalid pEffectUuid or pDescriptor +// -ENOENT no effect with this uuid found +// *pDescriptor: updated with the effect descriptor. +// +//////////////////////////////////////////////////////////////////////////////// +int EffectGetDescriptor(effect_uuid_t *pEffectUuid, effect_descriptor_t *pDescriptor); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectIsNullUuid +// +// Description: Helper function to compare effect uuid to EFFECT_UUID_NULL +// +// Input: +// pEffectUuid: pointer to effect uuid to compare to EFFECT_UUID_NULL. +// +// Output: +// returned value: 0 if uuid is different from EFFECT_UUID_NULL. +// 1 if uuid is equal to EFFECT_UUID_NULL. +// +//////////////////////////////////////////////////////////////////////////////// +int EffectIsNullUuid(effect_uuid_t *pEffectUuid); + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*ANDROID_EFFECTSFACTORYAPI_H_*/ diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h index c147632..70e505e 100644 --- a/include/media/IAudioFlinger.h +++ b/include/media/IAudioFlinger.h @@ -27,6 +27,9 @@ #include <media/IAudioTrack.h> #include <media/IAudioRecord.h> #include <media/IAudioFlingerClient.h> +#include <media/EffectApi.h> +#include <media/IEffect.h> +#include <media/IEffectClient.h> #include <utils/String8.h> namespace android { @@ -51,6 +54,7 @@ public: uint32_t flags, const sp<IMemory>& sharedBuffer, int output, + int *sessionId, status_t *status) = 0; virtual sp<IAudioRecord> openRecord( @@ -61,6 +65,7 @@ public: int channelCount, int frameCount, uint32_t flags, + int *sessionId, status_t *status) = 0; /* query the audio hardware state. This state never changes, @@ -134,6 +139,30 @@ public: virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output) = 0; virtual unsigned int getInputFramesLost(int ioHandle) = 0; + + virtual int newAudioSessionId() = 0; + + virtual status_t loadEffectLibrary(const char *libPath, int *handle) = 0; + + virtual status_t unloadEffectLibrary(int handle) = 0; + + virtual status_t queryNumberEffects(uint32_t *numEffects) = 0; + + virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor) = 0; + + virtual status_t getEffectDescriptor(effect_uuid_t *pEffectUUID, effect_descriptor_t *pDescriptor) = 0; + + virtual sp<IEffect> createEffect(pid_t pid, + effect_descriptor_t *pDesc, + const sp<IEffectClient>& client, + int32_t priority, + int output, + int sessionId, + status_t *status, + int *id, + int *enabled) = 0; + + virtual status_t moveEffects(int session, int srcOutput, int dstOutput) = 0; }; diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h index 4804bbd..49eee59 100644 --- a/include/media/IAudioPolicyService.h +++ b/include/media/IAudioPolicyService.h @@ -53,8 +53,12 @@ public: uint32_t format = AudioSystem::FORMAT_DEFAULT, uint32_t channels = 0, AudioSystem::output_flags flags = AudioSystem::OUTPUT_FLAG_INDIRECT) = 0; - virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream) = 0; - virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream) = 0; + virtual status_t startOutput(audio_io_handle_t output, + AudioSystem::stream_type stream, + int session = 0) = 0; + virtual status_t stopOutput(audio_io_handle_t output, + AudioSystem::stream_type stream, + int session = 0) = 0; virtual void releaseOutput(audio_io_handle_t output) = 0; virtual audio_io_handle_t getInput(int inputSource, uint32_t samplingRate = 0, @@ -69,6 +73,14 @@ public: int indexMax) = 0; virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index) = 0; virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index) = 0; + virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream) = 0; + virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc) = 0; + virtual status_t registerEffect(effect_descriptor_t *desc, + audio_io_handle_t output, + uint32_t strategy, + int session, + int id) = 0; + virtual status_t unregisterEffect(int id) = 0; }; diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h index de6426a..47d530b 100644 --- a/include/media/IAudioTrack.h +++ b/include/media/IAudioTrack.h @@ -62,6 +62,11 @@ public: */ virtual void pause() = 0; + /* Attach track auxiliary output to specified effect. Use effectId = 0 + * to detach track from effect. + */ + virtual status_t attachAuxEffect(int effectId) = 0; + /* get this tracks control block */ virtual sp<IMemory> getCblk() const = 0; }; diff --git a/include/media/IEffect.h b/include/media/IEffect.h new file mode 100644 index 0000000..ff04869 --- /dev/null +++ b/include/media/IEffect.h @@ -0,0 +1,60 @@ +/* + * 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_IEFFECT_H +#define ANDROID_IEFFECT_H + +#include <utils/RefBase.h> +#include <binder/IInterface.h> +#include <binder/Parcel.h> +#include <binder/IMemory.h> + +namespace android { + +class IEffect: public IInterface +{ +public: + DECLARE_META_INTERFACE(Effect); + + virtual status_t enable() = 0; + + virtual status_t disable() = 0; + + virtual status_t command(uint32_t cmdCode, + uint32_t cmdSize, + void *pCmdData, + uint32_t *pReplySize, + void *pReplyData) = 0; + + virtual void disconnect() = 0; + + virtual sp<IMemory> getCblk() const = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnEffect: public BnInterface<IEffect> +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IEFFECT_H diff --git a/include/media/IEffectClient.h b/include/media/IEffectClient.h new file mode 100644 index 0000000..2f78c98 --- /dev/null +++ b/include/media/IEffectClient.h @@ -0,0 +1,54 @@ +/* + * 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_IEFFECTCLIENT_H +#define ANDROID_IEFFECTCLIENT_H + +#include <utils/RefBase.h> +#include <binder/IInterface.h> +#include <binder/Parcel.h> +#include <binder/IMemory.h> + +namespace android { + +class IEffectClient: public IInterface +{ +public: + DECLARE_META_INTERFACE(EffectClient); + + virtual void controlStatusChanged(bool controlGranted) = 0; + virtual void enableStatusChanged(bool enabled) = 0; + virtual void commandExecuted(uint32_t cmdCode, + uint32_t cmdSize, + void *pCmdData, + uint32_t replySize, + void *pReplyData) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnEffectClient: public BnInterface<IEffectClient> +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IEFFECTCLIENT_H diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h index 2619691..af9a7ed 100644 --- a/include/media/IMediaPlayer.h +++ b/include/media/IMediaPlayer.h @@ -48,6 +48,8 @@ public: virtual status_t setVolume(float leftVolume, float rightVolume) = 0; virtual status_t suspend() = 0; virtual status_t resume() = 0; + virtual status_t setAuxEffectSendLevel(float level) = 0; + virtual status_t attachAuxEffect(int effectId) = 0; // Invoke a generic method on the player by using opaque parcels // for the request and reply. diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h index 31c0991..9416ca1 100644 --- a/include/media/IMediaPlayerService.h +++ b/include/media/IMediaPlayerService.h @@ -40,15 +40,14 @@ public: virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid) = 0; virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) = 0; - virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url, const KeyedVector<String8, String8> *headers = NULL) = 0; - virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) = 0; + virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, + const char* url, const KeyedVector<String8, String8> *headers = NULL, + int audioSessionId = 0) = 0; + virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, + int fd, int64_t offset, int64_t length, int audioSessionId) = 0; virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0; virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0; virtual sp<IOMX> getOMX() = 0; - - // Take a peek at currently playing audio, for visualization purposes. - // This returns a buffer of 16 bit mono PCM data, or NULL if no visualization buffer is currently available. - virtual sp<IMemory> snoop() = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h index 73bf2ee..54adca8 100644 --- a/include/media/IMediaRecorder.h +++ b/include/media/IMediaRecorder.h @@ -24,7 +24,7 @@ namespace android { class ISurface; class ICamera; -class IMediaPlayerClient; +class IMediaRecorderClient; class IMediaRecorder: public IInterface { @@ -43,7 +43,7 @@ public: virtual status_t setVideoSize(int width, int height) = 0; virtual status_t setVideoFrameRate(int frames_per_second) = 0; virtual status_t setParameters(const String8& params) = 0; - virtual status_t setListener(const sp<IMediaPlayerClient>& listener) = 0; + virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0; virtual status_t prepare() = 0; virtual status_t getMaxAmplitude(int* max) = 0; virtual status_t start() = 0; diff --git a/include/media/IMediaRecorderClient.h b/include/media/IMediaRecorderClient.h new file mode 100644 index 0000000..0058ef2 --- /dev/null +++ b/include/media/IMediaRecorderClient.h @@ -0,0 +1,48 @@ +/* + * 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_IMEDIARECORDERCLIENT_H +#define ANDROID_IMEDIARECORDERCLIENT_H + +#include <utils/RefBase.h> +#include <binder/IInterface.h> +#include <binder/Parcel.h> + +namespace android { + +class IMediaRecorderClient: public IInterface +{ +public: + DECLARE_META_INTERFACE(MediaRecorderClient); + + virtual void notify(int msg, int ext1, int ext2) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnMediaRecorderClient: public BnInterface<IMediaRecorderClient> +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IMEDIARECORDERCLIENT_H + diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index 9e606d9..3662983 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -39,7 +39,6 @@ template<typename T> class SortedVector; enum player_type { PV_PLAYER = 1, SONIVOX_PLAYER = 2, - VORBIS_PLAYER = 3, STAGEFRIGHT_PLAYER = 4, // Test players are available only in the 'test' and 'eng' builds. // The shared library with the test player is passed passed as an diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h index a4eea2a..c3cd361 100644 --- a/include/media/MediaProfiles.h +++ b/include/media/MediaProfiles.h @@ -48,8 +48,8 @@ public: static MediaProfiles* getInstance(); /** - * Returns the value for the given param name at the given quality level, - * or -1 if error. + * Returns the value for the given param name for the given camera at + * the given quality level, or -1 if error. * * Supported param name are: * duration - the recording duration. @@ -64,7 +64,8 @@ public: * aud.hz - audio sample rate * aud.ch - number of audio channels */ - int getCamcorderProfileParamByName(const char *name, camcorder_quality quality) const; + int getCamcorderProfileParamByName(const char *name, int cameraId, + camcorder_quality quality) const; /** * Returns the output file formats supported. @@ -124,12 +125,7 @@ public: /** * Returns the number of image encoding quality levels supported. */ - Vector<int> getImageEncodingQualityLevels() const; - - /** - * Returns the maximum amount of memory in bytes we can use for decoding a JPEG file. - */ - int getImageDecodingMaxMemory() const; + Vector<int> getImageEncodingQualityLevels(int cameraId) const; private: MediaProfiles& operator=(const MediaProfiles&); // Don't call me @@ -171,7 +167,8 @@ private: struct CamcorderProfile { CamcorderProfile() - : mFileFormat(OUTPUT_FORMAT_THREE_GPP), + : mCameraId(0), + mFileFormat(OUTPUT_FORMAT_THREE_GPP), mQuality(CAMCORDER_QUALITY_HIGH), mDuration(0), mVideoCodec(0), @@ -182,6 +179,7 @@ private: delete mAudioCodec; } + int mCameraId; output_format mFileFormat; camcorder_quality mQuality; int mDuration; @@ -249,6 +247,11 @@ private: int tag; }; + struct ImageEncodingQualityLevels { + int mCameraId; + Vector<int> mLevels; + }; + // Debug static void logVideoCodec(const VideoCodec& codec); static void logAudioCodec(const AudioCodec& codec); @@ -267,9 +270,11 @@ private: static VideoDecoderCap* createVideoDecoderCap(const char **atts); static VideoEncoderCap* createVideoEncoderCap(const char **atts); static AudioEncoderCap* createAudioEncoderCap(const char **atts); - static CamcorderProfile* createCamcorderProfile(const char **atts); - static int getImageEncodingQualityLevel(const char **atts); - static int getImageDecodingMaxMemory(const char **atts); + static CamcorderProfile* createCamcorderProfile(int cameraId, const char **atts); + static int getCameraId(const char **atts); + + ImageEncodingQualityLevels* findImageEncodingQualityLevels(int cameraId) const; + void addImageEncodingQualityLevel(int cameraId, const char** atts); // Customized element tag handler for parsing the xml configuration file. static void startElementHandler(void *userData, const char *name, const char **atts); @@ -303,6 +308,7 @@ private: static bool sIsInitialized; static MediaProfiles *sInstance; static Mutex sLock; + int mCurrentCameraId; Vector<CamcorderProfile*> mCamcorderProfiles; Vector<AudioEncoderCap*> mAudioEncoders; @@ -310,8 +316,7 @@ private: Vector<AudioDecoderCap*> mAudioDecoders; Vector<VideoDecoderCap*> mVideoDecoders; Vector<output_format> mEncoderOutputFileFormats; - Vector<int> mImageEncodingQualityLevels; - int mImageDecodingMaxMemory; + Vector<ImageEncodingQualityLevels *> mImageEncodingQualityLevels; }; }; // namespace android diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h index 5b787a7..5e9e368 100644 --- a/include/media/MediaRecorderBase.h +++ b/include/media/MediaRecorderBase.h @@ -41,13 +41,14 @@ struct MediaRecorderBase { virtual status_t setOutputFile(const char *path) = 0; virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0; virtual status_t setParameters(const String8& params) = 0; - virtual status_t setListener(const sp<IMediaPlayerClient>& listener) = 0; + virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0; virtual status_t prepare() = 0; virtual status_t start() = 0; virtual status_t stop() = 0; virtual status_t close() = 0; virtual status_t reset() = 0; virtual status_t getMaxAmplitude(int *max) = 0; + virtual status_t dump(int fd, const Vector<String16>& args) const = 0; private: MediaRecorderBase(const MediaRecorderBase &); diff --git a/include/media/PVMediaRecorder.h b/include/media/PVMediaRecorder.h index 2a1298a..c091c39 100644 --- a/include/media/PVMediaRecorder.h +++ b/include/media/PVMediaRecorder.h @@ -18,7 +18,7 @@ #ifndef ANDROID_PVMEDIARECORDER_H #define ANDROID_PVMEDIARECORDER_H -#include <media/IMediaPlayerClient.h> +#include <media/IMediaRecorderClient.h> #include <media/MediaRecorderBase.h> namespace android { @@ -45,13 +45,14 @@ public: virtual status_t setOutputFile(const char *path); virtual status_t setOutputFile(int fd, int64_t offset, int64_t length); virtual status_t setParameters(const String8& params); - virtual status_t setListener(const sp<IMediaPlayerClient>& listener); + virtual status_t setListener(const sp<IMediaRecorderClient>& listener); virtual status_t prepare(); virtual status_t start(); virtual status_t stop(); virtual status_t close(); virtual status_t reset(); virtual status_t getMaxAmplitude(int *max); + virtual status_t dump(int fd, const Vector<String16>& args) const; private: status_t doStop(); diff --git a/include/media/Visualizer.h b/include/media/Visualizer.h new file mode 100644 index 0000000..5d51de8 --- /dev/null +++ b/include/media/Visualizer.h @@ -0,0 +1,160 @@ +/* + * 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_MEDIA_VISUALIZER_H +#define ANDROID_MEDIA_VISUALIZER_H + +#include <media/AudioEffect.h> +#include <media/EffectVisualizerApi.h> +#include <string.h> + +/** + * The Visualizer class enables application to retrieve part of the currently playing audio for + * visualization purpose. It is not an audio recording interface and only returns partial and low + * quality audio content. However, to protect privacy of certain audio data (e.g voice mail) the use + * of the visualizer requires the permission android.permission.RECORD_AUDIO. + * The audio session ID passed to the constructor indicates which audio content should be + * visualized: + * - If the session is 0, the audio output mix is visualized + * - If the session is not 0, the audio from a particular MediaPlayer or AudioTrack + * using this audio session is visualized + * Two types of representation of audio content can be captured: + * - Waveform data: consecutive 8-bit (unsigned) mono samples by using the getWaveForm() method + * - Frequency data: 8-bit magnitude FFT by using the getFft() method + * + * The length of the capture can be retrieved or specified by calling respectively + * getCaptureSize() and setCaptureSize() methods. Note that the size of the FFT + * is half of the specified capture size but both sides of the spectrum are returned yielding in a + * number of bytes equal to the capture size. The capture size must be a power of 2 in the range + * returned by getMinCaptureSize() and getMaxCaptureSize(). + * In addition to the polling capture mode, a callback mode is also available by installing a + * callback function by use of the setCaptureCallBack() method. The rate at which the callback + * is called as well as the type of data returned is specified. + * Before capturing data, the Visualizer must be enabled by calling the setEnabled() method. + * When data capture is not needed any more, the Visualizer should be disabled. + */ + + +namespace android { + +// ---------------------------------------------------------------------------- + +class Visualizer: public AudioEffect { +public: + + enum callback_flags { + CAPTURE_WAVEFORM = 0x00000001, // capture callback returns a PCM wave form + CAPTURE_FFT = 0x00000002, // apture callback returns a frequency representation + CAPTURE_CALL_JAVA = 0x00000004 // the callback thread can call java + }; + + + /* Constructor. + * See AudioEffect constructor for details on parameters. + */ + Visualizer(int32_t priority = 0, + effect_callback_t cbf = 0, + void* user = 0, + int sessionId = 0); + + ~Visualizer(); + + virtual status_t setEnabled(bool enabled); + + // maximum capture size in samples + static uint32_t getMaxCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MAX; } + // minimum capture size in samples + static uint32_t getMinCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MIN; } + // maximum capture rate in millihertz + static uint32_t getMaxCaptureRate() { return CAPTURE_RATE_MAX; } + + // callback used to return periodic PCM or FFT captures to the application. Either one or both + // types of data are returned (PCM and FFT) according to flags indicated when installing the + // callback. When a type of data is not present, the corresponding size (waveformSize or + // fftSize) is 0. + typedef void (*capture_cbk_t)(void* user, + uint32_t waveformSize, + uint8_t *waveform, + uint32_t fftSize, + uint8_t *fft, + uint32_t samplingrate); + + // install a callback to receive periodic captures. The capture rate is specified in milliHertz + // and the capture format is according to flags (see callback_flags). + status_t setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, uint32_t rate); + + // set the capture size capture size must be a power of two in the range + // [VISUALIZER_CAPTURE_SIZE_MAX. VISUALIZER_CAPTURE_SIZE_MIN] + // must be called when the visualizer is not enabled + status_t setCaptureSize(uint32_t size); + uint32_t getCaptureSize() { return mCaptureSize; } + + // returns the capture rate indicated when installing the callback + uint32_t getCaptureRate() { return mCaptureRate; } + + // returns the sampling rate of the audio being captured + uint32_t getSamplingRate() { return mSampleRate; } + + // return a capture in PCM 8 bit unsigned format. The size of the capture is equal to + // getCaptureSize() + status_t getWaveForm(uint8_t *waveform); + + // return a capture in FFT 8 bit signed format. The size of the capture is equal to + // getCaptureSize() but the length of the FFT is half of the size (both parts of the spectrum + // are returned + status_t getFft(uint8_t *fft); + +private: + + static const uint32_t CAPTURE_RATE_MAX = 20000; + static const uint32_t CAPTURE_RATE_DEF = 10000; + static const uint32_t CAPTURE_SIZE_DEF = VISUALIZER_CAPTURE_SIZE_MAX; + + /* internal class to handle the callback */ + class CaptureThread : public Thread + { + public: + CaptureThread(Visualizer& receiver, uint32_t captureRate, bool bCanCallJava = false); + + private: + friend class Visualizer; + virtual bool threadLoop(); + virtual status_t readyToRun(); + virtual void onFirstRef(); + Visualizer& mReceiver; + Mutex mLock; + uint32_t mSleepTimeUs; + }; + + status_t doFft(uint8_t *fft, uint8_t *waveform); + void periodicCapture(); + uint32_t initCaptureSize(); + + Mutex mLock; + uint32_t mCaptureRate; + uint32_t mCaptureSize; + uint32_t mSampleRate; + capture_cbk_t mCaptureCallBack; + void *mCaptureCbkUser; + sp<CaptureThread> mCaptureThread; + uint32_t mCaptureFlags; + void *mFftTable; +}; + + +}; // namespace android + +#endif // ANDROID_MEDIA_VISUALIZER_H diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h index 7fad1b7..207191d 100644 --- a/include/media/mediaplayer.h +++ b/include/media/mediaplayer.h @@ -93,6 +93,11 @@ enum media_info_type { // The video is too complex for the decoder: it can't decode frames fast // enough. Possibly only the audio plays fine at this stage. MEDIA_INFO_VIDEO_TRACK_LAGGING = 700, + // MediaPlayer is temporarily pausing playback internally in order to + // buffer more data. + MEDIA_INFO_BUFFERING_START = 701, + // MediaPlayer is resuming playback after filling buffers. + MEDIA_INFO_BUFFERING_END = 702, // 8xx // Bad interleaving means that a media has been improperly interleaved or not // interleaved at all, e.g has all the video samples first then all the audio @@ -161,12 +166,15 @@ public: void notify(int msg, int ext1, int ext2); static sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); static sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); - static int snoop(short *data, int len, int kind); status_t invoke(const Parcel& request, Parcel *reply); status_t setMetadataFilter(const Parcel& filter); status_t getMetadata(bool update_only, bool apply_filter, Parcel *metadata); status_t suspend(); status_t resume(); + status_t setAudioSessionId(int sessionId); + int getAudioSessionId(); + status_t setAuxEffectSendLevel(float level); + status_t attachAuxEffect(int effectId); private: void clear_l(); status_t seekTo_l(int msec); @@ -193,6 +201,8 @@ private: float mRightVolume; int mVideoWidth; int mVideoHeight; + int mAudioSessionId; + float mSendLevel; }; }; // namespace android diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h index 9ea6c7b..291b18a 100644 --- a/include/media/mediarecorder.h +++ b/include/media/mediarecorder.h @@ -22,7 +22,7 @@ #include <utils/threads.h> #include <utils/List.h> #include <utils/Errors.h> -#include <media/IMediaPlayerClient.h> +#include <media/IMediaRecorderClient.h> #include <media/IMediaDeathNotifier.h> namespace android { @@ -73,6 +73,9 @@ enum output_format { OUTPUT_FORMAT_AAC_ADIF = 5, OUTPUT_FORMAT_AAC_ADTS = 6, + /* Stream over a socket, limited to a single stream */ + OUTPUT_FORMAT_RTP_AVP = 7, + OUTPUT_FORMAT_LIST_END // must be last - used to validate format type }; @@ -135,7 +138,10 @@ enum media_recorder_error_type { enum media_recorder_info_type { MEDIA_RECORDER_INFO_UNKNOWN = 1, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800, - MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801 + MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801, + MEDIA_RECORDER_INFO_COMPLETION_STATUS = 802, + MEDIA_RECORDER_INFO_PROGRESS_FRAME_STATUS = 803, + MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS = 804, }; // ---------------------------------------------------------------------------- @@ -146,7 +152,7 @@ public: virtual void notify(int msg, int ext1, int ext2) = 0; }; -class MediaRecorder : public BnMediaPlayerClient, +class MediaRecorder : public BnMediaRecorderClient, public virtual IMediaDeathNotifier { public: diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h index 372909a..813dd43 100644 --- a/include/media/stagefright/AMRWriter.h +++ b/include/media/stagefright/AMRWriter.h @@ -26,6 +26,7 @@ namespace android { struct MediaSource; +struct MetaData; struct AMRWriter : public MediaWriter { AMRWriter(const char *filename); @@ -35,25 +36,30 @@ struct AMRWriter : public MediaWriter { virtual status_t addSource(const sp<MediaSource> &source); virtual bool reachedEOS(); - virtual status_t start(); + virtual status_t start(MetaData *params = NULL); virtual void stop(); + virtual void pause(); protected: virtual ~AMRWriter(); private: - Mutex mLock; - FILE *mFile; status_t mInitCheck; sp<MediaSource> mSource; bool mStarted; + volatile bool mPaused; + volatile bool mResumed; volatile bool mDone; - bool mReachedEOS; + volatile bool mReachedEOS; pthread_t mThread; + int64_t mEstimatedSizeBytes; + int64_t mEstimatedDurationUs; static void *ThreadWrapper(void *); void threadFunc(); + bool exceedsFileSizeLimit(); + bool exceedsFileDurationLimit(); AMRWriter(const AMRWriter &); AMRWriter &operator=(const AMRWriter &); diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h index eb00140..2597e9e 100644 --- a/include/media/stagefright/AudioSource.h +++ b/include/media/stagefright/AudioSource.h @@ -39,6 +39,9 @@ struct AudioSource : public MediaSource { virtual status_t stop(); virtual sp<MetaData> getFormat(); + // Returns the maximum amplitude since last call. + int16_t getMaxAmplitude(); + virtual status_t read( MediaBuffer **buffer, const ReadOptions *options = NULL); @@ -46,13 +49,24 @@ protected: virtual ~AudioSource(); private: - enum { kMaxBufferSize = 8192 }; + enum { kMaxBufferSize = 2048 }; AudioRecord *mRecord; status_t mInitCheck; bool mStarted; + + bool mCollectStats; + bool mTrackMaxAmplitude; + int64_t mStartTimeUs; + int16_t mMaxAmplitude; + int64_t mPrevSampleTimeUs; + int64_t mTotalLostFrames; + int64_t mPrevLostBytes; + MediaBufferGroup *mGroup; + void trackMaxAmplitude(int16_t *data, int nSamples); + AudioSource(const AudioSource &); AudioSource &operator=(const AudioSource &); }; diff --git a/include/media/stagefright/CachingDataSource.h b/include/media/stagefright/CachingDataSource.h deleted file mode 100644 index 42d50e5..0000000 --- a/include/media/stagefright/CachingDataSource.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 CACHING_DATASOURCE_H_ - -#define CACHING_DATASOURCE_H_ - -#include <media/stagefright/DataSource.h> -#include <media/stagefright/MediaErrors.h> -#include <utils/threads.h> - -namespace android { - -class CachingDataSource : public DataSource { -public: - CachingDataSource( - const sp<DataSource> &source, size_t pageSize, int numPages); - - virtual status_t initCheck() const; - - virtual ssize_t readAt(off_t offset, void *data, size_t size); - - virtual status_t getSize(off_t *size); - - virtual uint32_t flags(); - -protected: - virtual ~CachingDataSource(); - -private: - struct Page { - Page *mPrev, *mNext; - off_t mOffset; - size_t mLength; - void *mData; - }; - - sp<DataSource> mSource; - void *mData; - size_t mPageSize; - Page *mFirst, *mLast; - - Page *allocate_page(); - - Mutex mLock; - - CachingDataSource(const CachingDataSource &); - CachingDataSource &operator=(const CachingDataSource &); -}; - -} // namespace android - -#endif // CACHING_DATASOURCE_H_ diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h index ea435de..3192d03 100644 --- a/include/media/stagefright/CameraSource.h +++ b/include/media/stagefright/CameraSource.h @@ -28,18 +28,15 @@ namespace android { class ICamera; class IMemory; -class ISurface; class Camera; -class CameraSource : public MediaSource { +class CameraSource : public MediaSource, public MediaBufferObserver { public: static CameraSource *Create(); - static CameraSource *CreateFromICamera(const sp<ICamera> &icamera); + static CameraSource *CreateFromCamera(const sp<Camera> &camera); virtual ~CameraSource(); - void setPreviewSurface(const sp<ISurface> &surface); - virtual status_t start(MetaData *params = NULL); virtual status_t stop(); @@ -48,25 +45,39 @@ public: virtual status_t read( MediaBuffer **buffer, const ReadOptions *options = NULL); + virtual void signalBufferReturned(MediaBuffer* buffer); + private: friend class CameraSourceListener; sp<Camera> mCamera; - sp<ISurface> mPreviewSurface; + sp<MetaData> mMeta; Mutex mLock; Condition mFrameAvailableCondition; - List<sp<IMemory> > mFrames; + Condition mFrameCompleteCondition; + List<sp<IMemory> > mFramesReceived; + List<sp<IMemory> > mFramesBeingEncoded; List<int64_t> mFrameTimes; - int mWidth, mHeight; + int64_t mStartTimeUs; int64_t mFirstFrameTimeUs; - int32_t mNumFrames; + int64_t mLastFrameTimestampUs; + int32_t mNumFramesReceived; + int32_t mNumFramesEncoded; + int32_t mNumFramesDropped; + int32_t mNumGlitches; + int64_t mGlitchDurationThresholdUs; + bool mCollectStats; bool mStarted; CameraSource(const sp<Camera> &camera); - void dataCallback(int32_t msgType, const sp<IMemory> &data); + void dataCallbackTimestamp( + int64_t timestampUs, int32_t msgType, const sp<IMemory> &data); + + void releaseQueuedFrames(); + void releaseOneRecordingFrame(const sp<IMemory>& frame); CameraSource(const CameraSource &); CameraSource &operator=(const CameraSource &); diff --git a/include/media/stagefright/ColorConverter.h b/include/media/stagefright/ColorConverter.h index 1e341b9..bc3f464 100644 --- a/include/media/stagefright/ColorConverter.h +++ b/include/media/stagefright/ColorConverter.h @@ -58,6 +58,11 @@ private: const void *srcBits, size_t srcSkip, void *dstBits, size_t dstSkip); + void convertYUV420SemiPlanar( + size_t width, size_t height, + const void *srcBits, size_t srcSkip, + void *dstBits, size_t dstSkip); + ColorConverter(const ColorConverter &); ColorConverter &operator=(const ColorConverter &); }; diff --git a/include/media/stagefright/HTTPDataSource.h b/include/media/stagefright/HTTPDataSource.h deleted file mode 100644 index 0400bea..0000000 --- a/include/media/stagefright/HTTPDataSource.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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 HTTP_DATASOURCE_H_ - -#define HTTP_DATASOURCE_H_ - -#include <media/stagefright/DataSource.h> -#include <utils/String8.h> -#include <utils/threads.h> - -namespace android { - -class HTTPStream; - -class HTTPDataSource : public DataSource { -public: - HTTPDataSource( - const char *host, int port, const char *path, - const KeyedVector<String8, String8> *headers = NULL); - - HTTPDataSource( - const char *uri, - const KeyedVector<String8, String8> *headers = NULL); - - status_t connect(); - void disconnect(); - - virtual status_t initCheck() const; - - virtual ssize_t readAt(off_t offset, void *data, size_t size); - - virtual status_t getSize(off_t *size); - - virtual uint32_t flags(); - -protected: - virtual ~HTTPDataSource(); - -private: - enum { - kBufferSize = 64 * 1024, - - // If we encounter a socket-read error we'll try reconnecting - // and restarting the read for at most this many times. - kMaxNumRetries = 3, - }; - - enum State { - DISCONNECTED, - CONNECTING, - CONNECTED - }; - - State mState; - mutable Mutex mStateLock; - - String8 mHeaders; - - String8 mStartingHost; - String8 mStartingPath; - int mStartingPort; - - HTTPStream *mHttp; - - void *mBuffer; - size_t mBufferLength; - off_t mBufferOffset; - - bool mContentLengthValid; - unsigned long long mContentLength; - - int32_t mNumRetriesLeft; - - void init(const KeyedVector<String8, String8> *headers); - - ssize_t sendRangeRequest(size_t offset); - void initHeaders(const KeyedVector<String8, String8> *overrides); - - status_t connectWithRedirectsAndRange(off_t rangeStart); - void applyTimeoutResponse(); - - HTTPDataSource(const HTTPDataSource &); - HTTPDataSource &operator=(const HTTPDataSource &); -}; - -} // namespace android - -#endif // HTTP_DATASOURCE_H_ - diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h index 6b93f19..be96935 100644 --- a/include/media/stagefright/MPEG4Writer.h +++ b/include/media/stagefright/MPEG4Writer.h @@ -36,9 +36,10 @@ public: MPEG4Writer(int fd); virtual status_t addSource(const sp<MediaSource> &source); - virtual status_t start(); + virtual status_t start(MetaData *param = NULL); virtual bool reachedEOS(); virtual void stop(); + virtual void pause(); void beginBox(const char *fourcc); void writeInt8(int8_t x); @@ -49,6 +50,9 @@ public: void writeFourcc(const char *fourcc); void write(const void *data, size_t size); void endBox(); + uint32_t interleaveDuration() const { return mInterleaveDurationUs; } + status_t setInterleaveDuration(uint32_t duration); + int32_t getTimeScale() const { return mTimeScale; } protected: virtual ~MPEG4Writer(); @@ -57,16 +61,90 @@ private: class Track; FILE *mFile; + bool mUse32BitOffset; + bool mPaused; + bool mStarted; off_t mOffset; off_t mMdatOffset; + uint8_t *mMoovBoxBuffer; + off_t mMoovBoxBufferOffset; + bool mWriteMoovBoxToMemory; + off_t mFreeBoxOffset; + bool mStreamableFile; + off_t mEstimatedMoovBoxSize; + uint32_t mInterleaveDurationUs; + int32_t mTimeScale; + int64_t mStartTimestampUs; + Mutex mLock; List<Track *> mTracks; List<off_t> mBoxes; - off_t addSample(MediaBuffer *buffer); - off_t addLengthPrefixedSample(MediaBuffer *buffer); + void setStartTimestampUs(int64_t timeUs); + int64_t getStartTimestampUs(); // Not const + status_t startTracks(MetaData *params); + size_t numTracks(); + int64_t estimateMoovBoxSize(int32_t bitRate); + + struct Chunk { + Track *mTrack; // Owner + int64_t mTimeStampUs; // Timestamp of the 1st sample + List<MediaBuffer *> mSamples; // Sample data + + // Convenient constructor + Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples) + : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) { + } + + }; + struct ChunkInfo { + Track *mTrack; // Owner + List<Chunk> mChunks; // Remaining chunks to be written + }; + + bool mIsFirstChunk; + volatile bool mDone; // Writer thread is done? + pthread_t mThread; // Thread id for the writer + List<ChunkInfo> mChunkInfos; // Chunk infos + Condition mChunkReadyCondition; // Signal that chunks are available + + // Writer thread handling + status_t startWriterThread(); + void stopWriterThread(); + static void *ThreadWrapper(void *me); + void threadFunc(); + + // Buffer a single chunk to be written out later. + void bufferChunk(const Chunk& chunk); + + // Write all buffered chunks from all tracks + void writeChunks(); + + // Write a chunk if there is one + status_t writeOneChunk(); + + // Write the first chunk from the given ChunkInfo. + void writeFirstChunk(ChunkInfo* info); + + // Adjust other track media clock (presumably wall clock) + // based on audio track media clock with the drift time. + int64_t mDriftTimeUs; + void addDriftTimeUs(int64_t driftTimeUs); + int64_t getDriftTimeUs(); + + void lock(); + void unlock(); + + // Acquire lock before calling these methods + off_t addSample_l(MediaBuffer *buffer); + off_t addLengthPrefixedSample_l(MediaBuffer *buffer); + + inline size_t write(const void *ptr, size_t size, size_t nmemb, FILE* stream); + bool exceedsFileSizeLimit(); + bool exceedsFileDurationLimit(); + void trackProgressStatus(const Track* track, int64_t timeUs, status_t err = OK); MPEG4Writer(const MPEG4Writer &); MPEG4Writer &operator=(const MPEG4Writer &); diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h index 207195a..92ce068 100644 --- a/include/media/stagefright/MediaDefs.h +++ b/include/media/stagefright/MediaDefs.h @@ -22,6 +22,7 @@ namespace android { extern const char *MEDIA_MIMETYPE_IMAGE_JPEG; +extern const char *MEDIA_MIMETYPE_VIDEO_VPX; extern const char *MEDIA_MIMETYPE_VIDEO_AVC; extern const char *MEDIA_MIMETYPE_VIDEO_MPEG4; extern const char *MEDIA_MIMETYPE_VIDEO_H263; @@ -33,11 +34,15 @@ extern const char *MEDIA_MIMETYPE_AUDIO_MPEG; extern const char *MEDIA_MIMETYPE_AUDIO_AAC; extern const char *MEDIA_MIMETYPE_AUDIO_QCELP; extern const char *MEDIA_MIMETYPE_AUDIO_VORBIS; +extern const char *MEDIA_MIMETYPE_AUDIO_G711_ALAW; +extern const char *MEDIA_MIMETYPE_AUDIO_G711_MLAW; extern const char *MEDIA_MIMETYPE_AUDIO_RAW; extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4; extern const char *MEDIA_MIMETYPE_CONTAINER_WAV; extern const char *MEDIA_MIMETYPE_CONTAINER_OGG; +extern const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA; +extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG2TS; } // namespace android diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h index 96d57e7..dafc621 100644 --- a/include/media/stagefright/MediaSource.h +++ b/include/media/stagefright/MediaSource.h @@ -20,6 +20,7 @@ #include <sys/types.h> +#include <media/stagefright/MediaErrors.h> #include <utils/RefBase.h> namespace android { @@ -61,28 +62,56 @@ struct MediaSource : public RefBase { // a) not request a seek // b) not be late, i.e. lateness_us = 0 struct ReadOptions { + enum SeekMode { + SEEK_PREVIOUS_SYNC, + SEEK_NEXT_SYNC, + SEEK_CLOSEST_SYNC, + SEEK_CLOSEST, + }; + ReadOptions(); // Reset everything back to defaults. void reset(); - void setSeekTo(int64_t time_us); + void setSeekTo(int64_t time_us, SeekMode mode = SEEK_CLOSEST_SYNC); void clearSeekTo(); - bool getSeekTo(int64_t *time_us) const; + bool getSeekTo(int64_t *time_us, SeekMode *mode) const; + + // Option allows encoder to skip some frames until the specified + // time stamp. + // To prevent from being abused, when the skipFrame timestamp is + // found to be more than 1 second later than the current timestamp, + // an error will be returned from read(). + void clearSkipFrame(); + bool getSkipFrame(int64_t *timeUs) const; + void setSkipFrame(int64_t timeUs); void setLateBy(int64_t lateness_us); int64_t getLateBy() const; private: enum Options { + // Bit map kSeekTo_Option = 1, + kSkipFrame_Option = 2, }; uint32_t mOptions; int64_t mSeekTimeUs; + SeekMode mSeekMode; int64_t mLatenessUs; + + int64_t mSkipFrameUntilTimeUs; }; + // Causes this source to suspend pulling data from its upstream source + // until a subsequent read-with-seek. Currently only supported by + // OMXCodec. + virtual status_t pause() { + return ERROR_UNSUPPORTED; + } + protected: virtual ~MediaSource(); diff --git a/include/media/stagefright/MediaWriter.h b/include/media/stagefright/MediaWriter.h index b8232c6..8d3a9df 100644 --- a/include/media/stagefright/MediaWriter.h +++ b/include/media/stagefright/MediaWriter.h @@ -19,22 +19,41 @@ #define MEDIA_WRITER_H_ #include <utils/RefBase.h> +#include <media/IMediaRecorderClient.h> namespace android { struct MediaSource; +struct MetaData; struct MediaWriter : public RefBase { - MediaWriter() {} + MediaWriter() + : mMaxFileSizeLimitBytes(0), + mMaxFileDurationLimitUs(0) { + } virtual status_t addSource(const sp<MediaSource> &source) = 0; virtual bool reachedEOS() = 0; - virtual status_t start() = 0; + virtual status_t start(MetaData *params = NULL) = 0; virtual void stop() = 0; + virtual void pause() = 0; + virtual void setMaxFileSize(int64_t bytes) { mMaxFileSizeLimitBytes = bytes; } + virtual void setMaxFileDuration(int64_t durationUs) { mMaxFileDurationLimitUs = durationUs; } + virtual void setListener(const sp<IMediaRecorderClient>& listener) { + mListener = listener; + } protected: virtual ~MediaWriter() {} + int64_t mMaxFileSizeLimitBytes; + int64_t mMaxFileDurationLimitUs; + sp<IMediaRecorderClient> mListener; + void notify(int msg, int ext1, int ext2) { + if (mListener != NULL) { + mListener->notify(msg, ext1, ext2); + } + } private: MediaWriter(const MediaWriter &); MediaWriter &operator=(const MediaWriter &); diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h index dc2bd50..43354c2 100644 --- a/include/media/stagefright/MetaData.h +++ b/include/media/stagefright/MetaData.h @@ -30,10 +30,13 @@ namespace android { // The following keys map to int32_t data unless indicated otherwise. enum { kKeyMIMEType = 'mime', // cstring - kKeyWidth = 'widt', - kKeyHeight = 'heig', - kKeyChannelCount = '#chn', - kKeySampleRate = 'srte', + kKeyWidth = 'widt', // int32_t + kKeyHeight = 'heig', // int32_t + kKeyIFramesInterval = 'ifiv', // int32_t + kKeyStride = 'strd', // int32_t + kKeySliceHeight = 'slht', // int32_t + kKeyChannelCount = '#chn', // int32_t + kKeySampleRate = 'srte', // int32_t (also video frame rate) kKeyBitRate = 'brte', // int32_t (bps) kKeyESDS = 'esds', // raw data kKeyAVCC = 'avcc', // raw data @@ -43,6 +46,8 @@ enum { kKeyIsSyncFrame = 'sync', // int32_t (bool) kKeyIsCodecConfig = 'conf', // int32_t (bool) kKeyTime = 'time', // int64_t (usecs) + kKeyNTPTime = 'ntpT', // uint64_t (ntp-timestamp) + kKeyTargetTime = 'tarT', // int64_t (usecs) kKeyDuration = 'dura', // int64_t (usecs) kKeyColorFormat = 'colf', kKeyPlatformPrivate = 'priv', // pointer @@ -65,6 +70,26 @@ enum { kKeyDiscNumber = 'dnum', // cstring kKeyDate = 'date', // cstring kKeyWriter = 'writ', // cstring + kKeyTimeScale = 'tmsl', // int32_t + + // video profile and level + kKeyVideoProfile = 'vprf', // int32_t + kKeyVideoLevel = 'vlev', // int32_t + + // Set this key to enable authoring files in 64-bit offset + kKey64BitFileOffset = 'fobt', // int32_t (bool) + + // Identify the file output format for authoring + // Please see <media/mediarecorder.h> for the supported + // file output formats. + kKeyFileType = 'ftyp', // int32_t + + // Track authoring progress status + // kKeyTrackTimeStatus is used to track progress in elapsed time + kKeyTrackTimeStatus = 'tktm', // int64_t + + kKeyNotRealTime = 'ntrt', // bool (int32_t) + }; enum { diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h index 1d76a1a..010ded1 100644 --- a/include/media/stagefright/OMXCodec.h +++ b/include/media/stagefright/OMXCodec.h @@ -27,6 +27,7 @@ namespace android { class MemoryDealer; struct OMXCodecObserver; +struct CodecProfileLevel; struct OMXCodec : public MediaSource, public MediaBufferObserver { @@ -52,6 +53,8 @@ struct OMXCodec : public MediaSource, virtual status_t read( MediaBuffer **buffer, const ReadOptions *options = NULL); + virtual status_t pause(); + void on_message(const omx_message &msg); // from MediaBufferObserver @@ -98,6 +101,7 @@ private: kDecoderLiesAboutNumberOfChannels = 256, kInputBufferSizesAreBogus = 512, kSupportsMultipleFramesPerInputBuffer = 1024, + kAvoidMemcopyInputRecordingFrames = 2048, }; struct BufferInfo { @@ -137,12 +141,17 @@ private: bool mNoMoreOutputData; bool mOutputPortSettingsHaveChanged; int64_t mSeekTimeUs; + ReadOptions::SeekMode mSeekMode; + int64_t mTargetTimeUs; + int64_t mSkipTimeUs; MediaBuffer *mLeftOverBuffer; Mutex mLock; Condition mAsyncCompletion; + bool mPaused; + // A list of indices into mPortStatus[kPortIndexOutput] filled with data. List<size_t> mFilledBuffers; Condition mBufferFilled; @@ -156,8 +165,8 @@ private: void setComponentRole(); - void setAMRFormat(bool isWAMR); - void setAACFormat(int32_t numChannels, int32_t sampleRate); + void setAMRFormat(bool isWAMR, int32_t bitRate); + void setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate); status_t setVideoPortFormatType( OMX_U32 portIndex, @@ -165,10 +174,24 @@ private: OMX_COLOR_FORMATTYPE colorFormat); void setVideoInputFormat( - const char *mime, OMX_U32 width, OMX_U32 height); - - status_t setupMPEG4EncoderParameters(); - status_t setupAVCEncoderParameters(); + const char *mime, const sp<MetaData>& meta); + + status_t setupBitRate(int32_t bitRate); + status_t setupErrorCorrectionParameters(); + status_t setupH263EncoderParameters(const sp<MetaData>& meta); + status_t setupMPEG4EncoderParameters(const sp<MetaData>& meta); + status_t setupAVCEncoderParameters(const sp<MetaData>& meta); + status_t findTargetColorFormat( + const sp<MetaData>& meta, OMX_COLOR_FORMATTYPE *colorFormat); + + status_t isColorFormatSupported( + OMX_COLOR_FORMATTYPE colorFormat, int portIndex); + + // If profile/level is set in the meta data, its value in the meta + // data will be used; otherwise, the default value will be used. + status_t getVideoProfileLevel(const sp<MetaData>& meta, + const CodecProfileLevel& defaultProfileLevel, + CodecProfileLevel& profileLevel); status_t setVideoOutputFormat( const char *mime, OMX_U32 width, OMX_U32 height); diff --git a/include/media/stagefright/foundation/AAtomizer.h b/include/media/stagefright/foundation/AAtomizer.h new file mode 100644 index 0000000..5f3a678 --- /dev/null +++ b/include/media/stagefright/foundation/AAtomizer.h @@ -0,0 +1,51 @@ +/* + * 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 A_ATOMIZER_H_ + +#define A_ATOMIZER_H_ + +#include <stdint.h> + +#include <media/stagefright/foundation/ABase.h> +#include <media/stagefright/foundation/AString.h> +#include <utils/List.h> +#include <utils/Vector.h> +#include <utils/threads.h> + +namespace android { + +struct AAtomizer { + static const char *Atomize(const char *name); + +private: + static AAtomizer gAtomizer; + + Mutex mLock; + Vector<List<AString> > mAtoms; + + AAtomizer(); + + const char *atomize(const char *name); + + static uint32_t Hash(const char *s); + + DISALLOW_EVIL_CONSTRUCTORS(AAtomizer); +}; + +} // namespace android + +#endif // A_ATOMIZER_H_ diff --git a/include/media/stagefright/foundation/ABase.h b/include/media/stagefright/foundation/ABase.h new file mode 100644 index 0000000..9eceea3 --- /dev/null +++ b/include/media/stagefright/foundation/ABase.h @@ -0,0 +1,25 @@ +/* + * 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 A_BASE_H_ + +#define A_BASE_H_ + +#define DISALLOW_EVIL_CONSTRUCTORS(name) \ + name(const name &); \ + name &operator=(const name &) + +#endif // A_BASE_H_ diff --git a/include/media/stagefright/foundation/ABuffer.h b/include/media/stagefright/foundation/ABuffer.h new file mode 100644 index 0000000..28f0aed --- /dev/null +++ b/include/media/stagefright/foundation/ABuffer.h @@ -0,0 +1,71 @@ +/* + * 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 A_BUFFER_H_ + +#define A_BUFFER_H_ + +#include <sys/types.h> +#include <stdint.h> + +#include <media/stagefright/foundation/ABase.h> +#include <utils/RefBase.h> + +namespace android { + +struct AMessage; + +struct ABuffer : public RefBase { + ABuffer(size_t capacity); + ABuffer(void *data, size_t capacity); + + void setFarewellMessage(const sp<AMessage> msg); + + uint8_t *base() { return (uint8_t *)mData; } + uint8_t *data() { return (uint8_t *)mData + mRangeOffset; } + size_t capacity() const { return mCapacity; } + size_t size() const { return mRangeLength; } + size_t offset() const { return mRangeOffset; } + + void setRange(size_t offset, size_t size); + + void setInt32Data(int32_t data) { mInt32Data = data; } + int32_t int32Data() const { return mInt32Data; } + + sp<AMessage> meta(); + +protected: + virtual ~ABuffer(); + +private: + sp<AMessage> mFarewell; + sp<AMessage> mMeta; + + void *mData; + size_t mCapacity; + size_t mRangeOffset; + size_t mRangeLength; + + int32_t mInt32Data; + + bool mOwnsData; + + DISALLOW_EVIL_CONSTRUCTORS(ABuffer); +}; + +} // namespace android + +#endif // A_BUFFER_H_ diff --git a/include/media/stagefright/foundation/ADebug.h b/include/media/stagefright/foundation/ADebug.h new file mode 100644 index 0000000..0f986a0 --- /dev/null +++ b/include/media/stagefright/foundation/ADebug.h @@ -0,0 +1,105 @@ +/* + * 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 A_DEBUG_H_ + +#define A_DEBUG_H_ + +#include <string.h> + +#include <media/stagefright/foundation/ABase.h> +#include <media/stagefright/foundation/AString.h> + +namespace android { + +enum LogType { + VERBOSE, + INFO, + WARNING, + ERROR, + FATAL, +}; + +struct Logger { + Logger(LogType type); + virtual ~Logger(); + + template<class T> Logger &operator<<(const T &x) { + mMessage.append(x); + + return *this; + } + +private: + android::AString mMessage; + LogType mLogType; + + DISALLOW_EVIL_CONSTRUCTORS(Logger); +}; + +const char *LeafName(const char *s); + +#undef LOG +#define LOG(type) Logger(type) << LeafName(__FILE__) << ":" << __LINE__ << " " + +#define CHECK(condition) \ + do { \ + if (!(condition)) { \ + LOG(FATAL) << "CHECK(" #condition ") failed."; \ + } \ + } while (false) + +#define MAKE_COMPARATOR(suffix,op) \ + template<class A, class B> \ + AString Compare_##suffix(const A &a, const B &b) { \ + AString res; \ + if (!(a op b)) { \ + res.append(a); \ + res.append(" vs. "); \ + res.append(b); \ + } \ + return res; \ + } + +MAKE_COMPARATOR(EQ,==) +MAKE_COMPARATOR(NE,!=) +MAKE_COMPARATOR(LE,<=) +MAKE_COMPARATOR(GE,>=) +MAKE_COMPARATOR(LT,<) +MAKE_COMPARATOR(GT,>) + +#define CHECK_OP(x,y,suffix,op) \ + do { \ + AString ___res = Compare_##suffix(x, y); \ + if (!___res.empty()) { \ + LOG(FATAL) << "CHECK_" #suffix "(" #x "," #y ") failed: " \ + << ___res; \ + } \ + } while (false) + +#define CHECK_EQ(x,y) CHECK_OP(x,y,EQ,==) +#define CHECK_NE(x,y) CHECK_OP(x,y,NE,!=) +#define CHECK_LE(x,y) CHECK_OP(x,y,LE,<=) +#define CHECK_LT(x,y) CHECK_OP(x,y,LT,<) +#define CHECK_GE(x,y) CHECK_OP(x,y,GE,>=) +#define CHECK_GT(x,y) CHECK_OP(x,y,GT,>) + +#define TRESPASS() LOG(FATAL) << "Should not be here." + +} // namespace android + +#endif // A_DEBUG_H_ + diff --git a/include/media/stagefright/foundation/AHandler.h b/include/media/stagefright/foundation/AHandler.h new file mode 100644 index 0000000..b008b54 --- /dev/null +++ b/include/media/stagefright/foundation/AHandler.h @@ -0,0 +1,56 @@ +/* + * 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 A_HANDLER_H_ + +#define A_HANDLER_H_ + +#include <media/stagefright/foundation/ALooper.h> +#include <utils/RefBase.h> + +namespace android { + +struct AMessage; + +struct AHandler : public RefBase { + AHandler() + : mID(0) { + } + + ALooper::handler_id id() const { + return mID; + } + + sp<ALooper> looper(); + +protected: + virtual void onMessageReceived(const sp<AMessage> &msg) = 0; + +private: + friend struct ALooperRoster; + + ALooper::handler_id mID; + + void setID(ALooper::handler_id id) { + mID = id; + } + + DISALLOW_EVIL_CONSTRUCTORS(AHandler); +}; + +} // namespace android + +#endif // A_HANDLER_H_ diff --git a/include/media/stagefright/foundation/AHandlerReflector.h b/include/media/stagefright/foundation/AHandlerReflector.h new file mode 100644 index 0000000..857866a --- /dev/null +++ b/include/media/stagefright/foundation/AHandlerReflector.h @@ -0,0 +1,32 @@ +#ifndef A_HANDLER_REFLECTOR_H_ + +#define A_HANDLER_REFLECTOR_H_ + +#include <media/stagefright/foundation/AHandler.h> + +namespace android { + +template<class T> +struct AHandlerReflector : public AHandler { + AHandlerReflector(T *target) + : mTarget(target) { + } + +protected: + virtual void onMessageReceived(const sp<AMessage> &msg) { + sp<T> target = mTarget.promote(); + if (target != NULL) { + target->onMessageReceived(msg); + } + } + +private: + wp<T> mTarget; + + AHandlerReflector(const AHandlerReflector<T> &); + AHandlerReflector<T> &operator=(const AHandlerReflector<T> &); +}; + +} // namespace android + +#endif // A_HANDLER_REFLECTOR_H_ diff --git a/include/media/stagefright/foundation/ALooper.h b/include/media/stagefright/foundation/ALooper.h new file mode 100644 index 0000000..153ead9 --- /dev/null +++ b/include/media/stagefright/foundation/ALooper.h @@ -0,0 +1,80 @@ +/* + * 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 A_LOOPER_H_ + +#define A_LOOPER_H_ + +#include <media/stagefright/foundation/ABase.h> +#include <utils/Errors.h> +#include <utils/KeyedVector.h> +#include <utils/List.h> +#include <utils/RefBase.h> +#include <utils/threads.h> + +namespace android { + +struct AHandler; +struct AMessage; + +struct ALooper : public RefBase { + typedef int32_t event_id; + typedef int32_t handler_id; + + ALooper(); + + handler_id registerHandler(const sp<AHandler> &handler); + void unregisterHandler(handler_id handlerID); + + status_t start( + bool runOnCallingThread = false, + bool canCallJava = false, + int32_t priority = PRIORITY_DEFAULT + ); + + status_t stop(); + + static int64_t GetNowUs(); + +protected: + virtual ~ALooper(); + +private: + friend struct ALooperRoster; + + struct Event { + int64_t mWhenUs; + sp<AMessage> mMessage; + }; + + Mutex mLock; + Condition mQueueChangedCondition; + + List<Event> mEventQueue; + + struct LooperThread; + sp<LooperThread> mThread; + bool mRunningLocally; + + void post(const sp<AMessage> &msg, int64_t delayUs); + bool loop(); + + DISALLOW_EVIL_CONSTRUCTORS(ALooper); +}; + +} // namespace android + +#endif // A_LOOPER_H_ diff --git a/include/media/stagefright/foundation/ALooperRoster.h b/include/media/stagefright/foundation/ALooperRoster.h new file mode 100644 index 0000000..c1bd4ed --- /dev/null +++ b/include/media/stagefright/foundation/ALooperRoster.h @@ -0,0 +1,54 @@ +/* + * 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 A_LOOPER_ROSTER_H_ + +#define A_LOOPER_ROSTER_H_ + +#include <media/stagefright/foundation/ALooper.h> +#include <utils/KeyedVector.h> + +namespace android { + +struct ALooperRoster { + ALooperRoster(); + + ALooper::handler_id registerHandler( + const sp<ALooper> looper, const sp<AHandler> &handler); + + void unregisterHandler(ALooper::handler_id handlerID); + + void postMessage(const sp<AMessage> &msg, int64_t delayUs = 0); + void deliverMessage(const sp<AMessage> &msg); + + sp<ALooper> findLooper(ALooper::handler_id handlerID); + +private: + struct HandlerInfo { + wp<ALooper> mLooper; + wp<AHandler> mHandler; + }; + + Mutex mLock; + KeyedVector<ALooper::handler_id, HandlerInfo> mHandlers; + ALooper::handler_id mNextHandlerID; + + DISALLOW_EVIL_CONSTRUCTORS(ALooperRoster); +}; + +} // namespace android + +#endif // A_LOOPER_ROSTER_H_ diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h new file mode 100644 index 0000000..c674cba --- /dev/null +++ b/include/media/stagefright/foundation/AMessage.h @@ -0,0 +1,115 @@ +/* + * 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 A_MESSAGE_H_ + +#define A_MESSAGE_H_ + +#include <media/stagefright/foundation/ABase.h> +#include <media/stagefright/foundation/ALooper.h> +#include <utils/KeyedVector.h> +#include <utils/RefBase.h> + +namespace android { + +struct AString; + +struct AMessage : public RefBase { + AMessage(uint32_t what = 0, ALooper::handler_id target = 0); + + void setWhat(uint32_t what); + uint32_t what() const; + + void setTarget(ALooper::handler_id target); + ALooper::handler_id target() const; + + void setInt32(const char *name, int32_t value); + void setInt64(const char *name, int64_t value); + void setSize(const char *name, size_t value); + void setFloat(const char *name, float value); + void setDouble(const char *name, double value); + void setPointer(const char *name, void *value); + void setString(const char *name, const char *s, ssize_t len = -1); + void setObject(const char *name, const sp<RefBase> &obj); + void setMessage(const char *name, const sp<AMessage> &obj); + + bool findInt32(const char *name, int32_t *value) const; + bool findInt64(const char *name, int64_t *value) const; + bool findSize(const char *name, size_t *value) const; + bool findFloat(const char *name, float *value) const; + bool findDouble(const char *name, double *value) const; + bool findPointer(const char *name, void **value) const; + bool findString(const char *name, AString *value) const; + bool findObject(const char *name, sp<RefBase> *obj) const; + bool findMessage(const char *name, sp<AMessage> *obj) const; + + void post(int64_t delayUs = 0); + + sp<AMessage> dup() const; + + AString debugString(int32_t indent = 0) const; + +protected: + virtual ~AMessage(); + +private: + enum Type { + kTypeInt32, + kTypeInt64, + kTypeSize, + kTypeFloat, + kTypeDouble, + kTypePointer, + kTypeString, + kTypeObject, + kTypeMessage, + }; + + uint32_t mWhat; + ALooper::handler_id mTarget; + + struct Item { + union { + int32_t int32Value; + int64_t int64Value; + size_t sizeValue; + float floatValue; + double doubleValue; + void *ptrValue; + RefBase *refValue; + AString *stringValue; + } u; + const char *mName; + Type mType; + }; + + enum { + kMaxNumItems = 16 + }; + Item mItems[kMaxNumItems]; + size_t mNumItems; + + void clear(); + Item *allocateItem(const char *name); + void freeItem(Item *item); + const Item *findItem(const char *name, Type type) const; + + DISALLOW_EVIL_CONSTRUCTORS(AMessage); +}; + +} // namespace android + +#endif // A_MESSAGE_H_ diff --git a/include/media/stagefright/foundation/AString.h b/include/media/stagefright/foundation/AString.h new file mode 100644 index 0000000..55ade64 --- /dev/null +++ b/include/media/stagefright/foundation/AString.h @@ -0,0 +1,94 @@ +/* + * 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 A_STRING_H_ + +#define A_STRING_H_ + +#include <sys/types.h> + +namespace android { + +struct AString { + AString(); + AString(const char *s); + AString(const char *s, size_t size); + AString(const AString &from); + AString(const AString &from, size_t offset, size_t n); + ~AString(); + + AString &operator=(const AString &from); + void setTo(const char *s); + void setTo(const char *s, size_t size); + void setTo(const AString &from, size_t offset, size_t n); + + size_t size() const; + const char *c_str() const; + + bool empty() const; + + void clear(); + void trim(); + void erase(size_t start, size_t n); + + void append(char c) { append(&c, 1); } + void append(const char *s); + void append(const char *s, size_t size); + void append(const AString &from); + void append(const AString &from, size_t offset, size_t n); + void append(int x); + void append(unsigned x); + void append(long x); + void append(unsigned long x); + void append(long long x); + void append(unsigned long long x); + void append(float x); + void append(double x); + void append(void *x); + + void insert(const AString &from, size_t insertionPos); + void insert(const char *from, size_t size, size_t insertionPos); + + ssize_t find(const char *substring, size_t start = 0) const; + + size_t hash() const; + + bool operator==(const AString &other) const; + bool operator<(const AString &other) const; + bool operator>(const AString &other) const; + + int compare(const AString &other) const; + + bool startsWith(const char *prefix) const; + + void tolower(); + +private: + static const char *kEmptyString; + + char *mData; + size_t mSize; + size_t mAllocSize; + + void makeMutable(); +}; + +AString StringPrintf(const char *format, ...); + +} // namespace android + +#endif // A_STRING_H_ + diff --git a/include/media/stagefright/foundation/base64.h b/include/media/stagefright/foundation/base64.h new file mode 100644 index 0000000..e340b89 --- /dev/null +++ b/include/media/stagefright/foundation/base64.h @@ -0,0 +1,33 @@ +/* + * 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 BASE_64_H_ + +#define BASE_64_H_ + +#include <utils/RefBase.h> + +namespace android { + +struct ABuffer; +struct AString; + +sp<ABuffer> decodeBase64(const AString &s); +void encodeBase64(const void *data, size_t size, AString *out); + +} // namespace android + +#endif // BASE_64_H_ diff --git a/include/media/stagefright/foundation/hexdump.h b/include/media/stagefright/foundation/hexdump.h new file mode 100644 index 0000000..f6083a9 --- /dev/null +++ b/include/media/stagefright/foundation/hexdump.h @@ -0,0 +1,29 @@ +/* + * 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 HEXDUMP_H_ + +#define HEXDUMP_H_ + +#include <sys/types.h> + +namespace android { + +void hexdump(const void *_data, size_t size); + +} // namespace android + +#endif // HEXDUMP_H_ diff --git a/include/private/README b/include/private/README new file mode 100644 index 0000000..ee41492 --- /dev/null +++ b/include/private/README @@ -0,0 +1,4 @@ +This folder contains private include files. + +These include files are part of the private implementation details of +various framework components. Use at your peril. diff --git a/include/private/media/AudioEffectShared.h b/include/private/media/AudioEffectShared.h new file mode 100644 index 0000000..a3a99a4 --- /dev/null +++ b/include/private/media/AudioEffectShared.h @@ -0,0 +1,51 @@ +/* + * 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_EFFECTCBASESHARED_H +#define ANDROID_EFFECTCBASESHARED_H + +#include <stdint.h> +#include <sys/types.h> + +#include <utils/threads.h> + +namespace android { + +// ---------------------------------------------------------------------------- + +// Size of buffer used to exchange parameters between application and mediaserver processes. +#define EFFECT_PARAM_BUFFER_SIZE 1024 + + +// Shared memory area used to exchange parameters between application and mediaserver +// process. +struct effect_param_cblk_t +{ + Mutex lock; + volatile uint32_t clientIndex; // Current read/write index for application + volatile uint32_t serverIndex; // Current read/write index for mediaserver + uint8_t* buffer; // start of parameter buffer + + effect_param_cblk_t() + : lock(Mutex::SHARED), clientIndex(0), serverIndex(0) {} +}; + + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_EFFECTCBASESHARED_H diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index 8e2db20..1510f87 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -32,6 +32,18 @@ namespace android { #define MAX_RUN_TIMEOUT_MS 1000 #define WAIT_PERIOD_MS 10 +#define CBLK_UNDERRUN_MSK 0x0001 +#define CBLK_UNDERRUN_ON 0x0001 // underrun (out) or overrrun (in) indication +#define CBLK_UNDERRUN_OFF 0x0000 // no underrun +#define CBLK_DIRECTION_MSK 0x0002 +#define CBLK_DIRECTION_OUT 0x0002 // this cblk is for an AudioTrack +#define CBLK_DIRECTION_IN 0x0000 // this cblk is for an AudioRecord +#define CBLK_FORCEREADY_MSK 0x0004 +#define CBLK_FORCEREADY_ON 0x0004 // track is considered ready immediately by AudioFlinger +#define CBLK_FORCEREADY_OFF 0x0000 // track is ready when buffer full +#define CBLK_INVALID_MSK 0x0008 +#define CBLK_INVALID_ON 0x0008 // track buffer is invalidated by AudioFlinger: must be re-created +#define CBLK_INVALID_OFF 0x0000 struct audio_track_cblk_t { @@ -44,12 +56,12 @@ struct audio_track_cblk_t volatile uint32_t server; uint32_t userBase; uint32_t serverBase; - void* buffers; - uint32_t frameCount; - // Cache line boundary - uint32_t loopStart; - uint32_t loopEnd; - int loopCount; + void* buffers; + uint32_t frameCount; + // Cache line boundary + uint32_t loopStart; + uint32_t loopEnd; + int loopCount; volatile union { uint16_t volume[2]; uint32_t volumeLR; @@ -58,15 +70,17 @@ struct audio_track_cblk_t // NOTE: audio_track_cblk_t::frameSize is not equal to AudioTrack::frameSize() for // 8 bit PCM data: in this case, mCblk->frameSize is based on a sample size of // 16 bit because data is converted to 16 bit before being stored in buffer - uint32_t frameSize; - uint8_t channels; - uint8_t flowControlFlag; // underrun (out) or overrrun (in) indication - uint8_t out; // out equals 1 for AudioTrack and 0 for AudioRecord - uint8_t forceReady; + + uint8_t frameSize; + uint8_t channelCount; + uint16_t flags; + uint16_t bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger uint16_t waitTimeMs; // Cumulated wait time - // Cache line boundary (32 bytes) + uint16_t sendLevel; + uint16_t reserved; + // Cache line boundary (32 bytes) audio_track_cblk_t(); uint32_t stepUser(uint32_t frameCount); bool stepServer(uint32_t frameCount); diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h index 9b5a1e0..1eb178e 100644 --- a/include/private/surfaceflinger/SharedBufferStack.h +++ b/include/private/surfaceflinger/SharedBufferStack.h @@ -43,24 +43,9 @@ namespace android { * unless they are in use by the server, which is only the case for the last * dequeue-able buffer. When these various conditions are not met, the caller * waits until the condition is met. - * - * - * CAVEATS: - * - * In the current implementation there are several limitations: - * - buffers must be locked in the same order they've been dequeued - * - buffers must be enqueued in the same order they've been locked - * - dequeue() is not reentrant - * - no error checks are done on the condition above * */ -// When changing these values, the COMPILE_TIME_ASSERT at the end of this -// file need to be updated. -const unsigned int NUM_LAYERS_MAX = 31; -const unsigned int NUM_BUFFER_MAX = 4; -const unsigned int NUM_DISPLAY_MAX = 4; - // ---------------------------------------------------------------------------- class Region; @@ -69,7 +54,11 @@ class SharedClient; // ---------------------------------------------------------------------------- -// should be 128 bytes (32 longs) +// 4 * (11 + 7 + (1 + 2*NUM_RECT_MAX) * NUM_BUFFER_MAX) * NUM_LAYERS_MAX +// 4 * (11 + 7 + (1 + 2*7)*16) * 31 +// 1032 * 31 +// = ~27 KiB (31992) + class SharedBufferStack { friend class SharedClient; @@ -78,21 +67,38 @@ class SharedBufferStack friend class SharedBufferServer; public: - struct FlatRegion { // 12 bytes - static const unsigned int NUM_RECT_MAX = 1; - uint32_t count; - uint16_t rects[4*NUM_RECT_MAX]; - }; - + // When changing these values, the COMPILE_TIME_ASSERT at the end of this + // file need to be updated. + static const unsigned int NUM_LAYERS_MAX = 31; + static const unsigned int NUM_BUFFER_MAX = 16; + static const unsigned int NUM_BUFFER_MIN = 2; + static const unsigned int NUM_DISPLAY_MAX = 4; + struct Statistics { // 4 longs typedef int32_t usecs_t; usecs_t totalTime; usecs_t reserved[3]; }; + + struct SmallRect { + uint16_t l, t, r, b; + }; + + struct FlatRegion { // 52 bytes = 4 * (1 + 2*N) + static const unsigned int NUM_RECT_MAX = 6; + uint32_t count; + SmallRect rects[NUM_RECT_MAX]; + }; + + struct BufferData { + FlatRegion dirtyRegion; + SmallRect crop; + }; SharedBufferStack(); void init(int32_t identity); status_t setDirtyRegion(int buffer, const Region& reg); + status_t setCrop(int buffer, const Rect& reg); Region getDirtyRegion(int buffer) const; // these attributes are part of the conditions/updates @@ -104,24 +110,25 @@ public: // not part of the conditions volatile int32_t reallocMask; + volatile int8_t index[NUM_BUFFER_MAX]; int32_t identity; // surface's identity (const) - int32_t reserved32[9]; + int32_t token; // surface's token (for debugging) + int32_t reserved32[1]; Statistics stats; - FlatRegion dirtyRegion[NUM_BUFFER_MAX]; // 12*4=48 bytes + int32_t reserved; + BufferData buffers[NUM_BUFFER_MAX]; // 960 bytes }; // ---------------------------------------------------------------------------- -// 4 KB max +// 32 KB max class SharedClient { public: SharedClient(); ~SharedClient(); - status_t validate(size_t token) const; - uint32_t getIdentity(size_t token) const; private: friend class SharedBufferBase; @@ -131,7 +138,7 @@ private: // FIXME: this should be replaced by a lock-less primitive Mutex lock; Condition cv; - SharedBufferStack surfaces[ NUM_LAYERS_MAX ]; + SharedBufferStack surfaces[ SharedBufferStack::NUM_LAYERS_MAX ]; }; // ============================================================================ @@ -139,18 +146,17 @@ private: class SharedBufferBase { public: - SharedBufferBase(SharedClient* sharedClient, int surface, int num, + SharedBufferBase(SharedClient* sharedClient, int surface, int32_t identity); ~SharedBufferBase(); - uint32_t getIdentity(); status_t getStatus() const; + int32_t getIdentity() const; size_t getFrontBuffer() const; String8 dump(char const* prefix) const; protected: SharedClient* const mSharedClient; SharedBufferStack* const mSharedStack; - const int mNumBuffers; const int mIdentity; friend struct Update; @@ -160,61 +166,22 @@ protected: SharedBufferStack& stack; inline ConditionBase(SharedBufferBase* sbc) : stack(*sbc->mSharedStack) { } + virtual ~ConditionBase() { }; + virtual bool operator()() const = 0; + virtual const char* name() const = 0; }; + status_t waitForCondition(const ConditionBase& condition); struct UpdateBase { SharedBufferStack& stack; inline UpdateBase(SharedBufferBase* sbb) : stack(*sbb->mSharedStack) { } }; - - template <typename T> - status_t waitForCondition(T condition); - template <typename T> status_t updateCondition(T update); }; template <typename T> -status_t SharedBufferBase::waitForCondition(T condition) -{ - const SharedBufferStack& stack( *mSharedStack ); - SharedClient& client( *mSharedClient ); - const nsecs_t TIMEOUT = s2ns(1); - Mutex::Autolock _l(client.lock); - while ((condition()==false) && - (stack.identity == mIdentity) && - (stack.status == NO_ERROR)) - { - status_t err = client.cv.waitRelative(client.lock, TIMEOUT); - - // handle errors and timeouts - if (CC_UNLIKELY(err != NO_ERROR)) { - if (err == TIMED_OUT) { - if (condition()) { - LOGE("waitForCondition(%s) timed out (identity=%d), " - "but condition is true! We recovered but it " - "shouldn't happen." , T::name(), - stack.identity); - break; - } else { - LOGW("waitForCondition(%s) timed out " - "(identity=%d, status=%d). " - "CPU may be pegged. trying again.", T::name(), - stack.identity, stack.status); - } - } else { - LOGE("waitForCondition(%s) error (%s) ", - T::name(), strerror(-err)); - return err; - } - } - } - return (stack.identity != mIdentity) ? status_t(BAD_INDEX) : stack.status; -} - - -template <typename T> status_t SharedBufferBase::updateCondition(T update) { SharedClient& client( *mSharedClient ); Mutex::Autolock _l(client.lock); @@ -238,13 +205,21 @@ public: status_t queue(int buf); bool needNewBuffer(int buffer) const; status_t setDirtyRegion(int buffer, const Region& reg); + status_t setCrop(int buffer, const Rect& reg); + + class SetBufferCountCallback { + friend class SharedBufferClient; + virtual status_t operator()(int bufferCount) const = 0; + protected: + virtual ~SetBufferCountCallback() { } + }; + status_t setBufferCount(int bufferCount, const SetBufferCountCallback& ipc); + private: friend struct Condition; friend struct DequeueCondition; friend struct LockCondition; - - int32_t computeTail() const; struct QueueUpdate : public UpdateBase { inline QueueUpdate(SharedBufferBase* sbb); @@ -260,25 +235,34 @@ private: struct DequeueCondition : public ConditionBase { inline DequeueCondition(SharedBufferClient* sbc); - inline bool operator()(); - static inline const char* name() { return "DequeueCondition"; } + inline bool operator()() const; + inline const char* name() const { return "DequeueCondition"; } }; struct LockCondition : public ConditionBase { int buf; inline LockCondition(SharedBufferClient* sbc, int buf); - inline bool operator()(); - static inline const char* name() { return "LockCondition"; } + inline bool operator()() const; + inline const char* name() const { return "LockCondition"; } }; + int32_t computeTail() const; + + mutable RWLock mLock; + int mNumBuffers; + int32_t tail; + int32_t undoDequeueTail; + int32_t queued_head; // statistics... - nsecs_t mDequeueTime[NUM_BUFFER_MAX]; + nsecs_t mDequeueTime[SharedBufferStack::NUM_BUFFER_MAX]; }; // ---------------------------------------------------------------------------- -class SharedBufferServer : public SharedBufferBase +class SharedBufferServer + : public SharedBufferBase, + public LightRefBase<SharedBufferServer> { public: SharedBufferServer(SharedClient* sharedClient, int surface, int num, @@ -287,16 +271,73 @@ public: ssize_t retireAndLock(); status_t unlock(int buffer); void setStatus(status_t status); - status_t reallocate(); - status_t assertReallocate(int buffer); + status_t reallocateAll(); + status_t reallocateAllExcept(int buffer); int32_t getQueuedCount() const; - Region getDirtyRegion(int buffer) const; + status_t resize(int newNumBuffers); + SharedBufferStack::Statistics getStats() const; private: + friend class LightRefBase<SharedBufferServer>; + ~SharedBufferServer(); + + /* + * BufferList is basically a fixed-capacity sorted-vector of + * unsigned 5-bits ints using a 32-bits int as storage. + * it has efficient iterators to find items in the list and not in the list. + */ + class BufferList { + size_t mCapacity; + uint32_t mList; + public: + BufferList(size_t c = SharedBufferStack::NUM_BUFFER_MAX) + : mCapacity(c), mList(0) { } + status_t add(int value); + status_t remove(int value); + uint32_t getMask() const { return mList; } + + class const_iterator { + friend class BufferList; + uint32_t mask, curr; + const_iterator(uint32_t mask) : + mask(mask), curr(__builtin_clz(mask)) { + } + public: + inline bool operator == (const const_iterator& rhs) const { + return mask == rhs.mask; + } + inline bool operator != (const const_iterator& rhs) const { + return mask != rhs.mask; + } + inline int operator *() const { return curr; } + inline const const_iterator& operator ++() { + mask &= ~(1<<(31-curr)); + curr = __builtin_clz(mask); + return *this; + } + }; + + inline const_iterator begin() const { + return const_iterator(mList); + } + inline const_iterator end() const { + return const_iterator(0); + } + inline const_iterator free_begin() const { + uint32_t mask = (1 << (32-mCapacity)) - 1; + return const_iterator( ~(mList | mask) ); + } + }; + + // this protects mNumBuffers and mBufferList + mutable RWLock mLock; + int mNumBuffers; + BufferList mBufferList; + struct UnlockUpdate : public UpdateBase { const int lockedBuffer; inline UnlockUpdate(SharedBufferBase* sbb, int lockedBuffer); @@ -314,13 +355,6 @@ private: inline StatusUpdate(SharedBufferBase* sbb, status_t status); inline ssize_t operator()(); }; - - struct ReallocateCondition : public ConditionBase { - int buf; - inline ReallocateCondition(SharedBufferBase* sbb, int buf); - inline bool operator()(); - static inline const char* name() { return "ReallocateCondition"; } - }; }; // =========================================================================== @@ -344,13 +378,12 @@ struct surface_flinger_cblk_t // 4KB max uint8_t connected; uint8_t reserved[3]; uint32_t pad[7]; - display_cblk_t displays[NUM_DISPLAY_MAX]; + display_cblk_t displays[SharedBufferStack::NUM_DISPLAY_MAX]; }; // --------------------------------------------------------------------------- -COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 4096) -COMPILE_TIME_ASSERT(sizeof(SharedBufferStack) == 128) +COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 32768) COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096) // --------------------------------------------------------------------------- diff --git a/include/surfaceflinger/ISurface.h b/include/surfaceflinger/ISurface.h index 472f759..ddbe03d 100644 --- a/include/surfaceflinger/ISurface.h +++ b/include/surfaceflinger/ISurface.h @@ -47,13 +47,30 @@ protected: POST_BUFFER, // one-way transaction CREATE_OVERLAY, REQUEST_BUFFER, + SET_BUFFER_COUNT, }; public: DECLARE_META_INTERFACE(Surface); - virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage) = 0; + /* + * requests a new buffer for the given index. If w, h, or format are + * null the buffer is created with the parameters assigned to the + * surface it is bound to. Otherwise the buffer's parameters are + * set to those specified. + */ + virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0; + + /* + * sets the number of buffers dequeuable for this surface. + */ + virtual status_t setBufferCount(int bufferCount) = 0; + // ------------------------------------------------------------------------ + // Deprecated... + // ------------------------------------------------------------------------ + class BufferHeap { public: enum { diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h index d1e7785..dd44aa5 100644 --- a/include/surfaceflinger/ISurfaceComposer.h +++ b/include/surfaceflinger/ISurfaceComposer.h @@ -27,7 +27,7 @@ #include <ui/PixelFormat.h> -#include <surfaceflinger/ISurfaceFlingerClient.h> +#include <surfaceflinger/ISurfaceComposerClient.h> namespace android { // ---------------------------------------------------------------------------- @@ -85,8 +85,11 @@ public: /* create connection with surface flinger, requires * ACCESS_SURFACE_FLINGER permission */ + virtual sp<ISurfaceComposerClient> createConnection() = 0; - virtual sp<ISurfaceFlingerClient> createConnection() = 0; + /* create a client connection with surface flinger + */ + virtual sp<ISurfaceComposerClient> createClientConnection() = 0; /* retrieve the control block */ virtual sp<IMemoryHeap> getCblk() const = 0; @@ -123,6 +126,7 @@ public: // Java by ActivityManagerService. BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION, CREATE_CONNECTION, + CREATE_CLIENT_CONNECTION, GET_CBLK, OPEN_GLOBAL_TRANSACTION, CLOSE_GLOBAL_TRANSACTION, diff --git a/include/surfaceflinger/ISurfaceFlingerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h index d257645..a1e9e04 100644 --- a/include/surfaceflinger/ISurfaceFlingerClient.h +++ b/include/surfaceflinger/ISurfaceComposerClient.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ANDROID_SF_ISURFACE_FLINGER_CLIENT_H -#define ANDROID_SF_ISURFACE_FLINGER_CLIENT_H +#ifndef ANDROID_SF_ISURFACE_COMPOSER_CLIENT_H +#define ANDROID_SF_ISURFACE_COMPOSER_CLIENT_H #include <stdint.h> #include <sys/types.h> @@ -26,7 +26,7 @@ #include <binder/IInterface.h> #include <ui/PixelFormat.h> - + #include <surfaceflinger/ISurface.h> namespace android { @@ -42,10 +42,10 @@ typedef int32_t DisplayID; class layer_state_t; -class ISurfaceFlingerClient : public IInterface +class ISurfaceComposerClient : public IInterface { -public: - DECLARE_META_INTERFACE(SurfaceFlingerClient); +public: + DECLARE_META_INTERFACE(SurfaceComposerClient); struct surface_data_t { int32_t token; @@ -56,26 +56,36 @@ public: status_t readFromParcel(const Parcel& parcel); status_t writeToParcel(Parcel* parcel) const; }; - + virtual sp<IMemoryHeap> getControlBlock() const = 0; + virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const = 0; + /* + * Requires ACCESS_SURFACE_FLINGER permission + */ virtual sp<ISurface> createSurface( surface_data_t* data, - int pid, + int pid, const String8& name, DisplayID display, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) = 0; - + + /* + * Requires ACCESS_SURFACE_FLINGER permission + */ virtual status_t destroySurface(SurfaceID sid) = 0; + /* + * Requires ACCESS_SURFACE_FLINGER permission + */ virtual status_t setState(int32_t count, const layer_state_t* states) = 0; }; // ---------------------------------------------------------------------------- -class BnSurfaceFlingerClient : public BnInterface<ISurfaceFlingerClient> +class BnSurfaceComposerClient : public BnInterface<ISurfaceComposerClient> { public: virtual status_t onTransact( uint32_t code, @@ -88,4 +98,4 @@ public: }; // namespace android -#endif // ANDROID_SF_ISURFACE_FLINGER_CLIENT_H +#endif // ANDROID_SF_ISURFACE_COMPOSER_CLIENT_H diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h index 0279d84..294c867 100644 --- a/include/surfaceflinger/Surface.h +++ b/include/surfaceflinger/Surface.h @@ -20,6 +20,7 @@ #include <stdint.h> #include <sys/types.h> +#include <utils/KeyedVector.h> #include <utils/RefBase.h> #include <utils/threads.h> @@ -28,12 +29,15 @@ #include <ui/egl/android_natives.h> #include <surfaceflinger/ISurface.h> -#include <surfaceflinger/ISurfaceFlingerClient.h> +#include <surfaceflinger/ISurfaceComposerClient.h> + +#define ANDROID_VIEW_SURFACE_JNI_ID "mNativeSurface" namespace android { // --------------------------------------------------------------------------- +class GraphicBuffer; class GraphicBufferMapper; class IOMX; class Rect; @@ -41,6 +45,7 @@ class Surface; class SurfaceComposerClient; class SharedClient; class SharedBufferClient; +class SurfaceClient; // --------------------------------------------------------------------------- @@ -56,7 +61,6 @@ public: static bool isSameSurface( const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs); - SurfaceID ID() const { return mToken; } uint32_t getFlags() const { return mFlags; } uint32_t getIdentity() const { return mIdentity; } @@ -104,7 +108,7 @@ private: SurfaceControl( const sp<SurfaceComposerClient>& client, const sp<ISurface>& surface, - const ISurfaceFlingerClient::surface_data_t& data, + const ISurfaceComposerClient::surface_data_t& data, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); ~SurfaceControl(); @@ -128,7 +132,7 @@ private: // --------------------------------------------------------------------------- class Surface - : public EGLNativeBase<android_native_window_t, Surface, RefBase> + : public EGLNativeBase<ANativeWindow, Surface, RefBase> { public: struct SurfaceInfo { @@ -141,17 +145,16 @@ public: uint32_t reserved[2]; }; - Surface(const Parcel& data); + static status_t writeToParcel( + const sp<Surface>& control, Parcel* parcel); + + static sp<Surface> readFromParcel(const Parcel& data); static bool isValid(const sp<Surface>& surface) { return (surface != 0) && surface->isValid(); } - static bool isSameSurface( - const sp<Surface>& lhs, const sp<Surface>& rhs); - bool isValid(); - SurfaceID ID() const { return mToken; } uint32_t getFlags() const { return mFlags; } uint32_t getIdentity() const { return mIdentity; } @@ -163,44 +166,43 @@ public: // setSwapRectangle() is intended to be used by GL ES clients void setSwapRectangle(const Rect& r); -private: - // can't be copied - Surface& operator = (Surface& rhs); - Surface(const Surface& rhs); - - Surface(const sp<SurfaceControl>& control); - void init(); - ~Surface(); - - friend class SurfaceComposerClient; - friend class SurfaceControl; - +private: + /* + * Android frameworks friends + * (eventually this should go away and be replaced by proper APIs) + */ // camera and camcorder need access to the ISurface binder interface for preview friend class Camera; friend class MediaRecorder; - // mediaplayer needs access to ISurface for display + // MediaPlayer needs access to ISurface for display friend class MediaPlayer; friend class IOMX; // this is just to be able to write some unit tests friend class Test; - sp<SurfaceComposerClient> getClient() const; - sp<ISurface> getISurface() const; +private: + friend class SurfaceComposerClient; + friend class SurfaceControl; - status_t getBufferLocked(int index, int usage); - - status_t validate() const; + // can't be copied + Surface& operator = (Surface& rhs); + Surface(const Surface& rhs); - inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; } - inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; } - - static int setSwapInterval(android_native_window_t* window, int interval); - static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer); - static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer); - static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer); - static int query(android_native_window_t* window, int what, int* value); - static int perform(android_native_window_t* window, int operation, ...); + Surface(const sp<SurfaceControl>& control); + Surface(const Parcel& data, const sp<IBinder>& ref); + ~Surface(); + + + /* + * ANativeWindow hooks + */ + static int setSwapInterval(ANativeWindow* window, int interval); + static int dequeueBuffer(ANativeWindow* window, android_native_buffer_t** buffer); + static int lockBuffer(ANativeWindow* window, android_native_buffer_t* buffer); + static int queueBuffer(ANativeWindow* window, android_native_buffer_t* buffer); + static int query(ANativeWindow* window, int what, int* value); + static int perform(ANativeWindow* window, int operation, ...); int dequeueBuffer(android_native_buffer_t** buffer); int lockBuffer(android_native_buffer_t* buffer); @@ -208,44 +210,88 @@ private: int query(int what, int* value); int perform(int operation, va_list args); - status_t dequeueBuffer(sp<GraphicBuffer>* buffer); - void dispatch_setUsage(va_list args); int dispatch_connect(va_list args); int dispatch_disconnect(va_list args); + int dispatch_crop(va_list args); + int dispatch_set_buffer_count(va_list args); + int dispatch_set_buffers_geometry(va_list args); void setUsage(uint32_t reqUsage); int connect(int api); int disconnect(int api); + int crop(Rect const* rect); + int setBufferCount(int bufferCount); + int setBuffersGeometry(int w, int h, int format); + + /* + * private stuff... + */ + void init(); + status_t validate() const; + sp<ISurface> getISurface() const; + + inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; } + inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; } + + status_t getBufferLocked(int index, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage); + int getBufferIndex(const sp<GraphicBuffer>& buffer) const; - uint32_t getUsage() const; - int getConnectedApi() const; + int getConnectedApi() const; + bool needNewBuffer(int bufIdx, + uint32_t *pWidth, uint32_t *pHeight, + uint32_t *pFormat, uint32_t *pUsage) const; + + static void cleanCachedSurfaces(); + + class BufferInfo { + uint32_t mWidth; + uint32_t mHeight; + uint32_t mFormat; + uint32_t mUsage; + mutable uint32_t mDirty; + enum { + GEOMETRY = 0x01 + }; + public: + BufferInfo(); + void set(uint32_t w, uint32_t h, uint32_t format); + void set(uint32_t usage); + void get(uint32_t *pWidth, uint32_t *pHeight, + uint32_t *pFormat, uint32_t *pUsage) const; + bool validateBuffer(const sp<GraphicBuffer>& buffer) const; + }; + // constants - sp<SurfaceComposerClient> mClient; + GraphicBufferMapper& mBufferMapper; + SurfaceClient& mClient; + SharedBufferClient* mSharedBufferClient; + status_t mInitCheck; sp<ISurface> mSurface; - SurfaceID mToken; uint32_t mIdentity; PixelFormat mFormat; uint32_t mFlags; - GraphicBufferMapper& mBufferMapper; - SharedBufferClient* mSharedBufferClient; // protected by mSurfaceLock Rect mSwapRectangle; - uint32_t mUsage; int mConnected; + Rect mNextBufferCrop; + BufferInfo mBufferInfo; // protected by mSurfaceLock. These are also used from lock/unlock // but in that case, they must be called form the same thread. - sp<GraphicBuffer> mBuffers[2]; mutable Region mDirtyRegion; // must be used from the lock/unlock thread sp<GraphicBuffer> mLockedBuffer; sp<GraphicBuffer> mPostedBuffer; mutable Region mOldDirtyRegion; - bool mNeedFullUpdate; + bool mReserved; + + // only used from dequeueBuffer() + Vector< sp<GraphicBuffer> > mBuffers; // query() must be called from dequeueBuffer() thread uint32_t mWidth; @@ -254,6 +300,10 @@ private: // Inherently thread-safe mutable Mutex mSurfaceLock; mutable Mutex mApiLock; + + // A cache of Surface objects that have been deserialized into this process. + static Mutex sCachedSurfacesLock; + static DefaultKeyedVector<wp<IBinder>, wp<Surface> > sCachedSurfaces; }; }; // namespace android diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h index 9d0f0cb..8773d71 100644 --- a/include/surfaceflinger/SurfaceComposerClient.h +++ b/include/surfaceflinger/SurfaceComposerClient.h @@ -22,8 +22,9 @@ #include <binder/IBinder.h> -#include <utils/SortedVector.h> #include <utils/RefBase.h> +#include <utils/Singleton.h> +#include <utils/SortedVector.h> #include <utils/threads.h> #include <ui/PixelFormat.h> @@ -39,8 +40,26 @@ class Region; class SharedClient; class ISurfaceComposer; class DisplayInfo; +class surface_flinger_cblk_t; + +// --------------------------------------------------------------------------- + +class ComposerService : public Singleton<ComposerService> +{ + // these are constants + sp<ISurfaceComposer> mComposerService; + sp<IMemoryHeap> mServerCblkMemory; + surface_flinger_cblk_t volatile* mServerCblk; + ComposerService(); + friend class Singleton<ComposerService>; +public: + static sp<ISurfaceComposer> getComposerService(); + static surface_flinger_cblk_t const volatile * getControlBlock(); +}; -class SurfaceComposerClient : virtual public RefBase +// --------------------------------------------------------------------------- + +class SurfaceComposerClient : public RefBase { public: SurfaceComposerClient(); @@ -52,10 +71,6 @@ public: // Return the connection of this client sp<IBinder> connection() const; - // Retrieve a client for an existing connection. - static sp<SurfaceComposerClient> - clientForConnection(const sp<IBinder>& conn); - // Forcibly remove connection before all references have gone away. void dispose(); @@ -123,13 +138,6 @@ public: status_t linkToComposerDeath(const sp<IBinder::DeathRecipient>& recipient, void* cookie = NULL, uint32_t flags = 0); -private: - friend class Surface; - friend class SurfaceControl; - - SurfaceComposerClient(const sp<ISurfaceComposer>& sm, - const sp<IBinder>& conn); - status_t hide(SurfaceID id); status_t show(SurfaceID id, int32_t layer = -1); status_t freeze(SurfaceID id); @@ -142,32 +150,26 @@ private: status_t setMatrix(SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy); status_t setPosition(SurfaceID id, int32_t x, int32_t y); status_t setSize(SurfaceID id, uint32_t w, uint32_t h); - - void signalServer(); - status_t destroySurface(SurfaceID sid); - void _init(const sp<ISurfaceComposer>& sm, - const sp<ISurfaceFlingerClient>& conn); - - inline layer_state_t* _get_state_l(SurfaceID id); - layer_state_t* _lockLayerState(SurfaceID id); - inline void _unlockLayerState(); +private: + virtual void onFirstRef(); + inline layer_state_t* get_state_l(SurfaceID id); + layer_state_t* lockLayerState(SurfaceID id); + inline void unlockLayerState(); mutable Mutex mLock; - layer_state_t* mPrebuiltLayerState; SortedVector<layer_state_t> mStates; int32_t mTransactionOpen; + layer_state_t* mPrebuiltLayerState; // these don't need to be protected because they never change // after assignment status_t mStatus; - SharedClient* mControl; - sp<IMemoryHeap> mControlMemory; - sp<ISurfaceFlingerClient> mClient; - sp<ISurfaceComposer> mSignalServer; + sp<ISurfaceComposerClient> mClient; }; +// --------------------------------------------------------------------------- }; // namespace android #endif // ANDROID_SF_SURFACE_COMPOSER_CLIENT_H diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h index 3b18c77..dab35b3 100644 --- a/include/ui/EventHub.h +++ b/include/ui/EventHub.h @@ -18,6 +18,7 @@ #ifndef _RUNTIME_EVENT_HUB_H #define _RUNTIME_EVENT_HUB_H +#include <android/input.h> #include <utils/String8.h> #include <utils/threads.h> #include <utils/Log.h> @@ -27,6 +28,31 @@ #include <linux/input.h> +/* These constants are not defined in linux/input.h but they are part of the multitouch + * input protocol. */ + +#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */ +#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */ +#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */ +#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */ +#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */ +#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */ +#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */ +#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device (finger, pen, ...) */ +#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */ +#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */ +#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */ + +#define MT_TOOL_FINGER 0 /* Identifies a finger */ +#define MT_TOOL_PEN 1 /* Identifies a pen */ + +#define SYN_MT_REPORT 2 + +/* Convenience constants. */ + +#define BTN_FIRST 0x100 // first button scancode +#define BTN_LAST 0x15f // last button scancode + struct pollfd; namespace android { @@ -34,73 +60,154 @@ namespace android { class KeyLayoutMap; /* - * Grand Central Station for events. With a single call to waitEvent() - * you can wait for: - * - input events from the keypad of a real device - * - input events and meta-events (e.g. "quit") from the simulator - * - synthetic events from the runtime (e.g. "URL fetch completed") - * - real or forged "vsync" events + * A raw event as retrieved from the EventHub. + */ +struct RawEvent { + nsecs_t when; + int32_t deviceId; + int32_t type; + int32_t scanCode; + int32_t keyCode; + int32_t value; + uint32_t flags; +}; + +/* Describes an absolute axis. */ +struct RawAbsoluteAxisInfo { + bool valid; // true if the information is valid, false otherwise + + int32_t minValue; // minimum value + int32_t maxValue; // maximum value + int32_t flat; // center flat position, eg. flat == 8 means center is between -8 and 8 + int32_t fuzz; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise + + inline int32_t getRange() { return maxValue - minValue; } +}; + +/* + * Input device classes. + */ +enum { + /* The input device is a keyboard. */ + INPUT_DEVICE_CLASS_KEYBOARD = 0x00000001, + + /* The input device is an alpha-numeric keyboard (not just a dial pad). */ + INPUT_DEVICE_CLASS_ALPHAKEY = 0x00000002, + + /* The input device is a touchscreen (either single-touch or multi-touch). */ + INPUT_DEVICE_CLASS_TOUCHSCREEN = 0x00000004, + + /* The input device is a trackball. */ + INPUT_DEVICE_CLASS_TRACKBALL = 0x00000008, + + /* The input device is a multi-touch touchscreen. */ + INPUT_DEVICE_CLASS_TOUCHSCREEN_MT= 0x00000010, + + /* The input device is a directional pad. */ + INPUT_DEVICE_CLASS_DPAD = 0x00000020, + + /* The input device is a gamepad (implies keyboard). */ + INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040, + + /* The input device has switches. */ + INPUT_DEVICE_CLASS_SWITCH = 0x00000080, +}; + +/* + * Grand Central Station for events. * - * Do not instantiate this class. Instead, call startUp(). + * The event hub aggregates input events received across all known input + * devices on the system, including devices that may be emulated by the simulator + * environment. In addition, the event hub generates fake input events to indicate + * when devices are added or removed. + * + * The event hub provies a stream of input events (via the getEvent function). + * It also supports querying the current actual state of input devices such as identifying + * which keys are currently down. Finally, the event hub keeps track of the capabilities of + * individual input devices, such as their class and the set of key codes that they support. */ -class EventHub : public RefBase +class EventHubInterface : public virtual RefBase { +protected: + EventHubInterface() { } + virtual ~EventHubInterface() { } + +public: + // Synthetic raw event type codes produced when devices are added or removed. + enum { + DEVICE_ADDED = 0x10000000, + DEVICE_REMOVED = 0x20000000 + }; + + virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0; + + virtual String8 getDeviceName(int32_t deviceId) const = 0; + + virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis, + RawAbsoluteAxisInfo* outAxisInfo) const = 0; + + virtual status_t scancodeToKeycode(int32_t deviceId, int scancode, + int32_t* outKeycode, uint32_t* outFlags) const = 0; + + // exclude a particular device from opening + // this can be used to ignore input devices for sensors + virtual void addExcludedDevice(const char* deviceName) = 0; + + /* + * Wait for the next event to become available and return it. + * After returning, the EventHub holds onto a wake lock until the next call to getEvent. + * This ensures that the device will not go to sleep while the event is being processed. + * If the device needs to remain awake longer than that, then the caller is responsible + * for taking care of it (say, by poking the power manager user activity timer). + */ + virtual bool getEvent(RawEvent* outEvent) = 0; + + /* + * Query current input state. + */ + virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0; + virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0; + virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0; + + /* + * Examine key input devices for specific framework keycode support + */ + virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes, + uint8_t* outFlags) const = 0; +}; + +class EventHub : public EventHubInterface { public: EventHub(); - + status_t errorCheck() const; + + virtual uint32_t getDeviceClasses(int32_t deviceId) const; - // bit fields for classes of devices. - enum { - CLASS_KEYBOARD = 0x00000001, - CLASS_ALPHAKEY = 0x00000002, - CLASS_TOUCHSCREEN = 0x00000004, - CLASS_TRACKBALL = 0x00000008, - CLASS_TOUCHSCREEN_MT= 0x00000010, - CLASS_DPAD = 0x00000020 - }; - uint32_t getDeviceClasses(int32_t deviceId) const; - - String8 getDeviceName(int32_t deviceId) const; - - int getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue, - int* outMaxValue, int* outFlat, int* outFuzz) const; - - int getSwitchState(int sw) const; - int getSwitchState(int32_t deviceId, int sw) const; - - int getScancodeState(int key) const; - int getScancodeState(int32_t deviceId, int key) const; - - int getKeycodeState(int key) const; - int getKeycodeState(int32_t deviceId, int key) const; + virtual String8 getDeviceName(int32_t deviceId) const; - status_t scancodeToKeycode(int32_t deviceId, int scancode, + virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis, + RawAbsoluteAxisInfo* outAxisInfo) const; + + virtual status_t scancodeToKeycode(int32_t deviceId, int scancode, int32_t* outKeycode, uint32_t* outFlags) const; - // exclude a particular device from opening - // this can be used to ignore input devices for sensors - void addExcludedDevice(const char* deviceName); + virtual void addExcludedDevice(const char* deviceName); - // special type codes when devices are added/removed. - enum { - DEVICE_ADDED = 0x10000000, - DEVICE_REMOVED = 0x20000000 - }; - - // examine key input devices for specific framework keycode support - bool hasKeys(size_t numCodes, int32_t* keyCodes, uint8_t* outFlags); + virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const; + virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const; + virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const; - virtual bool getEvent(int32_t* outDeviceId, int32_t* outType, - int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags, - int32_t* outValue, nsecs_t* outWhen); + virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, + const int32_t* keyCodes, uint8_t* outFlags) const; + + virtual bool getEvent(RawEvent* outEvent); protected: virtual ~EventHub(); private: bool openPlatformInput(void); - int32_t convertDeviceKey_TI_P2(int code); int open_device(const char *device); int close_device(const char *device); @@ -126,6 +233,12 @@ private: device_t* getDevice(int32_t deviceId) const; bool hasKeycode(device_t* device, int keycode) const; + int32_t getScanCodeStateLocked(device_t* device, int32_t scanCode) const; + int32_t getKeyCodeStateLocked(device_t* device, int32_t keyCode) const; + int32_t getSwitchStateLocked(device_t* device, int32_t sw) const; + bool markSupportedKeyCodesLocked(device_t* device, size_t numCodes, + const int32_t* keyCodes, uint8_t* outFlags) const; + // Protect all internal state. mutable Mutex mLock; @@ -151,7 +264,7 @@ private: // device ids that report particular switches. #ifdef EV_SW - int32_t mSwitches[SW_MAX+1]; + int32_t mSwitches[SW_MAX + 1]; #endif }; diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h index 8ea3ab9..0f4594f 100644 --- a/include/ui/FramebufferNativeWindow.h +++ b/include/ui/FramebufferNativeWindow.h @@ -43,7 +43,7 @@ class NativeBuffer; class FramebufferNativeWindow : public EGLNativeBase< - android_native_window_t, + ANativeWindow, FramebufferNativeWindow, LightRefBase<FramebufferNativeWindow> > { @@ -59,12 +59,12 @@ public: private: friend class LightRefBase<FramebufferNativeWindow>; ~FramebufferNativeWindow(); // this class cannot be overloaded - static int setSwapInterval(android_native_window_t* window, int interval); - static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer); - static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer); - static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer); - static int query(android_native_window_t* window, int what, int* value); - static int perform(android_native_window_t* window, int operation, ...); + static int setSwapInterval(ANativeWindow* window, int interval); + static int dequeueBuffer(ANativeWindow* window, android_native_buffer_t** buffer); + static int lockBuffer(ANativeWindow* window, android_native_buffer_t* buffer); + static int queueBuffer(ANativeWindow* window, android_native_buffer_t* buffer); + static int query(ANativeWindow* window, int what, int* value); + static int perform(ANativeWindow* window, int operation, ...); framebuffer_device_t* fbDev; alloc_device_t* grDev; diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h index e72b6b3..a3e85a9 100644 --- a/include/ui/GraphicBuffer.h +++ b/include/ui/GraphicBuffer.h @@ -93,10 +93,8 @@ public: void setIndex(int index); int getIndex() const; - void setVerticalStride(uint32_t vstride); - uint32_t getVerticalStride() const; -protected: +private: virtual ~GraphicBuffer(); enum { @@ -105,8 +103,12 @@ protected: ownData = 2, }; - inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; } - inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; } + inline const GraphicBufferMapper& getBufferMapper() const { + return mBufferMapper; + } + inline GraphicBufferMapper& getBufferMapper() { + return mBufferMapper; + } uint8_t mOwner; private: @@ -134,7 +136,6 @@ private: GraphicBufferMapper& mBufferMapper; ssize_t mInitCheck; - uint32_t mVStride; int mIndex; }; diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h index 741d763..54b8236 100644 --- a/include/ui/GraphicBufferAllocator.h +++ b/include/ui/GraphicBufferAllocator.h @@ -73,9 +73,9 @@ private: struct alloc_rec_t { uint32_t w; uint32_t h; + uint32_t s; PixelFormat format; uint32_t usage; - void* vaddr; size_t size; }; diff --git a/include/ui/Input.h b/include/ui/Input.h new file mode 100644 index 0000000..2385973 --- /dev/null +++ b/include/ui/Input.h @@ -0,0 +1,491 @@ +/* + * 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 _UI_INPUT_H +#define _UI_INPUT_H + +/** + * Native input event structures. + */ + +#include <android/input.h> +#include <utils/Vector.h> +#include <utils/KeyedVector.h> +#include <utils/Timers.h> +#include <utils/RefBase.h> +#include <utils/String8.h> + +/* + * Additional private constants not defined in ndk/ui/input.h. + */ +enum { + /* + * Private control to determine when an app is tracking a key sequence. + */ + AKEY_EVENT_FLAG_START_TRACKING = 0x40000000 +}; + +/* + * Maximum number of pointers supported per motion event. + */ +#define MAX_POINTERS 10 + +/* + * Declare a concrete type for the NDK's input event forward declaration. + */ +struct AInputEvent { + virtual ~AInputEvent() { } +}; + +/* + * Declare a concrete type for the NDK's input device forward declaration. + */ +struct AInputDevice { + virtual ~AInputDevice() { } +}; + + +namespace android { + +/* + * Flags that flow alongside events in the input dispatch system to help with certain + * policy decisions such as waking from device sleep. + */ +enum { + /* These flags originate in RawEvents and are generally set in the key map. */ + + POLICY_FLAG_WAKE = 0x00000001, + POLICY_FLAG_WAKE_DROPPED = 0x00000002, + POLICY_FLAG_SHIFT = 0x00000004, + POLICY_FLAG_CAPS_LOCK = 0x00000008, + POLICY_FLAG_ALT = 0x00000010, + POLICY_FLAG_ALT_GR = 0x00000020, + POLICY_FLAG_MENU = 0x00000040, + POLICY_FLAG_LAUNCHER = 0x00000080, + + POLICY_FLAG_RAW_MASK = 0x0000ffff, + + /* These flags are set by the input reader policy as it intercepts each event. */ + + // Indicates that the screen was off when the event was received and the event + // should wake the device. + POLICY_FLAG_WOKE_HERE = 0x10000000, + + // Indicates that the screen was dim when the event was received and the event + // should brighten the device. + POLICY_FLAG_BRIGHT_HERE = 0x20000000, +}; + +/* + * Describes the basic configuration of input devices that are present. + */ +struct InputConfiguration { + enum { + TOUCHSCREEN_UNDEFINED = 0, + TOUCHSCREEN_NOTOUCH = 1, + TOUCHSCREEN_STYLUS = 2, + TOUCHSCREEN_FINGER = 3 + }; + + enum { + KEYBOARD_UNDEFINED = 0, + KEYBOARD_NOKEYS = 1, + KEYBOARD_QWERTY = 2, + KEYBOARD_12KEY = 3 + }; + + enum { + NAVIGATION_UNDEFINED = 0, + NAVIGATION_NONAV = 1, + NAVIGATION_DPAD = 2, + NAVIGATION_TRACKBALL = 3, + NAVIGATION_WHEEL = 4 + }; + + int32_t touchScreen; + int32_t keyboard; + int32_t navigation; +}; + +/* + * Pointer coordinate data. + */ +struct PointerCoords { + float x; + float y; + float pressure; + float size; + float touchMajor; + float touchMinor; + float toolMajor; + float toolMinor; + float orientation; +}; + +/* + * Input events. + */ +class InputEvent : public AInputEvent { +public: + virtual ~InputEvent() { } + + virtual int32_t getType() const = 0; + + inline int32_t getDeviceId() const { return mDeviceId; } + + inline int32_t getSource() const { return mSource; } + +protected: + void initialize(int32_t deviceId, int32_t source); + void initialize(const InputEvent& from); + +private: + int32_t mDeviceId; + int32_t mSource; +}; + +/* + * Key events. + */ +class KeyEvent : public InputEvent { +public: + virtual ~KeyEvent() { } + + virtual int32_t getType() const { return AINPUT_EVENT_TYPE_KEY; } + + inline int32_t getAction() const { return mAction; } + + inline int32_t getFlags() const { return mFlags; } + + inline int32_t getKeyCode() const { return mKeyCode; } + + inline int32_t getScanCode() const { return mScanCode; } + + inline int32_t getMetaState() const { return mMetaState; } + + inline int32_t getRepeatCount() const { return mRepeatCount; } + + inline nsecs_t getDownTime() const { return mDownTime; } + + inline nsecs_t getEventTime() const { return mEventTime; } + + // Return true if this event may have a default action implementation. + static bool hasDefaultAction(int32_t keyCode); + bool hasDefaultAction() const; + + // Return true if this event represents a system key. + static bool isSystemKey(int32_t keyCode); + bool isSystemKey() const; + + void initialize( + int32_t deviceId, + int32_t source, + int32_t action, + int32_t flags, + int32_t keyCode, + int32_t scanCode, + int32_t metaState, + int32_t repeatCount, + nsecs_t downTime, + nsecs_t eventTime); + void initialize(const KeyEvent& from); + +private: + int32_t mAction; + int32_t mFlags; + int32_t mKeyCode; + int32_t mScanCode; + int32_t mMetaState; + int32_t mRepeatCount; + nsecs_t mDownTime; + nsecs_t mEventTime; +}; + +/* + * Motion events. + */ +class MotionEvent : public InputEvent { +public: + virtual ~MotionEvent() { } + + virtual int32_t getType() const { return AINPUT_EVENT_TYPE_MOTION; } + + inline int32_t getAction() const { return mAction; } + + inline int32_t getEdgeFlags() const { return mEdgeFlags; } + + inline int32_t getMetaState() const { return mMetaState; } + + inline float getXOffset() const { return mXOffset; } + + inline float getYOffset() const { return mYOffset; } + + inline float getXPrecision() const { return mXPrecision; } + + inline float getYPrecision() const { return mYPrecision; } + + inline nsecs_t getDownTime() const { return mDownTime; } + + inline size_t getPointerCount() const { return mPointerIds.size(); } + + inline int32_t getPointerId(size_t pointerIndex) const { return mPointerIds[pointerIndex]; } + + inline nsecs_t getEventTime() const { return mSampleEventTimes[getHistorySize()]; } + + inline float getRawX(size_t pointerIndex) const { + return getCurrentPointerCoords(pointerIndex).x; + } + + inline float getRawY(size_t pointerIndex) const { + return getCurrentPointerCoords(pointerIndex).y; + } + + inline float getX(size_t pointerIndex) const { + return getRawX(pointerIndex) + mXOffset; + } + + inline float getY(size_t pointerIndex) const { + return getRawY(pointerIndex) + mYOffset; + } + + inline float getPressure(size_t pointerIndex) const { + return getCurrentPointerCoords(pointerIndex).pressure; + } + + inline float getSize(size_t pointerIndex) const { + return getCurrentPointerCoords(pointerIndex).size; + } + + inline float getTouchMajor(size_t pointerIndex) const { + return getCurrentPointerCoords(pointerIndex).touchMajor; + } + + inline float getTouchMinor(size_t pointerIndex) const { + return getCurrentPointerCoords(pointerIndex).touchMinor; + } + + inline float getToolMajor(size_t pointerIndex) const { + return getCurrentPointerCoords(pointerIndex).toolMajor; + } + + inline float getToolMinor(size_t pointerIndex) const { + return getCurrentPointerCoords(pointerIndex).toolMinor; + } + + inline float getOrientation(size_t pointerIndex) const { + return getCurrentPointerCoords(pointerIndex).orientation; + } + + inline size_t getHistorySize() const { return mSampleEventTimes.size() - 1; } + + inline nsecs_t getHistoricalEventTime(size_t historicalIndex) const { + return mSampleEventTimes[historicalIndex]; + } + + inline float getHistoricalRawX(size_t pointerIndex, size_t historicalIndex) const { + return getHistoricalPointerCoords(pointerIndex, historicalIndex).x; + } + + inline float getHistoricalRawY(size_t pointerIndex, size_t historicalIndex) const { + return getHistoricalPointerCoords(pointerIndex, historicalIndex).y; + } + + inline float getHistoricalX(size_t pointerIndex, size_t historicalIndex) const { + return getHistoricalRawX(pointerIndex, historicalIndex) + mXOffset; + } + + inline float getHistoricalY(size_t pointerIndex, size_t historicalIndex) const { + return getHistoricalRawY(pointerIndex, historicalIndex) + mYOffset; + } + + inline float getHistoricalPressure(size_t pointerIndex, size_t historicalIndex) const { + return getHistoricalPointerCoords(pointerIndex, historicalIndex).pressure; + } + + inline float getHistoricalSize(size_t pointerIndex, size_t historicalIndex) const { + return getHistoricalPointerCoords(pointerIndex, historicalIndex).size; + } + + inline float getHistoricalTouchMajor(size_t pointerIndex, size_t historicalIndex) const { + return getHistoricalPointerCoords(pointerIndex, historicalIndex).touchMajor; + } + + inline float getHistoricalTouchMinor(size_t pointerIndex, size_t historicalIndex) const { + return getHistoricalPointerCoords(pointerIndex, historicalIndex).touchMinor; + } + + inline float getHistoricalToolMajor(size_t pointerIndex, size_t historicalIndex) const { + return getHistoricalPointerCoords(pointerIndex, historicalIndex).toolMajor; + } + + inline float getHistoricalToolMinor(size_t pointerIndex, size_t historicalIndex) const { + return getHistoricalPointerCoords(pointerIndex, historicalIndex).toolMinor; + } + + inline float getHistoricalOrientation(size_t pointerIndex, size_t historicalIndex) const { + return getHistoricalPointerCoords(pointerIndex, historicalIndex).orientation; + } + + void initialize( + int32_t deviceId, + int32_t source, + int32_t action, + int32_t edgeFlags, + int32_t metaState, + float xOffset, + float yOffset, + float xPrecision, + float yPrecision, + nsecs_t downTime, + nsecs_t eventTime, + size_t pointerCount, + const int32_t* pointerIds, + const PointerCoords* pointerCoords); + + void addSample( + nsecs_t eventTime, + const PointerCoords* pointerCoords); + + void offsetLocation(float xOffset, float yOffset); + + // Low-level accessors. + inline const int32_t* getPointerIds() const { return mPointerIds.array(); } + inline const nsecs_t* getSampleEventTimes() const { return mSampleEventTimes.array(); } + inline const PointerCoords* getSamplePointerCoords() const { + return mSamplePointerCoords.array(); + } + +private: + int32_t mAction; + int32_t mEdgeFlags; + int32_t mMetaState; + float mXOffset; + float mYOffset; + float mXPrecision; + float mYPrecision; + nsecs_t mDownTime; + Vector<int32_t> mPointerIds; + Vector<nsecs_t> mSampleEventTimes; + Vector<PointerCoords> mSamplePointerCoords; + + inline const PointerCoords& getCurrentPointerCoords(size_t pointerIndex) const { + return mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex]; + } + + inline const PointerCoords& getHistoricalPointerCoords( + size_t pointerIndex, size_t historicalIndex) const { + return mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex]; + } +}; + +/* + * Input event factory. + */ +class InputEventFactoryInterface { +protected: + virtual ~InputEventFactoryInterface() { } + +public: + InputEventFactoryInterface() { } + + virtual KeyEvent* createKeyEvent() = 0; + virtual MotionEvent* createMotionEvent() = 0; +}; + +/* + * A simple input event factory implementation that uses a single preallocated instance + * of each type of input event that are reused for each request. + */ +class PreallocatedInputEventFactory : public InputEventFactoryInterface { +public: + PreallocatedInputEventFactory() { } + virtual ~PreallocatedInputEventFactory() { } + + virtual KeyEvent* createKeyEvent() { return & mKeyEvent; } + virtual MotionEvent* createMotionEvent() { return & mMotionEvent; } + +private: + KeyEvent mKeyEvent; + MotionEvent mMotionEvent; +}; + +/* + * Describes the characteristics and capabilities of an input device. + */ +class InputDeviceInfo { +public: + InputDeviceInfo(); + InputDeviceInfo(const InputDeviceInfo& other); + ~InputDeviceInfo(); + + struct MotionRange { + float min; + float max; + float flat; + float fuzz; + }; + + void initialize(int32_t id, const String8& name); + + inline int32_t getId() const { return mId; } + inline const String8 getName() const { return mName; } + inline uint32_t getSources() const { return mSources; } + + const MotionRange* getMotionRange(int32_t rangeType) const; + + void addSource(uint32_t source); + void addMotionRange(int32_t rangeType, float min, float max, float flat, float fuzz); + void addMotionRange(int32_t rangeType, const MotionRange& range); + + inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; } + inline int32_t getKeyboardType() const { return mKeyboardType; } + +private: + int32_t mId; + String8 mName; + uint32_t mSources; + int32_t mKeyboardType; + + KeyedVector<int32_t, MotionRange> mMotionRanges; +}; + +/* + * Provides remote access to information about an input device. + * + * Note: This is essentially a wrapper for Binder calls into the Window Manager Service. + */ +class InputDeviceProxy : public RefBase, public AInputDevice { +protected: + InputDeviceProxy(); + virtual ~InputDeviceProxy(); + +public: + static void getDeviceIds(Vector<int32_t>& outIds); + + static sp<InputDeviceProxy> getDevice(int32_t id); + + inline const InputDeviceInfo* getInfo() { return & mInfo; } + + // TODO add hasKeys, keymap, etc... + +private: + InputDeviceInfo mInfo; +}; + + +} // namespace android + +#endif // _UI_INPUT_H diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h new file mode 100644 index 0000000..d3495fe --- /dev/null +++ b/include/ui/InputDispatcher.h @@ -0,0 +1,669 @@ +/* + * 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 _UI_INPUT_DISPATCHER_H +#define _UI_INPUT_DISPATCHER_H + +#include <ui/Input.h> +#include <ui/InputTransport.h> +#include <utils/KeyedVector.h> +#include <utils/Vector.h> +#include <utils/threads.h> +#include <utils/Timers.h> +#include <utils/RefBase.h> +#include <utils/String8.h> +#include <utils/PollLoop.h> +#include <utils/Pool.h> + +#include <stddef.h> +#include <unistd.h> + + +namespace android { + +/* + * Constants used to report the outcome of input event injection. + */ +enum { + /* (INTERNAL USE ONLY) Specifies that injection is pending and its outcome is unknown. */ + INPUT_EVENT_INJECTION_PENDING = -1, + + /* Injection succeeded. */ + INPUT_EVENT_INJECTION_SUCCEEDED = 0, + + /* Injection failed because the injector did not have permission to inject + * into the application with input focus. */ + INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1, + + /* Injection failed because there were no available input targets. */ + INPUT_EVENT_INJECTION_FAILED = 2, + + /* Injection failed due to a timeout. */ + INPUT_EVENT_INJECTION_TIMED_OUT = 3 +}; + +/* + * Constants used to determine the input event injection synchronization mode. + */ +enum { + /* Injection is asynchronous and is assumed always to be successful. */ + INPUT_EVENT_INJECTION_SYNC_NONE = 0, + + /* Waits for previous events to be dispatched so that the input dispatcher can determine + * whether input event injection willbe permitted based on the current input focus. + * Does not wait for the input event to finish processing. */ + INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1, + + /* Waits for the input event to be completely processed. */ + INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED = 2, +}; + + +/* + * An input target specifies how an input event is to be dispatched to a particular window + * including the window's input channel, control flags, a timeout, and an X / Y offset to + * be added to input event coordinates to compensate for the absolute position of the + * window area. + */ +struct InputTarget { + enum { + /* This flag indicates that subsequent event delivery should be held until the + * current event is delivered to this target or a timeout occurs. */ + FLAG_SYNC = 0x01, + + /* This flag indicates that a MotionEvent with ACTION_DOWN falls outside of the area of + * this target and so should instead be delivered as an ACTION_OUTSIDE to this target. */ + FLAG_OUTSIDE = 0x02, + + /* This flag indicates that a KeyEvent or MotionEvent is being canceled. + * In the case of a key event, it should be delivered with KeyEvent.FLAG_CANCELED set. + * In the case of a motion event, it should be delivered as MotionEvent.ACTION_CANCEL. */ + FLAG_CANCEL = 0x04 + }; + + // The input channel to be targeted. + sp<InputChannel> inputChannel; + + // Flags for the input target. + int32_t flags; + + // The timeout for event delivery to this target in nanoseconds. Or -1 if none. + nsecs_t timeout; + + // The x and y offset to add to a MotionEvent as it is delivered. + // (ignored for KeyEvents) + float xOffset, yOffset; +}; + + +/* + * Input dispatcher policy interface. + * + * The input reader policy is used by the input reader to interact with the Window Manager + * and other system components. + * + * The actual implementation is partially supported by callbacks into the DVM + * via JNI. This interface is also mocked in the unit tests. + */ +class InputDispatcherPolicyInterface : public virtual RefBase { +protected: + InputDispatcherPolicyInterface() { } + virtual ~InputDispatcherPolicyInterface() { } + +public: + /* Notifies the system that a configuration change has occurred. */ + virtual void notifyConfigurationChanged(nsecs_t when) = 0; + + /* Notifies the system that an input channel is unrecoverably broken. */ + virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) = 0; + + /* Notifies the system that an input channel is not responding. + * Returns true and a new timeout value if the dispatcher should keep waiting. + * Otherwise returns false. */ + virtual bool notifyInputChannelANR(const sp<InputChannel>& inputChannel, + nsecs_t& outNewTimeout) = 0; + + /* Notifies the system that an input channel recovered from ANR. */ + virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) = 0; + + /* Gets the key repeat timeout or -1 if automatic key repeating is disabled. */ + virtual nsecs_t getKeyRepeatTimeout() = 0; + + /* Waits for key event input targets to become available. + * If the event is being injected, injectorPid and injectorUid should specify the + * process id and used id of the injecting application, otherwise they should both + * be -1. + * Returns one of the INPUT_EVENT_INJECTION_XXX constants. */ + virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags, + int32_t injectorPid, int32_t injectorUid, + Vector<InputTarget>& outTargets) = 0; + + /* Waits for motion event targets to become available. + * If the event is being injected, injectorPid and injectorUid should specify the + * process id and used id of the injecting application, otherwise they should both + * be -1. + * Returns one of the INPUT_EVENT_INJECTION_XXX constants. */ + virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags, + int32_t injectorPid, int32_t injectorUid, + Vector<InputTarget>& outTargets) = 0; +}; + + +/* Notifies the system about input events generated by the input reader. + * The dispatcher is expected to be mostly asynchronous. */ +class InputDispatcherInterface : public virtual RefBase { +protected: + InputDispatcherInterface() { } + virtual ~InputDispatcherInterface() { } + +public: + /* Runs a single iteration of the dispatch loop. + * Nominally processes one queued event, a timeout, or a response from an input consumer. + * + * This method should only be called on the input dispatcher thread. + */ + virtual void dispatchOnce() = 0; + + /* Notifies the dispatcher about new events. + * + * These methods should only be called on the input reader thread. + */ + virtual void notifyConfigurationChanged(nsecs_t eventTime) = 0; + virtual void notifyAppSwitchComing(nsecs_t eventTime) = 0; + virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source, + uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode, + int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0; + virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source, + uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags, + uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords, + float xPrecision, float yPrecision, nsecs_t downTime) = 0; + + /* Injects an input event and optionally waits for sync. + * The synchronization mode determines whether the method blocks while waiting for + * input injection to proceed. + * Returns one of the INPUT_EVENT_INJECTION_XXX constants. + * + * This method may be called on any thread (usually by the input manager). + */ + virtual int32_t injectInputEvent(const InputEvent* event, + int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) = 0; + + /* Preempts input dispatch in progress by making pending synchronous + * dispatches asynchronous instead. This method is generally called during a focus + * transition from one application to the next so as to enable the new application + * to start receiving input as soon as possible without having to wait for the + * old application to finish up. + * + * This method may be called on any thread (usually by the input manager). + */ + virtual void preemptInputDispatch() = 0; + + /* Registers or unregister input channels that may be used as targets for input events. + * + * These methods may be called on any thread (usually by the input manager). + */ + virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) = 0; + virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0; +}; + +/* Dispatches events to input targets. Some functions of the input dispatcher, such as + * identifying input targets, are controlled by a separate policy object. + * + * IMPORTANT INVARIANT: + * Because the policy can potentially block or cause re-entrance into the input dispatcher, + * the input dispatcher never calls into the policy while holding its internal locks. + * The implementation is also carefully designed to recover from scenarios such as an + * input channel becoming unregistered while identifying input targets or processing timeouts. + * + * Methods marked 'Locked' must be called with the lock acquired. + * + * Methods marked 'LockedInterruptible' must be called with the lock acquired but + * may during the course of their execution release the lock, call into the policy, and + * then reacquire the lock. The caller is responsible for recovering gracefully. + * + * A 'LockedInterruptible' method may called a 'Locked' method, but NOT vice-versa. + */ +class InputDispatcher : public InputDispatcherInterface { +protected: + virtual ~InputDispatcher(); + +public: + explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy); + + virtual void dispatchOnce(); + + virtual void notifyConfigurationChanged(nsecs_t eventTime); + virtual void notifyAppSwitchComing(nsecs_t eventTime); + virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source, + uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode, + int32_t scanCode, int32_t metaState, nsecs_t downTime); + virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source, + uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags, + uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords, + float xPrecision, float yPrecision, nsecs_t downTime); + + virtual int32_t injectInputEvent(const InputEvent* event, + int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis); + + virtual void preemptInputDispatch(); + + virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel); + virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel); + +private: + template <typename T> + struct Link { + T* next; + T* prev; + }; + + struct EventEntry : Link<EventEntry> { + enum { + TYPE_SENTINEL, + TYPE_CONFIGURATION_CHANGED, + TYPE_KEY, + TYPE_MOTION + }; + + int32_t refCount; + int32_t type; + nsecs_t eventTime; + + int32_t injectionResult; // initially INPUT_EVENT_INJECTION_PENDING + bool injectionIsAsync; // set to true if injection is not waiting for the result + int32_t injectorPid; // -1 if not injected + int32_t injectorUid; // -1 if not injected + + bool dispatchInProgress; // initially false, set to true while dispatching + int32_t pendingSyncDispatches; // the number of synchronous dispatches in progress + + inline bool isInjected() { return injectorPid >= 0; } + }; + + struct ConfigurationChangedEntry : EventEntry { + }; + + struct KeyEntry : EventEntry { + int32_t deviceId; + int32_t source; + uint32_t policyFlags; + int32_t action; + int32_t flags; + int32_t keyCode; + int32_t scanCode; + int32_t metaState; + int32_t repeatCount; + nsecs_t downTime; + }; + + struct MotionSample { + MotionSample* next; + + nsecs_t eventTime; + PointerCoords pointerCoords[MAX_POINTERS]; + }; + + struct MotionEntry : EventEntry { + int32_t deviceId; + int32_t source; + uint32_t policyFlags; + int32_t action; + int32_t metaState; + int32_t edgeFlags; + float xPrecision; + float yPrecision; + nsecs_t downTime; + uint32_t pointerCount; + int32_t pointerIds[MAX_POINTERS]; + + // Linked list of motion samples associated with this motion event. + MotionSample firstSample; + MotionSample* lastSample; + }; + + // Tracks the progress of dispatching a particular event to a particular connection. + struct DispatchEntry : Link<DispatchEntry> { + EventEntry* eventEntry; // the event to dispatch + int32_t targetFlags; + float xOffset; + float yOffset; + nsecs_t timeout; + + // True if dispatch has started. + bool inProgress; + + // For motion events: + // Pointer to the first motion sample to dispatch in this cycle. + // Usually NULL to indicate that the list of motion samples begins at + // MotionEntry::firstSample. Otherwise, some samples were dispatched in a previous + // cycle and this pointer indicates the location of the first remainining sample + // to dispatch during the current cycle. + MotionSample* headMotionSample; + // Pointer to a motion sample to dispatch in the next cycle if the dispatcher was + // unable to send all motion samples during this cycle. On the next cycle, + // headMotionSample will be initialized to tailMotionSample and tailMotionSample + // will be set to NULL. + MotionSample* tailMotionSample; + + inline bool isSyncTarget() { + return targetFlags & InputTarget::FLAG_SYNC; + } + }; + + // A command entry captures state and behavior for an action to be performed in the + // dispatch loop after the initial processing has taken place. It is essentially + // a kind of continuation used to postpone sensitive policy interactions to a point + // in the dispatch loop where it is safe to release the lock (generally after finishing + // the critical parts of the dispatch cycle). + // + // The special thing about commands is that they can voluntarily release and reacquire + // the dispatcher lock at will. Initially when the command starts running, the + // dispatcher lock is held. However, if the command needs to call into the policy to + // do some work, it can release the lock, do the work, then reacquire the lock again + // before returning. + // + // This mechanism is a bit clunky but it helps to preserve the invariant that the dispatch + // never calls into the policy while holding its lock. + // + // Commands are implicitly 'LockedInterruptible'. + struct CommandEntry; + typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry); + + class Connection; + struct CommandEntry : Link<CommandEntry> { + CommandEntry(); + ~CommandEntry(); + + Command command; + + // parameters for the command (usage varies by command) + sp<Connection> connection; + }; + + // Generic queue implementation. + template <typename T> + struct Queue { + T head; + T tail; + + inline Queue() { + head.prev = NULL; + head.next = & tail; + tail.prev = & head; + tail.next = NULL; + } + + inline bool isEmpty() { + return head.next == & tail; + } + + inline void enqueueAtTail(T* entry) { + T* last = tail.prev; + last->next = entry; + entry->prev = last; + entry->next = & tail; + tail.prev = entry; + } + + inline void enqueueAtHead(T* entry) { + T* first = head.next; + head.next = entry; + entry->prev = & head; + entry->next = first; + first->prev = entry; + } + + inline void dequeue(T* entry) { + entry->prev->next = entry->next; + entry->next->prev = entry->prev; + } + + inline T* dequeueAtHead() { + T* first = head.next; + dequeue(first); + return first; + } + }; + + /* Allocates queue entries and performs reference counting as needed. */ + class Allocator { + public: + Allocator(); + + ConfigurationChangedEntry* obtainConfigurationChangedEntry(nsecs_t eventTime); + KeyEntry* obtainKeyEntry(nsecs_t eventTime, + int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, + int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, + int32_t repeatCount, nsecs_t downTime); + MotionEntry* obtainMotionEntry(nsecs_t eventTime, + int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, + int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision, + nsecs_t downTime, uint32_t pointerCount, + const int32_t* pointerIds, const PointerCoords* pointerCoords); + DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry); + CommandEntry* obtainCommandEntry(Command command); + + void releaseEventEntry(EventEntry* entry); + void releaseConfigurationChangedEntry(ConfigurationChangedEntry* entry); + void releaseKeyEntry(KeyEntry* entry); + void releaseMotionEntry(MotionEntry* entry); + void releaseDispatchEntry(DispatchEntry* entry); + void releaseCommandEntry(CommandEntry* entry); + + void appendMotionSample(MotionEntry* motionEntry, + nsecs_t eventTime, const PointerCoords* pointerCoords); + + private: + Pool<ConfigurationChangedEntry> mConfigurationChangeEntryPool; + Pool<KeyEntry> mKeyEntryPool; + Pool<MotionEntry> mMotionEntryPool; + Pool<MotionSample> mMotionSamplePool; + Pool<DispatchEntry> mDispatchEntryPool; + Pool<CommandEntry> mCommandEntryPool; + + void initializeEventEntry(EventEntry* entry, int32_t type, nsecs_t eventTime); + }; + + /* Manages the dispatch state associated with a single input channel. */ + class Connection : public RefBase { + protected: + virtual ~Connection(); + + public: + enum Status { + // Everything is peachy. + STATUS_NORMAL, + // An unrecoverable communication error has occurred. + STATUS_BROKEN, + // The client is not responding. + STATUS_NOT_RESPONDING, + // The input channel has been unregistered. + STATUS_ZOMBIE + }; + + Status status; + sp<InputChannel> inputChannel; + InputPublisher inputPublisher; + Queue<DispatchEntry> outboundQueue; + nsecs_t nextTimeoutTime; // next timeout time (LONG_LONG_MAX if none) + + nsecs_t lastEventTime; // the time when the event was originally captured + nsecs_t lastDispatchTime; // the time when the last event was dispatched + nsecs_t lastANRTime; // the time when the last ANR was recorded + + explicit Connection(const sp<InputChannel>& inputChannel); + + inline const char* getInputChannelName() const { return inputChannel->getName().string(); } + + const char* getStatusLabel() const; + + // Finds a DispatchEntry in the outbound queue associated with the specified event. + // Returns NULL if not found. + DispatchEntry* findQueuedDispatchEntryForEvent(const EventEntry* eventEntry) const; + + // Determine whether this connection has a pending synchronous dispatch target. + // Since there can only ever be at most one such target at a time, if there is one, + // it must be at the tail because nothing else can be enqueued after it. + inline bool hasPendingSyncTarget() { + return ! outboundQueue.isEmpty() && outboundQueue.tail.prev->isSyncTarget(); + } + + // Gets the time since the current event was originally obtained from the input driver. + inline double getEventLatencyMillis(nsecs_t currentTime) { + return (currentTime - lastEventTime) / 1000000.0; + } + + // Gets the time since the current event entered the outbound dispatch queue. + inline double getDispatchLatencyMillis(nsecs_t currentTime) { + return (currentTime - lastDispatchTime) / 1000000.0; + } + + // Gets the time since the current event ANR was declared, if applicable. + inline double getANRLatencyMillis(nsecs_t currentTime) { + return (currentTime - lastANRTime) / 1000000.0; + } + + status_t initialize(); + + void setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout); + }; + + sp<InputDispatcherPolicyInterface> mPolicy; + + Mutex mLock; + + Allocator mAllocator; + sp<PollLoop> mPollLoop; + + Queue<EventEntry> mInboundQueue; + Queue<CommandEntry> mCommandQueue; + + // All registered connections mapped by receive pipe file descriptor. + KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd; + + // Active connections are connections that have a non-empty outbound queue. + // We don't use a ref-counted pointer here because we explicitly abort connections + // during unregistration which causes the connection's outbound queue to be cleared + // and the connection itself to be deactivated. + Vector<Connection*> mActiveConnections; + + // List of connections that have timed out. Only used by dispatchOnce() + // We don't use a ref-counted pointer here because it is not possible for a connection + // to be unregistered while processing timed out connections since we hold the lock for + // the duration. + Vector<Connection*> mTimedOutConnections; + + // Preallocated key and motion event objects used only to ask the input dispatcher policy + // for the targets of an event that is to be dispatched. + KeyEvent mReusableKeyEvent; + MotionEvent mReusableMotionEvent; + + // The input targets that were most recently identified for dispatch. + // If there is a synchronous event dispatch in progress, the current input targets will + // remain unchanged until the dispatch has completed or been aborted. + Vector<InputTarget> mCurrentInputTargets; + bool mCurrentInputTargetsValid; // false while targets are being recomputed + + // Event injection and synchronization. + Condition mInjectionResultAvailableCondition; + EventEntry* createEntryFromInputEventLocked(const InputEvent* event); + void setInjectionResultLocked(EventEntry* entry, int32_t injectionResult); + + Condition mInjectionSyncFinishedCondition; + void decrementPendingSyncDispatchesLocked(EventEntry* entry); + + // Key repeat tracking. + // XXX Move this up to the input reader instead. + struct KeyRepeatState { + KeyEntry* lastKeyEntry; // or null if no repeat + nsecs_t nextRepeatTime; + } mKeyRepeatState; + + void resetKeyRepeatLocked(); + + // Deferred command processing. + bool runCommandsLockedInterruptible(); + CommandEntry* postCommandLocked(Command command); + + // Process events that have just been dequeued from the head of the input queue. + void processConfigurationChangedLockedInterruptible( + nsecs_t currentTime, ConfigurationChangedEntry* entry); + void processKeyLockedInterruptible( + nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout); + void processKeyRepeatLockedInterruptible( + nsecs_t currentTime, nsecs_t keyRepeatTimeout); + void processMotionLockedInterruptible( + nsecs_t currentTime, MotionEntry* entry); + + // Identify input targets for an event and dispatch to them. + void identifyInputTargetsAndDispatchKeyLockedInterruptible( + nsecs_t currentTime, KeyEntry* entry); + void identifyInputTargetsAndDispatchMotionLockedInterruptible( + nsecs_t currentTime, MotionEntry* entry); + void dispatchEventToCurrentInputTargetsLocked( + nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample); + + // Manage the dispatch cycle for a single connection. + // These methods are deliberately not Interruptible because doing all of the work + // with the mutex held makes it easier to ensure that connection invariants are maintained. + // If needed, the methods post commands to run later once the critical bits are done. + void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, + EventEntry* eventEntry, const InputTarget* inputTarget, + bool resumeWithAppendedMotionSample); + void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection); + void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection); + void timeoutDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection); + void resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime, + const sp<Connection>& connection, nsecs_t newTimeout); + void abortDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, + bool broken); + static bool handleReceiveCallback(int receiveFd, int events, void* data); + + // Add or remove a connection to the mActiveConnections vector. + void activateConnectionLocked(Connection* connection); + void deactivateConnectionLocked(Connection* connection); + + // Interesting events that we might like to log or tell the framework about. + void onDispatchCycleStartedLocked( + nsecs_t currentTime, const sp<Connection>& connection); + void onDispatchCycleFinishedLocked( + nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR); + void onDispatchCycleANRLocked( + nsecs_t currentTime, const sp<Connection>& connection); + void onDispatchCycleBrokenLocked( + nsecs_t currentTime, const sp<Connection>& connection); + + // Outbound policy interactions. + void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry); + void doNotifyInputChannelANRLockedInterruptible(CommandEntry* commandEntry); + void doNotifyInputChannelRecoveredFromANRLockedInterruptible(CommandEntry* commandEntry); +}; + +/* Enqueues and dispatches input events, endlessly. */ +class InputDispatcherThread : public Thread { +public: + explicit InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher); + ~InputDispatcherThread(); + +private: + virtual bool threadLoop(); + + sp<InputDispatcherInterface> mDispatcher; +}; + +} // namespace android + +#endif // _UI_INPUT_DISPATCHER_PRIV_H diff --git a/include/ui/InputManager.h b/include/ui/InputManager.h new file mode 100644 index 0000000..4012c69 --- /dev/null +++ b/include/ui/InputManager.h @@ -0,0 +1,172 @@ +/* + * 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 _UI_INPUT_MANAGER_H +#define _UI_INPUT_MANAGER_H + +/** + * Native input manager. + */ + +#include <ui/EventHub.h> +#include <ui/Input.h> +#include <utils/Errors.h> +#include <utils/Vector.h> +#include <utils/Timers.h> +#include <utils/RefBase.h> +#include <utils/String8.h> + +namespace android { + +class InputChannel; + +class InputReaderInterface; +class InputReaderPolicyInterface; +class InputReaderThread; + +class InputDispatcherInterface; +class InputDispatcherPolicyInterface; +class InputDispatcherThread; + +/* + * The input manager is the core of the system event processing. + * + * The input manager uses two threads. + * + * 1. The InputReaderThread (called "InputReader") reads and preprocesses raw input events, + * applies policy, and posts messages to a queue managed by the DispatcherThread. + * 2. The InputDispatcherThread (called "InputDispatcher") thread waits for new events on the + * queue and asynchronously dispatches them to applications. + * + * By design, the InputReaderThread class and InputDispatcherThread class do not share any + * internal state. Moreover, all communication is done one way from the InputReaderThread + * into the InputDispatcherThread and never the reverse. Both classes may interact with the + * InputDispatchPolicy, however. + * + * The InputManager class never makes any calls into Java itself. Instead, the + * InputDispatchPolicy is responsible for performing all external interactions with the + * system, including calling DVM services. + */ +class InputManagerInterface : public virtual RefBase { +protected: + InputManagerInterface() { } + virtual ~InputManagerInterface() { } + +public: + /* Starts the input manager threads. */ + virtual status_t start() = 0; + + /* Stops the input manager threads and waits for them to exit. */ + virtual status_t stop() = 0; + + /* Registers an input channel prior to using it as the target of an event. */ + virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) = 0; + + /* Unregisters an input channel. */ + virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0; + + /* Injects an input event and optionally waits for sync. + * The synchronization mode determines whether the method blocks while waiting for + * input injection to proceed. + * Returns one of the INPUT_EVENT_INJECTION_XXX constants. + */ + virtual int32_t injectInputEvent(const InputEvent* event, + int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) = 0; + + /* Preempts input dispatch in progress by making pending synchronous + * dispatches asynchronous instead. This method is generally called during a focus + * transition from one application to the next so as to enable the new application + * to start receiving input as soon as possible without having to wait for the + * old application to finish up. + */ + virtual void preemptInputDispatch() = 0; + + /* Gets input device configuration. */ + virtual void getInputConfiguration(InputConfiguration* outConfiguration) = 0; + + /* Gets information about the specified input device. + * Returns OK if the device information was obtained or NAME_NOT_FOUND if there + * was no such device. + */ + virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) = 0; + + /* Gets the list of all registered device ids. */ + virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds) = 0; + + /* Queries current input state. */ + virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, + int32_t scanCode) = 0; + virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, + int32_t keyCode) = 0; + virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, + int32_t sw) = 0; + + /* Determines whether physical keys exist for the given framework-domain key codes. */ + virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, + size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0; +}; + +class InputManager : public InputManagerInterface { +protected: + virtual ~InputManager(); + +public: + InputManager( + const sp<EventHubInterface>& eventHub, + const sp<InputReaderPolicyInterface>& readerPolicy, + const sp<InputDispatcherPolicyInterface>& dispatcherPolicy); + + // (used for testing purposes) + InputManager( + const sp<InputReaderInterface>& reader, + const sp<InputDispatcherInterface>& dispatcher); + + virtual status_t start(); + virtual status_t stop(); + + virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel); + virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel); + + virtual int32_t injectInputEvent(const InputEvent* event, + int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis); + + virtual void preemptInputDispatch(); + + virtual void getInputConfiguration(InputConfiguration* outConfiguration); + virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo); + virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds); + virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, + int32_t scanCode); + virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, + int32_t keyCode); + virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, + int32_t sw); + virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, + size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags); + +private: + sp<InputReaderInterface> mReader; + sp<InputReaderThread> mReaderThread; + + sp<InputDispatcherInterface> mDispatcher; + sp<InputDispatcherThread> mDispatcherThread; + + void initialize(); +}; + +} // namespace android + +#endif // _UI_INPUT_MANAGER_H diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h new file mode 100644 index 0000000..71c6c51 --- /dev/null +++ b/include/ui/InputReader.h @@ -0,0 +1,845 @@ +/* + * 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 _UI_INPUT_READER_H +#define _UI_INPUT_READER_H + +#include <ui/EventHub.h> +#include <ui/Input.h> +#include <ui/InputDispatcher.h> +#include <utils/KeyedVector.h> +#include <utils/threads.h> +#include <utils/Timers.h> +#include <utils/RefBase.h> +#include <utils/String8.h> +#include <utils/BitSet.h> + +#include <stddef.h> +#include <unistd.h> + +namespace android { + +class InputDevice; +class InputMapper; + + +/* + * Input reader policy interface. + * + * The input reader policy is used by the input reader to interact with the Window Manager + * and other system components. + * + * The actual implementation is partially supported by callbacks into the DVM + * via JNI. This interface is also mocked in the unit tests. + */ +class InputReaderPolicyInterface : public virtual RefBase { +protected: + InputReaderPolicyInterface() { } + virtual ~InputReaderPolicyInterface() { } + +public: + /* Display orientations. */ + enum { + ROTATION_0 = 0, + ROTATION_90 = 1, + ROTATION_180 = 2, + ROTATION_270 = 3 + }; + + /* Actions returned by interceptXXX methods. */ + enum { + // The input dispatcher should do nothing and discard the input unless other + // flags are set. + ACTION_NONE = 0, + + // The input dispatcher should dispatch the input to the application. + ACTION_DISPATCH = 0x00000001, + + // The input dispatcher should perform special filtering in preparation for + // a pending app switch. + ACTION_APP_SWITCH_COMING = 0x00000002, + }; + + /* Describes a virtual key. */ + struct VirtualKeyDefinition { + int32_t scanCode; + + // configured position data, specified in display coords + int32_t centerX; + int32_t centerY; + int32_t width; + int32_t height; + }; + + /* Gets information about the display with the specified id. + * Returns true if the display info is available, false otherwise. + */ + virtual bool getDisplayInfo(int32_t displayId, + int32_t* width, int32_t* height, int32_t* orientation) = 0; + + /* Provides feedback for a virtual key down. + */ + virtual void virtualKeyDownFeedback() = 0; + + /* Intercepts a key event. + * The policy can use this method as an opportunity to perform power management functions + * and early event preprocessing such as updating policy flags. + * + * Returns a policy action constant such as ACTION_DISPATCH. + */ + virtual int32_t interceptKey(nsecs_t when, int32_t deviceId, + bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) = 0; + + /* Intercepts a switch event. + * The policy can use this method as an opportunity to perform power management functions + * and early event preprocessing such as updating policy flags. + * + * Switches are not dispatched to applications so this method should + * usually return ACTION_NONE. + */ + virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue, + uint32_t& policyFlags) = 0; + + /* Intercepts a generic touch, trackball or other event. + * The policy can use this method as an opportunity to perform power management functions + * and early event preprocessing such as updating policy flags. + * + * Returns a policy action constant such as ACTION_DISPATCH. + */ + virtual int32_t interceptGeneric(nsecs_t when, uint32_t& policyFlags) = 0; + + /* Determines whether to turn on some hacks we have to improve the touch interaction with a + * certain device whose screen currently is not all that good. + */ + virtual bool filterTouchEvents() = 0; + + /* Determines whether to turn on some hacks to improve touch interaction with another device + * where touch coordinate data can get corrupted. + */ + virtual bool filterJumpyTouchEvents() = 0; + + /* Gets the configured virtual key definitions for an input device. */ + virtual void getVirtualKeyDefinitions(const String8& deviceName, + Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) = 0; + + /* Gets the excluded device names for the platform. */ + virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) = 0; +}; + + +/* Processes raw input events and sends cooked event data to an input dispatcher. */ +class InputReaderInterface : public virtual RefBase { +protected: + InputReaderInterface() { } + virtual ~InputReaderInterface() { } + +public: + /* Runs a single iteration of the processing loop. + * Nominally reads and processes one incoming message from the EventHub. + * + * This method should be called on the input reader thread. + */ + virtual void loopOnce() = 0; + + /* Gets the current input device configuration. + * + * This method may be called on any thread (usually by the input manager). + */ + virtual void getInputConfiguration(InputConfiguration* outConfiguration) = 0; + + /* Gets information about the specified input device. + * Returns OK if the device information was obtained or NAME_NOT_FOUND if there + * was no such device. + * + * This method may be called on any thread (usually by the input manager). + */ + virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) = 0; + + /* Gets the list of all registered device ids. */ + virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds) = 0; + + /* Query current input state. */ + virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, + int32_t scanCode) = 0; + virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, + int32_t keyCode) = 0; + virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, + int32_t sw) = 0; + + /* Determine whether physical keys exist for the given framework-domain key codes. */ + virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, + size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0; +}; + + +/* Internal interface used by individual input devices to access global input device state + * and parameters maintained by the input reader. + */ +class InputReaderContext { +protected: + InputReaderContext() { } + virtual ~InputReaderContext() { } + +public: + virtual void updateGlobalMetaState() = 0; + virtual int32_t getGlobalMetaState() = 0; + + virtual InputReaderPolicyInterface* getPolicy() = 0; + virtual InputDispatcherInterface* getDispatcher() = 0; + virtual EventHubInterface* getEventHub() = 0; +}; + + +/* The input reader reads raw event data from the event hub and processes it into input events + * that it sends to the input dispatcher. Some functions of the input reader, such as early + * event filtering in low power states, are controlled by a separate policy object. + * + * IMPORTANT INVARIANT: + * Because the policy and dispatcher can potentially block or cause re-entrance into + * the input reader, the input reader never calls into other components while holding + * an exclusive internal lock whenever re-entrance can happen. + */ +class InputReader : public InputReaderInterface, private InputReaderContext { +public: + InputReader(const sp<EventHubInterface>& eventHub, + const sp<InputReaderPolicyInterface>& policy, + const sp<InputDispatcherInterface>& dispatcher); + virtual ~InputReader(); + + virtual void loopOnce(); + + virtual void getInputConfiguration(InputConfiguration* outConfiguration); + + virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo); + virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds); + + virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, + int32_t scanCode); + virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, + int32_t keyCode); + virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, + int32_t sw); + + virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, + size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags); + +private: + sp<EventHubInterface> mEventHub; + sp<InputReaderPolicyInterface> mPolicy; + sp<InputDispatcherInterface> mDispatcher; + + virtual InputReaderPolicyInterface* getPolicy() { return mPolicy.get(); } + virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); } + virtual EventHubInterface* getEventHub() { return mEventHub.get(); } + + // This reader/writer lock guards the list of input devices. + // The writer lock must be held whenever the list of input devices is modified + // and then promptly released. + // The reader lock must be held whenever the list of input devices is traversed or an + // input device in the list is accessed. + // This lock only protects the registry and prevents inadvertent deletion of device objects + // that are in use. Individual devices are responsible for guarding their own internal state + // as needed for concurrent operation. + RWLock mDeviceRegistryLock; + KeyedVector<int32_t, InputDevice*> mDevices; + + // low-level input event decoding and device management + void process(const RawEvent* rawEvent); + + void addDevice(nsecs_t when, int32_t deviceId); + void removeDevice(nsecs_t when, int32_t deviceId); + InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes); + void configureExcludedDevices(); + + void consumeEvent(const RawEvent* rawEvent); + + void handleConfigurationChanged(nsecs_t when); + + // state management for all devices + Mutex mStateLock; + + int32_t mGlobalMetaState; + virtual void updateGlobalMetaState(); + virtual int32_t getGlobalMetaState(); + + InputConfiguration mInputConfiguration; + void updateInputConfiguration(); + + // state queries + typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code); + int32_t getState(int32_t deviceId, uint32_t sourceMask, int32_t code, + GetStateFunc getStateFunc); + bool markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes, + const int32_t* keyCodes, uint8_t* outFlags); +}; + + +/* Reads raw events from the event hub and processes them, endlessly. */ +class InputReaderThread : public Thread { +public: + InputReaderThread(const sp<InputReaderInterface>& reader); + virtual ~InputReaderThread(); + +private: + sp<InputReaderInterface> mReader; + + virtual bool threadLoop(); +}; + + +/* Represents the state of a single input device. */ +class InputDevice { +public: + InputDevice(InputReaderContext* context, int32_t id, const String8& name); + ~InputDevice(); + + inline InputReaderContext* getContext() { return mContext; } + inline int32_t getId() { return mId; } + inline const String8& getName() { return mName; } + inline uint32_t getSources() { return mSources; } + + inline bool isIgnored() { return mMappers.isEmpty(); } + + void addMapper(InputMapper* mapper); + void configure(); + void reset(); + void process(const RawEvent* rawEvent); + + void getDeviceInfo(InputDeviceInfo* outDeviceInfo); + int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode); + int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); + int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode); + bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, + const int32_t* keyCodes, uint8_t* outFlags); + + int32_t getMetaState(); + +private: + InputReaderContext* mContext; + int32_t mId; + + Vector<InputMapper*> mMappers; + + String8 mName; + uint32_t mSources; + + typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code); + int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc); +}; + + +/* An input mapper transforms raw input events into cooked event data. + * A single input device can have multiple associated input mappers in order to interpret + * different classes of events. + */ +class InputMapper { +public: + InputMapper(InputDevice* device); + virtual ~InputMapper(); + + inline InputDevice* getDevice() { return mDevice; } + inline int32_t getDeviceId() { return mDevice->getId(); } + inline const String8 getDeviceName() { return mDevice->getName(); } + inline InputReaderContext* getContext() { return mContext; } + inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); } + inline InputDispatcherInterface* getDispatcher() { return mContext->getDispatcher(); } + inline EventHubInterface* getEventHub() { return mContext->getEventHub(); } + + virtual uint32_t getSources() = 0; + virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); + virtual void configure(); + virtual void reset(); + virtual void process(const RawEvent* rawEvent) = 0; + + virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode); + virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); + virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode); + virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, + const int32_t* keyCodes, uint8_t* outFlags); + + virtual int32_t getMetaState(); + +protected: + InputDevice* mDevice; + InputReaderContext* mContext; + + bool applyStandardPolicyActions(nsecs_t when, int32_t policyActions); +}; + + +class SwitchInputMapper : public InputMapper { +public: + SwitchInputMapper(InputDevice* device); + virtual ~SwitchInputMapper(); + + virtual uint32_t getSources(); + virtual void process(const RawEvent* rawEvent); + + virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode); + +private: + void processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue); +}; + + +class KeyboardInputMapper : public InputMapper { +public: + KeyboardInputMapper(InputDevice* device, int32_t associatedDisplayId, uint32_t sources, + int32_t keyboardType); + virtual ~KeyboardInputMapper(); + + virtual uint32_t getSources(); + virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); + virtual void reset(); + virtual void process(const RawEvent* rawEvent); + + virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode); + virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); + virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, + const int32_t* keyCodes, uint8_t* outFlags); + + virtual int32_t getMetaState(); + +private: + Mutex mLock; + + struct KeyDown { + int32_t keyCode; + int32_t scanCode; + }; + + int32_t mAssociatedDisplayId; + uint32_t mSources; + int32_t mKeyboardType; + + struct LockedState { + Vector<KeyDown> keyDowns; // keys that are down + int32_t metaState; + nsecs_t downTime; // time of most recent key down + } mLocked; + + void initializeLocked(); + + bool isKeyboardOrGamepadKey(int32_t scanCode); + + void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode, + uint32_t policyFlags); + void applyPolicyAndDispatch(nsecs_t when, uint32_t policyFlags, + bool down, int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime); + + ssize_t findKeyDownLocked(int32_t scanCode); +}; + + +class TrackballInputMapper : public InputMapper { +public: + TrackballInputMapper(InputDevice* device, int32_t associatedDisplayId); + virtual ~TrackballInputMapper(); + + virtual uint32_t getSources(); + virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); + virtual void reset(); + virtual void process(const RawEvent* rawEvent); + + virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); + +private: + // Amount that trackball needs to move in order to generate a key event. + static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6; + + Mutex mLock; + + int32_t mAssociatedDisplayId; + + struct Accumulator { + enum { + FIELD_BTN_MOUSE = 1, + FIELD_REL_X = 2, + FIELD_REL_Y = 4 + }; + + uint32_t fields; + + bool btnMouse; + int32_t relX; + int32_t relY; + + inline void clear() { + fields = 0; + } + + inline bool isDirty() { + return fields != 0; + } + } mAccumulator; + + float mXScale; + float mYScale; + float mXPrecision; + float mYPrecision; + + struct LockedState { + bool down; + nsecs_t downTime; + } mLocked; + + void initializeLocked(); + + void sync(nsecs_t when); + void applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction, + PointerCoords* pointerCoords, nsecs_t downTime); +}; + + +class TouchInputMapper : public InputMapper { +public: + TouchInputMapper(InputDevice* device, int32_t associatedDisplayId); + virtual ~TouchInputMapper(); + + virtual uint32_t getSources(); + virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); + virtual void configure(); + virtual void reset(); + + virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode); + virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode); + virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, + const int32_t* keyCodes, uint8_t* outFlags); + +protected: + /* Maximum pointer id value supported. + * (This is limited by our use of BitSet32 to track pointer assignments.) */ + static const uint32_t MAX_POINTER_ID = 31; + + Mutex mLock; + + struct VirtualKey { + int32_t keyCode; + int32_t scanCode; + uint32_t flags; + + // computed hit box, specified in touch screen coords based on known display size + int32_t hitLeft; + int32_t hitTop; + int32_t hitRight; + int32_t hitBottom; + + inline bool isHit(int32_t x, int32_t y) const { + return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom; + } + }; + + struct PointerData { + uint32_t id; + int32_t x; + int32_t y; + int32_t pressure; + int32_t size; + int32_t touchMajor; + int32_t touchMinor; + int32_t toolMajor; + int32_t toolMinor; + int32_t orientation; + }; + + struct TouchData { + uint32_t pointerCount; + PointerData pointers[MAX_POINTERS]; + BitSet32 idBits; + uint32_t idToIndex[MAX_POINTER_ID + 1]; + + void copyFrom(const TouchData& other) { + pointerCount = other.pointerCount; + idBits = other.idBits; + + for (uint32_t i = 0; i < pointerCount; i++) { + pointers[i] = other.pointers[i]; + + int id = pointers[i].id; + idToIndex[id] = other.idToIndex[id]; + } + } + + inline void clear() { + pointerCount = 0; + idBits.clear(); + } + }; + + int32_t mAssociatedDisplayId; + + // Immutable configuration parameters. + struct Parameters { + bool useBadTouchFilter; + bool useJumpyTouchFilter; + bool useAveragingTouchFilter; + } mParameters; + + // Raw axis information. + struct Axes { + RawAbsoluteAxisInfo x; + RawAbsoluteAxisInfo y; + RawAbsoluteAxisInfo pressure; + RawAbsoluteAxisInfo size; + RawAbsoluteAxisInfo touchMajor; + RawAbsoluteAxisInfo touchMinor; + RawAbsoluteAxisInfo toolMajor; + RawAbsoluteAxisInfo toolMinor; + RawAbsoluteAxisInfo orientation; + } mAxes; + + // Current and previous touch sample data. + TouchData mCurrentTouch; + TouchData mLastTouch; + + // The time the primary pointer last went down. + nsecs_t mDownTime; + + struct LockedState { + Vector<VirtualKey> virtualKeys; + + // The surface orientation and width and height set by configureSurfaceLocked(). + int32_t surfaceOrientation; + int32_t surfaceWidth, surfaceHeight; + + // Translation and scaling factors, orientation-independent. + int32_t xOrigin; + float xScale; + float xPrecision; + + int32_t yOrigin; + float yScale; + float yPrecision; + + int32_t pressureOrigin; + float pressureScale; + + int32_t sizeOrigin; + float sizeScale; + + float orientationScale; + + // Oriented motion ranges for input device info. + struct OrientedRanges { + InputDeviceInfo::MotionRange x; + InputDeviceInfo::MotionRange y; + InputDeviceInfo::MotionRange pressure; + InputDeviceInfo::MotionRange size; + InputDeviceInfo::MotionRange touchMajor; + InputDeviceInfo::MotionRange touchMinor; + InputDeviceInfo::MotionRange toolMajor; + InputDeviceInfo::MotionRange toolMinor; + InputDeviceInfo::MotionRange orientation; + } orientedRanges; + + // Oriented dimensions and precision. + float orientedSurfaceWidth, orientedSurfaceHeight; + float orientedXPrecision, orientedYPrecision; + + struct CurrentVirtualKeyState { + bool down; + nsecs_t downTime; + int32_t keyCode; + int32_t scanCode; + } currentVirtualKey; + } mLocked; + + virtual void configureAxes(); + virtual bool configureSurfaceLocked(); + virtual void configureVirtualKeysLocked(); + + enum TouchResult { + // Dispatch the touch normally. + DISPATCH_TOUCH, + // Do not dispatch the touch, but keep tracking the current stroke. + SKIP_TOUCH, + // Do not dispatch the touch, and drop all information associated with the current stoke + // so the next movement will appear as a new down. + DROP_STROKE + }; + + void syncTouch(nsecs_t when, bool havePointerIds); + +private: + /* Maximum number of historical samples to average. */ + static const uint32_t AVERAGING_HISTORY_SIZE = 5; + + /* Slop distance for jumpy pointer detection. + * The vertical range of the screen divided by this is our epsilon value. */ + static const uint32_t JUMPY_EPSILON_DIVISOR = 212; + + /* Number of jumpy points to drop for touchscreens that need it. */ + static const uint32_t JUMPY_TRANSITION_DROPS = 3; + static const uint32_t JUMPY_DROP_LIMIT = 3; + + /* Maximum squared distance for averaging. + * If moving farther than this, turn of averaging to avoid lag in response. */ + static const uint64_t AVERAGING_DISTANCE_LIMIT = 75 * 75; + + struct AveragingTouchFilterState { + // Individual history tracks are stored by pointer id + uint32_t historyStart[MAX_POINTERS]; + uint32_t historyEnd[MAX_POINTERS]; + struct { + struct { + int32_t x; + int32_t y; + int32_t pressure; + } pointers[MAX_POINTERS]; + } historyData[AVERAGING_HISTORY_SIZE]; + } mAveragingTouchFilter; + + struct JumpTouchFilterState { + uint32_t jumpyPointsDropped; + } mJumpyTouchFilter; + + struct PointerDistanceHeapElement { + uint32_t currentPointerIndex : 8; + uint32_t lastPointerIndex : 8; + uint64_t distance : 48; // squared distance + }; + + void initializeLocked(); + + TouchResult consumeOffScreenTouches(nsecs_t when, uint32_t policyFlags); + void dispatchTouches(nsecs_t when, uint32_t policyFlags); + void dispatchTouch(nsecs_t when, uint32_t policyFlags, TouchData* touch, + BitSet32 idBits, uint32_t changedId, int32_t motionEventAction); + + void applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags, + int32_t keyEventAction, int32_t keyEventFlags, + int32_t keyCode, int32_t scanCode, nsecs_t downTime); + + bool isPointInsideSurfaceLocked(int32_t x, int32_t y); + const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y); + + bool applyBadTouchFilter(); + bool applyJumpyTouchFilter(); + void applyAveragingTouchFilter(); + void calculatePointerIds(); +}; + + +class SingleTouchInputMapper : public TouchInputMapper { +public: + SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId); + virtual ~SingleTouchInputMapper(); + + virtual void reset(); + virtual void process(const RawEvent* rawEvent); + +protected: + virtual void configureAxes(); + +private: + struct Accumulator { + enum { + FIELD_BTN_TOUCH = 1, + FIELD_ABS_X = 2, + FIELD_ABS_Y = 4, + FIELD_ABS_PRESSURE = 8, + FIELD_ABS_TOOL_WIDTH = 16 + }; + + uint32_t fields; + + bool btnTouch; + int32_t absX; + int32_t absY; + int32_t absPressure; + int32_t absToolWidth; + + inline void clear() { + fields = 0; + } + + inline bool isDirty() { + return fields != 0; + } + } mAccumulator; + + bool mDown; + int32_t mX; + int32_t mY; + int32_t mPressure; + int32_t mSize; + + void initialize(); + + void sync(nsecs_t when); +}; + + +class MultiTouchInputMapper : public TouchInputMapper { +public: + MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId); + virtual ~MultiTouchInputMapper(); + + virtual void reset(); + virtual void process(const RawEvent* rawEvent); + +protected: + virtual void configureAxes(); + +private: + struct Accumulator { + enum { + FIELD_ABS_MT_POSITION_X = 1, + FIELD_ABS_MT_POSITION_Y = 2, + FIELD_ABS_MT_TOUCH_MAJOR = 4, + FIELD_ABS_MT_TOUCH_MINOR = 8, + FIELD_ABS_MT_WIDTH_MAJOR = 16, + FIELD_ABS_MT_WIDTH_MINOR = 32, + FIELD_ABS_MT_ORIENTATION = 64, + FIELD_ABS_MT_TRACKING_ID = 128 + }; + + uint32_t pointerCount; + struct Pointer { + uint32_t fields; + + int32_t absMTPositionX; + int32_t absMTPositionY; + int32_t absMTTouchMajor; + int32_t absMTTouchMinor; + int32_t absMTWidthMajor; + int32_t absMTWidthMinor; + int32_t absMTOrientation; + int32_t absMTTrackingId; + + inline void clear() { + fields = 0; + } + } pointers[MAX_POINTERS + 1]; // + 1 to remove the need for extra range checks + + inline void clear() { + pointerCount = 0; + pointers[0].clear(); + } + + inline bool isDirty() { + return pointerCount != 0; + } + } mAccumulator; + + void initialize(); + + void sync(nsecs_t when); +}; + +} // namespace android + +#endif // _UI_INPUT_READER_H diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h new file mode 100644 index 0000000..31ec701 --- /dev/null +++ b/include/ui/InputTransport.h @@ -0,0 +1,334 @@ +/* + * 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 _UI_INPUT_TRANSPORT_H +#define _UI_INPUT_TRANSPORT_H + +/** + * Native input transport. + * + * Uses anonymous shared memory as a whiteboard for sending input events from an + * InputPublisher to an InputConsumer and ensuring appropriate synchronization. + * One interesting feature is that published events can be updated in place as long as they + * have not yet been consumed. + * + * The InputPublisher and InputConsumer only take care of transferring event data + * over an InputChannel and sending synchronization signals. The InputDispatcher and InputQueue + * build on these abstractions to add multiplexing and queueing. + */ + +#include <semaphore.h> +#include <ui/Input.h> +#include <utils/Errors.h> +#include <utils/PollLoop.h> +#include <utils/Timers.h> +#include <utils/RefBase.h> +#include <utils/String8.h> + +namespace android { + +/* + * An input channel consists of a shared memory buffer and a pair of pipes + * used to send input messages from an InputPublisher to an InputConsumer + * across processes. Each channel has a descriptive name for debugging purposes. + * + * Each endpoint has its own InputChannel object that specifies its own file descriptors. + * + * The input channel is closed when all references to it are released. + */ +class InputChannel : public RefBase { +protected: + virtual ~InputChannel(); + +public: + InputChannel(const String8& name, int32_t ashmemFd, int32_t receivePipeFd, + int32_t sendPipeFd); + + /* Creates a pair of input channels and their underlying shared memory buffers + * and pipes. + * + * Returns OK on success. + */ + static status_t openInputChannelPair(const String8& name, + sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel); + + inline String8 getName() const { return mName; } + inline int32_t getAshmemFd() const { return mAshmemFd; } + inline int32_t getReceivePipeFd() const { return mReceivePipeFd; } + inline int32_t getSendPipeFd() const { return mSendPipeFd; } + + /* Sends a signal to the other endpoint. + * + * Returns OK on success. + * Returns DEAD_OBJECT if the channel's peer has been closed. + * Other errors probably indicate that the channel is broken. + */ + status_t sendSignal(char signal); + + /* Receives a signal send by the other endpoint. + * (Should only call this after poll() indicates that the receivePipeFd has available input.) + * + * Returns OK on success. + * Returns WOULD_BLOCK if there is no signal present. + * Returns DEAD_OBJECT if the channel's peer has been closed. + * Other errors probably indicate that the channel is broken. + */ + status_t receiveSignal(char* outSignal); + +private: + String8 mName; + int32_t mAshmemFd; + int32_t mReceivePipeFd; + int32_t mSendPipeFd; +}; + +/* + * Private intermediate representation of input events as messages written into an + * ashmem buffer. + */ +struct InputMessage { + /* Semaphore count is set to 1 when the message is published. + * It becomes 0 transiently while the publisher updates the message. + * It becomes 0 permanently when the consumer consumes the message. + */ + sem_t semaphore; + + /* Initialized to false by the publisher. + * Set to true by the consumer when it consumes the message. + */ + bool consumed; + + int32_t type; + + struct SampleData { + nsecs_t eventTime; + PointerCoords coords[0]; // variable length + }; + + int32_t deviceId; + int32_t source; + + union { + struct { + int32_t action; + int32_t flags; + int32_t keyCode; + int32_t scanCode; + int32_t metaState; + int32_t repeatCount; + nsecs_t downTime; + nsecs_t eventTime; + } key; + + struct { + int32_t action; + int32_t metaState; + int32_t edgeFlags; + nsecs_t downTime; + float xOffset; + float yOffset; + float xPrecision; + float yPrecision; + size_t pointerCount; + int32_t pointerIds[MAX_POINTERS]; + size_t sampleCount; + SampleData sampleData[0]; // variable length + } motion; + }; + + /* Gets the number of bytes to add to step to the next SampleData object in a motion + * event message for a given number of pointers. + */ + static inline size_t sampleDataStride(size_t pointerCount) { + return sizeof(InputMessage::SampleData) + pointerCount * sizeof(PointerCoords); + } + + /* Adds the SampleData stride to the given pointer. */ + static inline SampleData* sampleDataPtrIncrement(SampleData* ptr, size_t stride) { + return reinterpret_cast<InputMessage::SampleData*>(reinterpret_cast<char*>(ptr) + stride); + } +}; + +/* + * Publishes input events to an anonymous shared memory buffer. + * Uses atomic operations to coordinate shared access with a single concurrent consumer. + */ +class InputPublisher { +public: + /* Creates a publisher associated with an input channel. */ + explicit InputPublisher(const sp<InputChannel>& channel); + + /* Destroys the publisher and releases its input channel. */ + ~InputPublisher(); + + /* Gets the underlying input channel. */ + inline sp<InputChannel> getChannel() { return mChannel; } + + /* Prepares the publisher for use. Must be called before it is used. + * Returns OK on success. + * + * This method implicitly calls reset(). */ + status_t initialize(); + + /* Resets the publisher to its initial state and unpins its ashmem buffer. + * Returns OK on success. + * + * Should be called after an event has been consumed to release resources used by the + * publisher until the next event is ready to be published. + */ + status_t reset(); + + /* Publishes a key event to the ashmem buffer. + * + * Returns OK on success. + * Returns INVALID_OPERATION if the publisher has not been reset. + */ + status_t publishKeyEvent( + int32_t deviceId, + int32_t source, + int32_t action, + int32_t flags, + int32_t keyCode, + int32_t scanCode, + int32_t metaState, + int32_t repeatCount, + nsecs_t downTime, + nsecs_t eventTime); + + /* Publishes a motion event to the ashmem buffer. + * + * Returns OK on success. + * Returns INVALID_OPERATION if the publisher has not been reset. + * Returns BAD_VALUE if pointerCount is less than 1 or greater than MAX_POINTERS. + */ + status_t publishMotionEvent( + int32_t deviceId, + int32_t source, + int32_t action, + int32_t edgeFlags, + int32_t metaState, + float xOffset, + float yOffset, + float xPrecision, + float yPrecision, + nsecs_t downTime, + nsecs_t eventTime, + size_t pointerCount, + const int32_t* pointerIds, + const PointerCoords* pointerCoords); + + /* Appends a motion sample to a motion event unless already consumed. + * + * Returns OK on success. + * Returns INVALID_OPERATION if the current event is not a AMOTION_EVENT_ACTION_MOVE event. + * Returns FAILED_TRANSACTION if the current event has already been consumed. + * Returns NO_MEMORY if the buffer is full and no additional samples can be added. + */ + status_t appendMotionSample( + nsecs_t eventTime, + const PointerCoords* pointerCoords); + + /* Sends a dispatch signal to the consumer to inform it that a new message is available. + * + * Returns OK on success. + * Errors probably indicate that the channel is broken. + */ + status_t sendDispatchSignal(); + + /* Receives the finished signal from the consumer in reply to the original dispatch signal. + * + * Returns OK on success. + * Returns WOULD_BLOCK if there is no signal present. + * Other errors probably indicate that the channel is broken. + */ + status_t receiveFinishedSignal(); + +private: + sp<InputChannel> mChannel; + + size_t mAshmemSize; + InputMessage* mSharedMessage; + bool mPinned; + bool mSemaphoreInitialized; + bool mWasDispatched; + + size_t mMotionEventPointerCount; + InputMessage::SampleData* mMotionEventSampleDataTail; + size_t mMotionEventSampleDataStride; + + status_t publishInputEvent( + int32_t type, + int32_t deviceId, + int32_t source); +}; + +/* + * Consumes input events from an anonymous shared memory buffer. + * Uses atomic operations to coordinate shared access with a single concurrent publisher. + */ +class InputConsumer { +public: + /* Creates a consumer associated with an input channel. */ + explicit InputConsumer(const sp<InputChannel>& channel); + + /* Destroys the consumer and releases its input channel. */ + ~InputConsumer(); + + /* Gets the underlying input channel. */ + inline sp<InputChannel> getChannel() { return mChannel; } + + /* Prepares the consumer for use. Must be called before it is used. */ + status_t initialize(); + + /* Consumes the input event in the buffer and copies its contents into + * an InputEvent object created using the specified factory. + * This operation will block if the publisher is updating the event. + * + * Returns OK on success. + * Returns INVALID_OPERATION if there is no currently published event. + * Returns NO_MEMORY if the event could not be created. + */ + status_t consume(InputEventFactoryInterface* factory, InputEvent** outEvent); + + /* Sends a finished signal to the publisher to inform it that the current message is + * finished processing. + * + * Returns OK on success. + * Errors probably indicate that the channel is broken. + */ + status_t sendFinishedSignal(); + + /* Receives the dispatched signal from the publisher. + * + * Returns OK on success. + * Returns WOULD_BLOCK if there is no signal present. + * Other errors probably indicate that the channel is broken. + */ + status_t receiveDispatchSignal(); + +private: + sp<InputChannel> mChannel; + + size_t mAshmemSize; + InputMessage* mSharedMessage; + + void populateKeyEvent(KeyEvent* keyEvent) const; + void populateMotionEvent(MotionEvent* motionEvent) const; +}; + +} // namespace android + +#endif // _UI_INPUT_TRANSPORT_H diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h index 571e47b..c8d6ffc 100644..100755 --- a/include/ui/KeycodeLabels.h +++ b/include/ui/KeycodeLabels.h @@ -17,6 +17,8 @@ #ifndef _UI_KEYCODE_LABELS_H #define _UI_KEYCODE_LABELS_H +#include <android/keycodes.h> + struct KeycodeLabel { const char *literal; int value; @@ -114,113 +116,32 @@ static const KeycodeLabel KEYCODES[] = { { "MEDIA_REWIND", 89 }, { "MEDIA_FAST_FORWARD", 90 }, { "MUTE", 91 }, + { "PAGE_UP", 92 }, + { "PAGE_DOWN", 93 }, + { "PICTSYMBOLS", 94 }, + { "SWITCH_CHARSET", 95 }, + { "BUTTON_A", 96 }, + { "BUTTON_B", 97 }, + { "BUTTON_C", 98 }, + { "BUTTON_X", 99 }, + { "BUTTON_Y", 100 }, + { "BUTTON_Z", 101 }, + { "BUTTON_L1", 102 }, + { "BUTTON_R1", 103 }, + { "BUTTON_L2", 104 }, + { "BUTTON_R2", 105 }, + { "BUTTON_THUMBL", 106 }, + { "BUTTON_THUMBR", 107 }, + { "BUTTON_START", 108 }, + { "BUTTON_SELECT", 109 }, + { "BUTTON_MODE", 110 }, - // NOTE: If you add a new keycode here you must also add it to: - // (enum KeyCode, in this file) - // frameworks/base/core/java/android/view/KeyEvent.java - // tools/puppet_master/PuppetMaster.nav_keys.py - // frameworks/base/core/res/res/values/attrs.xml + // NOTE: If you add a new keycode here you must also add it to several other files. + // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list. { NULL, 0 } }; -// These constants need to match the above mappings. -typedef enum KeyCode { - kKeyCodeUnknown = 0, - - kKeyCodeSoftLeft = 1, - kKeyCodeSoftRight = 2, - kKeyCodeHome = 3, - kKeyCodeBack = 4, - kKeyCodeCall = 5, - kKeyCodeEndCall = 6, - kKeyCode0 = 7, - kKeyCode1 = 8, - kKeyCode2 = 9, - kKeyCode3 = 10, - kKeyCode4 = 11, - kKeyCode5 = 12, - kKeyCode6 = 13, - kKeyCode7 = 14, - kKeyCode8 = 15, - kKeyCode9 = 16, - kKeyCodeStar = 17, - kKeyCodePound = 18, - kKeyCodeDpadUp = 19, - kKeyCodeDpadDown = 20, - kKeyCodeDpadLeft = 21, - kKeyCodeDpadRight = 22, - kKeyCodeDpadCenter = 23, - kKeyCodeVolumeUp = 24, - kKeyCodeVolumeDown = 25, - kKeyCodePower = 26, - kKeyCodeCamera = 27, - kKeyCodeClear = 28, - kKeyCodeA = 29, - kKeyCodeB = 30, - kKeyCodeC = 31, - kKeyCodeD = 32, - kKeyCodeE = 33, - kKeyCodeF = 34, - kKeyCodeG = 35, - kKeyCodeH = 36, - kKeyCodeI = 37, - kKeyCodeJ = 38, - kKeyCodeK = 39, - kKeyCodeL = 40, - kKeyCodeM = 41, - kKeyCodeN = 42, - kKeyCodeO = 43, - kKeyCodeP = 44, - kKeyCodeQ = 45, - kKeyCodeR = 46, - kKeyCodeS = 47, - kKeyCodeT = 48, - kKeyCodeU = 49, - kKeyCodeV = 50, - kKeyCodeW = 51, - kKeyCodeX = 52, - kKeyCodeY = 53, - kKeyCodeZ = 54, - kKeyCodeComma = 55, - kKeyCodePeriod = 56, - kKeyCodeAltLeft = 57, - kKeyCodeAltRight = 58, - kKeyCodeShiftLeft = 59, - kKeyCodeShiftRight = 60, - kKeyCodeTab = 61, - kKeyCodeSpace = 62, - kKeyCodeSym = 63, - kKeyCodeExplorer = 64, - kKeyCodeEnvelope = 65, - kKeyCodeNewline = 66, - kKeyCodeDel = 67, - kKeyCodeGrave = 68, - kKeyCodeMinus = 69, - kKeyCodeEquals = 70, - kKeyCodeLeftBracket = 71, - kKeyCodeRightBracket = 72, - kKeyCodeBackslash = 73, - kKeyCodeSemicolon = 74, - kKeyCodeApostrophe = 75, - kKeyCodeSlash = 76, - kKeyCodeAt = 77, - kKeyCodeNum = 78, - kKeyCodeHeadSetHook = 79, - kKeyCodeFocus = 80, - kKeyCodePlus = 81, - kKeyCodeMenu = 82, - kKeyCodeNotification = 83, - kKeyCodeSearch = 84, - kKeyCodePlayPause = 85, - kKeyCodeStop = 86, - kKeyCodeNextSong = 87, - kKeyCodePreviousSong = 88, - kKeyCodeRewind = 89, - kKeyCodeForward = 90, - kKeyCodeMute = 91 -} KeyCode; - static const KeycodeLabel FLAGS[] = { { "WAKE", 0x00000001 }, { "WAKE_DROPPED", 0x00000002 }, diff --git a/include/ui/Rect.h b/include/ui/Rect.h index a213c09..4e65a2d 100644 --- a/include/ui/Rect.h +++ b/include/ui/Rect.h @@ -20,31 +20,28 @@ #include <utils/TypeHelpers.h> #include <ui/Point.h> +#include <android/rect.h> + namespace android { -class Rect +class Rect : public ARect { public: - int left; - int top; - int right; - int bottom; - - typedef int value_type; + typedef int32_t value_type; // we don't provide copy-ctor and operator= on purpose // because we want the compiler generated versions inline Rect() { } - inline Rect(int w, int h) - : left(0), top(0), right(w), bottom(h) { + inline Rect(int32_t w, int32_t h) { + left = top = 0; right = w; bottom = h; } - inline Rect(int l, int t, int r, int b) - : left(l), top(t), right(r), bottom(b) { + inline Rect(int32_t l, int32_t t, int32_t r, int32_t b) { + left = l; top = t; right = r; bottom = b; } - inline Rect(const Point& lt, const Point& rb) - : left(lt.x), top(lt.y), right(rb.x), bottom(rb.y) { + inline Rect(const Point& lt, const Point& rb) { + left = lt.x; top = lt.y; right = rb.x; bottom = rb.y; } void makeInvalid(); @@ -68,12 +65,12 @@ public: } // rectangle's width - inline int width() const { + inline int32_t width() const { return right-left; } // rectangle's height - inline int height() const { + inline int32_t height() const { return bottom-top; } @@ -136,12 +133,12 @@ public: const Rect operator + (const Point& rhs) const; const Rect operator - (const Point& rhs) const; - void translate(int dx, int dy) { // legacy, don't use. + void translate(int32_t dx, int32_t dy) { // legacy, don't use. offsetBy(dx, dy); } - Rect& offsetTo(int x, int y); - Rect& offsetBy(int x, int y); + Rect& offsetTo(int32_t x, int32_t y); + Rect& offsetBy(int32_t x, int32_t y); bool intersect(const Rect& with, Rect* result) const; }; diff --git a/include/ui/android_native_buffer.h b/include/ui/android_native_buffer.h index 9c92af8..402843e 100644 --- a/include/ui/android_native_buffer.h +++ b/include/ui/android_native_buffer.h @@ -33,6 +33,15 @@ typedef struct android_native_buffer_t common.version = sizeof(android_native_buffer_t); memset(common.reserved, 0, sizeof(common.reserved)); } + + // Implement the methods that sp<android_native_buffer_t> expects so that it + // can be used to automatically refcount android_native_buffer_t'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; diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h index 773fd93..ca89b06 100644 --- a/include/ui/egl/android_natives.h +++ b/include/ui/egl/android_natives.h @@ -22,6 +22,8 @@ #include <hardware/gralloc.h> +#include <android/native_window.h> + #ifdef __cplusplus extern "C" { #endif @@ -41,6 +43,14 @@ extern "C" { struct android_native_buffer_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 @@ -63,15 +73,18 @@ typedef struct android_native_base_t /* attributes queriable with query() */ enum { NATIVE_WINDOW_WIDTH = 0, - NATIVE_WINDOW_HEIGHT = 1, - NATIVE_WINDOW_FORMAT = 2, + NATIVE_WINDOW_HEIGHT, + NATIVE_WINDOW_FORMAT, }; /* valid operations for the (*perform)() hook */ enum { NATIVE_WINDOW_SET_USAGE = 0, - NATIVE_WINDOW_CONNECT = 1, - NATIVE_WINDOW_DISCONNECT = 2 + NATIVE_WINDOW_CONNECT, + NATIVE_WINDOW_DISCONNECT, + NATIVE_WINDOW_SET_CROP, + NATIVE_WINDOW_SET_BUFFER_COUNT, + NATIVE_WINDOW_SET_BUFFERS_GEOMETRY, }; /* parameter for NATIVE_WINDOW_[DIS]CONNECT */ @@ -79,16 +92,25 @@ enum { NATIVE_WINDOW_API_EGL = 1 }; -typedef struct android_native_window_t +struct ANativeWindow { #ifdef __cplusplus - android_native_window_t() + ANativeWindow() : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0) { common.magic = ANDROID_NATIVE_WINDOW_MAGIC; - common.version = sizeof(android_native_window_t); + 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; @@ -115,7 +137,7 @@ typedef struct android_native_window_t * * Returns 0 on success or -errno on error. */ - int (*setSwapInterval)(struct android_native_window_t* window, + int (*setSwapInterval)(struct ANativeWindow* window, int interval); /* @@ -125,7 +147,7 @@ typedef struct android_native_window_t * * Returns 0 on success or -errno on error. */ - int (*dequeueBuffer)(struct android_native_window_t* window, + int (*dequeueBuffer)(struct ANativeWindow* window, struct android_native_buffer_t** buffer); /* @@ -135,7 +157,7 @@ typedef struct android_native_window_t * * Returns 0 on success or -errno on error. */ - int (*lockBuffer)(struct android_native_window_t* window, + int (*lockBuffer)(struct ANativeWindow* window, struct android_native_buffer_t* buffer); /* * hook called by EGL when modifications to the render buffer are done. @@ -145,7 +167,7 @@ typedef struct android_native_window_t * * Returns 0 on success or -errno on error. */ - int (*queueBuffer)(struct android_native_window_t* window, + int (*queueBuffer)(struct ANativeWindow* window, struct android_native_buffer_t* buffer); /* @@ -153,13 +175,13 @@ typedef struct android_native_window_t * * Returns 0 on success or -errno on error. */ - int (*query)(struct android_native_window_t* window, + int (*query)(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 - * android_native_window_t while keeping backward binary compatibility. + * ANativeWindow while keeping backward binary compatibility. * * This hook should not be called directly, instead use the helper functions * defined below. @@ -171,19 +193,25 @@ typedef struct android_native_window_t * NATIVE_WINDOW_SET_USAGE * NATIVE_WINDOW_CONNECT * NATIVE_WINDOW_DISCONNECT + * NATIVE_WINDOW_SET_CROP + * NATIVE_WINDOW_SET_BUFFER_COUNT + * NATIVE_WINDOW_SET_BUFFERS_GEOMETRY * */ - int (*perform)(struct android_native_window_t* window, + int (*perform)(struct ANativeWindow* window, int operation, ... ); void* reserved_proc[3]; -} android_native_window_t; +}; +// Backwards compatibility... please switch to ANativeWindow. +typedef struct ANativeWindow android_native_window_t; /* - * native_window_set_usage() sets the intended usage flags for the next - * buffers acquired with (*lockBuffer)() and on. + * 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. @@ -192,35 +220,83 @@ typedef struct android_native_window_t */ static inline int native_window_set_usage( - android_native_window_t* window, int usage) + ANativeWindow* window, int usage) { return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage); } /* - * native_window_connect(..., NATIVE_WINDOW_API_EGL) must be called - * by EGL when the window is made current. + * native_window_connect(..., NATIVE_WINDOW_API_EGL) + * Must be called by EGL when the window is made current. * 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_connect( - android_native_window_t* window, int api) + ANativeWindow* window, int api) { return window->perform(window, NATIVE_WINDOW_CONNECT, api); } /* - * native_window_disconnect(..., NATIVE_WINDOW_API_EGL) must be called - * by EGL when the window is made not current. + * native_window_disconnect(..., NATIVE_WINDOW_API_EGL) + * Must be called by EGL when the window is made not current. * An error is returned if for instance the window wasn't connected in the * first place. */ static inline int native_window_disconnect( - android_native_window_t* window, int api) + ANativeWindow* window, int api) { return window->perform(window, NATIVE_WINDOW_DISCONNECT, api); } +/* + * native_window_set_crop(..., crop) + * Sets which region of the next queued buffers needs to be considered. + * A buffer's crop region is scaled to match the surface's size. + * + * 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( + ANativeWindow* window, + android_native_rect_t const * crop) +{ + return window->perform(window, NATIVE_WINDOW_SET_CROP, crop); +} + +/* + * native_window_set_buffer_count(..., count) + * Sets the number of buffers associated with this native window. + */ +static inline int native_window_set_buffer_count( + 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 geometry specified. + * In particular, all buffers will have a fixed-size, independent form the + * native-window size. They will be appropriately scaled to the window-size + * upon composition. + * + * If all parameters are 0, the normal behavior is restored. That is, + * dequeued buffers following this call will be sized to the window's size. + * + */ +static inline int native_window_set_buffers_geometry( + ANativeWindow* window, + int w, int h, int format) +{ + return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY, + w, h, format); +} // --------------------------------------------------------------------------- @@ -263,6 +339,15 @@ namespace android { template <typename NATIVE_TYPE, typename TYPE, typename REF> class EGLNativeBase : public NATIVE_TYPE, public REF { +public: + // Disambiguate between the incStrong in REF and NATIVE_TYPE + void incStrong(const void* id) const { + REF::incStrong(id); + } + void decStrong(const void* id) const { + REF::decStrong(id); + } + protected: typedef EGLNativeBase<NATIVE_TYPE, TYPE, REF> BASE; EGLNativeBase() : NATIVE_TYPE(), REF() { diff --git a/include/utils/Asset.h b/include/utils/Asset.h index 5908bcc..2a09095 100644 --- a/include/utils/Asset.h +++ b/include/utils/Asset.h @@ -61,15 +61,6 @@ public: ACCESS_BUFFER, } AccessMode; - enum { - /* data larger than this does not get uncompressed into a buffer */ -#ifdef HAVE_ANDROID_OS - UNCOMPRESS_DATA_MAX = 1 * 1024 * 1024 -#else - UNCOMPRESS_DATA_MAX = 2 * 1024 * 1024 -#endif - }; - /* * Read data from the current offset. Returns the actual number of * bytes read, 0 on EOF, or -1 on error. @@ -317,6 +308,8 @@ private: FileMap* mMap; // for memory-mapped input int mFd; // for file input + class StreamingZipInflater* mZipInflater; // for streaming large compressed assets + unsigned char* mBuf; // for getBuffer() }; diff --git a/include/utils/AssetManager.h b/include/utils/AssetManager.h index d8994e0..9e2bf37 100644 --- a/include/utils/AssetManager.h +++ b/include/utils/AssetManager.h @@ -29,6 +29,24 @@ #include <utils/ZipFileRO.h> #include <utils/threads.h> +/* + * Native-app access is via the opaque typedef struct AAssetManager in the C namespace. + */ +#ifdef __cplusplus +extern "C" { +#endif + +struct AAssetManager { }; + +#ifdef __cplusplus +}; +#endif + + +/* + * Now the proper C++ android-namespace definitions + */ + namespace android { class Asset; // fwd decl for things that include Asset.h first @@ -48,7 +66,7 @@ struct ResTable_config; * The asset hierarchy may be examined like a filesystem, using * AssetDir objects to peruse a single directory. */ -class AssetManager { +class AssetManager : public AAssetManager { public: typedef enum CacheMode { CACHE_UNKNOWN = 0, @@ -111,6 +129,8 @@ public: */ void setConfiguration(const ResTable_config& config, const char* locale = NULL); + void getConfiguration(ResTable_config* outConfig) const; + typedef Asset::AccessMode AccessMode; // typing shortcut /* diff --git a/include/utils/BitSet.h b/include/utils/BitSet.h new file mode 100644 index 0000000..19c8bf0 --- /dev/null +++ b/include/utils/BitSet.h @@ -0,0 +1,67 @@ +/* + * 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> + +/* + * 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 true if the bit set does not contain any marked bits. + inline bool isEmpty() const { return ! value; } + + // 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); } + + inline bool operator== (const BitSet32& other) const { return value == other.value; } + inline bool operator!= (const BitSet32& other) const { return value != other.value; } +}; + +} // namespace android + +#endif // UTILS_BITSET_H diff --git a/include/utils/Buffer.h b/include/utils/Buffer.h deleted file mode 100644 index 8e22b0f..0000000 --- a/include/utils/Buffer.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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 __UTILS_BUFFER_H__ -#define __UTILS_BUFFER_H__ 1 - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -namespace android { - -class Buffer -{ -private: - char *buf; - int bufsiz; - int used; - void ensureCapacity(int len); - - void - makeRoomFor(int len) - { - if (len + used >= bufsiz) { - bufsiz = (len + used) * 3/2 + 2; - char *blah = new char[bufsiz]; - - memcpy(blah, buf, used); - delete[] buf; - buf = blah; - } - } - -public: - Buffer() - { - bufsiz = 16; - buf = new char[bufsiz]; - clear(); - } - - ~Buffer() - { - delete[] buf; - } - - void - clear() - { - buf[0] = '\0'; - used = 0; - } - - int - length() - { - return used; - } - - void - append(const char c) - { - makeRoomFor(1); - buf[used] = c; - used++; - buf[used] = '\0'; - } - - void - append(const char *s, int len) - { - makeRoomFor(len); - - memcpy(buf + used, s, len); - used += len; - buf[used] = '\0'; - } - - void - append(const char *s) - { - append(s, strlen(s)); - } - - char * - getBytes() - { - return buf; - } -}; - -}; // namespace android - -#endif diff --git a/include/utils/ObbFile.h b/include/utils/ObbFile.h new file mode 100644 index 0000000..d2ca82e --- /dev/null +++ b/include/utils/ObbFile.h @@ -0,0 +1,91 @@ +/* + * 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 OBBFILE_H_ +#define OBBFILE_H_ + +#include <stdint.h> + +#include <utils/RefBase.h> +#include <utils/String8.h> + +namespace android { + +class ObbFile : public RefBase { +protected: + virtual ~ObbFile(); + +public: + ObbFile(); + + bool readFrom(const char* filename); + bool readFrom(int fd); + bool writeTo(const char* filename); + bool writeTo(int fd); + bool removeFrom(const char* filename); + bool removeFrom(int fd); + + const char* getFileName() const { + return mFileName; + } + + const String8 getPackageName() const { + return mPackageName; + } + + int32_t getVersion() const { + return mVersion; + } + + void setPackageName(String8 packageName) { + mPackageName = packageName; + } + + void setVersion(int32_t version) { + mVersion = version; + } + + static inline uint32_t get4LE(const unsigned char* buf) { + return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); + } + + static inline void put4LE(unsigned char* buf, uint32_t val) { + buf[0] = val & 0xFF; + buf[1] = (val >> 8) & 0xFF; + buf[2] = (val >> 16) & 0xFF; + buf[3] = (val >> 24) & 0xFF; + } + +private: + /* Package name this ObbFile is associated with */ + String8 mPackageName; + + /* Package version this ObbFile is associated with */ + int32_t mVersion; + + const char* mFileName; + + size_t mFileSize; + + size_t mFooterStart; + + unsigned char* mReadBuf; + + bool parseObbFile(int fd); +}; + +} +#endif /* OBBFILE_H_ */ diff --git a/include/utils/PollLoop.h b/include/utils/PollLoop.h new file mode 100644 index 0000000..81230e8 --- /dev/null +++ b/include/utils/PollLoop.h @@ -0,0 +1,197 @@ +/* + * 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_POLL_LOOP_H +#define UTILS_POLL_LOOP_H + +#include <utils/Vector.h> +#include <utils/threads.h> + +#include <sys/poll.h> + +#include <android/looper.h> + +struct ALooper : public android::RefBase { +protected: + virtual ~ALooper() { } + +public: + ALooper() { } +}; + +namespace android { + +/** + * A basic file descriptor polling loop based on poll() with callbacks. + */ +class PollLoop : public ALooper { +protected: + virtual ~PollLoop(); + +public: + PollLoop(bool allowNonCallbacks); + + /** + * A callback that it to be invoked when an event occurs on a file descriptor. + * Specifies the events that were triggered and the user data provided when the + * callback was set. + * + * Returns true if the callback should be kept, false if it should be removed automatically + * after the callback returns. + */ + typedef bool (*Callback)(int fd, int events, void* data); + + enum { + POLL_CALLBACK = ALOOPER_POLL_CALLBACK, + POLL_TIMEOUT = ALOOPER_POLL_TIMEOUT, + POLL_ERROR = ALOOPER_POLL_ERROR, + }; + + /** + * Performs a single call to poll() 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 awoken. + * + * Returns ALOOPER_POLL_CALLBACK if a callback was invoked. + * + * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given + * timeout expired. + * + * Returns ALOPER_POLL_ERROR if an error occurred. + * + * Returns a value >= 0 containing a file descriptor if it has data + * and it has no callback function (requiring the caller here to handle it). + * In this (and only this) case outEvents and outData will contain the poll + * events and data associated with the fd. + * + * This method must only be called on the thread owning the PollLoop. + * This method blocks until either a file descriptor is signalled, a timeout occurs, + * or wake() is called. + * This method does not return until it has finished invoking the appropriate callbacks + * for all file descriptors that were signalled. + */ + int32_t pollOnce(int timeoutMillis, int* outEvents = NULL, void** outData = NULL); + + /** + * Wakes the loop asynchronously. + * + * This method can be called on any thread. + * This method returns immediately. + */ + void wake(); + + /** + * Control whether this PollLoop instance allows using IDs instead + * of callbacks. + */ + bool getAllowNonCallbacks() const; + + /** + * Sets the callback for a file descriptor, replacing the existing one, if any. + * It is an error to call this method with events == 0 or callback == NULL. + * + * Note that a callback can be invoked with the POLLERR, POLLHUP or POLLNVAL events + * even if it is not explicitly requested when registered. + * + * This method can be called on any thread. + * This method may block briefly if it needs to wake the poll loop. + */ + void setCallback(int fd, int events, Callback callback, void* data = NULL); + + /** + * Like setCallback(), but for the NDK callback function. + */ + void setLooperCallback(int fd, int events, ALooper_callbackFunc* callback, + void* data); + + /** + * Removes the callback for a file descriptor, if one exists. + * + * When this method returns, it is safe to close the file descriptor since the poll loop + * 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 false or calling this method, then it can be guaranteed to not be invoked + * again at any later time unless registered anew. + * + * This method can be called on any thread. + * This method may block briefly if it needs to wake the poll loop. + * + * Returns true if a callback was actually removed, false if none was registered. + */ + bool removeCallback(int fd); + + /** + * Set the given PollLoop to be associated with the + * calling thread. There must be a 1:1 relationship between + * PollLoop and thread. + */ + static void setForThread(const sp<PollLoop>& pollLoop); + + /** + * Return the PollLoop associated with the calling thread. + */ + static sp<PollLoop> getForThread(); + +private: + struct RequestedCallback { + Callback callback; + ALooper_callbackFunc* looperCallback; + void* data; + }; + + struct PendingCallback { + int fd; + int events; + Callback callback; + ALooper_callbackFunc* looperCallback; + void* data; + }; + + const bool mAllowNonCallbacks; + + Mutex mLock; + bool mPolling; + uint32_t mWaiters; + Condition mAwake; + Condition mResume; + + int mWakeReadPipeFd; + int mWakeWritePipeFd; + + Vector<struct pollfd> mRequestedFds; + Vector<RequestedCallback> mRequestedCallbacks; + + Vector<PendingCallback> mPendingCallbacks; // used privately by pollOnce + Vector<PendingCallback> mPendingFds; // used privately by pollOnce + size_t mPendingFdsPos; + + void openWakePipe(); + void closeWakePipe(); + + void setCallbackCommon(int fd, int events, Callback callback, + ALooper_callbackFunc* looperCallback, void* data); + ssize_t getRequestIndexLocked(int fd); + void wakeAndLock(); + static void threadDestructor(void *st); +}; + +} // namespace android + +#endif // UTILS_POLL_LOOP_H diff --git a/include/utils/Pool.h b/include/utils/Pool.h new file mode 100644 index 0000000..2ee768e --- /dev/null +++ b/include/utils/Pool.h @@ -0,0 +1,71 @@ +/* + * 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_POOL_H +#define UTILS_POOL_H + +#include <utils/TypeHelpers.h> + +namespace android { + +class PoolImpl { +public: + PoolImpl(size_t objSize); + ~PoolImpl(); + + void* allocImpl(); + void freeImpl(void* obj); + +private: + size_t mObjSize; +}; + +/* + * A homogeneous typed memory pool for fixed size objects. + * Not intended to be thread-safe. + */ +template<typename T> +class Pool : private PoolImpl { +public: + /* Creates an initially empty pool. */ + Pool() : PoolImpl(sizeof(T)) { } + + /* Destroys the pool. + * Assumes that the pool is empty. */ + ~Pool() { } + + /* Allocates an object from the pool, growing the pool if needed. */ + inline T* alloc() { + void* mem = allocImpl(); + if (! traits<T>::has_trivial_ctor) { + return new (mem) T(); + } else { + return static_cast<T*>(mem); + } + } + + /* Frees an object from the pool. */ + inline void free(T* obj) { + if (! traits<T>::has_trivial_dtor) { + obj->~T(); + } + freeImpl(obj); + } +}; + +} // namespace android + +#endif // UTILS_POOL_H diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h index bd7f28c..9c64ac0 100644 --- a/include/utils/RefBase.h +++ b/include/utils/RefBase.h @@ -333,9 +333,10 @@ sp<T>::~sp() template<typename T> sp<T>& sp<T>::operator = (const sp<T>& other) { - if (other.m_ptr) other.m_ptr->incStrong(this); + T* otherPtr(other.m_ptr); + if (otherPtr) otherPtr->incStrong(this); if (m_ptr) m_ptr->decStrong(this); - m_ptr = other.m_ptr; + m_ptr = otherPtr; return *this; } @@ -351,9 +352,10 @@ sp<T>& sp<T>::operator = (T* other) template<typename T> template<typename U> sp<T>& sp<T>::operator = (const sp<U>& other) { - if (other.m_ptr) other.m_ptr->incStrong(this); + U* otherPtr(other.m_ptr); + if (otherPtr) otherPtr->incStrong(this); if (m_ptr) m_ptr->decStrong(this); - m_ptr = other.m_ptr; + m_ptr = otherPtr; return *this; } @@ -466,10 +468,12 @@ wp<T>& wp<T>::operator = (T* other) template<typename T> wp<T>& wp<T>::operator = (const wp<T>& other) { - if (other.m_ptr) other.m_refs->incWeak(this); + 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 = other.m_ptr; - m_refs = other.m_refs; + m_ptr = otherPtr; + m_refs = otherRefs; return *this; } @@ -478,8 +482,9 @@ 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 = other.get(); + m_ptr = otherPtr; m_refs = newRefs; return *this; } @@ -498,10 +503,12 @@ wp<T>& wp<T>::operator = (U* other) template<typename T> template<typename U> wp<T>& wp<T>::operator = (const wp<U>& other) { - if (other.m_ptr) other.m_refs->incWeak(this); + 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 = other.m_ptr; - m_refs = other.m_refs; + m_ptr = otherPtr; + m_refs = otherRefs; return *this; } @@ -510,8 +517,9 @@ 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 = other.get(); + m_ptr = otherPtr; m_refs = newRefs; return *this; } diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h index b701ce7..da86da4 100644 --- a/include/utils/ResourceTypes.h +++ b/include/utils/ResourceTypes.h @@ -31,6 +31,8 @@ #include <stdint.h> #include <sys/types.h> +#include <android/configuration.h> + namespace android { /** ******************************************************************** @@ -822,25 +824,25 @@ struct ResTable_config }; enum { - ORIENTATION_ANY = 0x0000, - ORIENTATION_PORT = 0x0001, - ORIENTATION_LAND = 0x0002, - ORIENTATION_SQUARE = 0x0003, + ORIENTATION_ANY = ACONFIGURATION_ORIENTATION_ANY, + ORIENTATION_PORT = ACONFIGURATION_ORIENTATION_PORT, + ORIENTATION_LAND = ACONFIGURATION_ORIENTATION_LAND, + ORIENTATION_SQUARE = ACONFIGURATION_ORIENTATION_SQUARE, }; enum { - TOUCHSCREEN_ANY = 0x0000, - TOUCHSCREEN_NOTOUCH = 0x0001, - TOUCHSCREEN_STYLUS = 0x0002, - TOUCHSCREEN_FINGER = 0x0003, + TOUCHSCREEN_ANY = ACONFIGURATION_TOUCHSCREEN_ANY, + TOUCHSCREEN_NOTOUCH = ACONFIGURATION_TOUCHSCREEN_NOTOUCH, + TOUCHSCREEN_STYLUS = ACONFIGURATION_TOUCHSCREEN_STYLUS, + TOUCHSCREEN_FINGER = ACONFIGURATION_TOUCHSCREEN_FINGER, }; enum { - DENSITY_DEFAULT = 0, - DENSITY_LOW = 120, - DENSITY_MEDIUM = 160, - DENSITY_HIGH = 240, - DENSITY_NONE = 0xffff + DENSITY_DEFAULT = ACONFIGURATION_DENSITY_DEFAULT, + DENSITY_LOW = ACONFIGURATION_DENSITY_LOW, + DENSITY_MEDIUM = ACONFIGURATION_DENSITY_MEDIUM, + DENSITY_HIGH = ACONFIGURATION_DENSITY_HIGH, + DENSITY_NONE = ACONFIGURATION_DENSITY_NONE }; union { @@ -853,33 +855,34 @@ struct ResTable_config }; enum { - KEYBOARD_ANY = 0x0000, - KEYBOARD_NOKEYS = 0x0001, - KEYBOARD_QWERTY = 0x0002, - KEYBOARD_12KEY = 0x0003, + KEYBOARD_ANY = ACONFIGURATION_KEYBOARD_ANY, + KEYBOARD_NOKEYS = ACONFIGURATION_KEYBOARD_NOKEYS, + KEYBOARD_QWERTY = ACONFIGURATION_KEYBOARD_QWERTY, + KEYBOARD_12KEY = ACONFIGURATION_KEYBOARD_12KEY, }; enum { - NAVIGATION_ANY = 0x0000, - NAVIGATION_NONAV = 0x0001, - NAVIGATION_DPAD = 0x0002, - NAVIGATION_TRACKBALL = 0x0003, - NAVIGATION_WHEEL = 0x0004, + NAVIGATION_ANY = ACONFIGURATION_NAVIGATION_ANY, + NAVIGATION_NONAV = ACONFIGURATION_NAVIGATION_NONAV, + NAVIGATION_DPAD = ACONFIGURATION_NAVIGATION_DPAD, + NAVIGATION_TRACKBALL = ACONFIGURATION_NAVIGATION_TRACKBALL, + NAVIGATION_WHEEL = ACONFIGURATION_NAVIGATION_WHEEL, }; enum { MASK_KEYSHIDDEN = 0x0003, - KEYSHIDDEN_ANY = 0x0000, - KEYSHIDDEN_NO = 0x0001, - KEYSHIDDEN_YES = 0x0002, - KEYSHIDDEN_SOFT = 0x0003, + KEYSHIDDEN_ANY = ACONFIGURATION_KEYSHIDDEN_ANY, + KEYSHIDDEN_NO = ACONFIGURATION_KEYSHIDDEN_NO, + KEYSHIDDEN_YES = ACONFIGURATION_KEYSHIDDEN_YES, + KEYSHIDDEN_SOFT = ACONFIGURATION_KEYSHIDDEN_SOFT, }; enum { MASK_NAVHIDDEN = 0x000c, - NAVHIDDEN_ANY = 0x0000, - NAVHIDDEN_NO = 0x0004, - NAVHIDDEN_YES = 0x0008, + SHIFT_NAVHIDDEN = 2, + NAVHIDDEN_ANY = ACONFIGURATION_NAVHIDDEN_ANY << SHIFT_NAVHIDDEN, + NAVHIDDEN_NO = ACONFIGURATION_NAVHIDDEN_NO << SHIFT_NAVHIDDEN, + NAVHIDDEN_YES = ACONFIGURATION_NAVHIDDEN_YES << SHIFT_NAVHIDDEN, }; union { @@ -929,31 +932,34 @@ struct ResTable_config enum { // screenLayout bits for screen size class. MASK_SCREENSIZE = 0x0f, - SCREENSIZE_ANY = 0x00, - SCREENSIZE_SMALL = 0x01, - SCREENSIZE_NORMAL = 0x02, - SCREENSIZE_LARGE = 0x03, + SCREENSIZE_ANY = ACONFIGURATION_SCREENSIZE_ANY, + SCREENSIZE_SMALL = ACONFIGURATION_SCREENSIZE_SMALL, + SCREENSIZE_NORMAL = ACONFIGURATION_SCREENSIZE_NORMAL, + SCREENSIZE_LARGE = ACONFIGURATION_SCREENSIZE_LARGE, + SCREENSIZE_XLARGE = ACONFIGURATION_SCREENSIZE_XLARGE, // screenLayout bits for wide/long screen variation. MASK_SCREENLONG = 0x30, - SCREENLONG_ANY = 0x00, - SCREENLONG_NO = 0x10, - SCREENLONG_YES = 0x20, + SHIFT_SCREENLONG = 4, + SCREENLONG_ANY = ACONFIGURATION_SCREENLONG_ANY << SHIFT_SCREENLONG, + SCREENLONG_NO = ACONFIGURATION_SCREENLONG_NO << SHIFT_SCREENLONG, + SCREENLONG_YES = ACONFIGURATION_SCREENLONG_YES << SHIFT_SCREENLONG, }; enum { // uiMode bits for the mode type. MASK_UI_MODE_TYPE = 0x0f, - UI_MODE_TYPE_ANY = 0x00, - UI_MODE_TYPE_NORMAL = 0x01, - UI_MODE_TYPE_DESK = 0x02, - UI_MODE_TYPE_CAR = 0x03, + UI_MODE_TYPE_ANY = ACONFIGURATION_UI_MODE_TYPE_ANY, + UI_MODE_TYPE_NORMAL = ACONFIGURATION_UI_MODE_TYPE_NORMAL, + UI_MODE_TYPE_DESK = ACONFIGURATION_UI_MODE_TYPE_DESK, + UI_MODE_TYPE_CAR = ACONFIGURATION_UI_MODE_TYPE_CAR, // uiMode bits for the night switch. MASK_UI_MODE_NIGHT = 0x30, - UI_MODE_NIGHT_ANY = 0x00, - UI_MODE_NIGHT_NO = 0x10, - UI_MODE_NIGHT_YES = 0x20, + SHIFT_UI_MODE_NIGHT = 4, + UI_MODE_NIGHT_ANY = ACONFIGURATION_UI_MODE_NIGHT_ANY << SHIFT_UI_MODE_NIGHT, + UI_MODE_NIGHT_NO = ACONFIGURATION_UI_MODE_NIGHT_NO << SHIFT_UI_MODE_NIGHT, + UI_MODE_NIGHT_YES = ACONFIGURATION_UI_MODE_NIGHT_YES << SHIFT_UI_MODE_NIGHT, }; union { @@ -1022,19 +1028,19 @@ struct ResTable_config // match the corresponding ones in android.content.pm.ActivityInfo and // attrs_manifest.xml. enum { - CONFIG_MCC = 0x0001, - CONFIG_MNC = 0x0002, - CONFIG_LOCALE = 0x0004, - CONFIG_TOUCHSCREEN = 0x0008, - CONFIG_KEYBOARD = 0x0010, - CONFIG_KEYBOARD_HIDDEN = 0x0020, - CONFIG_NAVIGATION = 0x0040, - CONFIG_ORIENTATION = 0x0080, - CONFIG_DENSITY = 0x0100, - CONFIG_SCREEN_SIZE = 0x0200, - CONFIG_VERSION = 0x0400, - CONFIG_SCREEN_LAYOUT = 0x0800, - CONFIG_UI_MODE = 0x1000 + CONFIG_MCC = ACONFIGURATION_MCC, + CONFIG_MNC = ACONFIGURATION_MCC, + CONFIG_LOCALE = ACONFIGURATION_LOCALE, + CONFIG_TOUCHSCREEN = ACONFIGURATION_TOUCHSCREEN, + CONFIG_KEYBOARD = ACONFIGURATION_KEYBOARD, + CONFIG_KEYBOARD_HIDDEN = ACONFIGURATION_KEYBOARD_HIDDEN, + CONFIG_NAVIGATION = ACONFIGURATION_NAVIGATION, + CONFIG_ORIENTATION = ACONFIGURATION_ORIENTATION, + CONFIG_DENSITY = ACONFIGURATION_DENSITY, + CONFIG_SCREEN_SIZE = ACONFIGURATION_SCREEN_SIZE, + CONFIG_VERSION = ACONFIGURATION_VERSION, + CONFIG_SCREEN_LAYOUT = ACONFIGURATION_SCREEN_LAYOUT, + CONFIG_UI_MODE = ACONFIGURATION_UI_MODE }; // Compare two configuration, returning CONFIG_* flags set for each value @@ -1208,7 +1214,28 @@ struct ResTable_config if (screenLayout || o.screenLayout) { if (((screenLayout^o.screenLayout) & MASK_SCREENSIZE) != 0 && (requested->screenLayout & MASK_SCREENSIZE)) { - return (screenLayout & MASK_SCREENSIZE); + // A little backwards compatibility here: undefined is + // considered equivalent to normal. But only if the + // requested size is at least normal; otherwise, small + // is better than the default. + int mySL = (screenLayout & MASK_SCREENSIZE); + int oSL = (o.screenLayout & MASK_SCREENSIZE); + int fixedMySL = mySL; + int fixedOSL = oSL; + if ((requested->screenLayout & MASK_SCREENSIZE) >= SCREENSIZE_NORMAL) { + if (fixedMySL == 0) fixedMySL = SCREENSIZE_NORMAL; + if (fixedOSL == 0) fixedOSL = SCREENSIZE_NORMAL; + } + // For screen size, the best match is the one that is + // closest to the requested screen size, but not over + // (the not over part is dealt with in match() below). + if (fixedMySL == fixedOSL) { + // If the two are the same, but 'this' is actually + // undefined, then the other is really a better match. + if (mySL == 0) return false; + return true; + } + return fixedMySL >= fixedOSL; } if (((screenLayout^o.screenLayout) & MASK_SCREENLONG) != 0 && (requested->screenLayout & MASK_SCREENLONG)) { @@ -1370,8 +1397,11 @@ struct ResTable_config if (screenConfig != 0) { const int screenSize = screenLayout&MASK_SCREENSIZE; const int setScreenSize = settings.screenLayout&MASK_SCREENSIZE; - if (setScreenSize != 0 && screenSize != 0 - && screenSize != setScreenSize) { + // Any screen sizes for larger screens than the setting do not + // match. + if ((setScreenSize != 0 && screenSize != 0 + && screenSize > setScreenSize) || + (setScreenSize == 0 && screenSize != 0)) { return false; } diff --git a/include/utils/Singleton.h b/include/utils/Singleton.h index bc7626a8..3b975b4 100644 --- a/include/utils/Singleton.h +++ b/include/utils/Singleton.h @@ -54,11 +54,13 @@ private: * (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< class TYPE > Mutex Singleton< TYPE >::sLock; \ +#define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) \ + template class Singleton< TYPE >; \ + template<> Mutex Singleton< TYPE >::sLock(Mutex::PRIVATE); \ template<> TYPE* Singleton< TYPE >::sInstance(0); diff --git a/include/utils/StopWatch.h b/include/utils/StopWatch.h index cc0bebc..693dd3c 100644 --- a/include/utils/StopWatch.h +++ b/include/utils/StopWatch.h @@ -37,6 +37,8 @@ public: const char* name() const; nsecs_t lap(); nsecs_t elapsedTime() const; + + void reset(); private: const char* mName; diff --git a/include/utils/StreamingZipInflater.h b/include/utils/StreamingZipInflater.h new file mode 100644 index 0000000..16867d8 --- /dev/null +++ b/include/utils/StreamingZipInflater.h @@ -0,0 +1,82 @@ +/* + * 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 __LIBS_STREAMINGZIPINFLATER_H +#define __LIBS_STREAMINGZIPINFLATER_H + +#include <unistd.h> +#include <inttypes.h> +#include <zlib.h> + +namespace android { + +class StreamingZipInflater { +public: + static const size_t INPUT_CHUNK_SIZE = 64 * 1024; + static const size_t OUTPUT_CHUNK_SIZE = 64 * 1024; + + // Flavor that pages in the compressed data from a fd + StreamingZipInflater(int fd, off_t compDataStart, size_t uncompSize, size_t compSize); + + // Flavor that gets the compressed data from an in-memory buffer + StreamingZipInflater(class FileMap* dataMap, size_t uncompSize); + + ~StreamingZipInflater(); + + // read 'count' bytes of uncompressed data from the current position. outBuf may + // be NULL, in which case the data is consumed and discarded. + ssize_t read(void* outBuf, size_t count); + + // seeking backwards requires uncompressing fom the beginning, so is very + // expensive. seeking forwards only requires uncompressing from the current + // position to the destination. + off_t seekAbsolute(off_t absoluteInputPosition); + +private: + void initInflateState(); + int readNextChunk(); + + // where to find the uncompressed data + int mFd; + off_t mInFileStart; // where the compressed data lives in the file + class FileMap* mDataMap; + + z_stream mInflateState; + bool mStreamNeedsInit; + + // output invariants for this asset + uint8_t* mOutBuf; // output buf for decompressed bytes + size_t mOutBufSize; // allocated size of mOutBuf + size_t mOutTotalSize; // total uncompressed size of the blob + + // current output state bookkeeping + off_t mOutCurPosition; // current position in total offset + size_t mOutLastDecoded; // last decoded byte + 1 in mOutbuf + size_t mOutDeliverable; // next undelivered byte of decoded output in mOutBuf + + // input invariants + uint8_t* mInBuf; + size_t mInBufSize; // allocated size of mInBuf; + size_t mInTotalSize; // total size of compressed data for this blob + + // input state bookkeeping + size_t mInNextChunkOffset; // offset from start of blob at which the next input chunk lies + // the z_stream contains state about input block consumption +}; + +} + +#endif diff --git a/include/utils/String8.h b/include/utils/String8.h index c4b18a4..ef0b51a 100644 --- a/include/utils/String8.h +++ b/include/utils/String8.h @@ -171,6 +171,9 @@ public: 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))); + // Note that this function takes O(N) time to calculate the value. // No cache value is stored. size_t getUtf32Length() const; @@ -372,7 +375,7 @@ inline String8& String8::operator+=(const String8& other) inline String8 String8::operator+(const String8& other) const { - String8 tmp; + String8 tmp(*this); tmp += other; return tmp; } @@ -385,7 +388,7 @@ inline String8& String8::operator+=(const char* other) inline String8 String8::operator+(const char* other) const { - String8 tmp; + String8 tmp(*this); tmp += other; return tmp; } diff --git a/include/utils/Vector.h b/include/utils/Vector.h index ad59fd6..ec851bd 100644 --- a/include/utils/Vector.h +++ b/include/utils/Vector.h @@ -114,13 +114,19 @@ public: 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 on onr several items initialized from a prototype item + //! 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(); @@ -259,6 +265,16 @@ ssize_t Vector<TYPE>::appendVector(const Vector<TYPE>& 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); } diff --git a/include/utils/VectorImpl.h b/include/utils/VectorImpl.h index 49b03f1..c4ec2ff 100644 --- a/include/utils/VectorImpl.h +++ b/include/utils/VectorImpl.h @@ -65,9 +65,11 @@ public: size_t capacity() const; ssize_t setCapacity(size_t size); - /*! append/insert another vector */ + /*! 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); @@ -184,6 +186,8 @@ private: 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); diff --git a/include/utils/ZipFileCRO.h b/include/utils/ZipFileCRO.h index 30e0036..e38bf66 100644 --- a/include/utils/ZipFileCRO.h +++ b/include/utils/ZipFileCRO.h @@ -47,8 +47,8 @@ extern ZipEntryCRO ZipFileCRO_findEntryByName(ZipFileCRO zip, const char* fileName); extern bool ZipFileCRO_getEntryInfo(ZipFileCRO zip, ZipEntryCRO entry, - int* pMethod, long* pUncompLen, - long* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32); + int* pMethod, size_t* pUncompLen, + size_t* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32); extern bool ZipFileCRO_uncompressEntry(ZipFileCRO zip, ZipEntryCRO entry, int fd); diff --git a/include/utils/ZipFileRO.h b/include/utils/ZipFileRO.h index 51c4f2f..97d31f4 100644 --- a/include/utils/ZipFileRO.h +++ b/include/utils/ZipFileRO.h @@ -58,14 +58,19 @@ typedef void* ZipEntryRO; class ZipFileRO { public: ZipFileRO() - : mFd(-1), mFileMap(NULL), mHashTableSize(-1), mHashTable(NULL) + : mFd(-1), mFileName(NULL), mFileLength(-1), + mDirectoryMap(NULL), + mNumEntries(-1), mDirectoryOffset(-1), + mHashTableSize(-1), mHashTable(NULL) {} ~ZipFileRO() { free(mHashTable); - if (mFileMap) - mFileMap->release(); + if (mDirectoryMap) + mDirectoryMap->release(); if (mFd >= 0) close(mFd); + if (mFileName) + free(mFileName); } /* @@ -118,8 +123,8 @@ public: * Returns "false" if "entry" is bogus or if the data in the Zip file * appears to be bad. */ - bool getEntryInfo(ZipEntryRO entry, int* pMethod, long* pUncompLen, - long* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) const; + bool getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen, + size_t* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) const; /* * Create a new FileMap object that maps a subset of the archive. For @@ -155,13 +160,13 @@ public: * Utility function: uncompress deflated data, buffer to buffer. */ static bool inflateBuffer(void* outBuf, const void* inBuf, - long uncompLen, long compLen); + size_t uncompLen, size_t compLen); /* * Utility function: uncompress deflated data, buffer to fd. */ static bool inflateBuffer(int fd, const void* inBuf, - long uncompLen, long compLen); + size_t uncompLen, size_t compLen); /* * Some basic functions for raw data manipulation. "LE" means @@ -179,6 +184,9 @@ private: 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); @@ -203,12 +211,21 @@ private: /* open Zip archive */ int mFd; + /* zip file name */ + char* mFileName; + + /* length of file */ + size_t mFileLength; + /* mapped file */ - FileMap* mFileMap; + FileMap* mDirectoryMap; /* number of entries in the Zip archive */ int mNumEntries; + /* CD directory offset in the Zip archive */ + off_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. diff --git a/include/utils/threads.h b/include/utils/threads.h index 5ac0c5e..1bcfaed 100644 --- a/include/utils/threads.h +++ b/include/utils/threads.h @@ -295,6 +295,96 @@ typedef Mutex::Autolock AutoMutex; /*****************************************************************************/ +#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 + +/*****************************************************************************/ + /* * Condition variable class. The implementation is system-dependent. * |