diff options
author | Dianne Hackborn <hackbod@google.com> | 2011-10-27 12:58:16 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2011-10-27 16:03:14 -0700 |
commit | d4c4b76889f2bd2e2e34ba9fc835370020524ded (patch) | |
tree | 3593975f3011e1ee7099420b8b01edaec91f2e97 /tests/FrameworkPerf/src | |
parent | e49cf107e2533b7ca71c500bc20a0f6dcdf9efdc (diff) | |
download | frameworks_base-d4c4b76889f2bd2e2e34ba9fc835370020524ded.zip frameworks_base-d4c4b76889f2bd2e2e34ba9fc835370020524ded.tar.gz frameworks_base-d4c4b76889f2bd2e2e34ba9fc835370020524ded.tar.bz2 |
New framework performance tests.
Change-Id: Ib8cc6704f508b7516ba0a30aa71bb88ef028691d
Diffstat (limited to 'tests/FrameworkPerf/src')
3 files changed, 889 insertions, 0 deletions
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java new file mode 100644 index 0000000..9f05a55 --- /dev/null +++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java @@ -0,0 +1,694 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.frameworkperf; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.PowerManager; +import android.os.Process; +import android.os.SystemClock; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.widget.TextView; + +import java.util.ArrayList; + +/** + * So you thought sync used up your battery life. + */ +public class FrameworkPerfActivity extends Activity { + final Handler mHandler = new Handler(); + + TextView mLog; + PowerManager.WakeLock mPartialWakeLock; + + long mMaxRunTime = 5000; + boolean mStarted; + + final TestRunner mRunner = new TestRunner(); + + final Op[] mOpPairs = new Op[] { + new MethodCallOp(), new NoOp(), + new MethodCallOp(), new CpuOp(), + new MethodCallOp(), new SchedulerOp(), + new MethodCallOp(), new GcOp(), + new SchedulerOp(), new SchedulerOp(), + new GcOp(), new NoOp(), + new IpcOp(), new NoOp(), + new IpcOp(), new CpuOp(), + new IpcOp(), new SchedulerOp(), + new IpcOp(), new GcOp(), + new ParseXmlResOp(), new NoOp(), + new ParseLargeXmlResOp(), new NoOp(), + new LayoutInflaterOp(), new NoOp(), + new LayoutInflaterLargeOp(), new NoOp(), + new LoadSmallBitmapOp(), new NoOp(), + new LoadLargeBitmapOp(), new NoOp(), + new LoadSmallScaledBitmapOp(), new NoOp(), + new LoadLargeScaledBitmapOp(), new NoOp(), + }; + + final Op[] mAvailOps = new Op[] { + new NoOp(), + new CpuOp(), + new SchedulerOp(), + new MethodCallOp(), + new IpcOp(), + new ParseXmlResOp(), + new ParseLargeXmlResOp(), + new LoadSmallBitmapOp(), + new LoadLargeBitmapOp(), + new LoadSmallScaledBitmapOp(), + new LoadLargeScaledBitmapOp(), + }; + + int mCurOpIndex = 0; + + class RunResult { + final String name; + final String fgLongName; + final String bgLongName; + final long fgTime; + final long fgOps; + final long bgTime; + final long bgOps; + + RunResult(TestRunner op) { + name = op.getName(); + fgLongName = op.getForegroundLongName(); + bgLongName = op.getBackgroundLongName(); + fgTime = op.getForegroundTime(); + fgOps = op.getForegroundOps(); + bgTime = op.getBackgroundTime(); + bgOps = op.getBackgroundOps(); + } + + float getFgMsPerOp() { + return fgOps != 0 ? (fgTime / (float)fgOps) : 0; + } + + float getBgMsPerOp() { + return bgOps != 0 ? (bgTime / (float)bgOps) : 0; + } + } + + final ArrayList<RunResult> mResults = new ArrayList<RunResult>(); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Set the layout for this activity. You can find it + // in res/layout/hello_activity.xml + setContentView(R.layout.main); + + findViewById(R.id.start).setOnClickListener(new View.OnClickListener() { + @Override public void onClick(View v) { + startRunning(); + } + }); + findViewById(R.id.stop).setOnClickListener(new View.OnClickListener() { + @Override public void onClick(View v) { + stopRunning(); + } + }); + mLog = (TextView)findViewById(R.id.log); + + PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE); + mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Scheduler"); + mPartialWakeLock.setReferenceCounted(false); + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + stopRunning(); + if (mPartialWakeLock.isHeld()) { + mPartialWakeLock.release(); + } + } + + void startCurOp() { + mRunner.run(mHandler, mOpPairs[mCurOpIndex], mOpPairs[mCurOpIndex+1], new Runnable() { + @Override public void run() { + RunResult result = new RunResult(mRunner); + log(String.format("%s: fg=%d*%gms/op (%dms) / bg=%d*%gms/op (%dms)", + result.name, result.fgOps, result.getFgMsPerOp(), result.fgTime, + result.bgOps, result.getBgMsPerOp(), result.bgTime)); + mResults.add(result); + if (!mStarted) { + log("Stop"); + stopRunning(); + return; + } + mCurOpIndex+=2; + if (mCurOpIndex >= mOpPairs.length) { + log("Finished"); + stopRunning(); + return; + } + startCurOp(); + } + }); + } + + void startRunning() { + if (!mStarted) { + log("Start"); + mStarted = true; + updateWakeLock(); + startService(new Intent(this, SchedulerService.class)); + mCurOpIndex = 0; + mResults.clear(); + startCurOp(); + } + } + + void stopRunning() { + if (mStarted) { + mStarted = false; + updateWakeLock(); + stopService(new Intent(this, SchedulerService.class)); + for (int i=0; i<mResults.size(); i++) { + RunResult result = mResults.get(i); + float fgMsPerOp = result.getFgMsPerOp(); + float bgMsPerOp = result.getBgMsPerOp(); + String fgMsPerOpStr = fgMsPerOp != 0 ? Float.toString(fgMsPerOp) : ""; + String bgMsPerOpStr = bgMsPerOp != 0 ? Float.toString(bgMsPerOp) : ""; + Log.i("Perf", "\t" + result.name + "\t" + result.fgOps + + "\t" + result.getFgMsPerOp() + "\t" + result.fgTime + + "\t" + result.fgLongName + "\t" + result.bgOps + + "\t" + result.getBgMsPerOp() + "\t" + result.bgTime + + "\t" + result.bgLongName); + } + } + } + + void updateWakeLock() { + if (mStarted) { + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + if (!mPartialWakeLock.isHeld()) { + mPartialWakeLock.acquire(); + } + } else { + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + if (mPartialWakeLock.isHeld()) { + mPartialWakeLock.release(); + } + } + } + + void log(String s) { + mLog.setText(mLog.getText() + "\n" + s); + Log.i("Perf", s); + } + + enum BackgroundMode { + NOTHING, + CPU, + SCHEDULER + }; + + public class TestRunner { + Handler mHandler; + Op mForegroundOp; + Op mBackgroundOp; + Runnable mDoneCallback; + + RunnerThread mBackgroundThread; + RunnerThread mForegroundThread; + long mStartTime; + + boolean mBackgroundRunning; + boolean mForegroundRunning; + + long mBackgroundEndTime; + long mBackgroundOps; + long mForegroundEndTime; + long mForegroundOps; + + public TestRunner() { + } + + public String getForegroundName() { + return mForegroundOp.getName(); + } + + public String getBackgroundName() { + return mBackgroundOp.getName(); + } + + public String getName() { + String fgName = mForegroundOp.getName(); + String bgName = mBackgroundOp.getName(); + StringBuilder res = new StringBuilder(); + if (fgName != null) { + res.append(fgName); + res.append("Fg"); + } + if (bgName != null) { + res.append(bgName); + res.append("Bg"); + } + return res.toString(); + } + + public String getForegroundLongName() { + return mForegroundOp.getLongName(); + } + + public String getBackgroundLongName() { + return mBackgroundOp.getLongName(); + } + + public void run(Handler handler, Op foreground, Op background, Runnable doneCallback) { + mHandler = handler; + mForegroundOp = foreground; + mBackgroundOp = background; + mDoneCallback = doneCallback; + mBackgroundThread = new RunnerThread("background", new Runnable() { + @Override public void run() { + boolean running; + int ops = 0; + do { + running = mBackgroundOp.onRun(); + ops++; + } while (evalRepeat(running, true) && running); + mBackgroundEndTime = SystemClock.uptimeMillis(); + mBackgroundOps = ops * mBackgroundOp.getOpsPerRun(); + threadFinished(false); + } + }, Process.THREAD_PRIORITY_BACKGROUND); + mForegroundThread = new RunnerThread("background", new Runnable() { + @Override public void run() { + boolean running; + int ops = 0; + do { + running = mForegroundOp.onRun(); + ops++; + } while (evalRepeat(true, running) && running); + mForegroundEndTime = SystemClock.uptimeMillis(); + mForegroundOps = ops * mForegroundOp.getOpsPerRun(); + threadFinished(true); + } + }, Process.THREAD_PRIORITY_FOREGROUND); + + mForegroundOp.onInit(FrameworkPerfActivity.this); + mBackgroundOp.onInit(FrameworkPerfActivity.this); + + synchronized (this) { + mStartTime = SystemClock.uptimeMillis(); + mBackgroundRunning = true; + mForegroundRunning = true; + } + + mBackgroundThread.start(); + mForegroundThread.start(); + } + + public long getForegroundTime() { + return mForegroundEndTime-mStartTime; + } + + public long getForegroundOps() { + return mForegroundOps; + } + + public long getBackgroundTime() { + return mBackgroundEndTime-mStartTime; + } + + public long getBackgroundOps() { + return mBackgroundOps; + } + + private boolean evalRepeat(boolean bgRunning, boolean fgRunning) { + synchronized (this) { + if (!bgRunning) { + mBackgroundRunning = false; + } + if (!fgRunning) { + mForegroundRunning = false; + } + if (!mBackgroundRunning && !mForegroundRunning) { + return false; + } + long now = SystemClock.uptimeMillis(); + if (now > (mStartTime+mMaxRunTime)) { + return false; + } + return true; + } + } + + private void threadFinished(boolean foreground) { + synchronized (this) { + if (foreground) { + mForegroundRunning = false; + } else { + mBackgroundRunning = false; + } + if (!mBackgroundRunning && !mForegroundRunning) { + mHandler.post(new Runnable() { + @Override public void run() { + if (mDoneCallback != null) { + mDoneCallback.run(); + } + } + }); + } + } + } + } + + class RunnerThread extends Thread { + private final Runnable mOp; + private final int mPriority; + + RunnerThread(String name, Runnable op, int priority) { + super(name); + mOp = op; + mPriority = priority; + } + + public void run() { + Process.setThreadPriority(mPriority); + mOp.run(); + } + } + + static public abstract class Op { + final String mName; + final String mLongName; + + public Op(String name, String longName) { + mName = name; + mLongName = longName; + } + + public String getName() { + return mName; + } + + public String getLongName() { + return mLongName; + } + + void onInit(Context context) { + } + + abstract boolean onRun(); + + int getOpsPerRun() { + return 1; + } + } + + static class NoOp extends Op { + NoOp() { + super(null, "Nothing"); + } + + boolean onRun() { + return false; + } + + int getOpsPerRun() { + return 0; + } + } + + static class CpuOp extends Op { + CpuOp() { + super("CPU", "Consume CPU"); + } + + boolean onRun() { + return true; + } + } + + static class SchedulerOp extends Op { + SchedulerOp() { + super("Sched", "Change scheduler group"); + } + + boolean onRun() { + Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND); + Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + return true; + } + } + + static class GcOp extends Op { + GcOp() { + super("Gc", "Run garbage collector"); + } + + boolean onRun() { + byte[] stuff = new byte[1024*1024]; + return true; + } + } + + static class MethodCallOp extends Op { + MethodCallOp() { + super("MethodCall", "Method call"); + } + + boolean onRun() { + final int N = getOpsPerRun(); + for (int i=0; i<N; i++) { + someFunc(i); + } + return true; + } + + int someFunc(int foo) { + return 0; + } + + int getOpsPerRun() { + return 500; + } + } + + static class IpcOp extends Op { + PackageManager mPm; + String mProcessName; + + IpcOp() { + super("Ipc", "IPC to system process"); + } + + void onInit(Context context) { + mPm = context.getPackageManager(); + mProcessName = context.getApplicationInfo().processName; + } + + boolean onRun() { + final int N = getOpsPerRun(); + for (int i=0; i<N; i++) { + mPm.queryContentProviders(mProcessName, Process.myUid(), 0); + } + return true; + } + + int getOpsPerRun() { + return 100; + } + } + + static class ParseXmlResOp extends Op { + Context mContext; + + ParseXmlResOp() { + super("ParseXmlRes", "Parse compiled XML resource"); + } + + void onInit(Context context) { + mContext = context; + } + + boolean onRun() { + SimpleInflater inf = new SimpleInflater(mContext); + inf.inflate(R.xml.simple); + return true; + } + } + + static class ParseLargeXmlResOp extends Op { + Context mContext; + + ParseLargeXmlResOp() { + super("ParseLargeXmlRes", "Parse large XML resource"); + } + + void onInit(Context context) { + mContext = context; + } + + boolean onRun() { + SimpleInflater inf = new SimpleInflater(mContext); + inf.inflate(R.xml.simple_large); + return true; + } + } + + static class LayoutInflaterOp extends Op { + Context mContext; + + LayoutInflaterOp() { + super("LayoutInflaterOp", "Inflate layout resource"); + } + + void onInit(Context context) { + mContext = context; + } + + boolean onRun() { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + LayoutInflater inf = (LayoutInflater)mContext.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + inf.inflate(R.layout.small_layout, null); + return true; + } + } + + static class LayoutInflaterLargeOp extends Op { + Context mContext; + + LayoutInflaterLargeOp() { + super("LayoutInflaterLargeOp", "Inflate large layout resource"); + } + + void onInit(Context context) { + mContext = context; + } + + boolean onRun() { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + LayoutInflater inf = (LayoutInflater)mContext.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + inf.inflate(R.layout.large_layout, null); + return true; + } + } + + static class LoadSmallBitmapOp extends Op { + Context mContext; + + LoadSmallBitmapOp() { + super("LoadSmallBitmap", "Load small raw bitmap"); + } + + void onInit(Context context) { + mContext = context; + } + + boolean onRun() { + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE; + Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(), + R.drawable.stat_sample, opts); + bm.recycle(); + return true; + } + } + + static class LoadLargeBitmapOp extends Op { + Context mContext; + + LoadLargeBitmapOp() { + super("LoadLargeBitmap", "Load large raw bitmap"); + } + + void onInit(Context context) { + mContext = context; + } + + boolean onRun() { + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE; + Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(), + R.drawable.wallpaper_goldengate, opts); + bm.recycle(); + return true; + } + } + + static class LoadSmallScaledBitmapOp extends Op { + Context mContext; + + LoadSmallScaledBitmapOp() { + super("LoadSmallScaledBitmap", "Load small raw bitmap that is scaled for density"); + } + + void onInit(Context context) { + mContext = context; + } + + boolean onRun() { + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE; + Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(), + R.drawable.stat_sample_scale, opts); + bm.recycle(); + return true; + } + } + + static class LoadLargeScaledBitmapOp extends Op { + Context mContext; + + LoadLargeScaledBitmapOp() { + super("LoadLargeScaledBitmap", "Load large raw bitmap that is scaled for density"); + } + + void onInit(Context context) { + mContext = context; + } + + boolean onRun() { + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE; + Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(), + R.drawable.wallpaper_goldengate_scale, opts); + bm.recycle(); + return true; + } + } +} diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java b/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java new file mode 100644 index 0000000..7691e64 --- /dev/null +++ b/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.frameworkperf; + +import android.app.Notification; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; + +public class SchedulerService extends Service { + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Notification status = new Notification(R.drawable.stat_happy, null, + System.currentTimeMillis()); + status.flags |= Notification.FLAG_ONGOING_EVENT; + status.setLatestEventInfo(this, "Scheduler Test running", + "Scheduler Test running", PendingIntent.getActivity(this, 0, + new Intent(this, FrameworkPerfActivity.class) + .setAction(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_LAUNCHER) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0)); + startForeground(1, status); + return START_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/SimpleInflater.java b/tests/FrameworkPerf/src/com/android/frameworkperf/SimpleInflater.java new file mode 100644 index 0000000..5cbb12a --- /dev/null +++ b/tests/FrameworkPerf/src/com/android/frameworkperf/SimpleInflater.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.frameworkperf; + +import java.io.IOException; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import android.content.Context; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.util.AttributeSet; +import android.util.Xml; +import android.view.InflateException; + +public class SimpleInflater { + /** Menu tag name in XML. */ + private static final String XML_MENU = "menu"; + + /** Group tag name in XML. */ + private static final String XML_GROUP = "group"; + + /** Item tag name in XML. */ + private static final String XML_ITEM = "item"; + + private Context mContext; + + public SimpleInflater(Context context) { + mContext = context; + } + + public void inflate(int menuRes) { + XmlResourceParser parser = null; + try { + parser = mContext.getResources().getLayout(menuRes); + AttributeSet attrs = Xml.asAttributeSet(parser); + + parseMenu(parser, attrs); + } catch (XmlPullParserException e) { + throw new InflateException("Error inflating menu XML", e); + } catch (IOException e) { + throw new InflateException("Error inflating menu XML", e); + } finally { + if (parser != null) parser.close(); + } + } + + private void parseMenu(XmlPullParser parser, AttributeSet attrs) + throws XmlPullParserException, IOException { + int eventType = parser.getEventType(); + String tagName; + boolean lookingForEndOfUnknownTag = false; + String unknownTagName = null; + + // This loop will skip to the menu start tag + do { + if (eventType == XmlPullParser.START_TAG) { + tagName = parser.getName(); + if (tagName.equals(XML_MENU)) { + // Go to next tag + eventType = parser.next(); + break; + } + + throw new RuntimeException("Expecting menu, got " + tagName); + } + eventType = parser.next(); + } while (eventType != XmlPullParser.END_DOCUMENT); + + boolean reachedEndOfMenu = false; + while (!reachedEndOfMenu) { + switch (eventType) { + case XmlPullParser.START_TAG: + if (lookingForEndOfUnknownTag) { + break; + } + + tagName = parser.getName(); + if (tagName.equals(XML_ITEM)) { + readItem(attrs); + } else if (tagName.equals(XML_MENU)) { + parseMenu(parser, attrs); + } else { + lookingForEndOfUnknownTag = true; + unknownTagName = tagName; + } + break; + + case XmlPullParser.END_TAG: + tagName = parser.getName(); + if (lookingForEndOfUnknownTag && tagName.equals(unknownTagName)) { + lookingForEndOfUnknownTag = false; + unknownTagName = null; + } else if (tagName.equals(XML_ITEM)) { + } else if (tagName.equals(XML_MENU)) { + reachedEndOfMenu = true; + } + break; + + case XmlPullParser.END_DOCUMENT: + throw new RuntimeException("Unexpected end of document"); + } + + eventType = parser.next(); + } + } + + public void readItem(AttributeSet attrs) { + TypedArray a = mContext.obtainStyledAttributes(attrs, + com.android.internal.R.styleable.MenuItem); + + // Inherit attributes from the group as default value + int itemId = a.getResourceId(R.styleable.MenuItem_android_id, 0); + final int category = a.getInt(R.styleable.MenuItem_android_menuCategory, 0); + final int order = a.getInt(R.styleable.MenuItem_android_orderInCategory, 0); + CharSequence itemTitle = a.getText(R.styleable.MenuItem_android_title); + CharSequence itemTitleCondensed = a.getText(R.styleable.MenuItem_android_titleCondensed); + int itemIconResId = a.getResourceId(R.styleable.MenuItem_android_icon, 0); + String itemAlphabeticShortcut = a.getString(R.styleable.MenuItem_android_alphabeticShortcut); + String itemNumericShortcut = a.getString(R.styleable.MenuItem_android_numericShortcut); + int itemCheckable = 0; + if (a.hasValue(R.styleable.MenuItem_android_checkable)) { + // Item has attribute checkable, use it + itemCheckable = a.getBoolean(R.styleable.MenuItem_android_checkable, false) ? 1 : 0; + } + boolean itemChecked = a.getBoolean(R.styleable.MenuItem_android_checked, false); + boolean itemVisible = a.getBoolean(R.styleable.MenuItem_android_visible, false); + boolean itemEnabled = a.getBoolean(R.styleable.MenuItem_android_enabled, false); + + a.recycle(); + } +} |