From ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44ad Mon Sep 17 00:00:00 2001 From: Adam Lesinski Date: Mon, 1 Aug 2016 16:44:29 -0700 Subject: [PATCH] AAPT: faketouch feature implied if no touchscreen feature requested. This changes the default implied feature of 'android.hardware.touchscreen' to 'android.hardware.faketouch' if no 'android.hardware.touchscreen' feature is requested, required or otherwise. Bug:30571641 Change-Id: I1e41242d4b1dc549cf69741d2a309baf476d084e --- .../guide/topics/manifest/uses-feature-element.jd | 29 ++++------------------ tools/aapt/Command.cpp | 27 +++++++++++++++++--- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd index 10841d675834..9b32244b736f 100755 --- a/docs/html/guide/topics/manifest/uses-feature-element.jd +++ b/docs/html/guide/topics/manifest/uses-feature-element.jd @@ -1230,7 +1230,7 @@ densities: '160'

- When declared as required, this feature indicates that the app is + By default, your app requires this feature. This feature indicates that the app is compatible with a device only if that device emulates a touchscreen ("fake touch" interface) or has an actual touchscreen.

@@ -1240,19 +1240,12 @@ densities: '160' that emulates a subset of a touchscreen's capabilities. For example, a mouse or remote control could drive an on-screen cursor. If your app requires basic point and click interaction (in other words, it won't work - with only a d-pad controller), you should declare this feature. Because + with only a d-pad controller), you should declare this feature or simply + avoid declaring any {@code android.hardware.touchscreen.*} features. Because this is the minimum level of touch interaction, you can also use an app that declares this feature on devices that offer more complex touch interfaces.

- -

- Note: Apps require the {@code android.hardware.touchscreen} - feature by default. If you want your app to be available to devices that - provide a fake touch interface, you must also explicitly declare that a - touchscreen is not required as follows: -

-
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
@@ -1327,21 +1320,9 @@ densities: '160'

- By default, your app requires this feature. As such, your app is not - available to devices that provide only an emulated touch interface ("fake - touch") by default. If you want to make your app available on devices - that provide a fake touch interface (or even on devices that provide only - a d-pad controller), you must explicitly declare that a touchscreen is - not required by declaring {@code android.hardware.touchscreen} with - {@code android:required="false"}. You should add this declaration if your - app uses—but does not require—a real touchscreen interface. -

- -

If your app in fact requires a touch interface (to perform more advanced - touch gestures such as fling), then you don't need to declare any touch - interface features because they're required by default. However, it's - best if you explicitly declare all features that your app uses. + touch gestures such as fling), then you must explicitly declare this feature + or any advanced touchscreen features.

diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 9976d00fa872..59da467a1cc3 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -529,6 +529,16 @@ struct FeatureGroup { int openGLESVersion; }; +static bool hasFeature(const char* name, const FeatureGroup& grp, + const KeyedVector& implied) { + String8 name8(name); + ssize_t idx = grp.features.indexOfKey(name8); + if (idx < 0) { + idx = implied.indexOfKey(name8); + } + return idx >= 0; +} + static void addImpliedFeature(KeyedVector* impliedFeatures, const char* name, const char* reason, bool sdk23) { String8 name8(name); @@ -616,9 +626,16 @@ static void addParentFeatures(FeatureGroup* grp, const String8& name) { } else if (name == "android.hardware.location.gps" || name == "android.hardware.location.network") { grp->features.add(String8("android.hardware.location"), Feature(true)); + } else if (name == "android.hardware.faketouch.multitouch") { + grp->features.add(String8("android.hardware.faketouch"), Feature(true)); + } else if (name == "android.hardware.faketouch.multitouch.distinct" || + name == "android.hardware.faketouch.multitouch.jazzhands") { + grp->features.add(String8("android.hardware.faketouch.multitouch"), Feature(true)); + grp->features.add(String8("android.hardware.faketouch"), Feature(true)); } else if (name == "android.hardware.touchscreen.multitouch") { grp->features.add(String8("android.hardware.touchscreen"), Feature(true)); - } else if (name == "android.hardware.touchscreen.multitouch.distinct") { + } else if (name == "android.hardware.touchscreen.multitouch.distinct" || + name == "android.hardware.touchscreen.multitouch.jazzhands") { grp->features.add(String8("android.hardware.touchscreen.multitouch"), Feature(true)); grp->features.add(String8("android.hardware.touchscreen"), Feature(true)); } else if (name == "android.hardware.opengles.aep") { @@ -2005,8 +2022,12 @@ int doDump(Bundle* bundle) } } - addImpliedFeature(&impliedFeatures, "android.hardware.touchscreen", - "default feature for all apps", false); + // If the app hasn't declared the touchscreen as a feature requirement (either + // directly or implied, required or not), then the faketouch feature is implied. + if (!hasFeature("android.hardware.touchscreen", commonFeatures, impliedFeatures)) { + addImpliedFeature(&impliedFeatures, "android.hardware.faketouch", + "default feature for all apps", false); + } const size_t numFeatureGroups = featureGroups.size(); if (numFeatureGroups == 0) { -- 2.11.0