Skip to content

Commit 9275197

Browse files
author
Dianne Hackborn
committed
Add aapt support for generating proguard rules for onClick methods.
Also fix Activity menu inflater when using the dark on light theme wrapper to still be able to find onClick listeners. Change-Id: Ie206db26d1df96041bc477804e476b02ad99dc9d
1 parent fb5c3db commit 9275197

File tree

3 files changed

+50
-8
lines changed

3 files changed

+50
-8
lines changed

core/java/android/app/Activity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3273,7 +3273,7 @@ public MenuInflater getMenuInflater() {
32733273
if (mMenuInflater == null) {
32743274
initActionBar();
32753275
if (mActionBar != null) {
3276-
mMenuInflater = new MenuInflater(mActionBar.getThemedContext());
3276+
mMenuInflater = new MenuInflater(mActionBar.getThemedContext(), this);
32773277
} else {
32783278
mMenuInflater = new MenuInflater(this);
32793279
}

core/java/android/view/MenuInflater.java

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public class MenuInflater {
6565
private final Object[] mActionProviderConstructorArguments;
6666

6767
private Context mContext;
68+
private Object mRealOwner;
6869

6970
/**
7071
* Constructs a menu inflater.
@@ -73,6 +74,20 @@ public class MenuInflater {
7374
*/
7475
public MenuInflater(Context context) {
7576
mContext = context;
77+
mRealOwner = context;
78+
mActionViewConstructorArguments = new Object[] {context};
79+
mActionProviderConstructorArguments = mActionViewConstructorArguments;
80+
}
81+
82+
/**
83+
* Constructs a menu inflater.
84+
*
85+
* @see Activity#getMenuInflater()
86+
* @hide
87+
*/
88+
public MenuInflater(Context context, Object realOwner) {
89+
mContext = context;
90+
mRealOwner = realOwner;
7691
mActionViewConstructorArguments = new Object[] {context};
7792
mActionProviderConstructorArguments = mActionViewConstructorArguments;
7893
}
@@ -190,12 +205,12 @@ private static class InflatedOnMenuItemClickListener
190205
implements MenuItem.OnMenuItemClickListener {
191206
private static final Class<?>[] PARAM_TYPES = new Class[] { MenuItem.class };
192207

193-
private Context mContext;
208+
private Object mRealOwner;
194209
private Method mMethod;
195210

196-
public InflatedOnMenuItemClickListener(Context context, String methodName) {
197-
mContext = context;
198-
Class<?> c = context.getClass();
211+
public InflatedOnMenuItemClickListener(Object realOwner, String methodName) {
212+
mRealOwner = realOwner;
213+
Class<?> c = realOwner.getClass();
199214
try {
200215
mMethod = c.getMethod(methodName, PARAM_TYPES);
201216
} catch (Exception e) {
@@ -210,9 +225,9 @@ public InflatedOnMenuItemClickListener(Context context, String methodName) {
210225
public boolean onMenuItemClick(MenuItem item) {
211226
try {
212227
if (mMethod.getReturnType() == Boolean.TYPE) {
213-
return (Boolean) mMethod.invoke(mContext, item);
228+
return (Boolean) mMethod.invoke(mRealOwner, item);
214229
} else {
215-
mMethod.invoke(mContext, item);
230+
mMethod.invoke(mRealOwner, item);
216231
return true;
217232
}
218233
} catch (Exception e) {
@@ -400,7 +415,7 @@ private void setItem(MenuItem item) {
400415
+ "be used within a restricted context");
401416
}
402417
item.setOnMenuItemClickListener(
403-
new InflatedOnMenuItemClickListener(mContext, itemListenerMethodName));
418+
new InflatedOnMenuItemClickListener(mRealOwner, itemListenerMethodName));
404419
}
405420

406421
if (item instanceof MenuItemImpl) {

tools/aapt/Resource.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2089,6 +2089,23 @@ addProguardKeepRule(ProguardKeepSet* keep, const String8& inClassName,
20892089
keep->add(rule, location);
20902090
}
20912091

2092+
void
2093+
addProguardKeepMethodRule(ProguardKeepSet* keep, const String8& memberName,
2094+
const char* pkg, const String8& srcName, int line)
2095+
{
2096+
String8 rule("-keepclassmembers class * { *** ");
2097+
rule += memberName;
2098+
rule += "(...); }";
2099+
2100+
String8 location("onClick ");
2101+
location += srcName;
2102+
char lineno[20];
2103+
sprintf(lineno, ":%d", line);
2104+
location += lineno;
2105+
2106+
keep->add(rule, location);
2107+
}
2108+
20922109
status_t
20932110
writeProguardForAndroidManifest(ProguardKeepSet* keep, const sp<AaptAssets>& assets)
20942111
{
@@ -2251,6 +2268,13 @@ writeProguardForXml(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile,
22512268
}
22522269
}
22532270
}
2271+
ssize_t attrIndex = tree.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE, "onClick");
2272+
if (attrIndex >= 0) {
2273+
size_t len;
2274+
addProguardKeepMethodRule(keep,
2275+
String8(tree.getAttributeStringValue(attrIndex, &len)), NULL,
2276+
layoutFile->getPrintableSource(), tree.getLineNumber());
2277+
}
22542278
}
22552279

22562280
return NO_ERROR;
@@ -2289,6 +2313,9 @@ writeProguardForLayouts(ProguardKeepSet* keep, const sp<AaptAssets>& assets)
22892313
} else if ((dirName == String8("xml")) || (strncmp(dirName.string(), "xml-", 4) == 0)) {
22902314
startTag = "PreferenceScreen";
22912315
tagAttrPairs = &kXmlTagAttrPairs;
2316+
} else if ((dirName == String8("menu")) || (strncmp(dirName.string(), "menu-", 5) == 0)) {
2317+
startTag = "menu";
2318+
tagAttrPairs = NULL;
22922319
} else {
22932320
continue;
22942321
}

0 commit comments

Comments
 (0)