From 00a4ea970bab16ef5675e866cd856a0d9919f0c5 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Thu, 8 Jun 2017 21:43:20 +0100 Subject: New impulse-based VelocityTracker strategy. New velocity calculation strategy for VelocityTracker. The strategy models the phone screen as a physical object that gets pushed by the finger. Upon liftoff, the total work done on the object (past 100ms of data and at most 20 most recent samples) is considered to be kinetic energy, which gets converted into equivalent velocity. Works well with "bad" data - unclean touch liftoff, repeated coordinates. Time-shift invariant. Performance otherwise similar to the current default strategy, quadratic unweighted least squares. Bug: 35412046 Test: Recorded bad scroll event on swordfish, this fixes the fling in the wrong direction. Also tested common usecase scenarios on sailfish, no regressions observed. Similar velocity values to lsq2 strategy. Change-Id: Ib439db0ce3b4fe84f59cf66683eae0b5df7776eb --- include/input/VelocityTracker.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'include') diff --git a/include/input/VelocityTracker.h b/include/input/VelocityTracker.h index 795f575a2e..ffa1614b55 100644 --- a/include/input/VelocityTracker.h +++ b/include/input/VelocityTracker.h @@ -264,6 +264,40 @@ private: Movement mMovements[HISTORY_SIZE]; }; +class ImpulseVelocityTrackerStrategy : public VelocityTrackerStrategy { +public: + ImpulseVelocityTrackerStrategy(); + virtual ~ImpulseVelocityTrackerStrategy(); + + virtual void clear(); + virtual void clearPointers(BitSet32 idBits); + virtual void addMovement(nsecs_t eventTime, BitSet32 idBits, + const VelocityTracker::Position* positions); + virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; + +private: + // Sample horizon. + // We don't use too much history by default since we want to react to quick + // changes in direction. + static constexpr nsecs_t HORIZON = 100 * 1000000; // 100 ms + + // Number of samples to keep. + static constexpr size_t HISTORY_SIZE = 20; + + struct Movement { + nsecs_t eventTime; + BitSet32 idBits; + VelocityTracker::Position positions[MAX_POINTERS]; + + inline const VelocityTracker::Position& getPosition(uint32_t id) const { + return positions[idBits.getIndexOfBit(id)]; + } + }; + + size_t mIndex; + Movement mMovements[HISTORY_SIZE]; +}; + } // namespace android #endif // _LIBINPUT_VELOCITY_TRACKER_H -- cgit v1.2.3-59-g8ed1b From 0aeec07971d86c635412c672bd69d91f589a0cd9 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Mon, 12 Jun 2017 15:01:41 +0100 Subject: Fix resampling logic for duplicate events. When events with identical coordinates are reported by the input driver, resampling can lead to false change of direction due to extrapolation. The added logic will compare the current event to the previous event, and will use the previously resampled values for the new event if the raw (as reported by the driver) coordinates of the two events match. This commit makes events with identical coordinates possible, so it must be submitted together with the new impulse-based VelocityTracker strategy commit. The currently used 2nd degree polynomical unweighted least squares strategy cannot handle consecutive events with identical coordinates. Bug: 35412046 Test: Recorded bad scroll event on swordfish, and replayed the event to reproduce this bug. To twitch is no longer observed. Also tested common usecase scenarios on sailfish, no regressions observed. Change-Id: Icb5cf6c76959f3514b8b94c09e38cc5434f31b23 --- include/input/InputTransport.h | 31 ++++++++++++++----- libs/input/InputTransport.cpp | 68 ++++++++++++++++++++++++------------------ 2 files changed, 62 insertions(+), 37 deletions(-) (limited to 'include') diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index efa1ffbfee..0dd15b1221 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -370,14 +370,14 @@ private: int32_t idToIndex[MAX_POINTER_ID + 1]; PointerCoords pointers[MAX_POINTERS]; - void initializeFrom(const InputMessage* msg) { - eventTime = msg->body.motion.eventTime; + void initializeFrom(const InputMessage& msg) { + eventTime = msg.body.motion.eventTime; idBits.clear(); - for (uint32_t i = 0; i < msg->body.motion.pointerCount; i++) { - uint32_t id = msg->body.motion.pointers[i].properties.id; + for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) { + uint32_t id = msg.body.motion.pointers[i].properties.id; idBits.markBit(id); idToIndex[id] = i; - pointers[i].copyFrom(msg->body.motion.pointers[i].coords); + pointers[i].copyFrom(msg.body.motion.pointers[i].coords); } } @@ -402,7 +402,7 @@ private: lastResample.idBits.clear(); } - void addHistory(const InputMessage* msg) { + void addHistory(const InputMessage& msg) { historyCurrent ^= 1; if (historySize < 2) { historySize += 1; @@ -413,6 +413,21 @@ private: const History* getHistory(size_t index) const { return &history[(historyCurrent + index) & 1]; } + + bool recentCoordinatesAreIdentical(uint32_t id) const { + // Return true if the two most recently received "raw" coordinates are identical + if (historySize < 2) { + return false; + } + float currentX = getHistory(0)->getPointerById(id).getX(); + float currentY = getHistory(0)->getPointerById(id).getY(); + float previousX = getHistory(1)->getPointerById(id).getX(); + float previousY = getHistory(1)->getPointerById(id).getY(); + if (currentX == previousX && currentY == previousY) { + return true; + } + return false; + } }; Vector mTouchStates; @@ -432,8 +447,8 @@ private: Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId); - void updateTouchState(InputMessage* msg); - void rewriteMessage(const TouchState& state, InputMessage* msg); + void updateTouchState(InputMessage& msg); + bool rewriteMessage(const TouchState& state, InputMessage& msg); void resampleTouchState(nsecs_t frameTime, MotionEvent* event, const InputMessage *next); diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index d5c592752e..d8dc9575ba 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -496,7 +496,7 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, MotionEvent* motionEvent = factory->createMotionEvent(); if (! motionEvent) return NO_MEMORY; - updateTouchState(&mMsg); + updateTouchState(mMsg); initializeMotionEvent(motionEvent, &mMsg); *outSeq = mMsg.body.motion.seq; *outEvent = motionEvent; @@ -564,7 +564,7 @@ status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory, uint32_t chain = 0; for (size_t i = 0; i < count; i++) { InputMessage& msg = batch.samples.editItemAt(i); - updateTouchState(&msg); + updateTouchState(msg); if (i) { SeqChain seqChain; seqChain.seq = msg.body.motion.seq; @@ -584,20 +584,19 @@ status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory, return OK; } -void InputConsumer::updateTouchState(InputMessage* msg) { +void InputConsumer::updateTouchState(InputMessage& msg) { if (!mResampleTouch || - !(msg->body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) { + !(msg.body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) { return; } - int32_t deviceId = msg->body.motion.deviceId; - int32_t source = msg->body.motion.source; - nsecs_t eventTime = msg->body.motion.eventTime; + int32_t deviceId = msg.body.motion.deviceId; + int32_t source = msg.body.motion.source; // Update the touch state history to incorporate the new input message. // If the message is in the past relative to the most recently produced resampled // touch, then use the resampled time and coordinates instead. - switch (msg->body.motion.action & AMOTION_EVENT_ACTION_MASK) { + switch (msg.body.motion.action & AMOTION_EVENT_ACTION_MASK) { case AMOTION_EVENT_ACTION_DOWN: { ssize_t index = findTouchState(deviceId, source); if (index < 0) { @@ -615,9 +614,8 @@ void InputConsumer::updateTouchState(InputMessage* msg) { if (index >= 0) { TouchState& touchState = mTouchStates.editItemAt(index); touchState.addHistory(msg); - if (eventTime < touchState.lastResample.eventTime) { - rewriteMessage(touchState, msg); - } else { + bool messageRewritten = rewriteMessage(touchState, msg); + if (!messageRewritten) { touchState.lastResample.idBits.clear(); } } @@ -628,7 +626,7 @@ void InputConsumer::updateTouchState(InputMessage* msg) { ssize_t index = findTouchState(deviceId, source); if (index >= 0) { TouchState& touchState = mTouchStates.editItemAt(index); - touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId()); + touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId()); rewriteMessage(touchState, msg); } break; @@ -639,7 +637,7 @@ void InputConsumer::updateTouchState(InputMessage* msg) { if (index >= 0) { TouchState& touchState = mTouchStates.editItemAt(index); rewriteMessage(touchState, msg); - touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId()); + touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId()); } break; } @@ -666,23 +664,28 @@ void InputConsumer::updateTouchState(InputMessage* msg) { } } -void InputConsumer::rewriteMessage(const TouchState& state, InputMessage* msg) { - for (uint32_t i = 0; i < msg->body.motion.pointerCount; i++) { - uint32_t id = msg->body.motion.pointers[i].properties.id; +bool InputConsumer::rewriteMessage(const TouchState& state, InputMessage& msg) { + bool messageRewritten = false; + nsecs_t eventTime = msg.body.motion.eventTime; + for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) { + uint32_t id = msg.body.motion.pointers[i].properties.id; if (state.lastResample.idBits.hasBit(id)) { - PointerCoords& msgCoords = msg->body.motion.pointers[i].coords; + PointerCoords& msgCoords = msg.body.motion.pointers[i].coords; const PointerCoords& resampleCoords = state.lastResample.getPointerById(id); + if (eventTime < state.lastResample.eventTime || + state.recentCoordinatesAreIdentical(id)) { + msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX()); + msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY()); #if DEBUG_RESAMPLING - ALOGD("[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id, - resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_X), - resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_Y), - msgCoords.getAxisValue(AMOTION_EVENT_AXIS_X), - msgCoords.getAxisValue(AMOTION_EVENT_AXIS_Y)); + ALOGD("[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id, + resampleCoords.getX(), resampleCoords.getY(), + msgCoords.getX(), msgCoords.getY()); #endif - msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX()); - msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY()); + messageRewritten = true; + } } } + return messageRewritten; } void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event, @@ -710,6 +713,7 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event, } // Ensure that the current sample has all of the pointers that need to be reported. + // Also ensure that the past two "real" touch events do not contain duplicate coordinates const History* current = touchState.getHistory(0); size_t pointerCount = event->getPointerCount(); for (size_t i = 0; i < pointerCount; i++) { @@ -717,6 +721,12 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event, if (!current->idBits.hasBit(id)) { #if DEBUG_RESAMPLING ALOGD("Not resampled, missing id %d", id); +#endif + return; + } + if (touchState.recentCoordinatesAreIdentical(id)) { +#if DEBUG_RESAMPLING + ALOGD("Not resampled, past two historical events have duplicate coordinates"); #endif return; } @@ -729,12 +739,12 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event, if (next) { // Interpolate between current sample and future sample. // So current->eventTime <= sampleTime <= future.eventTime. - future.initializeFrom(next); + future.initializeFrom(*next); other = &future; nsecs_t delta = future.eventTime - current->eventTime; if (delta < RESAMPLE_MIN_DELTA) { #if DEBUG_RESAMPLING - ALOGD("Not resampled, delta time is too small: %lld ns.", delta); + ALOGD("Not resampled, delta time is too small: %" PRId64 " ns.", delta); #endif return; } @@ -746,12 +756,12 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event, nsecs_t delta = current->eventTime - other->eventTime; if (delta < RESAMPLE_MIN_DELTA) { #if DEBUG_RESAMPLING - ALOGD("Not resampled, delta time is too small: %lld ns.", delta); + ALOGD("Not resampled, delta time is too small: %" PRId64 " ns.", delta); #endif return; } else if (delta > RESAMPLE_MAX_DELTA) { #if DEBUG_RESAMPLING - ALOGD("Not resampled, delta time is too large: %lld ns.", delta); + ALOGD("Not resampled, delta time is too large: %" PRId64 " ns.", delta); #endif return; } @@ -759,7 +769,7 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event, if (sampleTime > maxPredict) { #if DEBUG_RESAMPLING ALOGD("Sample time is too far in the future, adjusting prediction " - "from %lld to %lld ns.", + "from %" PRId64 " to %" PRId64 " ns.", sampleTime - current->eventTime, maxPredict - current->eventTime); #endif sampleTime = maxPredict; -- cgit v1.2.3-59-g8ed1b From 70b9838aed3ae09eb3b8f47c51c939fea3d9e87d Mon Sep 17 00:00:00 2001 From: Peng Xu Date: Mon, 7 Aug 2017 14:09:11 -0700 Subject: Clarify sensor NDK struct has to be backward compatible Bug: 35842870 Test: compiles Change-Id: I7ee89f88d09b2204b61cfd090a29c80a064191e9 --- include/android/sensor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/android/sensor.h b/include/android/sensor.h index 97b4a2ae60..43b991a24a 100644 --- a/include/android/sensor.h +++ b/include/android/sensor.h @@ -197,7 +197,7 @@ enum { * A sensor event. */ -/* NOTE: Must match hardware/sensors.h */ +/* NOTE: changes to these structs have to be backward compatible */ typedef struct ASensorVector { union { float v[3]; @@ -259,7 +259,7 @@ typedef struct { }; } AAdditionalInfoEvent; -/* NOTE: Must match hardware/sensors.h */ +/* NOTE: changes to this struct has to be backward compatible */ typedef struct ASensorEvent { int32_t version; /* sizeof(struct ASensorEvent) */ int32_t sensor; -- cgit v1.2.3-59-g8ed1b From dc7efea69c7d6a25a050e1c60171b5a1660e1f1c Mon Sep 17 00:00:00 2001 From: John Reck Date: Mon, 7 Aug 2017 11:18:40 -0700 Subject: Add ASharedMemory_dupFromJava NDK API Bug: 64394076 Test: SharedMemory CTS tests Change-Id: I0ee5badff48ce72c8a664180beacfcf89112f6bf (cherry picked from commit 9f5599b436b80366ecbea274914fd057fa3dcb91) --- include/android/sharedmem_jni.h | 82 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 include/android/sharedmem_jni.h (limited to 'include') diff --git a/include/android/sharedmem_jni.h b/include/android/sharedmem_jni.h new file mode 100644 index 0000000000..38980f3ccc --- /dev/null +++ b/include/android/sharedmem_jni.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * @addtogroup Memory + * @{ + */ + +/** + * @file sharedmem_jni.h + */ + +#ifndef ANDROID_SHARED_MEMORY_JNI_H +#define ANDROID_SHARED_MEMORY_JNI_H + +#include +#include +#include + +/****************************************************************** + * + * IMPORTANT NOTICE: + * + * This file is part of Android's set of stable system headers + * exposed by the Android NDK (Native Development Kit). + * + * Third-party source AND binary code relies on the definitions + * here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES. + * + * - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES) + * - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS + * - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY + * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES + */ + +/** + * Structures and functions for a shared memory buffer that can be shared across process. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if __ANDROID_API__ >= __ANDROID_API_O_MR1__ + +/** + * Returns a dup'd FD from the given Java android.os.SharedMemory object. The returned file + * descriptor has all the same properties & capabilities as the FD returned from + * ASharedMemory_create(), however the protection flags will be the same as those of the + * android.os.SharedMemory object. + * + * Use close() to release the shared memory region. + * + * \param env The JNIEnv* pointer + * \param sharedMemory The Java android.os.SharedMemory object + * \return file descriptor that denotes the shared memory; -1 if the shared memory object is + * already closed or if the JNIEnv or jobject is NULL. + */ +int ASharedMemory_dupFromJava(JNIEnv* env, jobject sharedMemory); + +#endif + +#ifdef __cplusplus +}; +#endif + +#endif // ANDROID_SHARED_MEMORY_JNI_H + +/** @} */ -- cgit v1.2.3-59-g8ed1b From b334e6c1e949961da674afa244a66455bff9184e Mon Sep 17 00:00:00 2001 From: Ivan Lozano Date: Tue, 8 Aug 2017 12:51:42 -0700 Subject: Remove IPlayer.h, use AIDL generated interface. Part of migrating our binder interfaces to AIDL, this removes the IPlayer implementation and uses the new aidl generated binder interface library. Test: run cts --module CtsMediaTestCases Bug: 64223827 Change-Id: I5ded5e15681165503d6e2f5a24233add79373f9c --- include/audiomanager/IPlayer.h | 69 -------------- services/audiomanager/Android.bp | 1 - services/audiomanager/IPlayer.cpp | 189 -------------------------------------- 3 files changed, 259 deletions(-) delete mode 100644 include/audiomanager/IPlayer.h delete mode 100644 services/audiomanager/IPlayer.cpp (limited to 'include') diff --git a/include/audiomanager/IPlayer.h b/include/audiomanager/IPlayer.h deleted file mode 100644 index de5c1c7b64..0000000000 --- a/include/audiomanager/IPlayer.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2017 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_IPLAYER_H -#define ANDROID_IPLAYER_H - -#include -#include - -#include -#include -#include -#include - -namespace android { - -// ---------------------------------------------------------------------------- - -class IPlayer : public IInterface -{ -public: - DECLARE_META_INTERFACE(Player); - - virtual void start() = 0; - - virtual void pause() = 0; - - virtual void stop() = 0; - - virtual void setVolume(float vol) = 0; - - virtual void setPan(float pan) = 0; - - virtual void setStartDelayMs(int delayMs) = 0; - - virtual void applyVolumeShaper( - const sp& configuration, - const sp& operation) = 0; -}; - -// ---------------------------------------------------------------------------- - -class BnPlayer : public BnInterface -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_IPLAYER_H diff --git a/services/audiomanager/Android.bp b/services/audiomanager/Android.bp index 22b084abc6..12ad47e15a 100644 --- a/services/audiomanager/Android.bp +++ b/services/audiomanager/Android.bp @@ -3,7 +3,6 @@ cc_library_shared { srcs: [ "IAudioManager.cpp", - "IPlayer.cpp", ], shared_libs: [ diff --git a/services/audiomanager/IPlayer.cpp b/services/audiomanager/IPlayer.cpp deleted file mode 100644 index e8a9c3472f..0000000000 --- a/services/audiomanager/IPlayer.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* -** -** Copyright 2017, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#define LOG_TAG "IPlayer" -//#define LOG_NDEBUG 0 -#include - -#include -#include - -#include - -#include - -namespace android { - -enum { - START = IBinder::FIRST_CALL_TRANSACTION, - PAUSE = IBinder::FIRST_CALL_TRANSACTION + 1, - STOP = IBinder::FIRST_CALL_TRANSACTION + 2, - SET_VOLUME = IBinder::FIRST_CALL_TRANSACTION + 3, - SET_PAN = IBinder::FIRST_CALL_TRANSACTION + 4, - SET_START_DELAY_MS = IBinder::FIRST_CALL_TRANSACTION + 5, - APPLY_VOLUME_SHAPER = IBinder::FIRST_CALL_TRANSACTION + 6, -}; - -class BpPlayer : public BpInterface -{ -public: - explicit BpPlayer(const sp& impl) - : BpInterface(impl) - { - } - - virtual void start() - { - Parcel data, reply; - data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); - remote()->transact(START, data, &reply); - } - - virtual void pause() - { - Parcel data, reply; - data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); - remote()->transact(PAUSE, data, &reply); - } - - virtual void stop() - { - Parcel data, reply; - data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); - remote()->transact(STOP, data, &reply); - } - - virtual void setVolume(float vol) - { - Parcel data, reply; - data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); - data.writeFloat(vol); - remote()->transact(SET_VOLUME, data, &reply); - } - - virtual void setPan(float pan) - { - Parcel data, reply; - data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); - data.writeFloat(pan); - remote()->transact(SET_PAN, data, &reply); - } - - virtual void setStartDelayMs(int32_t delayMs) { - Parcel data, reply; - data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); - data.writeInt32(delayMs); - remote()->transact(SET_START_DELAY_MS, data, &reply); - } - - virtual void applyVolumeShaper( - const sp& configuration, - const sp& operation) { - Parcel data, reply; - data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); - - status_t status = configuration.get() == nullptr - ? data.writeInt32(0) - : data.writeInt32(1) - ?: configuration->writeToParcel(&data); - if (status != NO_ERROR) { - ALOGW("applyVolumeShaper failed configuration parceling: %d", status); - return; // ignore error - } - - status = operation.get() == nullptr - ? status = data.writeInt32(0) - : data.writeInt32(1) - ?: operation->writeToParcel(&data); - if (status != NO_ERROR) { - ALOGW("applyVolumeShaper failed operation parceling: %d", status); - return; // ignore error - } - - status = remote()->transact(APPLY_VOLUME_SHAPER, data, &reply); - - ALOGW_IF(status != NO_ERROR, "applyVolumeShaper failed transact: %d", status); - return; // one way transaction, ignore error - } -}; - -IMPLEMENT_META_INTERFACE(Player, "android.media.IPlayer"); - -// ---------------------------------------------------------------------- - -status_t BnPlayer::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch (code) { - case START: { - CHECK_INTERFACE(IPlayer, data, reply); - start(); - return NO_ERROR; - } break; - case PAUSE: { - CHECK_INTERFACE(IPlayer, data, reply); - pause(); - return NO_ERROR; - } - case STOP: { - CHECK_INTERFACE(IPlayer, data, reply); - stop(); - return NO_ERROR; - } break; - case SET_VOLUME: { - CHECK_INTERFACE(IPlayer, data, reply); - setVolume(data.readFloat()); - return NO_ERROR; - } break; - case SET_PAN: { - CHECK_INTERFACE(IPlayer, data, reply); - setPan(data.readFloat()); - return NO_ERROR; - } break; - case SET_START_DELAY_MS: { - CHECK_INTERFACE(IPlayer, data, reply); - setStartDelayMs(data.readInt32()); - return NO_ERROR; - } break; - case APPLY_VOLUME_SHAPER: { - CHECK_INTERFACE(IPlayer, data, reply); - sp configuration; - sp operation; - - int32_t present; - status_t status = data.readInt32(&present); - if (status == NO_ERROR && present != 0) { - configuration = new VolumeShaper::Configuration(); - status = configuration->readFromParcel(data); - } - status = status ?: data.readInt32(&present); - if (status == NO_ERROR && present != 0) { - operation = new VolumeShaper::Operation(); - status = operation->readFromParcel(data); - } - if (status == NO_ERROR) { - // one way transaction, no error returned - applyVolumeShaper(configuration, operation); - } - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -} // namespace android -- cgit v1.2.3-59-g8ed1b From 1d04428c3cff3503212ec3e76775ca5ba20abc18 Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 27 Sep 2017 12:19:28 -0700 Subject: Added protobuf to gather layer info. Use protobuf to gather information about the layers. This change also uses protobuf for the layer dumpsys. Test: Ran dumpsys for layers to confirm the data was correct. Change-Id: Iec474e57a4fb9de1e548440d6a08685505947278 --- include/layerproto | 1 + services/surfaceflinger/Android.bp | 2 +- services/surfaceflinger/Android.mk | 7 +- services/surfaceflinger/Layer.cpp | 77 +++++++ services/surfaceflinger/Layer.h | 5 + services/surfaceflinger/LayerProtoHelper.cpp | 63 ++++++ services/surfaceflinger/LayerProtoHelper.h | 39 ++++ services/surfaceflinger/SurfaceFlinger.cpp | 26 ++- services/surfaceflinger/SurfaceFlinger.h | 5 + services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 26 ++- services/surfaceflinger/layerproto/Android.bp | 35 ++++ .../surfaceflinger/layerproto/LayerProtoParser.cpp | 223 +++++++++++++++++++++ .../include/layerproto/LayerProtoHeader.h | 23 +++ .../include/layerproto/LayerProtoParser.h | 174 ++++++++++++++++ services/surfaceflinger/layerproto/layers.proto | 110 ++++++++++ services/surfaceflinger/tests/fakehwc/Android.bp | 3 +- 16 files changed, 809 insertions(+), 10 deletions(-) create mode 120000 include/layerproto create mode 100644 services/surfaceflinger/LayerProtoHelper.cpp create mode 100644 services/surfaceflinger/LayerProtoHelper.h create mode 100644 services/surfaceflinger/layerproto/Android.bp create mode 100644 services/surfaceflinger/layerproto/LayerProtoParser.cpp create mode 100644 services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h create mode 100644 services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h create mode 100644 services/surfaceflinger/layerproto/layers.proto (limited to 'include') diff --git a/include/layerproto b/include/layerproto new file mode 120000 index 0000000000..ef21a4eb8e --- /dev/null +++ b/include/layerproto @@ -0,0 +1 @@ +../services/surfaceflinger/layerproto/include/layerproto/ \ No newline at end of file diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 64a2a509ab..bd7f0ea364 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -5,4 +5,4 @@ cc_library_static { export_static_lib_headers = ["libserviceutils"], } -subdirs = ["tests/fakehwc"] \ No newline at end of file +subdirs = ["tests/fakehwc", "layerproto"] \ No newline at end of file diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 390263ff2e..d8152e08cc 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -39,6 +39,7 @@ LOCAL_SRC_FILES := \ RenderEngine/RenderEngine.cpp \ RenderEngine/Texture.cpp \ RenderEngine/GLES20RenderEngine.cpp \ + LayerProtoHelper.cpp \ LOCAL_MODULE := libsurfaceflinger LOCAL_C_INCLUDES := \ @@ -98,7 +99,8 @@ LOCAL_SHARED_LIBRARIES := \ libsync \ libprotobuf-cpp-lite \ libbase \ - android.hardware.power@1.0 + android.hardware.power@1.0 \ + liblayers_proto LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \ android.hardware.graphics.allocator@2.0 \ @@ -145,7 +147,8 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ libui \ libgui \ - libdl + libdl \ + liblayers_proto LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain LOCAL_STATIC_LIBRARIES := libtrace_proto \ diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 956f7f6c02..27739ce074 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -56,6 +56,7 @@ #include "RenderEngine/RenderEngine.h" #include +#include "LayerProtoHelper.h" #define DEBUG_RESIZE 0 @@ -2826,6 +2827,82 @@ void Layer::commitChildList() { mDrawingParent = mCurrentParent; } +void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) { + const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; + const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; + const State& state = useDrawing ? mDrawingState : mCurrentState; + + Transform requestedTransform = state.active.transform; + Transform transform = getTransform(); + + layerInfo->set_id(sequence); + layerInfo->set_name(getName().c_str()); + layerInfo->set_type(String8(getTypeId())); + + for (const auto& child : children) { + layerInfo->add_children(child->sequence); + } + + for (const wp& weakRelative : state.zOrderRelatives) { + sp strongRelative = weakRelative.promote(); + if (strongRelative != nullptr) { + layerInfo->add_relatives(strongRelative->sequence); + } + } + + LayerProtoHelper::writeToProto(state.activeTransparentRegion, + layerInfo->mutable_transparent_region()); + LayerProtoHelper::writeToProto(visibleRegion, layerInfo->mutable_visible_region()); + LayerProtoHelper::writeToProto(surfaceDamageRegion, layerInfo->mutable_damage_region()); + + layerInfo->set_layer_stack(getLayerStack()); + layerInfo->set_z(state.z); + + PositionProto* position = layerInfo->mutable_position(); + position->set_x(transform.tx()); + position->set_y(transform.ty()); + + PositionProto* requestedPosition = layerInfo->mutable_requested_position(); + requestedPosition->set_x(requestedTransform.tx()); + requestedPosition->set_y(requestedTransform.ty()); + + SizeProto* size = layerInfo->mutable_size(); + size->set_w(state.active.w); + size->set_h(state.active.h); + + LayerProtoHelper::writeToProto(state.crop, layerInfo->mutable_crop()); + LayerProtoHelper::writeToProto(state.finalCrop, layerInfo->mutable_final_crop()); + + layerInfo->set_is_opaque(isOpaque(state)); + layerInfo->set_invalidate(contentDirty); + layerInfo->set_dataspace(dataspaceDetails(getDataSpace())); + layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat())); + LayerProtoHelper::writeToProto(getColor(), layerInfo->mutable_color()); + LayerProtoHelper::writeToProto(state.color, layerInfo->mutable_requested_color()); + layerInfo->set_flags(state.flags); + + LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform()); + LayerProtoHelper::writeToProto(requestedTransform, layerInfo->mutable_requested_transform()); + + auto parent = getParent(); + if (parent != nullptr) { + layerInfo->set_parent(parent->sequence); + } + + auto zOrderRelativeOf = state.zOrderRelativeOf.promote(); + if (zOrderRelativeOf != nullptr) { + layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence); + } + + auto activeBuffer = getActiveBuffer(); + if (activeBuffer != nullptr) { + LayerProtoHelper::writeToProto(activeBuffer, layerInfo->mutable_active_buffer()); + } + + layerInfo->set_queued_frames(getQueuedFrameCount()); + layerInfo->set_refresh_pending(isBufferLatched()); +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 47924ae877..06c4863ce2 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -49,9 +49,12 @@ #include "DisplayHardware/HWComposerBufferCache.h" #include "RenderEngine/Mesh.h" #include "RenderEngine/Texture.h" +#include #include +using namespace android::surfaceflinger; + namespace android { // --------------------------------------------------------------------------- @@ -303,6 +306,8 @@ public: */ virtual bool isFixedSize() const; + void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); + protected: /* * onDraw - draws the surface. diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp new file mode 100644 index 0000000000..6a33148d27 --- /dev/null +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LayerProtoHelper.h" + +namespace android { +namespace surfaceflinger { +void LayerProtoHelper::writeToProto(const Region& region, RegionProto* regionProto) { + Region::const_iterator head = region.begin(); + Region::const_iterator const tail = region.end(); + uint64_t address = reinterpret_cast(®ion); + regionProto->set_id(address); + while (head != tail) { + RectProto* rectProto = regionProto->add_rect(); + writeToProto(*head, rectProto); + head++; + } +} + +void LayerProtoHelper::writeToProto(const Rect& rect, RectProto* rectProto) { + rectProto->set_left(rect.left); + rectProto->set_top(rect.top); + rectProto->set_bottom(rect.bottom); + rectProto->set_right(rect.right); +} + +void LayerProtoHelper::writeToProto(const half4 color, ColorProto* colorProto) { + colorProto->set_r(color.r); + colorProto->set_g(color.g); + colorProto->set_b(color.b); + colorProto->set_a(color.a); +} + +void LayerProtoHelper::writeToProto(const Transform& transform, TransformProto* transformProto) { + transformProto->set_dsdx(transform[0][0]); + transformProto->set_dtdx(transform[0][1]); + transformProto->set_dsdy(transform[1][0]); + transformProto->set_dtdy(transform[1][1]); +} + +void LayerProtoHelper::writeToProto(const sp& buffer, + ActiveBufferProto* activeBufferProto) { + activeBufferProto->set_width(buffer->getWidth()); + activeBufferProto->set_height(buffer->getHeight()); + activeBufferProto->set_stride(buffer->getStride()); + activeBufferProto->set_format(buffer->format); +} + +} // namespace surfaceflinger +} // namespace android diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h new file mode 100644 index 0000000000..45a0b5d173 --- /dev/null +++ b/services/surfaceflinger/LayerProtoHelper.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#include + +#include + +namespace android { +namespace surfaceflinger { +class LayerProtoHelper { +public: + static void writeToProto(const Rect& rect, RectProto* rectProto); + static void writeToProto(const Region& region, RegionProto* regionProto); + static void writeToProto(const half4 color, ColorProto* colorProto); + static void writeToProto(const Transform& transform, TransformProto* transformProto); + static void writeToProto(const sp& buffer, ActiveBufferProto* activeBufferProto); +}; + +} // namespace surfaceflinger +} // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5982422658..4a982524b5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -90,6 +90,8 @@ #include #include +#include + #define DISPLAY_COUNT 1 /* @@ -3532,6 +3534,13 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args) { dumpWideColorInfo(result); dumpAll = false; } + + if ((index < numArgs) && (args[index] == String16("--proto"))) { + index++; + LayersProto layersProto = dumpProtoInfo(); + result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize()); + dumpAll = false; + } } if (dumpAll) { @@ -3727,6 +3736,16 @@ void SurfaceFlinger::dumpWideColorInfo(String8& result) const { result.append("\n"); } +LayersProto SurfaceFlinger::dumpProtoInfo() const { + LayersProto layersProto; + mCurrentState.traverseInZOrder([&](Layer* layer) { + LayerProto* layerProto = layersProto.add_layers(); + layer->writeToProto(layerProto, LayerVector::StateSet::Current); + }); + + return layersProto; +} + void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, String8& result) const { @@ -3791,9 +3810,10 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, colorizer.bold(result); result.appendFormat("Visible layers (count = %zu)\n", mNumLayers); colorizer.reset(result); - mCurrentState.traverseInZOrder([&](Layer* layer) { - result.append(to_string(layer->getLayerDebugInfo()).c_str()); - }); + + LayersProto layersProto = dumpProtoInfo(); + auto layerTree = LayerProtoParser::generateLayerTree(layersProto); + result.append(LayerProtoParser::layersToString(layerTree).c_str()); /* * Dump Display state diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 2cba500500..9030124e8d 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -78,6 +78,10 @@ #include #include +#include + +using namespace android::surfaceflinger; + namespace android { // --------------------------------------------------------------------------- @@ -622,6 +626,7 @@ private: std::vector&& history); void dumpBufferingStats(String8& result) const; void dumpWideColorInfo(String8& result) const; + LayersProto dumpProtoInfo() const; bool isLayerTripleBufferingDisabled() const { return this->mLayerTripleBufferingDisabled; diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index b718ec806c..ed7641fe99 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -87,6 +87,8 @@ #include #include +#include + #define DISPLAY_COUNT 1 /* @@ -3073,6 +3075,13 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args) dumpFrameEventsLocked(result); dumpAll = false; } + + if ((index < numArgs) && (args[index] == String16("--proto"))) { + index++; + LayersProto layersProto = dumpProtoInfo(); + result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize()); + dumpAll = false; + } } if (dumpAll) { @@ -3243,6 +3252,16 @@ void SurfaceFlinger::dumpBufferingStats(String8& result) const { result.append("\n"); } +LayersProto SurfaceFlinger::dumpProtoInfo() const { + LayersProto layersProto; + mCurrentState.traverseInZOrder([&](Layer* layer) { + LayerProto* layerProto = layersProto.add_layers(); + layer->writeToProto(layerProto, LayerVector::StateSet::Current); + }); + + return layersProto; +} + void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, String8& result) const { @@ -3302,9 +3321,10 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, colorizer.bold(result); result.appendFormat("Visible layers (count = %zu)\n", mNumLayers); colorizer.reset(result); - mCurrentState.traverseInZOrder([&](Layer* layer) { - result.append(to_string(layer->getLayerDebugInfo()).c_str()); - }); + + LayersProto layersProto = dumpProtoInfo(); + auto layerTree = LayerProtoParser::generateLayerTree(layersProto); + result.append(LayerProtoParser::layersToString(layerTree).c_str()); /* * Dump Display state diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp new file mode 100644 index 0000000000..4c52bdfaa7 --- /dev/null +++ b/services/surfaceflinger/layerproto/Android.bp @@ -0,0 +1,35 @@ +cc_library_shared { + name: "liblayers_proto", + vendor_available: true, + export_include_dirs: ["include"], + + srcs: [ + "LayerProtoParser.cpp", + "layers.proto", + ], + + shared_libs: [ + "libui", + "libprotobuf-cpp-lite", + "libbase", + ], + + proto: { + export_proto_headers: true, + }, + + cppflags: [ + "-Werror", + "-Wno-unused-parameter", + "-Wno-format", + "-Wno-c++98-compat-pedantic", + "-Wno-float-conversion", + "-Wno-disabled-macro-expansion", + "-Wno-float-equal", + "-Wno-sign-conversion", + "-Wno-padded", + "-Wno-old-style-cast", + "-Wno-undef", + ], + +} \ No newline at end of file diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp new file mode 100644 index 0000000000..65541674f1 --- /dev/null +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace android { +namespace surfaceflinger { +bool sortLayers(const LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) { + uint32_t ls = lhs->layerStack; + uint32_t rs = rhs->layerStack; + if (ls != rs) return ls < rs; + + uint32_t lz = lhs->z; + uint32_t rz = rhs->z; + if (lz != rz) return lz < rz; + + return lhs->id < rhs->id; +} + +std::vector LayerProtoParser::generateLayerTree( + const LayersProto& layersProto) { + auto layerMap = generateMap(layersProto); + + std::vector layers; + std::for_each(layerMap.begin(), layerMap.end(), + [&](const std::pair& ref) { + if (ref.second->parent == nullptr) { + // only save top level layers + layers.push_back(ref.second); + } + }); + + std::sort(layers.begin(), layers.end(), sortLayers); + return layers; +} + +std::unordered_map LayerProtoParser::generateMap( + const LayersProto& layersProto) { + std::unordered_map layerMap; + + for (int i = 0; i < layersProto.layers_size(); i++) { + const LayerProto& layerProto = layersProto.layers(i); + layerMap[layerProto.id()] = generateLayer(layerProto); + } + + for (int i = 0; i < layersProto.layers_size(); i++) { + const LayerProto& layerProto = layersProto.layers(i); + updateChildrenAndRelative(layerProto, layerMap); + } + + return layerMap; +} + +LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layerProto) { + Layer* layer = new Layer(); + layer->id = layerProto.id(); + layer->name = layerProto.name(); + layer->type = layerProto.type(); + layer->transparentRegion = generateRegion(layerProto.transparent_region()); + layer->visibleRegion = generateRegion(layerProto.visible_region()); + layer->damageRegion = generateRegion(layerProto.damage_region()); + layer->layerStack = layerProto.layer_stack(); + layer->z = layerProto.z(); + layer->position = {layerProto.position().x(), layerProto.position().y()}; + layer->requestedPosition = {layerProto.requested_position().x(), + layerProto.requested_position().y()}; + layer->size = {layerProto.size().w(), layerProto.size().h()}; + layer->crop = generateRect(layerProto.crop()); + layer->finalCrop = generateRect(layerProto.final_crop()); + layer->isOpaque = layerProto.is_opaque(); + layer->invalidate = layerProto.invalidate(); + layer->dataspace = layerProto.dataspace(); + layer->pixelFormat = layerProto.pixel_format(); + layer->color = {layerProto.color().r(), layerProto.color().g(), layerProto.color().b(), + layerProto.color().a()}; + layer->requestedColor = {layerProto.requested_color().r(), layerProto.requested_color().g(), + layerProto.requested_color().b(), layerProto.requested_color().a()}; + layer->flags = layerProto.flags(); + layer->transform = generateTransform(layerProto.transform()); + layer->requestedTransform = generateTransform(layerProto.requested_transform()); + layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer()); + layer->queuedFrames = layerProto.queued_frames(); + layer->refreshPending = layerProto.refresh_pending(); + + return layer; +} + +LayerProtoParser::Region LayerProtoParser::generateRegion(const RegionProto& regionProto) { + LayerProtoParser::Region region; + region.id = regionProto.id(); + for (int i = 0; i < regionProto.rect_size(); i++) { + const RectProto& rectProto = regionProto.rect(i); + region.rects.push_back(generateRect(rectProto)); + } + + return region; +} + +LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto) { + LayerProtoParser::Rect rect; + rect.left = rectProto.left(); + rect.top = rectProto.top(); + rect.right = rectProto.right(); + rect.bottom = rectProto.bottom(); + + return rect; +} + +LayerProtoParser::Transform LayerProtoParser::generateTransform( + const TransformProto& transformProto) { + LayerProtoParser::Transform transform; + transform.dsdx = transformProto.dsdx(); + transform.dtdx = transformProto.dtdx(); + transform.dsdy = transformProto.dsdy(); + transform.dtdy = transformProto.dtdy(); + + return transform; +} + +LayerProtoParser::ActiveBuffer LayerProtoParser::generateActiveBuffer( + const ActiveBufferProto& activeBufferProto) { + LayerProtoParser::ActiveBuffer activeBuffer; + activeBuffer.width = activeBufferProto.width(); + activeBuffer.height = activeBufferProto.height(); + activeBuffer.stride = activeBufferProto.stride(); + activeBuffer.format = activeBufferProto.format(); + + return activeBuffer; +} + +void LayerProtoParser::updateChildrenAndRelative(const LayerProto& layerProto, + std::unordered_map& layerMap) { + auto currLayer = layerMap[layerProto.id()]; + + for (int i = 0; i < layerProto.children_size(); i++) { + if (layerMap.count(layerProto.children(i)) > 0) { + auto childLayer = layerMap[layerProto.children(i)]; + currLayer->children.push_back(childLayer); + } + } + + for (int i = 0; i < layerProto.relatives_size(); i++) { + if (layerMap.count(layerProto.relatives(i)) > 0) { + auto relativeLayer = layerMap[layerProto.relatives(i)]; + currLayer->relatives.push_back(relativeLayer); + } + } + + if (layerProto.has_parent()) { + if (layerMap.count(layerProto.parent()) > 0) { + auto parentLayer = layerMap[layerProto.parent()]; + currLayer->parent = parentLayer; + } + } + + if (layerProto.has_z_order_relative_of()) { + if (layerMap.count(layerProto.z_order_relative_of()) > 0) { + auto relativeLayer = layerMap[layerProto.z_order_relative_of()]; + currLayer->zOrderRelativeOf = relativeLayer; + } + } +} + +std::string LayerProtoParser::layersToString( + const std::vector layers) { + std::string result; + for (const LayerProtoParser::Layer* layer : layers) { + if (layer->zOrderRelativeOf != nullptr) { + continue; + } + result.append(layerToString(layer).c_str()); + } + + return result; +} + +std::string LayerProtoParser::layerToString(const LayerProtoParser::Layer* layer) { + std::string result; + + std::vector traverse(layer->relatives); + for (const LayerProtoParser::Layer* child : layer->children) { + if (child->zOrderRelativeOf != nullptr) { + continue; + } + + traverse.push_back(child); + } + + std::sort(traverse.begin(), traverse.end(), sortLayers); + + size_t i = 0; + for (; i < traverse.size(); i++) { + const auto& relative = traverse[i]; + if (relative->z >= 0) { + break; + } + result.append(layerToString(relative).c_str()); + } + result.append(layer->to_string().c_str()); + result.append("\n"); + for (; i < traverse.size(); i++) { + const auto& relative = traverse[i]; + result.append(layerToString(relative).c_str()); + } + + return result; +} + +} // namespace surfaceflinger +} // namespace android diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h new file mode 100644 index 0000000000..054d4f2cbc --- /dev/null +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2007 The Android Open Source Projectlayerproto/LayerProtoHeader.h + * + * 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. + */ + +// pragma is used here to disable the warnings emitted from the protobuf +// headers. By adding #pragma before including layer.pb.h, it supresses +// protobuf warnings, but allows the rest of the files to continuing using +// the current flags. +// This file should be included instead of directly including layer.b.h +#pragma GCC system_header +#include diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h new file mode 100644 index 0000000000..7b94cefbc8 --- /dev/null +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include +#include +#include +#include + +using android::base::StringAppendF; +using android::base::StringPrintf; + +namespace android { +namespace surfaceflinger { + +class LayerProtoParser { +public: + class ActiveBuffer { + public: + uint32_t width; + uint32_t height; + uint32_t stride; + int32_t format; + + std::string to_string() const { + return StringPrintf("[%4ux%4u:%4u,%s]", width, height, stride, + decodePixelFormat(format).c_str()); + } + }; + + class Transform { + public: + float dsdx; + float dtdx; + float dsdy; + float dtdy; + + std::string to_string() const { + return StringPrintf("[%.2f, %.2f][%.2f, %.2f]", static_cast(dsdx), + static_cast(dtdx), static_cast(dsdy), + static_cast(dtdy)); + } + }; + + class Rect { + public: + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; + + std::string to_string() const { + return StringPrintf("[%3d, %3d, %3d, %3d]", left, top, right, bottom); + } + }; + + class Region { + public: + uint64_t id; + std::vector rects; + + std::string to_string(const char* what) const { + std::string result = + StringPrintf(" Region %s (this=%lx count=%d)\n", what, + static_cast(id), static_cast(rects.size())); + + for (auto& rect : rects) { + StringAppendF(&result, " %s\n", rect.to_string().c_str()); + } + + return result; + } + }; + + class Layer { + public: + int32_t id; + std::string name; + std::vector children; + std::vector relatives; + std::string type; + LayerProtoParser::Region transparentRegion; + LayerProtoParser::Region visibleRegion; + LayerProtoParser::Region damageRegion; + uint32_t layerStack; + int32_t z; + float2 position; + float2 requestedPosition; + int2 size; + LayerProtoParser::Rect crop; + LayerProtoParser::Rect finalCrop; + bool isOpaque; + bool invalidate; + std::string dataspace; + std::string pixelFormat; + half4 color; + half4 requestedColor; + uint32_t flags; + Transform transform; + Transform requestedTransform; + Layer* parent = 0; + Layer* zOrderRelativeOf = 0; + LayerProtoParser::ActiveBuffer activeBuffer; + int32_t queuedFrames; + bool refreshPending; + + std::string to_string() const { + std::string result; + StringAppendF(&result, "+ %s (%s)\n", type.c_str(), name.c_str()); + result.append(transparentRegion.to_string("TransparentRegion").c_str()); + result.append(visibleRegion.to_string("VisibleRegion").c_str()); + result.append(damageRegion.to_string("SurfaceDamageRegion").c_str()); + + StringAppendF(&result, " layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), ", + layerStack, z, static_cast(position.x), + static_cast(position.y), size.x, size.y); + + StringAppendF(&result, "crop=%s, finalCrop=%s, ", crop.to_string().c_str(), + finalCrop.to_string().c_str()); + StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate); + StringAppendF(&result, "dataspace=%s, ", dataspace.c_str()); + StringAppendF(&result, "pixelformat=%s, ", pixelFormat.c_str()); + StringAppendF(&result, "color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ", + static_cast(color.r), static_cast(color.g), + static_cast(color.b), static_cast(color.a), flags); + StringAppendF(&result, "tr=%s", transform.to_string().c_str()); + result.append("\n"); + StringAppendF(&result, " parent=%s\n", + parent == nullptr ? "none" : parent->name.c_str()); + StringAppendF(&result, " zOrderRelativeOf=%s\n", + zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str()); + StringAppendF(&result, " activeBuffer=%s,", activeBuffer.to_string().c_str()); + StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d", queuedFrames, + refreshPending); + + return result; + } + }; + + static std::vector generateLayerTree(const LayersProto& layersProto); + static std::string layersToString(const std::vector layers); + +private: + static std::unordered_map generateMap(const LayersProto& layersProto); + static LayerProtoParser::Layer* generateLayer(const LayerProto& layerProto); + static LayerProtoParser::Region generateRegion(const RegionProto& regionProto); + static LayerProtoParser::Rect generateRect(const RectProto& rectProto); + static LayerProtoParser::Transform generateTransform(const TransformProto& transformProto); + static LayerProtoParser::ActiveBuffer generateActiveBuffer( + const ActiveBufferProto& activeBufferProto); + static void updateChildrenAndRelative(const LayerProto& layerProto, + std::unordered_map& layerMap); + + static std::string layerToString(const LayerProtoParser::Layer* layer); +}; + +} // namespace surfaceflinger +} // namespace android diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto new file mode 100644 index 0000000000..d27dc9b2ea --- /dev/null +++ b/services/surfaceflinger/layerproto/layers.proto @@ -0,0 +1,110 @@ +// Definitions for SurfaceFlinger layers. + +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; +package android.surfaceflinger; + +// Contains a list of all layers. +message LayersProto { + repeated LayerProto layers = 1; +} + +// Information about each layer. +message LayerProto { + // unique id per layer. + optional int32 id = 1; + // unique name per layer. + optional string name = 2; + // list of children this layer may have. May be empty. + repeated int32 children = 3; + // list of layers that are z order relative to this layer. + repeated int32 relatives = 4; + // The type of layer, ex Color, Layer + optional string type = 5; + optional RegionProto transparent_region = 6; + optional RegionProto visible_region = 7; + optional RegionProto damage_region = 8; + optional uint32 layer_stack = 9; + // The layer's z order. Can be z order in layer stack, relative to parent, + // or relative to another layer specified in zOrderRelative. + optional int32 z = 10; + // The layer's position on the display. + optional PositionProto position = 11; + // The layer's requested position. + optional PositionProto requested_position = 12; + // The layer's size. + optional SizeProto size = 13; + // The layer's crop in it's own bounds. + optional RectProto crop = 14; + // The layer's crop in it's parent's bounds. + optional RectProto final_crop = 15; + optional bool is_opaque = 16; + optional bool invalidate = 17; + optional string dataspace = 18; + optional string pixel_format = 19; + // The layer's actual color. + optional ColorProto color = 20; + // The layer's requested color. + optional ColorProto requested_color = 21; + // Can be any combination of + // hidden = 0x01 + // opaque = 0x02, + // secure = 0x80, + optional uint32 flags = 22; + // The layer's actual transform + optional TransformProto transform = 23; + // The layer's requested transform. + optional TransformProto requested_transform = 24; + // The parent layer. This value can be null if there is no parent. + optional int32 parent = 25 [default = -1]; + // The layer that this layer has a z order relative to. This value can be null. + optional int32 z_order_relative_of = 26 [default = -1]; + // This value can be null if there's nothing to draw. + optional ActiveBufferProto active_buffer = 27; + // The number of frames available. + optional int32 queued_frames = 28; + optional bool refresh_pending = 29; +} + +message PositionProto { + optional float x = 1; + optional float y = 2; +} + +message SizeProto { + optional int32 w = 1; + optional int32 h = 2; +} + +message TransformProto { + optional float dsdx = 1; + optional float dtdx = 2; + optional float dsdy = 3; + optional float dtdy = 4; +} + +message RegionProto { + optional uint64 id = 1; + repeated RectProto rect = 2; +} + +message RectProto { + optional int32 left = 1; + optional int32 top = 2; + optional int32 right = 3; + optional int32 bottom = 4; +} + +message ActiveBufferProto { + optional uint32 width = 1; + optional uint32 height = 2; + optional uint32 stride = 3; + optional int32 format = 4; +} + +message ColorProto { + optional float r = 1; + optional float g = 2; + optional float b = 3; + optional float a = 4; +} \ No newline at end of file diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp index 94f3f2561a..212b9e7ebb 100644 --- a/services/surfaceflinger/tests/fakehwc/Android.bp +++ b/services/surfaceflinger/tests/fakehwc/Android.bp @@ -22,7 +22,8 @@ cc_test { "libsync", "libfmq", "libbase", - "libhidltransport" + "libhidltransport", + "liblayers_proto" ], static_libs: [ "libhwcomposer-client", -- cgit v1.2.3-59-g8ed1b From 635cb71a65d361ec107afeafcb49488f6812f7d1 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Wed, 1 Nov 2017 16:32:14 -0700 Subject: Fix broken input tests InputPublisherAndConsumer_test currently segfaults due to null pointer dereference. This is because 0 is passed instead of a valid pointer to an allocated int32_t. Also, enforce strict compiler warnings, include signed comparisons. Bug: 62033391 Test: m -j libinput_tests_InputEvent_test libinput_tests_InputChannel_test libinput_tests_InputPublisherAndConsumer_test libinput_tests_InputTransport_test libinput_tests_VelocityTracker_test && adb push out/target/product/taimen/data/nativetest/libinput_tests/ /data/nativetest/ then run the above tests individually, for example /data/nativetest/libinput_tests # ./InputPublisherAndConsumer_test and others in a similar manner Change-Id: Ia030cdbfa22d2bf7bdf6274a337b059ca3f9a6c3 --- include/input/InputTransport.h | 2 +- libs/input/tests/Android.bp | 2 +- libs/input/tests/InputEvent_test.cpp | 8 ++++---- libs/input/tests/InputPublisherAndConsumer_test.cpp | 7 ++++--- services/inputflinger/InputDispatcher.cpp | 5 ++--- services/inputflinger/InputReader.cpp | 8 ++------ 6 files changed, 14 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 944947420e..c4b5dca23d 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -455,7 +455,6 @@ private: int32_t* displayId); void updateTouchState(InputMessage& msg); - bool rewriteMessage(const TouchState& state, InputMessage& msg); void resampleTouchState(nsecs_t frameTime, MotionEvent* event, const InputMessage *next); @@ -464,6 +463,7 @@ private: status_t sendUnchainedFinishedSignal(uint32_t seq, bool handled); + static bool rewriteMessage(const TouchState& state, InputMessage& msg); static void initializeKeyEvent(KeyEvent* event, const InputMessage* msg); static void initializeMotionEvent(MotionEvent* event, const InputMessage* msg); static void addSample(MotionEvent* event, const InputMessage* msg); diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp index e0bab1156b..aca9521c76 100644 --- a/libs/input/tests/Android.bp +++ b/libs/input/tests/Android.bp @@ -10,8 +10,8 @@ cc_test { ], cflags: [ "-Wall", + "-Wextra", "-Werror", - "-Wno-error=sign-compare", // to fix later "-Wno-unused-variable", ], shared_libs: [ diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp index 3fb1c6df9b..fd3b7c8ee4 100644 --- a/libs/input/tests/InputEvent_test.cpp +++ b/libs/input/tests/InputEvent_test.cpp @@ -184,7 +184,7 @@ TEST_F(KeyEventTest, Properties) { ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event.getType()); ASSERT_EQ(2, event.getDeviceId()); - ASSERT_EQ(AINPUT_SOURCE_GAMEPAD, event.getSource()); + ASSERT_EQ(static_cast(AINPUT_SOURCE_GAMEPAD), event.getSource()); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, event.getAction()); ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, event.getFlags()); ASSERT_EQ(AKEYCODE_BUTTON_X, event.getKeyCode()); @@ -196,7 +196,7 @@ TEST_F(KeyEventTest, Properties) { // Set source. event.setSource(AINPUT_SOURCE_JOYSTICK); - ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource()); + ASSERT_EQ(static_cast(AINPUT_SOURCE_JOYSTICK), event.getSource()); } @@ -300,7 +300,7 @@ void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) { // Check properties. ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()); ASSERT_EQ(2, event->getDeviceId()); - ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, event->getSource()); + ASSERT_EQ(static_cast(AINPUT_SOURCE_TOUCHSCREEN), event->getSource()); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event->getAction()); ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags()); ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags()); @@ -432,7 +432,7 @@ TEST_F(MotionEventTest, Properties) { // Set source. event.setSource(AINPUT_SOURCE_JOYSTICK); - ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource()); + ASSERT_EQ(static_cast(AINPUT_SOURCE_JOYSTICK), event.getSource()); // Set action. event.setAction(AMOTION_EVENT_ACTION_CANCEL); diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp index a1367387bc..34c52d03d1 100644 --- a/libs/input/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp @@ -89,8 +89,9 @@ void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() { uint32_t consumeSeq; InputEvent* event; + int32_t displayId; status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event, - 0); + &displayId); ASSERT_EQ(OK, status) << "consumer consume should return OK"; @@ -133,7 +134,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { const uint32_t seq = 15; const int32_t deviceId = 1; const int32_t source = AINPUT_SOURCE_TOUCHSCREEN; - const int32_t displayId = 0; + int32_t displayId = 0; const int32_t action = AMOTION_EVENT_ACTION_MOVE; const int32_t actionButton = 0; const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED; @@ -176,7 +177,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { uint32_t consumeSeq; InputEvent* event; status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event, - 0); + &displayId); ASSERT_EQ(OK, status) << "consumer consume should return OK"; diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp index 031218562f..906794aee9 100644 --- a/services/inputflinger/InputDispatcher.cpp +++ b/services/inputflinger/InputDispatcher.cpp @@ -1993,10 +1993,10 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, const PointerCoords* usingCoords = motionEntry->pointerCoords; // Set the X and Y offset depending on the input source. - float xOffset, yOffset, scaleFactor; + float xOffset, yOffset; if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) { - scaleFactor = dispatchEntry->scaleFactor; + float scaleFactor = dispatchEntry->scaleFactor; xOffset = dispatchEntry->xOffset * scaleFactor; yOffset = dispatchEntry->yOffset * scaleFactor; if (scaleFactor != 1.0f) { @@ -2009,7 +2009,6 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, } else { xOffset = 0.0f; yOffset = 0.0f; - scaleFactor = 1.0f; // We don't want the dispatch target to know. if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) { diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp index 6dd12d6bdd..4304982687 100644 --- a/services/inputflinger/InputReader.cpp +++ b/services/inputflinger/InputReader.cpp @@ -2258,7 +2258,7 @@ void KeyboardInputMapper::dump(String8& dump) { dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation); dump.appendFormat(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size()); dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState); - dump.appendFormat(INDENT3 "DownTime: %lld\n", (long long)mDownTime); + dump.appendFormat(INDENT3 "DownTime: %" PRId64 "\n", mDownTime); } @@ -2619,7 +2619,7 @@ void CursorInputMapper::dump(String8& dump) { dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation); dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState); dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState))); - dump.appendFormat(INDENT3 "DownTime: %lld\n", (long long)mDownTime); + dump.appendFormat(INDENT3 "DownTime: %" PRId64 "\n", mDownTime); } void CursorInputMapper::configure(nsecs_t when, @@ -5508,18 +5508,15 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, // Otherwise choose an arbitrary remaining pointer. // This guarantees we always have an active touch id when there is at least one pointer. // We keep the same active touch id for as long as possible. - bool activeTouchChanged = false; int32_t lastActiveTouchId = mPointerGesture.activeTouchId; int32_t activeTouchId = lastActiveTouchId; if (activeTouchId < 0) { if (!mCurrentCookedState.fingerIdBits.isEmpty()) { - activeTouchChanged = true; activeTouchId = mPointerGesture.activeTouchId = mCurrentCookedState.fingerIdBits.firstMarkedBit(); mPointerGesture.firstTouchTime = when; } } else if (!mCurrentCookedState.fingerIdBits.hasBit(activeTouchId)) { - activeTouchChanged = true; if (!mCurrentCookedState.fingerIdBits.isEmpty()) { activeTouchId = mPointerGesture.activeTouchId = mCurrentCookedState.fingerIdBits.firstMarkedBit(); @@ -5615,7 +5612,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, } if (bestId >= 0 && bestId != activeTouchId) { mPointerGesture.activeTouchId = activeTouchId = bestId; - activeTouchChanged = true; #if DEBUG_GESTURES ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, " "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed); -- cgit v1.2.3-59-g8ed1b From f93fcf4c403fa4181536821680d495824a4290c5 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Wed, 22 Nov 2017 16:00:14 -0800 Subject: Prefer std::string over String8 String8 is obsolete, only use std::string in the input libraries now. Bug: 64258224 Test: make Change-Id: I958b6b281d969138f39cc26825c877a24bc4a853 --- include/input/InputTransport.h | 9 +- libs/input/InputTransport.cpp | 62 ++-- libs/input/tests/InputChannel_test.cpp | 16 +- .../input/tests/InputPublisherAndConsumer_test.cpp | 2 +- services/inputflinger/Android.bp | 1 + services/inputflinger/EventHub.cpp | 39 +- services/inputflinger/EventHub.h | 5 +- services/inputflinger/InputApplication.h | 8 +- services/inputflinger/InputDispatcher.cpp | 271 +++++++------- services/inputflinger/InputDispatcher.h | 29 +- services/inputflinger/InputReader.cpp | 401 +++++++++++---------- services/inputflinger/InputReader.h | 49 ++- services/inputflinger/InputWindow.h | 7 +- .../inputflinger/tests/InputDispatcher_test.cpp | 2 +- services/inputflinger/tests/InputReader_test.cpp | 2 +- 15 files changed, 451 insertions(+), 452 deletions(-) (limited to 'include') diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index c4b5dca23d..6187528cff 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -142,16 +141,16 @@ protected: virtual ~InputChannel(); public: - InputChannel(const String8& name, int fd); + InputChannel(const std::string& name, int fd); /* Creates a pair of input channels. * * Returns OK on success. */ - static status_t openInputChannelPair(const String8& name, + static status_t openInputChannelPair(const std::string& name, sp& outServerChannel, sp& outClientChannel); - inline String8 getName() const { return mName; } + inline std::string getName() const { return mName; } inline int getFd() const { return mFd; } /* Sends a message to the other endpoint. @@ -183,7 +182,7 @@ public: sp dup() const; private: - String8 mName; + std::string mName; int mFd; }; diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index b8901bd123..5fe8d8bc9c 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -99,34 +99,34 @@ size_t InputMessage::size() const { // --- InputChannel --- -InputChannel::InputChannel(const String8& name, int fd) : +InputChannel::InputChannel(const std::string& name, int fd) : mName(name), mFd(fd) { #if DEBUG_CHANNEL_LIFECYCLE ALOGD("Input channel constructed: name='%s', fd=%d", - mName.string(), fd); + mName.c_str(), fd); #endif int result = fcntl(mFd, F_SETFL, O_NONBLOCK); LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make socket " - "non-blocking. errno=%d", mName.string(), errno); + "non-blocking. errno=%d", mName.c_str(), errno); } InputChannel::~InputChannel() { #if DEBUG_CHANNEL_LIFECYCLE ALOGD("Input channel destroyed: name='%s', fd=%d", - mName.string(), mFd); + mName.c_str(), mFd); #endif ::close(mFd); } -status_t InputChannel::openInputChannelPair(const String8& name, +status_t InputChannel::openInputChannelPair(const std::string& name, sp& outServerChannel, sp& outClientChannel) { int sockets[2]; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) { status_t result = -errno; ALOGE("channel '%s' ~ Could not create socket pair. errno=%d", - name.string(), errno); + name.c_str(), errno); outServerChannel.clear(); outClientChannel.clear(); return result; @@ -138,12 +138,12 @@ status_t InputChannel::openInputChannelPair(const String8& name, setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)); setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)); - String8 serverChannelName = name; - serverChannelName.append(" (server)"); + std::string serverChannelName = name; + serverChannelName += " (server)"; outServerChannel = new InputChannel(serverChannelName, sockets[0]); - String8 clientChannelName = name; - clientChannelName.append(" (client)"); + std::string clientChannelName = name; + clientChannelName += " (client)"; outClientChannel = new InputChannel(clientChannelName, sockets[1]); return OK; } @@ -158,7 +158,7 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { if (nWrite < 0) { int error = errno; #if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ error sending message of type %d, errno=%d", mName.string(), + ALOGD("channel '%s' ~ error sending message of type %d, errno=%d", mName.c_str(), msg->header.type, error); #endif if (error == EAGAIN || error == EWOULDBLOCK) { @@ -173,13 +173,13 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { if (size_t(nWrite) != msgLength) { #if DEBUG_CHANNEL_MESSAGES ALOGD("channel '%s' ~ error sending message type %d, send was incomplete", - mName.string(), msg->header.type); + mName.c_str(), msg->header.type); #endif return DEAD_OBJECT; } #if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ sent message of type %d", mName.string(), msg->header.type); + ALOGD("channel '%s' ~ sent message of type %d", mName.c_str(), msg->header.type); #endif return OK; } @@ -193,7 +193,7 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { if (nRead < 0) { int error = errno; #if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ receive message failed, errno=%d", mName.string(), errno); + ALOGD("channel '%s' ~ receive message failed, errno=%d", mName.c_str(), errno); #endif if (error == EAGAIN || error == EWOULDBLOCK) { return WOULD_BLOCK; @@ -206,20 +206,20 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { if (nRead == 0) { // check for EOF #if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ receive message failed because peer was closed", mName.string()); + ALOGD("channel '%s' ~ receive message failed because peer was closed", mName.c_str()); #endif return DEAD_OBJECT; } if (!msg->isValid(nRead)) { #if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ received invalid message", mName.string()); + ALOGD("channel '%s' ~ received invalid message", mName.c_str()); #endif return BAD_VALUE; } #if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ received message of type %d", mName.string(), msg->header.type); + ALOGD("channel '%s' ~ received message of type %d", mName.c_str(), msg->header.type); #endif return OK; } @@ -255,7 +255,7 @@ status_t InputPublisher::publishKeyEvent( ALOGD("channel '%s' publisher ~ publishKeyEvent: seq=%u, deviceId=%d, source=0x%x, " "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d," "downTime=%" PRId64 ", eventTime=%" PRId64, - mChannel->getName().string(), seq, + mChannel->getName().c_str(), seq, deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount, downTime, eventTime); #endif @@ -307,7 +307,7 @@ status_t InputPublisher::publishMotionEvent( "metaState=0x%x, buttonState=0x%x, xOffset=%f, yOffset=%f, " "xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", eventTime=%" PRId64 ", " "pointerCount=%" PRIu32, - mChannel->getName().string(), seq, + mChannel->getName().c_str(), seq, deviceId, source, action, actionButton, flags, edgeFlags, metaState, buttonState, xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount); #endif @@ -319,7 +319,7 @@ status_t InputPublisher::publishMotionEvent( if (pointerCount > MAX_POINTERS || pointerCount < 1) { ALOGE("channel '%s' publisher ~ Invalid number of pointers provided: %" PRIu32 ".", - mChannel->getName().string(), pointerCount); + mChannel->getName().c_str(), pointerCount); return BAD_VALUE; } @@ -352,7 +352,7 @@ status_t InputPublisher::publishMotionEvent( status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled) { #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' publisher ~ receiveFinishedSignal", - mChannel->getName().string()); + mChannel->getName().c_str()); #endif InputMessage msg; @@ -364,7 +364,7 @@ status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandle } if (msg.header.type != InputMessage::TYPE_FINISHED) { ALOGE("channel '%s' publisher ~ Received unexpected message of type %d from consumer", - mChannel->getName().string(), msg.header.type); + mChannel->getName().c_str(), msg.header.type); return UNKNOWN_ERROR; } *outSeq = msg.body.finished.seq; @@ -402,7 +402,7 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, int32_t* displayId) { #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%" PRId64, - mChannel->getName().string(), consumeBatches ? "true" : "false", frameTime); + mChannel->getName().c_str(), consumeBatches ? "true" : "false", frameTime); #endif *outSeq = 0; @@ -426,7 +426,7 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, if (*outEvent) { #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u", - mChannel->getName().string(), *outSeq); + mChannel->getName().c_str(), *outSeq); #endif break; } @@ -445,7 +445,7 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, *outEvent = keyEvent; #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ consumed key event, seq=%u", - mChannel->getName().string(), *outSeq); + mChannel->getName().c_str(), *outSeq); #endif break; } @@ -458,7 +458,7 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, batch.samples.push(mMsg); #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ appended to batch event", - mChannel->getName().string()); + mChannel->getName().c_str()); #endif break; } else { @@ -474,7 +474,7 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ consumed batch event and " "deferred current event, seq=%u", - mChannel->getName().string(), *outSeq); + mChannel->getName().c_str(), *outSeq); #endif break; } @@ -488,7 +488,7 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, batch.samples.push(mMsg); #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ started batch event", - mChannel->getName().string()); + mChannel->getName().c_str()); #endif break; } @@ -503,14 +503,14 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, *displayId = mMsg.body.motion.displayId; #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ consumed motion event, seq=%u", - mChannel->getName().string(), *outSeq); + mChannel->getName().c_str(), *outSeq); #endif break; } default: ALOGE("channel '%s' consumer ~ Received unexpected message of type %d", - mChannel->getName().string(), mMsg.header.type); + mChannel->getName().c_str(), mMsg.header.type); return UNKNOWN_ERROR; } } @@ -828,7 +828,7 @@ bool InputConsumer::shouldResampleTool(int32_t toolType) { status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) { #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ sendFinishedSignal: seq=%u, handled=%s", - mChannel->getName().string(), seq, handled ? "true" : "false"); + mChannel->getName().c_str(), seq, handled ? "true" : "false"); #endif if (!seq) { diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp index e71ebe2a1d..96c165cac2 100644 --- a/libs/input/tests/InputChannel_test.cpp +++ b/libs/input/tests/InputChannel_test.cpp @@ -41,9 +41,9 @@ TEST_F(InputChannelTest, ConstructorAndDestructor_TakesOwnershipOfFileDescriptor // of a pipe and to check for EPIPE on the other end after the channel is destroyed. Pipe pipe; - sp inputChannel = new InputChannel(String8("channel name"), pipe.sendFd); + sp inputChannel = new InputChannel("channel name", pipe.sendFd); - EXPECT_STREQ("channel name", inputChannel->getName().string()) + EXPECT_STREQ("channel name", inputChannel->getName().c_str()) << "channel should have provided name"; EXPECT_EQ(pipe.sendFd, inputChannel->getFd()) << "channel should have provided fd"; @@ -60,16 +60,16 @@ TEST_F(InputChannelTest, ConstructorAndDestructor_TakesOwnershipOfFileDescriptor TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { sp serverChannel, clientChannel; - status_t result = InputChannel::openInputChannelPair(String8("channel name"), + status_t result = InputChannel::openInputChannelPair("channel name", serverChannel, clientChannel); ASSERT_EQ(OK, result) << "should have successfully opened a channel pair"; // Name - EXPECT_STREQ("channel name (server)", serverChannel->getName().string()) + EXPECT_STREQ("channel name (server)", serverChannel->getName().c_str()) << "server channel should have suffixed name"; - EXPECT_STREQ("channel name (client)", clientChannel->getName().string()) + EXPECT_STREQ("channel name (client)", clientChannel->getName().c_str()) << "client channel should have suffixed name"; // Server->Client communication @@ -111,7 +111,7 @@ TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { TEST_F(InputChannelTest, ReceiveSignal_WhenNoSignalPresent_ReturnsAnError) { sp serverChannel, clientChannel; - status_t result = InputChannel::openInputChannelPair(String8("channel name"), + status_t result = InputChannel::openInputChannelPair("channel name", serverChannel, clientChannel); ASSERT_EQ(OK, result) @@ -125,7 +125,7 @@ TEST_F(InputChannelTest, ReceiveSignal_WhenNoSignalPresent_ReturnsAnError) { TEST_F(InputChannelTest, ReceiveSignal_WhenPeerClosed_ReturnsAnError) { sp serverChannel, clientChannel; - status_t result = InputChannel::openInputChannelPair(String8("channel name"), + status_t result = InputChannel::openInputChannelPair("channel name", serverChannel, clientChannel); ASSERT_EQ(OK, result) @@ -141,7 +141,7 @@ TEST_F(InputChannelTest, ReceiveSignal_WhenPeerClosed_ReturnsAnError) { TEST_F(InputChannelTest, SendSignal_WhenPeerClosed_ReturnsAnError) { sp serverChannel, clientChannel; - status_t result = InputChannel::openInputChannelPair(String8("channel name"), + status_t result = InputChannel::openInputChannelPair("channel name", serverChannel, clientChannel); ASSERT_EQ(OK, result) diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp index f86f876aa4..c5322414fd 100644 --- a/libs/input/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp @@ -36,7 +36,7 @@ protected: PreallocatedInputEventFactory mEventFactory; virtual void SetUp() { - status_t result = InputChannel::openInputChannelPair(String8("channel name"), + status_t result = InputChannel::openInputChannelPair("channel name", serverChannel, clientChannel); mPublisher = new InputPublisher(serverChannel); diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp index 238cba362c..a9e5a4339c 100644 --- a/services/inputflinger/Android.bp +++ b/services/inputflinger/Android.bp @@ -26,6 +26,7 @@ cc_library_shared { ], shared_libs: [ + "libbase", "libbinder", "libcrypto", "libcutils", diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp index 99fe0f5d55..4d9a2a0254 100644 --- a/services/inputflinger/EventHub.cpp +++ b/services/inputflinger/EventHub.cpp @@ -39,6 +39,7 @@ #include +#include #include #include #include @@ -64,6 +65,8 @@ #define INDENT2 " " #define INDENT3 " " +using android::base::StringPrintf; + namespace android { static const char *WAKE_LOCK_ID = "KeyEvents"; @@ -1733,43 +1736,43 @@ void EventHub::requestReopenDevices() { mNeedToReopenDevices = true; } -void EventHub::dump(String8& dump) { - dump.append("Event Hub State:\n"); +void EventHub::dump(std::string& dump) { + dump += "Event Hub State:\n"; { // acquire lock AutoMutex _l(mLock); - dump.appendFormat(INDENT "BuiltInKeyboardId: %d\n", mBuiltInKeyboardId); + dump += StringPrintf(INDENT "BuiltInKeyboardId: %d\n", mBuiltInKeyboardId); - dump.append(INDENT "Devices:\n"); + dump += INDENT "Devices:\n"; for (size_t i = 0; i < mDevices.size(); i++) { const Device* device = mDevices.valueAt(i); if (mBuiltInKeyboardId == device->id) { - dump.appendFormat(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n", + dump += StringPrintf(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n", device->id, device->identifier.name.string()); } else { - dump.appendFormat(INDENT2 "%d: %s\n", device->id, + dump += StringPrintf(INDENT2 "%d: %s\n", device->id, device->identifier.name.string()); } - dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes); - dump.appendFormat(INDENT3 "Path: %s\n", device->path.string()); - dump.appendFormat(INDENT3 "Enabled: %s\n", toString(device->enabled)); - dump.appendFormat(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.string()); - dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string()); - dump.appendFormat(INDENT3 "ControllerNumber: %d\n", device->controllerNumber); - dump.appendFormat(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.string()); - dump.appendFormat(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, " + dump += StringPrintf(INDENT3 "Classes: 0x%08x\n", device->classes); + dump += StringPrintf(INDENT3 "Path: %s\n", device->path.string()); + dump += StringPrintf(INDENT3 "Enabled: %s\n", toString(device->enabled)); + dump += StringPrintf(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.string()); + dump += StringPrintf(INDENT3 "Location: %s\n", device->identifier.location.string()); + dump += StringPrintf(INDENT3 "ControllerNumber: %d\n", device->controllerNumber); + dump += StringPrintf(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.string()); + dump += StringPrintf(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, " "product=0x%04x, version=0x%04x\n", device->identifier.bus, device->identifier.vendor, device->identifier.product, device->identifier.version); - dump.appendFormat(INDENT3 "KeyLayoutFile: %s\n", + dump += StringPrintf(INDENT3 "KeyLayoutFile: %s\n", device->keyMap.keyLayoutFile.string()); - dump.appendFormat(INDENT3 "KeyCharacterMapFile: %s\n", + dump += StringPrintf(INDENT3 "KeyCharacterMapFile: %s\n", device->keyMap.keyCharacterMapFile.string()); - dump.appendFormat(INDENT3 "ConfigurationFile: %s\n", + dump += StringPrintf(INDENT3 "ConfigurationFile: %s\n", device->configurationFile.string()); - dump.appendFormat(INDENT3 "HaveKeyboardLayoutOverlay: %s\n", + dump += StringPrintf(INDENT3 "HaveKeyboardLayoutOverlay: %s\n", toString(device->overlayKeyMap != NULL)); } } // release lock diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h index 727b73aeb8..66bc29456b 100644 --- a/services/inputflinger/EventHub.h +++ b/services/inputflinger/EventHub.h @@ -24,7 +24,6 @@ #include