Merge "Handle DEAD_OBJECT correctly in H2BGBP"
diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h
index 86da4d3..0f336dd 100644
--- a/include/input/DisplayViewport.h
+++ b/include/input/DisplayViewport.h
@@ -39,13 +39,13 @@
int32_t physicalBottom;
int32_t deviceWidth;
int32_t deviceHeight;
- String8 uniqueId;
+ std::string uniqueId;
DisplayViewport() :
displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0),
logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0),
physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0),
- deviceWidth(0), deviceHeight(0) {
+ deviceWidth(0), deviceHeight(0), uniqueId() {
}
bool operator==(const DisplayViewport& other) const {
diff --git a/include/input/Input.h b/include/input/Input.h
index 7c4379e..819a89f 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -25,7 +25,6 @@
#include <utils/BitSet.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
-#include <utils/String8.h>
#include <utils/Timers.h>
#include <utils/Vector.h>
#include <stdint.h>
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 1ea69d3..34d164c 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -31,9 +31,9 @@
}
// Information provided by the kernel.
- String8 name;
- String8 location;
- String8 uniqueId;
+ std::string name;
+ std::string location;
+ std::string uniqueId;
uint16_t bus;
uint16_t vendor;
uint16_t product;
@@ -45,7 +45,7 @@
// It is hashed from whatever kernel provided information is available.
// Ideally, the way this value is computed should not change between Android releases
// because that would invalidate persistent settings that rely on it.
- String8 descriptor;
+ std::string descriptor;
// A value added to uniquely identify a device in the absence of a unique id. This
// is intended to be a minimum way to distinguish from other active devices and may
@@ -73,16 +73,16 @@
};
void initialize(int32_t id, int32_t generation, int32_t controllerNumber,
- const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal,
+ const InputDeviceIdentifier& identifier, const std::string& alias, bool isExternal,
bool hasMic);
inline int32_t getId() const { return mId; }
inline int32_t getControllerNumber() const { return mControllerNumber; }
inline int32_t getGeneration() const { return mGeneration; }
inline const InputDeviceIdentifier& getIdentifier() const { return mIdentifier; }
- inline const String8& getAlias() const { return mAlias; }
- inline const String8& getDisplayName() const {
- return mAlias.isEmpty() ? mIdentifier.name : mAlias;
+ inline const std::string& getAlias() const { return mAlias; }
+ inline const std::string& getDisplayName() const {
+ return mAlias.empty() ? mIdentifier.name : mAlias;
}
inline bool isExternal() const { return mIsExternal; }
inline bool hasMic() const { return mHasMic; }
@@ -121,7 +121,7 @@
int32_t mGeneration;
int32_t mControllerNumber;
InputDeviceIdentifier mIdentifier;
- String8 mAlias;
+ std::string mAlias;
bool mIsExternal;
bool mHasMic;
uint32_t mSources;
@@ -149,7 +149,7 @@
*
* Returns an empty string if not found.
*/
-extern String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
+extern std::string getInputDeviceConfigurationFilePathByDeviceIdentifier(
const InputDeviceIdentifier& deviceIdentifier,
InputDeviceConfigurationFileType type);
@@ -162,8 +162,8 @@
*
* Returns an empty string if not found.
*/
-extern String8 getInputDeviceConfigurationFilePathByName(
- const String8& name, InputDeviceConfigurationFileType type);
+extern std::string getInputDeviceConfigurationFilePathByName(
+ const std::string& name, InputDeviceConfigurationFileType type);
} // namespace android
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index e8d1345..5fd86b4 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -27,6 +27,8 @@
* The InputConsumer is used by the application to receive events from the input dispatcher.
*/
+#include <string>
+
#include <input/Input.h>
#include <utils/Errors.h>
#include <utils/Timers.h>
diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h
index 33d2757..9f4559f 100644
--- a/include/input/KeyCharacterMap.h
+++ b/include/input/KeyCharacterMap.h
@@ -27,7 +27,6 @@
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/Tokenizer.h>
-#include <utils/String8.h>
#include <utils/Unicode.h>
#include <utils/RefBase.h>
@@ -75,10 +74,10 @@
};
/* Loads a key character map from a file. */
- static status_t load(const String8& filename, Format format, sp<KeyCharacterMap>* outMap);
+ static status_t load(const std::string& filename, Format format, sp<KeyCharacterMap>* outMap);
/* Loads a key character map from its string contents. */
- static status_t loadContents(const String8& filename,
+ static status_t loadContents(const std::string& filename,
const char* contents, Format format, sp<KeyCharacterMap>* outMap);
/* Combines a base key character map and an overlay. */
@@ -221,7 +220,7 @@
status_t parseKey();
status_t parseKeyProperty();
status_t finishKey(Key* key);
- status_t parseModifier(const String8& token, int32_t* outMetaState);
+ status_t parseModifier(const std::string& token, int32_t* outMetaState);
status_t parseCharacterLiteral(char16_t* outCharacter);
};
diff --git a/include/input/KeyLayoutMap.h b/include/input/KeyLayoutMap.h
index 1e8de71..73815fe 100644
--- a/include/input/KeyLayoutMap.h
+++ b/include/input/KeyLayoutMap.h
@@ -62,7 +62,7 @@
*/
class KeyLayoutMap : public RefBase {
public:
- static status_t load(const String8& filename, sp<KeyLayoutMap>* outMap);
+ static status_t load(const std::string& filename, sp<KeyLayoutMap>* outMap);
status_t mapKey(int32_t scanCode, int32_t usageCode,
int32_t* outKeyCode, uint32_t* outFlags) const;
diff --git a/include/input/Keyboard.h b/include/input/Keyboard.h
index d4903e9..8b66f69 100644
--- a/include/input/Keyboard.h
+++ b/include/input/Keyboard.h
@@ -21,7 +21,6 @@
#include <input/InputDevice.h>
#include <input/InputEventLabels.h>
#include <utils/Errors.h>
-#include <utils/String8.h>
#include <utils/PropertyMap.h>
namespace android {
@@ -43,10 +42,10 @@
*/
class KeyMap {
public:
- String8 keyLayoutFile;
+ std::string keyLayoutFile;
sp<KeyLayoutMap> keyLayoutMap;
- String8 keyCharacterMapFile;
+ std::string keyCharacterMapFile;
sp<KeyCharacterMap> keyCharacterMap;
KeyMap();
@@ -56,11 +55,11 @@
const PropertyMap* deviceConfiguration);
inline bool haveKeyLayout() const {
- return !keyLayoutFile.isEmpty();
+ return !keyLayoutFile.empty();
}
inline bool haveKeyCharacterMap() const {
- return !keyCharacterMapFile.isEmpty();
+ return !keyCharacterMapFile.empty();
}
inline bool isComplete() const {
@@ -68,12 +67,12 @@
}
private:
- bool probeKeyMap(const InputDeviceIdentifier& deviceIdentifier, const String8& name);
- status_t loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier, const String8& name);
+ bool probeKeyMap(const InputDeviceIdentifier& deviceIdentifier, const std::string& name);
+ status_t loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier, const std::string& name);
status_t loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier,
- const String8& name);
- String8 getPath(const InputDeviceIdentifier& deviceIdentifier,
- const String8& name, InputDeviceConfigurationFileType type);
+ const std::string& name);
+ std::string getPath(const InputDeviceIdentifier& deviceIdentifier,
+ const std::string& name, InputDeviceConfigurationFileType type);
};
/**
diff --git a/include/input/VirtualKeyMap.h b/include/input/VirtualKeyMap.h
index e245ead..24e0e0e 100644
--- a/include/input/VirtualKeyMap.h
+++ b/include/input/VirtualKeyMap.h
@@ -23,7 +23,6 @@
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/Tokenizer.h>
-#include <utils/String8.h>
#include <utils/Unicode.h>
namespace android {
@@ -50,7 +49,7 @@
public:
~VirtualKeyMap();
- static status_t load(const String8& filename, VirtualKeyMap** outMap);
+ static status_t load(const std::string& filename, VirtualKeyMap** outMap);
inline const Vector<VirtualKeyDefinition>& getVirtualKeys() const {
return mVirtualKeys;
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index d516eb1..857bbf9 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -189,7 +189,7 @@
// them out without going through the buffer.
// Slurp up all of the lines.
- const char* lastLine = txt+1;
+ const char* lastLine = txt;
while (txt < end) {
if (*txt++ == '\n') lastLine = txt;
}
diff --git a/libs/binder/ndk/AIBinder.cpp b/libs/binder/ndk/AIBinder.cpp
index d0ce98d..83972f7 100644
--- a/libs/binder/ndk/AIBinder.cpp
+++ b/libs/binder/ndk/AIBinder.cpp
@@ -28,14 +28,29 @@
using ::android::String16;
using ::android::wp;
+namespace ABBinderTag {
+
+static const void* kId = "ABBinder";
+static void* kValue = static_cast<void*>(new bool{true});
+void cleanId(const void* /*id*/, void* /*obj*/, void* /*cookie*/){/* do nothing */};
+
+static void attach(const sp<IBinder>& binder) {
+ binder->attachObject(kId, kValue, nullptr /*cookie*/, cleanId);
+}
+static bool has(const sp<IBinder>& binder) {
+ return binder != nullptr && binder->findObject(kId) == kValue;
+}
+
+} // namespace ABBinderTag
+
AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {}
AIBinder::~AIBinder() {}
-sp<AIBinder> AIBinder::associateClass(const AIBinder_Class* clazz) {
+bool AIBinder::associateClass(const AIBinder_Class* clazz) {
using ::android::String8;
- if (clazz == nullptr) return nullptr;
- if (mClazz == clazz) return this;
+ if (clazz == nullptr) return false;
+ if (mClazz == clazz) return true;
String8 newDescriptor(clazz->getInterfaceDescriptor());
@@ -45,42 +60,31 @@
LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor
<< "' match during associateClass, but they are different class objects. "
"Class descriptor collision?";
- return nullptr;
+ } else {
+ LOG(ERROR) << __func__
+ << ": Class cannot be associated on object which already has a class. "
+ "Trying to associate to '"
+ << newDescriptor.c_str() << "' but already set to '"
+ << currentDescriptor.c_str() << "'.";
}
- LOG(ERROR) << __func__
- << ": Class cannot be associated on object which already has a class. Trying to "
- "associate to '"
- << newDescriptor.c_str() << "' but already set to '" << currentDescriptor.c_str()
- << "'.";
- return nullptr;
+ // always a failure because we know mClazz != clazz
+ return false;
}
+ CHECK(asABpBinder() != nullptr); // ABBinder always has a descriptor
+
String8 descriptor(getBinder()->getInterfaceDescriptor());
if (descriptor != newDescriptor) {
LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor.c_str()
<< "' but descriptor is actually '" << descriptor.c_str() << "'.";
- return nullptr;
+ return false;
}
- // The descriptor matches, so if it is local, this is guaranteed to be the libbinder_ndk class.
- // An error here can occur if there is a conflict between descriptors (two unrelated classes
- // define the same descriptor), but this should never happen.
-
- // if this is a local ABBinder, mClazz should be non-null
- CHECK(asABBinder() == nullptr);
- CHECK(asABpBinder() != nullptr);
-
- if (!isRemote()) {
- // ABpBinder but proxy to a local object. Therefore that local object must be an ABBinder.
- ABBinder* binder = static_cast<ABBinder*>(getBinder().get());
- return binder;
- }
-
- // This is a remote object
+ // if this is a local object, it's not one known to libbinder_ndk
mClazz = clazz;
- return this;
+ return true;
}
ABBinder::ABBinder(const AIBinder_Class* clazz, void* userData)
@@ -111,24 +115,45 @@
}
}
-ABpBinder::ABpBinder(::android::sp<::android::IBinder> binder)
+ABpBinder::ABpBinder(const ::android::sp<::android::IBinder>& binder)
: AIBinder(nullptr /*clazz*/), BpRefBase(binder) {
CHECK(binder != nullptr);
}
ABpBinder::~ABpBinder() {}
+sp<AIBinder> ABpBinder::fromBinder(const ::android::sp<::android::IBinder>& binder) {
+ if (binder == nullptr) {
+ return nullptr;
+ }
+ if (ABBinderTag::has(binder)) {
+ return static_cast<ABBinder*>(binder.get());
+ }
+ return new ABpBinder(binder);
+}
+
struct AIBinder_Weak {
wp<AIBinder> binder;
};
AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder) {
- if (binder == nullptr) return nullptr;
+ if (binder == nullptr) {
+ return nullptr;
+ }
+
return new AIBinder_Weak{wp<AIBinder>(binder)};
}
-void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) {
- delete weakBinder;
+void AIBinder_Weak_delete(AIBinder_Weak** weakBinder) {
+ if (weakBinder == nullptr) {
+ return;
+ }
+
+ delete *weakBinder;
+ *weakBinder = nullptr;
}
AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder) {
- if (weakBinder == nullptr) return nullptr;
+ if (weakBinder == nullptr) {
+ return nullptr;
+ }
+
sp<AIBinder> binder = weakBinder->binder.promote();
AIBinder_incStrong(binder.get());
return binder.get();
@@ -162,12 +187,14 @@
void* userData = clazz->onCreate(args);
- AIBinder* ret = new ABBinder(clazz, userData);
- AIBinder_incStrong(ret);
- return ret;
+ sp<AIBinder> ret = new ABBinder(clazz, userData);
+ ABBinderTag::attach(ret->getBinder());
+
+ AIBinder_incStrong(ret.get());
+ return ret.get();
}
-bool AIBinder_isRemote(AIBinder* binder) {
+bool AIBinder_isRemote(const AIBinder* binder) {
if (binder == nullptr) {
return true;
}
@@ -175,6 +202,22 @@
return binder->isRemote();
}
+bool AIBinder_isAlive(const AIBinder* binder) {
+ if (binder == nullptr) {
+ return false;
+ }
+
+ return const_cast<AIBinder*>(binder)->getBinder()->isBinderAlive();
+}
+
+binder_status_t AIBinder_ping(AIBinder* binder) {
+ if (binder == nullptr) {
+ return EX_NULL_POINTER;
+ }
+
+ return binder->getBinder()->pingBinder();
+}
+
void AIBinder_incStrong(AIBinder* binder) {
if (binder == nullptr) {
LOG(ERROR) << __func__ << ": on null binder";
@@ -200,23 +243,12 @@
return binder->getStrongCount();
}
-void AIBinder_associateClass(AIBinder** binder, const AIBinder_Class* clazz) {
- if (binder == nullptr || *binder == nullptr) {
- return;
+bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) {
+ if (binder == nullptr) {
+ return false;
}
- sp<AIBinder> result = (*binder)->associateClass(clazz);
-
- // This function takes one refcount of 'binder' and delivers one refcount of 'result' to the
- // callee. First we give the callee their refcount and then take it away from binder. This is
- // done in this order in order to handle the case that the result and the binder are the same
- // object.
- if (result != nullptr) {
- AIBinder_incStrong(result.get());
- }
- AIBinder_decStrong(*binder);
-
- *binder = result.get(); // Maybe no-op
+ return binder->associateClass(clazz);
}
const AIBinder_Class* AIBinder_getClass(AIBinder* binder) {
@@ -263,12 +295,6 @@
return status;
}
-using AutoParcelDestroyer = std::unique_ptr<AParcel*, void (*)(AParcel**)>;
-static void destroy_parcel(AParcel** parcel) {
- delete *parcel;
- *parcel = nullptr;
-}
-
binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
AParcel** out, binder_flags_t flags) {
if (in == nullptr) {
@@ -276,9 +302,10 @@
return EX_NULL_POINTER;
}
+ using AutoParcelDestroyer = std::unique_ptr<AParcel*, void (*)(AParcel**)>;
// This object is the input to the transaction. This function takes ownership of it and deletes
// it.
- AutoParcelDestroyer forIn(in, destroy_parcel);
+ AutoParcelDestroyer forIn(in, AParcel_delete);
if (!isUserCommand(code)) {
LOG(ERROR) << __func__ << ": Only user-defined transactions can be made from the NDK.";
@@ -313,33 +340,3 @@
return parcelStatus;
}
-
-binder_status_t AIBinder_finalizeTransaction(AIBinder* binder, AParcel** out) {
- if (out == nullptr) {
- LOG(ERROR) << __func__ << ": requires non-null out parameter";
- return EX_NULL_POINTER;
- }
-
- // This object is the input to the transaction. This function takes ownership of it and deletes
- // it.
- AutoParcelDestroyer forOut(out, destroy_parcel);
-
- if (binder == nullptr || *out == nullptr) {
- LOG(ERROR) << __func__ << ": requires non-null parameters.";
- return EX_NULL_POINTER;
- }
-
- if ((*out)->getBinder() != binder) {
- LOG(ERROR) << __func__ << ": parcel is associated with binder object " << binder
- << " but called with " << (*out)->getBinder();
- return EX_ILLEGAL_STATE;
- }
-
- if ((**out)->dataAvail() != 0) {
- LOG(ERROR) << __func__
- << ": Only part of this transaction was read. There is remaining data left.";
- return EX_ILLEGAL_STATE;
- }
-
- return EX_NONE;
-}
diff --git a/libs/binder/ndk/AIBinder_internal.h b/libs/binder/ndk/AIBinder_internal.h
index d44b937..23949bb 100644
--- a/libs/binder/ndk/AIBinder_internal.h
+++ b/libs/binder/ndk/AIBinder_internal.h
@@ -35,23 +35,16 @@
AIBinder(const AIBinder_Class* clazz);
virtual ~AIBinder();
- // This returns an AIBinder object with this class associated. If the class is already
- // associated, 'this' will be returned. If there is a local AIBinder implementation, that will
- // be returned. If this is a remote object, the class will be associated and this will be ready
- // to be used for transactions.
- ::android::sp<AIBinder> associateClass(const AIBinder_Class* clazz);
+ bool associateClass(const AIBinder_Class* clazz);
const AIBinder_Class* getClass() const { return mClazz; }
- // This does not create the binder if it does not exist in the process.
virtual ::android::sp<::android::IBinder> getBinder() = 0;
virtual ABBinder* asABBinder() { return nullptr; }
virtual ABpBinder* asABpBinder() { return nullptr; }
- bool isRemote() {
- auto binder = getBinder();
- // if the binder is nullptr, then it is a local object which hasn't been sent out of process
- // yet.
- return binder != nullptr && binder->remoteBinder() != nullptr;
+ bool isRemote() const {
+ ::android::sp<::android::IBinder> binder = const_cast<AIBinder*>(this)->getBinder();
+ return binder->remoteBinder() != nullptr;
}
private:
@@ -63,7 +56,6 @@
// This is a local AIBinder object with a known class.
struct ABBinder : public AIBinder, public ::android::BBinder {
- ABBinder(const AIBinder_Class* clazz, void* userData);
virtual ~ABBinder();
void* getUserData() { return mUserData; }
@@ -76,6 +68,11 @@
::android::Parcel* reply, binder_flags_t flags) override;
private:
+ ABBinder(const AIBinder_Class* clazz, void* userData);
+
+ // only thing that should create an ABBinder
+ friend AIBinder* AIBinder_new(const AIBinder_Class*, void*);
+
// Can contain implementation if this is a local binder. This can still be nullptr for a local
// binder. If it is nullptr, the implication is the implementation state is entirely external to
// this object and the functionality provided in the AIBinder_Class is sufficient.
@@ -85,11 +82,15 @@
// This binder object may be remote or local (even though it is 'Bp'). It is not yet associated with
// a class.
struct ABpBinder : public AIBinder, public ::android::BpRefBase {
- ABpBinder(::android::sp<::android::IBinder> binder);
+ static ::android::sp<AIBinder> fromBinder(const ::android::sp<::android::IBinder>& binder);
+
virtual ~ABpBinder();
::android::sp<::android::IBinder> getBinder() override { return remote(); }
ABpBinder* asABpBinder() override { return this; }
+
+private:
+ ABpBinder(const ::android::sp<::android::IBinder>& binder);
};
struct AIBinder_Class {
diff --git a/libs/binder/ndk/AParcel.cpp b/libs/binder/ndk/AParcel.cpp
index b63b138..93384d6 100644
--- a/libs/binder/ndk/AParcel.cpp
+++ b/libs/binder/ndk/AParcel.cpp
@@ -25,6 +25,15 @@
using ::android::Parcel;
using ::android::sp;
+void AParcel_delete(AParcel** parcel) {
+ if (parcel == nullptr) {
+ return;
+ }
+
+ delete *parcel;
+ *parcel = nullptr;
+}
+
binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
return (*parcel)->writeStrongBinder(binder->getBinder());
}
@@ -34,8 +43,9 @@
if (status != EX_NONE) {
return status;
}
- *binder = new ABpBinder(readBinder);
- AIBinder_incStrong(*binder);
+ sp<AIBinder> ret = ABpBinder::fromBinder(readBinder);
+ AIBinder_incStrong(ret.get());
+ *binder = ret.get();
return status;
}
binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder) {
@@ -44,8 +54,9 @@
if (status != EX_NONE) {
return status;
}
- *binder = new ABpBinder(readBinder);
- AIBinder_incStrong(*binder);
+ sp<AIBinder> ret = ABpBinder::fromBinder(readBinder);
+ AIBinder_incStrong(ret.get());
+ *binder = ret.get();
return status;
}
diff --git a/libs/binder/ndk/AServiceManager.cpp b/libs/binder/ndk/AServiceManager.cpp
index f61b914..3979945 100644
--- a/libs/binder/ndk/AServiceManager.cpp
+++ b/libs/binder/ndk/AServiceManager.cpp
@@ -41,7 +41,7 @@
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16(instance));
- AIBinder* ret = new ABpBinder(binder);
- AIBinder_incStrong(ret);
- return ret;
+ sp<AIBinder> ret = ABpBinder::fromBinder(binder);
+ AIBinder_incStrong(ret.get());
+ return ret.get();
}
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 23136a2..aa29437 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -144,7 +144,23 @@
/**
* If this is hosted in a process other than the current one.
*/
-bool AIBinder_isRemote(AIBinder* binder);
+bool AIBinder_isRemote(const AIBinder* binder);
+
+/**
+ * If this binder is known to be alive. This will not send a transaction to a remote process and
+ * returns a result based on the last known information. That is, whenever a transaction is made,
+ * this is automatically updated to reflect the current alive status of this binder. This will be
+ * updated as the result of a transaction made using AIBinder_transact, but it will also be updated
+ * based on the results of bookkeeping or other transactions made internally.
+ */
+bool AIBinder_isAlive(const AIBinder* binder);
+
+/**
+ * Built-in transaction for all binder objects. This sends a transaction which will immediately
+ * return. Usually this is used to make sure that a binder is alive, as a placeholder call, or as a
+ * sanity check.
+ */
+binder_status_t AIBinder_ping(AIBinder* binder);
/**
* This can only be called if a strong reference to this object already exists in process.
@@ -167,13 +183,12 @@
* However, if an object is just intended to be passed through to another process or used as a
* handle this need not be called.
*
- * The binder parameter may or may not be updated. If it is updated, the ownership of the original
- * object is transferred to the new object. If the class association fails, ownership of the binder
- * is lost, and it is set to nullptr.
+ * This returns true if the class association succeeds. If it fails, no change is made to the
+ * binder object.
*/
-void AIBinder_associateClass(AIBinder** binder, const AIBinder_Class* clazz);
+bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz);
-/*
+/**
* Returns the class that this binder was constructed with or associated with.
*/
const AIBinder_Class* AIBinder_getClass(AIBinder* binder);
@@ -187,10 +202,9 @@
/**
* A transaction is a series of calls to these functions which looks this
* - call AIBinder_prepareTransaction
- * - fill out parcel with in parameters (lifetime of the 'in' variable)
+ * - fill out the in parcel with parameters (lifetime of the 'in' variable)
* - call AIBinder_transact
- * - fill out parcel with out parameters (lifetime of the 'out' variable)
- * - call AIBinder_finalizeTransaction
+ * - read results from the out parcel (lifetime of the 'out' variable)
*/
/**
@@ -201,7 +215,10 @@
* can be avoided. This AIBinder must be either built with a class or associated with a class before
* using this API.
*
- * This does not affect the ownership of binder.
+ * This does not affect the ownership of binder. When this function succeeds, the in parcel's
+ * ownership is passed to the caller. At this point, the parcel can be filled out and passed to
+ * AIBinder_transact. Alternatively, if there is an error while filling out the parcel, it can be
+ * deleted with AParcel_delete.
*/
binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in);
@@ -214,29 +231,22 @@
* remote process has processed the transaction, and the out parcel will contain the output data
* from transaction.
*
- * This does not affect the ownership of binder.
+ * This does not affect the ownership of binder. The out parcel's ownership is passed to the caller
+ * and must be released with AParcel_delete when finished reading.
*/
binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
AParcel** out, binder_flags_t flags);
/**
- * This takes ownership of the out parcel and automatically deletes it. Additional checks for
- * security or debugging maybe performed internally.
- *
- * This does not affect the ownership of binder.
- */
-binder_status_t AIBinder_finalizeTransaction(AIBinder* binder, AParcel** out);
-
-/*
* This does not take any ownership of the input binder, but it can be used to retrieve it if
* something else in some process still holds a reference to it.
*/
__attribute__((warn_unused_result)) AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder);
-/*
+/**
* Deletes the weak reference. This will have no impact on the lifetime of the binder.
*/
-void AIBinder_Weak_delete(AIBinder_Weak* weakBinder);
+void AIBinder_Weak_delete(AIBinder_Weak** weakBinder);
/**
* If promotion succeeds, result will have one strong refcount added to it. Otherwise, this returns
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index 091ae8e..19925f7 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -35,6 +35,11 @@
typedef struct AParcel AParcel;
/**
+ * Cleans up a parcel and sets it to nullptr.
+ */
+void AParcel_delete(AParcel** parcel);
+
+/**
* Writes an AIBinder to the next location in a non-null parcel. Can be null.
*/
binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder);
diff --git a/libs/binder/ndk/test/iface.cpp b/libs/binder/ndk/test/iface.cpp
index eed09f0..a1aa0fa 100644
--- a/libs/binder/ndk/test/iface.cpp
+++ b/libs/binder/ndk/test/iface.cpp
@@ -81,7 +81,8 @@
int32_t out;
CHECK(EX_NONE == AParcel_readInt32(parcelOut, &out));
- CHECK(EX_NONE == AIBinder_finalizeTransaction(mBinder, &parcelOut));
+ AParcel_delete(&parcelOut);
+
return out;
}
@@ -91,7 +92,7 @@
};
IFoo::~IFoo() {
- AIBinder_Weak_delete(mWeakBinder);
+ AIBinder_Weak_delete(&mWeakBinder);
}
binder_status_t IFoo::addService(const char* instance) {
@@ -105,7 +106,7 @@
// or one strong refcount here
binder = AIBinder_new(IFoo::kClass, static_cast<void*>(new IFoo_Class_Data{this}));
if (mWeakBinder != nullptr) {
- AIBinder_Weak_delete(mWeakBinder);
+ AIBinder_Weak_delete(&mWeakBinder);
}
mWeakBinder = AIBinder_Weak_new(binder);
}
@@ -118,12 +119,15 @@
sp<IFoo> IFoo::getService(const char* instance) {
AIBinder* binder = AServiceManager_getService(instance); // maybe nullptr
- AIBinder_associateClass(&binder, IFoo::kClass);
-
if (binder == nullptr) {
return nullptr;
}
+ if (!AIBinder_associateClass(binder, IFoo::kClass)) {
+ AIBinder_decStrong(binder);
+ return nullptr;
+ }
+
if (AIBinder_isRemote(binder)) {
sp<IFoo> ret = new BpFoo(binder); // takes ownership of binder
return ret;
diff --git a/libs/binder/ndk/test/main_client.cpp b/libs/binder/ndk/test/main_client.cpp
index 7c53e51..967789f 100644
--- a/libs/binder/ndk/test/main_client.cpp
+++ b/libs/binder/ndk/test/main_client.cpp
@@ -38,6 +38,10 @@
TEST(NdkBinder, RetrieveNonNdkService) {
AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
ASSERT_NE(nullptr, binder);
+ EXPECT_TRUE(AIBinder_isRemote(binder));
+ EXPECT_TRUE(AIBinder_isAlive(binder));
+ EXPECT_EQ(EX_NONE, AIBinder_ping(binder));
+
AIBinder_decStrong(binder);
}
diff --git a/libs/binder/tests/binderTextOutputTest.cpp b/libs/binder/tests/binderTextOutputTest.cpp
index f6dd22d..ce99f59 100644
--- a/libs/binder/tests/binderTextOutputTest.cpp
+++ b/libs/binder/tests/binderTextOutputTest.cpp
@@ -28,15 +28,14 @@
#include <binder/TextOutput.h>
#include <binder/Debug.h>
-static void CheckMessage(const CapturedStderr& cap,
+static void CheckMessage(CapturedStderr& cap,
const char* expected,
bool singleline) {
- std::string output;
- ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
- android::base::ReadFdToString(cap.fd(), &output);
+ cap.Stop();
+ std::string output = cap.str();
if (singleline)
output.erase(std::remove(output.begin(), output.end(), '\n'));
- ASSERT_STREQ(output.c_str(), expected);
+ ASSERT_EQ(output, expected);
}
#define CHECK_LOG_(input, expect, singleline) \
@@ -60,28 +59,22 @@
TEST(TextOutput, HandlesStdEndl) {
CapturedStderr cap;
android::aerr << "foobar" << std::endl;
- std::string output;
- ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
- android::base::ReadFdToString(cap.fd(), &output);
- ASSERT_STREQ(output.c_str(), "foobar\n");
+ cap.Stop();
+ ASSERT_EQ(cap.str(), "foobar\n");
}
TEST(TextOutput, HandlesCEndl) {
CapturedStderr cap;
android::aerr << "foobar" << "\n";
- std::string output;
- ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
- android::base::ReadFdToString(cap.fd(), &output);
- ASSERT_STREQ(output.c_str(), "foobar\n");
+ cap.Stop();
+ ASSERT_EQ(cap.str(), "foobar\n");
}
TEST(TextOutput, HandlesAndroidEndl) {
CapturedStderr cap;
android::aerr << "foobar" << android::endl;
- std::string output;
- ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
- android::base::ReadFdToString(cap.fd(), &output);
- ASSERT_STREQ(output.c_str(), "foobar\n");
+ cap.Stop();
+ ASSERT_EQ(cap.str(), "foobar\n");
}
TEST(TextOutput, HandleEmptyString) {
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 5d27bf6..778c453 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -20,9 +20,12 @@
#include <unistd.h>
#include <ctype.h>
+#include <android-base/stringprintf.h>
#include <input/InputDevice.h>
#include <input/InputEventLabels.h>
+using android::base::StringPrintf;
+
namespace android {
static const char* CONFIGURATION_FILE_DIR[] = {
@@ -41,8 +44,8 @@
return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_');
}
-static void appendInputDeviceConfigurationFileRelativePath(String8& path,
- const String8& name, InputDeviceConfigurationFileType type) {
+static void appendInputDeviceConfigurationFileRelativePath(std::string& path,
+ const std::string& name, InputDeviceConfigurationFileType type) {
path.append(CONFIGURATION_FILE_DIR[type]);
for (size_t i = 0; i < name.length(); i++) {
char ch = name[i];
@@ -54,28 +57,28 @@
path.append(CONFIGURATION_FILE_EXTENSION[type]);
}
-String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
+std::string getInputDeviceConfigurationFilePathByDeviceIdentifier(
const InputDeviceIdentifier& deviceIdentifier,
InputDeviceConfigurationFileType type) {
if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
if (deviceIdentifier.version != 0) {
// Try vendor product version.
- String8 versionPath(getInputDeviceConfigurationFilePathByName(
- String8::format("Vendor_%04x_Product_%04x_Version_%04x",
+ std::string versionPath = getInputDeviceConfigurationFilePathByName(
+ StringPrintf("Vendor_%04x_Product_%04x_Version_%04x",
deviceIdentifier.vendor, deviceIdentifier.product,
deviceIdentifier.version),
- type));
- if (!versionPath.isEmpty()) {
+ type);
+ if (!versionPath.empty()) {
return versionPath;
}
}
// Try vendor product.
- String8 productPath(getInputDeviceConfigurationFilePathByName(
- String8::format("Vendor_%04x_Product_%04x",
+ std::string productPath = getInputDeviceConfigurationFilePathByName(
+ StringPrintf("Vendor_%04x_Product_%04x",
deviceIdentifier.vendor, deviceIdentifier.product),
- type));
- if (!productPath.isEmpty()) {
+ type);
+ if (!productPath.empty()) {
return productPath;
}
}
@@ -84,22 +87,25 @@
return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type);
}
-String8 getInputDeviceConfigurationFilePathByName(
- const String8& name, InputDeviceConfigurationFileType type) {
+std::string getInputDeviceConfigurationFilePathByName(
+ const std::string& name, InputDeviceConfigurationFileType type) {
// Search system repository.
- String8 path;
+ std::string path;
// Treblized input device config files will be located /odm/usr or /vendor/usr.
const char *rootsForPartition[] {"/odm", "/vendor", getenv("ANDROID_ROOT")};
for (size_t i = 0; i < size(rootsForPartition); i++) {
- path.setTo(rootsForPartition[i]);
- path.append("/usr/");
+ if (rootsForPartition[i] == nullptr) {
+ continue;
+ }
+ path = rootsForPartition[i];
+ path += "/usr/";
appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBE
ALOGD("Probing for system provided input device configuration file: path='%s'",
- path.string());
+ path.c_str());
#endif
- if (!access(path.string(), R_OK)) {
+ if (!access(path.c_str(), R_OK)) {
#if DEBUG_PROBE
ALOGD("Found");
#endif
@@ -109,13 +115,17 @@
// Search user repository.
// TODO Should only look here if not in safe mode.
- path.setTo(getenv("ANDROID_DATA"));
- path.append("/system/devices/");
+ path = "";
+ char *androidData = getenv("ANDROID_DATA");
+ if (androidData != nullptr) {
+ path += androidData;
+ }
+ path += "/system/devices/";
appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBE
- ALOGD("Probing for system user input device configuration file: path='%s'", path.string());
+ ALOGD("Probing for system user input device configuration file: path='%s'", path.c_str());
#endif
- if (!access(path.string(), R_OK)) {
+ if (!access(path.c_str(), R_OK)) {
#if DEBUG_PROBE
ALOGD("Found");
#endif
@@ -125,16 +135,16 @@
// Not found.
#if DEBUG_PROBE
ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",
- name.string(), type);
+ name.c_str(), type);
#endif
- return String8();
+ return "";
}
// --- InputDeviceInfo ---
InputDeviceInfo::InputDeviceInfo() {
- initialize(-1, 0, -1, InputDeviceIdentifier(), String8(), false, false);
+ initialize(-1, 0, -1, InputDeviceIdentifier(), "", false, false);
}
InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
@@ -150,7 +160,7 @@
}
void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber,
- const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal,
+ const InputDeviceIdentifier& identifier, const std::string& alias, bool isExternal,
bool hasMic) {
mId = id;
mGeneration = generation;
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index 26747bd..e189d20 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -106,14 +106,14 @@
}
}
-status_t KeyCharacterMap::load(const String8& filename,
+status_t KeyCharacterMap::load(const std::string& filename,
Format format, sp<KeyCharacterMap>* outMap) {
outMap->clear();
Tokenizer* tokenizer;
- status_t status = Tokenizer::open(filename, &tokenizer);
+ status_t status = Tokenizer::open(String8(filename.c_str()), &tokenizer);
if (status) {
- ALOGE("Error %d opening key character map file %s.", status, filename.string());
+ ALOGE("Error %d opening key character map file %s.", status, filename.c_str());
} else {
status = load(tokenizer, format, outMap);
delete tokenizer;
@@ -121,12 +121,12 @@
return status;
}
-status_t KeyCharacterMap::loadContents(const String8& filename, const char* contents,
+status_t KeyCharacterMap::loadContents(const std::string& filename, const char* contents,
Format format, sp<KeyCharacterMap>* outMap) {
outMap->clear();
Tokenizer* tokenizer;
- status_t status = Tokenizer::fromContents(filename, contents, &tokenizer);
+ status_t status = Tokenizer::fromContents(String8(filename.c_str()), contents, &tokenizer);
if (status) {
ALOGE("Error %d opening key character map.", status);
} else {
@@ -944,7 +944,7 @@
properties.add(Property(PROPERTY_NUMBER));
} else {
int32_t metaState;
- status_t status = parseModifier(token, &metaState);
+ status_t status = parseModifier(token.string(), &metaState);
if (status) {
ALOGE("%s: Expected a property name or modifier, got '%s'.",
mTokenizer->getLocation().string(), token.string());
@@ -1137,7 +1137,7 @@
return NO_ERROR;
}
-status_t KeyCharacterMap::Parser::parseModifier(const String8& token, int32_t* outMetaState) {
+status_t KeyCharacterMap::Parser::parseModifier(const std::string& token, int32_t* outMetaState) {
if (token == "base") {
*outMetaState = 0;
return NO_ERROR;
@@ -1145,7 +1145,7 @@
int32_t combinedMeta = 0;
- const char* str = token.string();
+ const char* str = token.c_str();
const char* start = str;
for (const char* cur = str; ; cur++) {
char ch = *cur;
@@ -1164,7 +1164,7 @@
}
if (combinedMeta & metaState) {
ALOGE("%s: Duplicate modifier combination '%s'.",
- mTokenizer->getLocation().string(), token.string());
+ mTokenizer->getLocation().string(), token.c_str());
return BAD_VALUE;
}
diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp
index c440078..88cb0db 100644
--- a/libs/input/KeyLayoutMap.cpp
+++ b/libs/input/KeyLayoutMap.cpp
@@ -49,13 +49,13 @@
KeyLayoutMap::~KeyLayoutMap() {
}
-status_t KeyLayoutMap::load(const String8& filename, sp<KeyLayoutMap>* outMap) {
+status_t KeyLayoutMap::load(const std::string& filename, sp<KeyLayoutMap>* outMap) {
outMap->clear();
Tokenizer* tokenizer;
- status_t status = Tokenizer::open(filename, &tokenizer);
+ status_t status = Tokenizer::open(String8(filename.c_str()), &tokenizer);
if (status) {
- ALOGE("Error %d opening key layout map file %s.", status, filename.string());
+ ALOGE("Error %d opening key layout map file %s.", status, filename.c_str());
} else {
sp<KeyLayoutMap> map = new KeyLayoutMap();
if (!map.get()) {
diff --git a/libs/input/Keyboard.cpp b/libs/input/Keyboard.cpp
index 11842ee..0c22bfe 100644
--- a/libs/input/Keyboard.cpp
+++ b/libs/input/Keyboard.cpp
@@ -45,22 +45,22 @@
String8 keyLayoutName;
if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"),
keyLayoutName)) {
- status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName);
+ status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName.c_str());
if (status == NAME_NOT_FOUND) {
ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but "
"it was not found.",
- deviceIdenfifier.name.string(), keyLayoutName.string());
+ deviceIdenfifier.name.c_str(), keyLayoutName.string());
}
}
String8 keyCharacterMapName;
if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"),
keyCharacterMapName)) {
- status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName);
+ status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName.c_str());
if (status == NAME_NOT_FOUND) {
ALOGE("Configuration for keyboard device '%s' requested keyboard character "
"map '%s' but it was not found.",
- deviceIdenfifier.name.string(), keyLayoutName.string());
+ deviceIdenfifier.name.c_str(), keyLayoutName.string());
}
}
@@ -70,30 +70,30 @@
}
// Try searching by device identifier.
- if (probeKeyMap(deviceIdenfifier, String8::empty())) {
+ if (probeKeyMap(deviceIdenfifier, "")) {
return OK;
}
// Fall back on the Generic key map.
// TODO Apply some additional heuristics here to figure out what kind of
// generic key map to use (US English, etc.) for typical external keyboards.
- if (probeKeyMap(deviceIdenfifier, String8("Generic"))) {
+ if (probeKeyMap(deviceIdenfifier, "Generic")) {
return OK;
}
// Try the Virtual key map as a last resort.
- if (probeKeyMap(deviceIdenfifier, String8("Virtual"))) {
+ if (probeKeyMap(deviceIdenfifier, "Virtual")) {
return OK;
}
// Give up!
ALOGE("Could not determine key map for device '%s' and no default key maps were found!",
- deviceIdenfifier.name.string());
+ deviceIdenfifier.name.c_str());
return NAME_NOT_FOUND;
}
bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier,
- const String8& keyMapName) {
+ const std::string& keyMapName) {
if (!haveKeyLayout()) {
loadKeyLayout(deviceIdentifier, keyMapName);
}
@@ -104,10 +104,10 @@
}
status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier,
- const String8& name) {
- String8 path(getPath(deviceIdentifier, name,
+ const std::string& name) {
+ std::string path(getPath(deviceIdentifier, name,
INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT));
- if (path.isEmpty()) {
+ if (path.empty()) {
return NAME_NOT_FOUND;
}
@@ -116,15 +116,15 @@
return status;
}
- keyLayoutFile.setTo(path);
+ keyLayoutFile = path;
return OK;
}
status_t KeyMap::loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier,
- const String8& name) {
- String8 path(getPath(deviceIdentifier, name,
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP));
- if (path.isEmpty()) {
+ const std::string& name) {
+ std::string path = getPath(deviceIdentifier, name,
+ INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP);
+ if (path.empty()) {
return NAME_NOT_FOUND;
}
@@ -134,13 +134,13 @@
return status;
}
- keyCharacterMapFile.setTo(path);
+ keyCharacterMapFile = path;
return OK;
}
-String8 KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier,
- const String8& name, InputDeviceConfigurationFileType type) {
- return name.isEmpty()
+std::string KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier,
+ const std::string& name, InputDeviceConfigurationFileType type) {
+ return name.empty()
? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type)
: getInputDeviceConfigurationFilePathByName(name, type);
}
@@ -174,7 +174,7 @@
}
}
- return strstr(deviceIdentifier.name.string(), "-keypad");
+ return strstr(deviceIdentifier.name.c_str(), "-keypad");
}
static int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) {
diff --git a/libs/input/VirtualKeyMap.cpp b/libs/input/VirtualKeyMap.cpp
index 9932973..3ec53bf 100644
--- a/libs/input/VirtualKeyMap.cpp
+++ b/libs/input/VirtualKeyMap.cpp
@@ -46,13 +46,13 @@
VirtualKeyMap::~VirtualKeyMap() {
}
-status_t VirtualKeyMap::load(const String8& filename, VirtualKeyMap** outMap) {
+status_t VirtualKeyMap::load(const std::string& filename, VirtualKeyMap** outMap) {
*outMap = nullptr;
Tokenizer* tokenizer;
- status_t status = Tokenizer::open(filename, &tokenizer);
+ status_t status = Tokenizer::open(String8(filename.c_str()), &tokenizer);
if (status) {
- ALOGE("Error %d opening virtual key map file %s.", status, filename.string());
+ ALOGE("Error %d opening virtual key map file %s.", status, filename.c_str());
} else {
VirtualKeyMap* map = new VirtualKeyMap();
if (!map) {
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index 77a474f..a964d29 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -76,16 +76,16 @@
return value ? "true" : "false";
}
-static String8 sha1(const String8& in) {
+static std::string sha1(const std::string& in) {
SHA_CTX ctx;
SHA1_Init(&ctx);
- SHA1_Update(&ctx, reinterpret_cast<const u_char*>(in.string()), in.size());
+ SHA1_Update(&ctx, reinterpret_cast<const u_char*>(in.c_str()), in.size());
u_char digest[SHA_DIGEST_LENGTH];
SHA1_Final(digest, &ctx);
- String8 out;
+ std::string out;
for (size_t i = 0; i < SHA_DIGEST_LENGTH; i++) {
- out.appendFormat("%02x", digest[i]);
+ out += StringPrintf("%02x", digest[i]);
}
return out;
}
@@ -141,7 +141,7 @@
// --- EventHub::Device ---
-EventHub::Device::Device(int fd, int32_t id, const String8& path,
+EventHub::Device::Device(int fd, int32_t id, const std::string& path,
const InputDeviceIdentifier& identifier) :
next(nullptr),
fd(fd), id(id), path(path), identifier(identifier),
@@ -172,9 +172,9 @@
}
status_t EventHub::Device::enable() {
- fd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK);
+ fd = open(path.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
if(fd < 0) {
- ALOGE("could not open %s, %s\n", path.string(), strerror(errno));
+ ALOGE("could not open %s, %s\n", path.c_str(), strerror(errno));
return -errno;
}
enabled = true;
@@ -307,7 +307,7 @@
struct input_absinfo info;
if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
- axis, device->identifier.name.string(), device->fd, errno);
+ axis, device->identifier.name.c_str(), device->fd, errno);
return -errno;
}
@@ -416,7 +416,7 @@
struct input_absinfo info;
if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
- axis, device->identifier.name.string(), device->fd, errno);
+ axis, device->identifier.name.c_str(), device->fd, errno);
return -errno;
}
@@ -512,7 +512,7 @@
return NAME_NOT_FOUND;
}
-void EventHub::setExcludedDevices(const Vector<String8>& devices) {
+void EventHub::setExcludedDevices(const std::vector<std::string>& devices) {
AutoMutex _l(mLock);
mExcludedDevices = devices;
@@ -599,16 +599,16 @@
return false;
}
-static String8 generateDescriptor(InputDeviceIdentifier& identifier) {
- String8 rawDescriptor;
- rawDescriptor.appendFormat(":%04x:%04x:", identifier.vendor,
+static std::string generateDescriptor(InputDeviceIdentifier& identifier) {
+ std::string rawDescriptor;
+ rawDescriptor += StringPrintf(":%04x:%04x:", identifier.vendor,
identifier.product);
// TODO add handling for USB devices to not uniqueify kbs that show up twice
- if (!identifier.uniqueId.isEmpty()) {
- rawDescriptor.append("uniqueId:");
- rawDescriptor.append(identifier.uniqueId);
+ if (!identifier.uniqueId.empty()) {
+ rawDescriptor += "uniqueId:";
+ rawDescriptor += identifier.uniqueId;
} else if (identifier.nonce != 0) {
- rawDescriptor.appendFormat("nonce:%04x", identifier.nonce);
+ rawDescriptor += StringPrintf("nonce:%04x", identifier.nonce);
}
if (identifier.vendor == 0 && identifier.product == 0) {
@@ -616,12 +616,12 @@
// built-in so we need to rely on other information to uniquely identify
// the input device. Usually we try to avoid relying on the device name or
// location but for built-in input device, they are unlikely to ever change.
- if (!identifier.name.isEmpty()) {
- rawDescriptor.append("name:");
- rawDescriptor.append(identifier.name);
- } else if (!identifier.location.isEmpty()) {
- rawDescriptor.append("location:");
- rawDescriptor.append(identifier.location);
+ if (!identifier.name.empty()) {
+ rawDescriptor += "name:";
+ rawDescriptor += identifier.name;
+ } else if (!identifier.location.empty()) {
+ rawDescriptor += "location:";
+ rawDescriptor += identifier.location;
}
}
identifier.descriptor = sha1(rawDescriptor);
@@ -637,8 +637,8 @@
// Ideally, we also want the descriptor to be short and relatively opaque.
identifier.nonce = 0;
- String8 rawDescriptor = generateDescriptor(identifier);
- if (identifier.uniqueId.isEmpty()) {
+ std::string rawDescriptor = generateDescriptor(identifier);
+ if (identifier.uniqueId.empty()) {
// If it didn't have a unique id check for conflicts and enforce
// uniqueness if necessary.
while(getDeviceByDescriptorLocked(identifier.descriptor) != nullptr) {
@@ -646,8 +646,8 @@
rawDescriptor = generateDescriptor(identifier);
}
}
- ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.string(),
- identifier.descriptor.string());
+ ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.c_str(),
+ identifier.descriptor.c_str());
}
void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
@@ -664,7 +664,7 @@
effect.replay.delay = 0;
if (ioctl(device->fd, EVIOCSFF, &effect)) {
ALOGW("Could not upload force feedback effect to device %s due to error %d.",
- device->identifier.name.string(), errno);
+ device->identifier.name.c_str(), errno);
return;
}
device->ffEffectId = effect.id;
@@ -677,7 +677,7 @@
ev.value = 1;
if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) {
ALOGW("Could not start force feedback effect on device %s due to error %d.",
- device->identifier.name.string(), errno);
+ device->identifier.name.c_str(), errno);
return;
}
device->ffEffectPlaying = true;
@@ -699,18 +699,18 @@
ev.value = 0;
if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) {
ALOGW("Could not stop force feedback effect on device %s due to error %d.",
- device->identifier.name.string(), errno);
+ device->identifier.name.c_str(), errno);
return;
}
}
}
}
-EventHub::Device* EventHub::getDeviceByDescriptorLocked(String8& descriptor) const {
+EventHub::Device* EventHub::getDeviceByDescriptorLocked(const std::string& descriptor) const {
size_t size = mDevices.size();
for (size_t i = 0; i < size; i++) {
Device* device = mDevices.valueAt(i);
- if (descriptor.compare(device->identifier.descriptor) == 0) {
+ if (descriptor == device->identifier.descriptor) {
return device;
}
}
@@ -763,7 +763,7 @@
while (mClosingDevices) {
Device* device = mClosingDevices;
ALOGV("Reporting device closed: id=%d, name=%s\n",
- device->id, device->path.string());
+ device->id, device->path.c_str());
mClosingDevices = device->next;
event->when = now;
event->deviceId = device->id == mBuiltInKeyboardId ? BUILT_IN_KEYBOARD_ID : device->id;
@@ -785,7 +785,7 @@
while (mOpeningDevices != nullptr) {
Device* device = mOpeningDevices;
ALOGV("Reporting device opened: id=%d, name=%s\n",
- device->id, device->path.string());
+ device->id, device->path.c_str());
mOpeningDevices = device->next;
event->when = now;
event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
@@ -867,7 +867,7 @@
for (size_t i = 0; i < count; i++) {
struct input_event& iev = readBuffer[i];
ALOGV("%s got: time=%d.%06d, type=%d, code=%d, value=%d",
- device->path.string(),
+ device->path.c_str(),
(int) iev.time.tv_sec, (int) iev.time.tv_usec,
iev.type, iev.code, iev.value);
@@ -936,7 +936,7 @@
"event time %" PRId64 ", current time %" PRId64
", call time %" PRId64 ". "
"Using current time instead.",
- device->path.string(), event->when, time, now);
+ device->path.c_str(), event->when, time, now);
event->when = time;
} else {
ALOGV("Event time is ok but failed the fast path and required "
@@ -962,12 +962,12 @@
}
} else if (eventItem.events & EPOLLHUP) {
ALOGI("Removing device %s due to epoll hang-up event.",
- device->identifier.name.string());
+ device->identifier.name.c_str());
deviceChanged = true;
closeDeviceLocked(device);
} else {
ALOGW("Received unexpected epoll event 0x%08x for device %s.",
- eventItem.events, device->identifier.name.string());
+ eventItem.events, device->identifier.name.c_str());
}
}
@@ -1125,14 +1125,14 @@
//fprintf(stderr, "could not get device name for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
- identifier.name.setTo(buffer);
+ identifier.name = buffer;
}
// Check to see if the device is on our excluded list
for (size_t i = 0; i < mExcludedDevices.size(); i++) {
- const String8& item = mExcludedDevices.itemAt(i);
+ const std::string& item = mExcludedDevices[i];
if (identifier.name == item) {
- ALOGI("ignoring event id %s driver %s\n", devicePath, item.string());
+ ALOGI("ignoring event id %s driver %s\n", devicePath, item.c_str());
close(fd);
return -1;
}
@@ -1163,7 +1163,7 @@
//fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
- identifier.location.setTo(buffer);
+ identifier.location = buffer;
}
// Get device unique id.
@@ -1171,7 +1171,7 @@
//fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
- identifier.uniqueId.setTo(buffer);
+ identifier.uniqueId = buffer;
}
// Fill in the descriptor.
@@ -1179,7 +1179,7 @@
// Allocate device. (The device object takes ownership of the fd at this point.)
int32_t deviceId = mNextDeviceId++;
- Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
+ Device* device = new Device(fd, deviceId, devicePath, identifier);
ALOGV("add device %d: %s\n", deviceId, devicePath);
ALOGV(" bus: %04x\n"
@@ -1187,10 +1187,10 @@
" product %04x\n"
" version %04x\n",
identifier.bus, identifier.vendor, identifier.product, identifier.version);
- ALOGV(" name: \"%s\"\n", identifier.name.string());
- ALOGV(" location: \"%s\"\n", identifier.location.string());
- ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.string());
- ALOGV(" descriptor: \"%s\"\n", identifier.descriptor.string());
+ ALOGV(" name: \"%s\"\n", identifier.name.c_str());
+ ALOGV(" location: \"%s\"\n", identifier.location.c_str());
+ ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.c_str());
+ ALOGV(" descriptor: \"%s\"\n", identifier.descriptor.c_str());
ALOGV(" driver: v%d.%d.%d\n",
driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
@@ -1343,7 +1343,7 @@
// If the device isn't recognized as something we handle, don't monitor it.
if (device->classes == 0) {
ALOGV("Dropping device: id=%d, path='%s', name='%s'",
- deviceId, devicePath, device->identifier.name.string());
+ deviceId, devicePath, device->identifier.name.c_str());
delete device;
return -1;
}
@@ -1374,11 +1374,11 @@
ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
"configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
- deviceId, fd, devicePath, device->identifier.name.string(),
+ deviceId, fd, devicePath, device->identifier.name.c_str(),
device->classes,
- device->configurationFile.string(),
- device->keyMap.keyLayoutFile.string(),
- device->keyMap.keyCharacterMapFile.string(),
+ device->configurationFile.c_str(),
+ device->keyMap.keyLayoutFile.c_str(),
+ device->keyMap.keyCharacterMapFile.c_str(),
toString(mBuiltInKeyboardId == deviceId));
addDeviceLocked(device);
@@ -1392,11 +1392,11 @@
unsigned int repeatRate[] = {0, 0};
if (ioctl(device->fd, EVIOCSREP, repeatRate)) {
ALOGW("Unable to disable kernel key repeat for %s: %s",
- device->path.string(), strerror(errno));
+ device->path.c_str(), strerror(errno));
}
}
- String8 wakeMechanism("EPOLLWAKEUP");
+ std::string wakeMechanism = "EPOLLWAKEUP";
if (!mUsingEpollWakeup) {
#ifndef EVIOCSSUSPENDBLOCK
// uapi headers don't include EVIOCSSUSPENDBLOCK, and future kernels
@@ -1416,7 +1416,7 @@
// clock.
int clockId = CLOCK_MONOTONIC;
bool usingClockIoctl = !ioctl(device->fd, EVIOCSCLOCKID, &clockId);
- ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.string(),
+ ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.c_str(),
toString(usingClockIoctl));
}
@@ -1473,7 +1473,7 @@
identifier.uniqueId = "<virtual>";
assignDescriptorLocked(identifier);
- Device* device = new Device(-1, VIRTUAL_KEYBOARD_ID, String8("<virtual>"), identifier);
+ Device* device = new Device(-1, VIRTUAL_KEYBOARD_ID, "<virtual>", identifier);
device->classes = INPUT_DEVICE_CLASS_KEYBOARD
| INPUT_DEVICE_CLASS_ALPHAKEY
| INPUT_DEVICE_CLASS_DPAD
@@ -1491,26 +1491,26 @@
void EventHub::loadConfigurationLocked(Device* device) {
device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
- if (device->configurationFile.isEmpty()) {
+ if (device->configurationFile.empty()) {
ALOGD("No input device configuration file found for device '%s'.",
- device->identifier.name.string());
+ device->identifier.name.c_str());
} else {
- status_t status = PropertyMap::load(device->configurationFile,
+ status_t status = PropertyMap::load(String8(device->configurationFile.c_str()),
&device->configuration);
if (status) {
ALOGE("Error loading input device configuration file for device '%s'. "
"Using default configuration.",
- device->identifier.name.string());
+ device->identifier.name.c_str());
}
}
}
status_t EventHub::loadVirtualKeyMapLocked(Device* device) {
// The virtual key map is supplied by the kernel as a system board property file.
- String8 path;
- path.append("/sys/board_properties/virtualkeys.");
- path.append(device->identifier.name);
- if (access(path.string(), R_OK)) {
+ std::string path;
+ path += "/sys/board_properties/virtualkeys.";
+ path += device->identifier.name;
+ if (access(path.c_str(), R_OK)) {
return NAME_NOT_FOUND;
}
return VirtualKeyMap::load(path, &device->virtualKeyMap);
@@ -1543,7 +1543,7 @@
int32_t EventHub::getNextControllerNumberLocked(Device* device) {
if (mControllerNumbers.isFull()) {
ALOGI("Maximum number of controllers reached, assigning controller number 0 to device %s",
- device->identifier.name.string());
+ device->identifier.name.c_str());
return 0;
}
// Since the controller number 0 is reserved for non-controllers, translate all numbers up by
@@ -1617,12 +1617,12 @@
void EventHub::closeDeviceLocked(Device* device) {
ALOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x\n",
- device->path.string(), device->identifier.name.string(), device->id,
+ device->path.c_str(), device->identifier.name.c_str(), device->id,
device->fd, device->classes);
if (device->id == mBuiltInKeyboardId) {
ALOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
- device->path.string(), mBuiltInKeyboardId);
+ device->path.c_str(), mBuiltInKeyboardId);
mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;
}
@@ -1648,7 +1648,7 @@
// Unlink the device from the opening devices list then delete it.
// We don't need to tell the client that the device was closed because
// it does not even know it was opened in the first place.
- ALOGI("Device %s was immediately closed after opening.", device->path.string());
+ ALOGI("Device %s was immediately closed after opening.", device->path.c_str());
if (pred) {
pred->next = device->next;
} else {
@@ -1750,28 +1750,28 @@
const Device* device = mDevices.valueAt(i);
if (mBuiltInKeyboardId == device->id) {
dump += StringPrintf(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n",
- device->id, device->identifier.name.string());
+ device->id, device->identifier.name.c_str());
} else {
dump += StringPrintf(INDENT2 "%d: %s\n", device->id,
- device->identifier.name.string());
+ device->identifier.name.c_str());
}
dump += StringPrintf(INDENT3 "Classes: 0x%08x\n", device->classes);
- dump += StringPrintf(INDENT3 "Path: %s\n", device->path.string());
+ dump += StringPrintf(INDENT3 "Path: %s\n", device->path.c_str());
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 "Descriptor: %s\n", device->identifier.descriptor.c_str());
+ dump += StringPrintf(INDENT3 "Location: %s\n", device->identifier.location.c_str());
dump += StringPrintf(INDENT3 "ControllerNumber: %d\n", device->controllerNumber);
- dump += StringPrintf(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.string());
+ dump += StringPrintf(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.c_str());
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 += StringPrintf(INDENT3 "KeyLayoutFile: %s\n",
- device->keyMap.keyLayoutFile.string());
+ device->keyMap.keyLayoutFile.c_str());
dump += StringPrintf(INDENT3 "KeyCharacterMapFile: %s\n",
- device->keyMap.keyCharacterMapFile.string());
+ device->keyMap.keyCharacterMapFile.c_str());
dump += StringPrintf(INDENT3 "ConfigurationFile: %s\n",
- device->configurationFile.string());
+ device->configurationFile.c_str());
dump += StringPrintf(INDENT3 "HaveKeyboardLayoutOverlay: %s\n",
toString(device->overlayKeyMap != nullptr));
}
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h
index dfe3def..ea663b7 100644
--- a/services/inputflinger/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -18,6 +18,8 @@
#ifndef _RUNTIME_EVENT_HUB_H
#define _RUNTIME_EVENT_HUB_H
+#include <vector>
+
#include <input/Input.h>
#include <input/InputDevice.h>
#include <input/Keyboard.h>
@@ -29,7 +31,6 @@
#include <utils/List.h>
#include <utils/Errors.h>
#include <utils/PropertyMap.h>
-#include <utils/Vector.h>
#include <utils/KeyedVector.h>
#include <utils/BitSet.h>
@@ -207,7 +208,7 @@
// Sets devices that are excluded from opening.
// This can be used to ignore input devices for sensors.
- virtual void setExcludedDevices(const Vector<String8>& devices) = 0;
+ virtual void setExcludedDevices(const std::vector<std::string>& devices) = 0;
/*
* Wait for events to become available and returns them.
@@ -303,7 +304,7 @@
virtual status_t mapAxis(int32_t deviceId, int32_t scanCode,
AxisInfo* outAxisInfo) const;
- virtual void setExcludedDevices(const Vector<String8>& devices);
+ virtual void setExcludedDevices(const std::vector<std::string>& devices);
virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const;
virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const;
@@ -344,7 +345,7 @@
int fd; // may be -1 if device is closed
const int32_t id;
- const String8 path;
+ const std::string path;
const InputDeviceIdentifier identifier;
uint32_t classes;
@@ -357,7 +358,7 @@
uint8_t ffBitmask[(FF_MAX + 1) / 8];
uint8_t propBitmask[(INPUT_PROP_MAX + 1) / 8];
- String8 configurationFile;
+ std::string configurationFile;
PropertyMap* configuration;
VirtualKeyMap* virtualKeyMap;
KeyMap keyMap;
@@ -373,7 +374,8 @@
int32_t timestampOverrideSec;
int32_t timestampOverrideUsec;
- Device(int fd, int32_t id, const String8& path, const InputDeviceIdentifier& identifier);
+ Device(int fd, int32_t id, const std::string& path,
+ const InputDeviceIdentifier& identifier);
~Device();
void close();
@@ -413,7 +415,7 @@
void scanDevicesLocked();
status_t readNotifyLocked();
- Device* getDeviceByDescriptorLocked(String8& descriptor) const;
+ Device* getDeviceByDescriptorLocked(const std::string& descriptor) const;
Device* getDeviceLocked(int32_t deviceId) const;
Device* getDeviceByPathLocked(const char* devicePath) const;
@@ -457,7 +459,7 @@
bool mNeedToSendFinishedDeviceScan;
bool mNeedToReopenDevices;
bool mNeedToScanDevices;
- Vector<String8> mExcludedDevices;
+ std::vector<std::string> mExcludedDevices;
int mEpollFd;
int mINotifyFd;
diff --git a/services/inputflinger/InputApplication.h b/services/inputflinger/InputApplication.h
index 724fc2c..9b365b9 100644
--- a/services/inputflinger/InputApplication.h
+++ b/services/inputflinger/InputApplication.h
@@ -17,6 +17,8 @@
#ifndef _UI_INPUT_APPLICATION_H
#define _UI_INPUT_APPLICATION_H
+#include <string>
+
#include <input/Input.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index c805805..d609573 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -515,9 +515,10 @@
sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId,
int32_t x, int32_t y) {
// Traverse windows from front to back to find touched window.
- size_t numWindows = mWindowHandles.size();
+ const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
+ size_t numWindows = windowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
+ sp<InputWindowHandle> windowHandle = windowHandles.itemAt(i);
const InputWindowInfo* windowInfo = windowHandle->getInfo();
if (windowInfo->displayId == displayId) {
int32_t flags = windowInfo->layoutParamsFlags;
@@ -1247,9 +1248,10 @@
bool isTouchModal = false;
// Traverse windows from front to back to find touched window and outside targets.
- size_t numWindows = mWindowHandles.size();
+ const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
+ size_t numWindows = windowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
+ sp<InputWindowHandle> windowHandle = windowHandles.itemAt(i);
const InputWindowInfo* windowInfo = windowHandle->getInfo();
if (windowInfo->displayId != displayId) {
continue; // wrong display
@@ -1472,8 +1474,10 @@
sp<InputWindowHandle> foregroundWindowHandle =
mTempTouchState.getFirstForegroundWindowHandle();
if (foregroundWindowHandle->getInfo()->hasWallpaper) {
- for (size_t i = 0; i < mWindowHandles.size(); i++) {
- sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
+ const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
+ size_t numWindows = windowHandles.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ sp<InputWindowHandle> windowHandle = windowHandles.itemAt(i);
const InputWindowInfo* info = windowHandle->getInfo();
if (info->displayId == displayId
&& windowHandle->getInfo()->layoutParamsType
@@ -1658,9 +1662,10 @@
bool InputDispatcher::isWindowObscuredAtPointLocked(
const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const {
int32_t displayId = windowHandle->getInfo()->displayId;
- size_t numWindows = mWindowHandles.size();
+ const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
+ size_t numWindows = windowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
+ sp<InputWindowHandle> otherHandle = windowHandles.itemAt(i);
if (otherHandle == windowHandle) {
break;
}
@@ -1678,10 +1683,11 @@
bool InputDispatcher::isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const {
int32_t displayId = windowHandle->getInfo()->displayId;
+ const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
const InputWindowInfo* windowInfo = windowHandle->getInfo();
- size_t numWindows = mWindowHandles.size();
+ size_t numWindows = windowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
+ sp<InputWindowHandle> otherHandle = windowHandles.itemAt(i);
if (otherHandle == windowHandle) {
break;
}
@@ -2909,13 +2915,27 @@
}
}
+Vector<sp<InputWindowHandle>> InputDispatcher::getWindowHandlesLocked(int32_t displayId) const {
+ std::unordered_map<int32_t, Vector<sp<InputWindowHandle>>>::const_iterator it =
+ mWindowHandlesByDisplay.find(displayId);
+ if(it != mWindowHandlesByDisplay.end()) {
+ return it->second;
+ }
+
+ // Return an empty one if nothing found.
+ return Vector<sp<InputWindowHandle>>();
+}
+
sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
const sp<InputChannel>& inputChannel) const {
- size_t numWindows = mWindowHandles.size();
- for (size_t i = 0; i < numWindows; i++) {
- const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
- if (windowHandle->getInputChannel() == inputChannel) {
- return windowHandle;
+ for (auto& it : mWindowHandlesByDisplay) {
+ const Vector<sp<InputWindowHandle>> windowHandles = it.second;
+ size_t numWindows = windowHandles.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
+ if (windowHandle->getInputChannel() == inputChannel) {
+ return windowHandle;
+ }
}
}
return nullptr;
@@ -2923,45 +2943,90 @@
bool InputDispatcher::hasWindowHandleLocked(
const sp<InputWindowHandle>& windowHandle) const {
- size_t numWindows = mWindowHandles.size();
- for (size_t i = 0; i < numWindows; i++) {
- if (mWindowHandles.itemAt(i) == windowHandle) {
- return true;
+ for (auto& it : mWindowHandlesByDisplay) {
+ const Vector<sp<InputWindowHandle>> windowHandles = it.second;
+ size_t numWindows = windowHandles.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ if (windowHandles.itemAt(i) == windowHandle) {
+ if (windowHandle->getInfo()->displayId != it.first) {
+ ALOGE("Found window %s in display %d, but it should belong to display %d",
+ windowHandle->getName().c_str(), it.first,
+ windowHandle->getInfo()->displayId);
+ }
+ return true;
+ }
}
}
return false;
}
-void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
+/**
+ * Called from InputManagerService, update window handle list by displayId that can receive input.
+ * A window handle contains information about InputChannel, Touch Region, Types, Focused,...
+ * If set an empty list, remove all handles from the specific display.
+ * For focused handle, check if need to change and send a cancel event to previous one.
+ * For removed handle, check if need to send a cancel event if already in touch.
+ */
+void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle>>& inputWindowHandles,
+ int32_t displayId) {
#if DEBUG_FOCUS
ALOGD("setInputWindows");
#endif
{ // acquire lock
AutoMutex _l(mLock);
- Vector<sp<InputWindowHandle> > oldWindowHandles = mWindowHandles;
- mWindowHandles = inputWindowHandles;
+ // Copy old handles for release if they are no longer present.
+ const Vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
- sp<InputWindowHandle> newFocusedWindowHandle;
+ // TODO(b/111361570): multi-display focus, one focus window per display.
+ sp<InputWindowHandle> newFocusedWindowHandle = mFocusedWindowHandle;
+ // Reset newFocusedWindowHandle to nullptr if current display own the focus window,
+ // that will be updated below when going through all window handles in current display.
+ // And if list of window handles becomes empty then it will be updated by other display.
+ if (mFocusedWindowHandle != nullptr) {
+ const InputWindowInfo* info = mFocusedWindowHandle->getInfo();
+ if (info == nullptr || info->displayId == displayId) {
+ newFocusedWindowHandle = nullptr;
+ }
+ }
+
bool foundHoveredWindow = false;
- for (size_t i = 0; i < mWindowHandles.size(); i++) {
- const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
- if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == nullptr) {
- mWindowHandles.removeAt(i--);
- continue;
+
+ if (inputWindowHandles.isEmpty()) {
+ // Remove all handles on a display if there are no windows left.
+ mWindowHandlesByDisplay.erase(displayId);
+ } else {
+ size_t numWindows = inputWindowHandles.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ const sp<InputWindowHandle>& windowHandle = inputWindowHandles.itemAt(i);
+ if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == nullptr) {
+ continue;
+ }
+
+ if (windowHandle->getInfo()->displayId != displayId) {
+ ALOGE("Window %s updated by wrong display %d, should belong to display %d",
+ windowHandle->getName().c_str(), displayId,
+ windowHandle->getInfo()->displayId);
+ continue;
+ }
+
+ if (windowHandle->getInfo()->hasFocus) {
+ newFocusedWindowHandle = windowHandle;
+ }
+ if (windowHandle == mLastHoverWindowHandle) {
+ foundHoveredWindow = true;
+ }
}
- if (windowHandle->getInfo()->hasFocus) {
- newFocusedWindowHandle = windowHandle;
- }
- if (windowHandle == mLastHoverWindowHandle) {
- foundHoveredWindow = true;
- }
+
+ // Insert or replace
+ mWindowHandlesByDisplay[displayId] = inputWindowHandles;
}
if (!foundHoveredWindow) {
mLastHoverWindowHandle = nullptr;
}
+ // TODO(b/111361570): multi-display focus, one focus in all display in current.
if (mFocusedWindowHandle != newFocusedWindowHandle) {
if (mFocusedWindowHandle != nullptr) {
#if DEBUG_FOCUS
@@ -2985,8 +3050,9 @@
mFocusedWindowHandle = newFocusedWindowHandle;
}
- for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
- TouchState& state = mTouchStatesByDisplay.editValueAt(d);
+ ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
+ if (stateIndex >= 0) {
+ TouchState& state = mTouchStatesByDisplay.editValueAt(stateIndex);
for (size_t i = 0; i < state.windows.size(); ) {
TouchedWindow& touchedWindow = state.windows.editItemAt(i);
if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
@@ -3013,7 +3079,8 @@
// This ensures that unused input channels are released promptly.
// Otherwise, they might stick around until the window handle is destroyed
// which might not happen until the next GC.
- for (size_t i = 0; i < oldWindowHandles.size(); i++) {
+ size_t numWindows = oldWindowHandles.size();
+ for (size_t i = 0; i < numWindows; i++) {
const sp<InputWindowHandle>& oldWindowHandle = oldWindowHandles.itemAt(i);
if (!hasWindowHandleLocked(oldWindowHandle)) {
#if DEBUG_FOCUS
@@ -3266,36 +3333,44 @@
dump += INDENT "TouchStates: <no displays touched>\n";
}
- if (!mWindowHandles.isEmpty()) {
- dump += INDENT "Windows:\n";
- for (size_t i = 0; i < mWindowHandles.size(); i++) {
- const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
- const InputWindowInfo* windowInfo = windowHandle->getInfo();
+ if (!mWindowHandlesByDisplay.empty()) {
+ for (auto& it : mWindowHandlesByDisplay) {
+ const Vector<sp<InputWindowHandle>> windowHandles = it.second;
+ dump += StringPrintf(INDENT "Display: %d\n", it.first);
+ if (!windowHandles.isEmpty()) {
+ dump += INDENT2 "Windows:\n";
+ for (size_t i = 0; i < windowHandles.size(); i++) {
+ const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
+ const InputWindowInfo* windowInfo = windowHandle->getInfo();
- dump += StringPrintf(INDENT2 "%zu: name='%s', displayId=%d, "
- "paused=%s, hasFocus=%s, hasWallpaper=%s, "
- "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
- "frame=[%d,%d][%d,%d], scale=%f, "
- "touchableRegion=",
- i, windowInfo->name.c_str(), windowInfo->displayId,
- toString(windowInfo->paused),
- toString(windowInfo->hasFocus),
- toString(windowInfo->hasWallpaper),
- toString(windowInfo->visible),
- toString(windowInfo->canReceiveKeys),
- windowInfo->layoutParamsFlags, windowInfo->layoutParamsType,
- windowInfo->layer,
- windowInfo->frameLeft, windowInfo->frameTop,
- windowInfo->frameRight, windowInfo->frameBottom,
- windowInfo->scaleFactor);
- dumpRegion(dump, windowInfo->touchableRegion);
- dump += StringPrintf(", inputFeatures=0x%08x", windowInfo->inputFeatures);
- dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
- windowInfo->ownerPid, windowInfo->ownerUid,
- windowInfo->dispatchingTimeout / 1000000.0);
+ dump += StringPrintf(INDENT3 "%zu: name='%s', displayId=%d, "
+ "paused=%s, hasFocus=%s, hasWallpaper=%s, "
+ "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
+ "frame=[%d,%d][%d,%d], scale=%f, "
+ "touchableRegion=",
+ i, windowInfo->name.c_str(), windowInfo->displayId,
+ toString(windowInfo->paused),
+ toString(windowInfo->hasFocus),
+ toString(windowInfo->hasWallpaper),
+ toString(windowInfo->visible),
+ toString(windowInfo->canReceiveKeys),
+ windowInfo->layoutParamsFlags, windowInfo->layoutParamsType,
+ windowInfo->layer,
+ windowInfo->frameLeft, windowInfo->frameTop,
+ windowInfo->frameRight, windowInfo->frameBottom,
+ windowInfo->scaleFactor);
+ dumpRegion(dump, windowInfo->touchableRegion);
+ dump += StringPrintf(", inputFeatures=0x%08x", windowInfo->inputFeatures);
+ dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
+ windowInfo->ownerPid, windowInfo->ownerUid,
+ windowInfo->dispatchingTimeout / 1000000.0);
+ }
+ } else {
+ dump += INDENT2 "Windows: <none>\n";
+ }
}
} else {
- dump += INDENT "Windows: <none>\n";
+ dump += INDENT "Displays: <none>\n";
}
if (!mMonitoringChannels.isEmpty()) {
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 31ab339..fdf75f6 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -31,6 +31,7 @@
#include <stddef.h>
#include <unistd.h>
#include <limits.h>
+#include <unordered_map>
#include "InputWindow.h"
#include "InputApplication.h"
@@ -307,7 +308,8 @@
*
* This method may be called on any thread (usually by the input manager).
*/
- virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) = 0;
+ virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
+ int32_t displayId) = 0;
/* Sets the focused application.
*
@@ -387,7 +389,8 @@
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
uint32_t policyFlags);
- virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles);
+ virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
+ int32_t displayId);
virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle);
virtual void setInputDispatchMode(bool enabled, bool frozen);
virtual void setInputFilterEnabled(bool enabled);
@@ -956,8 +959,9 @@
bool mDispatchFrozen;
bool mInputFilterEnabled;
- Vector<sp<InputWindowHandle> > mWindowHandles;
-
+ std::unordered_map<int32_t, Vector<sp<InputWindowHandle>>> mWindowHandlesByDisplay;
+ // Get window handles by display, return an empty vector if not found.
+ Vector<sp<InputWindowHandle>> getWindowHandlesLocked(int32_t displayId) const;
sp<InputWindowHandle> getWindowHandleLocked(const sp<InputChannel>& inputChannel) const;
bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index a213b2d..92e0af2 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -31,7 +31,6 @@
#include <utils/Vector.h>
#include <utils/Timers.h>
#include <utils/RefBase.h>
-#include <utils/String8.h>
namespace android {
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index a4f83b7..8f12129 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -257,11 +257,12 @@
// --- InputReaderConfiguration ---
bool InputReaderConfiguration::getDisplayViewport(ViewportType viewportType,
- const String8* uniqueDisplayId, DisplayViewport* outViewport) const {
+ const std::string& uniqueDisplayId, DisplayViewport* outViewport) const {
const DisplayViewport* viewport = nullptr;
- if (viewportType == ViewportType::VIEWPORT_VIRTUAL && uniqueDisplayId != nullptr) {
+ if (viewportType == ViewportType::VIEWPORT_VIRTUAL && !uniqueDisplayId.empty()) {
+
for (const DisplayViewport& currentViewport : mVirtualDisplays) {
- if (currentViewport.uniqueId == *uniqueDisplayId) {
+ if (currentViewport.uniqueId == uniqueDisplayId) {
viewport = ¤tViewport;
break;
}
@@ -473,10 +474,10 @@
if (device->isIgnored()) {
ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
- identifier.name.string());
+ identifier.name.c_str());
} else {
ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
- identifier.name.string(), device->getSources());
+ identifier.name.c_str(), device->getSources());
}
mDevices.add(deviceId, device);
@@ -501,10 +502,10 @@
if (device->isIgnored()) {
ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
- device->getId(), device->getName().string());
+ device->getId(), device->getName().c_str());
} else {
ALOGI("Device removed: id=%d, name='%s', sources=0x%08x",
- device->getId(), device->getName().string(), device->getSources());
+ device->getId(), device->getName().c_str(), device->getSources());
}
if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
@@ -687,7 +688,7 @@
if (now < mDisableVirtualKeysTimeout) {
ALOGI("Dropping virtual key from device %s because virtual keys are "
"temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
- device->getName().string(),
+ device->getName().c_str(),
(mDisableVirtualKeysTimeout - now) * 0.000001,
keyCode, scanCode);
return true;
@@ -894,7 +895,7 @@
if (i != 0) {
dump += ", ";
}
- dump += mConfig.excludedDeviceNames.itemAt(i).string();
+ dump += mConfig.excludedDeviceNames[i];
}
dump += "]\n";
dump += StringPrintf(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
@@ -1077,7 +1078,7 @@
getDeviceInfo(& deviceInfo);
dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(),
- deviceInfo.getDisplayName().string());
+ deviceInfo.getDisplayName().c_str());
dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
dump += StringPrintf(INDENT2 "HasMic: %s\n", toString(mHasMic));
@@ -1135,7 +1136,7 @@
if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
- String8 alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
+ std::string alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
if (mAlias != alias) {
mAlias = alias;
bumpGeneration();
@@ -1196,7 +1197,7 @@
#endif
}
} else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
- ALOGI("Detected input event buffer overrun for device %s.", getName().string());
+ ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
mDropUntilNextSync = true;
reset(rawEvent->when);
} else {
@@ -2294,7 +2295,7 @@
if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
if (mParameters.orientationAware) {
DisplayViewport dvp;
- config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, nullptr, &dvp);
+ config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, "", &dvp);
mViewport = dvp;
}
}
@@ -2464,7 +2465,7 @@
// key was not actually down
ALOGI("Dropping key up from device %s because the key was not down. "
"keyCode=%d, scanCode=%d",
- getDeviceName().string(), keyCode, scanCode);
+ getDeviceName().c_str(), keyCode, scanCode);
return;
}
}
@@ -2705,7 +2706,7 @@
mOrientation = DISPLAY_ORIENTATION_0;
if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
DisplayViewport v;
- if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, nullptr, &v)) {
+ if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, "", &v)) {
mOrientation = v.orientation;
}
}
@@ -3020,7 +3021,7 @@
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
DisplayViewport v;
- if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, nullptr, &v)) {
+ if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, "", &v)) {
mOrientation = v.orientation;
} else {
mOrientation = DISPLAY_ORIENTATION_0;
@@ -3394,8 +3395,10 @@
mParameters.hasAssociatedDisplay = true;
if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
mParameters.associatedDisplayIsExternal = getDevice()->isExternal();
+ String8 uniqueDisplayId;
getDevice()->getConfiguration().tryGetProperty(String8("touch.displayId"),
- mParameters.uniqueDisplayId);
+ uniqueDisplayId);
+ mParameters.uniqueDisplayId = uniqueDisplayId.c_str();
}
}
@@ -3506,7 +3509,7 @@
// Ensure we have valid X and Y axes.
if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
ALOGW(INDENT "Touch device '%s' did not report support for X or Y axis! "
- "The device will be inoperable.", getDeviceName().string());
+ "The device will be inoperable.", getDeviceName().c_str());
mDeviceMode = DEVICE_MODE_DISABLED;
return;
}
@@ -3518,15 +3521,15 @@
// Get associated display dimensions.
DisplayViewport newViewport;
if (mParameters.hasAssociatedDisplay) {
- const String8* uniqueDisplayId = nullptr;
+ std::string uniqueDisplayId;
ViewportType viewportTypeToUse;
if (mParameters.associatedDisplayIsExternal) {
viewportTypeToUse = ViewportType::VIEWPORT_EXTERNAL;
- } else if (!mParameters.uniqueDisplayId.isEmpty()) {
+ } else if (!mParameters.uniqueDisplayId.empty()) {
// If the IDC file specified a unique display Id, then it expects to be linked to a
// virtual display with the same unique ID.
- uniqueDisplayId = &mParameters.uniqueDisplayId;
+ uniqueDisplayId = mParameters.uniqueDisplayId;
viewportTypeToUse = ViewportType::VIEWPORT_VIRTUAL;
} else {
viewportTypeToUse = ViewportType::VIEWPORT_INTERNAL;
@@ -3536,7 +3539,7 @@
ALOGI(INDENT "Touch device '%s' could not query the properties of its associated "
"display. The device will be inoperable until the display size "
"becomes available.",
- getDeviceName().string());
+ getDeviceName().c_str());
mDeviceMode = DEVICE_MODE_DISABLED;
return;
}
@@ -3642,7 +3645,7 @@
if (viewportChanged || deviceModeChanged) {
ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
"display id %d",
- getDeviceId(), getDeviceName().string(), mSurfaceWidth, mSurfaceHeight,
+ getDeviceId(), getDeviceName().c_str(), mSurfaceWidth, mSurfaceHeight,
mSurfaceOrientation, mDeviceMode, mViewport.displayId);
// Configure X and Y factors.
@@ -6925,7 +6928,7 @@
#if DEBUG_POINTERS
ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
"ignoring the rest.",
- getDeviceName().string(), MAX_POINTERS);
+ getDeviceName().c_str(), MAX_POINTERS);
#endif
break; // too many fingers!
}
@@ -7016,7 +7019,7 @@
if (slotCount > MAX_SLOTS) {
ALOGW("MultiTouch Device %s reported %zu slots but the framework "
"only supports a maximum of %zu slots at this time.",
- getDeviceName().string(), slotCount, MAX_SLOTS);
+ getDeviceName().c_str(), slotCount, MAX_SLOTS);
slotCount = MAX_SLOTS;
}
mMultiTouchMotionAccumulator.configure(getDevice(),
@@ -7259,7 +7262,7 @@
// Prefer to keep explicitly mapped axes.
if (mAxes.size() > PointerCoords::MAX_AXES) {
ALOGI("Joystick '%s' has %zu axes but the framework only supports a maximum of %d.",
- getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
+ getDeviceName().c_str(), mAxes.size(), PointerCoords::MAX_AXES);
pruneAxes(true);
pruneAxes(false);
}
@@ -7281,7 +7284,7 @@
} else {
ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
"have already been assigned to other axes.",
- getDeviceName().string(), mAxes.keyAt(i));
+ getDeviceName().c_str(), mAxes.keyAt(i));
mAxes.removeItemsAt(i--);
numAxes -= 1;
}
@@ -7310,7 +7313,7 @@
continue;
}
ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
- getDeviceName().string(), mAxes.keyAt(i));
+ getDeviceName().c_str(), mAxes.keyAt(i));
mAxes.removeItemsAt(i);
}
}
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index af26b4f..c06168d 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -101,7 +101,7 @@
// The excluded device names for the platform.
// Devices with these names will be ignored.
- Vector<String8> excludedDeviceNames;
+ std::vector<std::string> excludedDeviceNames;
// Velocity control parameters for mouse pointer movements.
VelocityControlParameters pointerVelocityControlParameters;
@@ -201,7 +201,7 @@
pointerGestureZoomSpeedRatio(0.3f),
showTouches(false) { }
- bool getDisplayViewport(ViewportType viewportType, const String8* displayId,
+ bool getDisplayViewport(ViewportType viewportType, const std::string& uniqueDisplayId,
DisplayViewport* outViewport) const;
void setPhysicalDisplayViewport(ViewportType viewportType, const DisplayViewport& viewport);
void setVirtualDisplayViewports(const Vector<DisplayViewport>& viewports);
@@ -274,11 +274,11 @@
const InputDeviceIdentifier& identifier) = 0;
/* Gets a user-supplied alias for a particular input device, or an empty string if none. */
- virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier) = 0;
+ virtual std::string getDeviceAlias(const InputDeviceIdentifier& identifier) = 0;
/* Gets the affine calibration associated with the specified device. */
virtual TouchAffineTransformation getTouchAffineTransformation(
- const String8& inputDeviceDescriptor, int32_t surfaceRotation) = 0;
+ const std::string& inputDeviceDescriptor, int32_t surfaceRotation) = 0;
};
@@ -553,8 +553,8 @@
inline int32_t getId() const { return mId; }
inline int32_t getControllerNumber() const { return mControllerNumber; }
inline int32_t getGeneration() const { return mGeneration; }
- inline const String8& getName() const { return mIdentifier.name; }
- inline const String8& getDescriptor() { return mIdentifier.descriptor; }
+ inline const std::string getName() const { return mIdentifier.name; }
+ inline const std::string getDescriptor() { return mIdentifier.descriptor; }
inline uint32_t getClasses() const { return mClasses; }
inline uint32_t getSources() const { return mSources; }
@@ -625,7 +625,7 @@
int32_t mGeneration;
int32_t mControllerNumber;
InputDeviceIdentifier mIdentifier;
- String8 mAlias;
+ std::string mAlias;
uint32_t mClasses;
Vector<InputMapper*> mMappers;
@@ -981,7 +981,7 @@
inline InputDevice* getDevice() { return mDevice; }
inline int32_t getDeviceId() { return mDevice->getId(); }
- inline const String8 getDeviceName() { return mDevice->getName(); }
+ inline const std::string getDeviceName() { return mDevice->getName(); }
inline InputReaderContext* getContext() { return mContext; }
inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
inline InputListenerInterface* getListener() { return mContext->getListener(); }
@@ -1309,7 +1309,7 @@
bool associatedDisplayIsExternal;
bool orientationAware;
bool hasButtonUnderPad;
- String8 uniqueDisplayId;
+ std::string uniqueDisplayId;
enum GestureMode {
GESTURE_MODE_SINGLE_TOUCH,
diff --git a/services/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
index bd11d56..2f046c3 100644
--- a/services/inputflinger/host/InputDriver.cpp
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -217,18 +217,18 @@
idi.product = id->productId;
idi.version = id->version;
- String8 configFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
+ std::string configFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
idi, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
- if (configFile.isEmpty()) {
+ if (configFile.empty()) {
ALOGD("No input device configuration file found for device '%s'.",
- idi.name.string());
+ idi.name.c_str());
} else {
auto propMap = new input_property_map_t();
- status_t status = PropertyMap::load(configFile, &propMap->propertyMap);
+ status_t status = PropertyMap::load(String8(configFile.c_str()), &propMap->propertyMap);
if (status) {
ALOGE("Error loading input device configuration file for device '%s'. "
"Using default configuration.",
- idi.name.string());
+ idi.name.c_str());
delete propMap;
return nullptr;
}
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 0e26d4a..61dcdd9 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -103,13 +103,20 @@
protected:
sp<FakeInputDispatcherPolicy> mFakePolicy;
sp<InputDispatcher> mDispatcher;
+ sp<InputDispatcherThread> mDispatcherThread;
virtual void SetUp() {
mFakePolicy = new FakeInputDispatcherPolicy();
mDispatcher = new InputDispatcher(mFakePolicy);
+ mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
+ //Start InputDispatcher thread
+ mDispatcherThread = new InputDispatcherThread(mDispatcher);
+ mDispatcherThread->run("InputDispatcherTest", PRIORITY_URGENT_DISPLAY);
}
virtual void TearDown() {
+ mDispatcherThread->requestExit();
+ mDispatcherThread.clear();
mFakePolicy.clear();
mDispatcher.clear();
}
@@ -253,4 +260,297 @@
<< "Should reject motion events with duplicate pointer ids.";
}
+// --- InputDispatcherTest SetInputWindowTest ---
+static const int32_t INJECT_EVENT_TIMEOUT = 500;
+static const int32_t DISPATCHING_TIMEOUT = 100;
+
+class FakeApplicationHandle : public InputApplicationHandle {
+public:
+ FakeApplicationHandle() {}
+ virtual ~FakeApplicationHandle() {}
+
+ virtual bool updateInfo() {
+ if (!mInfo) {
+ mInfo = new InputApplicationInfo();
+ }
+ mInfo->dispatchingTimeout = DISPATCHING_TIMEOUT;
+ return true;
+ }
+};
+
+class FakeWindowHandle : public InputWindowHandle {
+public:
+ static const int32_t WIDTH = 600;
+ static const int32_t HEIGHT = 800;
+
+ FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
+ const sp<InputDispatcher>& dispatcher, const std::string name) :
+ InputWindowHandle(inputApplicationHandle), mDispatcher(dispatcher),
+ mName(name), mFocused(false), mDisplayId(ADISPLAY_ID_DEFAULT) {
+ InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
+ mConsumer = new InputConsumer(mClientChannel);
+ mDispatcher->registerInputChannel(mServerChannel, this, false);
+ }
+
+ virtual ~FakeWindowHandle() {
+ mDispatcher->unregisterInputChannel(mServerChannel);
+ mServerChannel.clear();
+ mClientChannel.clear();
+ mDispatcher.clear();
+
+ if (mConsumer != nullptr) {
+ delete mConsumer;
+ }
+ }
+
+ virtual bool updateInfo() {
+ if (!mInfo) {
+ mInfo = new InputWindowInfo();
+ }
+ mInfo->inputChannel = mServerChannel;
+ mInfo->name = mName;
+ mInfo->layoutParamsFlags = 0;
+ mInfo->layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
+ mInfo->dispatchingTimeout = DISPATCHING_TIMEOUT;
+ mInfo->frameLeft = 0;
+ mInfo->frameTop = 0;
+ mInfo->frameRight = WIDTH;
+ mInfo->frameBottom = HEIGHT;
+ mInfo->scaleFactor = 1.0;
+ mInfo->addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
+ mInfo->visible = true;
+ mInfo->canReceiveKeys = true;
+ mInfo->hasFocus = mFocused;
+ mInfo->hasWallpaper = false;
+ mInfo->paused = false;
+ mInfo->layer = 0;
+ mInfo->ownerPid = INJECTOR_PID;
+ mInfo->ownerUid = INJECTOR_UID;
+ mInfo->inputFeatures = 0;
+ mInfo->displayId = mDisplayId;
+
+ return true;
+ }
+
+ void setFocus() {
+ mFocused = true;
+ }
+
+ void setDisplayId(int32_t displayId) {
+ mDisplayId = displayId;
+ }
+
+ void consumeEvent(int32_t expectedEventType, int32_t expectedDisplayId) {
+ uint32_t consumeSeq;
+ InputEvent* event;
+ status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
+ &consumeSeq, &event);
+
+ ASSERT_EQ(OK, status)
+ << mName.c_str() << ": consumer consume should return OK.";
+ ASSERT_TRUE(event != nullptr)
+ << mName.c_str() << ": consumer should have returned non-NULL event.";
+ ASSERT_EQ(expectedEventType, event->getType())
+ << mName.c_str() << ": consumer type should same as expected one.";
+
+ ASSERT_EQ(expectedDisplayId, event->getDisplayId())
+ << mName.c_str() << ": consumer displayId should same as expected one.";
+
+ status = mConsumer->sendFinishedSignal(consumeSeq, true /*handled*/);
+ ASSERT_EQ(OK, status)
+ << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
+ }
+
+ void assertNoEvents() {
+ uint32_t consumeSeq;
+ InputEvent* event;
+ status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
+ &consumeSeq, &event);
+ ASSERT_NE(OK, status)
+ << mName.c_str()
+ << ": should not have received any events, so consume(..) should not return OK.";
+ }
+
+ private:
+ sp<InputDispatcher> mDispatcher;
+ sp<InputChannel> mServerChannel, mClientChannel;
+ InputConsumer *mConsumer;
+ PreallocatedInputEventFactory mEventFactory;
+
+ std::string mName;
+ bool mFocused;
+ int32_t mDisplayId;
+};
+
+static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher) {
+ KeyEvent event;
+ nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ // Define a valid key down event.
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
+ AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
+ AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
+
+ // Inject event until dispatch out.
+ return dispatcher->injectInputEvent(
+ &event,
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
+ INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
+}
+
+static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t displayId) {
+ MotionEvent event;
+ PointerProperties pointerProperties[1];
+ PointerCoords pointerCoords[1];
+
+ pointerProperties[0].clear();
+ pointerProperties[0].id = 0;
+ pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+
+ pointerCoords[0].clear();
+ pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
+ pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 200);
+
+ nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+ // Define a valid motion down event.
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, displayId,
+ AMOTION_EVENT_ACTION_DOWN, /* actionButton */0, /* flags */ 0, /* edgeFlags */ 0,
+ AMETA_NONE, /* buttonState */ 0, /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
+ /* yPrecision */ 0, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties,
+ pointerCoords);
+
+ // Inject event until dispatch out.
+ return dispatcher->injectInputEvent(
+ &event,
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
+ INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
+}
+
+TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window");
+
+ Vector<sp<InputWindowHandle>> inputWindowHandles;
+ inputWindowHandles.add(window);
+
+ mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, ADISPLAY_ID_DEFAULT))
+ << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+
+ // Window should receive motion event.
+ window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
+}
+
+// The foreground window should receive the first touch down event.
+TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top");
+ sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second");
+
+ Vector<sp<InputWindowHandle>> inputWindowHandles;
+ inputWindowHandles.add(windowTop);
+ inputWindowHandles.add(windowSecond);
+
+ mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, ADISPLAY_ID_DEFAULT))
+ << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+
+ // Top window should receive the touch down event. Second window should not receive anything.
+ windowTop->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
+ windowSecond->assertNoEvents();
+}
+
+TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top");
+ sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second");
+
+ // Set focus application.
+ mDispatcher->setFocusedApplication(application);
+
+ // Expect one focus window exist in display.
+ windowSecond->setFocus();
+ Vector<sp<InputWindowHandle>> inputWindowHandles;
+ inputWindowHandles.add(windowTop);
+ inputWindowHandles.add(windowSecond);
+
+ mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
+ << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+
+ // Focused window should receive event.
+ windowTop->assertNoEvents();
+ windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
+}
+
+TEST_F(InputDispatcherTest, SetInputWindow_MultiDisplayTouch) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ sp<FakeWindowHandle> windowInPrimary = new FakeWindowHandle(application, mDispatcher, "D_1");
+ sp<FakeWindowHandle> windowInSecondary = new FakeWindowHandle(application, mDispatcher, "D_2");
+
+ // Test the primary display touch down.
+ Vector<sp<InputWindowHandle>> inputWindowHandles;
+ inputWindowHandles.push(windowInPrimary);
+
+ mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, ADISPLAY_ID_DEFAULT))
+ << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+ windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
+ windowInSecondary->assertNoEvents();
+
+ // Test the second display touch down.
+ constexpr int32_t SECOND_DISPLAY_ID = 1;
+ windowInSecondary->setDisplayId(SECOND_DISPLAY_ID);
+ Vector<sp<InputWindowHandle>> inputWindowHandles_Second;
+ inputWindowHandles_Second.push(windowInSecondary);
+
+ mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, SECOND_DISPLAY_ID))
+ << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+ windowInPrimary->assertNoEvents();
+ windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
+}
+
+// TODO(b/111361570): multi-display focus, one focus window per display.
+TEST_F(InputDispatcherTest, SetInputWindow_FocusedInMultiDisplay) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ sp<FakeWindowHandle> windowInPrimary = new FakeWindowHandle(application, mDispatcher, "D_1");
+ sp<FakeApplicationHandle> application2 = new FakeApplicationHandle();
+ sp<FakeWindowHandle> windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2");
+
+ // Set focus to second display window.
+ mDispatcher->setFocusedApplication(application2);
+ windowInSecondary->setFocus();
+
+ // Update all windows per displays.
+ Vector<sp<InputWindowHandle>> inputWindowHandles;
+ inputWindowHandles.push(windowInPrimary);
+ mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
+
+ constexpr int32_t SECOND_DISPLAY_ID = 1;
+ windowInSecondary->setDisplayId(SECOND_DISPLAY_ID);
+ Vector<sp<InputWindowHandle>> inputWindowHandles_Second;
+ inputWindowHandles_Second.push(windowInSecondary);
+ mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
+
+ // Test inject a key down.
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
+ << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+ windowInPrimary->assertNoEvents();
+ windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
+
+ // Remove secondary display.
+ inputWindowHandles_Second.clear();
+ mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
+
+ // Expect old focus should receive a cancel event.
+ windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
+
+ // Test inject a key down, should timeout because of no target window.
+ ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
+ << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
+ windowInPrimary->assertNoEvents();
+ windowInSecondary->assertNoEvents();
+}
+
} // namespace android
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 286cf88..9b985dc 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -142,7 +142,7 @@
}
void setDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
- const String8& uniqueId) {
+ const std::string& uniqueId) {
DisplayViewport v = createDisplayViewport(displayId, width, height, orientation, uniqueId);
// Set the size of both the internal and external display at the same time.
mConfig.setPhysicalDisplayViewport(ViewportType::VIEWPORT_INTERNAL, v);
@@ -150,14 +150,14 @@
}
void setVirtualDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
- const String8& uniqueId) {
+ const std::string& uniqueId) {
Vector<DisplayViewport> viewports;
viewports.push_back(createDisplayViewport(displayId, width, height, orientation, uniqueId));
mConfig.setVirtualDisplayViewports(viewports);
}
- void addExcludedDeviceName(const String8& deviceName) {
- mConfig.excludedDeviceNames.push(deviceName);
+ void addExcludedDeviceName(const std::string& deviceName) {
+ mConfig.excludedDeviceNames.push_back(deviceName);
}
void addDisabledDevice(int32_t deviceId) {
@@ -188,7 +188,7 @@
return mInputDevices;
}
- TouchAffineTransformation getTouchAffineTransformation(const String8& inputDeviceDescriptor,
+ TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
int32_t surfaceRotation) {
return transform;
}
@@ -203,7 +203,7 @@
private:
DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height,
- int32_t orientation, const String8& uniqueId) {
+ int32_t orientation, const std::string& uniqueId) {
bool isRotated = (orientation == DISPLAY_ORIENTATION_90
|| orientation == DISPLAY_ORIENTATION_270);
DisplayViewport v;
@@ -239,8 +239,8 @@
return nullptr;
}
- virtual String8 getDeviceAlias(const InputDeviceIdentifier&) {
- return String8::empty();
+ virtual std::string getDeviceAlias(const InputDeviceIdentifier&) {
+ return "";
}
};
@@ -392,7 +392,7 @@
};
KeyedVector<int32_t, Device*> mDevices;
- Vector<String8> mExcludedDevices;
+ std::vector<std::string> mExcludedDevices;
List<RawEvent> mEvents;
protected:
@@ -405,7 +405,7 @@
public:
FakeEventHub() { }
- void addDevice(int32_t deviceId, const String8& name, uint32_t classes) {
+ void addDevice(int32_t deviceId, const std::string& name, uint32_t classes) {
Device* device = new Device(classes);
device->identifier.name = name;
mDevices.add(deviceId, device);
@@ -534,7 +534,7 @@
return device->leds.valueFor(led);
}
- Vector<String8>& getExcludedDevices() {
+ std::vector<std::string>& getExcludedDevices() {
return mExcludedDevices;
}
@@ -566,7 +566,7 @@
private:
Device* getDevice(int32_t deviceId) const {
ssize_t index = mDevices.indexOfKey(deviceId);
- return index >= 0 ? mDevices.valueAt(index) : NULL;
+ return index >= 0 ? mDevices.valueAt(index) : nullptr;
}
virtual uint32_t getDeviceClasses(int32_t deviceId) const {
@@ -658,7 +658,7 @@
return NAME_NOT_FOUND;
}
- virtual void setExcludedDevices(const Vector<String8>& devices) {
+ virtual void setExcludedDevices(const std::vector<std::string>& devices) {
mExcludedDevices = devices;
}
@@ -1052,7 +1052,7 @@
mNextDevice = device;
}
- InputDevice* newDevice(int32_t deviceId, int32_t controllerNumber, const String8& name,
+ InputDevice* newDevice(int32_t deviceId, int32_t controllerNumber, const std::string& name,
uint32_t classes) {
InputDeviceIdentifier identifier;
identifier.name = name;
@@ -1101,7 +1101,7 @@
mFakeEventHub.clear();
}
- void addDevice(int32_t deviceId, const String8& name, uint32_t classes,
+ void addDevice(int32_t deviceId, const std::string& name, uint32_t classes,
const PropertyMap* configuration) {
mFakeEventHub->addDevice(deviceId, name, classes);
@@ -1129,7 +1129,7 @@
}
FakeInputMapper* addDeviceWithFakeInputMapper(int32_t deviceId, int32_t controllerNumber,
- const String8& name, uint32_t classes, uint32_t sources,
+ const std::string& name, uint32_t classes, uint32_t sources,
const PropertyMap* configuration) {
InputDevice* device = mReader->newDevice(deviceId, controllerNumber, name, classes);
FakeInputMapper* mapper = new FakeInputMapper(device, sources);
@@ -1141,17 +1141,18 @@
};
TEST_F(InputReaderTest, GetInputDevices) {
- ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
+ ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard",
INPUT_DEVICE_CLASS_KEYBOARD, nullptr));
- ASSERT_NO_FATAL_FAILURE(addDevice(2, String8("ignored"),
+ ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored",
0, nullptr)); // no classes so device will be ignored
+
Vector<InputDeviceInfo> inputDevices;
mReader->getInputDevices(inputDevices);
ASSERT_EQ(1U, inputDevices.size());
ASSERT_EQ(1, inputDevices[0].getId());
- ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.string());
+ ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.c_str());
ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
ASSERT_EQ(size_t(0), inputDevices[0].getMotionRanges().size());
@@ -1160,7 +1161,7 @@
inputDevices = mFakePolicy->getInputDevices();
ASSERT_EQ(1U, inputDevices.size());
ASSERT_EQ(1, inputDevices[0].getId());
- ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.string());
+ ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.c_str());
ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
ASSERT_EQ(size_t(0), inputDevices[0].getMotionRanges().size());
@@ -1169,12 +1170,12 @@
TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) {
constexpr int32_t deviceId = 1;
constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
- InputDevice* device = mReader->newDevice(deviceId, 0, String8("fake"), deviceClass);
+ InputDevice* device = mReader->newDevice(deviceId, 0, "fake", deviceClass);
// Must add at least one mapper or the device will be ignored!
FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD);
device->addMapper(mapper);
mReader->setNextDevice(device);
- addDevice(deviceId, String8("fake"), deviceClass, nullptr);
+ addDevice(deviceId, "fake", deviceClass, nullptr);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr));
@@ -1208,7 +1209,7 @@
TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
FakeInputMapper* mapper = nullptr;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
+ ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, "fake",
INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr));
mapper->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
@@ -1235,7 +1236,7 @@
TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
FakeInputMapper* mapper = nullptr;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
+ ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, "fake",
INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr));
mapper->setScanCodeState(KEY_A, AKEY_STATE_DOWN);
@@ -1262,7 +1263,7 @@
TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
FakeInputMapper* mapper = nullptr;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
+ ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, "fake",
INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr));
mapper->setSwitchState(SW_LID, AKEY_STATE_DOWN);
@@ -1289,8 +1290,9 @@
TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
FakeInputMapper* mapper = nullptr;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
+ ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, "fake",
INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr));
+
mapper->addSupportedKeyCode(AKEYCODE_A);
mapper->addSupportedKeyCode(AKEYCODE_B);
@@ -1323,7 +1325,7 @@
}
TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
- addDevice(1, String8("ignored"), INPUT_DEVICE_CLASS_KEYBOARD, nullptr);
+ addDevice(1, "ignored", INPUT_DEVICE_CLASS_KEYBOARD, nullptr);
NotifyConfigurationChangedArgs args;
@@ -1333,7 +1335,7 @@
TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
FakeInputMapper* mapper = nullptr;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
+ ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, "fake",
INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr));
mFakeEventHub->enqueueEvent(0, 1, EV_KEY, KEY_A, 1);
@@ -1373,7 +1375,7 @@
mFakeListener = new FakeInputListener();
mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
- mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
+ mFakeEventHub->addDevice(DEVICE_ID, DEVICE_NAME, 0);
InputDeviceIdentifier identifier;
identifier.name = DEVICE_NAME;
mDevice = new InputDevice(mFakeContext, DEVICE_ID, DEVICE_GENERATION,
@@ -1399,7 +1401,7 @@
TEST_F(InputDeviceTest, ImmutableProperties) {
ASSERT_EQ(DEVICE_ID, mDevice->getId());
- ASSERT_STREQ(DEVICE_NAME, mDevice->getName());
+ ASSERT_STREQ(DEVICE_NAME, mDevice->getName().c_str());
ASSERT_EQ(DEVICE_CLASSES, mDevice->getClasses());
}
@@ -1427,7 +1429,7 @@
InputDeviceInfo info;
mDevice->getDeviceInfo(&info);
ASSERT_EQ(DEVICE_ID, info.getId());
- ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.string());
+ ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
@@ -1497,7 +1499,7 @@
InputDeviceInfo info;
mDevice->getDeviceInfo(&info);
ASSERT_EQ(DEVICE_ID, info.getId());
- ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.string());
+ ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
@@ -1570,7 +1572,7 @@
mDevice = new InputDevice(mFakeContext, DEVICE_ID, DEVICE_GENERATION,
DEVICE_CONTROLLER_NUMBER, identifier, DEVICE_CLASSES);
- mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
+ mFakeEventHub->addDevice(DEVICE_ID, DEVICE_NAME, 0);
}
virtual void TearDown() {
@@ -1597,12 +1599,12 @@
void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
int32_t orientation) {
- mFakePolicy->setDisplayViewport(displayId, width, height, orientation, String8::empty());
+ mFakePolicy->setDisplayViewport(displayId, width, height, orientation, "");
configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
}
void setVirtualDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
- int32_t orientation, const String8& uniqueId) {
+ int32_t orientation, const std::string& uniqueId) {
mFakePolicy->setVirtualDisplayViewport(displayId, width, height, orientation, uniqueId);
configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
}
@@ -3048,7 +3050,7 @@
void TouchInputMapperTest::prepareVirtualDisplay(int32_t orientation) {
setVirtualDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH,
- VIRTUAL_DISPLAY_HEIGHT, orientation, String8(VIRTUAL_DISPLAY_UNIQUE_ID));
+ VIRTUAL_DISPLAY_HEIGHT, orientation, VIRTUAL_DISPLAY_UNIQUE_ID);
}
void TouchInputMapperTest::prepareVirtualKeys() {
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 2712b1c..e94200e 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -184,97 +184,6 @@
return SyncFeatures::getInstance().useWaitSync();
}
-base::unique_fd RenderEngine::flush() {
- if (!GLExtensions::getInstance().hasNativeFenceSync()) {
- return base::unique_fd();
- }
-
- EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
- if (sync == EGL_NO_SYNC_KHR) {
- ALOGW("failed to create EGL native fence sync: %#x", eglGetError());
- return base::unique_fd();
- }
-
- // native fence fd will not be populated until flush() is done.
- glFlush();
-
- // get the fence fd
- base::unique_fd fenceFd(eglDupNativeFenceFDANDROID(mEGLDisplay, sync));
- eglDestroySyncKHR(mEGLDisplay, sync);
- if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
- ALOGW("failed to dup EGL native fence sync: %#x", eglGetError());
- }
-
- return fenceFd;
-}
-
-bool RenderEngine::finish() {
- if (!GLExtensions::getInstance().hasFenceSync()) {
- ALOGW("no synchronization support");
- return false;
- }
-
- EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr);
- if (sync == EGL_NO_SYNC_KHR) {
- ALOGW("failed to create EGL fence sync: %#x", eglGetError());
- return false;
- }
-
- EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
- 2000000000 /*2 sec*/);
- EGLint error = eglGetError();
- eglDestroySyncKHR(mEGLDisplay, sync);
- if (result != EGL_CONDITION_SATISFIED_KHR) {
- if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- ALOGW("fence wait timed out");
- } else {
- ALOGW("error waiting on EGL fence: %#x", error);
- }
- return false;
- }
-
- return true;
-}
-
-bool RenderEngine::waitFence(base::unique_fd fenceFd) {
- if (!GLExtensions::getInstance().hasNativeFenceSync() ||
- !GLExtensions::getInstance().hasWaitSync()) {
- return false;
- }
-
- EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
- EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
- if (sync == EGL_NO_SYNC_KHR) {
- ALOGE("failed to create EGL native fence sync: %#x", eglGetError());
- return false;
- }
-
- // fenceFd is now owned by EGLSync
- (void)fenceFd.release();
-
- // XXX: The spec draft is inconsistent as to whether this should return an
- // EGLint or void. Ignore the return value for now, as it's not strictly
- // needed.
- eglWaitSyncKHR(mEGLDisplay, sync, 0);
- EGLint error = eglGetError();
- eglDestroySyncKHR(mEGLDisplay, sync);
- if (error != EGL_SUCCESS) {
- ALOGE("failed to wait for EGL native fence sync: %#x", error);
- return false;
- }
-
- return true;
-}
-
-void RenderEngine::checkErrors() const {
- do {
- // there could be more than one error flag
- GLenum error = glGetError();
- if (error == GL_NO_ERROR) break;
- ALOGE("GL error 0x%04x", int(error));
- } while (true);
-}
-
RenderEngine::GlesVersion RenderEngine::parseGlesVersion(const char* str) {
int major, minor;
if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
@@ -293,56 +202,6 @@
return GLES_VERSION_1_0;
}
-void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height, float red,
- float green, float blue, float alpha) {
- size_t c;
- Rect const* r = region.getArray(&c);
- Mesh mesh(Mesh::TRIANGLES, c * 6, 2);
- Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
- for (size_t i = 0; i < c; i++, r++) {
- position[i * 6 + 0].x = r->left;
- position[i * 6 + 0].y = height - r->top;
- position[i * 6 + 1].x = r->left;
- position[i * 6 + 1].y = height - r->bottom;
- position[i * 6 + 2].x = r->right;
- position[i * 6 + 2].y = height - r->bottom;
- position[i * 6 + 3].x = r->left;
- position[i * 6 + 3].y = height - r->top;
- position[i * 6 + 4].x = r->right;
- position[i * 6 + 4].y = height - r->bottom;
- position[i * 6 + 5].x = r->right;
- position[i * 6 + 5].y = height - r->top;
- }
- setupFillWithColor(red, green, blue, alpha);
- drawMesh(mesh);
-}
-
-void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
- glClearColor(red, green, blue, alpha);
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-void RenderEngine::setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) {
- glScissor(left, bottom, right, top);
- glEnable(GL_SCISSOR_TEST);
-}
-
-void RenderEngine::disableScissor() {
- glDisable(GL_SCISSOR_TEST);
-}
-
-void RenderEngine::genTextures(size_t count, uint32_t* names) {
- glGenTextures(count, names);
-}
-
-void RenderEngine::deleteTextures(size_t count, uint32_t const* names) {
- glDeleteTextures(count, names);
-}
-
-void RenderEngine::readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) {
- glReadPixels(l, b, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-}
-
void RenderEngine::dump(String8& result) {
const GLExtensions& extensions = GLExtensions::getInstance();
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
index bfabf4d..61df675 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
@@ -34,6 +34,7 @@
#include <ui/ColorSpace.h>
#include <ui/DebugUtils.h>
#include <ui/Rect.h>
+#include <ui/Region.h>
#include <utils/String8.h>
#include <utils/Trace.h>
#include "GLExtensions.h"
@@ -195,6 +196,134 @@
eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
+base::unique_fd GLES20RenderEngine::flush() {
+ if (!GLExtensions::getInstance().hasNativeFenceSync()) {
+ return base::unique_fd();
+ }
+
+ EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
+ if (sync == EGL_NO_SYNC_KHR) {
+ ALOGW("failed to create EGL native fence sync: %#x", eglGetError());
+ return base::unique_fd();
+ }
+
+ // native fence fd will not be populated until flush() is done.
+ glFlush();
+
+ // get the fence fd
+ base::unique_fd fenceFd(eglDupNativeFenceFDANDROID(mEGLDisplay, sync));
+ eglDestroySyncKHR(mEGLDisplay, sync);
+ if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+ ALOGW("failed to dup EGL native fence sync: %#x", eglGetError());
+ }
+
+ return fenceFd;
+}
+
+bool GLES20RenderEngine::finish() {
+ if (!GLExtensions::getInstance().hasFenceSync()) {
+ ALOGW("no synchronization support");
+ return false;
+ }
+
+ EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr);
+ if (sync == EGL_NO_SYNC_KHR) {
+ ALOGW("failed to create EGL fence sync: %#x", eglGetError());
+ return false;
+ }
+
+ EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
+ 2000000000 /*2 sec*/);
+ EGLint error = eglGetError();
+ eglDestroySyncKHR(mEGLDisplay, sync);
+ if (result != EGL_CONDITION_SATISFIED_KHR) {
+ if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+ ALOGW("fence wait timed out");
+ } else {
+ ALOGW("error waiting on EGL fence: %#x", error);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool GLES20RenderEngine::waitFence(base::unique_fd fenceFd) {
+ if (!GLExtensions::getInstance().hasNativeFenceSync() ||
+ !GLExtensions::getInstance().hasWaitSync()) {
+ return false;
+ }
+
+ EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
+ EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+ if (sync == EGL_NO_SYNC_KHR) {
+ ALOGE("failed to create EGL native fence sync: %#x", eglGetError());
+ return false;
+ }
+
+ // fenceFd is now owned by EGLSync
+ (void)fenceFd.release();
+
+ // XXX: The spec draft is inconsistent as to whether this should return an
+ // EGLint or void. Ignore the return value for now, as it's not strictly
+ // needed.
+ eglWaitSyncKHR(mEGLDisplay, sync, 0);
+ EGLint error = eglGetError();
+ eglDestroySyncKHR(mEGLDisplay, sync);
+ if (error != EGL_SUCCESS) {
+ ALOGE("failed to wait for EGL native fence sync: %#x", error);
+ return false;
+ }
+
+ return true;
+}
+
+void GLES20RenderEngine::fillRegionWithColor(const Region& region, uint32_t height, float red,
+ float green, float blue, float alpha) {
+ size_t c;
+ Rect const* r = region.getArray(&c);
+ Mesh mesh(Mesh::TRIANGLES, c * 6, 2);
+ Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
+ for (size_t i = 0; i < c; i++, r++) {
+ position[i * 6 + 0].x = r->left;
+ position[i * 6 + 0].y = height - r->top;
+ position[i * 6 + 1].x = r->left;
+ position[i * 6 + 1].y = height - r->bottom;
+ position[i * 6 + 2].x = r->right;
+ position[i * 6 + 2].y = height - r->bottom;
+ position[i * 6 + 3].x = r->left;
+ position[i * 6 + 3].y = height - r->top;
+ position[i * 6 + 4].x = r->right;
+ position[i * 6 + 4].y = height - r->bottom;
+ position[i * 6 + 5].x = r->right;
+ position[i * 6 + 5].y = height - r->top;
+ }
+ setupFillWithColor(red, green, blue, alpha);
+ drawMesh(mesh);
+}
+
+void GLES20RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
+ glClearColor(red, green, blue, alpha);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+void GLES20RenderEngine::setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) {
+ glScissor(left, bottom, right, top);
+ glEnable(GL_SCISSOR_TEST);
+}
+
+void GLES20RenderEngine::disableScissor() {
+ glDisable(GL_SCISSOR_TEST);
+}
+
+void GLES20RenderEngine::genTextures(size_t count, uint32_t* names) {
+ glGenTextures(count, names);
+}
+
+void GLES20RenderEngine::deleteTextures(size_t count, uint32_t const* names) {
+ glDeleteTextures(count, names);
+}
+
void GLES20RenderEngine::bindExternalTextureImage(uint32_t texName,
const Image& image) {
const GLImage& glImage = static_cast<const GLImage&>(image);
@@ -207,6 +336,10 @@
}
}
+void GLES20RenderEngine::readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) {
+ glReadPixels(l, b, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+}
+
status_t GLES20RenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(framebuffer);
EGLImageKHR eglImage = glFramebuffer->getEGLImage();
@@ -245,6 +378,15 @@
disableScissor();
}
+void GLES20RenderEngine::checkErrors() const {
+ do {
+ // there could be more than one error flag
+ GLenum error = glGetError();
+ if (error == GL_NO_ERROR) break;
+ ALOGE("GL error 0x%04x", int(error));
+ } while (true);
+}
+
void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
ui::Transform::orientation_flags rotation) {
int32_t l = sourceCrop.left;
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
index 3113e53..04dc1b1 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
@@ -48,14 +48,24 @@
std::unique_ptr<Image> createImage() override;
void primeCache() const override;
-
- bool isCurrent() const;
+ bool isCurrent() const override;
bool setCurrentSurface(const Surface& surface) override;
void resetCurrentSurface() override;
-
+ base::unique_fd flush() override;
+ bool finish() override;
+ bool waitFence(base::unique_fd fenceFd) override;
+ void clearWithColor(float red, float green, float blue, float alpha) override;
+ void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
+ float blue, float alpha) override;
+ void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) override;
+ void disableScissor() override;
+ void genTextures(size_t count, uint32_t* names) override;
+ void deleteTextures(size_t count, uint32_t const* names) override;
void bindExternalTextureImage(uint32_t texName, const Image& image) override;
+ void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) override;
status_t bindFrameBuffer(Framebuffer* framebuffer) override;
void unbindFrameBuffer(Framebuffer* framebuffer) override;
+ void checkErrors() const override;
protected:
void dump(String8& result) override;
diff --git a/services/surfaceflinger/RenderEngine/gl/Program.cpp b/services/surfaceflinger/RenderEngine/gl/Program.cpp
index 4d6839b..c8d6cf9 100644
--- a/services/surfaceflinger/RenderEngine/gl/Program.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/Program.cpp
@@ -20,7 +20,6 @@
#include <log/log.h>
#include <math/mat4.h>
-#include <renderengine/private/Description.h>
#include <utils/String8.h>
#include "ProgramCache.h"
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
index 7777202..86a1264 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
@@ -25,8 +25,8 @@
#include <EGL/eglext.h>
#include <android-base/unique_fd.h>
#include <math/mat4.h>
-#include <renderengine/Image.h>
#include <renderengine/Framebuffer.h>
+#include <renderengine/Image.h>
#include <ui/GraphicTypes.h>
#include <ui/Transform.h>
@@ -105,7 +105,7 @@
virtual void unbindFrameBuffer(Framebuffer* framebuffer) = 0;
// set-up
- virtual void checkErrors() const;
+ virtual void checkErrors() const = 0;
virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
ui::Transform::orientation_flags rotation) = 0;
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
@@ -188,33 +188,6 @@
bool useNativeFenceSync() const override;
bool useWaitSync() const override;
- // synchronization
-
- // flush submits RenderEngine command stream for execution and returns a
- // native fence fd that is signaled when the execution has completed. It
- // returns -1 on errors.
- base::unique_fd flush() override;
- // finish waits until RenderEngine command stream has been executed. It
- // returns false on errors.
- bool finish() override;
- // waitFence inserts a wait on an external fence fd to RenderEngine
- // command stream. It returns false on errors.
- bool waitFence(base::unique_fd fenceFd) override;
-
- // helpers
- void clearWithColor(float red, float green, float blue, float alpha) override;
- void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
- float blue, float alpha) override;
-
- // common to all GL versions
- void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) override;
- void disableScissor() override;
- void genTextures(size_t count, uint32_t* names) override;
- void deleteTextures(size_t count, uint32_t const* names) override;
- void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) override;
-
- void checkErrors() const override;
-
void setupColorTransform(const mat4& /* colorTransform */) override {}
// internal to RenderEngine
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index a7c08cf..bb85f4c 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -29,8 +29,15 @@
namespace android {
+#define RETURN_VALUE_IF_INVALID(value) \
+ if (handle == nullptr || mConnections.count(handle->id) == 0) return value
+#define RETURN_IF_INVALID() \
+ if (handle == nullptr || mConnections.count(handle->id) == 0) return
+
std::atomic<int64_t> Scheduler::sNextId = 0;
+Scheduler::~Scheduler() = default;
+
sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
@@ -38,11 +45,9 @@
const int64_t id = sNextId++;
ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
- std::unique_ptr<VSyncSource> eventThreadSource =
- std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
std::unique_ptr<EventThread> eventThread =
- std::make_unique<impl::EventThread>(std::move(eventThreadSource), resyncCallback,
- interceptCallback, connectionName);
+ makeEventThread(connectionName, dispSync, phaseOffsetNs, resyncCallback,
+ interceptCallback);
auto connection = std::make_unique<Connection>(new ConnectionHandle(id),
eventThread->createEventConnection(),
std::move(eventThread));
@@ -50,56 +55,55 @@
return mConnections[id]->handle;
}
+std::unique_ptr<EventThread> Scheduler::makeEventThread(
+ const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+ impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
+ impl::EventThread::InterceptVSyncsCallback interceptCallback) {
+ std::unique_ptr<VSyncSource> eventThreadSource =
+ std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
+ return std::make_unique<impl::EventThread>(std::move(eventThreadSource), resyncCallback,
+ interceptCallback, connectionName);
+}
+
sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
const sp<Scheduler::ConnectionHandle>& handle) {
- if (mConnections.count(handle->id) != 0) {
- return mConnections[handle->id]->thread->createEventConnection();
- }
- return nullptr;
+ RETURN_VALUE_IF_INVALID(nullptr);
+ return mConnections[handle->id]->thread->createEventConnection();
}
EventThread* Scheduler::getEventThread(const sp<Scheduler::ConnectionHandle>& handle) {
- if (mConnections.count(handle->id) != 0) {
- return mConnections[handle->id]->thread.get();
- }
- return nullptr;
+ RETURN_VALUE_IF_INVALID(nullptr);
+ return mConnections[handle->id]->thread.get();
}
sp<BnDisplayEventConnection> Scheduler::getEventConnection(const sp<ConnectionHandle>& handle) {
- if (mConnections.find(handle->id) != mConnections.end()) {
- return mConnections[handle->id]->eventConnection;
- }
- return nullptr;
+ RETURN_VALUE_IF_INVALID(nullptr);
+ return mConnections[handle->id]->eventConnection;
}
void Scheduler::hotplugReceived(const sp<Scheduler::ConnectionHandle>& handle,
EventThread::DisplayType displayType, bool connected) {
- if (mConnections.find(handle->id) != mConnections.end()) {
- mConnections[handle->id]->thread->onHotplugReceived(displayType, connected);
- }
+ RETURN_IF_INVALID();
+ mConnections[handle->id]->thread->onHotplugReceived(displayType, connected);
}
void Scheduler::onScreenAcquired(const sp<Scheduler::ConnectionHandle>& handle) {
- if (mConnections.find(handle->id) != mConnections.end()) {
- mConnections[handle->id]->thread->onScreenAcquired();
- }
+ RETURN_IF_INVALID();
+ mConnections[handle->id]->thread->onScreenAcquired();
}
void Scheduler::onScreenReleased(const sp<Scheduler::ConnectionHandle>& handle) {
- if (mConnections.find(handle->id) != mConnections.end()) {
- mConnections[handle->id]->thread->onScreenReleased();
- }
+ RETURN_IF_INVALID();
+ mConnections[handle->id]->thread->onScreenReleased();
}
void Scheduler::dump(const sp<Scheduler::ConnectionHandle>& handle, String8& result) const {
- if (mConnections.find(handle->id) != mConnections.end()) {
- mConnections.at(handle->id)->thread->dump(result);
- }
+ RETURN_IF_INVALID();
+ mConnections.at(handle->id)->thread->dump(result);
}
void Scheduler::setPhaseOffset(const sp<Scheduler::ConnectionHandle>& handle, nsecs_t phaseOffset) {
- if (mConnections.find(handle->id) != mConnections.end()) {
- mConnections[handle->id]->thread->setPhaseOffset(phaseOffset);
- }
+ RETURN_IF_INVALID();
+ mConnections[handle->id]->thread->setPhaseOffset(phaseOffset);
}
} // namespace android
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index caccd6f..8efbff4 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -52,7 +52,7 @@
};
Scheduler() = default;
- ~Scheduler() = default;
+ virtual ~Scheduler();
/** Creates an EventThread connection. */
sp<ConnectionHandle> createConnection(
@@ -77,6 +77,12 @@
// Offers ability to modify phase offset in the event thread.
void setPhaseOffset(const sp<ConnectionHandle>& handle, nsecs_t phaseOffset);
+protected:
+ virtual std::unique_ptr<EventThread> makeEventThread(
+ const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+ impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
+ impl::EventThread::InterceptVSyncsCallback interceptCallback);
+
private:
static std::atomic<int64_t> sNextId;
std::unordered_map<int64_t, std::unique_ptr<Connection>> mConnections;
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 8f1f5e5..f1f0fbf 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -22,6 +22,7 @@
"DisplayTransactionTest.cpp",
"EventControlThreadTest.cpp",
"EventThreadTest.cpp",
+ "SchedulerTest.cpp",
"mock/DisplayHardware/MockComposer.cpp",
"mock/DisplayHardware/MockDisplaySurface.cpp",
"mock/DisplayHardware/MockPowerAdvisor.cpp",
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
new file mode 100644
index 0000000..c809e82
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -0,0 +1,186 @@
+#undef LOG_TAG
+#define LOG_TAG "SchedulerUnittests"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <log/log.h>
+
+#include "AsyncCallRecorder.h"
+#include "Scheduler/DispSync.h"
+#include "Scheduler/EventThread.h"
+#include "Scheduler/Scheduler.h"
+#include "mock/MockDispSync.h"
+#include "mock/MockEventThread.h"
+
+using testing::_;
+using testing::Return;
+
+namespace android {
+
+class SchedulerTest : public testing::Test {
+protected:
+ class MockEventThreadConnection : public BnDisplayEventConnection {
+ public:
+ MockEventThreadConnection() = default;
+ ~MockEventThreadConnection() = default;
+
+ MOCK_METHOD1(stealReceiveChannel, status_t(gui::BitTube* outChannel));
+ MOCK_METHOD1(setVsyncRate, status_t(uint32_t count));
+ MOCK_METHOD0(requestNextVsync, void());
+ };
+
+ /**
+ * This mock Scheduler class uses implementation of mock::EventThread but keeps everything else
+ * the same.
+ */
+ class MockScheduler : public android::Scheduler {
+ public:
+ MockScheduler(std::unique_ptr<EventThread> eventThread)
+ : mEventThread(std::move(eventThread)) {}
+
+ std::unique_ptr<EventThread> makeEventThread(
+ const char* /* connectionName */, DispSync* /* dispSync */,
+ nsecs_t /* phaseOffsetNs */,
+ impl::EventThread::ResyncWithRateLimitCallback /* resyncCallback */,
+ impl::EventThread::InterceptVSyncsCallback /* interceptCallback */) override {
+ return std::move(mEventThread);
+ }
+
+ MockScheduler() = default;
+ ~MockScheduler() override = default;
+
+ std::unique_ptr<EventThread> mEventThread;
+ };
+
+ SchedulerTest();
+ ~SchedulerTest() override;
+
+ sp<Scheduler::ConnectionHandle> mConnectionHandle;
+ mock::DispSync* mPrimaryDispSync = new mock::DispSync();
+ mock::EventThread* mEventThread;
+ std::unique_ptr<MockScheduler> mScheduler;
+ sp<MockEventThreadConnection> mEventThreadConnection;
+
+ AsyncCallRecorder<void (*)()> mResyncCallRecorder;
+ AsyncCallRecorder<void (*)(nsecs_t)> mInterceptVSyncCallRecorder;
+};
+
+SchedulerTest::SchedulerTest() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+
+ std::unique_ptr<mock::EventThread> eventThread = std::make_unique<mock::EventThread>();
+ mEventThread = eventThread.get();
+ mScheduler = std::make_unique<MockScheduler>(std::move(eventThread));
+ mEventThreadConnection = new MockEventThreadConnection();
+
+ // createConnection call to scheduler makes a createEventConnection call to EventThread. Make
+ // sure that call gets executed and returns an EventThread::Connection object.
+ EXPECT_CALL(*mEventThread, createEventConnection())
+ .WillRepeatedly(Return(mEventThreadConnection));
+
+ mConnectionHandle = mScheduler->createConnection("appConnection", mPrimaryDispSync, 16,
+ mResyncCallRecorder.getInvocable(),
+ mInterceptVSyncCallRecorder.getInvocable());
+}
+
+SchedulerTest::~SchedulerTest() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+}
+
+namespace {
+/* ------------------------------------------------------------------------
+ * Test cases
+ */
+TEST_F(SchedulerTest, canCreateAndDestroyTest) {
+ EXPECT_FALSE(mResyncCallRecorder.waitForCall().has_value());
+ EXPECT_FALSE(mInterceptVSyncCallRecorder.waitForCall().has_value());
+ EXPECT_EQ(0, mConnectionHandle->id);
+}
+
+TEST_F(SchedulerTest, testNullPtr) {
+ // Passing a null pointer for ConnectionHandle is a valid argument. The code doesn't throw any
+ // exceptions, just gracefully continues.
+ sp<IDisplayEventConnection> returnedValue;
+ ASSERT_NO_FATAL_FAILURE(returnedValue = mScheduler->createDisplayEventConnection(nullptr));
+ EXPECT_TRUE(returnedValue == nullptr);
+ EXPECT_TRUE(mScheduler->getEventThread(nullptr) == nullptr);
+ EXPECT_TRUE(mScheduler->getEventConnection(nullptr) == nullptr);
+ ASSERT_NO_FATAL_FAILURE(
+ mScheduler->hotplugReceived(nullptr, EventThread::DisplayType::Primary, false));
+ ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(nullptr));
+ ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(nullptr));
+ String8 testString;
+ ASSERT_NO_FATAL_FAILURE(mScheduler->dump(nullptr, testString));
+ EXPECT_TRUE(testString == "");
+ ASSERT_NO_FATAL_FAILURE(mScheduler->setPhaseOffset(nullptr, 10));
+}
+
+TEST_F(SchedulerTest, invalidConnectionHandle) {
+ // Passing an invalid ConnectionHandle is a valid argument. The code doesn't throw any
+ // exceptions, just gracefully continues.
+ sp<Scheduler::ConnectionHandle> connectionHandle = new Scheduler::ConnectionHandle(20);
+
+ sp<IDisplayEventConnection> returnedValue;
+ ASSERT_NO_FATAL_FAILURE(returnedValue =
+ mScheduler->createDisplayEventConnection(connectionHandle));
+ EXPECT_TRUE(returnedValue == nullptr);
+ EXPECT_TRUE(mScheduler->getEventThread(connectionHandle) == nullptr);
+ EXPECT_TRUE(mScheduler->getEventConnection(connectionHandle) == nullptr);
+
+ // The EXPECT_CALLS make sure we don't call the functions on the subsequent event threads.
+ EXPECT_CALL(*mEventThread, onHotplugReceived(_, _)).Times(0);
+ ASSERT_NO_FATAL_FAILURE(mScheduler->hotplugReceived(connectionHandle,
+ EventThread::DisplayType::Primary, false));
+
+ EXPECT_CALL(*mEventThread, onScreenAcquired()).Times(0);
+ ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(connectionHandle));
+
+ EXPECT_CALL(*mEventThread, onScreenReleased()).Times(0);
+ ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(connectionHandle));
+
+ String8 testString;
+ EXPECT_CALL(*mEventThread, dump(_)).Times(0);
+ ASSERT_NO_FATAL_FAILURE(mScheduler->dump(connectionHandle, testString));
+ EXPECT_TRUE(testString == "");
+
+ EXPECT_CALL(*mEventThread, setPhaseOffset(_)).Times(0);
+ ASSERT_NO_FATAL_FAILURE(mScheduler->setPhaseOffset(connectionHandle, 10));
+}
+
+TEST_F(SchedulerTest, validConnectionHandle) {
+ sp<IDisplayEventConnection> returnedValue;
+ ASSERT_NO_FATAL_FAILURE(returnedValue =
+ mScheduler->createDisplayEventConnection(mConnectionHandle));
+ EXPECT_TRUE(returnedValue != nullptr);
+ ASSERT_EQ(returnedValue, mEventThreadConnection);
+
+ EXPECT_TRUE(mScheduler->getEventThread(mConnectionHandle) != nullptr);
+ EXPECT_TRUE(mScheduler->getEventConnection(mConnectionHandle) != nullptr);
+
+ EXPECT_CALL(*mEventThread, onHotplugReceived(EventThread::DisplayType::Primary, false))
+ .Times(1);
+ ASSERT_NO_FATAL_FAILURE(mScheduler->hotplugReceived(mConnectionHandle,
+ EventThread::DisplayType::Primary, false));
+
+ EXPECT_CALL(*mEventThread, onScreenAcquired()).Times(1);
+ ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(mConnectionHandle));
+
+ EXPECT_CALL(*mEventThread, onScreenReleased()).Times(1);
+ ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(mConnectionHandle));
+
+ String8 testString("dump");
+ EXPECT_CALL(*mEventThread, dump(testString)).Times(1);
+ ASSERT_NO_FATAL_FAILURE(mScheduler->dump(mConnectionHandle, testString));
+ EXPECT_TRUE(testString != "");
+
+ EXPECT_CALL(*mEventThread, setPhaseOffset(10)).Times(1);
+ ASSERT_NO_FATAL_FAILURE(mScheduler->setPhaseOffset(mConnectionHandle, 10));
+}
+
+} // namespace
+} // namespace android
\ No newline at end of file